📄 track.py
字号:
if nip and not self.only_local_override_ip: ip = nip try: ip = to_ipv4(ip) ipv4 = True except ValueError: ipv4 = False 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 == '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) # automated access from here on if path in ('scrape', 'scrape.php', 'tracker.php/scrape'): return self.get_scrape(paramslist) if not path in ('announce', 'announce.php', 'tracker.php/announce'): return (404, 'Not Found', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'}, alas) # main tracker function filtered = self.Filter.check(real_ip, paramslist, headers) if filtered: return (400, 'Not Authorized', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'}, bencode({'failure reason': filtered})) infohash = params('info_hash') if not infohash: raise ValueError, 'no info hash' notallowed = self.check_allowed(infohash, paramslist) if notallowed: return notallowed event = params('event') rsize = self.add_data(infohash, event, ip, paramslist) except ValueError, e: return (400, 'Bad Request', {'Content-Type': 'text/plain'}, 'you sent me garbage - ' + str(e)) if self.aggregate_forward and not paramslist.has_key('tracker'): self.aggregate_senddata(query) if self.is_aggregator: # don't return peer data here return (200, 'OK', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'}, bencode({'response': 'OK'})) if params('compact') and ipv4: if params('requirecrypto'): return_type = 1 elif params('supportcrypto'): return_type = 2 else: return_type = 0 elif self.config['compact_reqd'] and ipv4: return (400, 'Bad Request', {'Content-Type': 'text/plain'}, 'your client is outdated, please upgrade') elif params('no_peer_id'): return_type = 4 else: return_type = 3 data = self.peerlist(infohash, event=='stopped', params('tracker'), not params('left'), return_type, rsize, params('supportcrypto')) if paramslist.has_key('scrape'): # deprecated data['scrape'] = self.scrapedata(infohash, False) if self.dedicated_seed_id: if params('seed_id') == self.dedicated_seed_id and params('left') == 0: self.is_seeded[infohash] = True if params('check_seeded') and self.is_seeded.get(infohash): data['seeded'] = 1 return (200, 'OK', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'}, bencode(data)) def natcheckOK(self, infohash, peerid, ip, port, peer): seed = not peer['left'] bc = self.becache.setdefault(infohash,self.cache_default) cp = compact_peer_info(ip, port) reqc = peer['requirecrypto'] bc[2][seed][peerid] = (cp,chr(reqc)) if peer['supportcrypto']: bc[1][seed][peerid] = cp if not reqc: bc[0][seed][peerid] = cp if not self.config['compact_reqd']: bc[3][seed][peerid] = Bencached(bencode({'ip': ip, 'port': port, 'peer id': peerid})) bc[4][seed][peerid] = Bencached(bencode({'ip': ip, 'port': port})) def natchecklog(self, peerid, ip, port, result): year, month, day, hour, minute, second, a, b, c = localtime(time()) print '%s - %s [%02d/%3s/%04d:%02d:%02d:%02d] "!natcheck-%s:%i" %i 0 - -' % ( ip, quote(peerid), day, months[month], year, hour, minute, second, ip, 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) elif result and record['nat']: record['nat'] = 0 self.natcheckOK(downloadid,peerid,ip,port,record) elif not result: record['nat'] += 1 def remove_from_state(self, *l): for s in l: try: del self.state[s] except: pass def save_state(self): self.rawserver.add_task(self.save_state, self.save_dfile_interval) h = open(self.dfile, 'wb') h.write(bencode(self.state)) h.close() def parse_allowed(self): self.rawserver.add_task(self.parse_allowed, self.parse_dir_interval) if self.config['allowed_dir']: r = parsedir( self.config['allowed_dir'], self.allowed, self.allowed_dir_files, self.allowed_dir_blocked, [".torrent"] ) ( self.allowed, self.allowed_dir_files, self.allowed_dir_blocked, added, garbage2 ) = r self.state['allowed'] = self.allowed self.state['allowed_dir_files'] = self.allowed_dir_files self.t2tlist.parse(self.allowed) else: f = self.config['allowed_list'] if self.allowed_list_mtime == os.path.getmtime(f): return try: r = parsetorrentlist(f, self.allowed) (self.allowed, added, garbage2) = r self.state['allowed_list'] = self.allowed except (IOError, OSError): print '**warning** unable to read allowed torrent list' return self.allowed_list_mtime = os.path.getmtime(f) for infohash in added.keys(): self.downloads.setdefault(infohash, {}) self.completed.setdefault(infohash, 0) self.seedcount.setdefault(infohash, 0) def read_ip_lists(self): self.rawserver.add_task(self.read_ip_lists,self.parse_dir_interval) f = self.config['allowed_ips'] if f and self.allowed_ip_mtime != os.path.getmtime(f): self.allowed_IPs = IP_List() try: self.allowed_IPs.read_fieldlist(f) self.allowed_ip_mtime = os.path.getmtime(f) except (IOError, OSError): print '**warning** unable to read allowed_IP list' f = self.config['banned_ips'] if f and self.banned_ip_mtime != os.path.getmtime(f): self.banned_IPs = IP_Range_List() try: self.banned_IPs.read_rangelist(f) self.banned_ip_mtime = os.path.getmtime(f) except (IOError, OSError): print '**warning** unable to read banned_IP list' 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: if x[y].has_key(peerid): del x[y][peerid] del self.times[infohash][peerid] del dls[peerid] def expire_downloaders(self): for x in self.times.keys(): for myid, t in self.times[x].items(): if t < self.prevtime: self.delete_peer(x,myid) self.prevtime = clock() if (self.keep_dead != 1): for key, value in self.downloads.items(): if len(value) == 0 and ( self.allowed is None or not self.allowed.has_key(key) ): del self.times[key] del self.downloads[key] del self.seedcount[key] self.rawserver.add_task(self.expire_downloaders, self.timeout_downloaders_interval)def track(args): if len(args) == 0: print formatDefinitions(defaults, 80) return try: config, files = parseargs(args, defaults, 0, 0) except ValueError, e: print 'error: ' + str(e) print 'run with no arguments for parameter explanations' return r = RawServer(Event(), config['timeout_check_interval'], config['socket_timeout'], ipv6_enable = config['ipv6_enabled']) t = Tracker(config, r) r.bind(config['port'], config['bind'], reuse = True, ipv6_socket_style = config['ipv6_binds_v4']) r.listen_forever(HTTPHandler(t.get, config['min_time_between_log_flushes'])) t.save_state() print '# Shutting down: ' + isotime()def size_format(s): if (s < 1024): r = str(s) + 'B' elif (s < 1048576): r = str(int(s/1024)) + 'KiB' elif (s < 1073741824L): r = str(int(s/1048576)) + 'MiB' elif (s < 1099511627776L): r = str(int((s/1073741824.0)*100.0)/100.0) + 'GiB' else: r = str(int((s/1099511627776.0)*100.0)/100.0) + 'TiB' return(r)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -