Subversion Repositories svnkaklik

Rev

Details | Last modification | View Log

Rev Author Line No. Line
36 kaklik 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
from traceback import print_exc
7
try:
8
    True
9
except:
10
    True = 1
11
    False = 0
12
 
13
protocol_name = 'BitTorrent protocol'
14
 
15
# header, reserved, download id, my id, [length, message]
16
 
17
class NatCheck:
18
    def __init__(self, resultfunc, downloadid, peerid, ip, port, rawserver):
19
        self.resultfunc = resultfunc
20
        self.downloadid = downloadid
21
        self.peerid = peerid
22
        self.ip = ip
23
        self.port = port
24
        self.closed = False
25
        self.buffer = StringIO()
26
        self.next_len = 1
27
        self.next_func = self.read_header_len
28
        try:
29
            self.connection = rawserver.start_connection((ip, port), self)
30
            self.connection.write(chr(len(protocol_name)) + protocol_name +
31
                (chr(0) * 8) + downloadid)
32
        except socketerror:
33
            self.answer(False)
34
        except IOError:
35
            self.answer(False)
36
 
37
    def answer(self, result):
38
        self.closed = True
39
        try:
40
            self.connection.close()
41
        except AttributeError:
42
            pass
43
        self.resultfunc(result, self.downloadid, self.peerid, self.ip, self.port)
44
 
45
    def read_header_len(self, s):
46
        if ord(s) != len(protocol_name):
47
            return None
48
        return len(protocol_name), self.read_header
49
 
50
    def read_header(self, s):
51
        if s != protocol_name:
52
            return None
53
        return 8, self.read_reserved
54
 
55
    def read_reserved(self, s):
56
        return 20, self.read_download_id
57
 
58
    def read_download_id(self, s):
59
        if s != self.downloadid:
60
            return None
61
        return 20, self.read_peer_id
62
 
63
    def read_peer_id(self, s):
64
        if s != self.peerid:
65
            return None
66
        self.answer(True)
67
        return None
68
 
69
    def data_came_in(self, connection, s):
70
        while True:
71
            if self.closed:
72
                return
73
            i = self.next_len - self.buffer.tell()
74
            if i > len(s):
75
                self.buffer.write(s)
76
                return
77
            self.buffer.write(s[:i])
78
            s = s[i:]
79
            m = self.buffer.getvalue()
80
            self.buffer.reset()
81
            self.buffer.truncate()
82
            x = self.next_func(m)
83
            if x is None:
84
                if not self.closed:
85
                    self.answer(False)
86
                return
87
            self.next_len, self.next_func = x
88
 
89
    def connection_lost(self, connection):
90
        if not self.closed:
91
            self.closed = True
92
            self.resultfunc(False, self.downloadid, self.peerid, self.ip, self.port)
93
 
94
    def connection_flushed(self, connection):
95
        pass