⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 connector.py

📁 bittorrent source by python. please enjoy
💻 PY
📖 第 1 页 / 共 2 页
字号:
                self.connection.write(chr(len(protocol_name)) + protocol_name +                                      FLAGS + self.parent.download_id)                yield padlen            else:                dhstr = self._message                yield DH_BYTES - len(dhstr)                dhstr += self._message                privkey = bytetonum(urandom(20))                pub = numtobyte(pow(2, privkey, dh_prime))                self.connection.write(pub + urandom(randrange(PAD_MAX)))                pub = bytetonum(dhstr)                S = numtobyte(pow(pub, privkey, dh_prime))                dhstr = pub = privkey = None                streamid = sha('req1' + S).digest()                x = ''                while 1:                    yield 1                    x += self._message                    i = (x + self._rest).find(streamid)                    if i >= 0:                        break                    yield len(self._rest)                    x += self._message                    if len(x) >= 532:                        self.protocol_violation('incoming VC not found',                                           self.connection)                        return                yield i + 20 + 20 + 8 + 4 + 2 - len(x)                self._message = (x + self._message)[-34:]                streamid = self._message[0:20]                x = sha('req3' + S).digest()                streamid = ''.join([chr(ord(streamid[i]) ^ ord(x[i]))                                    for i in range(20)])                self.parent.select_torrent_obfuscated(self, streamid)                if self.parent.download_id is None:                    self.protocol_violation('download id unknown/rejected',                                       self.connection)                    return                self.logger = logging.getLogger(                    self.log_prefix + '.' + repr(self.parent.download_id) +                    '.peer_id_not_yet' )                SKEY = self.parent.download_id                decrypt = ARC4.new(sha('keyA' + S + SKEY).digest()).decrypt                decrypt('x'*1024)                s = decrypt(self._message[20:34])                if s[0:8] != '\x00' * 8:                    self.protocol_violation('BAD VC', self.connection)                    return                crypto_provide = toint(s[8:12])                padlen = (ord(s[12]) << 8) + ord(s[13])                if padlen > 512:                    self.protocol_violation('BAD padlen, too long', self.connection)                    return                self._decrypt = decrypt                yield padlen + 2                s = self._message                encrypt = ARC4.new(sha('keyB' + S + SKEY).digest()).encrypt                encrypt('x'*1024)                self.connection.encrypt = encrypt                if not crypto_provide & 2:                    self.protocol_violation("peer doesn't support crypto mode 2", self.connection)                    return                padlen = randrange(PAD_MAX)                s = '\x00' * 11 + '\x02\x00' + chr(padlen) + urandom(padlen)                self.connection.write(s)            S = SKEY = s = x = streamid = VC = padlen = None            yield 1 + len(protocol_name)            if self._message != chr(len(protocol_name)) + protocol_name:                self.protocol_violation('classic handshake fails', self.connection)                return        yield 8  # reserved        # dht is on last reserved byte        if ord(self._message[7]) & DHT:            self.uses_dht = True        if ord(self._message[7]) & FAST_EXTENSION:            if disable_fast_extension:                self.uses_fast_extension = False            else:                if noisy: log( "Implements FAST_EXTENSION")                self.uses_fast_extension = True                yield 20 # download id (i.e., infohash)        if self.parent.download_id is None:  # incoming connection            # modifies self.parent if successful            self.parent.select_torrent(self, self._message)            if self.parent.download_id is None:                self.protocol_violation("no download_id from parent (peer from a torrent you're not running)", self.connection)                return        elif self._message != self.parent.download_id:            self.protocol_violation("incorrect download_id from parent",                               self.connection)            return        if not self.locally_initiated:            self.connection.write(chr(len(protocol_name)) + protocol_name +                FLAGS + self.parent.download_id + self.parent.my_id)        yield 20  # peer id        if not self.id:            self.id = self._message            ns = (self.log_prefix + '.' + repr(self.parent.download_id) +                  '.' + self._message.encode('hex'))            self.logger = logging.getLogger(ns)            if self.id == self.parent.my_id:                self.protocol_violation("talking to self", self.connection)                return            for v in self.parent.connections.itervalues():                if v is not self:                    if v.id == self.id:                        self.protocol_violation(                            "duplicate connection (id collision)",                            self.connection)                        return                    if (self.parent.config['one_connection_per_ip'] and                        v.ip == self.ip):                        self.protocol_violation(                            "duplicate connection (ip collision)",                            self.connection)                        return            if self.locally_initiated:                self.connection.write(self.parent.my_id)            else:                self.parent.everinc = True        else:            if self._message != self.id:                self.protocol_violation("incorrect id")                return        self.complete = True        self.parent.connection_completed(self)        while True:            yield 4   # message length            l = toint(self._message)            if l > self.parent.config['max_message_length']:                self.protocol_violation("message length exceeds max (%s %s)" %                    (l, self.parent.config['max_message_length']),                    self.connection)                return            if l > 0:                yield l                self._got_message(self._message)    def _got_message(self, message):        t = message[0]        #if noisy: log( "GOT %s" % message_dict[t] )        if t in [BITFIELD, HAVE_ALL, HAVE_NONE] and self.got_anything:            self.close()            return        self.got_anything = True        if (t in [CHOKE, UNCHOKE, INTERESTED, NOT_INTERESTED] and                len(message) != 1):            self.close()            return        if t == CHOKE:            if noisy: log( "GOT %s" % message_dict[t] )            self.download.got_choke()        elif t == UNCHOKE:            if noisy: log( "GOT %s" % message_dict[t] )            self.download.got_unchoke()        elif t == INTERESTED:            if noisy: log( "GOT %s" % message_dict[t] )            self.upload.got_interested()        elif t == NOT_INTERESTED:            if noisy: log( "GOT %s" % message_dict[t] )            self.upload.got_not_interested()        elif t == HAVE:            i = unpack("!xi", message)[0]            if noisy: log( "GOT HAVE %d" % i )            if i >= self.parent.numpieces:                self.close()                return            self.download.got_have(i)        elif t == BITFIELD:            try:                b = Bitfield(self.parent.numpieces, message[1:])            except ValueError:                self.close()                return            self.download.got_have_bitfield(b)        elif t == REQUEST:            if len(message) != 13:                self.close()                return            i, a, b = unpack("!xiii", message)            if noisy: log( "GOT REQUEST %d %d %d" % (i, a, b) )            if i >= self.parent.numpieces:                self.protocol_violation(                     "Requested piece index %d > numpieces which is %d" %                     (i,self.parent.numpieces), self.connection )                self.close()                return            if self.download.have[i]:                self.protocol_violation(                     "Requested piece index %d which the peer already has" %                     (i,), self.connection )                self.close()                return            self.upload.got_request(i, a, b)        elif t == CANCEL:            if len(message) != 13:                self.protocol_violation(                    "Invalid cancel message length %d" % len(message),                    self.connection )                self.close()                return            i, a, b = unpack("!xiii", message)            if noisy: log( "GOT CANCEL %d %d %d" % (i, a, b) )            if i >= self.parent.numpieces:                self.protocol_violation(                     "Cancelled piece index %d > numpieces which is %d" %                     (i,self.parent.numpieces), self.connection )                self.close()                return            self.upload.got_cancel(i, a, b)        elif t == PIECE:            if len(message) <= 9:                self.close()                return            n = len(message) - 9            i, a, b = unpack("!xii%ss" % n, message)            if noisy: log( "GOT PIECE %d %d" % (i, a) )            if i >= self.parent.numpieces:                self.close()                return            self.download.got_piece(i, a, b)        elif t == PORT:            if len(message) != 3:                self.close()                return            self.dht_port = unpack('!H', message[1:3])[0]            self.parent.got_port(self)        elif t == SUGGEST_PIECE:            if not self.uses_fast_extension:                self.protocol_violation(                    "Received 'SUGGEST_PIECE' when fast extension disabled.",                    self.connection )                self.close()                return            i = unpack("!xi", message)[0]            if noisy: log( "GOT SUGGEST_PIECE %d" % i )            if i >= self.parent.numpieces:                self.protocol_violation(                    "Received 'SUGGEST_PIECE' with piece id %d > numpieces." %                    self.parent.numpieces, self.connection )                self.close()                return            self.download.got_suggest_piece(i)        elif t == HAVE_ALL:            if noisy: log( "GOT %s" % message_dict[t] )            if not self.uses_fast_extension:                self.protocol_violation(                    "Received 'HAVE_ALL' when fast extension disabled.",                    self.connection )                self.close()                return            self.download.got_have_all()        elif t == HAVE_NONE:            if noisy: log( "GOT %s" % message_dict[t] )            if not self.uses_fast_extension:                self.protocol_violation(                    "Received 'HAVE_NONE' when fast extension disabled.",                    self.connection )                self.close()                return            self.download.got_have_none()        elif t == REJECT_REQUEST:            if not self.uses_fast_extension:                self.protocol_violation(                    "Received 'REJECT_REQUEST' when fast extension disabled.",                    self.connection )                self.close()                return            if len(message) != 13:                self.protocol_violation(                    "Received 'REJECT_REQUEST' with length %d != 13." %                    len(message), self.connection )                self.close()                return            i, a, b = unpack("!xiii", message)            if noisy: log( "GOT REJECT_REQUEST %d %d" % (i,a) )            if i >= self.parent.numpieces:                self.close()                return            self.download.got_reject_request(i, a, b)        elif t == ALLOWED_FAST:            if not self.uses_fast_extension:                self.protocol_violation(                    "Received 'ALLOWED_FAST' when fast extension disabled.",                    self.connection )                self.close()                return            i = unpack("!xi", message)[0]            if noisy: log( "GOT ALLOWED_FAST %d" % i )            self.download.got_allowed_fast(i)        else:            self.close()    def _send_message(self, message):        if self.closed:            return        s = tobinary(len(message)) + message        if self._partial_message is not None:            self._outqueue.append(s)        else:            self.connection.write(s)    def data_came_in(self, conn, s):        self.received_data = True        if not self.download:            # this is really annoying.            self.sloppy_pre_connection_counter += len(s)        else:            l = self.sloppy_pre_connection_counter + len(s)            self.sloppy_pre_connection_counter = 0                    while True:            if self.closed:                return            i = self._next_len - self._buffer_len            if i > len(s):                self._buffer.append(s)                self._buffer_len += len(s)                return            m = s[:i]            if self._buffer_len > 0:                self._buffer.append(m)                m = ''.join(self._buffer)                self._buffer = []                self._buffer_len = 0            s = s[i:]            if self._decrypt is not None:                m = self._decrypt(m)            self._message = m            self._rest = s            try:                self._next_len = self._reader.next()            except StopIteration:                self.close()                return    def _optional_restart(self):                    if self.locally_initiated and not self.obfuscate_outgoing and not self.received_data:            dns = (self.connection.ip, self.connection.port)            self.parent.start_connection(dns, id=None, encrypt=True)    def connection_lost(self, conn):        assert conn is self.connection        self.closed = True        self._reader = None        del self.parent.connections[self.connection]        # ARG. Thanks Uoti        if hasattr(self.parent, 'ratelimiter'):            self.parent.ratelimiter.dequeue(self)        self._optional_restart()        self.connection = None        self.parent.replace_connection()        if self.complete:            self.parent.complete_connections.remove(self)            if self.download is not None:                self.download.disconnected()            self.parent.choker.connection_lost(self)            self.upload = None            self.download = None    def connection_flushed(self, connection):        if self.complete and self.next_upload is None and (self._partial_message is not None                                             or (self.upload and self.upload.buffer)):            if self.lan:                # bypass upload rate limiter                self.send_partial(self.parent.ratelimiter.unitsize)            else:                self.parent.ratelimiter.queue(self)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -