1 /*
2 
3 Copyright (c) 2008, Arvid Norberg
4 All rights reserved.
5 
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
8 are met:
9 
10     * Redistributions of source code must retain the above copyright
11       notice, this list of conditions and the following disclaimer.
12     * Redistributions in binary form must reproduce the above copyright
13       notice, this list of conditions and the following disclaimer in
14       the documentation and/or other materials provided with the distribution.
15     * Neither the name of the author nor the names of its
16       contributors may be used to endorse or promote products derived
17       from this software without specific prior written permission.
18 
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 POSSIBILITY OF SUCH DAMAGE.
30 
31 */
32 
33 #include "test.hpp"
34 
35 #ifndef TORRENT_DISABLE_DHT
36 
37 #include "libtorrent/config.hpp"
38 #include "libtorrent/session.hpp"
39 #include "libtorrent/kademlia/msg.hpp" // for verify_message
40 #include "libtorrent/kademlia/node.hpp"
41 #include "libtorrent/bencode.hpp"
42 #include "libtorrent/bdecode.hpp"
43 #include "libtorrent/socket_io.hpp" // for hash_address
44 #include "libtorrent/broadcast_socket.hpp" // for supports_ipv6
45 #include "libtorrent/performance_counters.hpp" // for counters
46 #include "libtorrent/random.hpp"
47 #include "libtorrent/kademlia/ed25519.hpp"
48 #include "libtorrent/hex.hpp" // to_hex, from_hex
49 #include "libtorrent/bloom_filter.hpp"
50 #include "libtorrent/hasher.hpp"
51 #include "libtorrent/aux_/time.hpp"
52 #include "libtorrent/aux_/listen_socket_handle.hpp"
53 #include "libtorrent/aux_/session_impl.hpp"
54 
55 #include "libtorrent/kademlia/node_id.hpp"
56 #include "libtorrent/kademlia/routing_table.hpp"
57 #include "libtorrent/kademlia/item.hpp"
58 #include "libtorrent/kademlia/dht_observer.hpp"
59 #include "libtorrent/kademlia/dht_tracker.hpp"
60 
61 #include <numeric>
62 #include <cstdarg>
63 #include <tuple>
64 #include <iostream>
65 #include <cstdio> // for vsnprintf
66 
67 #include "setup_transfer.hpp"
68 
69 using namespace lt;
70 using namespace lt::dht;
71 using namespace std::placeholders;
72 
73 namespace {
74 
get_test_keypair(public_key & pk,secret_key & sk)75 void get_test_keypair(public_key& pk, secret_key& sk)
76 {
77 	aux::from_hex({"77ff84905a91936367c01360803104f92432fcd904a43511876df5cdf3e7e548", 64}
78 		, pk.bytes.data());
79 	aux::from_hex({"e06d3183d14159228433ed599221b80bd0a5ce8352e4bdf0262f76786ef1c74d"
80 		"b7e7a9fea2c0eb269d61e3b38e450a22e754941ac78479d6c54e1faf6037881d", 128}
81 		, sk.bytes.data());
82 }
83 
prev_seq(sequence_number s)84 sequence_number prev_seq(sequence_number s)
85 {
86 	return sequence_number(s.value - 1);
87 }
88 
next_seq(sequence_number s)89 sequence_number next_seq(sequence_number s)
90 {
91 	return sequence_number(s.value + 1);
92 }
93 
add_and_replace(node_id & dst,node_id const & add)94 void add_and_replace(node_id& dst, node_id const& add)
95 {
96 	bool carry = false;
97 	for (int k = 19; k >= 0; --k)
98 	{
99 		int sum = dst[k] + add[k] + (carry ? 1 : 0);
100 		dst[k] = sum & 255;
101 		carry = sum > 255;
102 	}
103 }
104 
node_push_back(std::vector<node_entry> * nv,node_entry const & n)105 void node_push_back(std::vector<node_entry>* nv, node_entry const& n)
106 {
107 	nv->push_back(n);
108 }
109 
nop_node()110 void nop_node() {}
111 
112 // TODO: 3 make the mock_socket hold a reference to the list of where to record
113 // packets instead of having a global variable
114 std::list<std::pair<udp::endpoint, entry>> g_sent_packets;
115 
116 struct mock_socket final : socket_manager
117 {
has_quota__anone716e03d0111::mock_socket118 	bool has_quota() override { return true; }
send_packet__anone716e03d0111::mock_socket119 	bool send_packet(aux::listen_socket_handle const&, entry& msg, udp::endpoint const& ep) override
120 	{
121 		// TODO: 3 ideally the mock_socket would contain this queue of packets, to
122 		// make tests independent
123 		g_sent_packets.push_back(std::make_pair(ep, msg));
124 		return true;
125 	}
126 };
127 
dummy_listen_socket(udp::endpoint src)128 std::shared_ptr<aux::listen_socket_t> dummy_listen_socket(udp::endpoint src)
129 {
130 	auto ret = std::make_shared<aux::listen_socket_t>();
131 	ret->local_endpoint = tcp::endpoint(src.address(), src.port());
132 	ret->external_address.cast_vote(src.address()
133 		, aux::session_interface::source_dht, rand_v4());
134 	return ret;
135 }
136 
dummy_listen_socket4()137 std::shared_ptr<aux::listen_socket_t> dummy_listen_socket4()
138 {
139 	auto ret = std::make_shared<aux::listen_socket_t>();
140 	ret->local_endpoint = tcp::endpoint(addr4("192.168.4.1"), 6881);
141 	ret->external_address.cast_vote(addr4("236.0.0.1")
142 		, aux::session_interface::source_dht, rand_v4());
143 	return ret;
144 }
145 
dummy_listen_socket6()146 std::shared_ptr<aux::listen_socket_t> dummy_listen_socket6()
147 {
148 	auto ret = std::make_shared<aux::listen_socket_t>();
149 	ret->local_endpoint = tcp::endpoint(addr6("2002::1"), 6881);
150 	ret->external_address.cast_vote(addr6("2002::1")
151 		, aux::session_interface::source_dht, rand_v6());
152 	return ret;
153 }
154 
get_foreign_node_stub(node_id const &,std::string const &)155 node* get_foreign_node_stub(node_id const&, std::string const&)
156 {
157 	return nullptr;
158 }
159 
generate_next()160 sha1_hash generate_next()
161 {
162 	sha1_hash ret;
163 	aux::random_bytes(ret);
164 	return ret;
165 }
166 
167 std::list<std::pair<udp::endpoint, entry>>::iterator
find_packet(udp::endpoint ep)168 find_packet(udp::endpoint ep)
169 {
170 	return std::find_if(g_sent_packets.begin(), g_sent_packets.end()
171 		, [&ep] (std::pair<udp::endpoint, entry> const& p)
172 		{ return p.first == ep; });
173 }
174 
node_from_entry(entry const & e,bdecode_node & l)175 void node_from_entry(entry const& e, bdecode_node& l)
176 {
177 	error_code ec;
178 	static char inbuf[1500];
179 	int len = bencode(inbuf, e);
180 	int ret = bdecode(inbuf, inbuf + len, l, ec);
181 	TEST_CHECK(ret == 0);
182 }
183 
write_peers(std::set<tcp::endpoint> const & peers)184 entry write_peers(std::set<tcp::endpoint> const& peers)
185 {
186 	entry r;
187 	entry::list_type& pe = r.list();
188 	for (auto const& p : peers)
189 	{
190 		std::string endpoint(18, '\0');
191 		std::string::iterator out = endpoint.begin();
192 		lt::detail::write_endpoint(p, out);
193 		endpoint.resize(std::size_t(out - endpoint.begin()));
194 		pe.push_back(entry(endpoint));
195 	}
196 	return r;
197 }
198 
199 struct msg_args
200 {
info_hash__anone716e03d0111::msg_args201 	msg_args& info_hash(char const* i)
202 	{ if (i) a["info_hash"] = std::string(i, 20); return *this; }
203 
name__anone716e03d0111::msg_args204 	msg_args& name(char const* n)
205 	{ if (n) a["n"] = n; return *this; }
206 
token__anone716e03d0111::msg_args207 	msg_args& token(std::string t)
208 	{ a["token"] = t; return *this; }
209 
port__anone716e03d0111::msg_args210 	msg_args& port(int p)
211 	{ a["port"] = p; return *this; }
212 
target__anone716e03d0111::msg_args213 	msg_args& target(sha1_hash const& t)
214 	{ a["target"] = t.to_string(); return *this; }
215 
value__anone716e03d0111::msg_args216 	msg_args& value(entry const& v)
217 	{ a["v"] = v; return *this; }
218 
scrape__anone716e03d0111::msg_args219 	msg_args& scrape(bool s)
220 	{ a["scrape"] = s ? 1 : 0; return *this; }
221 
seed__anone716e03d0111::msg_args222 	msg_args& seed(bool s)
223 	{ a["seed"] = s ? 1 : 0; return *this; }
224 
key__anone716e03d0111::msg_args225 	msg_args& key(public_key const& k)
226 	{ a["k"] = k.bytes; return *this; }
227 
sig__anone716e03d0111::msg_args228 	msg_args& sig(signature const& s)
229 	{ a["sig"] = s.bytes; return *this; }
230 
seq__anone716e03d0111::msg_args231 	msg_args& seq(sequence_number s)
232 	{ a["seq"] = s.value; return *this; }
233 
cas__anone716e03d0111::msg_args234 	msg_args& cas(sequence_number c)
235 	{ a["cas"] = c.value; return *this; }
236 
nid__anone716e03d0111::msg_args237 	msg_args& nid(sha1_hash const& n)
238 	{ a["id"] = n.to_string(); return *this; }
239 
salt__anone716e03d0111::msg_args240 	msg_args& salt(span<char const> s)
241 	{ if (!s.empty()) a["salt"] = s; return *this; }
242 
want__anone716e03d0111::msg_args243 	msg_args& want(std::string w)
244 	{ a["want"].list().push_back(w); return *this; }
245 
nodes__anone716e03d0111::msg_args246 	msg_args& nodes(std::vector<node_entry> const& n)
247 	{ if (!n.empty()) a["nodes"] = dht::write_nodes_entry(n); return *this; }
248 
nodes6__anone716e03d0111::msg_args249 	msg_args& nodes6(std::vector<node_entry> const& n)
250 	{ if (!n.empty()) a["nodes6"] = dht::write_nodes_entry(n); return *this; }
251 
peers__anone716e03d0111::msg_args252 	msg_args& peers(std::set<tcp::endpoint> const& p)
253 	{ if (!p.empty()) a.dict()["values"] = write_peers(p); return *this; }
254 
interval__anone716e03d0111::msg_args255 	msg_args& interval(time_duration interval)
256 	{ a["interval"] = total_seconds(interval); return *this; }
257 
num__anone716e03d0111::msg_args258 	msg_args& num(int num)
259 	{ a["num"] = num; return *this; }
260 
samples__anone716e03d0111::msg_args261 	msg_args& samples(std::vector<sha1_hash> const& samples)
262 	{
263 		a["samples"] = span<char const>(
264 			reinterpret_cast<char const*>(samples.data()), int(samples.size()) * 20);
265 		return *this;
266 	}
267 
268 	entry a;
269 };
270 
send_dht_request(node & node,char const * msg,udp::endpoint const & ep,bdecode_node * reply,msg_args const & args=msg_args (),char const * t="10",bool has_response=true)271 void send_dht_request(node& node, char const* msg, udp::endpoint const& ep
272 	, bdecode_node* reply, msg_args const& args = msg_args()
273 	, char const* t = "10", bool has_response = true)
274 {
275 	// we're about to clear out the backing buffer
276 	// for this bdecode_node, so we better clear it now
277 	reply->clear();
278 	entry e;
279 	e["q"] = msg;
280 	e["t"] = t;
281 	e["y"] = "q";
282 	e["a"] = args.a;
283 	e["a"].dict().insert(std::make_pair("id", generate_next().to_string()));
284 	char msg_buf[1500];
285 	int size = bencode(msg_buf, e);
286 
287 	bdecode_node decoded;
288 	error_code ec;
289 	bdecode(msg_buf, msg_buf + size, decoded, ec);
290 	if (ec) std::printf("bdecode failed: %s\n", ec.message().c_str());
291 
292 	dht::msg m(decoded, ep);
293 	node.incoming(node.m_sock, m);
294 
295 	// If the request is supposed to get a response, by now the node should have
296 	// invoked the send function and put the response in g_sent_packets
297 	auto const i = find_packet(ep);
298 	if (has_response)
299 	{
300 		if (i == g_sent_packets.end())
301 		{
302 			TEST_ERROR("not response from DHT node");
303 			return;
304 		}
305 
306 		node_from_entry(i->second, *reply);
307 		g_sent_packets.erase(i);
308 
309 		return;
310 	}
311 
312 	// this request suppose won't be responsed.
313 	if (i != g_sent_packets.end())
314 	{
315 		TEST_ERROR("shouldn't have response from DHT node");
316 		return;
317 	}
318 }
319 
send_dht_response(node & node,bdecode_node const & request,udp::endpoint const & ep,msg_args const & args=msg_args ())320 void send_dht_response(node& node, bdecode_node const& request, udp::endpoint const& ep
321 	, msg_args const& args = msg_args())
322 {
323 	entry e;
324 	e["y"] = "r";
325 	e["t"] = request.dict_find_string_value("t").to_string();
326 //	e["ip"] = endpoint_to_bytes(ep);
327 	e["r"] = args.a;
328 	e["r"].dict().insert(std::make_pair("id", generate_next().to_string()));
329 	char msg_buf[1500];
330 	int const size = bencode(msg_buf, e);
331 
332 	bdecode_node decoded;
333 	error_code ec;
334 	bdecode(msg_buf, msg_buf + size, decoded, ec);
335 	if (ec) std::printf("bdecode failed: %s\n", ec.message().c_str());
336 
337 	dht::msg m(decoded, ep);
338 	node.incoming(node.m_sock, m);
339 }
340 
341 struct announce_item
342 {
announce_item__anone716e03d0111::announce_item343 	announce_item(sha1_hash nxt, int const num)
344 		: next(nxt)
345 		, num_peers(num)
346 	{
347 		num_peers = (rand() % 5) + 2;
348 		ent["next"] = next.to_string();
349 		ent["A"] = "a";
350 		ent["B"] = "b";
351 		ent["num_peers"] = num_peers;
352 
353 		char buf[512];
354 		char* ptr = buf;
355 		int len = bencode(ptr, ent);
356 		target = hasher(buf, len).final();
357 	}
358 	sha1_hash next;
359 	int num_peers;
360 	entry ent;
361 	sha1_hash target;
362 };
363 
announce_immutable_items(node & node,udp::endpoint const * eps,announce_item const * items,int num_items)364 void announce_immutable_items(node& node, udp::endpoint const* eps
365 	, announce_item const* items, int num_items)
366 {
367 	std::string token;
368 	for (int i = 0; i < 1000; ++i)
369 	{
370 		for (int j = 0; j < num_items; ++j)
371 		{
372 			if ((i % items[j].num_peers) == 0) continue;
373 			bdecode_node response;
374 			send_dht_request(node, "get", eps[i], &response
375 				, msg_args().target(items[j].target));
376 
377 			key_desc_t const desc[] =
378 			{
379 				{ "r", bdecode_node::dict_t, 0, key_desc_t::parse_children },
380 					{ "id", bdecode_node::string_t, 20, 0},
381 					{ "token", bdecode_node::string_t, 0, 0},
382 					{ "ip", bdecode_node::string_t, 0, key_desc_t::optional | key_desc_t::last_child},
383 				{ "y", bdecode_node::string_t, 1, 0},
384 			};
385 
386 			bdecode_node parsed[5];
387 			char error_string[200];
388 
389 //			std::printf("msg: %s\n", print_entry(response).c_str());
390 			int ret = verify_message(response, desc, parsed, error_string);
391 			if (ret)
392 			{
393 				TEST_EQUAL(parsed[4].string_value(), "r");
394 				token = parsed[2].string_value().to_string();
395 //				std::printf("got token: %s\n", token.c_str());
396 			}
397 			else
398 			{
399 				std::printf("msg: %s\n", print_entry(response).c_str());
400 				std::printf("   invalid get response: %s\n", error_string);
401 				TEST_ERROR(error_string);
402 			}
403 
404 			if (parsed[3])
405 			{
406 				address_v4::bytes_type b;
407 				memcpy(&b[0], parsed[3].string_ptr(), b.size());
408 				address_v4 addr(b);
409 				TEST_EQUAL(addr, eps[i].address());
410 			}
411 
412 			send_dht_request(node, "put", eps[i], &response
413 				, msg_args()
414 					.token(token)
415 					.target(items[j].target)
416 					.value(items[j].ent));
417 
418 			key_desc_t const desc2[] =
419 			{
420 				{ "y", bdecode_node::string_t, 1, 0 }
421 			};
422 
423 			bdecode_node parsed2[1];
424 			ret = verify_message(response, desc2, parsed2, error_string);
425 			if (ret)
426 			{
427 				if (parsed2[0].string_value() != "r")
428 					std::printf("msg: %s\n", print_entry(response).c_str());
429 
430 				TEST_EQUAL(parsed2[0].string_value(), "r");
431 			}
432 			else
433 			{
434 				std::printf("msg: %s\n", print_entry(response).c_str());
435 				std::printf("   invalid put response: %s\n", error_string);
436 				TEST_ERROR(error_string);
437 			}
438 		}
439 	}
440 
441 	std::set<int> items_num;
442 	for (int j = 0; j < num_items; ++j)
443 	{
444 		bdecode_node response;
445 		send_dht_request(node, "get", eps[j], &response
446 			, msg_args().target(items[j].target));
447 
448 		key_desc_t const desc[] =
449 		{
450 			{ "r", bdecode_node::dict_t, 0, key_desc_t::parse_children },
451 				{ "v", bdecode_node::dict_t, 0, 0},
452 				{ "id", bdecode_node::string_t, 20, key_desc_t::last_child},
453 			{ "y", bdecode_node::string_t, 1, 0},
454 		};
455 
456 		bdecode_node parsed[4];
457 		char error_string[200];
458 
459 		int ret = verify_message(response, desc, parsed, error_string);
460 		if (ret)
461 		{
462 			items_num.insert(items_num.begin(), j);
463 		}
464 	}
465 
466 	// TODO: check to make sure the "best" items are stored
467 	TEST_EQUAL(items_num.size(), 4);
468 }
469 
sum_distance_exp(int s,node_entry const & e,node_id const & ref)470 int sum_distance_exp(int s, node_entry const& e, node_id const& ref)
471 {
472 	return s + distance_exp(e.id, ref);
473 }
474 
475 std::vector<tcp::endpoint> g_got_peers;
476 
get_peers_cb(std::vector<tcp::endpoint> const & peers)477 void get_peers_cb(std::vector<tcp::endpoint> const& peers)
478 {
479 	g_got_peers.insert(g_got_peers.end(), peers.begin(), peers.end());
480 }
481 
482 std::vector<dht::item> g_got_items;
483 dht::item g_put_item;
484 int g_put_count;
485 
get_mutable_item_cb(dht::item const & i,bool a)486 void get_mutable_item_cb(dht::item const& i, bool a)
487 {
488 	if (!a) return;
489 	if (!i.empty())
490 		g_got_items.push_back(i);
491 }
492 
put_mutable_item_data_cb(dht::item & i)493 void put_mutable_item_data_cb(dht::item& i)
494 {
495 	if (!i.empty())
496 		g_got_items.push_back(i);
497 
498 	TEST_CHECK(!g_put_item.empty());
499 	i = g_put_item;
500 	g_put_count++;
501 }
502 
put_mutable_item_cb(dht::item const &,int num,int expect)503 void put_mutable_item_cb(dht::item const&, int num, int expect)
504 {
505 	TEST_EQUAL(num, expect);
506 }
507 
get_immutable_item_cb(dht::item const & i)508 void get_immutable_item_cb(dht::item const& i)
509 {
510 	if (!i.empty())
511 		g_got_items.push_back(i);
512 }
513 
put_immutable_item_cb(int num,int expect)514 void put_immutable_item_cb(int num, int expect)
515 {
516 	TEST_EQUAL(num, expect);
517 }
518 
519 struct obs : dht::dht_observer
520 {
set_external_address__anone716e03d0111::obs521 	void set_external_address(aux::listen_socket_handle const& s, address const& addr
522 		, address const& /*source*/) override
523 	{
524 		s.get()->external_address.cast_vote(addr
525 			, aux::session_interface::source_dht, rand_v4());
526 	}
527 
get_listen_port__anone716e03d0111::obs528 	int get_listen_port(aux::transport, aux::listen_socket_handle const& s) override
529 	{ return s.get()->udp_external_port(); }
530 
get_peers__anone716e03d0111::obs531 	void get_peers(sha1_hash const&) override {}
outgoing_get_peers__anone716e03d0111::obs532 	void outgoing_get_peers(sha1_hash const& /*target*/
533 		, sha1_hash const& /*sent_target*/, udp::endpoint const&) override {}
announce__anone716e03d0111::obs534 	void announce(sha1_hash const&, address const&, int) override {}
535 #ifndef TORRENT_DISABLE_LOGGING
should_log__anone716e03d0111::obs536 	bool should_log(module_t) const override { return true; }
log__anone716e03d0111::obs537 	void log(dht_logger::module_t, char const* fmt, ...) override
538 	{
539 		va_list v;
540 		va_start(v, fmt);
541 		char buf[1024];
542 #ifdef __clang__
543 #pragma clang diagnostic push
544 #pragma clang diagnostic ignored "-Wformat-nonliteral"
545 #endif
546 		std::vsnprintf(buf, sizeof(buf), fmt, v);
547 #ifdef __clang__
548 #pragma clang diagnostic pop
549 #endif
550 		va_end(v);
551 		std::printf("%s\n", buf);
552 		m_log.emplace_back(buf);
553 	}
log_packet__anone716e03d0111::obs554 	void log_packet(message_direction_t, span<char const>
555 		, udp::endpoint const&) override {}
556 #endif
on_dht_request__anone716e03d0111::obs557 	bool on_dht_request(string_view
558 		, dht::msg const&, entry&) override { return false; }
559 
560 	virtual ~obs() = default;
561 
562 #ifndef TORRENT_DISABLE_LOGGING
563 	std::vector<std::string> m_log;
564 #endif
565 };
566 
test_settings()567 dht::settings test_settings()
568 {
569 	dht::settings sett;
570 	sett.max_torrents = 4;
571 	sett.max_dht_items = 4;
572 	sett.enforce_node_id = false;
573 	return sett;
574 }
575 
576 struct dht_test_setup
577 {
dht_test_setup__anone716e03d0111::dht_test_setup578 	explicit dht_test_setup(udp::endpoint src)
579 		: sett(test_settings())
580 		, ls(dummy_listen_socket(src))
581 		, dht_storage(dht_default_storage_constructor(sett))
582 		, source(src)
583 		, dht_node(ls, &s, sett
584 			, node_id(nullptr), &observer, cnt, get_foreign_node_stub, *dht_storage)
585 	{
586 		dht_storage->update_node_ids({node_id::min()});
587 	}
588 
589 	dht::settings sett;
590 	mock_socket s;
591 	std::shared_ptr<aux::listen_socket_t> ls;
592 	obs observer;
593 	counters cnt;
594 	std::unique_ptr<dht_storage_interface> dht_storage;
595 	udp::endpoint source;
596 	dht::node dht_node;
597 	char error_string[200];
598 };
599 
600 dht::key_desc_t const err_desc[] = {
601 	{"y", bdecode_node::string_t, 1, 0},
602 	{"e", bdecode_node::list_t, 2, 0}
603 };
604 
605 dht::key_desc_t const peer1_desc[] = {
606 	{"y", bdecode_node::string_t, 1, 0},
607 	{"r", bdecode_node::dict_t, 0, key_desc_t::parse_children},
608 		{"token", bdecode_node::string_t, 0, 0},
609 		{"id", bdecode_node::string_t, 20, key_desc_t::last_child},
610 };
611 
612 dht::key_desc_t const get_item_desc[] = {
613 	{"y", bdecode_node::string_t, 1, 0},
614 	{"t", bdecode_node::string_t, 2, 0},
615 	{"q", bdecode_node::string_t, 3, 0},
616 	{"a", bdecode_node::dict_t, 0, key_desc_t::parse_children},
617 		{"id", bdecode_node::string_t, 20, 0},
618 		{"target", bdecode_node::string_t, 20, key_desc_t::last_child},
619 };
620 
621 dht::key_desc_t const put_mutable_item_desc[] = {
622 	{"y", bdecode_node::string_t, 1, 0},
623 	{"t", bdecode_node::string_t, 2, 0},
624 	{"q", bdecode_node::string_t, 3, 0},
625 	{"a", bdecode_node::dict_t, 0, key_desc_t::parse_children},
626 		{"id", bdecode_node::string_t, 20, 0},
627 		{"cas", bdecode_node::string_t, 20, key_desc_t::optional},
628 		{"k", bdecode_node::string_t, public_key::len, 0},
629 		{"seq", bdecode_node::int_t, 0, 0},
630 		{"sig", bdecode_node::string_t, signature::len, 0},
631 		{"token", bdecode_node::string_t, 2, 0},
632 		{"v", bdecode_node::none_t, 0, key_desc_t::last_child},
633 };
634 
635 dht::key_desc_t const sample_infohashes_desc[] = {
636 	{"y", bdecode_node::string_t, 1, 0},
637 	{"t", bdecode_node::string_t, 2, 0},
638 	{"q", bdecode_node::string_t, 17, 0},
639 	{"a", bdecode_node::dict_t, 0, key_desc_t::parse_children},
640 		{"id", bdecode_node::string_t, 20, 0},
641 		{"target", bdecode_node::string_t, 20, key_desc_t::last_child},
642 };
643 
print_state(std::ostream & os,routing_table const & table)644 void print_state(std::ostream& os, routing_table const& table)
645 {
646 #define BUFFER_CURSOR_POS &buf[std::size_t(cursor)], buf.size() - std::size_t(cursor)
647 	std::vector<char> buf(2048);
648 	int cursor = 0;
649 
650 	cursor += std::snprintf(BUFFER_CURSOR_POS
651 		, "kademlia routing table state\n"
652 		"bucket_size: %d\n"
653 		"global node count: %" PRId64 "\n"
654 		"node_id: %s\n\n"
655 		"number of nodes per bucket:\n"
656 		, table.bucket_size()
657 		, table.num_global_nodes()
658 		, aux::to_hex(table.id()).c_str());
659 	if (cursor > int(buf.size()) - 500) buf.resize(buf.size() * 3 / 2);
660 
661 	int idx = 0;
662 
663 	for (auto i = table.buckets().begin(), end(table.buckets().end());
664 		i != end; ++i, ++idx)
665 	{
666 		cursor += std::snprintf(BUFFER_CURSOR_POS
667 			, "%2d: ", idx);
668 		for (int k = 0; k < int(i->live_nodes.size()); ++k)
669 			cursor += std::snprintf(BUFFER_CURSOR_POS, "#");
670 		for (int k = 0; k < int(i->replacements.size()); ++k)
671 			cursor += std::snprintf(BUFFER_CURSOR_POS, "-");
672 		cursor += std::snprintf(BUFFER_CURSOR_POS, "\n");
673 
674 		if (cursor > int(buf.size()) - 500) buf.resize(buf.size() * 3 / 2);
675 	}
676 
677 	time_point now = aux::time_now();
678 
679 	cursor += std::snprintf(BUFFER_CURSOR_POS
680 		, "\nnodes:");
681 
682 	int bucket_index = 0;
683 	for (auto i = table.buckets().begin(), end(table.buckets().end());
684 		i != end; ++i, ++bucket_index)
685 	{
686 		cursor += std::snprintf(BUFFER_CURSOR_POS
687 			, "\n=== BUCKET == %d == %d|%d ==== \n"
688 			, bucket_index, int(i->live_nodes.size())
689 			, int(i->replacements.size()));
690 		if (cursor > int(buf.size()) - 500) buf.resize(buf.size() * 3 / 2);
691 
692 		bucket_t nodes = i->live_nodes;
693 
694 		std::sort(nodes.begin(), nodes.end()
695 			, [](node_entry const& lhs, node_entry const& rhs)
696 			{ return lhs.id < rhs.id; }
697 		);
698 
699 		for (auto j = nodes.begin(); j != nodes.end(); ++j)
700 		{
701 			int const bucket_size_limit = table.bucket_limit(bucket_index);
702 			TORRENT_ASSERT_VAL(bucket_size_limit <= 256, bucket_size_limit);
703 			TORRENT_ASSERT_VAL(bucket_size_limit > 0, bucket_size_limit);
704 
705 			bool const last_bucket = bucket_index + 1 == int(table.buckets().size());
706 			int const prefix = classify_prefix(bucket_index, last_bucket
707 				, bucket_size_limit, j->id);
708 
709 			cursor += std::snprintf(BUFFER_CURSOR_POS
710 				, " prefix: %2x id: %s", prefix, aux::to_hex(j->id).c_str());
711 
712 			if (j->rtt == 0xffff)
713 			{
714 				cursor += std::snprintf(BUFFER_CURSOR_POS
715 					, " rtt:     ");
716 			}
717 			else
718 			{
719 				cursor += std::snprintf(BUFFER_CURSOR_POS
720 					, " rtt: %4d", j->rtt);
721 			}
722 
723 			cursor += std::snprintf(BUFFER_CURSOR_POS
724 				, " fail: %3d ping: %d dist: %3d"
725 				, j->fail_count()
726 				, j->pinged()
727 				, distance_exp(table.id(), j->id));
728 
729 			if (j->last_queried == min_time())
730 			{
731 				cursor += std::snprintf(BUFFER_CURSOR_POS
732 					, " query:    ");
733 			}
734 			else
735 			{
736 				cursor += std::snprintf(BUFFER_CURSOR_POS
737 					, " query: %3d", int(total_seconds(now - j->last_queried)));
738 			}
739 
740 			cursor += std::snprintf(BUFFER_CURSOR_POS
741 				, " ip: %s\n", print_endpoint(j->ep()).c_str());
742 			if (cursor > int(buf.size()) - 500) buf.resize(buf.size() * 3 / 2);
743 		}
744 	}
745 
746 	cursor += std::snprintf(BUFFER_CURSOR_POS
747 		, "\nnode spread per bucket:\n");
748 	bucket_index = 0;
749 	for (auto i = table.buckets().begin(), end(table.buckets().end());
750 		i != end; ++i, ++bucket_index)
751 	{
752 		int const bucket_size_limit = table.bucket_limit(bucket_index);
753 		TORRENT_ASSERT_VAL(bucket_size_limit <= 256, bucket_size_limit);
754 		TORRENT_ASSERT_VAL(bucket_size_limit > 0, bucket_size_limit);
755 		std::array<bool, 256> sub_buckets;
756 		sub_buckets.fill(false);
757 
758 		// the last bucket is special, since it hasn't been split yet, it
759 		// includes that top bit as well
760 		bool const last_bucket = bucket_index + 1 == int(table.buckets().size());
761 
762 		for (auto const& e : i->live_nodes)
763 		{
764 			std::size_t const prefix = static_cast<std::size_t>(
765 				classify_prefix(bucket_index, last_bucket, bucket_size_limit, e.id));
766 			sub_buckets[prefix] = true;
767 		}
768 
769 		cursor += std::snprintf(BUFFER_CURSOR_POS, "%2d: [", bucket_index);
770 
771 		for (int j = 0; j < bucket_size_limit; ++j)
772 		{
773 			cursor += std::snprintf(BUFFER_CURSOR_POS
774 				, (sub_buckets[static_cast<std::size_t>(j)] ? "X" : " "));
775 		}
776 		cursor += std::snprintf(BUFFER_CURSOR_POS
777 			, "]\n");
778 		if (cursor > int(buf.size()) - 500) buf.resize(buf.size() * 3 / 2);
779 	}
780 	buf[std::size_t(cursor)] = '\0';
781 	os << &buf[0];
782 #undef BUFFER_CURSOR_POS
783 }
784 
785 } // anonymous namespace
786 
TORRENT_TEST(ping)787 TORRENT_TEST(ping)
788 {
789 	dht_test_setup t(udp::endpoint(rand_v4(), 20));
790 	bdecode_node response;
791 
792 	send_dht_request(t.dht_node, "ping", t.source, &response);
793 
794 	dht::key_desc_t const pong_desc[] = {
795 		{"y", bdecode_node::string_t, 1, 0},
796 		{"t", bdecode_node::string_t, 2, 0},
797 		{"r", bdecode_node::dict_t, 0, key_desc_t::parse_children},
798 			{"id", bdecode_node::string_t, 20, key_desc_t::last_child},
799 	};
800 
801 	bdecode_node pong_keys[4];
802 
803 	std::printf("msg: %s\n", print_entry(response).c_str());
804 	bool ret = dht::verify_message(response, pong_desc, pong_keys, t.error_string);
805 	TEST_CHECK(ret);
806 	if (ret)
807 	{
808 		TEST_CHECK(pong_keys[0].string_value() == "r");
809 		TEST_CHECK(pong_keys[1].string_value() == "10");
810 	}
811 	else
812 	{
813 		std::printf("   invalid ping response: %s\n", t.error_string);
814 	}
815 }
816 
TORRENT_TEST(invalid_message)817 TORRENT_TEST(invalid_message)
818 {
819 	dht_test_setup t(udp::endpoint(rand_v4(), 20));
820 	bdecode_node response;
821 	bdecode_node err_keys[2];
822 
823 	send_dht_request(t.dht_node, "find_node", t.source, &response);
824 
825 	std::printf("msg: %s\n", print_entry(response).c_str());
826 	bool ret = dht::verify_message(response, err_desc, err_keys, t.error_string);
827 	TEST_CHECK(ret);
828 	if (ret)
829 	{
830 		TEST_CHECK(err_keys[0].string_value() == "e");
831 		if (err_keys[1].list_at(0).type() == bdecode_node::int_t
832 			&& err_keys[1].list_at(1).type() == bdecode_node::string_t)
833 		{
834 			TEST_CHECK(err_keys[1].list_at(1).string_value() == "missing 'target' key");
835 		}
836 		else
837 		{
838 			TEST_ERROR("invalid error response");
839 		}
840 	}
841 	else
842 	{
843 		std::printf("   invalid error response: %s\n", t.error_string);
844 	}
845 }
846 
TORRENT_TEST(node_id_testng)847 TORRENT_TEST(node_id_testng)
848 {
849 	node_id rnd = generate_secret_id();
850 	TEST_CHECK(verify_secret_id(rnd));
851 
852 	rnd[19] ^= 0x55;
853 	TEST_CHECK(!verify_secret_id(rnd));
854 
855 	rnd = generate_random_id();
856 	make_id_secret(rnd);
857 	TEST_CHECK(verify_secret_id(rnd));
858 }
859 
TORRENT_TEST(get_peers_announce)860 TORRENT_TEST(get_peers_announce)
861 {
862 	dht_test_setup t(udp::endpoint(rand_v4(), 20));
863 	bdecode_node response;
864 
865 	send_dht_request(t.dht_node, "get_peers", t.source, &response
866 		, msg_args().info_hash("01010101010101010101"));
867 
868 	bdecode_node peer1_keys[4];
869 
870 	std::string token;
871 	std::printf("msg: %s\n", print_entry(response).c_str());
872 	bool ret = dht::verify_message(response, peer1_desc, peer1_keys, t.error_string);
873 	TEST_CHECK(ret);
874 	if (ret)
875 	{
876 		TEST_CHECK(peer1_keys[0].string_value() == "r");
877 		token = peer1_keys[2].string_value().to_string();
878 //		std::printf("got token: %s\n", token.c_str());
879 	}
880 	else
881 	{
882 		std::printf("msg: %s\n", print_entry(response).c_str());
883 		std::printf("   invalid get_peers response: %s\n", t.error_string);
884 	}
885 
886 	send_dht_request(t.dht_node, "announce_peer", t.source, &response
887 		, msg_args()
888 			.info_hash("01010101010101010101")
889 			.name("test")
890 			.token(token)
891 			.port(8080));
892 
893 	dht::key_desc_t const ann_desc[] = {
894 		{"y", bdecode_node::string_t, 1, 0},
895 		{"r", bdecode_node::dict_t, 0, key_desc_t::parse_children},
896 			{"id", bdecode_node::string_t, 20, key_desc_t::last_child},
897 	};
898 
899 	bdecode_node ann_keys[3];
900 
901 	std::printf("msg: %s\n", print_entry(response).c_str());
902 	ret = dht::verify_message(response, ann_desc, ann_keys, t.error_string);
903 	TEST_CHECK(ret);
904 	if (ret)
905 	{
906 		TEST_CHECK(ann_keys[0].string_value() == "r");
907 	}
908 	else
909 	{
910 		std::printf("   invalid announce response:\n");
911 		TEST_ERROR(t.error_string);
912 	}
913 }
914 
915 namespace {
916 
test_scrape(address (& rand_addr)())917 void test_scrape(address(&rand_addr)())
918 {
919 	dht_test_setup t(udp::endpoint(rand_addr(), 20));
920 	bdecode_node response;
921 
922 	init_rand_address();
923 
924 	// announce from 100 random IPs and make sure scrape works
925 	// 50 downloaders and 50 seeds
926 	for (int i = 0; i < 100; ++i)
927 	{
928 		t.source = udp::endpoint(rand_addr(), 6000);
929 		send_dht_request(t.dht_node, "get_peers", t.source, &response
930 			, msg_args().info_hash("01010101010101010101"));
931 
932 		bdecode_node peer1_keys[4];
933 		bool ret = dht::verify_message(response, peer1_desc, peer1_keys, t.error_string);
934 
935 		std::string token;
936 		if (ret)
937 		{
938 			TEST_CHECK(peer1_keys[0].string_value() == "r");
939 			token = peer1_keys[2].string_value().to_string();
940 		}
941 		else
942 		{
943 			std::printf("msg: %s\n", print_entry(response).c_str());
944 			std::printf("   invalid get_peers response: %s\n", t.error_string);
945 		}
946 		response.clear();
947 		send_dht_request(t.dht_node, "announce_peer", t.source, &response
948 			, msg_args()
949 				.info_hash("01010101010101010101")
950 				.name("test")
951 				.token(token)
952 				.port(8080)
953 				.seed(i >= 50));
954 
955 		response.clear();
956 	}
957 
958 	// ====== get_peers ======
959 
960 	send_dht_request(t.dht_node, "get_peers", t.source, &response
961 		, msg_args().info_hash("01010101010101010101").scrape(true));
962 
963 	dht::key_desc_t const peer2_desc[] = {
964 		{"y", bdecode_node::string_t, 1, 0},
965 		{"r", bdecode_node::dict_t, 0, key_desc_t::parse_children},
966 			{"BFpe", bdecode_node::string_t, 256, 0},
967 			{"BFsd", bdecode_node::string_t, 256, 0},
968 			{"id", bdecode_node::string_t, 20, key_desc_t::last_child},
969 	};
970 
971 	bdecode_node peer2_keys[5];
972 
973 	std::printf("msg: %s\n", print_entry(response).c_str());
974 	bool ret = dht::verify_message(response, peer2_desc, peer2_keys, t.error_string);
975 	TEST_CHECK(ret);
976 	if (ret)
977 	{
978 		TEST_CHECK(peer2_keys[0].string_value() == "r");
979 		TEST_EQUAL(peer2_keys[1].dict_find_string_value("n"), "test");
980 
981 		bloom_filter<256> downloaders;
982 		bloom_filter<256> seeds;
983 		downloaders.from_string(peer2_keys[2].string_ptr());
984 		seeds.from_string(peer2_keys[3].string_ptr());
985 
986 		std::printf("seeds: %f\n", double(seeds.size()));
987 		std::printf("downloaders: %f\n", double(downloaders.size()));
988 
989 		TEST_CHECK(std::abs(seeds.size() - 50.f) <= 3.f);
990 		TEST_CHECK(std::abs(downloaders.size() - 50.f) <= 3.f);
991 	}
992 	else
993 	{
994 		std::printf("invalid get_peers response:\n");
995 		TEST_ERROR(t.error_string);
996 	}
997 }
998 
999 } // anonymous namespace
1000 
TORRENT_TEST(scrape_v4)1001 TORRENT_TEST(scrape_v4)
1002 {
1003 	test_scrape(rand_v4);
1004 }
1005 
TORRENT_TEST(scrape_v6)1006 TORRENT_TEST(scrape_v6)
1007 {
1008 	if (supports_ipv6())
1009 		test_scrape(rand_v6);
1010 }
1011 
1012 namespace {
1013 
test_id_enforcement(address (& rand_addr)())1014 void test_id_enforcement(address(&rand_addr)())
1015 {
1016 	dht_test_setup t(udp::endpoint(rand_addr(), 20));
1017 	bdecode_node response;
1018 
1019 	// enable node_id enforcement
1020 	t.sett.enforce_node_id = true;
1021 
1022 	node_id nid;
1023 	if (is_v4(t.source))
1024 	{
1025 		// this is one of the test vectors from:
1026 		// http://libtorrent.org/dht_sec.html
1027 		t.source = udp::endpoint(addr("124.31.75.21"), 1);
1028 		nid = to_hash("5fbfbff10c5d6a4ec8a88e4c6ab4c28b95eee401");
1029 	}
1030 	else
1031 	{
1032 		t.source = udp::endpoint(addr("2001:b829:2123:be84:e16c:d6ae:5290:49f1"), 1);
1033 		nid = to_hash("0a8ad123be84e16cd6ae529049f1f1bbe9ebb304");
1034 	}
1035 
1036 	// verify that we reject invalid node IDs
1037 	// this is now an invalid node-id for 'source'
1038 	nid[0] = 0x18;
1039 	// the test nodes don't get pinged so they will only get as far
1040 	// as the replacement bucket
1041 	int nodes_num = std::get<1>(t.dht_node.size());
1042 	send_dht_request(t.dht_node, "find_node", t.source, &response
1043 		, msg_args()
1044 			.target(sha1_hash("0101010101010101010101010101010101010101"))
1045 			.nid(nid));
1046 
1047 	bdecode_node err_keys[2];
1048 	bool ret = dht::verify_message(response, err_desc, err_keys, t.error_string);
1049 	TEST_CHECK(ret);
1050 	if (ret)
1051 	{
1052 		TEST_CHECK(err_keys[0].string_value() == "e");
1053 		if (err_keys[1].list_at(0).type() == bdecode_node::int_t
1054 			&& err_keys[1].list_at(1).type() == bdecode_node::string_t)
1055 		{
1056 			TEST_CHECK(err_keys[1].list_at(1).string_value() == "invalid node ID");
1057 		}
1058 		else
1059 		{
1060 			std::printf("msg: %s\n", print_entry(response).c_str());
1061 			TEST_ERROR("invalid error response");
1062 		}
1063 	}
1064 	else
1065 	{
1066 		std::printf("msg: %s\n", print_entry(response).c_str());
1067 		std::printf("   invalid error response: %s\n", t.error_string);
1068 	}
1069 
1070 	// a node with invalid node-id shouldn't be added to routing table.
1071 	TEST_EQUAL(std::get<1>(t.dht_node.size()), nodes_num);
1072 
1073 	// now the node-id is valid.
1074 	if (is_v4(t.source))
1075 		nid[0] = 0x5f;
1076 	else
1077 		nid[0] = 0x0a;
1078 	send_dht_request(t.dht_node, "find_node", t.source, &response
1079 		, msg_args()
1080 			.target(sha1_hash("0101010101010101010101010101010101010101"))
1081 			.nid(nid));
1082 
1083 	dht::key_desc_t const nodes_desc[] = {
1084 		{"y", bdecode_node::string_t, 1, 0},
1085 		{"r", bdecode_node::dict_t, 0, key_desc_t::parse_children},
1086 			{"id", bdecode_node::string_t, 20, key_desc_t::last_child},
1087 	};
1088 
1089 	bdecode_node nodes_keys[3];
1090 
1091 	std::printf("msg: %s\n", print_entry(response).c_str());
1092 	ret = dht::verify_message(response, nodes_desc, nodes_keys, t.error_string);
1093 	TEST_CHECK(ret);
1094 	if (ret)
1095 	{
1096 		TEST_CHECK(nodes_keys[0].string_value() == "r");
1097 	}
1098 	else
1099 	{
1100 		std::printf("msg: %s\n", print_entry(response).c_str());
1101 		std::printf("   invalid error response: %s\n", t.error_string);
1102 	}
1103 	// node with valid node-id should be added to routing table.
1104 	TEST_EQUAL(std::get<1>(t.dht_node.size()), nodes_num + 1);
1105 }
1106 
1107 } // anonymous namespace
1108 
TORRENT_TEST(id_enforcement_v4)1109 TORRENT_TEST(id_enforcement_v4)
1110 {
1111 	test_id_enforcement(rand_v4);
1112 }
1113 
TORRENT_TEST(id_enforcement_v6)1114 TORRENT_TEST(id_enforcement_v6)
1115 {
1116 	if (supports_ipv6())
1117 		test_id_enforcement(rand_v6);
1118 }
1119 
TORRENT_TEST(bloom_filter)1120 TORRENT_TEST(bloom_filter)
1121 {
1122 	bloom_filter<256> test;
1123 	for (int i = 0; i < 256; ++i)
1124 	{
1125 		char adr[50];
1126 		std::snprintf(adr, sizeof(adr), "192.0.2.%d", i);
1127 		address a = addr(adr);
1128 		sha1_hash const iphash = hash_address(a);
1129 		test.set(iphash);
1130 	}
1131 
1132 	if (supports_ipv6())
1133 	{
1134 		for (int i = 0; i < 0x3E8; ++i)
1135 		{
1136 			char adr[50];
1137 			std::snprintf(adr, sizeof(adr), "2001:db8::%x", i);
1138 			address a = addr(adr);
1139 			sha1_hash const iphash = hash_address(a);
1140 			test.set(iphash);
1141 		}
1142 	}
1143 
1144 	// these are test vectors from BEP 33
1145 	// http://www.bittorrent.org/beps/bep_0033.html
1146 	std::printf("test.size: %f\n", double(test.size()));
1147 	std::string const bf_str = test.to_string();
1148 	std::printf("%s\n", aux::to_hex(bf_str).c_str());
1149 	if (supports_ipv6())
1150 	{
1151 		TEST_CHECK(std::abs(double(test.size()) - 1224.93) < 0.001);
1152 		TEST_CHECK(aux::to_hex(bf_str) ==
1153 			"f6c3f5eaa07ffd91bde89f777f26fb2b"
1154 			"ff37bdb8fb2bbaa2fd3ddde7bacfff75"
1155 			"ee7ccbaefe5eedb1fbfaff67f6abff5e"
1156 			"43ddbca3fd9b9ffdf4ffd3e9dff12d1b"
1157 			"df59db53dbe9fa5b7ff3b8fdfcde1afb"
1158 			"8bedd7be2f3ee71ebbbfe93bcdeefe14"
1159 			"8246c2bc5dbff7e7efdcf24fd8dc7adf"
1160 			"fd8fffdfddfff7a4bbeedf5cb95ce81f"
1161 			"c7fcff1ff4ffffdfe5f7fdcbb7fd79b3"
1162 			"fa1fc77bfe07fff905b7b7ffc7fefeff"
1163 			"e0b8370bb0cd3f5b7f2bd93feb4386cf"
1164 			"dd6f7fd5bfaf2e9ebffffeecd67adbf7"
1165 			"c67f17efd5d75eba6ffeba7fff47a91e"
1166 			"b1bfbb53e8abfb5762abe8ff237279bf"
1167 			"efbfeef5ffc5febfdfe5adffadfee1fb"
1168 			"737ffffbfd9f6aeffeee76b6fd8f72ef");
1169 	}
1170 	else
1171 	{
1172 		TEST_CHECK(std::abs(double(test.size()) - 257.854) < 0.001);
1173 		TEST_CHECK(aux::to_hex(bf_str) ==
1174 			"24c0004020043000102012743e004800"
1175 			"37110820422110008000c0e302854835"
1176 			"a05401a4045021302a306c0600018810"
1177 			"02d8a0a3a8001901b40a800900310008"
1178 			"d2108110c2496a0028700010d804188b"
1179 			"01415200082004088026411104a80404"
1180 			"8002002000080680828c400080cc4002"
1181 			"0c042c0494447280928041402104080d"
1182 			"4240040414a41f0205654800b0811830"
1183 			"d2020042b002c5800004a71d0204804a"
1184 			"0028120a004c10017801490b83400404"
1185 			"4106005421000c86900a002050020351"
1186 			"0060144e900100924a1018141a028012"
1187 			"913f0041802250042280481200002004"
1188 			"430804210101c08111c1080100108000"
1189 			"2038008211004266848606b035001048");
1190 	}
1191 }
1192 
1193 namespace {
1194 	announce_item const items[] =
1195 	{
1196 		{ generate_next(), 1 },
1197 		{ generate_next(), 2 },
1198 		{ generate_next(), 3 },
1199 		{ generate_next(), 4 },
1200 		{ generate_next(), 5 },
1201 		{ generate_next(), 6 },
1202 		{ generate_next(), 7 },
1203 		{ generate_next(), 8 }
1204 	};
1205 
build_nodes()1206 	lt::aux::array<node_entry, 8> build_nodes()
1207 	{
1208 		return lt::aux::array<node_entry, 8>(
1209 			std::array<node_entry, 8> {
1210 			{ { items[0].target, udp::endpoint(addr4("1.1.1.1"), 1231), 10, true}
1211 			, { items[1].target, udp::endpoint(addr4("2.2.2.2"), 1232), 10, true}
1212 			, { items[2].target, udp::endpoint(addr4("3.3.3.3"), 1233), 10, true}
1213 			, { items[3].target, udp::endpoint(addr4("4.4.4.4"), 1234), 10, true}
1214 			, { items[4].target, udp::endpoint(addr4("5.5.5.5"), 1235), 10, true}
1215 			, { items[5].target, udp::endpoint(addr4("6.6.6.6"), 1236), 10, true}
1216 			, { items[6].target, udp::endpoint(addr4("7.7.7.7"), 1237), 10, true}
1217 			, { items[7].target, udp::endpoint(addr4("8.8.8.8"), 1238), 10, true} }
1218 		});
1219 	}
1220 
build_nodes(sha1_hash target)1221 	lt::aux::array<node_entry, 9> build_nodes(sha1_hash target)
1222 	{
1223 		return lt::aux::array<node_entry, 9>(
1224 			std::array<node_entry, 9> {
1225 			{ { target, udp::endpoint(addr4("1.1.1.1"), 1231), 10, true}
1226 			, { target, udp::endpoint(addr4("2.2.2.2"), 1232), 10, true}
1227 			, { target, udp::endpoint(addr4("3.3.3.3"), 1233), 10, true}
1228 			, { target, udp::endpoint(addr4("4.4.4.4"), 1234), 10, true}
1229 			, { target, udp::endpoint(addr4("5.5.5.5"), 1235), 10, true}
1230 			, { target, udp::endpoint(addr4("6.6.6.6"), 1236), 10, true}
1231 			, { target, udp::endpoint(addr4("7.7.7.7"), 1237), 10, true}
1232 			, { target, udp::endpoint(addr4("8.8.8.8"), 1238), 10, true}
1233 			, { target, udp::endpoint(addr4("9.9.9.9"), 1239), 10, true} }
1234 		});
1235 	}
1236 
1237 span<char const> const empty_salt;
1238 
1239 // TODO: 3 split this up into smaller tests
test_put(address (& rand_addr)())1240 void test_put(address(&rand_addr)())
1241 {
1242 	dht_test_setup t(udp::endpoint(rand_addr(), 20));
1243 
1244 	bdecode_node response;
1245 	bool ret;
1246 
1247 	// ====== put ======
1248 
1249 	init_rand_address();
1250 	udp::endpoint eps[1000];
1251 	for (int i = 0; i < 1000; ++i)
1252 		eps[i] = udp::endpoint(rand_addr(), (rand() % 16534) + 1);
1253 
1254 	announce_immutable_items(t.dht_node, eps, items, sizeof(items)/sizeof(items[0]));
1255 
1256 	key_desc_t const desc2[] =
1257 	{
1258 		{ "y", bdecode_node::string_t, 1, 0 }
1259 	};
1260 
1261 	bdecode_node desc2_keys[1];
1262 
1263 	key_desc_t const desc_error[] =
1264 	{
1265 		{ "e", bdecode_node::list_t, 2, 0 },
1266 		{ "y", bdecode_node::string_t, 1, 0},
1267 	};
1268 
1269 	bdecode_node desc_error_keys[2];
1270 
1271 	// ==== get / put mutable items ===
1272 
1273 	span<char const> itemv;
1274 
1275 	signature sig;
1276 	char buffer[1200];
1277 	sequence_number seq(4);
1278 	public_key pk;
1279 	secret_key sk;
1280 	get_test_keypair(pk, sk);
1281 
1282 	// TODO: 4 pass in the actual salt as a parameter
1283 	for (int with_salt = 0; with_salt < 2; ++with_salt)
1284 	{
1285 		seq = sequence_number(4);
1286 		std::printf("\nTEST GET/PUT%s \ngenerating ed25519 keys\n\n"
1287 			, with_salt ? " with-salt" : " no-salt");
1288 		std::array<char, 32> seed = ed25519_create_seed();
1289 
1290 		std::tie(pk, sk) = ed25519_create_keypair(seed);
1291 		std::printf("pub: %s priv: %s\n"
1292 			, aux::to_hex(pk.bytes).c_str()
1293 			, aux::to_hex(sk.bytes).c_str());
1294 
1295 		std::string salt;
1296 		if (with_salt) salt = "foobar";
1297 
1298 		hasher h(pk.bytes);
1299 		if (with_salt) h.update(salt);
1300 		sha1_hash target_id = h.final();
1301 
1302 		std::printf("target_id: %s\n"
1303 			, aux::to_hex(target_id).c_str());
1304 
1305 		send_dht_request(t.dht_node, "get", t.source, &response
1306 			, msg_args().target(target_id));
1307 
1308 		key_desc_t const desc[] =
1309 		{
1310 			{ "r", bdecode_node::dict_t, 0, key_desc_t::parse_children },
1311 			{ "id", bdecode_node::string_t, 20, 0},
1312 			{ "token", bdecode_node::string_t, 0, 0},
1313 			{ "ip", bdecode_node::string_t, 0, key_desc_t::optional | key_desc_t::last_child},
1314 			{ "y", bdecode_node::string_t, 1, 0},
1315 		};
1316 
1317 		bdecode_node desc_keys[5];
1318 
1319 		ret = verify_message(response, desc, desc_keys, t.error_string);
1320 		std::string token;
1321 		if (ret)
1322 		{
1323 			TEST_EQUAL(desc_keys[4].string_value(), "r");
1324 			token = desc_keys[2].string_value().to_string();
1325 			std::printf("get response: %s\n"
1326 				, print_entry(response).c_str());
1327 			std::printf("got token: %s\n", aux::to_hex(token).c_str());
1328 		}
1329 		else
1330 		{
1331 			std::printf("msg: %s\n", print_entry(response).c_str());
1332 			std::printf("   invalid get response: %s\n%s\n"
1333 				, t.error_string, print_entry(response).c_str());
1334 			TEST_ERROR(t.error_string);
1335 		}
1336 
1337 		itemv = span<char const>(buffer, bencode(buffer, items[0].ent));
1338 		sig = sign_mutable_item(itemv, salt, seq, pk, sk);
1339 		TEST_EQUAL(verify_mutable_item(itemv, salt, seq, pk, sig), true);
1340 
1341 		send_dht_request(t.dht_node, "put", t.source, &response
1342 			, msg_args()
1343 				.token(token)
1344 				.value(items[0].ent)
1345 				.key(pk)
1346 				.sig(sig)
1347 				.seq(seq)
1348 				.salt(salt));
1349 
1350 		ret = verify_message(response, desc2, desc2_keys, t.error_string);
1351 		if (ret)
1352 		{
1353 			std::printf("put response: %s\n"
1354 				, print_entry(response).c_str());
1355 			TEST_EQUAL(desc2_keys[0].string_value(), "r");
1356 		}
1357 		else
1358 		{
1359 			std::printf("   invalid put response: %s\n%s\n"
1360 				, t.error_string, print_entry(response).c_str());
1361 			TEST_ERROR(t.error_string);
1362 		}
1363 
1364 		send_dht_request(t.dht_node, "get", t.source, &response
1365 			, msg_args().target(target_id));
1366 
1367 		std::printf("target_id: %s\n"
1368 			, aux::to_hex(target_id).c_str());
1369 
1370 		key_desc_t const desc3[] =
1371 		{
1372 			{ "r", bdecode_node::dict_t, 0, key_desc_t::parse_children },
1373 				{ "id", bdecode_node::string_t, 20, 0},
1374 				{ "v", bdecode_node::none_t, 0, 0},
1375 				{ "seq", bdecode_node::int_t, 0, 0},
1376 				{ "sig", bdecode_node::string_t, 0, 0},
1377 				{ "ip", bdecode_node::string_t, 0, key_desc_t::optional | key_desc_t::last_child},
1378 			{ "y", bdecode_node::string_t, 1, 0},
1379 		};
1380 
1381 		bdecode_node desc3_keys[7];
1382 
1383 		ret = verify_message(response, desc3, desc3_keys, t.error_string);
1384 		if (ret == 0)
1385 		{
1386 			std::printf("msg: %s\n", print_entry(response).c_str());
1387 			std::printf("   invalid get response: %s\n%s\n"
1388 				, t.error_string, print_entry(response).c_str());
1389 			TEST_ERROR(t.error_string);
1390 		}
1391 		else
1392 		{
1393 			std::printf("get response: %s\n"
1394 				, print_entry(response).c_str());
1395 			char value[1020];
1396 			char* ptr = value;
1397 			int const value_len = bencode(ptr, items[0].ent);
1398 			TEST_EQUAL(value_len, int(desc3_keys[2].data_section().size()));
1399 			TEST_CHECK(std::memcmp(desc3_keys[2].data_section().data(), value, std::size_t(value_len)) == 0);
1400 
1401 			TEST_EQUAL(int(seq.value), desc3_keys[3].int_value());
1402 		}
1403 
1404 		// also test that invalid signatures fail!
1405 
1406 		itemv = span<char const>(buffer, bencode(buffer, items[0].ent));
1407 		sig = sign_mutable_item(itemv, salt, seq, pk, sk);
1408 		TEST_EQUAL(verify_mutable_item(itemv, salt, seq, pk, sig), 1);
1409 		// break the signature
1410 		sig.bytes[2] ^= 0xaa;
1411 
1412 		std::printf("PUT broken signature\n");
1413 
1414 		TEST_CHECK(verify_mutable_item(itemv, salt, seq, pk, sig) != 1);
1415 
1416 		send_dht_request(t.dht_node, "put", t.source, &response
1417 			, msg_args()
1418 				.token(token)
1419 				.value(items[0].ent)
1420 				.key(pk)
1421 				.sig(sig)
1422 				.seq(seq)
1423 				.salt(salt));
1424 
1425 		ret = verify_message(response, desc_error, desc_error_keys, t.error_string);
1426 		if (ret)
1427 		{
1428 			std::printf("put response: %s\n", print_entry(response).c_str());
1429 			TEST_EQUAL(desc_error_keys[1].string_value(), "e");
1430 			// 206 is the code for invalid signature
1431 			TEST_EQUAL(desc_error_keys[0].list_int_value_at(0), 206);
1432 		}
1433 		else
1434 		{
1435 			std::printf("   invalid put response: %s\n%s\n"
1436 				, t.error_string, print_entry(response).c_str());
1437 			TEST_ERROR(t.error_string);
1438 		}
1439 
1440 		// === test conditional get ===
1441 
1442 		send_dht_request(t.dht_node, "get", t.source, &response
1443 			, msg_args().target(target_id).seq(prev_seq(seq)));
1444 
1445 		{
1446 			bdecode_node const r = response.dict_find_dict("r");
1447 			TEST_CHECK(r.dict_find("v"));
1448 			TEST_CHECK(r.dict_find("k"));
1449 			TEST_CHECK(r.dict_find("sig"));
1450 		}
1451 
1452 		send_dht_request(t.dht_node, "get", t.source, &response
1453 			, msg_args().target(target_id).seq(seq));
1454 
1455 		{
1456 			bdecode_node r = response.dict_find_dict("r");
1457 			TEST_CHECK(!r.dict_find("v"));
1458 			TEST_CHECK(!r.dict_find("k"));
1459 			TEST_CHECK(!r.dict_find("sig"));
1460 		}
1461 
1462 		// === test CAS put ===
1463 
1464 		// this is the sequence number we expect to be there
1465 		sequence_number cas = seq;
1466 
1467 		// increment sequence number
1468 		seq = next_seq(seq);
1469 		// put item 1
1470 		itemv = span<char const>(buffer, bencode(buffer, items[1].ent));
1471 		sig = sign_mutable_item(itemv, salt, seq, pk, sk);
1472 		TEST_EQUAL(verify_mutable_item(itemv, salt, seq, pk, sig), 1);
1473 
1474 		TEST_CHECK(item_target_id(salt, pk) == target_id);
1475 
1476 		std::printf("PUT CAS 1\n");
1477 
1478 		send_dht_request(t.dht_node, "put", t.source, &response
1479 			, msg_args()
1480 				.token(token)
1481 				.value(items[1].ent)
1482 				.key(pk)
1483 				.sig(sig)
1484 				.seq(seq)
1485 				.cas(cas)
1486 				.salt(salt));
1487 
1488 		ret = verify_message(response, desc2, desc2_keys, t.error_string);
1489 		if (ret)
1490 		{
1491 			std::printf("put response: %s\n"
1492 				, print_entry(response).c_str());
1493 			TEST_EQUAL(desc2_keys[0].string_value(), "r");
1494 		}
1495 		else
1496 		{
1497 			std::printf("   invalid put response: %s\n%s\n"
1498 				, t.error_string, print_entry(response).c_str());
1499 			TEST_ERROR(t.error_string);
1500 		}
1501 
1502 		std::printf("PUT CAS 2\n");
1503 
1504 		// put the same message again. This should fail because the
1505 		// CAS hash is outdated, it's not the hash of the value that's
1506 		// stored anymore
1507 		send_dht_request(t.dht_node, "put", t.source, &response
1508 			, msg_args()
1509 				.token(token)
1510 				.value(items[1].ent)
1511 				.key(pk)
1512 				.sig(sig)
1513 				.seq(seq)
1514 				.cas(cas)
1515 				.salt(salt));
1516 
1517 		ret = verify_message(response, desc_error, desc_error_keys, t.error_string);
1518 		if (ret)
1519 		{
1520 			std::printf("put response: %s\n"
1521 				, print_entry(response).c_str());
1522 			TEST_EQUAL(desc_error_keys[1].string_value(), "e");
1523 			// 301 is the error code for CAS hash mismatch
1524 			TEST_EQUAL(desc_error_keys[0].list_int_value_at(0), 301);
1525 		}
1526 		else
1527 		{
1528 			std::printf("   invalid put response: %s\n%s\nExpected failure 301 (CAS hash mismatch)\n"
1529 				, t.error_string, print_entry(response).c_str());
1530 			TEST_ERROR(t.error_string);
1531 		}
1532 	}
1533 }
1534 
1535 } // anonymous namespace
1536 
TORRENT_TEST(put_v4)1537 TORRENT_TEST(put_v4)
1538 {
1539 	test_put(rand_v4);
1540 }
1541 
TORRENT_TEST(put_v6)1542 TORRENT_TEST(put_v6)
1543 {
1544 	if (supports_ipv6())
1545 		test_put(rand_v6);
1546 }
1547 
1548 namespace {
1549 
test_routing_table(address (& rand_addr)())1550 void test_routing_table(address(&rand_addr)())
1551 {
1552 	init_rand_address();
1553 
1554 	dht_test_setup t(udp::endpoint(rand_addr(), 20));
1555 	bdecode_node response;
1556 
1557 	// test kademlia routing table
1558 	dht::settings s;
1559 	s.extended_routing_table = false;
1560 	//	s.restrict_routing_ips = false;
1561 	node_id const nid = to_hash("3123456789abcdef01232456789abcdef0123456");
1562 	const int bucket_size = 8;
1563 	dht::routing_table table(nid, t.source.protocol(), bucket_size, s, &t.observer);
1564 	TEST_EQUAL(std::get<0>(table.size()), 0);
1565 
1566 	address node_addr;
1567 	address node_near_addr;
1568 	if (is_v6(t.source))
1569 	{
1570 		node_addr = addr6("2001:1111:1111:1111:1111:1111:1111:1111");
1571 		node_near_addr = addr6("2001:1111:1111:1111:eeee:eeee:eeee:eeee");
1572 	}
1573 	else
1574 	{
1575 		node_addr = addr4("4.4.4.4");
1576 		node_near_addr = addr4("4.4.4.5");
1577 	}
1578 
1579 	// test a node with the same IP:port changing ID
1580 	node_id const tmp = generate_id_impl(node_addr, 1);
1581 	table.node_seen(tmp, udp::endpoint(node_addr, 4), 10);
1582 
1583 	std::vector<node_entry> nodes;
1584 	table.find_node(nid, nodes, 0, 10);
1585 	TEST_EQUAL(table.bucket_size(0), 1);
1586 	TEST_EQUAL(std::get<0>(table.size()), 1);
1587 	TEST_EQUAL(nodes.size(), 1);
1588 	if (!nodes.empty())
1589 	{
1590 		TEST_EQUAL(nodes[0].id, tmp);
1591 		TEST_EQUAL(nodes[0].addr(), node_addr);
1592 		TEST_EQUAL(nodes[0].port(), 4);
1593 		TEST_EQUAL(nodes[0].timeout_count, 0);
1594 	}
1595 
1596 	// set timeout_count to 1
1597 	table.node_failed(tmp, udp::endpoint(node_addr, 4));
1598 
1599 	nodes.clear();
1600 	table.for_each_node(std::bind(node_push_back, &nodes, _1), nullptr);
1601 	TEST_EQUAL(nodes.size(), 1);
1602 	if (!nodes.empty())
1603 	{
1604 		TEST_EQUAL(nodes[0].id, tmp);
1605 		TEST_EQUAL(nodes[0].addr(), node_addr);
1606 		TEST_EQUAL(nodes[0].port(), 4);
1607 		TEST_EQUAL(nodes[0].timeout_count, 1);
1608 	}
1609 
1610 	// add the exact same node again, it should set the timeout_count to 0
1611 	table.node_seen(tmp, udp::endpoint(node_addr, 4), 10);
1612 	nodes.clear();
1613 	table.for_each_node(std::bind(node_push_back, &nodes, _1), nullptr);
1614 	TEST_EQUAL(nodes.size(), 1);
1615 	if (!nodes.empty())
1616 	{
1617 		TEST_EQUAL(nodes[0].id, tmp);
1618 		TEST_EQUAL(nodes[0].addr(), node_addr);
1619 		TEST_EQUAL(nodes[0].port(), 4);
1620 		TEST_EQUAL(nodes[0].timeout_count, 0);
1621 	}
1622 
1623 	// test adding the same node ID again with a different IP (should be ignored)
1624 	table.node_seen(tmp, udp::endpoint(node_addr, 5), 10);
1625 	table.find_node(nid, nodes, 0, 10);
1626 	TEST_EQUAL(table.bucket_size(0), 1);
1627 	if (!nodes.empty())
1628 	{
1629 		TEST_EQUAL(nodes[0].id, tmp);
1630 		TEST_EQUAL(nodes[0].addr(), node_addr);
1631 		TEST_EQUAL(nodes[0].port(), 4);
1632 	}
1633 
1634 	// test adding a node that ends up in the same bucket with an IP
1635 	// very close to the current one (should be ignored)
1636 	// if restrict_routing_ips == true
1637 	table.node_seen(tmp, udp::endpoint(node_near_addr, 5), 10);
1638 	table.find_node(nid, nodes, 0, 10);
1639 	TEST_EQUAL(table.bucket_size(0), 1);
1640 	if (!nodes.empty())
1641 	{
1642 		TEST_EQUAL(nodes[0].id, tmp);
1643 		TEST_EQUAL(nodes[0].addr(), node_addr);
1644 		TEST_EQUAL(nodes[0].port(), 4);
1645 	}
1646 
1647 	// test adding the same IP:port again with a new node ID (should remove the node)
1648 	{
1649 		auto const id = generate_id_impl(node_addr, 2);
1650 		table.node_seen(id, udp::endpoint(node_addr, 4), 10);
1651 		table.find_node(id, nodes, 0, 10);
1652 	}
1653 	TEST_EQUAL(table.bucket_size(0), 0);
1654 	TEST_EQUAL(nodes.size(), 0);
1655 
1656 	s.restrict_routing_ips = false;
1657 
1658 	{
1659 		auto const ep = rand_udp_ep(rand_addr);
1660 		auto const id = generate_id_impl(ep.address(), 2);
1661 		table.node_seen(id, ep, 10);
1662 	}
1663 
1664 	nodes.clear();
1665 	for (int i = 0; i < 10000; ++i)
1666 	{
1667 		auto const ep = rand_udp_ep(rand_addr);
1668 		auto const id = generate_id_impl(ep.address(), 6);
1669 		table.node_seen(id, ep, 20 + (id[19] & 0xff));
1670 	}
1671 	std::printf("active buckets: %d\n", table.num_active_buckets());
1672 	TEST_CHECK(table.num_active_buckets() == 11
1673 		|| table.num_active_buckets() == 12);
1674 	TEST_CHECK(std::get<0>(table.size()) >= bucket_size * 10);
1675 	//TODO: 2 test num_global_nodes
1676 	//TODO: 2 test need_refresh
1677 
1678 	print_state(std::cout, table);
1679 
1680 	table.for_each_node(std::bind(node_push_back, &nodes, _1), nullptr);
1681 
1682 	std::printf("nodes: %d\n", int(nodes.size()));
1683 
1684 	std::vector<node_entry> temp;
1685 
1686 	{
1687 		node_id const id = generate_random_id();
1688 		table.find_node(id, temp, 0, int(nodes.size()) * 2);
1689 		std::printf("returned-all: %d\n", int(temp.size()));
1690 		TEST_EQUAL(temp.size(), nodes.size());
1691 	}
1692 
1693 	// This makes sure enough of the nodes returned are actually
1694 	// part of the closest nodes
1695 	std::set<node_id> duplicates;
1696 
1697 	const int reps = 50;
1698 
1699 	for (int r = 0; r < reps; ++r)
1700 	{
1701 		node_id const id = generate_random_id();
1702 		table.find_node(id, temp, 0, bucket_size * 2);
1703 		TEST_EQUAL(int(temp.size()), std::min(bucket_size * 2, int(nodes.size())));
1704 
1705 		std::sort(nodes.begin(), nodes.end(), std::bind(&compare_ref
1706 				, std::bind(&node_entry::id, _1)
1707 				, std::bind(&node_entry::id, _2), id));
1708 
1709 		int expected = std::accumulate(nodes.begin(), nodes.begin() + int(temp.size())
1710 			, 0, std::bind(&sum_distance_exp, _1, _2, id));
1711 		int sum_hits = std::accumulate(temp.begin(), temp.end()
1712 			, 0, std::bind(&sum_distance_exp, _1, _2, id));
1713 		TEST_EQUAL(bucket_size * 2, int(temp.size()));
1714 		TEST_EQUAL(expected, sum_hits);
1715 
1716 		duplicates.clear();
1717 		// This makes sure enough of the nodes returned are actually
1718 		// part of the closest nodes
1719 		for (std::vector<node_entry>::iterator i = temp.begin()
1720 			, end(temp.end()); i != end; ++i)
1721 		{
1722 			TEST_CHECK(duplicates.count(i->id) == 0);
1723 			duplicates.insert(i->id);
1724 		}
1725 	}
1726 
1727 	char const* ips[] = {
1728 		"124.31.75.21",
1729 		"21.75.31.124",
1730 		"65.23.51.170",
1731 		"84.124.73.14",
1732 		"43.213.53.83",
1733 	};
1734 
1735 	int rs[] = { 1,86,22,65,90 };
1736 
1737 	std::uint8_t prefixes[][3] =
1738 	{
1739 		{ 0x5f, 0xbf, 0xbf },
1740 		{ 0x5a, 0x3c, 0xe9 },
1741 		{ 0xa5, 0xd4, 0x32 },
1742 		{ 0x1b, 0x03, 0x21 },
1743 		{ 0xe5, 0x6f, 0x6c }
1744 	};
1745 
1746 	for (int i = 0; i < 5; ++i)
1747 	{
1748 		address const a = addr4(ips[i]);
1749 		node_id const new_id = generate_id_impl(a, std::uint32_t(rs[i]));
1750 		TEST_CHECK(new_id[0] == prefixes[i][0]);
1751 		TEST_CHECK(new_id[1] == prefixes[i][1]);
1752 		TEST_CHECK((new_id[2] & 0xf8) == (prefixes[i][2] & 0xf8));
1753 
1754 		TEST_CHECK(new_id[19] == rs[i]);
1755 		std::printf("IP address: %s r: %d node ID: %s\n", ips[i]
1756 			, rs[i], aux::to_hex(new_id).c_str());
1757 	}
1758 }
1759 
1760 } // anonymous namespace
1761 
TORRENT_TEST(routing_table_v4)1762 TORRENT_TEST(routing_table_v4)
1763 {
1764 	test_routing_table(rand_v4);
1765 }
1766 
TORRENT_TEST(routing_table_v6)1767 TORRENT_TEST(routing_table_v6)
1768 {
1769 	if (supports_ipv6())
1770 		test_routing_table(rand_v6);
1771 }
1772 
1773 namespace {
1774 
test_bootstrap(address (& rand_addr)())1775 void test_bootstrap(address(&rand_addr)())
1776 {
1777 	dht_test_setup t(udp::endpoint(rand_addr(), 20));
1778 	bdecode_node response;
1779 	bool ret;
1780 
1781 	dht::key_desc_t const find_node_desc[] = {
1782 		{"y", bdecode_node::string_t, 1, 0},
1783 		{"t", bdecode_node::string_t, 2, 0},
1784 		{"q", bdecode_node::string_t, 9, 0},
1785 		{"a", bdecode_node::dict_t, 0, key_desc_t::parse_children},
1786 			{"id", bdecode_node::string_t, 20, 0},
1787 			{"target", bdecode_node::string_t, 20, key_desc_t::optional},
1788 			{"info_hash", bdecode_node::string_t, 20, key_desc_t::optional | key_desc_t::last_child},
1789 	};
1790 
1791 	bdecode_node find_node_keys[7];
1792 
1793 	// bootstrap
1794 
1795 	g_sent_packets.clear();
1796 
1797 	udp::endpoint initial_node(rand_addr(), 1234);
1798 	std::vector<udp::endpoint> nodesv;
1799 	nodesv.push_back(initial_node);
1800 	t.dht_node.bootstrap(nodesv, std::bind(&nop_node));
1801 
1802 	TEST_EQUAL(g_sent_packets.size(), 1);
1803 	if (g_sent_packets.empty()) return;
1804 	TEST_EQUAL(g_sent_packets.front().first, initial_node);
1805 
1806 	node_from_entry(g_sent_packets.front().second, response);
1807 	ret = verify_message(response, find_node_desc, find_node_keys, t.error_string);
1808 	if (ret)
1809 	{
1810 		TEST_EQUAL(find_node_keys[0].string_value(), "q");
1811 		TEST_CHECK(find_node_keys[2].string_value() == "find_node"
1812 			|| find_node_keys[2].string_value() == "get_peers");
1813 
1814 		if (find_node_keys[0].string_value() != "q"
1815 			|| (find_node_keys[2].string_value() != "find_node"
1816 				&& find_node_keys[2].string_value() != "get_peers")) return;
1817 	}
1818 	else
1819 	{
1820 		std::printf("   invalid find_node request: %s\n", print_entry(response).c_str());
1821 		TEST_ERROR(t.error_string);
1822 		return;
1823 	}
1824 
1825 	udp::endpoint found_node(rand_addr(), 2235);
1826 	std::vector<node_entry> nodes;
1827 	nodes.push_back(node_entry{found_node});
1828 	g_sent_packets.clear();
1829 	if (is_v4(initial_node))
1830 		send_dht_response(t.dht_node, response, initial_node, msg_args().nodes(nodes));
1831 	else
1832 		send_dht_response(t.dht_node, response, initial_node, msg_args().nodes6(nodes));
1833 
1834 	TEST_EQUAL(g_sent_packets.size(), 1);
1835 	if (g_sent_packets.empty()) return;
1836 	TEST_EQUAL(g_sent_packets.front().first, found_node);
1837 
1838 	node_from_entry(g_sent_packets.front().second, response);
1839 	ret = verify_message(response, find_node_desc, find_node_keys, t.error_string);
1840 	if (ret)
1841 	{
1842 		TEST_EQUAL(find_node_keys[0].string_value(), "q");
1843 		TEST_CHECK(find_node_keys[2].string_value() == "find_node"
1844 			|| find_node_keys[2].string_value() == "get_peers");
1845 		if (find_node_keys[0].string_value() != "q"
1846 			|| (find_node_keys[2].string_value() != "find_node"
1847 				&& find_node_keys[2].string_value() != "get_peers")) return;
1848 	}
1849 	else
1850 	{
1851 		std::printf("   invalid find_node request: %s\n", print_entry(response).c_str());
1852 		TEST_ERROR(t.error_string);
1853 		return;
1854 	}
1855 
1856 	g_sent_packets.clear();
1857 	send_dht_response(t.dht_node, response, found_node);
1858 
1859 	TEST_CHECK(g_sent_packets.empty());
1860 	TEST_EQUAL(t.dht_node.num_global_nodes(), 3);
1861 }
1862 
1863 } // anonymous namespace
1864 
TORRENT_TEST(bootstrap_v4)1865 TORRENT_TEST(bootstrap_v4)
1866 {
1867 	test_bootstrap(rand_v4);
1868 }
1869 
TORRENT_TEST(bootstrap_v6)1870 TORRENT_TEST(bootstrap_v6)
1871 {
1872 	if (supports_ipv6())
1873 		test_bootstrap(rand_v6);
1874 }
1875 
1876 namespace {
1877 
test_bootstrap_want(address (& rand_addr)())1878 void test_bootstrap_want(address(&rand_addr)())
1879 {
1880 	dht_test_setup t(udp::endpoint(rand_addr(), 20));
1881 	bdecode_node response;
1882 	bool ret;
1883 
1884 	dht::key_desc_t const find_node_desc[] = {
1885 		{"y", bdecode_node::string_t, 1, 0},
1886 		{"t", bdecode_node::string_t, 2, 0},
1887 		{"q", bdecode_node::string_t, 9, 0},
1888 		{"a", bdecode_node::dict_t, 0, key_desc_t::parse_children},
1889 			{"id", bdecode_node::string_t, 20, 0},
1890 			{"target", bdecode_node::string_t, 20, key_desc_t::optional},
1891 			{"info_hash", bdecode_node::string_t, 20, key_desc_t::optional},
1892 			{"want", bdecode_node::list_t, 0, key_desc_t::last_child},
1893 	};
1894 
1895 	bdecode_node find_node_keys[8];
1896 
1897 	g_sent_packets.clear();
1898 
1899 	std::vector<udp::endpoint> nodesv;
1900 	if (is_v4(t.source))
1901 		nodesv.push_back(rand_udp_ep(rand_v6));
1902 	else
1903 		nodesv.push_back(rand_udp_ep(rand_v4));
1904 
1905 	t.dht_node.bootstrap(nodesv, std::bind(&nop_node));
1906 
1907 	TEST_EQUAL(g_sent_packets.size(), 1);
1908 	TEST_EQUAL(g_sent_packets.front().first, nodesv[0]);
1909 
1910 	node_from_entry(g_sent_packets.front().second, response);
1911 	ret = verify_message(response, find_node_desc, find_node_keys, t.error_string);
1912 	if (ret)
1913 	{
1914 		TEST_EQUAL(find_node_keys[0].string_value(), "q");
1915 		TEST_CHECK(find_node_keys[2].string_value() == "find_node"
1916 			|| find_node_keys[2].string_value() == "get_peers");
1917 
1918 		TEST_EQUAL(find_node_keys[7].list_size(), 1);
1919 		if (is_v4(t.source))
1920 		{
1921 			TEST_EQUAL(find_node_keys[7].list_string_value_at(0), "n4");
1922 		}
1923 		else
1924 		{
1925 			TEST_EQUAL(find_node_keys[7].list_string_value_at(0), "n6");
1926 		}
1927 	}
1928 	else
1929 	{
1930 		std::printf("   invalid find_node request: %s\n", print_entry(response).c_str());
1931 		TEST_ERROR(t.error_string);
1932 	}
1933 }
1934 
1935 } // anonymous namespace
1936 
TORRENT_TEST(bootstrap_want_v4)1937 TORRENT_TEST(bootstrap_want_v4)
1938 {
1939 	test_bootstrap_want(rand_v4);
1940 }
1941 
TORRENT_TEST(bootstrap_want_v6)1942 TORRENT_TEST(bootstrap_want_v6)
1943 {
1944 	test_bootstrap_want(rand_v6);
1945 }
1946 
1947 namespace {
1948 
1949 // test that the node ignores a nodes entry which is too short
test_short_nodes(address (& rand_addr)())1950 void test_short_nodes(address(&rand_addr)())
1951 {
1952 	dht_test_setup t(udp::endpoint(rand_addr(), 20));
1953 	bdecode_node response;
1954 	bool ret;
1955 
1956 	dht::key_desc_t const find_node_desc[] = {
1957 		{ "y", bdecode_node::string_t, 1, 0 },
1958 		{ "t", bdecode_node::string_t, 2, 0 },
1959 		{ "q", bdecode_node::string_t, 9, 0 },
1960 		{ "a", bdecode_node::dict_t, 0, key_desc_t::parse_children },
1961 		{ "id", bdecode_node::string_t, 20, 0 },
1962 		{ "target", bdecode_node::string_t, 20, key_desc_t::optional },
1963 		{ "info_hash", bdecode_node::string_t, 20, key_desc_t::optional | key_desc_t::last_child },
1964 	};
1965 
1966 	bdecode_node find_node_keys[7];
1967 
1968 	// bootstrap
1969 
1970 	g_sent_packets.clear();
1971 
1972 	udp::endpoint initial_node(rand_addr(), 1234);
1973 	std::vector<udp::endpoint> nodesv;
1974 	nodesv.push_back(initial_node);
1975 	t.dht_node.bootstrap(nodesv, std::bind(&nop_node));
1976 
1977 	TEST_EQUAL(g_sent_packets.size(), 1);
1978 	if (g_sent_packets.empty()) return;
1979 	TEST_EQUAL(g_sent_packets.front().first, initial_node);
1980 
1981 	node_from_entry(g_sent_packets.front().second, response);
1982 	ret = verify_message(response, find_node_desc, find_node_keys, t.error_string);
1983 	if (ret)
1984 	{
1985 		TEST_EQUAL(find_node_keys[0].string_value(), "q");
1986 		TEST_CHECK(find_node_keys[2].string_value() == "find_node"
1987 				   || find_node_keys[2].string_value() == "get_peers");
1988 
1989 		if (find_node_keys[0].string_value() != "q"
1990 			|| (find_node_keys[2].string_value() != "find_node"
1991 				&& find_node_keys[2].string_value() != "get_peers")) return;
1992 	}
1993 	else
1994 	{
1995 		std::printf("   invalid find_node request: %s\n", print_entry(response).c_str());
1996 		TEST_ERROR(t.error_string);
1997 		return;
1998 	}
1999 
2000 	udp::endpoint found_node(rand_addr(), 2235);
2001 	std::vector<node_entry> nodes;
2002 	nodes.push_back(node_entry{found_node});
2003 	g_sent_packets.clear();
2004 	msg_args args;
2005 	// chop one byte off of the nodes string
2006 	if (is_v4(initial_node))
2007 	{
2008 		args.nodes(nodes);
2009 		args.a["nodes"] = args.a["nodes"].string().substr(1);
2010 	}
2011 	else
2012 	{
2013 		args.nodes6(nodes);
2014 		args.a["nodes6"] = args.a["nodes6"].string().substr(1);
2015 	}
2016 
2017 	send_dht_response(t.dht_node, response, initial_node, args);
2018 
2019 	TEST_EQUAL(g_sent_packets.size(), 0);
2020 }
2021 
2022 } // anonymous namespace
2023 
TORRENT_TEST(short_nodes_v4)2024 TORRENT_TEST(short_nodes_v4)
2025 {
2026 	test_short_nodes(rand_v4);
2027 }
2028 
TORRENT_TEST(short_nodes_v6)2029 TORRENT_TEST(short_nodes_v6)
2030 {
2031 	if (supports_ipv6())
2032 		test_short_nodes(rand_v6);
2033 }
2034 
2035 namespace {
2036 
test_get_peers(address (& rand_addr)())2037 void test_get_peers(address(&rand_addr)())
2038 {
2039 	dht_test_setup t(udp::endpoint(rand_addr(), 20));
2040 	bdecode_node response;
2041 	bool ret;
2042 
2043 	dht::key_desc_t const get_peers_desc[] = {
2044 		{"y", bdecode_node::string_t, 1, 0},
2045 		{"t", bdecode_node::string_t, 2, 0},
2046 		{"q", bdecode_node::string_t, 9, 0},
2047 		{"a", bdecode_node::dict_t, 0, key_desc_t::parse_children},
2048 			{"id", bdecode_node::string_t, 20, 0},
2049 			{"info_hash", bdecode_node::string_t, 20, key_desc_t::last_child},
2050 	};
2051 
2052 	bdecode_node get_peers_keys[6];
2053 
2054 	// get_peers
2055 
2056 	g_sent_packets.clear();
2057 
2058 	dht::node_id const target = to_hash("1234876923549721020394873245098347598635");
2059 
2060 	udp::endpoint const initial_node(rand_addr(), 1234);
2061 	dht::node_id const initial_node_id = to_hash("1111111111222222222233333333334444444444");
2062 	t.dht_node.m_table.add_node(node_entry{initial_node_id, initial_node, 10, true});
2063 
2064 	t.dht_node.announce(target, 1234, {}, get_peers_cb);
2065 
2066 	TEST_EQUAL(g_sent_packets.size(), 1);
2067 	if (g_sent_packets.empty()) return;
2068 	TEST_EQUAL(g_sent_packets.front().first, initial_node);
2069 
2070 	node_from_entry(g_sent_packets.front().second, response);
2071 	ret = verify_message(response, get_peers_desc, get_peers_keys, t.error_string);
2072 	if (ret)
2073 	{
2074 		TEST_EQUAL(get_peers_keys[0].string_value(), "q");
2075 		TEST_EQUAL(get_peers_keys[2].string_value(), "get_peers");
2076 		TEST_EQUAL(get_peers_keys[5].string_value(), target.to_string());
2077 		if (get_peers_keys[0].string_value() != "q"
2078 			|| get_peers_keys[2].string_value() != "get_peers")
2079 			return;
2080 	}
2081 	else
2082 	{
2083 		std::printf("   invalid get_peers request: %s\n", print_entry(response).c_str());
2084 		TEST_ERROR(t.error_string);
2085 		return;
2086 	}
2087 
2088 	std::set<tcp::endpoint> peers[2];
2089 	peers[0].insert(tcp::endpoint(rand_addr(), 4111));
2090 	peers[0].insert(tcp::endpoint(rand_addr(), 4112));
2091 	peers[0].insert(tcp::endpoint(rand_addr(), 4113));
2092 
2093 	udp::endpoint next_node(rand_addr(), 2235);
2094 	std::vector<node_entry> nodes;
2095 	nodes.push_back(node_entry{next_node});
2096 
2097 	g_sent_packets.clear();
2098 	if (is_v4(initial_node))
2099 	{
2100 		send_dht_response(t.dht_node, response, initial_node
2101 			, msg_args().nodes(nodes).token("10").port(1234).peers(peers[0]));
2102 	}
2103 	else
2104 	{
2105 		send_dht_response(t.dht_node, response, initial_node
2106 			, msg_args().nodes6(nodes).token("10").port(1234).peers(peers[0]));
2107 	}
2108 
2109 	TEST_EQUAL(g_sent_packets.size(), 1);
2110 	if (g_sent_packets.empty()) return;
2111 	TEST_EQUAL(g_sent_packets.front().first, next_node);
2112 
2113 	node_from_entry(g_sent_packets.front().second, response);
2114 	ret = verify_message(response, get_peers_desc, get_peers_keys, t.error_string);
2115 	if (ret)
2116 	{
2117 		TEST_EQUAL(get_peers_keys[0].string_value(), "q");
2118 		TEST_EQUAL(get_peers_keys[2].string_value(), "get_peers");
2119 		TEST_EQUAL(get_peers_keys[5].string_value(), target.to_string());
2120 		if (get_peers_keys[0].string_value() != "q"
2121 			|| get_peers_keys[2].string_value() != "get_peers")
2122 			return;
2123 	}
2124 	else
2125 	{
2126 		std::printf("   invalid get_peers request: %s\n", print_entry(response).c_str());
2127 		TEST_ERROR(t.error_string);
2128 		return;
2129 	}
2130 
2131 	peers[1].insert(tcp::endpoint(rand_addr(), 4114));
2132 	peers[1].insert(tcp::endpoint(rand_addr(), 4115));
2133 	peers[1].insert(tcp::endpoint(rand_addr(), 4116));
2134 
2135 	g_sent_packets.clear();
2136 	send_dht_response(t.dht_node, response, next_node
2137 		, msg_args().token("11").port(1234).peers(peers[1]));
2138 
2139 	for (auto const& p : g_sent_packets)
2140 	{
2141 //		std::printf(" %s:%d: %s\n", i->first.address().to_string(ec).c_str()
2142 //			, i->first.port(), i->second.to_string().c_str());
2143 		TEST_EQUAL(p.second["q"].string(), "announce_peer");
2144 	}
2145 
2146 	g_sent_packets.clear();
2147 
2148 	for (int i = 0; i < 2; ++i)
2149 	{
2150 		for (auto const& peer : peers[i])
2151 		{
2152 			TEST_CHECK(std::find(g_got_peers.begin(), g_got_peers.end(), peer) != g_got_peers.end());
2153 		}
2154 	}
2155 	g_got_peers.clear();
2156 }
2157 
2158 } // anonymous namespace
2159 
TORRENT_TEST(get_peers_v4)2160 TORRENT_TEST(get_peers_v4)
2161 {
2162 	test_get_peers(rand_v4);
2163 }
2164 
TORRENT_TEST(get_peers_v6)2165 TORRENT_TEST(get_peers_v6)
2166 {
2167 	if (supports_ipv6())
2168 		test_get_peers(rand_v6);
2169 }
2170 
2171 namespace {
2172 
2173 // TODO: 4 pass in th actual salt as the argument
test_mutable_get(address (& rand_addr)(),bool const with_salt)2174 void test_mutable_get(address(&rand_addr)(), bool const with_salt)
2175 {
2176 	dht_test_setup t(udp::endpoint(rand_addr(), 20));
2177 
2178 	public_key pk;
2179 	secret_key sk;
2180 	get_test_keypair(pk, sk);
2181 
2182 	char buffer[1200];
2183 	sequence_number seq(4);
2184 	span<char const> itemv;
2185 	bdecode_node response;
2186 
2187 	std::string salt;
2188 	if (with_salt) salt = "foobar";
2189 
2190 	// mutable get
2191 
2192 	g_sent_packets.clear();
2193 
2194 	udp::endpoint const initial_node(rand_addr(), 1234);
2195 	dht::node_id const initial_node_id = to_hash("1111111111222222222233333333334444444444");
2196 	t.dht_node.m_table.add_node(node_entry{initial_node_id, initial_node, 10, true});
2197 
2198 	g_put_item.assign(items[0].ent, salt, seq, pk, sk);
2199 	t.dht_node.put_item(pk, std::string()
2200 		, std::bind(&put_mutable_item_cb, _1, _2, 0)
2201 		, put_mutable_item_data_cb);
2202 
2203 	TEST_EQUAL(g_sent_packets.size(), 1);
2204 
2205 	// mutable_get
2206 
2207 	g_sent_packets.clear();
2208 
2209 	t.dht_node.get_item(pk, salt, get_mutable_item_cb);
2210 
2211 	TEST_EQUAL(g_sent_packets.size(), 1);
2212 	if (g_sent_packets.empty()) return;
2213 	TEST_EQUAL(g_sent_packets.front().first, initial_node);
2214 
2215 	node_from_entry(g_sent_packets.front().second, response);
2216 	bdecode_node get_item_keys[6];
2217 	bool const ret = verify_message(response, get_item_desc, get_item_keys, t.error_string);
2218 	if (ret)
2219 	{
2220 		TEST_EQUAL(get_item_keys[0].string_value(), "q");
2221 		TEST_EQUAL(get_item_keys[2].string_value(), "get");
2222 		if (get_item_keys[0].string_value() != "q"
2223 			|| get_item_keys[2].string_value() != "get")
2224 			return;
2225 	}
2226 	else
2227 	{
2228 		std::printf("   invalid get request: %s\n", print_entry(response).c_str());
2229 		TEST_ERROR(t.error_string);
2230 		return;
2231 	}
2232 
2233 	g_sent_packets.clear();
2234 
2235 	signature sig;
2236 	itemv = span<char const>(buffer, bencode(buffer, items[0].ent));
2237 	sig = sign_mutable_item(itemv, salt, seq, pk, sk);
2238 	send_dht_response(t.dht_node, response, initial_node
2239 		, msg_args()
2240 			.token("10")
2241 			.port(1234)
2242 			.value(items[0].ent)
2243 			.key(pk)
2244 			.sig(sig)
2245 			.salt(salt)
2246 			.seq(seq));
2247 
2248 	TEST_CHECK(g_sent_packets.empty());
2249 	TEST_EQUAL(g_got_items.size(), 1);
2250 	if (g_got_items.empty()) return;
2251 
2252 	TEST_EQUAL(g_got_items.front().value(), items[0].ent);
2253 	TEST_CHECK(g_got_items.front().pk() == pk);
2254 	TEST_CHECK(g_got_items.front().sig() == sig);
2255 	TEST_CHECK(g_got_items.front().seq() == seq);
2256 	g_got_items.clear();
2257 }
2258 
2259 } // anonymous namespace
2260 
TORRENT_TEST(mutable_get_v4)2261 TORRENT_TEST(mutable_get_v4)
2262 {
2263 	test_mutable_get(rand_v4, false);
2264 }
2265 
TORRENT_TEST(mutable_get_salt_v4)2266 TORRENT_TEST(mutable_get_salt_v4)
2267 {
2268 	test_mutable_get(rand_v4, true);
2269 }
2270 
TORRENT_TEST(mutable_get_v6)2271 TORRENT_TEST(mutable_get_v6)
2272 {
2273 	if (supports_ipv6())
2274 		test_mutable_get(rand_v6, false);
2275 }
2276 
TORRENT_TEST(mutable_get_salt_v6)2277 TORRENT_TEST(mutable_get_salt_v6)
2278 {
2279 	if (supports_ipv6())
2280 		test_mutable_get(rand_v6, true);
2281 }
2282 
TORRENT_TEST(immutable_get)2283 TORRENT_TEST(immutable_get)
2284 {
2285 	dht_test_setup t(udp::endpoint(rand_v4(), 20));
2286 	bdecode_node response;
2287 
2288 	// immutable get
2289 
2290 	g_sent_packets.clear();
2291 
2292 	udp::endpoint initial_node(addr4("4.4.4.4"), 1234);
2293 	dht::node_id const initial_node_id = to_hash("1111111111222222222233333333334444444444");
2294 	t.dht_node.m_table.add_node(node_entry{initial_node_id, initial_node, 10, true});
2295 
2296 	t.dht_node.get_item(items[0].target, get_immutable_item_cb);
2297 
2298 	TEST_EQUAL(g_sent_packets.size(), 1);
2299 	if (g_sent_packets.empty()) return;
2300 	TEST_EQUAL(g_sent_packets.front().first, initial_node);
2301 
2302 	node_from_entry(g_sent_packets.front().second, response);
2303 	bdecode_node get_item_keys[6];
2304 	bool const ret = verify_message(response, get_item_desc, get_item_keys, t.error_string);
2305 	if (ret)
2306 	{
2307 		TEST_EQUAL(get_item_keys[0].string_value(), "q");
2308 		TEST_EQUAL(get_item_keys[2].string_value(), "get");
2309 		TEST_EQUAL(get_item_keys[5].string_value(), items[0].target.to_string());
2310 		if (get_item_keys[0].string_value() != "q" || get_item_keys[2].string_value() != "get") return;
2311 	}
2312 	else
2313 	{
2314 		std::printf("   invalid get request: %s\n", print_entry(response).c_str());
2315 		TEST_ERROR(t.error_string);
2316 		return;
2317 	}
2318 
2319 	g_sent_packets.clear();
2320 	send_dht_response(t.dht_node, response, initial_node
2321 		, msg_args().token("10").port(1234).value(items[0].ent));
2322 
2323 	TEST_CHECK(g_sent_packets.empty());
2324 	TEST_EQUAL(g_got_items.size(), 1);
2325 	if (g_got_items.empty()) return;
2326 
2327 	TEST_EQUAL(g_got_items.front().value(), items[0].ent);
2328 	g_got_items.clear();
2329 }
2330 
TORRENT_TEST(immutable_put)2331 TORRENT_TEST(immutable_put)
2332 {
2333 	bdecode_node response;
2334 	span<char const> itemv;
2335 	char buffer[1200];
2336 
2337 	dht::key_desc_t const put_immutable_item_desc[] = {
2338 		{"y", bdecode_node::string_t, 1, 0},
2339 		{"t", bdecode_node::string_t, 2, 0},
2340 		{"q", bdecode_node::string_t, 3, 0},
2341 		{"a", bdecode_node::dict_t, 0, key_desc_t::parse_children},
2342 			{"id", bdecode_node::string_t, 20, 0},
2343 			{"token", bdecode_node::string_t, 2, 0},
2344 			{"v", bdecode_node::none_t, 0, key_desc_t::last_child},
2345 	};
2346 
2347 	bdecode_node put_immutable_item_keys[7];
2348 
2349 	// immutable put
2350 	g_sent_packets.clear();
2351 	for (int loop = 0; loop < 9; loop++)
2352 	{
2353 		dht_test_setup t(udp::endpoint(rand_v4(), 20));
2354 
2355 		// set the branching factor to k to make this a little easier
2356 		t.sett.search_branching = 8;
2357 
2358 		lt::aux::array<node_entry, 8> const nodes = build_nodes();
2359 
2360 		for (node_entry const& n : nodes)
2361 			t.dht_node.m_table.add_node(n);
2362 
2363 		entry put_data;
2364 		put_data = "Hello world";
2365 		std::string flat_data;
2366 		bencode(std::back_inserter(flat_data), put_data);
2367 		sha1_hash target = item_target_id(flat_data);
2368 
2369 		t.dht_node.put_item(target, put_data, std::bind(&put_immutable_item_cb, _1, loop));
2370 
2371 		TEST_EQUAL(g_sent_packets.size(), 8);
2372 		if (g_sent_packets.size() != 8) break;
2373 
2374 		int idx = -1;
2375 		for (auto& node : nodes)
2376 		{
2377 			++idx;
2378 			auto const packet = find_packet(node.ep());
2379 			TEST_CHECK(packet != g_sent_packets.end());
2380 			if (packet == g_sent_packets.end()) continue;
2381 
2382 			node_from_entry(packet->second, response);
2383 			bdecode_node get_item_keys[6];
2384 			bool const ret = verify_message(response, get_item_desc, get_item_keys, t.error_string);
2385 			if (!ret)
2386 			{
2387 				std::printf("   invalid get request: %s\n", print_entry(response).c_str());
2388 				TEST_ERROR(t.error_string);
2389 				continue;
2390 			}
2391 			char tok[11];
2392 			std::snprintf(tok, sizeof(tok), "%02d", idx);
2393 
2394 			msg_args args;
2395 			args.token(tok).port(1234).nid(node.id).nodes({node});
2396 			send_dht_response(t.dht_node, response, node.ep(), args);
2397 			g_sent_packets.erase(packet);
2398 		}
2399 
2400 		TEST_EQUAL(g_sent_packets.size(), 8);
2401 		if (g_sent_packets.size() != 8) break;
2402 
2403 		itemv = span<char const>(buffer, bencode(buffer, put_data));
2404 
2405 		idx = -1;
2406 		for (auto& node : nodes)
2407 		{
2408 			++idx;
2409 			auto const packet = find_packet(node.ep());
2410 			TEST_CHECK(packet != g_sent_packets.end());
2411 			if (packet == g_sent_packets.end()) continue;
2412 
2413 			node_from_entry(packet->second, response);
2414 			bool const ret = verify_message(response, put_immutable_item_desc, put_immutable_item_keys
2415 				, t.error_string);
2416 			if (ret)
2417 			{
2418 				TEST_EQUAL(put_immutable_item_keys[0].string_value(), "q");
2419 				TEST_EQUAL(put_immutable_item_keys[2].string_value(), "put");
2420 				span<const char> const v = put_immutable_item_keys[6].data_section();
2421 				TEST_EQUAL(v, span<char const>(flat_data));
2422 				char tok[11];
2423 				std::snprintf(tok, sizeof(tok), "%02d", idx);
2424 				TEST_EQUAL(put_immutable_item_keys[5].string_value(), tok);
2425 				if (put_immutable_item_keys[0].string_value() != "q"
2426 					|| put_immutable_item_keys[2].string_value() != "put") continue;
2427 
2428 				if (idx < loop) send_dht_response(t.dht_node, response, node.ep());
2429 			}
2430 			else
2431 			{
2432 				std::printf("   invalid immutable put request: %s\n", print_entry(response).c_str());
2433 				TEST_ERROR(t.error_string);
2434 				continue;
2435 			}
2436 		}
2437 		g_sent_packets.clear();
2438 		g_put_item.clear();
2439 		g_put_count = 0;
2440 	}
2441 }
2442 
TORRENT_TEST(mutable_put)2443 TORRENT_TEST(mutable_put)
2444 {
2445 	bdecode_node response;
2446 	span<char const> itemv;
2447 	char buffer[1200];
2448 	bdecode_node put_mutable_item_keys[11];
2449 	public_key pk;
2450 	secret_key sk;
2451 	get_test_keypair(pk, sk);
2452 
2453 	sequence_number seq(4);
2454 
2455 	// mutable put
2456 	g_sent_packets.clear();
2457 	for (int loop = 0; loop < 9; loop++)
2458 	{
2459 		dht_test_setup t(udp::endpoint(rand_v4(), 20));
2460 
2461 		// set the branching factor to k to make this a little easier
2462 		t.sett.search_branching = 8;
2463 
2464 		enum { num_test_nodes = 8 };
2465 		lt::aux::array<node_entry, num_test_nodes> const nodes = build_nodes();
2466 
2467 		for (auto const& n : nodes)
2468 			t.dht_node.m_table.add_node(n);
2469 
2470 		g_put_item.assign(items[0].ent, empty_salt, seq, pk, sk);
2471 		signature const sig = g_put_item.sig();
2472 		t.dht_node.put_item(pk, std::string()
2473 			, std::bind(&put_mutable_item_cb, _1, _2, loop)
2474 			, put_mutable_item_data_cb);
2475 
2476 		TEST_EQUAL(g_sent_packets.size(), 8);
2477 		if (g_sent_packets.size() != 8) break;
2478 
2479 		int idx = -1;
2480 		for (auto& node : nodes)
2481 		{
2482 			++idx;
2483 			auto const packet = find_packet(node.ep());
2484 			TEST_CHECK(packet != g_sent_packets.end());
2485 			if (packet == g_sent_packets.end()) continue;
2486 
2487 			node_from_entry(packet->second, response);
2488 			bdecode_node get_item_keys[6];
2489 			bool const ret = verify_message(response, get_item_desc, get_item_keys, t.error_string);
2490 			if (!ret)
2491 			{
2492 				std::printf("   invalid get request: %s\n", print_entry(response).c_str());
2493 				TEST_ERROR(t.error_string);
2494 				continue;
2495 			}
2496 			char tok[11];
2497 			std::snprintf(tok, sizeof(tok), "%02d", idx);
2498 
2499 			msg_args args;
2500 			args.token(tok).port(1234).nid(node.id).nodes({node});
2501 			send_dht_response(t.dht_node, response, node.ep(), args);
2502 			g_sent_packets.erase(packet);
2503 		}
2504 
2505 		TEST_EQUAL(g_sent_packets.size(), 8);
2506 		if (g_sent_packets.size() != 8) break;
2507 
2508 		itemv = span<char const>(buffer, bencode(buffer, items[0].ent));
2509 
2510 		idx = -1;
2511 		for (auto& node : nodes)
2512 		{
2513 			++idx;
2514 			auto const packet = find_packet(node.ep());
2515 			TEST_CHECK(packet != g_sent_packets.end());
2516 			if (packet == g_sent_packets.end()) continue;
2517 
2518 			node_from_entry(packet->second, response);
2519 			bool const ret = verify_message(response, put_mutable_item_desc, put_mutable_item_keys
2520 				, t.error_string);
2521 			if (ret)
2522 			{
2523 				TEST_EQUAL(put_mutable_item_keys[0].string_value(), "q");
2524 				TEST_EQUAL(put_mutable_item_keys[2].string_value(), "put");
2525 				TEST_EQUAL(put_mutable_item_keys[6].string_value()
2526 					, std::string(pk.bytes.data(), public_key::len));
2527 				TEST_EQUAL(put_mutable_item_keys[7].int_value(), int(seq.value));
2528 				TEST_EQUAL(put_mutable_item_keys[8].string_value()
2529 					, std::string(sig.bytes.data(), signature::len));
2530 				span<const char> const v = put_mutable_item_keys[10].data_section();
2531 				TEST_CHECK(v == itemv);
2532 				char tok[11];
2533 				std::snprintf(tok, sizeof(tok), "%02d", idx);
2534 				TEST_EQUAL(put_mutable_item_keys[9].string_value(), tok);
2535 				if (put_mutable_item_keys[0].string_value() != "q"
2536 					|| put_mutable_item_keys[2].string_value() != "put") continue;
2537 
2538 				if (idx < loop) send_dht_response(t.dht_node, response, node.ep());
2539 			}
2540 			else
2541 			{
2542 				std::printf("   invalid put request: %s\n", print_entry(response).c_str());
2543 				TEST_ERROR(t.error_string);
2544 				continue;
2545 			}
2546 		}
2547 		g_sent_packets.clear();
2548 		g_put_item.clear();
2549 		g_put_count = 0;
2550 	}
2551 }
2552 
TORRENT_TEST(traversal_done)2553 TORRENT_TEST(traversal_done)
2554 {
2555 	dht_test_setup t(udp::endpoint(rand_v4(), 20));
2556 
2557 	// set the branching factor to k to make this a little easier
2558 	t.sett.search_branching = 8;
2559 
2560 	public_key pk;
2561 	secret_key sk;
2562 	get_test_keypair(pk, sk);
2563 
2564 	sequence_number seq(4);
2565 	bdecode_node response;
2566 
2567 	// verify that done() is only invoked once
2568 	// See PR 252
2569 	g_sent_packets.clear();
2570 
2571 	sha1_hash const target = hasher(pk.bytes).final();
2572 	constexpr int num_test_nodes = 9; // we need K + 1 nodes to create the failing sequence
2573 
2574 	lt::aux::array<node_entry, num_test_nodes> nodes = build_nodes(target);
2575 
2576 	// invert the ith most significant byte so that the test nodes are
2577 	// progressively closer to the target item
2578 	for (int i = 0; i < num_test_nodes; ++i)
2579 		nodes[i].id[i] = static_cast<std::uint8_t>(~nodes[i].id[i]);
2580 
2581 	// add the first k nodes to the subject's routing table
2582 	for (int i = 0; i < 8; ++i)
2583 		t.dht_node.m_table.add_node(nodes[i]);
2584 
2585 	// kick off a mutable put request
2586 	g_put_item.assign(items[0].ent, empty_salt, seq, pk, sk);
2587 	t.dht_node.put_item(pk, std::string()
2588 		, std::bind(&put_mutable_item_cb, _1, _2, 0)
2589 		, put_mutable_item_data_cb);
2590 	TEST_EQUAL(g_sent_packets.size(), 8);
2591 	if (g_sent_packets.size() != 8) return;
2592 
2593 	// first send responses for the k closest nodes
2594 	for (int i = 1;; ++i)
2595 	{
2596 		// once the k closest nodes have responded, send the final response
2597 		// from the farthest node, this shouldn't trigger a second call to
2598 		// get_item_cb
2599 		if (i == num_test_nodes) i = 0;
2600 
2601 		auto const packet = find_packet(nodes[i].ep());
2602 		TEST_CHECK(packet != g_sent_packets.end());
2603 		if (packet == g_sent_packets.end()) continue;
2604 
2605 		node_from_entry(packet->second, response);
2606 		bdecode_node get_item_keys[6];
2607 		bool const ret = verify_message(response, get_item_desc, get_item_keys, t.error_string);
2608 		if (!ret)
2609 		{
2610 			std::printf("   invalid get request: %s\n", print_entry(response).c_str());
2611 			TEST_ERROR(t.error_string);
2612 			continue;
2613 		}
2614 		char tok[11];
2615 		std::snprintf(tok, sizeof(tok), "%02d", i);
2616 
2617 		msg_args args;
2618 		args.token(tok).port(1234).nid(nodes[i].id);
2619 
2620 		// add the address of the closest node to the first response
2621 		if (i == 1)
2622 			args.nodes({nodes[8]});
2623 
2624 		send_dht_response(t.dht_node, response, nodes[i].ep(), args);
2625 		g_sent_packets.erase(packet);
2626 
2627 		// once we've sent the response from the farthest node, we're done
2628 		if (i == 0) break;
2629 	}
2630 
2631 	TEST_EQUAL(g_put_count, 1);
2632 	// k nodes should now have outstanding put requests
2633 	TEST_EQUAL(g_sent_packets.size(), 8);
2634 
2635 	g_sent_packets.clear();
2636 	g_put_item.clear();
2637 	g_put_count = 0;
2638 }
2639 
TORRENT_TEST(dht_dual_stack)2640 TORRENT_TEST(dht_dual_stack)
2641 {
2642 	// TODO: 3 use dht_test_setup class to simplify the node setup
2643 	dht::settings sett = test_settings();
2644 	mock_socket s;
2645 	auto sock4 = dummy_listen_socket4();
2646 	auto sock6 = dummy_listen_socket6();
2647 	obs observer;
2648 	counters cnt;
2649 	node* node4p = nullptr, *node6p = nullptr;
2650 	auto get_foreign_node = [&](node_id const&, std::string const& family)
2651 	{
2652 		if (family == "n4") return node4p;
2653 		if (family == "n6") return node6p;
2654 		TEST_CHECK(false);
2655 		return static_cast<node*>(nullptr);
2656 	};
2657 	std::unique_ptr<dht_storage_interface> dht_storage(dht_default_storage_constructor(sett));
2658 	dht_storage->update_node_ids({node_id(nullptr)});
2659 	dht::node node4(sock4, &s, sett, node_id(nullptr), &observer, cnt, get_foreign_node, *dht_storage);
2660 	dht::node node6(sock6, &s, sett, node_id(nullptr), &observer, cnt, get_foreign_node, *dht_storage);
2661 	node4p = &node4;
2662 	node6p = &node6;
2663 
2664 	// DHT should be running on port 48199 now
2665 	bdecode_node response;
2666 	char error_string[200];
2667 	bool ret;
2668 
2669 	node_id id = to_hash("3123456789abcdef01232456789abcdef0123456");
2670 	node4.m_table.node_seen(id, udp::endpoint(addr("4.4.4.4"), 4440), 10);
2671 	node6.m_table.node_seen(id, udp::endpoint(addr("4::4"), 4441), 10);
2672 
2673 	// v4 node requesting v6 nodes
2674 
2675 	udp::endpoint source(addr("10.0.0.1"), 20);
2676 
2677 	send_dht_request(node4, "find_node", source, &response
2678 		, msg_args()
2679 			.target(sha1_hash("0101010101010101010101010101010101010101"))
2680 			.want("n6"));
2681 
2682 	dht::key_desc_t const nodes6_desc[] = {
2683 		{ "y", bdecode_node::string_t, 1, 0 },
2684 		{ "r", bdecode_node::dict_t, 0, key_desc_t::parse_children },
2685 		{ "id", bdecode_node::string_t, 20, 0 },
2686 		{ "nodes6", bdecode_node::string_t, 38, key_desc_t::last_child }
2687 	};
2688 
2689 	bdecode_node nodes6_keys[4];
2690 
2691 	ret = verify_message(response, nodes6_desc, nodes6_keys, error_string);
2692 
2693 	if (ret)
2694 	{
2695 		char const* nodes_ptr = nodes6_keys[3].string_ptr();
2696 		TEST_CHECK(memcmp(nodes_ptr, id.data(), id.size()) == 0);
2697 		nodes_ptr += id.size();
2698 		udp::endpoint rep = detail::read_v6_endpoint<udp::endpoint>(nodes_ptr);
2699 		TEST_EQUAL(rep, udp::endpoint(addr("4::4"), 4441));
2700 	}
2701 	else
2702 	{
2703 		std::printf("find_node response: %s\n", print_entry(response).c_str());
2704 		TEST_ERROR(error_string);
2705 	}
2706 
2707 	// v6 node requesting v4 nodes
2708 
2709 	source.address(addr("10::1"));
2710 
2711 	send_dht_request(node6, "get_peers", source, &response
2712 		, msg_args().info_hash("0101010101010101010101010101010101010101").want("n4"));
2713 
2714 	dht::key_desc_t const nodes_desc[] = {
2715 		{ "y", bdecode_node::string_t, 1, 0 },
2716 		{ "r", bdecode_node::dict_t, 0, key_desc_t::parse_children },
2717 		{ "id", bdecode_node::string_t, 20, 0 },
2718 		{ "nodes", bdecode_node::string_t, 26, key_desc_t::last_child }
2719 	};
2720 
2721 	bdecode_node nodes_keys[4];
2722 
2723 	ret = verify_message(response, nodes_desc, nodes_keys, error_string);
2724 
2725 	if (ret)
2726 	{
2727 		char const* nodes_ptr = nodes_keys[3].string_ptr();
2728 		TEST_CHECK(memcmp(nodes_ptr, id.data(), id.size()) == 0);
2729 		nodes_ptr += id.size();
2730 		udp::endpoint rep = detail::read_v4_endpoint<udp::endpoint>(nodes_ptr);
2731 		TEST_EQUAL(rep, udp::endpoint(addr("4.4.4.4"), 4440));
2732 	}
2733 	else
2734 	{
2735 		std::printf("find_node response: %s\n", print_entry(response).c_str());
2736 		TEST_ERROR(error_string);
2737 	}
2738 
2739 	// v6 node requesting both v4 and v6 nodes
2740 
2741 	send_dht_request(node6, "find_node", source, &response
2742 		, msg_args().target(sha1_hash("0101010101010101010101010101010101010101"))
2743 			.want("n4")
2744 			.want("n6"));
2745 
2746 	dht::key_desc_t const nodes46_desc[] = {
2747 		{ "y", bdecode_node::string_t, 1, 0 },
2748 		{ "r", bdecode_node::dict_t, 0, key_desc_t::parse_children },
2749 		{ "id", bdecode_node::string_t, 20, 0 },
2750 		{ "nodes", bdecode_node::string_t, 26, 0 },
2751 		{ "nodes6", bdecode_node::string_t, 38, key_desc_t::last_child }
2752 	};
2753 
2754 	bdecode_node nodes46_keys[5];
2755 
2756 	ret = verify_message(response, nodes46_desc, nodes46_keys, error_string);
2757 
2758 	if (ret)
2759 	{
2760 		char const* nodes_ptr = nodes46_keys[3].string_ptr();
2761 		TEST_CHECK(memcmp(nodes_ptr, id.data(), id.size()) == 0);
2762 		nodes_ptr += id.size();
2763 		udp::endpoint rep = detail::read_v4_endpoint<udp::endpoint>(nodes_ptr);
2764 		TEST_EQUAL(rep, udp::endpoint(addr("4.4.4.4"), 4440));
2765 
2766 		nodes_ptr = nodes46_keys[4].string_ptr();
2767 		TEST_CHECK(memcmp(nodes_ptr, id.data(), id.size()) == 0);
2768 		nodes_ptr += id.size();
2769 		rep = detail::read_v6_endpoint<udp::endpoint>(nodes_ptr);
2770 		TEST_EQUAL(rep, udp::endpoint(addr("4::4"), 4441));
2771 	}
2772 	else
2773 	{
2774 		std::printf("find_node response: %s\n", print_entry(response).c_str());
2775 		TEST_ERROR(error_string);
2776 	}
2777 }
2778 
TORRENT_TEST(multi_home)2779 TORRENT_TEST(multi_home)
2780 {
2781 	// send a request with a different listen socket and make sure the node ignores it
2782 	dht_test_setup t(udp::endpoint(rand_v4(), 20));
2783 	bdecode_node response;
2784 
2785 	entry e;
2786 	e["q"] = "ping";
2787 	e["t"] = "10";
2788 	e["y"] = "q";
2789 	e["a"].dict().insert(std::make_pair("id", generate_next().to_string()));
2790 	char msg_buf[1500];
2791 	int size = bencode(msg_buf, e);
2792 
2793 	bdecode_node decoded;
2794 	error_code ec;
2795 	bdecode(msg_buf, msg_buf + size, decoded, ec);
2796 	if (ec) std::printf("bdecode failed: %s\n", ec.message().c_str());
2797 
2798 	dht::msg m(decoded, t.source);
2799 	t.dht_node.incoming(dummy_listen_socket(udp::endpoint(rand_v4(), 21)), m);
2800 	TEST_CHECK(g_sent_packets.empty());
2801 	g_sent_packets.clear();
2802 }
2803 
TORRENT_TEST(signing_test1)2804 TORRENT_TEST(signing_test1)
2805 {
2806 	// test vector 1
2807 
2808 	// test content
2809 	span<char const> test_content("12:Hello World!", 15);
2810 	// test salt
2811 	span<char const> test_salt("foobar", 6);
2812 
2813 	public_key pk;
2814 	secret_key sk;
2815 	get_test_keypair(pk, sk);
2816 
2817 	signature sig;
2818 	sig = sign_mutable_item(test_content, empty_salt, sequence_number(1), pk, sk);
2819 
2820 	TEST_EQUAL(aux::to_hex(sig.bytes)
2821 		, "305ac8aeb6c9c151fa120f120ea2cfb923564e11552d06a5d856091e5e853cff"
2822 		"1260d3f39e4999684aa92eb73ffd136e6f4f3ecbfda0ce53a1608ecd7ae21f01");
2823 
2824 	sha1_hash const target_id = item_target_id(empty_salt, pk);
2825 	TEST_EQUAL(aux::to_hex(target_id), "4a533d47ec9c7d95b1ad75f576cffc641853b750");
2826 }
2827 
TORRENT_TEST(signing_test2)2828 TORRENT_TEST(signing_test2)
2829 {
2830 	public_key pk;
2831 	secret_key sk;
2832 	get_test_keypair(pk, sk);
2833 
2834 	// test content
2835 	span<char const> test_content("12:Hello World!", 15);
2836 
2837 	signature sig;
2838 	// test salt
2839 	span<char const> test_salt("foobar", 6);
2840 
2841 	// test vector 2 (the keypair is the same as test 1)
2842 	sig = sign_mutable_item(test_content, test_salt, sequence_number(1), pk, sk);
2843 
2844 	TEST_EQUAL(aux::to_hex(sig.bytes)
2845 		, "6834284b6b24c3204eb2fea824d82f88883a3d95e8b4a21b8c0ded553d17d17d"
2846 		"df9a8a7104b1258f30bed3787e6cb896fca78c58f8e03b5f18f14951a87d9a08");
2847 
2848 	sha1_hash target_id = item_target_id(test_salt, pk);
2849 	TEST_EQUAL(aux::to_hex(target_id), "411eba73b6f087ca51a3795d9c8c938d365e32c1");
2850 }
2851 
TORRENT_TEST(signing_test3)2852 TORRENT_TEST(signing_test3)
2853 {
2854 	// test vector 3
2855 
2856 	// test content
2857 	span<char const> test_content("12:Hello World!", 15);
2858 
2859 	sha1_hash target_id = item_target_id(test_content);
2860 	TEST_EQUAL(aux::to_hex(target_id), "e5f96f6f38320f0f33959cb4d3d656452117aadb");
2861 }
2862 
2863 // TODO: 2 split this up into smaller test cases
TORRENT_TEST(verify_message)2864 TORRENT_TEST(verify_message)
2865 {
2866 	char error_string[200];
2867 
2868 	// test verify_message
2869 	static const key_desc_t msg_desc[] = {
2870 		{"A", bdecode_node::string_t, 4, 0},
2871 		{"B", bdecode_node::dict_t, 0, key_desc_t::optional | key_desc_t::parse_children},
2872 			{"B1", bdecode_node::string_t, 0, 0},
2873 			{"B2", bdecode_node::string_t, 0, key_desc_t::last_child},
2874 		{"C", bdecode_node::dict_t, 0, key_desc_t::optional | key_desc_t::parse_children},
2875 			{"C1", bdecode_node::string_t, 0, 0},
2876 			{"C2", bdecode_node::string_t, 0, key_desc_t::last_child},
2877 	};
2878 
2879 	bdecode_node msg_keys[7];
2880 
2881 	bdecode_node ent;
2882 
2883 	error_code ec;
2884 	char const test_msg[] = "d1:A4:test1:Bd2:B15:test22:B25:test3ee";
2885 	bdecode(test_msg, test_msg + sizeof(test_msg)-1, ent, ec);
2886 	std::printf("%s\n", print_entry(ent).c_str());
2887 
2888 	bool ret = verify_message(ent, msg_desc, msg_keys, error_string);
2889 	TEST_CHECK(ret);
2890 	TEST_CHECK(msg_keys[0]);
2891 	if (msg_keys[0]) TEST_EQUAL(msg_keys[0].string_value(), "test");
2892 	TEST_CHECK(msg_keys[1]);
2893 	TEST_CHECK(msg_keys[2]);
2894 	if (msg_keys[2]) TEST_EQUAL(msg_keys[2].string_value(), "test2");
2895 	TEST_CHECK(msg_keys[3]);
2896 	if (msg_keys[3]) TEST_EQUAL(msg_keys[3].string_value(), "test3");
2897 	TEST_CHECK(!msg_keys[4]);
2898 	TEST_CHECK(!msg_keys[5]);
2899 	TEST_CHECK(!msg_keys[6]);
2900 
2901 	char const test_msg2[] = "d1:A4:test1:Cd2:C15:test22:C25:test3ee";
2902 	bdecode(test_msg2, test_msg2 + sizeof(test_msg2)-1, ent, ec);
2903 	std::printf("%s\n", print_entry(ent).c_str());
2904 
2905 	ret = verify_message(ent, msg_desc, msg_keys, error_string);
2906 	TEST_CHECK(ret);
2907 	TEST_CHECK(msg_keys[0]);
2908 	if (msg_keys[0]) TEST_EQUAL(msg_keys[0].string_value(), "test");
2909 	TEST_CHECK(!msg_keys[1]);
2910 	TEST_CHECK(!msg_keys[2]);
2911 	TEST_CHECK(!msg_keys[3]);
2912 	TEST_CHECK(msg_keys[4]);
2913 	TEST_CHECK(msg_keys[5]);
2914 	if (msg_keys[5]) TEST_EQUAL(msg_keys[5].string_value(), "test2");
2915 	TEST_CHECK(msg_keys[6]);
2916 	if (msg_keys[6]) TEST_EQUAL(msg_keys[6].string_value(), "test3");
2917 
2918 
2919 	char const test_msg3[] = "d1:Cd2:C15:test22:C25:test3ee";
2920 	bdecode(test_msg3, test_msg3 + sizeof(test_msg3)-1, ent, ec);
2921 	std::printf("%s\n", print_entry(ent).c_str());
2922 
2923 	ret = verify_message(ent, msg_desc, msg_keys, error_string);
2924 	TEST_CHECK(!ret);
2925 	std::printf("%s\n", error_string);
2926 	TEST_EQUAL(error_string, std::string("missing 'A' key"));
2927 
2928 	char const test_msg4[] = "d1:A6:foobare";
2929 	bdecode(test_msg4, test_msg4 + sizeof(test_msg4)-1, ent, ec);
2930 	std::printf("%s\n", print_entry(ent).c_str());
2931 
2932 	ret = verify_message(ent, msg_desc, msg_keys, error_string);
2933 	TEST_CHECK(!ret);
2934 	std::printf("%s\n", error_string);
2935 	TEST_EQUAL(error_string, std::string("invalid value for 'A'"));
2936 
2937 	char const test_msg5[] = "d1:A4:test1:Cd2:C15:test2ee";
2938 	bdecode(test_msg5, test_msg5 + sizeof(test_msg5)-1, ent, ec);
2939 	std::printf("%s\n", print_entry(ent).c_str());
2940 
2941 	ret = verify_message(ent, msg_desc, msg_keys, error_string);
2942 	TEST_CHECK(!ret);
2943 	std::printf("%s\n", error_string);
2944 	TEST_EQUAL(error_string, std::string("missing 'C2' key"));
2945 
2946 	// test empty strings [ { "":1 }, "" ]
2947 	char const test_msg6[] = "ld0:i1ee0:e";
2948 	bdecode(test_msg6, test_msg6 + sizeof(test_msg6)-1, ent, ec);
2949 	std::printf("%s\n", print_entry(ent).c_str());
2950 	TEST_CHECK(ent.type() == bdecode_node::list_t);
2951 	if (ent.type() == bdecode_node::list_t)
2952 	{
2953 		TEST_CHECK(ent.list_size() == 2);
2954 		if (ent.list_size() == 2)
2955 		{
2956 			TEST_CHECK(ent.list_at(0).dict_find_int_value("") == 1);
2957 			TEST_CHECK(ent.list_at(1).string_value() == "");
2958 		}
2959 	}
2960 }
2961 
TORRENT_TEST(routing_table_uniform)2962 TORRENT_TEST(routing_table_uniform)
2963 {
2964 	// test routing table
2965 	dht::settings sett = test_settings();
2966 	obs observer;
2967 
2968 	sett.extended_routing_table = false;
2969 	// it's difficult to generate valid nodes with specific node IDs, so just
2970 	// turn off that check
2971 	sett.prefer_verified_node_ids = false;
2972 	node_id id = to_hash("1234876923549721020394873245098347598635");
2973 	node_id diff = to_hash("15764f7459456a9453f8719b09547c11d5f34061");
2974 
2975 	routing_table tbl(id, udp::v4(), 8, sett, &observer);
2976 
2977 	// insert 256 nodes evenly distributed across the ID space.
2978 	// we expect to fill the top 5 buckets
2979 	for (int i = 255; i >= 0; --i)
2980 	{
2981 		// test a node with the same IP:port changing ID
2982 		add_and_replace(id, diff);
2983 		// in order to make this node-load a bit more realistic, start from
2984 		// distant nodes and work our way in closer to the node id
2985 		// the routing table will reject nodes that are too imbalanced (if all
2986 		// nodes are very close to our ID and none are far away, it's
2987 		// suspicious).
2988 		id[0] ^= i;
2989 		tbl.node_seen(id, rand_udp_ep(), 20 + (id[19] & 0xff));
2990 
2991 		// restore the first byte of the node ID
2992 		id[0] ^= i;
2993 	}
2994 	std::printf("num_active_buckets: %d\n", tbl.num_active_buckets());
2995 	// number of nodes per tree level (when adding 256 evenly distributed
2996 	// nodes):
2997 	// 0: 128
2998 	// 1: 64
2999 	// 2: 32
3000 	// 3: 16
3001 	// 4: 8
3002 	// i.e. no more than 5 levels
3003 	TEST_EQUAL(tbl.num_active_buckets(), 6);
3004 
3005 	print_state(std::cout, tbl);
3006 }
3007 
TORRENT_TEST(routing_table_balance)3008 TORRENT_TEST(routing_table_balance)
3009 {
3010 	dht::settings sett = test_settings();
3011 	obs observer;
3012 
3013 	sett.extended_routing_table = false;
3014 	sett.prefer_verified_node_ids = false;
3015 	node_id id = to_hash("1234876923549721020394873245098347598635");
3016 
3017 	routing_table tbl(id, udp::v4(), 8, sett, &observer);
3018 
3019 	// insert nodes in the routing table that will force it to split
3020 	// and make sure we don't end up with a table completely out of balance
3021 	for (int i = 0; i < 32; ++i)
3022 	{
3023 		id[0] = (i << 3) & 0xff;
3024 		tbl.node_seen(id, rand_udp_ep(), 20 + (id[19] & 0xff));
3025 	}
3026 	std::printf("num_active_buckets: %d\n", tbl.num_active_buckets());
3027 	TEST_EQUAL(tbl.num_active_buckets(), 2);
3028 
3029 	print_state(std::cout, tbl);
3030 }
3031 
TORRENT_TEST(routing_table_extended)3032 TORRENT_TEST(routing_table_extended)
3033 {
3034 	dht::settings sett = test_settings();
3035 	obs observer;
3036 	sett.extended_routing_table = true;
3037 	sett.prefer_verified_node_ids = false;
3038 	node_id id = to_hash("1234876923549721020394873245098347598635");
3039 	node_id diff = to_hash("15764f7459456a9453f8719b09547c11d5f34061");
3040 
3041 	// we can't add the nodes in straight 0,1,2,3 order. That way the routing
3042 	// table would get unbalanced and intermediate nodes would be dropped
3043 	std::vector<std::uint8_t> node_id_prefix;
3044 	node_id_prefix.reserve(256);
3045 	for (int i = 0; i < 256; ++i) node_id_prefix.push_back(i & 0xff);
3046 	aux::random_shuffle(node_id_prefix);
3047 
3048 	routing_table tbl(id, udp::v4(), 8, sett, &observer);
3049 	for (std::size_t i = 0; i < 256; ++i)
3050 	{
3051 		add_and_replace(id, diff);
3052 		id[0] = node_id_prefix[i];
3053 		tbl.node_seen(id, rand_udp_ep(), 20 + (id[19] & 0xff));
3054 	}
3055 	TEST_EQUAL(tbl.num_active_buckets(), 6);
3056 
3057 	print_state(std::cout, tbl);
3058 }
3059 
3060 namespace {
inserter(std::set<node_id> * nodes,node_entry const & ne)3061 void inserter(std::set<node_id>* nodes, node_entry const& ne)
3062 {
3063 	nodes->insert(nodes->begin(), ne.id);
3064 }
3065 } // anonymous namespace
3066 
TORRENT_TEST(routing_table_set_id)3067 TORRENT_TEST(routing_table_set_id)
3068 {
3069 	dht::settings sett = test_settings();
3070 	sett.enforce_node_id = false;
3071 	sett.extended_routing_table = false;
3072 	sett.prefer_verified_node_ids = false;
3073 	obs observer;
3074 	node_id id = to_hash("0000000000000000000000000000000000000000");
3075 
3076 	// we can't add the nodes in straight 0,1,2,3 order. That way the routing
3077 	// table would get unbalanced and intermediate nodes would be dropped
3078 	std::vector<std::uint8_t> node_id_prefix;
3079 	node_id_prefix.reserve(256);
3080 	for (int i = 0; i < 256; ++i) node_id_prefix.push_back(i & 0xff);
3081 	aux::random_shuffle(node_id_prefix);
3082 	routing_table tbl(id, udp::v4(), 8, sett, &observer);
3083 	for (std::size_t i = 0; i < 256; ++i)
3084 	{
3085 		id[0] = node_id_prefix[i];
3086 		tbl.node_seen(id, rand_udp_ep(), 20 + (id[19] & 0xff));
3087 	}
3088 	TEST_EQUAL(tbl.num_active_buckets(), 6);
3089 
3090 	std::set<node_id> original_nodes;
3091 	tbl.for_each_node(std::bind(&inserter, &original_nodes, _1));
3092 
3093 	print_state(std::cout, tbl);
3094 
3095 	id = to_hash("ffffffffffffffffffffffffffffffffffffffff");
3096 
3097 	tbl.update_node_id(id);
3098 
3099 	TEST_CHECK(tbl.num_active_buckets() <= 4);
3100 	std::set<node_id> remaining_nodes;
3101 	tbl.for_each_node(std::bind(&inserter, &remaining_nodes, _1));
3102 
3103 	std::set<node_id> intersection;
3104 	std::set_intersection(remaining_nodes.begin(), remaining_nodes.end()
3105 		, original_nodes.begin(), original_nodes.end()
3106 		, std::inserter(intersection, intersection.begin()));
3107 
3108 	// all remaining nodes also exist in the original nodes
3109 	TEST_EQUAL(intersection.size(), remaining_nodes.size());
3110 
3111 	print_state(std::cout, tbl);
3112 }
3113 
TORRENT_TEST(routing_table_for_each)3114 TORRENT_TEST(routing_table_for_each)
3115 {
3116 	dht::settings sett = test_settings();
3117 	obs observer;
3118 
3119 	sett.extended_routing_table = false;
3120 	sett.prefer_verified_node_ids = false;
3121 	node_id id = to_hash("1234876923549721020394873245098347598635");
3122 
3123 	routing_table tbl(id, udp::v4(), 2, sett, &observer);
3124 
3125 	for (int i = 0; i < 32; ++i)
3126 	{
3127 		id[0] = (i << 3) & 0xff;
3128 		tbl.node_seen(id, rand_udp_ep(), 20 + (id[19] & 0xff));
3129 	}
3130 
3131 	int nodes;
3132 	int replacements;
3133 	std::tie(nodes, replacements, std::ignore) = tbl.size();
3134 
3135 	std::printf("num_active_buckets: %d\n", tbl.num_active_buckets());
3136 	std::printf("live nodes: %d\n", nodes);
3137 	std::printf("replacements: %d\n", replacements);
3138 
3139 	TEST_EQUAL(tbl.num_active_buckets(), 2);
3140 	TEST_EQUAL(nodes, 4);
3141 	TEST_EQUAL(replacements, 4);
3142 
3143 	print_state(std::cout, tbl);
3144 
3145 	std::vector<node_entry> v;
3146 	tbl.for_each_node([&](node_entry const& e) { v.push_back(e); }, nullptr);
3147 	TEST_EQUAL(v.size(), 4);
3148 	v.clear();
3149 	tbl.for_each_node(nullptr, [&](node_entry const& e) { v.push_back(e); });
3150 	TEST_EQUAL(v.size(), 4);
3151 	v.clear();
3152 	tbl.for_each_node([&](node_entry const& e) { v.push_back(e); });
3153 	TEST_EQUAL(v.size(), 8);
3154 }
3155 
TORRENT_TEST(node_set_id)3156 TORRENT_TEST(node_set_id)
3157 {
3158 	dht_test_setup t(udp::endpoint(rand_v4(), 20));
3159 	node_id old_nid = t.dht_node.nid();
3160 	// put in a few votes to make sure the address really changes
3161 	for (int i = 0; i < 25; ++i)
3162 		t.observer.set_external_address(aux::listen_socket_handle(t.ls), addr4("237.0.0.1"), rand_v4());
3163 	t.dht_node.update_node_id();
3164 	TEST_CHECK(old_nid != t.dht_node.nid());
3165 	// now that we've changed the node's id,  make sure the id sent in outgoing messages
3166 	// reflects the change
3167 
3168 	bdecode_node response;
3169 	send_dht_request(t.dht_node, "ping", t.source, &response);
3170 
3171 	dht::key_desc_t const pong_desc[] = {
3172 		{ "y", bdecode_node::string_t, 1, 0 },
3173 		{ "t", bdecode_node::string_t, 2, 0 },
3174 		{ "r", bdecode_node::dict_t, 0, key_desc_t::parse_children },
3175 		{ "id", bdecode_node::string_t, 20, key_desc_t::last_child },
3176 	};
3177 	bdecode_node pong_keys[4];
3178 	bool ret = dht::verify_message(response, pong_desc, pong_keys, t.error_string);
3179 	TEST_CHECK(ret);
3180 	if (!ret) return;
3181 
3182 	TEST_EQUAL(node_id(pong_keys[3].string_ptr()), t.dht_node.nid());
3183 }
3184 
TORRENT_TEST(read_only_node)3185 TORRENT_TEST(read_only_node)
3186 {
3187 	// TODO: 3 use dht_test_setup class to simplify the node setup
3188 	dht::settings sett = test_settings();
3189 	sett.read_only = true;
3190 	mock_socket s;
3191 	auto ls = dummy_listen_socket4();
3192 	obs observer;
3193 	counters cnt;
3194 
3195 	std::unique_ptr<dht_storage_interface> dht_storage(dht_default_storage_constructor(sett));
3196 	dht_storage->update_node_ids({node_id(nullptr)});
3197 	dht::node node(ls, &s, sett, node_id(nullptr), &observer, cnt, get_foreign_node_stub, *dht_storage);
3198 	udp::endpoint source(addr("10.0.0.1"), 20);
3199 	bdecode_node response;
3200 	msg_args args;
3201 
3202 	// for incoming requests, read_only node won't response.
3203 	send_dht_request(node, "ping", source, &response, args, "10", false);
3204 	TEST_EQUAL(response.type(), bdecode_node::none_t);
3205 
3206 	args.target(sha1_hash("01010101010101010101"));
3207 	send_dht_request(node, "get", source, &response, args, "10", false);
3208 	TEST_EQUAL(response.type(), bdecode_node::none_t);
3209 
3210 	// also, the sender shouldn't be added to routing table.
3211 	TEST_EQUAL(std::get<0>(node.size()), 0);
3212 
3213 	// for outgoing requests, read_only node will add 'ro' key (value == 1)
3214 	// in top-level of request.
3215 	bdecode_node parsed[7];
3216 	char error_string[200];
3217 	udp::endpoint initial_node(addr("4.4.4.4"), 1234);
3218 	dht::node_id const initial_node_id = to_hash("1111111111222222222233333333334444444444");
3219 	node.m_table.add_node(node_entry{initial_node_id, initial_node, 10, true});
3220 	bdecode_node request;
3221 	sha1_hash target = generate_next();
3222 
3223 	node.get_item(target, get_immutable_item_cb);
3224 	TEST_EQUAL(g_sent_packets.size(), 1);
3225 	TEST_EQUAL(g_sent_packets.front().first, initial_node);
3226 
3227 	dht::key_desc_t const get_item_desc_ro[] = {
3228 		{"y", bdecode_node::string_t, 1, 0},
3229 		{"t", bdecode_node::string_t, 2, 0},
3230 		{"q", bdecode_node::string_t, 3, 0},
3231 		{"ro", bdecode_node::int_t, 4, key_desc_t::optional},
3232 		{"a", bdecode_node::dict_t, 0, key_desc_t::parse_children},
3233 			{"id", bdecode_node::string_t, 20, 0},
3234 			{"target", bdecode_node::string_t, 20, key_desc_t::last_child},
3235 	};
3236 
3237 	node_from_entry(g_sent_packets.front().second, request);
3238 	bool ret = verify_message(request, get_item_desc_ro, parsed, error_string);
3239 
3240 	TEST_CHECK(ret);
3241 	TEST_EQUAL(parsed[3].int_value(), 1);
3242 
3243 	// should have one node now, which is 4.4.4.4:1234
3244 	TEST_EQUAL(std::get<0>(node.size()), 1);
3245 	// and no replacement nodes
3246 	TEST_EQUAL(std::get<1>(node.size()), 0);
3247 
3248 	// now, disable read_only, try again.
3249 	g_sent_packets.clear();
3250 	sett.read_only = false;
3251 
3252 	send_dht_request(node, "get", source, &response);
3253 	// sender should be added to repacement bucket
3254 	TEST_EQUAL(std::get<1>(node.size()), 1);
3255 
3256 	g_sent_packets.clear();
3257 #if 0
3258 	// TODO: this won't work because the second node isn't pinged so it wont
3259 	// be added to the routing table
3260 	target = generate_next();
3261 	node.get_item(target, get_immutable_item_cb);
3262 
3263 	// since we have 2 nodes, we should have two packets.
3264 	TEST_EQUAL(g_sent_packets.size(), 2);
3265 
3266 	// both of them shouldn't have a 'ro' key.
3267 	node_from_entry(g_sent_packets.front().second, request);
3268 	ret = verify_message(request, get_item_desc_ro, parsed, error_string);
3269 
3270 	TEST_CHECK(ret);
3271 	TEST_CHECK(!parsed[3]);
3272 
3273 	node_from_entry(g_sent_packets.back().second, request);
3274 	ret = verify_message(request, get_item_desc_ro, parsed, error_string);
3275 
3276 	TEST_CHECK(ret);
3277 	TEST_CHECK(!parsed[3]);
3278 #endif
3279 }
3280 
3281 #ifndef TORRENT_DISABLE_LOGGING
3282 // these tests rely on logging being enabled
3283 
TORRENT_TEST(invalid_error_msg)3284 TORRENT_TEST(invalid_error_msg)
3285 {
3286 	// TODO: 3 use dht_test_setup class to simplify the node setup
3287 	dht::settings sett = test_settings();
3288 	mock_socket s;
3289 	auto ls = dummy_listen_socket4();
3290 	obs observer;
3291 	counters cnt;
3292 
3293 	std::unique_ptr<dht_storage_interface> dht_storage(dht_default_storage_constructor(sett));
3294 	dht_storage->update_node_ids({node_id(nullptr)});
3295 	dht::node node(ls, &s, sett, node_id(nullptr), &observer, cnt, get_foreign_node_stub, *dht_storage);
3296 	udp::endpoint source(addr("10.0.0.1"), 20);
3297 
3298 	entry e;
3299 	e["y"] = "e";
3300 	e["e"].string() = "Malformed Error";
3301 	char msg_buf[1500];
3302 	int size = bencode(msg_buf, e);
3303 
3304 	bdecode_node decoded;
3305 	error_code ec;
3306 	bdecode(msg_buf, msg_buf + size, decoded, ec);
3307 	if (ec) std::printf("bdecode failed: %s\n", ec.message().c_str());
3308 
3309 	dht::msg m(decoded, source);
3310 	node.incoming(node.m_sock, m);
3311 
3312 	bool found = false;
3313 	for (auto const& log : observer.m_log)
3314 	{
3315 		if (log.find("INCOMING ERROR") != std::string::npos
3316 			&& log.find("(malformed)") != std::string::npos)
3317 			found = true;
3318 
3319 		std::printf("%s\n", log.c_str());
3320 	}
3321 
3322 	TEST_EQUAL(found, true);
3323 }
3324 
3325 struct test_algo : dht::traversal_algorithm
3326 {
test_algotest_algo3327 	test_algo(node& dht_node, node_id const& target)
3328 		: traversal_algorithm(dht_node, target)
3329 	{}
3330 
donetest_algo3331 	void done() { this->dht::traversal_algorithm::done(); }
3332 
resultstest_algo3333 	std::vector<observer_ptr> const& results() const { return m_results; }
3334 
3335 	using traversal_algorithm::num_sorted_results;
3336 };
3337 
TORRENT_TEST(unsorted_traversal_results)3338 TORRENT_TEST(unsorted_traversal_results)
3339 {
3340 	init_rand_address();
3341 
3342 	// make sure the handling of an unsorted tail of nodes is correct in the
3343 	// traversal algorithm. Initial nodes (that we bootstrap from) remain
3344 	// unsorted, since we don't know their node IDs
3345 
3346 	dht_test_setup t(udp::endpoint(rand_v4(), 20));
3347 
3348 	node_id const our_id = t.dht_node.nid();
3349 	auto algo = std::make_shared<test_algo>(t.dht_node, our_id);
3350 
3351 	std::vector<udp::endpoint> eps;
3352 	for (int i = 0; i < 10; ++i)
3353 	{
3354 		eps.push_back(rand_udp_ep(rand_v4));
3355 		algo->add_entry(node_id(), eps.back(), observer::flag_initial);
3356 	}
3357 
3358 	// we should have 10 unsorted nodes now
3359 	TEST_CHECK(algo->num_sorted_results() == 0);
3360 	auto results = algo->results();
3361 	TEST_CHECK(results.size() == eps.size());
3362 	for (std::size_t i = 0; i < eps.size(); ++i)
3363 		TEST_CHECK(eps[i] == results[i]->target_ep());
3364 
3365 	// setting the node ID, regardless of what we set it to, should cause this
3366 	// observer to become sorted. i.e. be moved to the beginning of the result
3367 	// list.
3368 	results[5]->set_id(node_id("abababababababababab"));
3369 
3370 	TEST_CHECK(algo->num_sorted_results() == 1);
3371 	results = algo->results();
3372 	TEST_CHECK(results.size() == eps.size());
3373 	TEST_CHECK(eps[5] == results[0]->target_ep());
3374 	algo->done();
3375 }
3376 
TORRENT_TEST(rpc_invalid_error_msg)3377 TORRENT_TEST(rpc_invalid_error_msg)
3378 {
3379 	// TODO: 3 use dht_test_setup class to simplify the node setup
3380 	dht::settings sett = test_settings();
3381 	mock_socket s;
3382 	auto ls = dummy_listen_socket4();
3383 	obs observer;
3384 	counters cnt;
3385 
3386 	dht::routing_table table(node_id(), udp::v4(), 8, sett, &observer);
3387 	dht::rpc_manager rpc(node_id(), sett, table, ls, &s, &observer);
3388 	std::unique_ptr<dht_storage_interface> dht_storage(dht_default_storage_constructor(sett));
3389 	dht_storage->update_node_ids({node_id(nullptr)});
3390 	dht::node node(ls, &s, sett, node_id(nullptr), &observer, cnt, get_foreign_node_stub, *dht_storage);
3391 
3392 	udp::endpoint source(addr("10.0.0.1"), 20);
3393 
3394 	// we need this to create an entry for this transaction ID, otherwise the
3395 	// incoming message will just be dropped
3396 	entry req;
3397 	req["y"] = "q";
3398 	req["q"] = "bogus_query";
3399 	req["t"] = "\0\0\0\0";
3400 
3401 	g_sent_packets.clear();
3402 	auto algo = std::make_shared<dht::traversal_algorithm>(node, node_id());
3403 
3404 	auto o = rpc.allocate_observer<null_observer>(std::move(algo), source, node_id());
3405 #if TORRENT_USE_ASSERTS
3406 	o->m_in_constructor = false;
3407 #endif
3408 	rpc.invoke(req, source, o);
3409 
3410 	// here's the incoming (malformed) error message
3411 	entry err;
3412 	err["y"] = "e";
3413 	err["e"].string() = "Malformed Error";
3414 	err["t"] = g_sent_packets.begin()->second["t"].string();
3415 	char msg_buf[1500];
3416 	int size = bencode(msg_buf, err);
3417 
3418 	bdecode_node decoded;
3419 	error_code ec;
3420 	bdecode(msg_buf, msg_buf + size, decoded, ec);
3421 	if (ec) std::printf("bdecode failed: %s\n", ec.message().c_str());
3422 
3423 	dht::msg m(decoded, source);
3424 	node_id nid;
3425 	rpc.incoming(m, &nid);
3426 
3427 	bool found = false;
3428 	for (auto const& log : observer.m_log)
3429 	{
3430 		if (log.find("reply with") != std::string::npos
3431 			&& log.find("(malformed)") != std::string::npos
3432 			&& log.find("error") != std::string::npos)
3433 			found = true;
3434 
3435 		std::printf("%s\n", log.c_str());
3436 	}
3437 
3438 	TEST_EQUAL(found, true);
3439 }
3440 #endif
3441 
3442 // test bucket distribution
TORRENT_TEST(node_id_bucket_distribution)3443 TORRENT_TEST(node_id_bucket_distribution)
3444 {
3445 	init_rand_address();
3446 
3447 	int nodes_per_bucket[160] = {0};
3448 	dht::node_id reference_id = generate_id(rand_v4());
3449 	int const num_samples = 100000;
3450 	for (int i = 0; i < num_samples; ++i)
3451 	{
3452 		dht::node_id nid = generate_id(rand_v4());
3453 		int const bucket = 159 - distance_exp(reference_id, nid);
3454 		++nodes_per_bucket[bucket];
3455 	}
3456 
3457 	for (int i = 0; i < 25; ++i)
3458 	{
3459 		std::printf("%3d ", nodes_per_bucket[i]);
3460 	}
3461 	std::printf("\n");
3462 
3463 	int expected = num_samples / 2;
3464 	for (int i = 0; i < 25; ++i)
3465 	{
3466 		TEST_CHECK(std::abs(nodes_per_bucket[i] - expected) < num_samples / 20);
3467 		expected /= 2;
3468 	}
3469 }
3470 
TORRENT_TEST(node_id_min_distance_exp)3471 TORRENT_TEST(node_id_min_distance_exp)
3472 {
3473 	node_id const n1 = to_hash("0000000000000000000000000000000000000002");
3474 	node_id const n2 = to_hash("0000000000000000000000000000000000000004");
3475 	node_id const n3 = to_hash("0000000000000000000000000000000000000008");
3476 
3477 	std::vector<node_id> ids;
3478 
3479 	ids.push_back(n1);
3480 
3481 	TEST_EQUAL(min_distance_exp(sha1_hash::min(), ids), 1);
3482 
3483 	ids.push_back(n1);
3484 	ids.push_back(n2);
3485 
3486 	TEST_EQUAL(min_distance_exp(sha1_hash::min(), ids), 1);
3487 
3488 	ids.push_back(n1);
3489 	ids.push_back(n2);
3490 	ids.push_back(n3);
3491 
3492 	TEST_EQUAL(min_distance_exp(sha1_hash::min(), ids), 1);
3493 
3494 	ids.clear();
3495 	ids.push_back(n3);
3496 	ids.push_back(n2);
3497 	ids.push_back(n2);
3498 
3499 	TEST_EQUAL(min_distance_exp(sha1_hash::min(), ids), 2);
3500 }
3501 
TORRENT_TEST(dht_verify_node_address)3502 TORRENT_TEST(dht_verify_node_address)
3503 {
3504 	obs observer;
3505 	// initial setup taken from dht test above
3506 	dht::settings s;
3507 	s.extended_routing_table = false;
3508 	node_id id = to_hash("3123456789abcdef01232456789abcdef0123456");
3509 	const int bucket_size = 8;
3510 	dht::routing_table table(id, udp::v4(), bucket_size, s, &observer);
3511 	std::vector<node_entry> nodes;
3512 	TEST_EQUAL(std::get<0>(table.size()), 0);
3513 
3514 	node_id tmp = id;
3515 	node_id diff = to_hash("15764f7459456a9453f8719b09547c11d5f34061");
3516 
3517 	add_and_replace(tmp, diff);
3518 	table.node_seen(tmp, udp::endpoint(addr("4.4.4.4"), 4), 10);
3519 	table.find_node(id, nodes, 0, 10);
3520 	TEST_EQUAL(std::get<0>(table.size()), 1);
3521 	TEST_EQUAL(nodes.size(), 1);
3522 
3523 	// incorrect data, wrong IP
3524 	table.node_seen(tmp
3525 		, udp::endpoint(addr("4.4.4.6"), 4), 10);
3526 	table.find_node(id, nodes, 0, 10);
3527 
3528 	TEST_EQUAL(std::get<0>(table.size()), 1);
3529 	TEST_EQUAL(nodes.size(), 1);
3530 
3531 	// incorrect data, wrong id, should cause node to be removed
3532 	table.node_seen(to_hash("0123456789abcdef01232456789abcdef0123456")
3533 		, udp::endpoint(addr("4.4.4.4"), 4), 10);
3534 	table.find_node(id, nodes, 0, 10);
3535 
3536 	TEST_EQUAL(std::get<0>(table.size()), 0);
3537 	TEST_EQUAL(nodes.size(), 0);
3538 }
3539 
TORRENT_TEST(generate_prefix_mask)3540 TORRENT_TEST(generate_prefix_mask)
3541 {
3542 	std::vector<std::pair<int, char const*>> const test = {
3543 		{   0, "0000000000000000000000000000000000000000" },
3544 		{   1, "8000000000000000000000000000000000000000" },
3545 		{   2, "c000000000000000000000000000000000000000" },
3546 		{  11, "ffe0000000000000000000000000000000000000" },
3547 		{  17, "ffff800000000000000000000000000000000000" },
3548 		{  37, "fffffffff8000000000000000000000000000000" },
3549 		{ 160, "ffffffffffffffffffffffffffffffffffffffff" },
3550 	};
3551 
3552 	for (auto const& i : test)
3553 	{
3554 		TEST_EQUAL(generate_prefix_mask(i.first), to_hash(i.second));
3555 	}
3556 }
3557 
TORRENT_TEST(distance_exp)3558 TORRENT_TEST(distance_exp)
3559 {
3560 	// distance_exp
3561 
3562 
3563 	using tst = std::tuple<char const*, char const*, int>;
3564 
3565 	std::vector<std::tuple<char const*, char const*, int>> const distance_tests = {
3566 		tst{ "ffffffffffffffffffffffffffffffffffffffff"
3567 		, "0000000000000000000000000000000000000000", 159 },
3568 
3569 		tst{ "ffffffffffffffffffffffffffffffffffffffff"
3570 		, "7fffffffffffffffffffffffffffffffffffffff", 159 },
3571 
3572 		tst{ "ffffffffffffffffffffffffffffffffffffffff"
3573 		, "ffffffffffffffffffffffffffffffffffffffff", 0 },
3574 
3575 		tst{ "ffffffffffffffffffffffffffffffffffffffff"
3576 		, "fffffffffffffffffffffffffffffffffffffffe", 0 },
3577 
3578 		tst{ "8000000000000000000000000000000000000000"
3579 		, "fffffffffffffffffffffffffffffffffffffffe", 158 },
3580 
3581 		tst{ "c000000000000000000000000000000000000000"
3582 		, "fffffffffffffffffffffffffffffffffffffffe", 157 },
3583 
3584 		tst{ "e000000000000000000000000000000000000000"
3585 		, "fffffffffffffffffffffffffffffffffffffffe", 156 },
3586 
3587 		tst{ "f000000000000000000000000000000000000000"
3588 		, "fffffffffffffffffffffffffffffffffffffffe", 155 },
3589 
3590 		tst{ "f8f2340985723049587230495872304958703294"
3591 		, "f743589043r890f023980f90e203980d090c3840", 155 },
3592 
3593 		tst{ "ffff740985723049587230495872304958703294"
3594 		, "ffff889043r890f023980f90e203980d090c3840", 159 - 16 },
3595 	};
3596 
3597 	for (auto const& t : distance_tests)
3598 	{
3599 		std::printf("%s %s: %d\n"
3600 			, std::get<0>(t), std::get<1>(t), std::get<2>(t));
3601 
3602 		TEST_EQUAL(distance_exp(to_hash(std::get<0>(t))
3603 				, to_hash(std::get<1>(t))), std::get<2>(t));
3604 	}
3605 }
3606 
TORRENT_TEST(compare_ip_cidr)3607 TORRENT_TEST(compare_ip_cidr)
3608 {
3609 	using tst = std::tuple<char const*, char const*, bool>;
3610 	std::vector<tst> const v4tests = {
3611 		tst{"10.255.255.0", "10.255.255.255", true},
3612 		tst{"11.0.0.0", "10.255.255.255", false},
3613 		tst{"0.0.0.0", "128.255.255.255", false},
3614 		tst{"0.0.0.0", "127.255.255.255", false},
3615 		tst{"255.255.255.0", "255.255.255.255", true},
3616 		tst{"255.254.255.0", "255.255.255.255", false},
3617 		tst{"0.0.0.0", "0.0.0.0", true},
3618 		tst{"255.255.255.255", "255.255.255.255", true},
3619 	};
3620 
3621 	for (auto const& t : v4tests)
3622 	{
3623 		std::printf("%s %s\n", std::get<0>(t), std::get<1>(t));
3624 		TEST_EQUAL(compare_ip_cidr(
3625 			addr4(std::get<0>(t)), addr4(std::get<1>(t))), std::get<2>(t));
3626 	}
3627 
3628 	std::vector<tst> const v6tests = {
3629 		tst{"::1", "::ffff:ffff:ffff:ffff", true},
3630 		tst{"::2:0000:0000:0000:0000", "::1:ffff:ffff:ffff:ffff", false},
3631 		tst{"::ff:0000:0000:0000:0000", "::ffff:ffff:ffff:ffff", false},
3632 		tst{"::caca:0000:0000:0000:0000", "::ffff:ffff:ffff:ffff:ffff", false},
3633 		tst{"::a:0000:0000:0000:0000", "::b:ffff:ffff:ffff:ffff", false},
3634 		tst{"::7f:0000:0000:0000:0000", "::ffff:ffff:ffff:ffff", false},
3635 		tst{"7f::", "ff::", false},
3636 		tst{"ff::", "ff::", true},
3637 		tst{"::", "::", true},
3638 		tst{"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", true},
3639 	};
3640 
3641 	for (auto const& t : v6tests)
3642 	{
3643 		TEST_EQUAL(compare_ip_cidr(
3644 			addr6(std::get<0>(t)), addr6(std::get<1>(t))), std::get<2>(t));
3645 	}
3646 }
3647 
TORRENT_TEST(dht_state)3648 TORRENT_TEST(dht_state)
3649 {
3650 	dht_state s;
3651 
3652 	s.nids.emplace_back(address::from_string("1.1.1.1"), to_hash("0000000000000000000000000000000000000001"));
3653 	s.nodes.push_back(uep("1.1.1.1", 1));
3654 	s.nodes.push_back(uep("2.2.2.2", 2));
3655 	// remove these for now because they will only get used if the host system has IPv6 support
3656 	// hopefully in the future we can rely on the test system supporting IPv6
3657 	//s.nids.emplace_back(address::from_string("1::1"), to_hash("0000000000000000000000000000000000000002"));
3658 	//s.nodes6.push_back(uep("1::1", 3));
3659 	//s.nodes6.push_back(uep("2::2", 4));
3660 
3661 	entry const e = save_dht_state(s);
3662 
3663 	std::vector<char> tmp;
3664 	bencode(std::back_inserter(tmp), e);
3665 
3666 	bdecode_node n;
3667 	error_code ec;
3668 	int r = bdecode(&tmp[0], &tmp[0] + tmp.size(), n, ec);
3669 	TEST_CHECK(!r);
3670 
3671 	dht_state const s1 = read_dht_state(n);
3672 	TEST_CHECK(s1.nids == s.nids);
3673 	TEST_CHECK(s1.nodes == s.nodes);
3674 
3675 	// empty
3676 	bdecode_node n1;
3677 	dht_state const s2 = read_dht_state(n1);
3678 	TEST_CHECK(s2.nids.empty());
3679 	TEST_CHECK(s2.nodes.empty());
3680 }
3681 
TORRENT_TEST(sample_infohashes)3682 TORRENT_TEST(sample_infohashes)
3683 {
3684 	init_rand_address();
3685 
3686 	dht_test_setup t(rand_udp_ep());
3687 	bdecode_node response;
3688 
3689 	g_sent_packets.clear();
3690 
3691 	udp::endpoint initial_node = rand_udp_ep();
3692 	t.dht_node.m_table.add_node(node_entry{initial_node});
3693 
3694 	// nodes
3695 	sha1_hash const h1 = rand_hash();
3696 	sha1_hash const h2 = rand_hash();
3697 	udp::endpoint const ep1 = rand_udp_ep(rand_v4);
3698 	udp::endpoint const ep2 = rand_udp_ep(rand_v4);
3699 
3700 	t.dht_node.sample_infohashes(initial_node, items[0].target,
3701 		[h1, ep1, h2, ep2](time_duration interval, int num
3702 			, std::vector<sha1_hash> samples
3703 			, std::vector<std::pair<sha1_hash, udp::endpoint>> const& nodes)
3704 	{
3705 		TEST_EQUAL(total_seconds(interval), 10);
3706 		TEST_EQUAL(num, 2);
3707 		TEST_EQUAL(samples.size(), 1);
3708 		TEST_EQUAL(samples[0], to_hash("1000000000000000000000000000000000000001"));
3709 		TEST_EQUAL(nodes.size(), 2);
3710 		TEST_EQUAL(nodes[0].first, h1);
3711 		TEST_EQUAL(nodes[0].second, ep1);
3712 		TEST_EQUAL(nodes[1].first, h2);
3713 		TEST_EQUAL(nodes[1].second, ep2);
3714 	});
3715 
3716 	TEST_EQUAL(g_sent_packets.size(), 1);
3717 	if (g_sent_packets.empty()) return;
3718 	TEST_EQUAL(g_sent_packets.front().first, initial_node);
3719 
3720 	node_from_entry(g_sent_packets.front().second, response);
3721 	bdecode_node sample_infohashes_keys[6];
3722 	bool const ret = verify_message(response
3723 		, sample_infohashes_desc, sample_infohashes_keys, t.error_string);
3724 	if (ret)
3725 	{
3726 		TEST_EQUAL(sample_infohashes_keys[0].string_value(), "q");
3727 		TEST_EQUAL(sample_infohashes_keys[2].string_value(), "sample_infohashes");
3728 		TEST_EQUAL(sample_infohashes_keys[5].string_value(), items[0].target.to_string());
3729 	}
3730 	else
3731 	{
3732 		std::printf("   invalid sample_infohashes request: %s\n", print_entry(response).c_str());
3733 		TEST_ERROR(t.error_string);
3734 		return;
3735 	}
3736 
3737 	std::vector<node_entry> nodes;
3738 	nodes.emplace_back(h1, ep1);
3739 	nodes.emplace_back(h2, ep2);
3740 
3741 	g_sent_packets.clear();
3742 	send_dht_response(t.dht_node, response, initial_node
3743 		, msg_args()
3744 			.interval(seconds(10))
3745 			.num(2)
3746 			.samples({to_hash("1000000000000000000000000000000000000001")})
3747 			.nodes(nodes));
3748 
3749 	TEST_CHECK(g_sent_packets.empty());
3750 }
3751 
3752 namespace {
fake_node(bool verified,int rtt=0)3753 node_entry fake_node(bool verified, int rtt = 0)
3754 {
3755 	node_entry e(rand_udp_ep());
3756 	e.verified = verified;
3757 	e.rtt = static_cast<std::uint16_t>(rtt);
3758 	return e;
3759 }
3760 }
3761 
TORRENT_TEST(node_entry_comparison)3762 TORRENT_TEST(node_entry_comparison)
3763 {
3764 	// being verified or not always trumps RTT in sort order
3765 	TEST_CHECK(fake_node(true, 10) < fake_node(false, 5));
3766 	TEST_CHECK(fake_node(true, 5) < fake_node(false, 10));
3767 	TEST_CHECK(!(fake_node(false, 10) < fake_node(true, 5)));
3768 	TEST_CHECK(!(fake_node(false, 5) < fake_node(true, 10)));
3769 
3770 	// if both are verified, lower RTT is better
3771 	TEST_CHECK(fake_node(true, 5) < fake_node(true, 10));
3772 	TEST_CHECK(!(fake_node(true, 10) < fake_node(true, 5)));
3773 
3774 	// if neither are verified, lower RTT is better
3775 	TEST_CHECK(fake_node(false, 5) < fake_node(false, 10));
3776 	TEST_CHECK(!(fake_node(false, 10) < fake_node(false, 5)));
3777 }
3778 
TORRENT_TEST(mostly_verified_nodes)3779 TORRENT_TEST(mostly_verified_nodes)
3780 {
3781 	// an empty bucket is OK
3782 	TEST_CHECK(mostly_verified_nodes({}));
3783 	TEST_CHECK(mostly_verified_nodes({fake_node(true)}));
3784 	TEST_CHECK(mostly_verified_nodes({fake_node(true), fake_node(false)}));
3785 	TEST_CHECK(mostly_verified_nodes({fake_node(true), fake_node(true), fake_node(false)}));
3786 	TEST_CHECK(mostly_verified_nodes({fake_node(true), fake_node(true), fake_node(true), fake_node(false)}));
3787 
3788 	// a large bucket with only half of the nodes verified, does not count as
3789 	// "mostly"
3790 	TEST_CHECK(!mostly_verified_nodes({fake_node(true), fake_node(false)
3791 		, fake_node(true), fake_node(false)
3792 		, fake_node(true), fake_node(false)
3793 		, fake_node(true), fake_node(false)
3794 		, fake_node(true), fake_node(false)
3795 		, fake_node(true), fake_node(false)}));
3796 
3797 	// 1 of 3 is not "mostly"
3798 	TEST_CHECK(!mostly_verified_nodes({fake_node(false), fake_node(true), fake_node(false)}));
3799 
3800 	TEST_CHECK(!mostly_verified_nodes({fake_node(false)}));
3801 	TEST_CHECK(!mostly_verified_nodes({fake_node(false), fake_node(false)}));
3802 	TEST_CHECK(!mostly_verified_nodes({fake_node(false), fake_node(false), fake_node(false)}));
3803 }
3804 
TORRENT_TEST(classify_prefix)3805 TORRENT_TEST(classify_prefix)
3806 {
3807 	// the last bucket in the routing table
3808 	TEST_EQUAL(int(classify_prefix(0, true, 8, to_hash("0cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdc"))), 0);
3809 	TEST_EQUAL(int(classify_prefix(0, true, 8, to_hash("2cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdc"))), 1);
3810 	TEST_EQUAL(int(classify_prefix(0, true, 8, to_hash("4cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdc"))), 2);
3811 	TEST_EQUAL(int(classify_prefix(0, true, 8, to_hash("6cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdc"))), 3);
3812 	TEST_EQUAL(int(classify_prefix(0, true, 8, to_hash("8cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdc"))), 4);
3813 	TEST_EQUAL(int(classify_prefix(0, true, 8, to_hash("acdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdc"))), 5);
3814 	TEST_EQUAL(int(classify_prefix(0, true, 8, to_hash("ccdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdc"))), 6);
3815 	TEST_EQUAL(int(classify_prefix(0, true, 8, to_hash("ecdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdc"))), 7);
3816 	TEST_EQUAL(int(classify_prefix(0, true, 8, to_hash("fcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdc"))), 7);
3817 
3818 	TEST_EQUAL(int(classify_prefix(4, true, 8, to_hash("c0cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 0);
3819 	TEST_EQUAL(int(classify_prefix(4, true, 8, to_hash("c2cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 1);
3820 	TEST_EQUAL(int(classify_prefix(4, true, 8, to_hash("c4cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 2);
3821 	TEST_EQUAL(int(classify_prefix(4, true, 8, to_hash("c6cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 3);
3822 	TEST_EQUAL(int(classify_prefix(4, true, 8, to_hash("c8cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 4);
3823 	TEST_EQUAL(int(classify_prefix(4, true, 8, to_hash("cacdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 5);
3824 	TEST_EQUAL(int(classify_prefix(4, true, 8, to_hash("cccdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 6);
3825 	TEST_EQUAL(int(classify_prefix(4, true, 8, to_hash("cecdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 7);
3826 	TEST_EQUAL(int(classify_prefix(4, true, 8, to_hash("cfcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 7);
3827 
3828 	TEST_EQUAL(int(classify_prefix(8, true, 8, to_hash("dc0cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdc"))), 0);
3829 	TEST_EQUAL(int(classify_prefix(8, true, 8, to_hash("dc2cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdc"))), 1);
3830 	TEST_EQUAL(int(classify_prefix(8, true, 8, to_hash("dc4cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdc"))), 2);
3831 	TEST_EQUAL(int(classify_prefix(8, true, 8, to_hash("dc6cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdc"))), 3);
3832 	TEST_EQUAL(int(classify_prefix(8, true, 8, to_hash("dc8cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdc"))), 4);
3833 	TEST_EQUAL(int(classify_prefix(8, true, 8, to_hash("dcacdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdc"))), 5);
3834 	TEST_EQUAL(int(classify_prefix(8, true, 8, to_hash("dcccdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdc"))), 6);
3835 	TEST_EQUAL(int(classify_prefix(8, true, 8, to_hash("dcecdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdc"))), 7);
3836 	TEST_EQUAL(int(classify_prefix(8, true, 8, to_hash("dcfcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdc"))), 7);
3837 
3838 	TEST_EQUAL(int(classify_prefix(12, true, 8, to_hash("cdc0cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 0);
3839 	TEST_EQUAL(int(classify_prefix(12, true, 8, to_hash("cdc2cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 1);
3840 	TEST_EQUAL(int(classify_prefix(12, true, 8, to_hash("cdc4cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 2);
3841 	TEST_EQUAL(int(classify_prefix(12, true, 8, to_hash("cdc6cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 3);
3842 	TEST_EQUAL(int(classify_prefix(12, true, 8, to_hash("cdc8cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 4);
3843 	TEST_EQUAL(int(classify_prefix(12, true, 8, to_hash("cdcacdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 5);
3844 	TEST_EQUAL(int(classify_prefix(12, true, 8, to_hash("cdcccdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 6);
3845 	TEST_EQUAL(int(classify_prefix(12, true, 8, to_hash("cdcecdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 7);
3846 	TEST_EQUAL(int(classify_prefix(12, true, 8, to_hash("cdcfcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 7);
3847 
3848 	// not the last bucket in the routing table
3849 	TEST_EQUAL(int(classify_prefix(11, false, 8, to_hash("cdc0cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 0);
3850 	TEST_EQUAL(int(classify_prefix(11, false, 8, to_hash("cdc2cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 1);
3851 	TEST_EQUAL(int(classify_prefix(11, false, 8, to_hash("cdc4cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 2);
3852 	TEST_EQUAL(int(classify_prefix(11, false, 8, to_hash("cdc6cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 3);
3853 	TEST_EQUAL(int(classify_prefix(11, false, 8, to_hash("cdc8cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 4);
3854 	TEST_EQUAL(int(classify_prefix(11, false, 8, to_hash("cdcacdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 5);
3855 	TEST_EQUAL(int(classify_prefix(11, false, 8, to_hash("cdcccdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 6);
3856 	TEST_EQUAL(int(classify_prefix(11, false, 8, to_hash("cdcecdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 7);
3857 	TEST_EQUAL(int(classify_prefix(11, false, 8, to_hash("cdcfcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 7);
3858 
3859 	TEST_EQUAL(int(classify_prefix(12, false, 8, to_hash("cdc8cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 0);
3860 	TEST_EQUAL(int(classify_prefix(12, false, 8, to_hash("cdc9cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 1);
3861 	TEST_EQUAL(int(classify_prefix(12, false, 8, to_hash("cdcacdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 2);
3862 	TEST_EQUAL(int(classify_prefix(12, false, 8, to_hash("cdcbcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 3);
3863 	TEST_EQUAL(int(classify_prefix(12, false, 8, to_hash("cdcccdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 4);
3864 	TEST_EQUAL(int(classify_prefix(12, false, 8, to_hash("cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 5);
3865 	TEST_EQUAL(int(classify_prefix(12, false, 8, to_hash("cdcecdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 6);
3866 	TEST_EQUAL(int(classify_prefix(12, false, 8, to_hash("cdcfcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 7);
3867 	TEST_EQUAL(int(classify_prefix(12, false, 8, to_hash("cdc7cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 7);
3868 
3869 	// larger bucket
3870 	TEST_EQUAL(int(classify_prefix(12, true, 16, to_hash("cdc0cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 0);
3871 	TEST_EQUAL(int(classify_prefix(12, true, 16, to_hash("cdc1cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 1);
3872 	TEST_EQUAL(int(classify_prefix(12, true, 16, to_hash("cdc2cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 2);
3873 	TEST_EQUAL(int(classify_prefix(12, true, 16, to_hash("cdc3cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 3);
3874 	TEST_EQUAL(int(classify_prefix(12, true, 16, to_hash("cdc4cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 4);
3875 	TEST_EQUAL(int(classify_prefix(12, true, 16, to_hash("cdc5cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 5);
3876 	TEST_EQUAL(int(classify_prefix(12, true, 16, to_hash("cdc6cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 6);
3877 	TEST_EQUAL(int(classify_prefix(12, true, 16, to_hash("cdc7cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 7);
3878 	TEST_EQUAL(int(classify_prefix(12, true, 16, to_hash("cdc8cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 8);
3879 	TEST_EQUAL(int(classify_prefix(12, true, 16, to_hash("cdc9cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 9);
3880 	TEST_EQUAL(int(classify_prefix(12, true, 16, to_hash("cdcacdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 10);
3881 	TEST_EQUAL(int(classify_prefix(12, true, 16, to_hash("cdcbcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 11);
3882 	TEST_EQUAL(int(classify_prefix(12, true, 16, to_hash("cdcccdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 12);
3883 	TEST_EQUAL(int(classify_prefix(12, true, 16, to_hash("cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 13);
3884 	TEST_EQUAL(int(classify_prefix(12, true, 16, to_hash("cdcecdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 14);
3885 	TEST_EQUAL(int(classify_prefix(12, true, 16, to_hash("cdcfcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"))), 15);
3886 }
3887 
3888 namespace {
n(ip_set * ips,char const * nid,bool verified=true,int rtt=0,int failed=0)3889 node_entry n(ip_set* ips, char const* nid, bool verified = true, int rtt = 0, int failed = 0)
3890 {
3891 	node_entry e(rand_udp_ep());
3892 	if (ips) ips->insert(e.addr());
3893 	e.verified = verified;
3894 	e.rtt = static_cast<std::uint16_t>(rtt);
3895 	e.id = to_hash(nid);
3896 	if (failed != 0) e.timeout_count = static_cast<std::uint8_t>(failed);
3897 	return e;
3898 }
3899 }
3900 
3901 #ifndef TORRENT_DISABLE_LOGGING
3902 #define LOGGER , nullptr
3903 #else
3904 #define LOGGER
3905 #endif
TORRENT_TEST(replace_node_impl)3906 TORRENT_TEST(replace_node_impl)
3907 {
3908 	// replace specific prefix "slot"
3909 	{
3910 	ip_set p;
3911 	dht::bucket_t b = {
3912 		n(&p, "1fffffffffffffffffffffffffffffffffffffff", true, 50),
3913 		n(&p, "3fffffffffffffffffffffffffffffffffffffff", true, 50),
3914 		n(&p, "5fffffffffffffffffffffffffffffffffffffff", true, 50),
3915 		n(&p, "7fffffffffffffffffffffffffffffffffffffff", true, 50),
3916 		n(&p, "9fffffffffffffffffffffffffffffffffffffff", true, 50), // <== replaced
3917 		n(&p, "bfffffffffffffffffffffffffffffffffffffff", true, 50),
3918 		n(&p, "dfffffffffffffffffffffffffffffffffffffff", true, 50),
3919 		n(&p, "ffffffffffffffffffffffffffffffffffffffff", true, 50),
3920 	};
3921 	TEST_EQUAL(p.size(), 8);
3922 	TEST_CHECK(
3923 		replace_node_impl(n(nullptr, "9fcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd")
3924 	, b, p, 0, 8, true LOGGER) == routing_table::node_added);
3925 	TEST_CHECK(b[4].id == to_hash("9fcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"));
3926 	TEST_EQUAL(p.size(), 8);
3927 	}
3928 
3929 	// only try to replace specific prefix "slot", and if we fail (RTT is
3930 	// higher), don't replace anything else
3931 	{
3932 	ip_set p;
3933 	dht::bucket_t b = {
3934 		n(&p, "1fffffffffffffffffffffffffffffffffffffff", true, 500),
3935 		n(&p, "3fffffffffffffffffffffffffffffffffffffff", true, 500),
3936 		n(&p, "5fffffffffffffffffffffffffffffffffffffff", true, 500),
3937 		n(&p, "7fffffffffffffffffffffffffffffffffffffff", true, 500),
3938 		n(&p, "9fffffffffffffffffffffffffffffffffffffff", true, 50),
3939 		n(&p, "bfffffffffffffffffffffffffffffffffffffff", true, 500),
3940 		n(&p, "dfffffffffffffffffffffffffffffffffffffff", true, 500),
3941 		n(&p, "ffffffffffffffffffffffffffffffffffffffff", true, 500),
3942 	};
3943 	TEST_EQUAL(p.size(), 8);
3944 	TEST_CHECK(
3945 		replace_node_impl(n(nullptr, "9fcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd", true, 100)
3946 	, b, p, 0, 8, true LOGGER) != routing_table::node_added);
3947 	TEST_CHECK(b[4].id == to_hash("9fffffffffffffffffffffffffffffffffffffff"));
3948 	TEST_EQUAL(p.size(), 8);
3949 	}
3950 
3951 	// if there are multiple candidates to replace, pick the one with the highest
3952 	// RTT. We're picking the prefix slots with duplicates
3953 	{
3954 	ip_set p;
3955 	dht::bucket_t b = {
3956 		n(&p, "1fffffffffffffffffffffffffffffffffffffff", true, 50),
3957 		n(&p, "3fffffffffffffffffffffffffffffffffffffff", true, 50),
3958 		n(&p, "5fffffffffffffffffffffffffffffffffffffff", true, 50),
3959 		n(&p, "7fffffffffffffffffffffffffffffffffffffff", true, 50),
3960 		n(&p, "bfffffffffffffffffffffffffffffffffffffff", true, 50),
3961 		n(&p, "bfffffffffffffffffffffffffffffffffffffff", true, 51), // <== replaced
3962 		n(&p, "dfffffffffffffffffffffffffffffffffffffff", true, 50),
3963 		n(&p, "ffffffffffffffffffffffffffffffffffffffff", true, 50),
3964 	};
3965 	TEST_EQUAL(p.size(), 8);
3966 	TEST_CHECK(
3967 		replace_node_impl(n(nullptr, "9fcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd", true, 50)
3968 	, b, p, 0, 8, true LOGGER) == routing_table::node_added);
3969 	TEST_CHECK(b[5].id == to_hash("9fcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"));
3970 	TEST_EQUAL(p.size(), 8);
3971 	}
3972 
3973 	// if there is a node with fail count > 0, replaec that, regardless of
3974 	// anything else
3975 	{
3976 	ip_set p;
3977 	dht::bucket_t b = {
3978 		n(&p, "1fffffffffffffffffffffffffffffffffffffff", true, 50),
3979 		n(&p, "3fffffffffffffffffffffffffffffffffffffff", true, 50),
3980 		n(&p, "5fffffffffffffffffffffffffffffffffffffff", true, 50),
3981 		n(&p, "7fffffffffffffffffffffffffffffffffffffff", true, 50),
3982 		n(&p, "9fffffffffffffffffffffffffffffffffffffff", true, 50),
3983 		n(&p, "bfffffffffffffffffffffffffffffffffffffff", true, 50),
3984 		n(&p, "dfffffffffffffffffffffffffffffffffffffff", true, 50),
3985 		n(&p, "ffffffffffffffffffffffffffffffffffffffff", true, 50, 1), // <== replaced
3986 	};
3987 	TEST_EQUAL(p.size(), 8);
3988 	TEST_CHECK(
3989 		replace_node_impl(n(nullptr, "9fcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd", true, 50)
3990 	, b, p, 0, 8, true LOGGER) == routing_table::node_added);
3991 	TEST_CHECK(b[7].id == to_hash("9fcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"));
3992 	TEST_EQUAL(p.size(), 8);
3993 	}
3994 }
3995 
TORRENT_TEST(all_in_same_bucket)3996 TORRENT_TEST(all_in_same_bucket)
3997 {
3998 	TEST_CHECK(all_in_same_bucket({}, to_hash("8000000000000000000000000000000000000000"), 0) == true);
3999 	TEST_CHECK(all_in_same_bucket({}, to_hash("8000000000000000000000000000000000000001"), 1) == true);
4000 	TEST_CHECK(all_in_same_bucket({}, to_hash("8000000000000000000000000000000000000002"), 2) == true);
4001 	TEST_CHECK(all_in_same_bucket({}, to_hash("8000000000000000000000000000000000000003"), 3) == true);
4002 	{
4003 		dht::bucket_t b = {
4004 			n(nullptr, "0000000000000000000000000000000000000000"),
4005 		};
4006 		TEST_CHECK(all_in_same_bucket(b, to_hash("8000000000000000000000000000000000000000"), 0) == false);
4007 	}
4008 
4009 	{
4010 		dht::bucket_t b = {
4011 			n(nullptr, "8000000000000000000000000000000000000000"),
4012 			n(nullptr, "f000000000000000000000000000000000000000"),
4013 		};
4014 		TEST_CHECK(all_in_same_bucket(b, to_hash("8000000000000000000000000000000000000000"), 0) == true);
4015 	}
4016 	{
4017 		dht::bucket_t b = {
4018 			n(nullptr, "8000000000000000000000000000000000000000"),
4019 			n(nullptr, "0000000000000000000000000000000000000000"),
4020 		};
4021 		TEST_CHECK(all_in_same_bucket(b, to_hash("8000000000000000000000000000000000000000"), 0) == false);
4022 	}
4023 	{
4024 		dht::bucket_t b = {
4025 			n(nullptr, "0800000000000000000000000000000000000000"),
4026 			n(nullptr, "0000000000000000000000000000000000000000"),
4027 		};
4028 		TEST_CHECK(all_in_same_bucket(b, to_hash("0800000000000000000000000000000000000000"), 4) == false);
4029 	}
4030 	{
4031 		dht::bucket_t b = {
4032 			n(nullptr, "0800000000000000000000000000000000000000"),
4033 			n(nullptr, "0800000000000000000000000000000000000000"),
4034 		};
4035 
4036 		TEST_CHECK(all_in_same_bucket(b, to_hash("0800000000000000000000000000000000000000"), 4) == true);
4037 	}
4038 	{
4039 		dht::bucket_t b = {
4040 			n(nullptr, "0007000000000000000000000000000000000000"),
4041 			n(nullptr, "0004000000000000000000000000000000000000"),
4042 		};
4043 
4044 		TEST_CHECK(all_in_same_bucket(b, to_hash("0005000000000000000000000000000000000000"), 13) == true);
4045 	}
4046 }
4047 
4048 namespace {
test_rate_limit(dht::settings & sett,std::function<void (lt::dht::socket_manager &)> f)4049 void test_rate_limit(dht::settings& sett, std::function<void(lt::dht::socket_manager&)> f)
4050 {
4051 	io_service ios;
4052 	obs observer;
4053 	counters cnt;
4054 	auto dht_storage = dht_default_storage_constructor(sett);
4055 	dht_state s;
4056 
4057 	lt::dht::dht_tracker::send_fun_t send;
4058 
4059 	dht_tracker dht(&observer, ios, send, sett, cnt, *dht_storage, std::move(s));
4060 	f(dht);
4061 }
4062 }
4063 
TORRENT_TEST(rate_limit_int_max)4064 TORRENT_TEST(rate_limit_int_max)
4065 {
4066 	dht::settings sett;
4067 	sett.upload_rate_limit = std::numeric_limits<int>::max();
4068 
4069 	test_rate_limit(sett, [](lt::dht::socket_manager& sm) {
4070 		TEST_CHECK(sm.has_quota());
4071 		std::this_thread::sleep_for(milliseconds(10));
4072 
4073 		// *any* increment to the quote above INT_MAX may overflow. Ensure it
4074 		// doesn't
4075 		TEST_CHECK(sm.has_quota());
4076 	});
4077 }
4078 
TORRENT_TEST(rate_limit_large_delta)4079 TORRENT_TEST(rate_limit_large_delta)
4080 {
4081 	dht::settings sett;
4082 	sett.upload_rate_limit = std::numeric_limits<int>::max() / 2;
4083 
4084 	test_rate_limit(sett, [](lt::dht::socket_manager& sm) {
4085 		TEST_CHECK(sm.has_quota());
4086 		std::this_thread::sleep_for(milliseconds(2500));
4087 
4088 		// even though we have headroom in the limit itself, this long delay
4089 		// would increment the quota past INT_MAX
4090 		TEST_CHECK(sm.has_quota());
4091 	});
4092 }
4093 
TORRENT_TEST(rate_limit_accrue_limit)4094 TORRENT_TEST(rate_limit_accrue_limit)
4095 {
4096 	dht::settings sett;
4097 	sett.upload_rate_limit = std::numeric_limits<int>::max() / 5;
4098 
4099 	test_rate_limit(sett, [](lt::dht::socket_manager& sm) {
4100 		TEST_CHECK(sm.has_quota());
4101 		for (int i = 0; i < 10; ++i)
4102 		{
4103 			std::this_thread::sleep_for(milliseconds(500));
4104 			TEST_CHECK(sm.has_quota());
4105 		}
4106 	});
4107 }
4108 
4109 
4110 // TODO: test obfuscated_get_peers
4111 
4112 #else
TORRENT_TEST(dht)4113 TORRENT_TEST(dht)
4114 {
4115 	// dummy dht test
4116 	TEST_CHECK(true);
4117 }
4118 
4119 #endif
4120