def run(params): h = HeadlessDisplayer() while 1: configdir = ConfigDir('downloadheadless') defaultsToIgnore = ['metafile', 'url', 'priority'] configdir.setDefaults(defaults, defaultsToIgnore) configdefaults = configdir.loadConfig() defaults.append( ('save_options', 0, 'whether to save the current options as the ' 'new default configuration (only for btdownloadheadless.py)')) try: config = parse_params(params, configdefaults) except ValueError as e: print('error: {}\n'.format(e), 'run with no args for parameter explanations') break if not config: print(get_usage(defaults, 80, configdefaults)) break if config['save_options']: configdir.saveConfig(config) configdir.deleteOldCacheData(config['expire_cache_data']) myid = createPeerID() random.seed(myid) doneflag = threading.Event() def disp_exception(text): print(text) rawserver = RawServer(doneflag, config['timeout_check_interval'], config['timeout'], ipv6_enable=config['ipv6_enabled'], failfunc=h.failed, errorfunc=disp_exception) upnp_type = UPnP_test(config['upnp_nat_access']) while True: try: listen_port = rawserver.find_and_bind( config['minport'], config['maxport'], config['bind'], ipv6_socket_style=config['ipv6_binds_v4'], upnp=upnp_type, randomizer=config['random_port']) break except socket.error as e: if upnp_type and e == UPnP_ERROR: print('WARNING: COULD NOT FORWARD VIA UPnP') upnp_type = 0 continue print("error: Couldn't listen - ", e) h.failed() return metainfo = get_metainfo(config['metafile'], config['url'], h.error) if not metainfo: break infohash = hashlib.sha1(bencode(metainfo['info'])).digest() dow = BT1Download(h.display, h.finished, h.error, disp_exception, doneflag, config, metainfo, infohash, myid, rawserver, listen_port, configdir) if not dow.saveAs(h.chooseFile, h.newpath): break if not dow.initFiles(old_style=True): break if not dow.startEngine(): dow.shutdown() break dow.startRerequester() dow.autoStats() if not dow.am_I_finished(): h.display(activity='connecting to peers') rawserver.listen_forever(dow.getPortHandler()) h.display(activity='shutting down') dow.shutdown() break try: rawserver.shutdown() except Exception: pass if not h.done: h.failed()
class LaunchMany: def __init__(self, config, Output): try: self.config = config self.Output = Output self.torrent_dir = config['torrent_dir'] self.torrent_cache = {} self.file_cache = {} self.blocked_files = {} self.scan_period = config['parse_dir_interval'] self.stats_period = config['display_interval'] self.torrent_list = [] self.downloads = {} self.counter = 0 self.doneflag = threading.Event() self.hashcheck_queue = [] self.hashcheck_current = None self.rawserver = RawServer(self.doneflag, config['timeout_check_interval'], config['timeout'], ipv6_enable=config['ipv6_enabled'], failfunc=self.failed, errorfunc=self.exchandler) upnp_type = UPnP_test(config['upnp_nat_access']) while True: try: self.listen_port = self.rawserver.find_and_bind( config['minport'], config['maxport'], config['bind'], ipv6_socket_style=config['ipv6_binds_v4'], upnp=upnp_type, randomizer=config['random_port']) break except socket.error as e: if upnp_type and e == UPnP_ERROR: self.Output.message( 'WARNING: COULD NOT FORWARD VIA UPnP') upnp_type = 0 continue self.failed("Couldn't listen - " + str(e)) return self.ratelimiter = RateLimiter(self.rawserver.add_task, config['upload_unit_size']) self.ratelimiter.set_upload_rate(config['max_upload_rate']) self.handler = MultiHandler(self.rawserver, self.doneflag, config) random.seed(createPeerID()) self.rawserver.add_task(self.scan, 0) self.rawserver.add_task(self.stats, 0) self.handler.listen_forever() self.Output.message('shutting down') self.hashcheck_queue = [] for hash in self.torrent_list: self.Output.message('dropped "{}"'.format( self.torrent_cache[hash]['path'])) self.downloads[hash].shutdown() self.rawserver.shutdown() except Exception: data = StringIO() print_exc(file=data) Output.exception(data.getvalue()) def scan(self): self.rawserver.add_task(self.scan, self.scan_period) r = parsedir(self.torrent_dir, self.torrent_cache, self.file_cache, self.blocked_files, return_metainfo=True, errfunc=self.Output.message) (self.torrent_cache, self.file_cache, self.blocked_files, added, removed) = r for hash, data in removed.iteritems(): self.Output.message('dropped "{}"'.format(data['path'])) self.remove(hash) for hash, data in added.iteritems(): self.Output.message('added "{}"'.format(data['path'])) self.add(hash, data) def stats(self): self.rawserver.add_task(self.stats, self.stats_period) data = [] for hash in self.torrent_list: cache = self.torrent_cache[hash] if self.config['display_path']: name = cache['path'] else: name = cache['name'] size = cache['length'] d = self.downloads[hash] progress = '0.0%' peers = 0 seeds = 0 seedsmsg = "S" dist = 0.0 uprate = 0.0 dnrate = 0.0 upamt = 0 dnamt = 0 t = 0 if d.is_dead(): status = 'stopped' elif d.waiting: status = 'waiting for hash check' elif d.checking: status = d.status_msg progress = '{:.1%}'.format(d.status_done) else: stats = d.statsfunc() s = stats['stats'] if d.seed: status = 'seeding' progress = '100.0%' seeds = s.numOldSeeds seedsmsg = "s" dist = s.numCopies else: if s.numSeeds + s.numPeers: t = stats['time'] if t == 0: # unlikely t = 0.01 status = formatIntClock(t) or 'downloading' else: t = -1 status = 'connecting to peers' progress = '{:.1%}'.format(stats['frac']) seeds = s.numSeeds dist = s.numCopies2 dnrate = stats['down'] peers = s.numPeers uprate = stats['up'] upamt = s.upTotal dnamt = s.downTotal if d.is_dead() or d.status_errtime + 300 > clock(): msg = d.status_err[-1] else: msg = '' data.append((name, status, progress, peers, seeds, seedsmsg, dist, uprate, dnrate, upamt, dnamt, size, t, msg)) stop = self.Output.display(data) if stop: self.doneflag.set() def remove(self, hash): self.torrent_list.remove(hash) self.downloads[hash].shutdown() del self.downloads[hash] def add(self, hash, data): c = self.counter self.counter += 1 x = '' for _ in xrange(3): x = mapbase64[c & 0x3F] + x c >>= 6 peer_id = createPeerID(x) d = SingleDownload(self, hash, data['metainfo'], self.config, peer_id) self.torrent_list.append(hash) self.downloads[hash] = d d.start() def saveAs(self, hash, name, saveas, isdir): x = self.torrent_cache[hash] style = self.config['saveas_style'] if style == 1 or style == 3: if saveas: saveas = os.path.join(saveas, x['file'][:-1 - len(x['type'])]) else: saveas = x['path'][:-1 - len(x['type'])] if style == 3: if not os.path.isdir(saveas): try: os.mkdir(saveas) except OSError: raise OSError("couldn't create directory for {} ({})" ''.format(x['path'], saveas)) if not isdir: saveas = os.path.join(saveas, name) else: if saveas: saveas = os.path.join(saveas, name) else: saveas = os.path.join(os.path.split(x['path'])[0], name) if isdir and not os.path.isdir(saveas): try: os.mkdir(saveas) except OSError: raise OSError("couldn't create directory for {} ({})".format( x['path'], saveas)) return saveas def hashchecksched(self, hash=None): if hash: self.hashcheck_queue.append(hash) if not self.hashcheck_current: self._hashcheck_start() def _hashcheck_start(self): self.hashcheck_current = self.hashcheck_queue.pop(0) self.downloads[self.hashcheck_current].hashcheck_start( self.hashcheck_callback) def hashcheck_callback(self): self.downloads[self.hashcheck_current].hashcheck_callback() if self.hashcheck_queue: self._hashcheck_start() else: self.hashcheck_current = None def died(self, hash): if hash in self.torrent_cache: self.Output.message('DIED: "{}"'.format( self.torrent_cache[hash]['path'])) def was_stopped(self, hash): try: self.hashcheck_queue.remove(hash) except ValueError: pass if self.hashcheck_current == hash: self.hashcheck_current = None if self.hashcheck_queue: self._hashcheck_start() def failed(self, s): self.Output.message('FAILURE: ' + s) def exchandler(self, s): self.Output.exception(s)
def run(scrwin, errlist, params): doneflag = threading.Event() d = CursesDisplayer(scrwin, errlist, doneflag) try: while 1: configdir = ConfigDir('downloadcurses') defaultsToIgnore = ['responsefile', 'url', 'priority'] configdir.setDefaults(defaults, defaultsToIgnore) configdefaults = configdir.loadConfig() defaults.append( ('save_options', 0, 'whether to save the current options as ' 'the new default configuration (only for btdownloadcurses.py)' )) try: config = parse_params(params, configdefaults) except ValueError as e: d.error('error: {}\nrun with no args for parameter ' 'explanations'.format(e)) break if not config: d.error(get_usage(defaults, d.fieldw, configdefaults)) break if config['save_options']: configdir.saveConfig(config) configdir.deleteOldCacheData(config['expire_cache_data']) myid = createPeerID() random.seed(myid) rawserver = RawServer( doneflag, config['timeout_check_interval'], config['timeout'], ipv6_enable=config['ipv6_enabled'], failfunc=d.failed, errorfunc=d.error) upnp_type = UPnP_test(config['upnp_nat_access']) while True: try: listen_port = rawserver.find_and_bind( config['minport'], config['maxport'], config['bind'], ipv6_socket_style=config['ipv6_binds_v4'], upnp=upnp_type, randomizer=config['random_port']) break except socket.error as e: if upnp_type and e == UPnP_ERROR: d.error('WARNING: COULD NOT FORWARD VIA UPnP') upnp_type = 0 continue d.error("Couldn't listen - " + str(e)) d.failed() return response = get_response(config['responsefile'], config['url'], d.error) if not response: break infohash = hashlib.sha1(bencode(response['info'])).digest() dow = BT1Download( d.display, d.finished, d.error, d.error, doneflag, config, response, infohash, myid, rawserver, listen_port, configdir) if not dow.saveAs(d.chooseFile): break if not dow.initFiles(old_style=True): break if not dow.startEngine(): dow.shutdown() break dow.startRerequester() dow.autoStats() if not dow.am_I_finished(): d.display(activity='connecting to peers') rawserver.listen_forever(dow.getPortHandler()) d.display(activity='shutting down') dow.shutdown() break except KeyboardInterrupt: # ^C to exit... pass try: rawserver.shutdown() except Exception: pass if not d.done: d.failed()
class LaunchMany: def __init__(self, config, Output): try: self.config = config self.Output = Output self.torrent_dir = config['torrent_dir'] self.torrent_cache = {} self.file_cache = {} self.blocked_files = {} self.scan_period = config['parse_dir_interval'] self.stats_period = config['display_interval'] self.torrent_list = [] self.downloads = {} self.counter = 0 self.doneflag = threading.Event() self.hashcheck_queue = [] self.hashcheck_current = None self.rawserver = RawServer( self.doneflag, config['timeout_check_interval'], config['timeout'], ipv6_enable=config['ipv6_enabled'], failfunc=self.failed, errorfunc=self.exchandler) upnp_type = UPnP_test(config['upnp_nat_access']) while True: try: self.listen_port = self.rawserver.find_and_bind( config['minport'], config['maxport'], config['bind'], ipv6_socket_style=config['ipv6_binds_v4'], upnp=upnp_type, randomizer=config['random_port']) break except socket.error as e: if upnp_type and e == UPnP_ERROR: self.Output.message( 'WARNING: COULD NOT FORWARD VIA UPnP') upnp_type = 0 continue self.failed("Couldn't listen - " + str(e)) return self.ratelimiter = RateLimiter(self.rawserver.add_task, config['upload_unit_size']) self.ratelimiter.set_upload_rate(config['max_upload_rate']) self.handler = MultiHandler(self.rawserver, self.doneflag, config) random.seed(createPeerID()) self.rawserver.add_task(self.scan, 0) self.rawserver.add_task(self.stats, 0) self.handler.listen_forever() self.Output.message('shutting down') self.hashcheck_queue = [] for hash in self.torrent_list: self.Output.message('dropped "{}"'.format( self.torrent_cache[hash]['path'])) self.downloads[hash].shutdown() self.rawserver.shutdown() except Exception: data = StringIO() print_exc(file=data) Output.exception(data.getvalue()) def scan(self): self.rawserver.add_task(self.scan, self.scan_period) r = parsedir(self.torrent_dir, self.torrent_cache, self.file_cache, self.blocked_files, return_metainfo=True, errfunc=self.Output.message) (self.torrent_cache, self.file_cache, self.blocked_files, added, removed) = r for hash, data in removed.items(): self.Output.message('dropped "{}"'.format(data['path'])) self.remove(hash) for hash, data in added.items(): self.Output.message('added "{}"'.format(data['path'])) self.add(hash, data) def stats(self): self.rawserver.add_task(self.stats, self.stats_period) data = [] for hash in self.torrent_list: cache = self.torrent_cache[hash] if self.config['display_path']: name = cache['path'] else: name = cache['name'] size = cache['length'] d = self.downloads[hash] progress = '0.0%' peers = 0 seeds = 0 seedsmsg = "S" dist = 0.0 uprate = 0.0 dnrate = 0.0 upamt = 0 dnamt = 0 t = 0 if d.is_dead(): status = 'stopped' elif d.waiting: status = 'waiting for hash check' elif d.checking: status = d.status_msg progress = '{:.1%}'.format(d.status_done) else: stats = d.statsfunc() s = stats['stats'] if d.seed: status = 'seeding' progress = '100.0%' seeds = s.numOldSeeds seedsmsg = "s" dist = s.numCopies else: if s.numSeeds + s.numPeers: t = stats['time'] if t == 0: # unlikely t = 0.01 status = formatIntClock(t) or 'downloading' else: t = -1 status = 'connecting to peers' progress = '{:.1%}'.format(stats['frac']) seeds = s.numSeeds dist = s.numCopies2 dnrate = stats['down'] peers = s.numPeers uprate = stats['up'] upamt = s.upTotal dnamt = s.downTotal if d.is_dead() or d.status_errtime + 300 > clock(): msg = d.status_err[-1] else: msg = '' data.append((name, status, progress, peers, seeds, seedsmsg, dist, uprate, dnrate, upamt, dnamt, size, t, msg)) stop = self.Output.display(data) if stop: self.doneflag.set() def remove(self, hash): self.torrent_list.remove(hash) self.downloads[hash].shutdown() del self.downloads[hash] def add(self, hash, data): peer_id = createPeerID(self.counter) self.counter += 1 d = SingleDownload(self, hash, data['metainfo'], self.config, peer_id) self.torrent_list.append(hash) self.downloads[hash] = d d.start() def saveAs(self, hash, name, saveas, isdir): x = self.torrent_cache[hash] style = self.config['saveas_style'] if style == 1 or style == 3: if saveas: saveas = os.path.join(saveas, x['file'][:-1 - len(x['type'])]) else: saveas = x['path'][:-1 - len(x['type'])] if style == 3: if not os.path.isdir(saveas): try: os.mkdir(saveas) except OSError: raise OSError("couldn't create directory for {} ({})" ''.format(x['path'], saveas)) if not isdir: saveas = os.path.join(saveas, name) else: if saveas: saveas = os.path.join(saveas, name) else: saveas = os.path.join(os.path.split(x['path'])[0], name) if isdir and not os.path.isdir(saveas): try: os.mkdir(saveas) except OSError: raise OSError("couldn't create directory for {} ({})".format( x['path'], saveas)) return saveas def hashchecksched(self, hash=None): if hash: self.hashcheck_queue.append(hash) if not self.hashcheck_current: self._hashcheck_start() def _hashcheck_start(self): self.hashcheck_current = self.hashcheck_queue.pop(0) self.downloads[self.hashcheck_current].hashcheck_start( self.hashcheck_callback) def hashcheck_callback(self): self.downloads[self.hashcheck_current].hashcheck_callback() if self.hashcheck_queue: self._hashcheck_start() else: self.hashcheck_current = None def died(self, hash): if hash in self.torrent_cache: self.Output.message('DIED: "{}"'.format( self.torrent_cache[hash]['path'])) def was_stopped(self, hash): try: self.hashcheck_queue.remove(hash) except ValueError: pass if self.hashcheck_current == hash: self.hashcheck_current = None if self.hashcheck_queue: self._hashcheck_start() def failed(self, s): self.Output.message('FAILURE: ' + s) def exchandler(self, s): self.Output.exception(s)
def run(params): h = HeadlessDisplayer() while 1: configdir = ConfigDir('downloadheadless') defaultsToIgnore = ['metafile', 'url', 'priority'] configdir.setDefaults(defaults, defaultsToIgnore) configdefaults = configdir.loadConfig() defaults.append( ('save_options', 0, 'whether to save the current options as the ' 'new default configuration (only for btdownloadheadless.py)')) try: config = parse_params(params, configdefaults) except ValueError as e: print('error: {}\n'.format(e), 'run with no args for parameter explanations') break if not config: print(get_usage(defaults, 80, configdefaults)) break if config['save_options']: configdir.saveConfig(config) configdir.deleteOldCacheData(config['expire_cache_data']) myid = createPeerID() random.seed(myid) doneflag = threading.Event() def disp_exception(text): print(text) rawserver = RawServer( doneflag, config['timeout_check_interval'], config['timeout'], ipv6_enable=config['ipv6_enabled'], failfunc=h.failed, errorfunc=disp_exception) upnp_type = UPnP_test(config['upnp_nat_access']) while True: try: listen_port = rawserver.find_and_bind( config['minport'], config['maxport'], config['bind'], ipv6_socket_style=config['ipv6_binds_v4'], upnp=upnp_type, randomizer=config['random_port']) break except socket.error as e: if upnp_type and e == UPnP_ERROR: print('WARNING: COULD NOT FORWARD VIA UPnP') upnp_type = 0 continue print("error: Couldn't listen - ", e) h.failed() return metainfo = get_metainfo(config['metafile'], config['url'], h.error) if not metainfo: break infohash = hashlib.sha1(bencode(metainfo['info'])).digest() dow = BT1Download( h.display, h.finished, h.error, disp_exception, doneflag, config, metainfo, infohash, myid, rawserver, listen_port, configdir) if not dow.saveAs(h.chooseFile, h.newpath): break if not dow.initFiles(old_style=True): break if not dow.startEngine(): dow.shutdown() break dow.startRerequester() dow.autoStats() if not dow.am_I_finished(): h.display(activity='connecting to peers') rawserver.listen_forever(dow.getPortHandler()) h.display(activity='shutting down') dow.shutdown() break try: rawserver.shutdown() except Exception: pass if not h.done: h.failed()
def run(scrwin, errlist, params): doneflag = threading.Event() d = CursesDisplayer(scrwin, errlist, doneflag) try: while 1: configdir = ConfigDir("downloadcurses") defaultsToIgnore = ["metafile", "url", "priority"] configdir.setDefaults(defaults, defaultsToIgnore) configdefaults = configdir.loadConfig() defaults.append( ( "save_options", 0, "whether to save the current options as " "the new default configuration (only for btdownloadcurses.py)", ) ) try: config = parse_params(params, configdefaults) except ValueError as e: d.error("error: {}\nrun with no args for parameter " "explanations".format(e)) break if not config: d.error(get_usage(defaults, d.fieldw, configdefaults)) break if config["save_options"]: configdir.saveConfig(config) configdir.deleteOldCacheData(config["expire_cache_data"]) myid = createPeerID() random.seed(myid) rawserver = RawServer( doneflag, config["timeout_check_interval"], config["timeout"], ipv6_enable=config["ipv6_enabled"], failfunc=d.failed, errorfunc=d.error, ) upnp_type = UPnP_test(config["upnp_nat_access"]) while True: try: listen_port = rawserver.find_and_bind( config["minport"], config["maxport"], config["bind"], ipv6_socket_style=config["ipv6_binds_v4"], upnp=upnp_type, randomizer=config["random_port"], ) break except socket.error as e: if upnp_type and e == UPnP_ERROR: d.error("WARNING: COULD NOT FORWARD VIA UPnP") upnp_type = 0 continue d.error("Couldn't listen - " + str(e)) d.failed() return metainfo = get_metainfo(config["metafile"], config["url"], d.error) if not metainfo: break infohash = hashlib.sha1(bencode(metainfo["info"])).digest() dow = BT1Download( d.display, d.finished, d.error, d.error, doneflag, config, metainfo, infohash, myid, rawserver, listen_port, configdir, ) if not dow.saveAs(d.chooseFile): break if not dow.initFiles(old_style=True): break if not dow.startEngine(): dow.shutdown() break dow.startRerequester() dow.autoStats() if not dow.am_I_finished(): d.display(activity="connecting to peers") rawserver.listen_forever(dow.getPortHandler()) d.display(activity="shutting down") dow.shutdown() break except KeyboardInterrupt: # ^C to exit... pass try: rawserver.shutdown() except Exception: pass if not d.done: d.failed()