1 # Written by Bram Cohen
2 # see LICENSE.txt for license information
4 from cStringIO import StringIO
5 from socket import error as socketerror
12 protocol_name = 'BitTorrent protocol'
14 # header, reserved, download id, my id, [length, message]
17 def __init__(self, resultfunc, downloadid, peerid, ip, port, rawserver):
18 self.resultfunc = resultfunc
19 self.downloadid = downloadid
24 self.buffer = StringIO()
26 self.next_func = self.read_header_len
28 self.connection = rawserver.start_connection((ip, port), self)
29 self.connection.write(chr(len(protocol_name)) + protocol_name +
30 (chr(0) * 8) + downloadid)
36 def answer(self, result):
39 self.connection.close()
40 except AttributeError:
42 self.resultfunc(result, self.downloadid, self.peerid, self.ip, self.port)
44 def read_header_len(self, s):
45 if ord(s) != len(protocol_name):
47 return len(protocol_name), self.read_header
49 def read_header(self, s):
50 if s != protocol_name:
52 return 8, self.read_reserved
54 def read_reserved(self, s):
55 return 20, self.read_download_id
57 def read_download_id(self, s):
58 if s != self.downloadid:
60 return 20, self.read_peer_id
62 def read_peer_id(self, s):
68 def data_came_in(self, connection, s):
72 i = self.next_len - self.buffer.tell()
76 self.buffer.write(s[:i])
78 m = self.buffer.getvalue()
80 self.buffer.truncate()
86 self.next_len, self.next_func = x
88 def connection_lost(self, connection):
91 self.resultfunc(False, self.downloadid, self.peerid, self.ip, self.port)
93 def connection_flushed(self, connection):