📄 track.py
字号:
'Content-Disposition': 'attachment; filename=' + fname},
open(fpath, 'rb').read())
def check_allowed(self, infohash, paramslist):
if ( self.aggregator_key is not None
and not ( paramslist.has_key('password')
and paramslist['password'][0] == self.aggregator_key ) ):
return (200, 'Not Authorized', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'},
bencode({'failure reason':
'Requested download is not authorized for use with this tracker.'}))
if self.allowed is not None:
if not self.allowed.has_key(infohash):
return (200, 'Not Authorized', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'},
bencode({'failure reason':
'Requested download is not authorized for use with this tracker.'}))
if self.config['allowed_controls']:
if self.allowed[infohash].has_key('failure reason'):
return (200, 'Not Authorized', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'},
bencode({'failure reason': self.allowed[infohash]['failure reason']}))
if paramslist.has_key('tracker'):
if ( self.config['multitracker_allowed'] == 'none' or # turned off
paramslist['peer_id'][0] == self.trackerid ): # oops! contacted myself
return (200, 'Not Authorized', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'},
bencode({'failure reason': 'disallowed'}))
if ( self.config['multitracker_allowed'] == 'autodetect'
and not self.allowed[infohash].has_key('announce-list') ):
return (200, 'Not Authorized', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'},
bencode({'failure reason':
'Requested download is not authorized for multitracker use.'}))
return None
def add_data(self, infohash, event, ip, paramslist):
peers = self.downloads.setdefault(infohash, {})
ts = self.times.setdefault(infohash, {})
self.completed.setdefault(infohash, 0)
self.seedcount.setdefault(infohash, 0)
def params(key, default = None, l = paramslist):
if l.has_key(key):
return l[key][0]
return default
myid = params('peer_id','')
if len(myid) != 20:
raise ValueError, 'id not of length 20'
if event not in ['started', 'completed', 'stopped', 'snooped', None]:
raise ValueError, 'invalid event'
port = long(params('port',''))
if port < 0 or port > 65535:
raise ValueError, 'invalid port'
left = long(params('left',''))
if left < 0:
raise ValueError, 'invalid amount left'
uploaded = long(params('uploaded',''))
downloaded = long(params('downloaded',''))
peer = peers.get(myid)
islocal = local_IPs.includes(ip)
mykey = params('key')
if peer:
auth = peer.get('key',-1) == mykey or peer.get('ip') == ip
gip = params('ip')
if is_valid_ip(gip) and (islocal or not self.only_local_override_ip):
ip1 = gip
else:
ip1 = ip
if params('numwant') is not None:
rsize = min(int(params('numwant')),self.response_size)
else:
rsize = self.response_size
if event == 'stopped':
if peer:
if auth:
self.delete_peer(infohash,myid)
elif not peer:
ts[myid] = clock()
peer = {'ip': ip, 'port': port, 'left': left}
if mykey:
peer['key'] = mykey
if gip:
peer['given ip'] = gip
if port:
if not self.natcheck or islocal:
peer['nat'] = 0
self.natcheckOK(infohash,myid,ip1,port,left)
else:
NatCheck(self.connectback_result,infohash,myid,ip1,port,self.rawserver)
else:
peer['nat'] = 2**30
if event == 'completed':
self.completed[infohash] += 1
if not left:
self.seedcount[infohash] += 1
peers[myid] = peer
else:
if not auth:
return rsize # return w/o changing stats
ts[myid] = clock()
if not left and peer['left']:
self.completed[infohash] += 1
self.seedcount[infohash] += 1
if not peer.get('nat', -1):
for bc in self.becache[infohash]:
bc[1][myid] = bc[0][myid]
del bc[0][myid]
if peer['left']:
peer['left'] = left
if port:
recheck = False
if ip != peer['ip']:
peer['ip'] = ip
recheck = True
if gip != peer.get('given ip'):
if gip:
peer['given ip'] = gip
elif peer.has_key('given ip'):
del peer['given ip']
recheck = True
natted = peer.get('nat', -1)
if recheck:
if natted == 0:
l = self.becache[infohash]
y = not peer['left']
for x in l:
del x[y][myid]
if not self.natcheck or islocal:
del peer['nat'] # restart NAT testing
if natted and natted < self.natcheck:
recheck = True
if recheck:
if not self.natcheck or islocal:
peer['nat'] = 0
self.natcheckOK(infohash,myid,ip1,port,left)
else:
NatCheck(self.connectback_result,infohash,myid,ip1,port,self.rawserver)
return rsize
def peerlist(self, infohash, stopped, tracker, is_seed, return_type, rsize):
data = {} # return data
seeds = self.seedcount[infohash]
data['complete'] = seeds
data['incomplete'] = len(self.downloads[infohash]) - seeds
if ( self.config['allowed_controls']
and self.allowed[infohash].has_key('warning message') ):
data['warning message'] = self.allowed[infohash]['warning message']
if tracker:
data['interval'] = self.config['multitracker_reannounce_interval']
if not rsize:
return data
cache = self.cached_t.setdefault(infohash, None)
if ( not cache or len(cache[1]) < rsize
or cache[0] + self.config['min_time_between_cache_refreshes'] < clock() ):
bc = self.becache.setdefault(infohash,[[{}, {}], [{}, {}], [{}, {}]])
cache = [ clock(), bc[0][0].values() + bc[0][1].values() ]
self.cached_t[infohash] = cache
shuffle(cache[1])
cache = cache[1]
data['peers'] = cache[-rsize:]
del cache[-rsize:]
return data
data['interval'] = self.reannounce_interval
if stopped or not rsize: # save some bandwidth
data['peers'] = []
return data
bc = self.becache.setdefault(infohash,[[{}, {}], [{}, {}], [{}, {}]])
len_l = len(bc[0][0])
len_s = len(bc[0][1])
if not (len_l+len_s): # caches are empty!
data['peers'] = []
return data
l_get_size = int(float(rsize)*(len_l)/(len_l+len_s))
cache = self.cached.setdefault(infohash,[None,None,None])[return_type]
if cache and ( not cache[1]
or (is_seed and len(cache[1]) < rsize)
or len(cache[1]) < l_get_size
or cache[0]+self.config['min_time_between_cache_refreshes'] < self.cachetime ):
cache = None
if not cache:
peers = self.downloads[infohash]
vv = [[],[],[]]
for key, ip, port in self.t2tlist.harvest(infohash): # empty if disabled
if not peers.has_key(key):
vv[0].append({'ip': ip, 'port': port, 'peer id': key})
vv[1].append({'ip': ip, 'port': port})
vv[2].append(compact_peer_info(ip, port))
cache = [ self.cachetime,
bc[return_type][0].values()+vv[return_type],
bc[return_type][1].values() ]
shuffle(cache[1])
shuffle(cache[2])
self.cached[infohash][return_type] = cache
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):
real_ip = connection.get_ip()
ip = real_ip
if is_ipv4(ip):
ipv4 = True
else:
try:
ip = ipv6_to_ipv4(ip)
ipv4 = True
except ValueError:
ipv4 = False
if ( (self.allowed_IPs and not self.allowed_IPs.includes(ip))
or (self.banned_IPs and self.banned_IPs.includes(ip)) ):
return (400, 'Not Authorized', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'},
bencode({'failure reason':
'your IP is not allowed on this tracker'}))
nip = get_forwarded_ip(headers)
if nip and not self.only_local_override_ip:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -