def __init__(self, infohash, metainfo, kvconfig, multihandler, get_extip_func, listenport, videoanalyserpath, vodfileindex, extra_vodfileindex, set_error_func, pstate, lmvodeventcallback, lmhashcheckcompletecallback): self.dow = None self.set_error_func = set_error_func self.videoinfo = None self.videostatus = None self.metainfo = metainfo self.dlmode = kvconfig['mode'] self.extra_vodfileindex = extra_vodfileindex self.lmvodeventcallback = lmvodeventcallback self.lmhashcheckcompletecallback = lmhashcheckcompletecallback self.logmsgs = [] self._hashcheckfunc = None self._getstatsfunc = None self.infohash = infohash self.b64_infohash = b64encode(infohash) self.repexer = None self.log_prefix = 'sd::' + binascii.hexlify(self.infohash) + ':' self.lock = Lock() self.download_id = binascii.hexlify(self.infohash) + '-' + str(long(time.time())) + '-' + str(random.randint(0, 100000)) try: self.dldoneflag = Event() self.dlrawserver = multihandler.newRawServer(infohash, self.dldoneflag) self.lmvodeventcallback = lmvodeventcallback if pstate is not None: self.hashcheckfrac = pstate['dlstate']['progress'] else: self.hashcheckfrac = 0.0 self.peerid = createPeerID() self.dow = BT1Download(self.hashcheckprogressfunc, self.finishedfunc, self.fatalerrorfunc, self.nonfatalerrorfunc, self.logerrorfunc, self.dldoneflag, kvconfig, metainfo, infohash, self.peerid, self.dlrawserver, get_extip_func, listenport, videoanalyserpath) file = self.dow.saveAs(self.save_as) if vodfileindex is not None: index = vodfileindex['index'] if index == -1: index = 0 outpathindex = self.dow.get_dest(index) vodfileindex['outpath'] = outpathindex self.videoinfo = vodfileindex if 'live' in metainfo['info']: authparams = metainfo['info']['live'] else: authparams = None self.videostatus = VideoStatus(metainfo['info']['piece length'], self.dow.files, vodfileindex, authparams) self.videoinfo['status'] = self.videostatus self.dow.set_videoinfo(vodfileindex, self.videostatus) if DEBUG: log(self.log_prefix + '__init__: setting vodfileindex', vodfileindex) if kvconfig['initialdlstatus'] == DLSTATUS_REPEXING: if pstate is not None and pstate.has_key('dlstate'): swarmcache = pstate['dlstate'].get('swarmcache', {}) else: swarmcache = {} self.repexer = RePEXer(self.infohash, swarmcache) else: self.repexer = None if pstate is None: resumedata = None else: resumedata = pstate['engineresumedata'] self._hashcheckfunc = self.dow.initFiles(resumedata=resumedata) except Exception as e: self.fatalerrorfunc(e)
class SingleDownload: def __init__(self, infohash, metainfo, kvconfig, multihandler, get_extip_func, listenport, videoanalyserpath, vodfileindex, extra_vodfileindex, set_error_func, pstate, lmvodeventcallback, lmhashcheckcompletecallback): self.dow = None self.set_error_func = set_error_func self.videoinfo = None self.videostatus = None self.metainfo = metainfo self.dlmode = kvconfig['mode'] self.extra_vodfileindex = extra_vodfileindex self.lmvodeventcallback = lmvodeventcallback self.lmhashcheckcompletecallback = lmhashcheckcompletecallback self.logmsgs = [] self._hashcheckfunc = None self._getstatsfunc = None self.infohash = infohash self.b64_infohash = b64encode(infohash) self.repexer = None self.log_prefix = 'sd::' + binascii.hexlify(self.infohash) + ':' self.lock = Lock() self.download_id = binascii.hexlify(self.infohash) + '-' + str(long(time.time())) + '-' + str(random.randint(0, 100000)) try: self.dldoneflag = Event() self.dlrawserver = multihandler.newRawServer(infohash, self.dldoneflag) self.lmvodeventcallback = lmvodeventcallback if pstate is not None: self.hashcheckfrac = pstate['dlstate']['progress'] else: self.hashcheckfrac = 0.0 self.peerid = createPeerID() self.dow = BT1Download(self.hashcheckprogressfunc, self.finishedfunc, self.fatalerrorfunc, self.nonfatalerrorfunc, self.logerrorfunc, self.dldoneflag, kvconfig, metainfo, infohash, self.peerid, self.dlrawserver, get_extip_func, listenport, videoanalyserpath) file = self.dow.saveAs(self.save_as) if vodfileindex is not None: index = vodfileindex['index'] if index == -1: index = 0 outpathindex = self.dow.get_dest(index) vodfileindex['outpath'] = outpathindex self.videoinfo = vodfileindex if 'live' in metainfo['info']: authparams = metainfo['info']['live'] else: authparams = None self.videostatus = VideoStatus(metainfo['info']['piece length'], self.dow.files, vodfileindex, authparams) self.videoinfo['status'] = self.videostatus self.dow.set_videoinfo(vodfileindex, self.videostatus) if DEBUG: log(self.log_prefix + '__init__: setting vodfileindex', vodfileindex) if kvconfig['initialdlstatus'] == DLSTATUS_REPEXING: if pstate is not None and pstate.has_key('dlstate'): swarmcache = pstate['dlstate'].get('swarmcache', {}) else: swarmcache = {} self.repexer = RePEXer(self.infohash, swarmcache) else: self.repexer = None if pstate is None: resumedata = None else: resumedata = pstate['engineresumedata'] self._hashcheckfunc = self.dow.initFiles(resumedata=resumedata) except Exception as e: self.fatalerrorfunc(e) def get_download_id(self): return self.download_id def set_extra_files(self, extra_vodfileindex): if self.dow is None: return if extra_vodfileindex is None: extra_vodfileindex = [] extra_vs = [] for vodfileindex in extra_vodfileindex: index = vodfileindex['index'] if index == -1: index = 0 vodfileindex['outpath'] = self.dow.get_dest(index) vs = VideoStatus(self.metainfo['info']['piece length'], self.dow.files, vodfileindex, authparams=None, is_extra=True) extra_vs.append(vs) self.dow.picker.set_extra_videostatus(extra_vs) def get_bt1download(self): return self.dow def save_as(self, name, length, saveas, isdir, islive = False): if DEBUG: log(self.log_prefix + 'save_as(', `name`, length, `saveas`, isdir, ')') try: if not os.access(saveas, os.F_OK): os.mkdir(saveas) path = os.path.join(saveas, name) if isdir and not os.path.isdir(path): os.mkdir(path) return path except Exception as e: self.fatalerrorfunc(e) def perform_hashcheck(self, complete_callback): if DEBUG: log(self.log_prefix + 'perform_hashcheck: thread', currentThread().getName()) self.lock.acquire() try: self._getstatsfunc = SPECIAL_VALUE self.lmhashcheckcompletecallback = complete_callback if self._hashcheckfunc is None: if DEBUG: log(self.log_prefix + 'perform_hashcheck: _hashcheckfunc is none, sd is shutted down: thread', currentThread().getName()) else: if DEBUG: log(self.log_prefix + 'perform_hashcheck: run _hashcheckfunc:', self._hashcheckfunc, 'thread', currentThread().getName()) complete_callback_lambda = lambda sd = self, success = True: complete_callback(sd, success) self._hashcheckfunc(complete_callback_lambda) except Exception as e: self.fatalerrorfunc(e) finally: self.lock.release() def hashcheck_done(self): if DEBUG: log(self.log_prefix + 'hashcheck_done: dow', self.dow, 'thread', currentThread().getName()) self.lock.acquire() try: if self.dow is None: log(self.log_prefix + 'hashcheck_done: dow is None, shutted down while hashchecking, skip start: thread', currentThread().getName()) return if DEBUG: t = time.time() self.dow.startEngine(vodeventfunc=self.lmvodeventcallback) if DEBUG: log(self.log_prefix + 'hashcheck_done: dow.startEngine() time', time.time() - t) if DEBUG: t = time.time() self._getstatsfunc = self.dow.startStats() if DEBUG: log(self.log_prefix + 'hashcheck_done: dow.startStats() time', time.time() - t) if self.dlmode == DLMODE_VOD: self.set_extra_files(self.extra_vodfileindex) repexer = self.repexer if repexer is None: if DEBUG: t = time.time() self.dow.startRerequester() if DEBUG: log(self.log_prefix + 'hashcheck_done: dow.startRerequester() time', time.time() - t) else: self.hook_repexer() if DEBUG: t = time.time() self.dlrawserver.start_listening(self.dow.getPortHandler()) if DEBUG: log(self.log_prefix + 'hashcheck_done: dlrawserver.start_listening() time', time.time() - t) except Exception as e: self.fatalerrorfunc(e) finally: self.lock.release() def set_max_speed(self, direct, speed, auto_limit = False, callback = None): if self.dow is not None: if DEBUG: log(self.log_prefix + 'set_max_speed: direction', direct, 'speed', speed) if direct == UPLOAD: self.dow.setUploadRate(speed, networkcalling=True) else: self.dow.setDownloadRate(rate=speed, auto_limit=auto_limit, networkcalling=True) if callback is not None: callback(direct, speed) def set_player_buffer_time(self, value): if self.dow is not None: if DEBUG: log(self.log_prefix + 'set_player_buffer_time:', value) self.dow.set_player_buffer_time(value) def set_live_buffer_time(self, value): if self.dow is not None: if DEBUG: log(self.log_prefix + 'set_live_buffer_time:', value) self.dow.set_live_buffer_time(value) def set_max_conns_to_initiate(self, nconns, callback): if self.dow is not None: if DEBUG: log(self.log_prefix + 'set_max_conns_to_initiate', `(self.dow.response['info']['name'])`) self.dow.setInitiate(nconns, networkcalling=True) if callback is not None: callback(nconns) def set_max_uploads(self, value): if self.dow is not None: if DEBUG: log(self.log_prefix + 'set_max_uploads:', value) self.dow.setConns(value) def set_max_conns(self, nconns, callback): if self.dow is not None: if DEBUG: log(self.log_prefix + 'set_max_conns', `(self.dow.response['info']['name'])`) self.dow.setMaxConns(nconns, networkcalling=True) if callback is not None: callback(nconns) def set_wait_sufficient_speed(self, value): if self.dow is not None: if DEBUG: log(self.log_prefix + 'set_wait_sufficient_speed:', value) self.dow.set_wait_sufficient_speed(value) def set_http_support(self, value): if self.dow is not None: if DEBUG: log(self.log_prefix + 'set_http_support:', value) self.dow.set_http_support(value) def get_stats(self, getpeerlist): logmsgs = self.logmsgs[:] coopdl_helpers = [] coopdl_coordinator = None paused = False if self.dow is not None: paused = self.dow.isPaused() if self.dow.helper is not None: coopdl_coordinator = self.dow.helper.get_coordinator_permid() if self.dow.coordinator is not None: peerreclist = self.dow.coordinator.network_get_asked_helpers_copy() for peerrec in peerreclist: coopdl_helpers.append(peerrec['permid']) if self._getstatsfunc is None: return (DLSTATUS_WAITING4HASHCHECK, None, logmsgs, coopdl_helpers, coopdl_coordinator, paused) elif self._getstatsfunc == SPECIAL_VALUE: stats = {} stats['frac'] = self.hashcheckfrac return (DLSTATUS_HASHCHECKING, stats, logmsgs, coopdl_helpers, coopdl_coordinator, paused) else: if self.repexer is not None: status = DLSTATUS_REPEXING else: status = None return (status, self._getstatsfunc(getpeerlist=getpeerlist), logmsgs, coopdl_helpers, coopdl_coordinator, paused) def get_infohash(self): return self.infohash def checkpoint(self): if self.dow is not None: return self.dow.checkpoint() else: return def shutdown(self): if DEBUG: log(self.log_prefix + 'shutdown: thread', currentThread().getName()) resumedata = None self.lock.acquire() try: if self.dow is not None: if self.repexer: repexer = self.unhook_repexer() repexer.repex_aborted(self.infohash, DLSTATUS_STOPPED) self.dldoneflag.set() self.dlrawserver.shutdown() resumedata = self.dow.shutdown() if DEBUG: log(self.log_prefix + 'shutdown: resumedata', resumedata) self.dow = None if self._hashcheckfunc is not None: if DEBUG: log(self.log_prefix + 'shutdown: reset _hashcheckfunc:', self._hashcheckfunc, 'thread', currentThread().getName()) self._hashcheckfunc = None if self._getstatsfunc is None or self._getstatsfunc == SPECIAL_VALUE: log(self.log_prefix + 'shutdown: shutdown on hashcheck: _getstatsfunc', self._getstatsfunc, 'thread', currentThread().getName()) self.lmhashcheckcompletecallback(self, success=False) elif DEBUG: log(self.log_prefix + 'shutdown: regular shutdown: _getstatsfunc', self._getstatsfunc, 'thread', currentThread().getName()) finally: self.lock.release() return resumedata def got_duration(self, duration, from_player): if DEBUG: log(self.log_prefix + 'got_duration: duration', duration, 'from_player', from_player) if self.dow is not None: return self.dow.got_duration(duration, from_player) def live_seek(self, pos): if DEBUG: log(self.log_prefix + 'live_seek: pos', pos) if self.dow is None: log(self.log_prefix + 'live_seek: dow is none') return self.dow.live_seek(pos) def got_metadata(self, metadata): if DEBUG: log(self.log_prefix + 'got_metadata: metadata', metadata) if self.dow is not None: return self.dow.got_metadata(metadata) def got_http_seeds(self, http_seeds): if DEBUG: log(self.log_prefix + 'got_http_seeds: http_seeds', http_seeds) if self.dow is not None: return self.dow.got_http_seeds(http_seeds) def pause(self, pause, close_connections = False): self.lock.acquire() try: if self.dow is not None: if DEBUG: log(self.log_prefix + 'pause: pause', pause, 'close_connections', close_connections) if pause: self.dow.Pause(close_connections) else: self.dow.Unpause() return finally: self.lock.release() def restart(self, initialdlstatus = None, vodfileindex = None, extra_vodfileindex = None, dlmode = None, new_priority = None): self.lock.acquire() try: if self.dow is None: if DEBUG: log(self.log_prefix + 'restart: shutted down, skip restart') return if self._getstatsfunc is None or self._getstatsfunc == SPECIAL_VALUE: if DEBUG: log(self.log_prefix + 'restart: hashchecking, skip restart') return finally: self.lock.release() if DEBUG: log(self.log_prefix + 'restart: vodfileindex', vodfileindex, 'initialdlstatus', initialdlstatus) self.dow.Unpause() if 'live' in self.metainfo['info']: authparams = self.metainfo['info']['live'] else: authparams = None if self.repexer and initialdlstatus != DLSTATUS_REPEXING: repexer = self.unhook_repexer() repexer.repex_aborted(self.infohash, initialdlstatus) elif vodfileindex is not None: index = vodfileindex['index'] if index == -1: index = 0 outpathindex = self.dow.get_dest(index) vodfileindex['outpath'] = outpathindex videostatus = VideoStatus(self.metainfo['info']['piece length'], self.dow.files, vodfileindex, authparams) self.dow.restartEngine(vodfileindex, videostatus, self.lmvodeventcallback, dlmode, new_priority) self.set_extra_files(extra_vodfileindex) if DEBUG: log(self.log_prefix + 'restart: fileselector priorities:', self.dow.fileselector.get_priorities()) self._getstatsfunc = self.dow.startStats() else: vodfileindex = self.dow.videoinfo videostatus = VideoStatus(self.metainfo['info']['piece length'], self.dow.files, vodfileindex, authparams) self.dow.restartEngine(vodfileindex, videostatus, self.lmvodeventcallback, dlmode) self._getstatsfunc = self.dow.startStats() def get_swarmcache(self): if self.repexer is not None: return self.repexer.get_swarmcache()[0] def hook_repexer(self): repexer = self.repexer if repexer is None: return if self.dow is None: return self.dow.Pause() self.dow.startRerequester(paused=True) connecter, encoder = self.dow.connecter, self.dow.encoder connecter.repexer = repexer encoder.repexer = repexer rerequest = self.dow.createRerequester(repexer.rerequester_peers) repexer.repex_ready(self.infohash, connecter, encoder, rerequest) def unhook_repexer(self): repexer = self.repexer if repexer is None: return self.repexer = None if self.dow is not None: connecter, encoder = self.dow.connecter, self.dow.encoder connecter.repexer = None encoder.repexer = None self.dow.startRerequester() self.dow.Unpause() return repexer def ask_coopdl_helpers(self, peerreclist): if self.dow is not None: self.dow.coordinator.send_ask_for_help(peerreclist) def stop_coopdl_helpers(self, peerreclist): if self.dow is not None: self.dow.coordinator.send_stop_helping(peerreclist, force=True) def get_coopdl_role_object(self, role): if self.dow is not None: if role == COOPDL_ROLE_COORDINATOR: return self.dow.coordinator else: return self.dow.helper else: return def hashcheckprogressfunc(self, activity = '', fractionDone = 0.0): self.hashcheckfrac = fractionDone def finishedfunc(self): if DEBUG: log(self.log_prefix + 'finishedfunc called: download is complete *******************************') def fatalerrorfunc(self, data): log(self.log_prefix + ':fatalerrorfunc called', data) if type(data) == StringType: log(self.log_prefix + 'LEGACY CORE FATAL ERROR', data) print_stack() self.set_error_func(ACEStreamLegacyException(data)) else: log_exc() self.set_error_func(data) self.shutdown() def nonfatalerrorfunc(self, e): log(self.log_prefix + 'nonfatalerrorfunc called', e) def logerrorfunc(self, msg): t = time.time() self.logmsgs.append((t, msg)) if len(self.logmsgs) > 10: self.logmsgs.pop(0)