示例#1
0
time_duration rpc_manager::tick()
{
	INVARIANT_CHECK;

	static const int short_timeout = 1;
	static const int timeout = 15;

	// look for observers that have timed out

	if (m_transactions.empty()) return seconds(short_timeout);

	std::vector<observer_ptr> timeouts;
	std::vector<observer_ptr> short_timeouts;

	time_duration ret = seconds(short_timeout);
	time_point now = aux::time_now();

	for (transactions_t::iterator i = m_transactions.begin();
		i != m_transactions.end();)
	{
		observer_ptr o = i->second;

		time_duration diff = now - o->sent();
		if (diff >= seconds(timeout))
		{
#ifndef TORRENT_DISABLE_LOGGING
			m_log->log(dht_logger::rpc_manager, "[%p] timing out transaction id: %d from: %s"
				, static_cast<void*>(o->algorithm()), o->transaction_id()
				, print_endpoint(o->target_ep()).c_str());
#endif
			m_transactions.erase(i++);
			timeouts.push_back(o);
			continue;
		}

		// don't call short_timeout() again if we've
		// already called it once
		if (diff >= seconds(short_timeout) && !o->has_short_timeout())
		{
#ifndef TORRENT_DISABLE_LOGGING
			m_log->log(dht_logger::rpc_manager, "[%p] short-timing out transaction id: %d from: %s"
				, static_cast<void*>(o->algorithm()), o->transaction_id()
				, print_endpoint(o->target_ep()).c_str());
#endif
			++i;

			short_timeouts.push_back(o);
			continue;
		}

		ret = std::min(seconds(timeout) - diff, ret);
		++i;
	}

	std::for_each(timeouts.begin(), timeouts.end(), std::bind(&observer::timeout, _1));
	std::for_each(short_timeouts.begin(), short_timeouts.end(), std::bind(&observer::short_timeout, _1));

	return (std::max)(ret, duration_cast<time_duration>(milliseconds(200)));
}
示例#2
0
void find_data::done()
{
	m_done = true;

#ifndef TORRENT_DISABLE_LOGGING
	auto logger = get_node().observer();
	if (logger != nullptr)
	{
		logger->log(dht_logger::traversal, "[%u] %s DONE"
			, id(), name());
	}
#endif

	std::vector<std::pair<node_entry, std::string>> results;
	int num_results = m_node.m_table.bucket_size();
	for (std::vector<observer_ptr>::iterator i = m_results.begin()
		, end(m_results.end()); i != end && num_results > 0; ++i)
	{
		observer_ptr const& o = *i;
		if ((o->flags & observer::flag_alive) == 0)
		{
#ifndef TORRENT_DISABLE_LOGGING
			if (logger != nullptr && logger->should_log(dht_logger::traversal))
			{
				logger->log(dht_logger::traversal, "[%u] not alive: %s"
					, id(), print_endpoint(o->target_ep()).c_str());
			}
#endif
			continue;
		}
		auto j = m_write_tokens.find(o->id());
		if (j == m_write_tokens.end())
		{
#ifndef TORRENT_DISABLE_LOGGING
			if (logger != nullptr && logger->should_log(dht_logger::traversal))
			{
				logger->log(dht_logger::traversal, "[%u] no write token: %s"
					, id(), print_endpoint(o->target_ep()).c_str());
			}
#endif
			continue;
		}
		results.push_back(std::make_pair(node_entry(o->id(), o->target_ep()), j->second));
#ifndef TORRENT_DISABLE_LOGGING
		if (logger != nullptr && logger->should_log(dht_logger::traversal))
		{
			logger->log(dht_logger::traversal, "[%u] %s"
				, id(), print_endpoint(o->target_ep()).c_str());
		}
#endif
		--num_results;
	}

	if (m_nodes_callback) m_nodes_callback(results);

	traversal_algorithm::done();
}
char *print_connection(connection_t *connection) {
    char *result = NULL;
    char *connection_info = NULL;
    char *request_endpoint_info = NULL;
    char *response_endpoint_info = NULL;
    int success;

    success = asprintf(
            &connection_info,
            "%s\n | %-39s |\n%s\n | %-39s |\n%s\n | %-18s | %-18s |\n%s\n | %-18s | %-18s |\n%s\n",
            get_hdr_line(0),
            "Connection by Call-ID",
            get_line(0),
            connection->call_id,
            get_hdr_line(1),
            "Request IP",
            "Response IP",
            get_line(1),
            connection->request_endpoint != NULL ? *(connection->request_endpoint_ip) : "none",
            connection->response_endpoint != NULL ? *(connection->response_endpoint_ip) : "none",
            get_line(0)
    );

    if (success == -1) {
        ERR("asprintf failed to allocate memory\n");
        return NULL;
    }

    request_endpoint_info = print_endpoint(connection->request_endpoint, "Request endpoint");
    response_endpoint_info = print_endpoint(connection->response_endpoint, "Response endpoint");

    success = asprintf(
            &result,
            "%s\n%s%s\n\n\n",
            connection_info,
            request_endpoint_info,
            response_endpoint_info
    );

    if (connection_info != NULL)
        free(connection_info);

    if (request_endpoint_info != NULL)
        free(request_endpoint_info);

    if (response_endpoint_info != NULL)
        free(response_endpoint_info);

    if (success == -1) {
        ERR("asprintf failed to allocate memory\n");
        return NULL;
    }

    return result;
}
示例#4
0
文件: debug.c 项目: mwilbur/minix
PRIVATE void
print_sigmgr(struct proc *pp)
{
	endpoint_t sig_mgr, bak_sig_mgr;
	sig_mgr = priv(pp)->s_sig_mgr;
	bak_sig_mgr = priv(pp)->s_bak_sig_mgr;
	printf("sigmgr ");
	print_endpoint(sig_mgr);
	if(bak_sig_mgr != NONE) {
		printf(" / ");
		print_endpoint(bak_sig_mgr);
	}
}
static void
print_sigmgr(struct proc *pp)
{
	endpoint_t sig_mgr, bak_sig_mgr;
	sig_mgr = priv(pp) ? priv(pp)->s_sig_mgr : NONE;
	bak_sig_mgr = priv(pp) ? priv(pp)->s_bak_sig_mgr : NONE;
	if(sig_mgr == NONE) { printf("no sigmgr"); return; }
	printf("sigmgr ");
	print_endpoint(sig_mgr);
	if(bak_sig_mgr != NONE) {
		printf(" / ");
		print_endpoint(bak_sig_mgr);
	}
}
示例#6
0
文件: alert.cpp 项目: pedia/raidget
	std::string listen_failed_alert::message() const
	{
		char ret[200];
		snprintf(ret, sizeof(ret), "listening on %s failed: %s"
			, print_endpoint(endpoint).c_str(), error.message().c_str());
		return ret;
	}
