📄 track.py
字号:
for rr in xrange(len(self.cached[infohash])): if rr != return_type: try: self.cached[infohash][rr][1].extend(vv[rr]) except: pass if len(cache[1]) < l_get_size: peerdata = cache[1] if not is_seed: peerdata.extend(cache[2]) cache[1] = [] cache[2] = [] else: if not is_seed: peerdata = cache[2][l_get_size-rsize:] del cache[2][l_get_size-rsize:] rsize -= len(peerdata) else: peerdata = [] if rsize: peerdata.extend(cache[1][-rsize:]) del cache[1][-rsize:] if return_type == 2: peerdata = ''.join(peerdata) data['peers'] = peerdata return data 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 - ' + unicode(e.args[0])) if params('compact'): return_type = 2 elif params('no_peer_id'): return_type = 1 else: return_type = 0 data = self.peerlist(infohash, event=='stopped', not params('left'), return_type, rsize) if paramslist.has_key('scrape'): data['scrape'] = self.scrapedata(infohash, False) return (200, 'OK', default_headers, bencode(data)) def natcheckOK(self, infohash, peerid, ip, port, not_seed): bc = self.becache.setdefault(infohash,[[{}, {}], [{}, {}], [{}, {}]]) bc[0][not not_seed][peerid] = Bencached(bencode({'ip': ip, 'port': port, 'peer id': peerid})) bc[1][not not_seed][peerid] = Bencached(bencode({'ip': ip, 'port': port})) bc[2][not not_seed][peerid] = compact_peer_info(ip, port) def natchecklog(self, peerid, ip, port, result): print isotime(), '"!natcheck-%s:%i" %s %i 0 - -' % ( ip, quote(peerid), port, result) def connectback_result(self, result, downloadid, peerid, ip, port): record = self.downloads.get(downloadid, {}).get(peerid) if ( record is None or (record['ip'] != ip and record.get('given ip') != ip) or record['port'] != port ): if self.config['log_nat_checks']: self.natchecklog(peerid, ip, port, 404) return if self.config['log_nat_checks']: if result: x = 200 else: x = 503 self.natchecklog(peerid, ip, port, x) if not record.has_key('nat'): record['nat'] = int(not result) if result: self.natcheckOK(downloadid,peerid,ip,port,record['left']) elif result and record['nat']: record['nat'] = 0 self.natcheckOK(downloadid,peerid,ip,port,record['left']) elif not result: record['nat'] += 1 def save_dfile(self): if self.save_pending: return self.save_pending = True # if this is taking all the time, threading it won't help anyway because # of the GIL #state = bencode(self.state) state = cPickle.dumps(self.state) # pickle handles Unicode. df = ThreadedDeferred(wrap_task(self.rawserver.external_add_task), self._save_dfile, state) def cb(r): self.save_pending = False if NOISY: self._print_event( "save_dfile: Completed" ) def eb(etup): self.save_pending = False self._print_exc( "save_dfile: ", etup ) df.addCallbacks(cb, eb) def _save_dfile(self, state): exc_info = None try: h = open(self.dfile, 'wb') h.write(state) h.close() except: exc_info = sys.exc_info() self.rawserver.external_add_task(self.save_dfile_interval, self.save_dfile) if exc_info: raise exc_info[0], exc_info[1], exc_info[2] def parse_allowed(self): if self.parse_pending: return self.parse_pending = True df = ThreadedDeferred(wrap_task(self.rawserver.external_add_task), self._parse_allowed, daemon=True) def eb(etup): self.parse_pending = False self._print_exc("parse_dir: ", etup) df.addCallbacks(self._parse_allowed_finished, eb) def _parse_allowed(self): def errfunc(message, exc_info=None): # logging broken .torrent files would be useful but could confuse # programs parsing log files m = "parse_dir: %s" % message if exc_info: self._print_exc(m, exc_info) else: self._print_event(m) pass r = parsedir(self.allowed_dir, self.allowed, self.allowed_dir_files, self.allowed_dir_blocked, errfunc, include_metainfo = False) # register the call to parse a dir. self.rawserver.external_add_task(self.parse_dir_interval, self.parse_allowed) return r def _parse_allowed_finished(self, r): self.parse_pending = False ( self.allowed, self.allowed_dir_files, self.allowed_dir_blocked, added, removed ) = r if NOISY: self._print_event("_parse_allowed_finished: removals: %s" % str(removed)) for infohash in added: self.downloads.setdefault(infohash, {}) self.completed.setdefault(infohash, 0) self.seedcount.setdefault(infohash, 0) self.state['allowed'] = self.allowed self.state['allowed_dir_files'] = self.allowed_dir_files def delete_peer(self, infohash, peerid): dls = self.downloads[infohash] peer = dls[peerid] if not peer['left']: self.seedcount[infohash] -= 1 if not peer.get('nat', -1): l = self.becache[infohash] y = not peer['left'] for x in l: del x[y][peerid] del self.times[infohash][peerid] del dls[peerid] def expire_downloaders(self): for infohash, peertimes in self.times.iteritems(): items = peertimes.items() for myid, t in items: if t < self.prevtime: self.delete_peer(infohash, myid) self.prevtime = time() if self.keep_dead != 1: items = self.downloads.items() for key, peers in items: if len(peers) == 0 and (self.allowed is None or key not in self.allowed): del self.times[key] del self.downloads[key] del self.seedcount[key] self.rawserver.add_task(self.timeout_downloaders_interval, self.expire_downloaders) def _print_event(self, message): print datetime.datetime.utcnow().isoformat(), message def _print_exc(self, note, etup): print datetime.datetime.utcnow().isoformat(), note, ':' traceback.print_exception(*etup)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: ") + unicode(e.args[0]) print _("run with -? for parameter explanations") return except BTFailure, e: print _("error: ") + unicode(e.args[0]) 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) t = Tracker(config, r) try: #DEBUG print "track: create_serversocket, port=", config['port'] #END s = r.create_serversocket(config['port'], config['bind'], True) handler = HTTPHandler(t.get, config['min_time_between_log_flushes']) r.start_listening(s, handler) except socket.error, e: print ("Unable to open port %d. Use a different port?" % config['port']) return r.listen_forever() finally: if t: t.save_dfile() print _("# Shutting down: ") + isotime()def size_format(s): return str(Size(s))def errorfunc( level, text ): print "%s: %s" % (logging.getLevelName(level), text)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -