/* Copyright (c) 2016, Alden Torres Copyright (c) 2016-2017, 2019-2020, 2022, Arvid Norberg Copyright (c) 2017, Steven Siloti All rights reserved. You may use, distribute and modify this code under the terms of the BSD license, see LICENSE file. */ #include "libtorrent/config.hpp" #include "libtorrent/session.hpp" #include "libtorrent/extensions.hpp" #include "libtorrent/bencode.hpp" #include "libtorrent/bdecode.hpp" #include "libtorrent/hex.hpp" #include "setup_transfer.hpp" // for addr6 #include "settings.hpp" #include "libtorrent/session_params.hpp" #include "libtorrent/extensions.hpp" #include "test.hpp" #include "setup_transfer.hpp" #include using namespace lt; using dht::dht_storage_interface; using dht::dht_state; namespace { #ifndef TORRENT_DISABLE_DHT bool g_storage_constructor_invoked = false; std::unique_ptr dht_custom_storage_constructor( settings_interface const& settings) { g_storage_constructor_invoked = true; return dht::dht_default_storage_constructor(settings); } #endif #ifndef TORRENT_DISABLE_EXTENSIONS bool g_plugin_added_invoked = false; struct custom_plugin : plugin { void added(session_handle const& h) override { TORRENT_UNUSED(h); g_plugin_added_invoked = true; } }; #endif } TORRENT_TEST(default_plugins) { session_params p1; #ifndef TORRENT_DISABLE_EXTENSIONS #if TORRENT_USE_I2P // this also has i2p_pex TEST_EQUAL(int(p1.extensions.size()), 4); #else TEST_EQUAL(int(p1.extensions.size()), 3); #endif #else TEST_EQUAL(int(p1.extensions.size()), 0); #endif std::vector> exts; session_params p2(settings_pack(), exts); TEST_EQUAL(int(p2.extensions.size()), 0); } #ifndef TORRENT_DISABLE_DHT TORRENT_TEST(custom_dht_storage) { g_storage_constructor_invoked = false; settings_pack p = settings(); p.set_bool(settings_pack::enable_dht, true); session_params params(p); params.dht_storage_constructor = dht_custom_storage_constructor; lt::session ses(params); TEST_CHECK(ses.is_dht_running() == true); TEST_EQUAL(g_storage_constructor_invoked, true); } TORRENT_TEST(dht_state) { settings_pack p = settings(); p.set_bool(settings_pack::enable_dht, true); p.set_int(settings_pack::dht_max_dht_items, 10000); p.set_int(settings_pack::dht_max_peers, 20000); dht_state s; s.nids.emplace_back(addr4("0.0.0.0"), to_hash("0000000000000000000000000000000000000001")); s.nodes.push_back(uep("1.1.1.1", 1)); s.nodes.push_back(uep("2.2.2.2", 2)); // not important that IPv6 is disabled here s.nids.emplace_back(addr6("::"), to_hash("0000000000000000000000000000000000000002")); session_params params(p); params.dht_state = s; params.settings.set_str(settings_pack::listen_interfaces, "127.0.0.1:6881"); lt::session ses1(params); TEST_CHECK(ses1.is_dht_running() == true); session_params const params1 = ses1.session_state(); TEST_EQUAL(params1.settings.get_int(settings_pack::dht_max_dht_items), 10000); TEST_EQUAL(params1.settings.get_int(settings_pack::dht_max_peers), 20000); entry const e = write_session_params(params1); std::vector const tmp = bencode(e); session_params params2 = read_session_params(tmp); TEST_EQUAL(params2.settings.get_int(settings_pack::dht_max_dht_items), 10000); TEST_EQUAL(params2.settings.get_int(settings_pack::dht_max_peers), 20000); TEST_EQUAL(params2.dht_state.nids.size(), 1); if (params2.dht_state.nids.size() >= 1) { // not a chance the nid will be the fake initial ones TEST_CHECK(params2.dht_state.nids[0].second != s.nids[0].second); } } #endif namespace { settings_pack test_pack() { settings_pack ret; for (std::uint16_t i = 0; i < settings_pack::num_string_settings; ++i) { std::uint16_t const n = i | settings_pack::string_type_base; if (name_for_setting(n) == std::string()) continue; ret.set_str(n , std::to_string(i) + "__"); } for (std::uint16_t i = 0; i < settings_pack::num_int_settings; ++i) { std::uint16_t const n = i | settings_pack::int_type_base; if (name_for_setting(n) == std::string()) continue; ret.set_int(n, 1000000 + i); } for (std::uint16_t i = 0; i < settings_pack::num_bool_settings; ++i) { std::uint16_t const n = i | settings_pack::bool_type_base; if (name_for_setting(n) == std::string()) continue; ret.set_bool(n, i & 1); } return ret; } dht::dht_state test_state() { dht::dht_state ret; auto a1 = make_address("1.2.3.4"); auto a2 = make_address("1234:abcd:ef01::1"); ret.nids = dht::node_ids_t{{a1, dht::generate_id(a1)}, {a2, dht::generate_id(a2)}}; for (int i = 0; i < 50; ++i) ret.nodes.push_back(rand_udp_ep(rand_v4)); for (int i = 0; i < 50; ++i) ret.nodes.push_back(rand_udp_ep(rand_v6)); return ret; } ip_filter test_ip_filter() { ip_filter ret; ret.add_rule(make_address("fe80::"), make_address("fe81::"), 1); ret.add_rule(make_address("127.0.0.1"), make_address("127.255.255.255"), 1); return ret; } session_params test_params() { session_params ret; ret.settings = test_pack(); ret.dht_state = test_state(); for (int i = 0; i < 100; ++i) ret.ext_state[std::to_string(i)] = std::string(std::to_string(i)); ret.ip_filter = test_ip_filter(); return ret; } bool operator==(dht::dht_state const& lhs, dht::dht_state const& rhs) { return lhs.nids == rhs.nids && lhs.nodes == rhs.nodes && lhs.nodes6 == rhs.nodes6 ; } bool operator==(lt::settings_pack const& lhs, lt::settings_pack const& rhs) { for (std::uint16_t i = 0; i < settings_pack::num_string_settings; ++i) if (lhs.get_str(i | settings_pack::string_type_base) != rhs.get_str(i | settings_pack::string_type_base)) return false; for (std::uint16_t i = 0; i < settings_pack::num_int_settings; ++i) if (lhs.get_int(i | settings_pack::int_type_base) != rhs.get_int(i | settings_pack::int_type_base)) return false; for (std::uint16_t i = 0; i < settings_pack::num_bool_settings; ++i) if (lhs.get_bool(i | settings_pack::bool_type_base) != rhs.get_bool(i | settings_pack::bool_type_base)) return false; return true; } void test_ip_filter(ip_filter const& f) { TEST_EQUAL(f.access(make_address("fe7f::1")), 0); TEST_EQUAL(f.access(make_address("fe80::1")), 1); TEST_EQUAL(f.access(make_address("fe81::1")), 0); TEST_EQUAL(f.access(make_address("127.0.0.0")), 0); TEST_EQUAL(f.access(make_address("127.0.0.1")), 1); TEST_EQUAL(f.access(make_address("127.255.0.1")), 1); TEST_EQUAL(f.access(make_address("128.0.0.0")), 0); } } // anonymous namespace TORRENT_TEST(session_params_ip_filter) { session_params input; input.ip_filter = test_ip_filter(); test_ip_filter(input.ip_filter); std::vector const buf = write_session_params_buf(input); { std::ofstream f("../session_state.test"); f.write(buf.data(), static_cast(buf.size())); } session_params const output = read_session_params(buf); test_ip_filter(output.ip_filter); } TORRENT_TEST(session_params_round_trip) { session_params const input = test_params(); std::vector const buf = write_session_params_buf(input); { std::ofstream f("../session_state.test"); f.write(buf.data(), static_cast(buf.size())); } session_params const output = read_session_params(buf); TEST_CHECK(input.settings == output.settings); TEST_CHECK(input.dht_state == output.dht_state); TEST_CHECK(input.ext_state == output.ext_state); TEST_CHECK(input.ip_filter.export_filter() == output.ip_filter.export_filter()); } #ifndef TORRENT_DISABLE_EXTENSIONS TORRENT_TEST(add_plugin) { g_plugin_added_invoked = false; session_params params(settings()); params.extensions.push_back(std::make_shared()); lt::session ses(params); TEST_EQUAL(g_plugin_added_invoked, true); } #endif