Blame | Last modification | View Log | Download
# Written by Bram Cohen# see LICENSE.txt for license informationfrom cStringIO import StringIOfrom socket import error as socketerrorfrom traceback import print_exctry:Trueexcept:True = 1False = 0protocol_name = 'BitTorrent protocol'# header, reserved, download id, my id, [length, message]class NatCheck:def __init__(self, resultfunc, downloadid, peerid, ip, port, rawserver):self.resultfunc = resultfuncself.downloadid = downloadidself.peerid = peeridself.ip = ipself.port = portself.closed = Falseself.buffer = StringIO()self.next_len = 1self.next_func = self.read_header_lentry:self.connection = rawserver.start_connection((ip, port), self)self.connection.write(chr(len(protocol_name)) + protocol_name +(chr(0) * 8) + downloadid)except socketerror:self.answer(False)except IOError:self.answer(False)def answer(self, result):self.closed = Truetry:self.connection.close()except AttributeError:passself.resultfunc(result, self.downloadid, self.peerid, self.ip, self.port)def read_header_len(self, s):if ord(s) != len(protocol_name):return Nonereturn len(protocol_name), self.read_headerdef read_header(self, s):if s != protocol_name:return Nonereturn 8, self.read_reserveddef read_reserved(self, s):return 20, self.read_download_iddef read_download_id(self, s):if s != self.downloadid:return Nonereturn 20, self.read_peer_iddef read_peer_id(self, s):if s != self.peerid:return Noneself.answer(True)return Nonedef data_came_in(self, connection, s):while True:if self.closed:returni = self.next_len - self.buffer.tell()if i > len(s):self.buffer.write(s)returnself.buffer.write(s[:i])s = s[i:]m = self.buffer.getvalue()self.buffer.reset()self.buffer.truncate()x = self.next_func(m)if x is None:if not self.closed:self.answer(False)returnself.next_len, self.next_func = xdef connection_lost(self, connection):if not self.closed:self.closed = Trueself.resultfunc(False, self.downloadid, self.peerid, self.ip, self.port)def connection_flushed(self, connection):pass