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 binascii import b2a_hex
6
from socket import error as socketerror
7
from urllib import quote
8
from traceback import print_exc
9
import Connecter
10
try:
11
    True
12
except:
13
    True = 1
14
    False = 0
15
 
16
DEBUG = False
17
 
18
 
19
protocol_name = 'BitTorrent protocol'
20
option_pattern = chr(0)*8
21
 
22
def toint(s):
23
    return long(b2a_hex(s), 16)
24
 
25
def tobinary(i):
26
    return (chr(i >> 24) + chr((i >> 16) & 0xFF) + 
27
        chr((i >> 8) & 0xFF) + chr(i & 0xFF))
28
 
29
hexchars = '0123456789ABCDEF'
30
hexmap = []
31
for i in xrange(256):
32
    hexmap.append(hexchars[(i&0xF0)/16]+hexchars[i&0x0F])
33
 
34
def tohex(s):
35
    r = []
36
    for c in s:
37
        r.append(hexmap[ord(c)])
38
    return ''.join(r)
39
 
40
def make_readable(s):
41
    if not s:
42
        return ''
43
    if quote(s).find('%') >= 0:
44
        return tohex(s)
45
    return '"'+s+'"'
46
 
47
def toint(s):
48
    return long(b2a_hex(s), 16)
49
 
50
# header, reserved, download id, my id, [length, message]
51
 
52
streamno = 0
53
 
54
 
55
class StreamCheck:
56
    def __init__(self):
57
        global streamno
58
        self.no = streamno
59
        streamno += 1
60
        self.buffer = StringIO()
61
        self.next_len, self.next_func = 1, self.read_header_len
62
 
63
    def read_header_len(self, s):
64
        if ord(s) != len(protocol_name):
65
            print self.no, 'BAD HEADER LENGTH'
66
        return len(protocol_name), self.read_header
67
 
68
    def read_header(self, s):
69
        if s != protocol_name:
70
            print self.no, 'BAD HEADER'
71
        return 8, self.read_reserved
72
 
73
    def read_reserved(self, s):
74
        return 20, self.read_download_id
75
 
76
    def read_download_id(self, s):
77
        if DEBUG:
78
            print self.no, 'download ID ' + tohex(s)
79
        return 20, self.read_peer_id
80
 
81
    def read_peer_id(self, s):
82
        if DEBUG:
83
            print self.no, 'peer ID' + make_readable(s)
84
        return 4, self.read_len
85
 
86
    def read_len(self, s):
87
        l = toint(s)
88
        if l > 2 ** 23:
89
            print self.no, 'BAD LENGTH: '+str(l)+' ('+s+')'
90
        return l, self.read_message
91
 
92
    def read_message(self, s):
93
        if not s:
94
            return 4, self.read_len
95
        m = s[0]
96
        if ord(m) > 8:
97
            print self.no, 'BAD MESSAGE: '+str(ord(m))
98
        if m == Connecter.REQUEST:
99
            if len(s) != 13:
100
                print self.no, 'BAD REQUEST SIZE: '+str(len(s))
101
                return 4, self.read_len
102
            index = toint(s[1:5])
103
            begin = toint(s[5:9])
104
            length = toint(s[9:])
105
            print self.no, 'Request: '+str(index)+': '+str(begin)+'-'+str(begin)+'+'+str(length)
106
        elif m == Connecter.CANCEL:
107
            if len(s) != 13:
108
                print self.no, 'BAD CANCEL SIZE: '+str(len(s))
109
                return 4, self.read_len
110
            index = toint(s[1:5])
111
            begin = toint(s[5:9])
112
            length = toint(s[9:])
113
            print self.no, 'Cancel: '+str(index)+': '+str(begin)+'-'+str(begin)+'+'+str(length)
114
        elif m == Connecter.PIECE:
115
            index = toint(s[1:5])
116
            begin = toint(s[5:9])
117
            length = len(s)-9
118
            print self.no, 'Piece: '+str(index)+': '+str(begin)+'-'+str(begin)+'+'+str(length)
119
        else:
120
            print self.no, 'Message '+str(ord(m))+' (length '+str(len(s))+')'
121
        return 4, self.read_len
122
 
123
    def write(self, s):
124
        while True:
125
            i = self.next_len - self.buffer.tell()
126
            if i > len(s):
127
                self.buffer.write(s)
128
                return
129
            self.buffer.write(s[:i])
130
            s = s[i:]
131
            m = self.buffer.getvalue()
132
            self.buffer.reset()
133
            self.buffer.truncate()
134
            x = self.next_func(m)
135
            self.next_len, self.next_func = x