instrumentation: add next-share/
[cs-p2p-next.git] / instrumentation / next-share / BaseLib / Core / BitTornado / BT1 / NatCheck.py
1 # Written by Bram Cohen
2 # see LICENSE.txt for license information
3
4 from cStringIO import StringIO
5 from socket import error as socketerror
6 try:
7     True
8 except:
9     True = 1
10     False = 0
11
12 protocol_name = 'BitTorrent protocol'
13
14 # header, reserved, download id, my id, [length, message]
15
16 class NatCheck:
17     def __init__(self, resultfunc, downloadid, peerid, ip, port, rawserver):
18         self.resultfunc = resultfunc
19         self.downloadid = downloadid
20         self.peerid = peerid
21         self.ip = ip
22         self.port = port
23         self.closed = False
24         self.buffer = StringIO()
25         self.next_len = 1
26         self.next_func = self.read_header_len
27         try:
28             self.connection = rawserver.start_connection((ip, port), self)
29             self.connection.write(chr(len(protocol_name)) + protocol_name +
30                 (chr(0) * 8) + downloadid)
31         except socketerror:
32             self.answer(False)
33         except IOError:
34             self.answer(False)
35
36     def answer(self, result):
37         self.closed = True
38         try:
39             self.connection.close()
40         except AttributeError:
41             pass
42         self.resultfunc(result, self.downloadid, self.peerid, self.ip, self.port)
43
44     def read_header_len(self, s):
45         if ord(s) != len(protocol_name):
46             return None
47         return len(protocol_name), self.read_header
48
49     def read_header(self, s):
50         if s != protocol_name:
51             return None
52         return 8, self.read_reserved
53
54     def read_reserved(self, s):
55         return 20, self.read_download_id
56
57     def read_download_id(self, s):
58         if s != self.downloadid:
59             return None
60         return 20, self.read_peer_id
61
62     def read_peer_id(self, s):
63         if s != self.peerid:
64             return None
65         self.answer(True)
66         return None
67
68     def data_came_in(self, connection, s):
69         while 1:
70             if self.closed:
71                 return
72             i = self.next_len - self.buffer.tell()
73             if i > len(s):
74                 self.buffer.write(s)
75                 return
76             self.buffer.write(s[:i])
77             s = s[i:]
78             m = self.buffer.getvalue()
79             self.buffer.reset()
80             self.buffer.truncate()
81             x = self.next_func(m)
82             if x is None:
83                 if not self.closed:
84                     self.answer(False)
85                 return
86             self.next_len, self.next_func = x
87
88     def connection_lost(self, connection):
89         if not self.closed:
90             self.closed = True
91             self.resultfunc(False, self.downloadid, self.peerid, self.ip, self.port)
92
93     def connection_flushed(self, connection):
94         pass