import torrent_parser as tp import threading from math import ceil BUFFER_SIZE = 10 * 1024 * 1024 class Cron(object): alive = False def __init__(self, interval, func, *a, **kw): self.interval = interval self.func = func self.a = a self.kw = kw self.ticker = threading.Event() def start(self): self.t = threading.Thread(target=self.run) self.alive = True self.t.start() def run(self): while self.alive and not self.ticker.wait(self.interval): self.func(*self.a, **self.kw) def stop(self): self.alive = False class Buffer(object): def __init__(self, piece_size): self.buf_reset_pending = False self.buf_changed = threading.Event() self.size = ceil(BUFFER_SIZE / piece_size) self.buf = [] def buf_changed_event(self): self.buf_changed.set() self.buf_changed.clear() def put(self, piece): if not self.buf_reset_pending: self.buf.append(piece) self.buf_changed_event() return True else: return False def get(self): if not self.buf_reset_pending: if len(self.buf): return self.buf.pop(0) return None def reset(self): self.buf_reset_pending = True self.buf = [] self.buf_reset_pending = False self.buf_changed_event() def pieces(self): if not self.buf_reset_pending: return list(map(lambda x: (x.index, x.hash), self.buf)) else: return [] class Piece(object): def __init__(self, p_index, p_hash, payload): self.index = p_index self.hash = p_hash self.payload = payload class Pyrrent(object): multifile = False def __init__(self, filepath): self.data = tp.parse_torrent_file(filepath) self.piece_length = self.data['info']['piece length'] self.buffer = Buffer(self.piece_length) self.pieces = self.data['info']['pieces'] if 'files' in self.data['info'].keys(): self.multifile = True if not self.multifile: self.file_addresses = [(0, self.piece_length)] else: self.file_addresses = [] addr_ptr = 0 for length in map(lambda x: x['length'], self.data['info']['files']): next_at = addr_ptr + length self.file_addresses.append((addr_ptr, next_at)) addr_ptr += length def piece_range(self, f_index): start, next_at = self.file_addresses[f_index] start_piece = start // self.piece_length start_byte = start % self.piece_length tail = next_at % self.piece_length end_piece = next_at // self.piece_length - int(not bool(tail)) end_byte = self.piece_length if not tail else tail return [(start_piece, start_byte),(end_piece, end_byte)]