def read_torrent_config(global_config, path, infohash, error_callback): section = infohash.encode('hex') filename = os.path.join(path, TORRENT_CONFIG_FILE) p = _read_config(filename) if not p.has_section(section): return {} else: c = {} for name, value in p.items(section): if global_config.has_key(name): t = type(global_config[name]) if t == bool: c[name] = value in ('1', 'True', True) else: try: c[name] = type(global_config[name])(value) except ValueError, e: error_callback('%s (name:%s value:%s type:%s global:%s)' % (str_exc(e), name, repr(value), type(global_config[name]), global_config[name])) # is this reasonable? c[name] = global_config[name] elif name == 'save_as': # Backwards compatibility for BitTorrent 4.4 torrent_config file c[name] = value try: c[name] = c[name].decode('utf-8') except: pass
def _dump_torrents(self): assert self.resume_from_torrent_config self.last_save_time = bttime() r = [] def write_entry(infohash, t): r.append(' '.join( (infohash.encode('hex'), str(t.uptotal), str(t.downtotal)))) r.append('BitTorrent UI state file, version 5') r.append('Queued torrents') for t in self.torrents.values(): write_entry(t.metainfo.infohash, self.torrents[t.metainfo.infohash]) r.append('End') f = None try: path = os.path.join(self.data_dir, 'ui_state') f = file(path + '.new', 'wb') f.write('\n'.join(r) + '\n') f.close() shutil.move(path + '.new', path) except Exception, e: self.logger.error(_("Could not save UI state: ") + str_exc(e)) if f is not None: f.close()
def errback(f): exc_type, value, tb = f.exc_info() if issubclass(exc_type, GetTorrent.GetTorrentException): self.logger.critical(str_exc(value)) else: self.logger.error("open_torrent_arg_with_callbacks failed", exc_info=f.exc_info())
class IPCUnixSocket(IPCSocketBase): def __init__(self, *args): IPCSocketBase.__init__(self, *args) data_dir, bad = encode_for_filesystem(self.config['data_dir']) if bad: raise BTFailure(_("Invalid path encoding.")) self.socket_filename = os.path.join(data_dir, self.name) def create(self): filename = self.socket_filename if os.path.exists(filename): try: self.send_command('no-op') except BTFailure: pass else: raise BTFailure( _("Could not create control socket: already in use")) try: os.unlink(filename) except OSError, e: raise BTFailure( _("Could not remove old control socket filename:") + str_exc(e)) try: controlsocket = self.rawserver.create_unixserversocket(filename) except socket.error, e: raise BTFailure( _("Could not create control socket: ") + str_exc(e))
def ping(self, dst, timeout, ttl=None): """Returns ICMP echo round-trip time to dst or returns None if a timeout occurs. timeout is measured in milliseconds. The TTL is useful if the caller wants to ping the router that is a number of hops in the direction of the dst, e.g., when a router will not respond to pings directly but will generate ICMP Time Exceeded messages.""" i = win32icmp.IcmpCreateFile() rtt = None try: o = None if ttl is not None: o = win32icmp.Options() o.Ttl = ttl addr, status, rtt = win32icmp.IcmpSendEcho(i, dst, None, o, timeout) if debug: if status == win32icmp.IP_SUCCESS: print "Reply from", addr + ":", "time=" + str(rtt) elif status == win32icmp.IP_TTL_EXPIRED_TRANSIT: print "Ping ttl expired %d: from %s time=%s" % ( status, str(addr), str(rtt)) else: print "Ping failed", win32icmp.status[status] except KeyboardInterrupt: raise except Exception, e: if debug: print "Ping failed:", str_exc(e)
def ping(self, dst, timeout, ttl = None): """Returns ICMP echo round-trip time to dst or returns None if a timeout occurs. timeout is measured in milliseconds. The TTL is useful if the caller wants to ping the router that is a number of hops in the direction of the dst, e.g., when a router will not respond to pings directly but will generate ICMP Time Exceeded messages.""" i = win32icmp.IcmpCreateFile() rtt = None try: o = None if ttl is not None: o = win32icmp.Options() o.Ttl = ttl addr, status, rtt = win32icmp.IcmpSendEcho(i, dst, None, o, timeout) if debug: if status == win32icmp.IP_SUCCESS: print "Reply from", addr + ":", "time=" + str(rtt) elif status == win32icmp.IP_TTL_EXPIRED_TRANSIT: print "Ping ttl expired %d: from %s time=%s" %( status, str(addr), str(rtt)) else: print "Ping failed", win32icmp.status[status] except KeyboardInterrupt: raise except Exception, e: if debug: print "Ping failed:", str_exc(e)
def get(self, connection, path, headers): ip = connection.get_ip() nip = get_forwarded_ip(headers) if nip and not self.only_local_override_ip: ip = nip paramslist = {} def params(key, default = None, l = paramslist): if l.has_key(key): return l[key][0] return default try: (scheme, netloc, path, pars, query, fragment) = urlparse(path) if self.uq_broken == 1: path = path.replace('+',' ') query = query.replace('+',' ') path = unquote(path)[1:] for s in query.split('&'): if s != '': i = s.index('=') kw = unquote(s[:i]) paramslist.setdefault(kw, []) paramslist[kw] += [unquote(s[i+1:])] if path == '' or path == 'index.html': return self.get_infopage() if path == 'scrape': return self.get_scrape(paramslist) if (path == 'file'): return self.get_file(params('info_hash')) if path == 'favicon.ico' and self.favicon is not None: return (200, 'OK', {'Content-Type' : 'image/x-icon'}, self.favicon) if path != 'announce': return (404, 'Not Found', default_headers, alas) # main tracker function infohash = params('info_hash') if not infohash: raise ValueError, 'no info hash' notallowed = self.check_allowed(infohash, paramslist) if notallowed: if NOISY: self._print_event( "get: NOT ALLOWED: info_hash=%s, %s" % (infohash.encode('hex'). str(notallowed)) ) return notallowed event = params('event') rsize = self.add_data(infohash, event, ip, paramslist) except ValueError, e: print e if NOISY: self._print_exc( "get: ",e ) return (400, 'Bad Request', {'Content-Type': 'text/plain'}, 'you sent me garbage - ' + str_exc(e))
def _restore_state(self, init_torrents): def decode_line(line): hashtext = line[:40] try: infohash = InfoHashType(hashtext.decode('hex')) except: raise BTFailure(_("Invalid state file contents")) if len(infohash) != 20: raise BTFailure(_("Invalid state file contents")) if infohash in self.torrents: raise BTFailure(_("Invalid state file (duplicate entry)")) try: metainfo = self._read_metainfo(infohash) except OSError, e: try: f.close() except: pass self.logger.error((_("Error reading metainfo file \"%s\".") % hashtext) + " (" + str_exc(e)+ "), " + _("cannot restore state completely")) return None except Exception, e: self.logger.error((_("Corrupt data in metainfo \"%s\", cannot restore torrent.") % hashtext) + '('+str_exc(e)+')') return None
def _restore_state(self, init_torrents): def decode_line(line): hashtext = line[:40] try: infohash = InfoHashType(hashtext.decode('hex')) except: raise BTFailure(_("Invalid state file contents")) if len(infohash) != 20: raise BTFailure(_("Invalid state file contents")) if infohash in self.torrents: raise BTFailure(_("Invalid state file (duplicate entry)")) try: metainfo = self._read_metainfo(infohash) except OSError, e: try: f.close() except: pass self.logger.error((_("Error reading metainfo file \"%s\".") % hashtext) + " (" + str_exc(e) + "), " + _("cannot restore state completely")) return None except Exception, e: self.logger.error((_( "Corrupt data in metainfo \"%s\", cannot restore torrent.") % hashtext) + '(' + str_exc(e) + ')') return None
def parse_options(defaults, newvalues, encoding): """Given the type provided by the default value, this tries to cast/convert the corresponding newvalue to the type of the default value. By calling eval() on it, in some cases! Entertainly, newvalue sometimes holds strings and, apparently, sometimes holds values which have already been cast appropriately. This function is like a boat made of shit, floating on a river of shit. @param defaults: dict of key-value pairs where value is the default. @param newvalues: dict of key-value pairs which override the default. """ assert type(defaults) == dict assert type(newvalues) == dict for key, value in newvalues.iteritems(): if not defaults.has_key(key): raise UsageException(_("unknown option ") + format_key(key)) try: t = type(defaults[key]) if t is bool: if value in ('True', '1', True): value = True else: value = False newvalues[key] = value elif t in (StringType, NoneType): # force ASCII newvalues[key] = value.decode('ascii').encode('ascii') elif t in (IntType, LongType): if value == 'False': newvalues[key] == 0 elif value == 'True': newvalues[key] == 1 else: newvalues[key] = int(value) elif t is FloatType: newvalues[key] = float(value) elif t in (ListType, TupleType, DictType): if type(value) == StringType: try: n = eval(value) assert type(n) == t newvalues[key] = n except: newvalues[key] = t() elif t is UnicodeType: if type(value) == StringType: try: newvalues[key] = value.decode(encoding) except: newvalues[key] = value.decode('ascii') else: raise TypeError, str(t) except ValueError, e: raise UsageException( _("wrong format of %s - %s") % (format_key(key), str_exc(e)))
def parse_options(defaults, newvalues, encoding): """Given the type provided by the default value, this tries to cast/convert the corresponding newvalue to the type of the default value. By calling eval() on it, in some cases! Entertainly, newvalue sometimes holds strings and, apparently, sometimes holds values which have already been cast appropriately. This function is like a boat made of shit, floating on a river of shit. @param defaults: dict of key-value pairs where value is the default. @param newvalues: dict of key-value pairs which override the default. """ assert type(defaults) == dict assert type(newvalues) == dict for key, value in newvalues.iteritems(): if not defaults.has_key(key): raise UsageException(_("unknown option ") + format_key(key)) try: t = type(defaults[key]) if t is bool: if value in ('True', '1', True): value = True else: value = False newvalues[key] = value elif t in (StringType, NoneType): # force ASCII newvalues[key] = value.decode('ascii').encode('ascii') elif t in (IntType, LongType): if value == 'False': newvalues[key] == 0 elif value == 'True': newvalues[key] == 1 else: newvalues[key] = int(value) elif t is FloatType: newvalues[key] = float(value) elif t in (ListType, TupleType, DictType): if type(value) == StringType: try: n = eval(value) assert type(n) == t newvalues[key] = n except: newvalues[key] = t() elif t is UnicodeType: if type(value) == StringType: try: newvalues[key] = value.decode(encoding) except: newvalues[key] = value.decode('ascii') else: raise TypeError, str(t) except ValueError, e: raise UsageException(_("wrong format of %s - %s") % (format_key(key), str_exc(e)))
def _get_torrent(self, installer_url): """Get the .torrent file from the version site.""" torrentfile = None try: torrentfile = GetTorrent.get_url(installer_url) except GetTorrent.GetTorrentException, e: self.debug('_get_torrent() run#%d: failed to download torrent file %s: %s' % (self.runs, installer_url, str_exc(e))) pass
def _get_torrent(self, installer_url): """Get the .torrent file from the version site.""" torrentfile = None try: torrentfile = GetTorrent.get_url(installer_url) except GetTorrent.GetTorrentException, e: self.debug( '_get_torrent() run#%d: failed to download torrent file %s: %s' % (self.runs, installer_url, str_exc(e))) pass
def data_came_in(self, addr, datagram): if self.transport is None: return try: statusline, response = datagram.split('\r\n', 1) except ValueError, e: nat_logger.error(str_exc(e) + ": " + str(datagram)) # resume init services, because the data is unknown self.traverser.resume_init_services() return
def to_utf8(name): if isinstance(name, unicode): u = name else: try: u = decode_from_filesystem(name) except Exception, e: s = str_exc(e) raise BTFailure(_('Could not convert file/directory name %r to ' 'Unicode (%s). Either the assumed filesystem ' 'encoding "%s" is wrong or the filename contains ' 'illegal bytes.') % (name, s, get_filesystem_encoding()))
def init_services(self): # this loop is a little funny so a service can resume the init if it fails later if not self.rawserver.config['upnp']: return while self.current_service < len(self.services): service = self.services[self.current_service] self.current_service += 1 try: nat_logger.info("Trying: %s" % service.__name__) service(self) break except Exception, e: nat_logger.warning(str_exc(e))
def track(args): assert type(args) == list and \ len([x for x in args if type(x)==str])==len(args) config = {} defaults = get_defaults('bittorrent-tracker') # hard-coded defaults. try: config, files = parse_configuration_and_args(defaults, 'bittorrent-tracker', args, 0, 0 ) except ValueError, e: print _("error: ") + str_exc(e) print _("run with -? for parameter explanations") return
def to_utf8(name): if isinstance(name, unicode): u = name else: try: u = decode_from_filesystem(name) except Exception, e: s = str_exc(e) raise BTFailure( _('Could not convert file/directory name %r to ' 'Unicode (%s). Either the assumed filesystem ' 'encoding "%s" is wrong or the filename contains ' 'illegal bytes.') % (name, s, get_filesystem_encoding()))
def _cbRender(self, result, request): if isinstance(result, Handler): result = result.result if not isinstance(result, Fault): result = (result,) try: s = ebrpc.dumps(result, methodresponse=1) except Exception, e: f = Fault(self.FAILURE, "function:%s can't serialize output: %s" % (request.functionPath, str_exc(e))) self._err(f) s = ebrpc.dumps(f, methodresponse=1)
def send_command(self, command, *args): s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) filename = self.socket_filename try: s.connect(filename) s.send(tobinary(len(command))) s.send(command) for arg in args: s.send(tobinary(len(arg))) s.send(arg) s.close() except socket.error, e: s.close() raise BTFailure(_("Could not send command: ") + str_exc(e))
def _write_config(error_callback, filename, p): if not p.has_section('format'): p.add_section('format') p.set('format', 'encoding', 'utf-8') try: f = file(filename, 'wb') p.write(f) f.close() except Exception, e: try: f.close() except: pass error_callback(_("Could not permanently save options: ")+str_exc(e))
def _write_config(error_callback, filename, p): if not p.has_section("format"): p.add_section("format") p.set("format", "encoding", "utf-8") try: f = file(filename, "wb") p.write(f) f.close() except Exception, e: try: f.close() except: pass error_callback(_("Could not permanently save options: ") + str_exc(e))
def create(self): filename = self.socket_filename if os.path.exists(filename): try: self.send_command('no-op') except BTFailure: pass else: raise BTFailure(_("Could not create control socket: already in use")) try: os.unlink(filename) except OSError, e: raise BTFailure(_("Could not remove old control socket filename:") + str_exc(e))
def create(self): filename = self.socket_filename if os.path.exists(filename): try: self.send_command('no-op') except BTFailure: pass else: raise BTFailure( _("Could not create control socket: already in use")) try: os.unlink(filename) except OSError, e: raise BTFailure( _("Could not remove old control socket filename:") + str_exc(e))
def send_command(self, command, *datas): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: s.connect(('127.0.0.1', self.port)) s.send(tobinary(len(command))) s.send(command) for data in datas: data = data.encode('utf-8') s.send(tobinary(len(data))) s.send(data) s.close() except socket.error, e: try: s.close() except: pass raise BTFailure(_("Could not send command: ") + str_exc(e))
def traceroute(self, dst, timeout, report=None): """If report is None then this returns the route as a list of IP addresses. If report is not None then this calls report as each node is discovered in the path (e.g., if there are 6 hops in the path then report gets called 6 times).""" if debug: print "Tracing route to [%s]" % dst i = win32icmp.IcmpCreateFile() o = win32icmp.Options() route = None if report == None: route = [] def add_node(node): route.append(node) report = add_node for ttl in xrange(64): o.Ttl = ttl try: if ttl == 0: addr = get_host_ip() status = -1 rtt = 0 else: addr, status, rtt = win32icmp.IcmpSendEcho( i, dst, None, o, timeout) if debug: print "ttl", ttl, "\t", rtt, "ms\t", addr report(addr) if status == win32icmp.IP_SUCCESS: if debug: print "Traceroute complete in", ttl, "hops" break except Exception, e: report('*') if debug: print "Hop", ttl, "failed:", str_exc(e) if self.abort_traceroute.isSet(): break
def traceroute(self, dst, timeout, report=None): """If report is None then this returns the route as a list of IP addresses. If report is not None then this calls report as each node is discovered in the path (e.g., if there are 6 hops in the path then report gets called 6 times).""" if debug: print "Tracing route to [%s]" % dst i = win32icmp.IcmpCreateFile() o = win32icmp.Options() route = None if report == None: route = [] def add_node(node): route.append(node) report = add_node for ttl in xrange(64): o.Ttl = ttl try: if ttl == 0: addr = get_host_ip() status = -1 rtt = 0 else: addr, status, rtt = win32icmp.IcmpSendEcho(i, dst, None, o, timeout) if debug: print "ttl", ttl, "\t", rtt, "ms\t", addr report(addr) if status == win32icmp.IP_SUCCESS: if debug: print "Traceroute complete in", ttl, "hops" break except Exception, e: report('*') if debug: print "Hop", ttl, "failed:", str_exc(e) if self.abort_traceroute.isSet(): break
def _dump_torrents(self): assert self.resume_from_torrent_config self.last_save_time = bttime() r = [] def write_entry(infohash, t): r.append(' '.join((infohash.encode('hex'), str(t.uptotal), str(t.downtotal)))) r.append('BitTorrent UI state file, version 5') r.append('Queued torrents') for t in self.torrents.values(): write_entry(t.metainfo.infohash, self.torrents[t.metainfo.infohash]) r.append('End') f = None try: path = os.path.join(self.data_dir, 'ui_state') f = file(path+'.new', 'wb') f.write('\n'.join(r) + '\n') f.close() shutil.move(path+'.new', path) except Exception, e: self.logger.error(_("Could not save UI state: ") + str_exc(e)) if f is not None: f.close()
def read_config(self): try: newvalues = configfile.get_config(self.config, self.configfile_key) except Exception, e: self.logger.error(_("Error reading config: ") + str_exc(e) ) return
def __init__(self, config, display, configfile_key): """Starts torrents for all .torrent files in a directory tree. All errors are logged using Python logging to 'configfile_key' logger. @param config: Preferences object storing config. @param display: output function for stats. """ # 4.4.x version of LaunchMany output exceptions to a displayer. # This version only outputs stats to the displayer. We do not use # the logger to output stats so that a caller-provided object # can provide stats formatting as opposed to using the # logger Formatter, which is specific to exceptions, warnings, and # info messages. self.logger = logging.getLogger(configfile_key) try: self.multitorrent = None self.rawserver = None self.config = config self.configfile_key = configfile_key self.display = display self.torrent_dir = config['torrent_dir'] # Ex: torrent_cache = infohash -> (path,metainfo) self.torrent_cache = {} # maps path -> [(modification time, size), infohash] self.file_cache = {} # used as set containing paths of files that do not have separate # entries in torrent_cache either because torrent_cache already # contains the torrent or because the torrent file is corrupt. self.blocked_files = {} #self.torrent_list = [] #self.downloads = {} self.hashcheck_queue = [] #self.hashcheck_store = {} self.hashcheck_current = None self.core_doneflag = DeferredEvent() self.rawserver = RawServer(self.config) try: # set up shut-down procedure before we begin doing things that # can throw exceptions. def shutdown(): self.logger.critical(_("shutting down")) for t in self.multitorrent.get_torrents(): self.logger.info(_('dropped "%s"') % self.torrent_cache[t.infohash][0]) if self.multitorrent: df = self.multitorrent.shutdown() set_flag = lambda *a : self.rawserver.stop() df.addCallbacks(set_flag, set_flag) else: self.rawserver.stop() # It is safe to addCallback here, because there is only one thread, # but even if the code were multi-threaded, core_doneflag has not # been passed to anyone. There is no chance of a race condition # between the DeferredEvent's callback and addCallback. self.core_doneflag.addCallback( lambda r: self.rawserver.external_add_task(0, shutdown)) self.rawserver.install_sigint_handler(self.core_doneflag) data_dir = config['data_dir'] self.multitorrent = MultiTorrent(config, self.rawserver, data_dir, resume_from_torrent_config=False) self.rawserver.add_task(0, self.scan) self.rawserver.add_task(0.5, self.periodic_check_hashcheck_queue) self.rawserver.add_task(self.config['display_interval'], self.periodic_stats) try: import signal def handler(signum, frame): self.rawserver.external_add_task(0, self.read_config) signal.signal(signal.SIGHUP, handler) except Exception, e: self.logger.error(_("Could not set signal handler: ") + str_exc(e)) self.rawserver.add_task(0,self.core_doneflag.set()) except UserFailure, e: self.logger.error(str_exc(e)) self.rawserver.add_task(0,self.core_doneflag.set()) except: data = StringIO() print_exc(file = data) self.logger.error(data.getvalue()) self.rawserver.add_task(0,self.core_doneflag.set()) # always make sure events get processed even if only for # shutting down. self.rawserver.listen_forever()
''' if self.config['start_trackerless_client']: self.dht = UTKhashmir(self.config['bind'], self.singleport_listener.get_port(), self.data_dir, self.rawserver, int(self.config['max_upload_rate'] * 0.01), rlcount=self.up_ratelimiter.increase_offset, config=self.config) ''' break except socket.error, e: exc_info = sys.exc_info() else: if not listen_fail_ok: raise BTFailure, (_("Could not open a listening port: %s.") % str_exc(e)) self.global_error( logging.CRITICAL, (_("Could not open a listening port: %s. ") % e) + (_("Check your port range settings (%s:%s-%s).") % (self.config['bind'], self.config['minport'], self.config['maxport'])), exc_info=exc_info) def shutdown(self): df = launch_coroutine(wrap_task(self.rawserver.add_task), self._shutdown) df.addErrback(lambda f: self.logger.error('shutdown failed!', exc_info=f.exc_info())) return df
def read_config(self): try: newvalues = configfile.get_config(self.config, self.configfile_key) except Exception, e: self.logger.error(_("Error reading config: ") + str_exc(e)) return
def track(args): assert type(args) == list and \ len([x for x in args if type(x)==str])==len(args) config = {} defaults = get_defaults('bittorrent-tracker') # hard-coded defaults. try: config, files = parse_configuration_and_args(defaults, 'bittorrent-tracker', args, 0, 0 ) except ValueError, e: print _("error: ") + str_exc(e) print _("run with -? for parameter explanations") return except BTFailure, e: print _("error: ") + str_exc(e) print _("run with -? for parameter explanations") return if config['dfile']=="": config['dfile'] = decode_from_filesystem( os.path.join(platform.get_temp_dir(), efs2(u"dfile") + str(os.getpid()))) config = Preferences().initWithDict(config) ef = lambda e: errorfunc(logging.WARNING, e) platform.write_pid_file(config['pid'], ef) t = None try: r = RawServer(config)
def __init__(self, config, display, configfile_key): """Starts torrents for all .torrent files in a directory tree. All errors are logged using Python logging to 'configfile_key' logger. @param config: Preferences object storing config. @param display: output function for stats. """ # 4.4.x version of LaunchMany output exceptions to a displayer. # This version only outputs stats to the displayer. We do not use # the logger to output stats so that a caller-provided object # can provide stats formatting as opposed to using the # logger Formatter, which is specific to exceptions, warnings, and # info messages. self.logger = logging.getLogger(configfile_key) try: self.multitorrent = None self.rawserver = None self.config = config self.configfile_key = configfile_key self.display = display self.torrent_dir = config['torrent_dir'] # Ex: torrent_cache = infohash -> (path,metainfo) self.torrent_cache = {} # maps path -> [(modification time, size), infohash] self.file_cache = {} # used as set containing paths of files that do not have separate # entries in torrent_cache either because torrent_cache already # contains the torrent or because the torrent file is corrupt. self.blocked_files = {} #self.torrent_list = [] #self.downloads = {} self.hashcheck_queue = [] #self.hashcheck_store = {} self.hashcheck_current = None self.core_doneflag = DeferredEvent() self.rawserver = RawServer(self.config) try: # set up shut-down procedure before we begin doing things that # can throw exceptions. def shutdown(): self.logger.critical(_("shutting down")) if self.multitorrent: if len(self.multitorrent.get_torrents()) > 0: for t in self.multitorrent.get_torrents(): self.logger.info( _('dropped "%s"') % self.torrent_cache[t.infohash][0]) def after_mt(r): self.logger.critical( "multitorrent shutdown completed. Calling rawserver.stop" ) self.rawserver.stop() self.logger.critical("calling multitorrent shutdown") df = self.multitorrent.shutdown() #set_flag = lambda *a : self.rawserver.stop() df.addCallbacks(after_mt, after_mt) else: self.rawserver.stop() ### PROFILER POSTPROCESSING. #self.logger.critical( "Disabling profiles" ) #prof.disable() #self.logger.critical( "Running profiler post-processing" ) #stats = Stats(prof.getstats()) #stats.sort("inlinetime") #self.logger.info( "Calling stats.pprint") #stats.pprint() #self.logger.info( "After stats.pprint") ### PROFILER POSTPROCESSING # It is safe to addCallback here, because there is only one thread, # but even if the code were multi-threaded, core_doneflag has not # been passed to anyone. There is no chance of a race condition # between the DeferredEvent's callback and addCallback. self.core_doneflag.addCallback( lambda r: self.rawserver.external_add_task(0, shutdown)) self.rawserver.install_sigint_handler(self.core_doneflag) data_dir = config['data_dir'] self.multitorrent = MultiTorrent( config, self.rawserver, data_dir, resume_from_torrent_config=False) # first time sleep_time is 0 so that it will startup fast. On # subsequent scans, the scan is slowed down to not affect performance. self.rawserver.add_task(0, self.scan, sleep_time=0) self.rawserver.add_task(0.5, self.periodic_check_hashcheck_queue) self.rawserver.add_task(self.config['display_interval'], self.periodic_stats) try: import signal def handler(signum, frame): self.rawserver.external_add_task(0, self.read_config) if hasattr(signal, 'SIGHUP'): signal.signal(signal.SIGHUP, handler) except Exception, e: self.logger.error( _("Could not set signal handler: ") + str_exc(e)) self.rawserver.add_task(0, self.core_doneflag.set) except UserFailure, e: self.logger.error(str_exc(e)) self.rawserver.add_task(0, self.core_doneflag.set) except: #data = StringIO() #print_exc(file = data) #self.logger.error(data.getvalue()) self.logger.exception( "Exception raised while initializing LaunchMany") self.rawserver.add_task(0, self.core_doneflag.set) # always make sure events get processed even if only for # shutting down. self.rawserver.listen_forever() self.logger.info("After rawserver.listen_forever")
try: self.singleport_listener.open_port(port, self.config) if self.config['start_trackerless_client']: self.dht = UTKhashmir(self.config['bind'], self.singleport_listener.get_port(), self.data_dir, self.rawserver, int(self.config['max_upload_rate'] * 0.01), rlcount=self.up_ratelimiter.increase_offset, config=self.config) break except socket.error, e: exc_info = sys.exc_info() else: if not listen_fail_ok: raise BTFailure, (_("Could not open a listening port: %s.") % str_exc(e) ) self.global_error(logging.CRITICAL, (_("Could not open a listening port: %s. ") % e) + (_("Check your port range settings (%s:%s-%s).") % (self.config['bind'], self.config['minport'], self.config['maxport'])), exc_info=exc_info) def shutdown(self): df = launch_coroutine(wrap_task(self.rawserver.add_task), self._shutdown) df.addErrback(lambda f : self.logger.error('shutdown failed!', exc_info=f.exc_info())) return df def _shutdown(self): self.choker.shutdown()