void print_proc(struct proc *pp)
{
	endpoint_t dep;

	printf("%d: %s %d prio %d time %d/%d cycles 0x%x%08x cpu %2d "
			"pdbr 0x%lx rts %s misc %s sched %s ",
		proc_nr(pp), pp->p_name, pp->p_endpoint, 
		pp->p_priority, pp->p_user_time,
		pp->p_sys_time, ex64hi(pp->p_cycles),
		ex64lo(pp->p_cycles), pp->p_cpu,
#if defined(__i386__)
		pp->p_seg.p_cr3,
#elif defined(__arm__)
		pp->p_seg.p_ttbr,
#endif
		rtsflagstr(pp->p_rts_flags), miscflagstr(pp->p_misc_flags),
		schedulerstr(pp->p_scheduler));

	print_sigmgr(pp);

	dep = P_BLOCKEDON(pp);
	if(dep != NONE) {
		printf(" blocked on: ");
		print_endpoint(dep);
	}
	printf("\n");
}
示例#8
0
	std::string listen_succeeded_alert::message() const
	{
		char ret[200];
		snprintf(ret, sizeof(ret), "successfully listening on [%s] %s"
			, sock_type_str[sock_type], print_endpoint(endpoint).c_str());
		return ret;
	}
示例#9
0
	std::string peer_log_alert::message() const
	{
		static char const* mode[] =
		{ "<==", "==>", "<<<", ">>>", "***" };
		return torrent_alert::message() + " [" + print_endpoint(ip) + "] "
			+ mode[direction] + " " + event_type + " [ " + msg() + " ]";
	}
示例#10
0
static void print_interface(openusb_devid_t devid, int cfgidx, int
		ifcidx,int alt, struct usb_interface_desc *intf)
{ 
	int i;
	int ret;

	printf("    Interface:		%d\n", ifcidx);
	printf("    bInterfaceNumber:   %d\n", intf->bInterfaceNumber);
	printf("    bAlternateSetting:  %d\n", intf->bAlternateSetting);
	printf("    bNumEndpoints:      %d\n", intf->bNumEndpoints);
	printf("    bInterfaceClass:    %02x\n", intf->bInterfaceClass);
	printf("    bInterfaceSubClass: %02x\n", intf->bInterfaceSubClass);
	printf("    bInterfaceProtocol: %02x\n", intf->bInterfaceProtocol);
	printf("    iInterface:         %d\n", intf->iInterface);
	printf("\n");

	for (i = 0; i < intf->bNumEndpoints; i++) {
		struct usb_endpoint_desc ep;

		ret = openusb_parse_endpoint_desc(libhandle,devid,NULL,0,
			cfgidx,ifcidx,alt,i,&ep);
		if(ret != 0) {
			printf("parse endpoint desc fail, ret = %d %s\n", 
					ret, openusb_strerror(ret));
			return;
		}

		print_endpoint(&ep);
	}
}
示例#11
0
	std::string incoming_connection_alert::message() const
	{
		char msg[600];
		error_code ec;
		snprintf(msg, sizeof(msg), "incoming connection from %s (%s)"
			, print_endpoint(ip).c_str(), socket_type_str[socket_type]);
		return msg;
	}
示例#12
0
	bool tracker_manager::incoming_packet(udp::endpoint const& ep
		, span<char const> const buf)
	{
		TORRENT_ASSERT(is_single_thread());
		// ignore packets smaller than 8 bytes
		if (buf.size() < 8)
		{
#ifndef TORRENT_DISABLE_LOGGING
			if (m_ses.should_log())
			{
				m_ses.session_log("incoming packet from %s, not a UDP tracker message "
					"(%d Bytes)", print_endpoint(ep).c_str(), int(buf.size()));
			}
#endif
			return false;
		}

		// the first word is the action, if it's not [0, 3]
		// it's not a valid udp tracker response
		span<const char> ptr = buf;
		std::uint32_t const action = aux::read_uint32(ptr);
		if (action > 3) return false;

		std::uint32_t const transaction = aux::read_uint32(ptr);
		auto const i = m_udp_conns.find(transaction);

		if (i == m_udp_conns.end())
		{
#ifndef TORRENT_DISABLE_LOGGING
			if (m_ses.should_log())
			{
				m_ses.session_log("incoming UDP tracker packet from %s has invalid "
					"transaction ID (%x)", print_endpoint(ep).c_str()
					, transaction);
			}
#endif
			return false;
		}

		std::shared_ptr<udp_tracker_connection> const p = i->second;
		// on_receive() may remove the tracker connection from the list
		return p->on_receive(ep, buf);
	}
示例#13
0
	std::string listen_succeeded_alert::message() const
	{
		static char const* type_str[] =
		{
			"TCP", "TCP/SSL", "UDP"
		};
		char ret[200];
		snprintf(ret, sizeof(ret), "successfully listening on [%s] %s"
			, type_str[sock_type], print_endpoint(endpoint).c_str());
		return ret;
	}
示例#14
0
void traversal_algorithm::done()
{
#ifndef TORRENT_DISABLE_LOGGING
	int results_target = m_node.m_table.bucket_size();
	int closest_target = 160;
#endif

	for (auto const& o : m_results)
	{
		if ((o->flags & (observer::flag_queried | observer::flag_failed)) == observer::flag_queried)
		{
			// set the done flag on any outstanding queries to prevent them from
			// calling finished() or failed() after we've already declared the traversal
			// done
			o->flags |= observer::flag_done;
		}

#ifndef TORRENT_DISABLE_LOGGING
		dht_observer* logger = get_node().observer();
		if (results_target > 0 && (o->flags & observer::flag_alive)
			&& logger != nullptr && logger->should_log(dht_logger::traversal))
		{
			TORRENT_ASSERT(o->flags & observer::flag_queried);
			char hex_id[41];
			aux::to_hex(o->id(), hex_id);
			logger->log(dht_logger::traversal
				, "[%p] id: %s distance: %d addr: %s"
				, static_cast<void*>(this), hex_id, closest_target
				, print_endpoint(o->target_ep()).c_str());

			--results_target;
			int dist = distance_exp(m_target, o->id());
			if (dist < closest_target) closest_target = dist;
		}
#endif
	}

#ifndef TORRENT_DISABLE_LOGGING
	if (get_node().observer() != nullptr)
	{
		get_node().observer()->log(dht_logger::traversal
			, "[%p] COMPLETED distance: %d type: %s"
			, static_cast<void*>(this), closest_target, name());
	}
#endif

	// delete all our references to the observer objects so
	// they will in turn release the traversal algorithm
	m_results.clear();
	m_invoke_count = 0;
}
示例#15
0
static void print_altsetting(struct usb_interface_descriptor *interface)
{
  int i;

  edit_printf("    bInterfaceNumber:   %d\r\n", interface->bInterfaceNumber);
  edit_printf("    bAlternateSetting:  %d\r\n", interface->bAlternateSetting);
  edit_printf("    bNumEndpoints:      %d\r\n", interface->bNumEndpoints);
  edit_printf("    bInterfaceClass:    %d\r\n", interface->bInterfaceClass);
  edit_printf("    bInterfaceSubClass: %d\r\n", interface->bInterfaceSubClass);
  edit_printf("    bInterfaceProtocol: %d\r\n", interface->bInterfaceProtocol);
  edit_printf("    iInterface:         %d\r\n", interface->iInterface);

  for (i = 0; i < interface->bNumEndpoints; i++)
    print_endpoint(&interface->endpoint[i]);
}
示例#16
0
	std::string dht_outgoing_get_peers_alert::message() const
	{
		char msg[600];
		char obf[70];
		obf[0] = '\0';
		if (obfuscated_info_hash != info_hash)
		{
			snprintf(obf, sizeof(obf), " [obfuscated: %s]"
			, to_hex(obfuscated_info_hash.to_string()).c_str());
		}
		snprintf(msg, sizeof(msg), "outgoing dht get_peers : %s%s -> %s"
			, to_hex(info_hash.to_string()).c_str()
			, obf
			, print_endpoint(ip).c_str());
		return msg;
	}
示例#17
0
bool rpc_manager::invoke(entry& e, udp::endpoint target_addr
	, observer_ptr o)
{
	INVARIANT_CHECK;

	if (m_destructing) return false;

	e["y"] = "q";
	entry& a = e["a"];
	add_our_id(a);

	std::string transaction_id;
	transaction_id.resize(2);
	char* out = &transaction_id[0];
	int tid = (random() ^ (random() << 5)) & 0xffff;
	io::write_uint16(tid, out);
	e["t"] = transaction_id;

	// When a DHT node enters the read-only state, in each outgoing query message,
	// places a 'ro' key in the top-level message dictionary and sets its value to 1.
	if (m_settings.read_only) e["ro"] = 1;

	node& n = o->algorithm()->get_node();
	if (!n.native_address(o->target_addr()))
	{
		a["want"].list().push_back(entry(n.protocol_family_name()));
	}

	o->set_target(target_addr);
	o->set_transaction_id(tid);

#ifndef TORRENT_DISABLE_LOGGING
	m_log->log(dht_logger::rpc_manager, "[%p] invoking %s -> %s"
		, static_cast<void*>(o->algorithm()), e["q"].string().c_str()
		, print_endpoint(target_addr).c_str());
#endif

	if (m_sock->send_packet(e, target_addr))
	{
		m_transactions.insert(std::make_pair(tid, o));
#if TORRENT_USE_ASSERTS
		o->m_was_sent = true;
#endif
		return true;
	}
	return false;
}
示例#18
0
	std::string dht_pkt_alert::message() const
	{
		bdecode_node print;
		error_code ec;

		// ignore errors here. This is best-effort. It may be a broken encoding
		// but at least we'll print the valid parts
		bdecode(pkt_buf(), pkt_buf() + pkt_size(), print, ec, NULL, 100, 100);

		std::string msg = print_entry(print, true);

		char const* prefix[2] = { "<==", "==>"};
		char buf[1024];
		snprintf(buf, sizeof(buf), "%s [%s] %s", prefix[dir]
			, print_endpoint(node).c_str(), msg.c_str());

		return buf;
	}
示例#19
0
	std::string listen_failed_alert::message() const
	{
		static char const* op_str[] =
		{
			"parse_addr",
			"open",
			"bind",
			"listen",
			"get_socket_name",
			"accept",
			"enum_if",
			"bind_to_device"
		};
		char ret[300];
		snprintf(ret, sizeof(ret), "listening on %s (device: %s) failed: [%s] [%s] %s"
			, print_endpoint(endpoint).c_str()
			, listen_interface()
			, op_str[operation]
			, sock_type_str[sock_type]
			, convert_from_native(error.message()).c_str());
		return ret;
	}
示例#20
0
void rpc_manager::unreachable(udp::endpoint const& ep)
{
#ifndef TORRENT_DISABLE_LOGGING
	m_log->log(dht_logger::rpc_manager, "PORT_UNREACHABLE [ ip: %s ]"
		, print_endpoint(ep).c_str());
#endif

	for (transactions_t::iterator i = m_transactions.begin();
		i != m_transactions.end();)
	{
		TORRENT_ASSERT(i->second);
		observer_ptr const& o = i->second;
		if (o->target_ep() != ep) { ++i; continue; }
		observer_ptr ptr = i->second;
		i = m_transactions.erase(i);
#ifndef TORRENT_DISABLE_LOGGING
		m_log->log(dht_logger::rpc_manager, "found transaction [ tid: %d ]"
			, int(ptr->transaction_id()));
#endif
		ptr->timeout();
		break;
	}
}
示例#21
0
	std::string listen_failed_alert::message() const
	{
		static char const* op_str[] =
		{
			"parse_addr",
			"open",
			"bind",
			"listen",
			"get_peer_name",
			"accept"
		};
		static char const* type_str[] =
		{
			"TCP", "TCP/SSL", "UDP", "I2P", "Socks5"
		};
		char ret[250];
		snprintf(ret, sizeof(ret), "listening on %s failed: [%s] [%s] %s"
			, print_endpoint(endpoint).c_str()
			, op_str[operation]
			, type_str[sock_type]
			, convert_from_native(error.message()).c_str());
		return ret;
	}
示例#22
0
bool rpc_manager::invoke(entry& e, udp::endpoint target_addr
	, observer_ptr o)
{
	INVARIANT_CHECK;

	if (m_destructing) return false;

	e["y"] = "q";
	entry& a = e["a"];
	add_our_id(a);

	std::string transaction_id;
	transaction_id.resize(2);
	char* out = &transaction_id[0];
	int tid = (random() ^ (random() << 5)) & 0xffff;
	io::write_uint16(tid, out);
	e["t"] = transaction_id;

	o->set_target(target_addr);
	o->set_transaction_id(tid);

#ifndef TORRENT_DISABLE_LOGGING
	m_log->log(dht_logger::rpc_manager, "[%p] invoking %s -> %s"
		, static_cast<void*>(o->algorithm()), e["q"].string().c_str()
		, print_endpoint(target_addr).c_str());
#endif

	if (m_sock->send_packet(e, target_addr, 1))
	{
		m_transactions.insert(std::make_pair(tid,o));
#if TORRENT_USE_ASSERTS
		o->m_was_sent = true;
#endif
		return true;
	}
	return false;
}
示例#23
0
文件: debug.c 项目: mwilbur/minix
PUBLIC void print_proc(struct proc *pp)
{
	struct proc *depproc = NULL;
	endpoint_t dep;

	printf("%d: %s %d prio %d time %d/%d cycles 0x%x%08x cpu %2d "
			"cr3 0x%lx rts %s misc %s sched %s ",
		proc_nr(pp), pp->p_name, pp->p_endpoint, 
		pp->p_priority, pp->p_user_time,
		pp->p_sys_time, ex64hi(pp->p_cycles),
		ex64lo(pp->p_cycles), pp->p_cpu,
		pp->p_seg.p_cr3,
		rtsflagstr(pp->p_rts_flags), miscflagstr(pp->p_misc_flags),
		schedulerstr(pp->p_scheduler));

	print_sigmgr(pp);

	dep = P_BLOCKEDON(pp);
	if(dep != NONE) {
		printf(" blocked on: ");
		print_endpoint(dep);
	}
	printf("\n");
}
示例#24
0
bool rpc_manager::incoming(msg const& m, node_id* id
	, libtorrent::dht_settings const& settings)
{
	INVARIANT_CHECK;

	if (m_destructing) return false;

	// we only deal with replies and errors, not queries
	TORRENT_ASSERT(m.message.dict_find_string_value("y") == "r"
		|| m.message.dict_find_string_value("y") == "e");

	// if we don't have the transaction id in our
	// request list, ignore the packet

	std::string transaction_id = m.message.dict_find_string_value("t");
	if (transaction_id.empty()) return false;

	std::string::const_iterator i = transaction_id.begin();	
	int tid = transaction_id.size() != 2 ? -1 : io::read_uint16(i);

	observer_ptr o;
	std::pair<transactions_t::iterator, transactions_t::iterator> range = m_transactions.equal_range(tid);
	for (transactions_t::iterator i = range.first; i != range.second; ++i)
	{
		if (m.addr.address() != i->second->target_addr()) continue;
		o = i->second;
		i = m_transactions.erase(i);
		break;
	}

	if (!o)
	{
#ifndef TORRENT_DISABLE_LOGGING
		m_log->log(dht_logger::rpc_manager, "reply with unknown transaction id size: %d from %s"
			, int(transaction_id.size()), print_endpoint(m.addr).c_str());
#endif
		// this isn't necessarily because the other end is doing
		// something wrong. This can also happen when we restart
		// the node, and we prematurely abort all outstanding
		// requests. Also, this opens up a potential magnification
		// attack.
//		entry e;
//		incoming_error(e, "invalid transaction id");
//		m_sock->send_packet(e, m.addr, 0);
		return false;
	}

	time_point now = clock_type::now();

#ifndef TORRENT_DISABLE_LOGGING
	std::ofstream reply_stats("round_trip_ms.log", std::ios::app);
	reply_stats << m.addr << "\t" << total_milliseconds(now - o->sent())
		<< std::endl;
#endif

	bdecode_node ret_ent = m.message.dict_find_dict("r");
	if (!ret_ent)
	{
		// it may be an error
		ret_ent = m.message.dict_find("e");
		o->timeout();
		if (!ret_ent)
		{
			entry e;
			incoming_error(e, "missing 'r' key");
			m_sock->send_packet(e, m.addr, 0);
		}
		return false;
	}

	bdecode_node node_id_ent = ret_ent.dict_find_string("id");
	if (!node_id_ent || node_id_ent.string_length() != 20)
	{
		o->timeout();
		entry e;
		incoming_error(e, "missing 'id' key");
		m_sock->send_packet(e, m.addr, 0);
		return false;
	}

	node_id nid = node_id(node_id_ent.string_ptr());
	if (settings.enforce_node_id && !verify_id(nid, m.addr.address()))
	{
		o->timeout();
		entry e;
		incoming_error(e, "invalid node ID");
		m_sock->send_packet(e, m.addr, 0);
		return false;
	}

#ifndef TORRENT_DISABLE_LOGGING
	m_log->log(dht_logger::rpc_manager, "[%p] reply with transaction id: %d from %s"
		, o->algorithm(), int(transaction_id.size())
		, print_endpoint(m.addr).c_str());
#endif
	o->reply(m);
	*id = nid;

	int rtt = int(total_milliseconds(now - o->sent()));

	// we found an observer for this reply, hence the node is not spoofing
	// add it to the routing table
	return m_table.node_seen(*id, m.addr, rtt);
}
示例#25
0
	std::string peer_alert::message() const
	{
		error_code ec;
		return torrent_alert::message() + " peer (" + print_endpoint(ip)
			+ ", " + identify_client(pid) + ")";
	}
