def __init__(self, my_node, querier, bootstrap_lookup_f, bootstrap_nodes): self.my_node = my_node self.querier = querier self.bootstrap_lookup = bootstrap_lookup_f #Copy the bootstrap list self.bootstrap_nodes = [n for n in bootstrap_nodes] self.table = RoutingTable(my_node, NODES_PER_BUCKET) self.ping_msg = message.OutgoingPingQuery(my_node.id) self.find_closest_msg = message.OutgoingFindNodeQuery( my_node.id, my_node.id) #This must be called by an external party: self.do_bootstrap() #After initializing callbacks # maintenance variables # self.last_maintenance_index = -1 self.maintenance_mode = BOOTSTRAP_MODE self.lookup_mode = False self._query_received_queue = _QueryReceivedQueue(self.table) self._found_nodes_queue = _FoundNodesQueue(self.table) self.maintenance_tasks = [ self._ping_a_staled_rnode, self._ping_a_query_received_node, self._ping_a_found_node ]
def __init__(self, my_id, target): GetPeersLookup.__init__(self, my_id, target, None) self.bootstrap_alpha = 4 self.normal_alpha = 4 self.normal_m = 1 self.slowdown_alpha = 4 self.slowdown_m = 1 self._get_peers_msg = message.OutgoingFindNodeQuery(my_id, target)
def send_query_and_get_response(self, querier_, later_delay=0): ping_msg = message.OutgoingPingQuery(tc.CLIENT_ID) msg = message.OutgoingFindNodeQuery(tc.CLIENT_ID, tc.CLIENT_ID) if later_delay: task = querier_.send_query_later(later_delay, msg, tc.EXTERNAL_NODE, self.on_response, self.on_timeout, self.on_error, tc.TIMEOUT_DELAY) # This second query is just to have two elements # in the querier_.pending[tc.EXTERNAL_ADDR] list task = querier_.send_query_later(later_delay, msg, tc.EXTERNAL_NODE, self.on_response, self.on_timeout, self.on_error, tc.TIMEOUT_DELAY) else: node_ = (querier_ == self.querier_mock) and tc.SERVER_NODE query = querier_.send_query(ping_msg, node_ or tc.EXTERNAL_NODE, self.on_response, self.on_timeout, self.on_error, timeout_delay=tc.TIMEOUT_DELAY) # querier creates TID msg_tid = '\0\0' if querier_ is self.querier_mock: # server gets query # the server creates the response pong_msg = message.OutgoingPingResponse(tc.SERVER_ID) pong_msg_data = pong_msg.encode(msg_tid) # the client gets the response # rpc_m decodes msg and calls callback pong_msg = message.IncomingMsg(pong_msg_data) querier_.on_response_received(pong_msg, tc.SERVER_ADDR) if later_delay: ok_(not self.got_response) ok_(not self.got_timeout) time.sleep(later_delay*2) time.sleep(tc.TIMEOUT_DELAY+.1) ### It crashed (timeout_task.cancelled??????) #TODO2: move the 'real' tests to integration ############################################### ### A DHT node must be running on peer_addr ### ############################################### ok_(self.got_response) ok_(not self.got_timeout)
def setup(self): self.queries = [ m.OutgoingPingQuery(tc.CLIENT_ID), m.OutgoingFindNodeQuery(tc.CLIENT_ID, tc.TARGET_ID), m.OutgoingGetPeersQuery(tc.CLIENT_ID, tc.INFO_HASH), m.OutgoingAnnouncePeerQuery(tc.CLIENT_ID, tc.INFO_HASH, tc.BT_PORT, tc.TOKEN), ] self.responses = [ m.OutgoingPingResponse(tc.SERVER_ID), m.OutgoingFindNodeResponse(tc.SERVER_ID, tc.NODES), m.OutgoingGetPeersResponse(tc.SERVER_ID, tc.TOKEN, tc.NODES, tc.PEERS), m.OutgoingAnnouncePeerResponse(tc.SERVER_ID), ]
def test_find_node(self): #client outgoing_query = m.OutgoingFindNodeQuery(tc.CLIENT_ID, tc.NODE_ID) data = outgoing_query.encode(tc.TID) #server incoming_query = m.IncomingMsg(data, tc.CLIENT_ADDR) assert incoming_query.type is m.QUERY outgoing_response = m.OutgoingFindNodeResponse(tc.SERVER_ID, tc.NODES) data = outgoing_response.encode(incoming_query.tid) #client incoming_response = m.IncomingMsg(data, tc.SERVER_ADDR) eq_(incoming_response.type, m.RESPONSE) #incoming_response.sanitize_response(outgoing_query.query) for n1, n2 in zip(tc.NODES, incoming_response.all_nodes): eq_(n1, n2)
def test_return_response_for_find_node(self): # client side query_msg = message.OutgoingFindNodeQuery(tc.CLIENT_ID, tc.TARGET_ID) # querier encodes query_data = query_msg.encode(tc.TID) # server side # rpc_manager.datagram_received() decodes query_msg = message.IncomingMsg(query_data) # rpc calls responder assert not self.notification_callback_done response_msg = self.responder.on_query_received( query_msg, tc.CLIENT_ADDR) response_data = response_msg.encode(query_msg.tid) assert self.notification_callback_done expected_msg = message.OutgoingFindNodeResponse(tc.SERVER_ID, tc.NODES) expected_data = expected_msg.encode(tc.TID) eq_(response_data, expected_data)
def _send_maintenance_ping(self, node_): m_bucket, r_bucket = self.table.buckets[0] if m_bucket.there_is_room() and r_bucket.there_is_room(): target = identifier.RandomId() msg = message.OutgoingFindNodeQuery(self.my_node.id, target) m_bucket, r_bucket = self.table.buckets[0] print 'FIND_NODE(%d:%d:%d)' % (0, len(m_bucket), len(r_bucket)), else: print 'PING', msg = self.ping_msg if node_.id: m_bucket, r_bucket = self.table.buckets[0] print 'to %r - %d:%d:%d --' % (node_.addr, node_.log_distance(self.my_node), len(m_bucket), len(r_bucket)) else: print 'to UNKNOWN id' self.querier.send_query(msg, node_)
def test_find_node_with_error(self): # Client creates a query fn_msg = message.OutgoingFindNodeQuery(tc.CLIENT_ID, tc.TARGET_ID) # the destination's ID is unknown q = Query(fn_msg, node.Node(tc.SERVER_ADDR)) # Querier.register_query sets a TID and timeout_task q.tid = tc.TID q.timeout_task = minitwisted.Task(TIMEOUT_DELAY, None) q.query_ts = time.time() # The query is sent # The server creates a response fn_r_out = message.OutgoingErrorMsg(message.GENERIC_E) bencoded_fn_r = fn_r_out.encode(tc.TID) time.sleep(1) # The client receives the bencoded message fn_r_in = message.IncomingMsg(bencoded_fn_r, tc.SERVER_ADDR) q.on_error_received(fn_r_in) assert 1 < q.rtt < 1.1 assert q.lookup_obj is None
def __init__(self, my_node, querier, bootstrap_nodes): self.my_node = my_node self.querier = querier #Copy the bootstrap list self.bootstrap_nodes = [n for n in bootstrap_nodes] self.main = RoutingTable(my_node, NODES_PER_BUCKET) self.replacement = RoutingTable(my_node, NODES_PER_BUCKET) self.ping_msg = message.OutgoingPingQuery(my_node.id) self.find_node_msg = message.OutgoingFindNodeQuery( my_node.id, my_node.id) self.mode = BOOTSTRAP_MODE self.num_concurrent_refresh_msgs = 0 #This must be called by an external party: self.do_bootstrap() #After initializing callbacks # Add myself to the routing table rnode = self.main.add(my_node) self._reset_refresh_task(rnode)
def test_msg_exhanges(self): self._exchange_msgs(m.OutgoingPingQuery(tc.CLIENT_ID), m.OutgoingPingResponse(tc.SERVER_ID)) self._exchange_msgs( m.OutgoingFindNodeQuery(tc.CLIENT_ID, tc.TARGET_ID), m.OutgoingFindNodeResponse(tc.SERVER_ID, tc.NODES)) # Test different combinations of token, nodes and peers self._exchange_msgs( m.OutgoingGetPeersQuery(tc.CLIENT_ID, tc.INFO_HASH), m.OutgoingGetPeersResponse(tc.SERVER_ID, tc.TOKEN, tc.NODES, tc.PEERS)) self._exchange_msgs( m.OutgoingGetPeersQuery(tc.CLIENT_ID, tc.INFO_HASH), m.OutgoingGetPeersResponse(tc.SERVER_ID, tc.TOKEN, tc.NODES)) self._exchange_msgs( m.OutgoingGetPeersQuery(tc.CLIENT_ID, tc.INFO_HASH), m.OutgoingGetPeersResponse(tc.SERVER_ID, tc.TOKEN, peers=tc.PEERS)) assert_raises(AssertionError, m.OutgoingGetPeersResponse, tc.SERVER_ID, tc.TOKEN) self._exchange_msgs( m.OutgoingGetPeersQuery(tc.CLIENT_ID, tc.INFO_HASH), m.OutgoingGetPeersResponse(tc.SERVER_ID, peers=tc.PEERS)) self._exchange_msgs( m.OutgoingGetPeersQuery(tc.CLIENT_ID, tc.INFO_HASH), m.OutgoingGetPeersResponse(tc.SERVER_ID, nodes=tc.NODES)) self._exchange_msgs( m.OutgoingGetPeersQuery(tc.CLIENT_ID, tc.INFO_HASH), m.OutgoingGetPeersResponse(tc.SERVER_ID, nodes=tc.NODES, peers=tc.PEERS)) assert_raises(AssertionError, m.OutgoingGetPeersResponse, tc.SERVER_ID) self._exchange_msgs( m.OutgoingAnnouncePeerQuery(tc.CLIENT_ID, tc.INFO_HASH, tc.BT_PORT, tc.TOKEN), m.OutgoingAnnouncePeerResponse(tc.SERVER_ID))
def _send_maintenance_ping(self, node_): if node_.id: log_distance = self.table.find_next_bucket_with_room_index(node_) else: # Bootstrap nodes don't have id log_distance = 0 if 0: #log_distance: target = self.my_node.id.generate_close_id(log_distance) msg = message.OutgoingFindNodeQuery(self.my_node.id, target) m_bucket, r_bucket = self.table.buckets[log_distance] print '[%f] FIND_NODE(%d:%d:%d)' % (time.time(), log_distance, len(m_bucket), len(r_bucket)), else: print '[%f] PING' % (time.time()), msg = self.ping_msg if node_.id: m_bucket, r_bucket = self.table.get_buckets(node_) print 'to (%r) %d:%d:%d --' % (node_.addr, node_.log_distance(self.my_node), len(m_bucket), len(r_bucket)) else: print 'to UNKNOWN id' self.querier.send_query(msg, node_)
b_err = m.OutgoingErrorMsg(error_code).encode(tc.TID) logger.info( "TEST LOGGING ** IGNORE EXPECTED INFO ** Unknown error: %r", error_code) _ = m.IncomingMsg(b_err, tc.CLIENT_ADDR) def test_nodes2(self): response = m.OutgoingGetPeersResponse(tc.CLIENT_ID, peers=tc.PEERS) response._dict[m.RESPONSE][m.NODES2] = mt.compact_nodes2(tc.NODES) bencoded = response.encode(tc.TID) m.IncomingMsg(bencoded, tc.CLIENT_ADDR) b_ping_q = m.OutgoingPingQuery(tc.CLIENT_ID).encode(tc.TID) b_fn_q = m.OutgoingFindNodeQuery(tc.CLIENT_ID, tc.NODE_ID).encode(tc.TID) b_gp_q = m.OutgoingGetPeersQuery(tc.CLIENT_ID, tc.INFO_HASH).encode(tc.TID) b_ap_q = m.OutgoingAnnouncePeerQuery(tc.CLIENT_ID, tc.INFO_HASH, tc.BT_PORT, tc.TOKEN).encode(tc.TID) class TestSanitizeQueryError: def setup(self): self.ping_d = m.IncomingMsg(b_ping_q, tc.CLIENT_ADDR)._msg_dict self.fn_d = m.IncomingMsg(b_fn_q, tc.CLIENT_ADDR)._msg_dict self.gp_d = m.IncomingMsg(b_gp_q, tc.CLIENT_ADDR)._msg_dict self.ap_d = m.IncomingMsg(b_ap_q, tc.CLIENT_ADDR)._msg_dict def test_weird_msg(self): self.ping_d[m.ARGS] = [] assert_raises(m.MsgError, m.IncomingMsg, bencode.encode(self.ping_d),
def __init__(self, my_id, querier, max_parallel_queries, target, nodes): GetPeersLookup.__init__(self, my_id, querier, max_parallel_queries, target, None, nodes) self._get_peers_msg = message.OutgoingFindNodeQuery(my_id, target)