/* Copyright (c) 2015-2017, Alden Torres Copyright (c) 2015-2019, 2021, Arvid Norberg All rights reserved. You may use, distribute and modify this code under the terms of the BSD license, see LICENSE file. */ #include "test.hpp" #ifndef TORRENT_DISABLE_DHT #include "settings.hpp" #include "setup_transfer.hpp" // for ep() #include "libtorrent/config.hpp" #include "libtorrent/kademlia/dht_storage.hpp" #include "libtorrent/kademlia/dht_settings.hpp" #include "libtorrent/io_context.hpp" #include "libtorrent/aux_/session_settings.hpp" #include "libtorrent/address.hpp" #include "libtorrent/aux_/time.hpp" #include "simulator/simulator.hpp" #include #include using namespace lt; using namespace lt::dht; using namespace sim; using sim::chrono::high_resolution_clock; using namespace sim::asio; using sim::simulation; using sim::default_config; using namespace std::placeholders; namespace { lt::aux::session_settings test_settings() { lt::aux::session_settings sett; sett.set_int(settings_pack::dht_max_torrents, 2); sett.set_int(settings_pack::dht_max_dht_items, 2); sett.set_int(settings_pack::dht_item_lifetime, 120 * 60); return sett; } std::unique_ptr create_default_dht_storage( settings_interface const& sett) { std::unique_ptr s(dht_default_storage_constructor(sett)); TEST_CHECK(s.get() != nullptr); s->update_node_ids({to_hash("0000000000000000000000000000000000000200")}); return s; } } void timer_tick(dht_storage_interface* s , dht_storage_counters const& c , boost::system::error_code const&) { s->tick(); TEST_EQUAL(s->counters().peers, c.peers); TEST_EQUAL(s->counters().torrents, c.torrents); TEST_EQUAL(s->counters().immutable_data, c.immutable_data); TEST_EQUAL(s->counters().mutable_data, c.mutable_data); } void test_expiration(simulation& sim , high_resolution_clock::duration const& expiry_time , std::unique_ptr& s , dht_storage_counters const& c) { sim::asio::io_context ios(sim, addr("10.0.0.1")); sim::asio::high_resolution_timer timer(ios); timer.expires_after(expiry_time); timer.async_wait(std::bind(&timer_tick, s.get(), c, _1)); sim.run(); } TORRENT_TEST(dht_storage_counters) { auto sett = test_settings(); std::unique_ptr s(create_default_dht_storage(sett)); TEST_CHECK(s.get() != nullptr); sha1_hash const n1 = to_hash("5fbfbff10c5d6a4ec8a88e4c6ab4c28b95eee401"); sha1_hash const n2 = to_hash("5fbfbff10c5d6a4ec8a88e4c6ab4c28b95eee402"); sha1_hash const n3 = to_hash("5fbfbff10c5d6a4ec8a88e4c6ab4c28b95eee403"); sha1_hash const n4 = to_hash("5fbfbff10c5d6a4ec8a88e4c6ab4c28b95eee404"); tcp::endpoint const p1 = ep("124.31.75.21", 1); tcp::endpoint const p2 = ep("124.31.75.22", 1); tcp::endpoint const p3 = ep("124.31.75.23", 1); tcp::endpoint const p4 = ep("124.31.75.24", 1); s->announce_peer(n1, p1, "torrent_name", false); s->announce_peer(n2, p2, "torrent_name1", false); s->announce_peer(n2, p3, "torrent_name1", false); s->announce_peer(n3, p4, "torrent_name2", false); s->put_immutable_item(n4, {"123", 3}, addr("124.31.75.21")); s->put_immutable_item(n1, {"123", 3}, addr("124.31.75.21")); s->put_immutable_item(n2, {"123", 3}, addr("124.31.75.21")); s->put_immutable_item(n3, {"123", 3}, addr("124.31.75.21")); dht::public_key pk; dht::signature sig; s->put_mutable_item(n4, {"123", 3}, sig, sequence_number(1), pk, {"salt", 4} , addr("124.31.75.21")); dht_storage_counters c; // note that we are using the aux global timer default_config cfg; simulation sim(cfg); c.peers = 3; c.torrents = 2; c.immutable_data = 2; c.mutable_data = 1; test_expiration(sim, minutes(30), s, c); // test expiration of torrents and peers c.peers = 0; c.torrents = 0; c.immutable_data = 2; c.mutable_data = 1; test_expiration(sim, minutes(80), s, c); // test expiration of items before 2 hours c.peers = 0; c.torrents = 0; c.immutable_data = 0; c.mutable_data = 0; test_expiration(sim, hours(1), s, c); // test expiration of everything after 3 hours } TORRENT_TEST(dht_storage_infohashes_sample) { default_config cfg; simulation sim(cfg); sim::asio::io_context ios(sim, addr("10.0.0.1")); auto sett = test_settings(); sett.set_int(settings_pack::dht_max_torrents, 5); sett.set_int(settings_pack::dht_sample_infohashes_interval, 30); sett.set_int(settings_pack::dht_max_infohashes_sample_count, 2); std::unique_ptr s(create_default_dht_storage(sett)); TEST_CHECK(s.get() != nullptr); sha1_hash const n1 = to_hash("5fbfbff10c5d6a4ec8a88e4c6ab4c28b95eee401"); sha1_hash const n2 = to_hash("5fbfbff10c5d6a4ec8a88e4c6ab4c28b95eee402"); sha1_hash const n3 = to_hash("5fbfbff10c5d6a4ec8a88e4c6ab4c28b95eee403"); sha1_hash const n4 = to_hash("5fbfbff10c5d6a4ec8a88e4c6ab4c28b95eee404"); tcp::endpoint const p1 = ep("124.31.75.21", 1); tcp::endpoint const p2 = ep("124.31.75.22", 1); tcp::endpoint const p3 = ep("124.31.75.23", 1); tcp::endpoint const p4 = ep("124.31.75.24", 1); s->announce_peer(n1, p1, "torrent_name1", false); s->announce_peer(n2, p2, "torrent_name2", false); s->announce_peer(n3, p3, "torrent_name3", false); s->announce_peer(n4, p4, "torrent_name4", false); entry item; int r = s->get_infohashes_sample(item); TEST_EQUAL(r, 2); sim::asio::high_resolution_timer timer(ios); timer.expires_after(hours(1)); // expiration of torrents timer.async_wait([&s](boost::system::error_code const&) { // tick here to trigger the torrents expiration s->tick(); entry item; int r = s->get_infohashes_sample(item); TEST_EQUAL(r, 0); }); sim.run(); } #else TORRENT_TEST(disabled) {} #endif // TORRENT_DISABLE_DHT