示例#26
0
bool rpc_manager::incoming(msg const& m, node_id* id)
{
	INVARIANT_CHECK;

	if (m_destructing) return false;

	// we only deal with replies and errors, not queries
	TORRENT_ASSERT(m.message.dict_find_string_value("y") == "r"
		|| m.message.dict_find_string_value("y") == "e");

	// if we don't have the transaction id in our
	// request list, ignore the packet

	std::string transaction_id = m.message.dict_find_string_value("t");
	if (transaction_id.empty()) return false;

	std::string::const_iterator ptr = transaction_id.begin();
	int tid = transaction_id.size() != 2 ? -1 : io::read_uint16(ptr);

	observer_ptr o;
	std::pair<transactions_t::iterator, transactions_t::iterator> range = m_transactions.equal_range(tid);
	for (transactions_t::iterator i = range.first; i != range.second; ++i)
	{
		if (m.addr.address() != i->second->target_addr()) continue;
		o = i->second;
		i = m_transactions.erase(i);
		break;
	}

	if (!o)
	{
#ifndef TORRENT_DISABLE_LOGGING
		if (m_table.native_endpoint(m.addr))
		{
			m_log->log(dht_logger::rpc_manager, "reply with unknown transaction id size: %d from %s"
				, int(transaction_id.size()), print_endpoint(m.addr).c_str());
		}
#endif
		// this isn't necessarily because the other end is doing
		// something wrong. This can also happen when we restart
		// the node, and we prematurely abort all outstanding
		// requests. Also, this opens up a potential magnification
		// attack.
//		entry e;
//		incoming_error(e, "invalid transaction id");
//		m_sock->send_packet(e, m.addr);
		return false;
	}

	time_point now = clock_type::now();

#ifndef TORRENT_DISABLE_LOGGING
	m_log->log(dht_logger::rpc_manager, "round trip time(ms): %" PRId64 " from %s"
		, total_milliseconds(now - o->sent()), print_endpoint(m.addr).c_str());
#endif

	if (m.message.dict_find_string_value("y") == "e")
	{
		// It's an error.
#ifndef TORRENT_DISABLE_LOGGING
		bdecode_node err = m.message.dict_find_list("e");
		if (err && err.list_size() >= 2
			&& err.list_at(0).type() == bdecode_node::int_t
			&& err.list_at(1).type() == bdecode_node::string_t)
		{
			m_log->log(dht_logger::rpc_manager, "reply with error from %s: (%" PRId64 ") %s"
				, print_endpoint(m.addr).c_str()
				, err.list_int_value_at(0)
				, err.list_string_value_at(1).c_str());
		}
		else
		{
			m_log->log(dht_logger::rpc_manager, "reply with (malformed) error from %s"
				, print_endpoint(m.addr).c_str());
		}
#endif
		// Logically, we should call o->reply(m) since we get a reply.
		// a reply could be "response" or "error", here the reply is an "error".
		// if the reply is an "error", basically the observer could/will
		// do nothing with it, especially when observer::reply() is intended to
		// handle a "response", not an "error".
		// A "response" should somehow call algorithm->finished(), and an error/timeout
		// should call algorithm->failed(). From this point of view,
		// we should call o->timeout() instead of o->reply(m) because o->reply()
		// will call algorithm->finished().
		o->timeout();
		return false;
	}

	bdecode_node ret_ent = m.message.dict_find_dict("r");
	if (!ret_ent)
	{
		o->timeout();
		return false;
	}

	bdecode_node node_id_ent = ret_ent.dict_find_string("id");
	if (!node_id_ent || node_id_ent.string_length() != 20)
	{
		o->timeout();
		return false;
	}

	node_id nid = node_id(node_id_ent.string_ptr());
	if (m_settings.enforce_node_id && !verify_id(nid, m.addr.address()))
	{
		o->timeout();
		return false;
	}

#ifndef TORRENT_DISABLE_LOGGING
	m_log->log(dht_logger::rpc_manager, "[%p] reply with transaction id: %d from %s"
		, static_cast<void*>(o->algorithm()), int(transaction_id.size())
		, print_endpoint(m.addr).c_str());
#endif
	o->reply(m);
	*id = nid;

	int rtt = int(total_milliseconds(now - o->sent()));

	// we found an observer for this reply, hence the node is not spoofing
	// add it to the routing table
	return m_table.node_seen(*id, m.addr, rtt);
}
示例#27
0
	void error_logger::handle_alert(alert const* a)
	{
		if (m_file == NULL) return;
		time_t now = time(NULL);
		char timestamp[256];
		strncpy(timestamp, ctime(&now), sizeof(timestamp));
		for (int i = 0; i < sizeof(timestamp); ++i)
		{
			if (timestamp[i] != '\n' && timestamp[i] != '\r') continue;
			timestamp[i] = '\0';
			break;
		}

		switch (a->type())
		{
			case peer_error_alert::alert_type:
			{
				peer_error_alert const* pe = alert_cast<peer_error_alert>(a);
#ifdef TORRENT_USE_OPENSSL
				// unknown protocol
				if (pe->error != error_code(336027900, boost::asio::error::get_ssl_category()))
#endif
				{
					fprintf(m_file, "%s\terror [%s] (%s:%d) %s\n", timestamp
						, print_endpoint(pe->ip).c_str(), pe->error.category().name()
						, pe->error.value(), pe->error.message().c_str());
				}
				break;
			}
			case peer_disconnected_alert::alert_type:
			{
				peer_disconnected_alert const* pd = alert_cast<peer_disconnected_alert>(a);
				if (pd
					&& pd->error != boost::system::errc::connection_reset
					&& pd->error != boost::system::errc::connection_aborted
					&& pd->error != boost::system::errc::connection_refused
					&& pd->error != boost::system::errc::timed_out
					&& pd->error != boost::asio::error::eof
					&& pd->error != boost::asio::error::host_unreachable
					&& pd->error != boost::asio::error::network_unreachable
					&& pd->error != boost::asio::error::broken_pipe
#ifdef TORRENT_USE_OPENSSL
					// unknown protocol
					&& pd->error != error_code(336027900, boost::asio::error::get_ssl_category())
#endif
					&& pd->error != error_code(libtorrent::errors::self_connection)
					&& pd->error != error_code(libtorrent::errors::torrent_removed)
					&& pd->error != error_code(libtorrent::errors::torrent_aborted)
					&& pd->error != error_code(libtorrent::errors::stopping_torrent)
					&& pd->error != error_code(libtorrent::errors::session_closing)
					&& pd->error != error_code(libtorrent::errors::duplicate_peer_id)
					&& pd->error != error_code(libtorrent::errors::timed_out)
					&& pd->error != error_code(libtorrent::errors::timed_out_no_handshake)
					&& pd->error != error_code(libtorrent::errors::upload_upload_connection))
					fprintf(m_file, "%s\tdisconnect [%s][%s] (%s:%d) %s\n", timestamp
						, print_endpoint(pd->ip).c_str(), operation_name(pd->operation)
						, pd->error.category().name(), pd->error.value(), pd->error.message().c_str());
				break;
			}
			case save_resume_data_failed_alert::alert_type:
			{
				save_resume_data_failed_alert const* rs= alert_cast<save_resume_data_failed_alert>(a);
				if (rs)
					fprintf(m_file, "%s\tsave-resume-failed (%s:%d) %s\n", timestamp
						, rs->error.category().name(), rs->error.value()
						, rs->message().c_str());
			}
			case torrent_delete_failed_alert::alert_type:
			{
				torrent_delete_failed_alert const* td = alert_cast<torrent_delete_failed_alert>(a);
				if (td)
					fprintf(m_file, "%s\tstorage-delete-failed (%s:%d) %s\n", timestamp
						, td->error.category().name(), td->error.value()
						, td->message().c_str());
			}
			case storage_moved_failed_alert::alert_type:
			{
				storage_moved_failed_alert const* sm = alert_cast<storage_moved_failed_alert>(a);
				if (sm)
					fprintf(m_file, "%s\tstorage-move-failed (%s:%d) %s\n", timestamp
						, sm->error.category().name(), sm->error.value()
						, sm->message().c_str());
			}
			case file_rename_failed_alert::alert_type:
			{
				file_rename_failed_alert const* rn = alert_cast<file_rename_failed_alert>(a);
				if (rn)
					fprintf(m_file, "%s\tfile-rename-failed (%s:%d) %s\n", timestamp
						, rn->error.category().name(), rn->error.value()
						, rn->message().c_str());
			}
			case torrent_error_alert::alert_type:
			{
				torrent_error_alert const* te = alert_cast<torrent_error_alert>(a);
				if (te)
					fprintf(m_file, "%s\ttorrent-error (%s:%d) %s\n", timestamp
						, te->error.category().name(), te->error.value()
						, te->message().c_str());
			}
			case hash_failed_alert::alert_type:
			{
				hash_failed_alert const* hf = alert_cast<hash_failed_alert>(a);
				if (hf)
					fprintf(m_file, "%s\thash-failed %s\n", timestamp
						, hf->message().c_str());
			}
			case file_error_alert::alert_type:
			{
				file_error_alert const* fe = alert_cast<file_error_alert>(a);
				if (fe)
					fprintf(m_file, "%s\tfile-error (%s:%d) %s\n", timestamp
						, fe->error.category().name(), fe->error.value()
						, fe->message().c_str());
			}
			case metadata_failed_alert::alert_type:
			{
				metadata_failed_alert const* mf = alert_cast<metadata_failed_alert>(a);
				if (mf)
					fprintf(m_file, "%s\tmetadata-error (%s:%d) %s\n", timestamp
						, mf->error.category().name(), mf->error.value()
						, mf->message().c_str());
			}
			case udp_error_alert::alert_type:
			{
				udp_error_alert const* ue = alert_cast<udp_error_alert>(a);
				if (ue)
					fprintf(m_file, "%s\tudp-error (%s:%d) %s %s\n", timestamp
						, ue->error.category().name(), ue->error.value()
						, print_endpoint(ue->endpoint).c_str()
						, ue->error.message().c_str());
			}
			case listen_failed_alert::alert_type:
			{
				listen_failed_alert const* lf = alert_cast<listen_failed_alert>(a);
				if (lf)
					fprintf(m_file, "%s\tlisten-error (%s:%d) %s\n", timestamp
						, lf->error.category().name(), lf->error.value()
						, lf->message().c_str());
			}
			case rss_alert::alert_type:
			{
				rss_alert const* ra = alert_cast<rss_alert>(a);
				if (ra && ra->state == rss_alert::state_error)
					fprintf(m_file, "%s\trss-error (%s:%d) %s %s\n", timestamp
						, ra->error.category().name(), ra->error.value()
						, ra->error.message().c_str()
						, ra->url.c_str());
			}
			case invalid_request_alert::alert_type:
			{
				invalid_request_alert const* ira = alert_cast<invalid_request_alert>(a);
				if (ira)
					fprintf(m_file, "%s\tinvalid-request %s\n", timestamp
						, ira->message().c_str());
			}
			case mmap_cache_alert::alert_type:
			{
				mmap_cache_alert const* ma = alert_cast<mmap_cache_alert>(a);
				if (ma)
					fprintf(m_file, "%s\tmmap-cache-error (%s:%d )%s\n", timestamp
						, ma->error.category().name(), ma->error.value()
						, ma->message().c_str());
			}
		}
	}
