📄 track.py
字号:
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 == 'scrape':
return self.get_scrape(paramslist)
if path != '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:
return_type = 2
elif params('no_peer_id'):
return_type = 1
else:
return_type = 0
data = self.peerlist(infohash, event=='stopped',
params('tracker'), not params('left'),
return_type, rsize)
if paramslist.has_key('scrape'):
data['scrape'] = self.scrapedata(infohash, False)
return (200, 'OK', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'}, 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):
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['left'])
elif result and record['nat']:
record['nat'] = 0
self.natcheckOK(downloadid,peerid,ip,port,record['left'])
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:
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 not args:
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 + -