void timeout() override
	{
		if (flags & flag_done) return;
		flags |= flag_done;
		bdecode_node e;
		msg m(e, target_ep());
		static_cast<direct_traversal*>(algorithm())->invoke_cb(m);
	}
예제 #2
0
void traversal_observer::reply(msg const& m)
{
	bdecode_node r = m.message.dict_find_dict("r");
	if (!r)
	{
#ifndef TORRENT_DISABLE_LOGGING
		if (get_observer() != nullptr)
		{
			get_observer()->log(dht_logger::traversal
				, "[%p] missing response dict"
				, static_cast<void*>(algorithm()));
		}
#endif
		return;
	}

#ifndef TORRENT_DISABLE_LOGGING
	dht_observer* logger = get_observer();
	if (logger != nullptr && logger->should_log(dht_logger::traversal))
	{
		bdecode_node nid = r.dict_find_string("id");
		char hex_id[41];
		aux::to_hex({nid.string_ptr(), 20}, hex_id);
		logger->log(dht_logger::traversal
			, "[%p] RESPONSE id: %s invoke-count: %d addr: %s type: %s"
			, static_cast<void*>(algorithm()), hex_id, algorithm()->invoke_count()
			, print_endpoint(target_ep()).c_str(), algorithm()->name());
	}
#endif

	// look for nodes
#if TORRENT_USE_IPV6
	udp protocol = algorithm()->get_node().protocol();
#endif
	char const* nodes_key = algorithm()->get_node().protocol_nodes_key();
	bdecode_node n = r.dict_find_string(nodes_key);
	if (n)
	{
		char const* nodes = n.string_ptr();
		char const* end = nodes + n.string_length();

		while (end - nodes >= 20 + detail::address_size(protocol) + 2)
		{
			node_id id;
			std::copy(nodes, nodes + 20, id.begin());
			nodes += 20;
			udp::endpoint ep;
#if TORRENT_USE_IPV6
			if (protocol == udp::v6())
				ep = detail::read_v6_endpoint<udp::endpoint>(nodes);
			else
#endif
				ep = detail::read_v4_endpoint<udp::endpoint>(nodes);
			algorithm()->traverse(id, ep);
		}
	}

	bdecode_node id = r.dict_find_string("id");
	if (!id || id.string_length() != 20)
	{
#ifndef TORRENT_DISABLE_LOGGING
		if (get_observer() != nullptr)
		{
			get_observer()->log(dht_logger::traversal, "[%p] invalid id in response"
				, static_cast<void*>(algorithm()));
		}
#endif
		return;
	}

	// in case we didn't know the id of this peer when we sent the message to
	// it. For instance if it's a bootstrap node.
	set_id(node_id(id.string_ptr()));
}