示例#28
0
void traversal_algorithm::add_entry(node_id const& id
	, udp::endpoint const& addr, unsigned char const flags)
{
	TORRENT_ASSERT(m_node.m_rpc.allocation_size() >= sizeof(find_data_observer));
	auto o = new_observer(addr, id);
	if (!o)
	{
#ifndef TORRENT_DISABLE_LOGGING
		if (get_node().observer() != nullptr)
		{
			get_node().observer()->log(dht_logger::traversal, "[%p] failed to allocate memory or observer. aborting!"
				, static_cast<void*>(this));
		}
#endif
		done();
		return;
	}
	if (id.is_all_zeros())
	{
		o->set_id(generate_random_id());
		o->flags |= observer::flag_no_id;
	}

	o->flags |= flags;

	TORRENT_ASSERT(libtorrent::dht::is_sorted(m_results.begin(), m_results.end()
		, [this](observer_ptr const& lhs, observer_ptr const& rhs)
		{ return compare_ref(lhs->id(), rhs->id(), m_target); }));

	auto iter = std::lower_bound(m_results.begin(), m_results.end(), o
		, [this](observer_ptr const& lhs, observer_ptr const& rhs)
		{ return compare_ref(lhs->id(), rhs->id(), m_target); });

	if (iter == m_results.end() || (*iter)->id() != id)
	{
		if (m_node.settings().restrict_search_ips
			&& !(flags & observer::flag_initial))
		{
#if TORRENT_USE_IPV6
			if (o->target_addr().is_v6())
			{
				address_v6::bytes_type addr_bytes = o->target_addr().to_v6().to_bytes();
				address_v6::bytes_type::const_iterator prefix_it = addr_bytes.begin();
				std::uint64_t const prefix6 = detail::read_uint64(prefix_it);

				if (m_peer6_prefixes.insert(prefix6).second)
					goto add_result;
			}
			else
#endif
			{
				// mask the lower octet
				std::uint32_t const prefix4
					= o->target_addr().to_v4().to_ulong() & 0xffffff00;

				if (m_peer4_prefixes.insert(prefix4).second)
					goto add_result;
			}

			// we already have a node in this search with an IP very
			// close to this one. We know that it's not the same, because
			// it claims a different node-ID. Ignore this to avoid attacks
#ifndef TORRENT_DISABLE_LOGGING
			dht_observer* logger = get_node().observer();
			if (logger != nullptr && logger->should_log(dht_logger::traversal))
			{
				char hex_id[41];
				aux::to_hex(o->id(), hex_id);
				logger->log(dht_logger::traversal
					, "[%p] traversal DUPLICATE node. id: %s addr: %s type: %s"
					, static_cast<void*>(this), hex_id, print_address(o->target_addr()).c_str(), name());
			}
#endif
			return;
		}

	add_result:

		TORRENT_ASSERT((o->flags & observer::flag_no_id)
			|| std::none_of(m_results.begin(), m_results.end()
			, [&id](observer_ptr const& ob) { return ob->id() == id; }));

#ifndef TORRENT_DISABLE_LOGGING
		dht_observer* logger = get_node().observer();
		if (logger != nullptr && logger->should_log(dht_logger::traversal))
		{
			char hex_id[41];
			aux::to_hex(id, hex_id);
			logger->log(dht_logger::traversal
				, "[%p] ADD id: %s addr: %s distance: %d invoke-count: %d type: %s"
				, static_cast<void*>(this), hex_id, print_endpoint(addr).c_str()
				, distance_exp(m_target, id), m_invoke_count, name());
		}
#endif
		iter = m_results.insert(iter, o);

		TORRENT_ASSERT(libtorrent::dht::is_sorted(m_results.begin(), m_results.end()
			, [this](observer_ptr const& lhs, observer_ptr const& rhs)
			{ return compare_ref(lhs->id(), rhs->id(), m_target); }));
	}

	if (m_results.size() > 100)
	{
		for (int i = 100; i < int(m_results.size()); ++i)
		{
			if ((m_results[i]->flags & (observer::flag_queried | observer::flag_failed | observer::flag_alive))
				== observer::flag_queried)
			{
				// set the done flag on any outstanding queries to prevent them from
				// calling finished() or failed()
				m_results[i]->flags |= observer::flag_done;
				TORRENT_ASSERT(m_invoke_count > 0);
				--m_invoke_count;
			}

#if TORRENT_USE_ASSERTS
			m_results[i]->m_was_abandoned = true;
#endif
		}
		m_results.resize(100);
	}
}
示例#29
0
文件: core.c 项目: thearcanum/WIFSS
bool start_client(void)
{
	clear_console();

	printf("\n\033[32m[WIFSS] Starting Client...\033[0m\n\n");

	init_global_variables();

	char address[BUFFER];
	char *args[BUFFER];
	int16_t nbArgs = -1;

	do
	{
		printf("-> Server IP: ");
		prompt_keyboard(address);
		free_args(args, &nbArgs);
		parse_command(address, args, &nbArgs);

	} while(nbArgs != 1);

	int32_t port;
	char portBuffer[BUFFER];
	do
	{
		printf("-> Server Port: ");
		prompt_keyboard(portBuffer);
		free_args(args, &nbArgs);
		parse_command(portBuffer, args, &nbArgs);

		if(nbArgs == 1)
		{
			port = strtoul(args[0], NULL, 10);
		}

		else
		{
			port = -1;
		}

	} while(port < 0 || port > 65535);

	struct addrinfo *servinfo;

	struct addrinfo hints;
	memset(&hints, 0, sizeof hints);
	hints.ai_family   = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_flags    = AI_PASSIVE;

	int16_t status = getaddrinfo(address, args[0], &hints, &servinfo);
	if(status != 0)
	{
	    fprintf(stderr, "\n\033[31m[WIFSS] An error occurred while trying to get some information about your host: %s.\033[0m\n\n", gai_strerror(status));
	    exit(EXIT_FAILURE);
	}

	char buffer[BUFFER];

	// Some stuff to set a timeout on `connect`
	int16_t sock     = -1;
	int8_t error     = 0;
	socklen_t lenght = sizeof(error);
	int16_t nbFds    = -1;
	fd_set readfds;
	do
	{
		for(struct addrinfo *tmp = servinfo; tmp != NULL; tmp = tmp->ai_next)
		{
			/* Only for previous iterations */
			if(sock != -1 && close(sock) == -1)
			{
				fprintf(stderr, "\n\033[31m[WIFSS] An error occurred while closing a socket: %s.\033[0m\n\n", strerror(errno));
				exit(EXIT_FAILURE);
			}
			/* ____________________________ */

			sock = socket(tmp->ai_family, tmp->ai_socktype, tmp->ai_protocol);
			if(sock == -1)
			{
				printf("\n\033[31m[WIFSS] Error while creating an endpoint for communication with server: %s.\033[0m\n\n", strerror(errno));
				return false;
			}

			// Before the connection procedure, we'll set the socket as NON-BLOCKING
			fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, false) | O_NONBLOCK);

			// Let's launch the connection procedure
			connect(sock, tmp->ai_addr, tmp->ai_addrlen);
			if(errno != EINPROGRESS)
			{
				fprintf(stderr, "\n\033[31m[WIFSS] An error occurred while running the connection procedure to: ");
				print_endpoint(tmp);
				printf(" (%s).\033[0m\n\n", strerror(errno));
				continue;
			}

			// Let's now set a watch dog of 3 seconds on it
			FD_ZERO(&readfds);
			FD_SET(sock, &readfds);
			nbFds = select(sock + 1, &readfds, NULL, NULL, &(struct timeval){3, 0});
			if(nbFds == 0)
			{
				// The timeout has been elapsed...
				printf("\n\033[31m[WIFSS] Error while connecting to ");
				print_endpoint(tmp);
				printf(": timeout reached.\033[0m\n");
				continue;
			}

			else if(nbFds == -1)
			{
				// Again ? An error occurred...
				fprintf(stderr, "\n\033[31m[WIFSS] An error occurred while waiting for the connection procedure ending: %s.\033[0m\n\n", strerror(errno));
				exit(EXIT_FAILURE);
			}

			else
			{
				// Fetch the buffered SYNC data [see @server/commands.c]
				recv(sock, buffer, BUFFER, false);

				if(strcmp(buffer, CLIENT_SERVER_SYNC))
				{
					printf("%s\n", buffer);
					exit(EXIT_FAILURE);
				}
			}

			// Two cases: The connection has been established OR a f*cking new error occurred (before the timeout !)...
			if(getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &lenght) != 0)
			{
				fprintf(stderr, "\n\033[31m[WIFSS] An error occurred while retrieving some information about the socket: %s.\033[0m\n\n", gai_strerror(status));
				exit(EXIT_FAILURE);
			}

			if(error == 0)
			{
				// For the future, let's set again the socket as BLOCKING
				fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, false) ^ O_NONBLOCK);

				// SSL stuffs
				SSL *ssl = SSL_new(core_variables.ctx);
				if(ssl == NULL)
				{
					fprintf(stderr, "\n\n\033[31mSSL Error: Couldn\'t enable the SSL layer on the socket.\n\n");
					exit(EXIT_FAILURE);
				}

				if(SSL_set_cipher_list(ssl, (const char *const)"HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4") != 1)
				{
					fprintf(stderr, "\n\n\033[31mSSL Error: Couldn\'t set the ciphers list.\n\n");
					exit(EXIT_FAILURE);
				}

				SSL_set_fd(ssl, sock);

				if(SSL_connect(ssl) <= 0)
				{
					printf("\n\n\033[31m[WIFSS] Couldn\'t create a TLS tunnel with the host...\033[0m\n\n");
					ERR_print_errors_fp(stderr);
					exit(EXIT_FAILURE);
				}

				// SSL Verification + Certificate information
				if(SSL_get_verify_result(ssl) != X509_V_OK)
				{
					fprintf(stderr, "\n\n\033[31mSSL Error: The result got from SSL is not valid (is your certificate correct ?).\n\n");
					exit(EXIT_FAILURE);
				}

				X509 *cert = SSL_get_peer_certificate(ssl);
				if(cert == NULL)
				{
					fprintf(stderr, "\n\n\033[31mSSL Error: No certificate was sent by server.\n\n");
					exit(EXIT_FAILURE);
				}

				printf("\n\033[34m\tTLS cipher used for this connection: %s\n", SSL_get_cipher(ssl));

				char *str = NULL;
				printf("\tServer certificate:\n");
				str = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
				printf("\t\tSubject: %s\n", (str != NULL ? str : "None"));
				OPENSSL_free(str);
				str = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
				printf("\t\tIssuer : %s\033[0m\n", (str != NULL ? str : "None"));
				OPENSSL_free(str);
				X509_free(cert);
				// __________________________________________

				core_variables.ssl = ssl;

				printf("\n\033[32m[WIFSS] Connected to ");
				print_endpoint(tmp);
				printf(".\033[0m\n");

				strncpy(buffer, "", BUFFER);

				if(SSL_read(ssl, buffer, BUFFER) <= 0)
				{
					printf("\n\033[31m[WIFSS] Couldn\'t get your ID from server, exiting now.\033[0m\n\n");
					exit(EXIT_FAILURE);
				}

				uint16_t idTemp = get_second_args_group_as_integer(buffer);
				printf("\n\033[32m[WIFSS] Your ID on the server is %d.\033[0m\n\n", idTemp);

				/* We save the ID of the client for the future */
				core_variables.client_id = idTemp;

				break;
			}

			else
			{
				printf("\n\033[31m[WIFSS] Error while connecting to ");
				print_endpoint(tmp);
				printf(": %s.\033[0m\n", strerror(errno));
			}
		}

		if(core_variables.client_id != -1)
		{
			// Yeah... We've to `break` the loop a second time 
			break;
		}

		else
		{
			printf("\nWould you like to retry now ? (YES / no)\n\n");
			if(!prompt_yes_no(buffer, args, &nbArgs))
			{
				printf("\n");
				return false;
			}
		}

	} while(true);
示例#30
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()));
}