Coverage for torrent_dht.py : 82%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
#!/usr/bin/env python3 Create by Martin Vasko 3BIT, Brno, Faculty of Information Technology.
This should be used as part of library, where you can create, bind socket and send all torrent DHT messages over UDP. BOOTSTRAP_NODES are well known nodes from which should begin torrent peer detection. '''
# TODO no IPv6 support ''' entropy to generate infohash '''
''' generates random 20 bytes infohash ''' # infohash should be 20 bytes long
''' mixture of infohashes '''
''' when node is in infopool clear duplicities. '''
''' decode with bencoding. When exception is thrown, return None. ''' # try: # except: # return None
''' decode nodes from response message ''' except TypeError: length = 0
return nodes # nodes in raw state except TypeError: return nodes
else: info_pool[nid].append((ip_addr, port)) else: # duplicates pass
''' decodes peers from get_peers response. They have only ip address and port within message ''' except IndexError: continue continue info_pool[str(ip_addr)] = [datetime.datetime.now() .strftime('%d.%m.%Y %H:%M:%S:%f'), (infohash, ip_addr, port)] else: .strftime('%d.%m.%Y %H:%M:%S:%f'), (infohash, ip_addr, port)]
''' get my global ip_address, by connecting to google and get sockname '''
''' bootstrap arguments for DHT class ''' ("router.bittorrent.com", 6881), ("dht.transmissionbt.com", 6881), ("router.utorrent.com", 6881) ] else: self.bootstrap_nodes = bootstrap_nodes
''' clear ''' self.bootstrap_nodes = []
''' ''' return self.bootstrap_nodes
''' Class which perform query and response of dht messages. '''
socket.SOCK_DGRAM, socket.IPPROTO_UDP) # Set verboisty
# create all necessary for transmission over network # list of nodes # Append all bootstrap nodes
''' change class arguments ''' # change queue type self.nodes = queue.Queue(self.max_node_qsize)
''' change bootstrap nodes when parsed magnet-link or .torrent file ''' self.nodes = queue.LifoQueue(self.max_node_qsize) else:
''' change infohash in nodes queue ''' self.target = infohash
# This part is about query messages. Supports all 4 Kademlia messages sends # over UDP with bencoding as torrent BEP05 refers.
''' sends bencoded krpc to node ip address and node port ''' except (IndexError, TypeError): pass
# Query messages. ''' send query find_node to node with our infohash ''' message = { "t": "fn", "y": "q", "q": "find_node", "a": { "id": infohash, "target": node[0] } } self.send_krpc(message, node)
''' send query ping to node ''' infohash = get_neighbor(infohash, self.infohash) if infohash \ else self.infohash # By default transaction ID should be at least 2 bytes long message = { "t": "pg", "y": "q", "q": "ping", "a": { "id": infohash } } self.send_krpc(message, node)
''' send simple get_peers with our infohash to node ''' else self.infohash "t": "gp", "y": "q", "q": "get_peers", "a": { "id": binascii.unhexlify(infohash), "info_hash": binascii.unhexlify(self.target) } }
''' send announce_peer query ''' # get port from node port = node[2] peer_id = get_neighbor(peer_id, self.infohash) if peer_id \ else self.infohash message = { "t": "ap", "y": "q", "q": "announce_peer", "a": { "id": peer_id, "implied_port": 1, # could be 0 or 1 "info_hash": infohash, "port": port, "token": token } } self.send_krpc(message, node)
# Response message decode # Decode all types of messages, recieved and querry ''' decodes response message. When nodes decode nodes when peers decode peers and return them as result. ''' # response is detected # TODO not unique IP now |