Coverage for dht_crawler/torrent_dht.py : 71%

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. '''
''' 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. ''' list_node = None for nodes in info_pool[id_node]: if nodes[0] == host and nodes[1] == port: list_node = nodes break return list_node
''' decode with bencoding. When exception is thrown, return None. ''' except BTFailure: return None
''' sends bencoded krpc to node ip address and node port ''' pass
''' decode nodes from response message ''' except TypeError: length = 0
return nodes # nodes in raw state except TypeError: return nodes
else: if not has_node(nid, ip_addr, port, info_pool): 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. When unique specified get only ip address as key ''' except (IndexError, TypeError): continue continue info_pool[str(ip_addr)] = [datetime.datetime.now() .strftime('%d.%m.%Y %H:%M:%S:%f'), (token, ip_addr, port)] else: .strftime('%d.%m.%Y %H:%M:%S:%f'), (token, 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) # self.query_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # Set verboisty
# create all necessary for transmission over network # Infohash, target_pool, target torrent and wether # output should be unique or not random_infohash(), arguments.unique] # list of nodes # 200 lifo # Append all bootstrap nodes
''' change class arguments ''' # change queue type self.nodes = queue.Queue(self.max_node_qsize) else:
''' change bootstrap nodes when parsed magnet-link or .torrent file ''' if queue_type: self.nodes = queue.Queue(self.max_node_qsize) else: self.nodes = queue.LifoQueue(self.max_node_qsize)
for node_list in nodes: for node in node_list: compact_node = node.decode("utf-8") port = re.search(r":\d+", compact_node) try: port = port.group(0)[1::] except AttributeError: port = 80 compact_node = re.search(r".*:", compact_node) compact_node = compact_node.group(0)[6:-1] for bootstrap in self.bootstrap_nodes: self.nodes.put((infohash, bootstrap[0], bootstrap[1]))
''' change infohash in nodes queue ''' self.infohash_list[2] = infohash
# This part is about query messages. Supports all 4 Kademlia messages sends # over UDP with bencoding as torrent BEP05 refers.
# Query messages. ''' send query find_node to node with our infohash ''' message = { "t": "fn", "y": "q", "q": "find_node", "a": { "id": self.infohash_list[2], "target": node[0] } } send_krpc(message, node, sock)
''' send query ping to node ''' infohash = get_neighbor(infohash, self.infohash_list[0]) if infohash \ else self.infohash_list[0] # By default transaction ID should be at least 2 bytes long message = { "t": "pg", "y": "q", "q": "ping", "a": { "id": infohash } } send_krpc(message, node, sock)
''' send simple get_peers with our infohash to node ''' else self.infohash_list[0] "t": "gp", "y": "q", "q": "get_peers", "a": { "id": binascii.unhexlify(infohash), "info_hash": binascii.unhexlify(self.infohash_list[2]) } }
''' send announce_peer query ''' # get port from node token = node[0] message = { "t": "ap", "y": "q", "q": "announce_peer", "a": { "id": binascii.unhexlify(infohash), "implied_port": 1, # could be 0 or 1 "info_hash": binascii.unhexlify(self.infohash_list[2]), "port": port, "token": binascii.unhexlify(token) } } send_krpc(message, node, sock)
# 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 return retval
# decode peers with target token, their value and fill # tmp pool by given unique or non unique value within # self.infohash_list token, self.infohash_list[3]) addr[0], addr[1]), time.time()] |