/* Copyright (c) 2015-2020, 2022, Arvid Norberg Copyright (c) 2015, Steven Siloti Copyright (c) 2016, Alden Torres All rights reserved. You may use, distribute and modify this code under the terms of the BSD license, see LICENSE file. */ #include "test.hpp" #if !defined TORRENT_DISABLE_EXTENSIONS && !defined TORRENT_DISABLE_DHT #include "libtorrent/config.hpp" #include "libtorrent/session.hpp" #include "libtorrent/session_params.hpp" #include "libtorrent/extensions.hpp" #include "libtorrent/alert_types.hpp" #include "libtorrent/bdecode.hpp" #include "setup_transfer.hpp" using namespace lt; namespace { struct test_plugin : plugin { feature_flags_t implemented_features() override { return plugin::dht_request_feature; } bool on_dht_request(string_view /* query */ , udp::endpoint const& /* source */, bdecode_node const& message , entry& response) override { if (message.dict_find_string_value("q") == "test_good") { response["r"]["good"] = 1; return true; } return false; } }; dht_direct_response_alert* get_direct_response(lt::session& ses) { for (;;) { // it shouldn't take more than 30 seconds to get a response // so fail the test and bail out if we don't get an alert in that time bool const got = ses.wait_for_alert(seconds(30)); TEST_CHECK(got); if (!got) return nullptr; std::vector alerts; ses.pop_alerts(&alerts); for (std::vector::iterator i = alerts.begin(); i != alerts.end(); ++i) { if ((*i)->type() == dht_direct_response_alert::alert_type) return static_cast(&**i); } } } } #endif // #if !defined TORRENT_DISABLE_EXTENSIONS && !defined TORRENT_DISABLE_DHT TORRENT_TEST(direct_dht_request) { #if !defined TORRENT_DISABLE_EXTENSIONS && !defined TORRENT_DISABLE_DHT std::vector abort; settings_pack sp; sp.set_bool(settings_pack::enable_lsd, false); sp.set_bool(settings_pack::enable_natpmp, false); sp.set_bool(settings_pack::enable_upnp, false); sp.set_str(settings_pack::dht_bootstrap_nodes, ""); sp.set_int(settings_pack::max_retry_port_bind, 800); sp.set_str(settings_pack::listen_interfaces, "127.0.0.1:42434"); lt::session responder(session_params(sp, {})); sp.set_str(settings_pack::listen_interfaces, "127.0.0.1:45434"); lt::session requester(session_params(sp, {})); responder.add_extension(std::make_shared()); // successful request entry r; r["q"] = "test_good"; requester.dht_direct_request(uep("127.0.0.1", responder.listen_port()) , r, client_data_t(reinterpret_cast(12345))); dht_direct_response_alert* ra = get_direct_response(requester); TEST_CHECK(ra); if (ra) { bdecode_node response = ra->response(); TEST_EQUAL(ra->endpoint.address(), make_address("127.0.0.1")); TEST_EQUAL(ra->endpoint.port(), responder.listen_port()); TEST_EQUAL(response.type(), bdecode_node::dict_t); TEST_EQUAL(response.dict_find_dict("r").dict_find_int_value("good"), 1); TEST_EQUAL(ra->userdata.get(), reinterpret_cast(12345)); } // failed request requester.dht_direct_request(uep("127.0.0.1", 53545) , r, client_data_t(reinterpret_cast(123456))); ra = get_direct_response(requester); TEST_CHECK(ra); if (ra) { TEST_EQUAL(ra->endpoint.address(), make_address("127.0.0.1")); TEST_EQUAL(ra->endpoint.port(), 53545); TEST_EQUAL(ra->response().type(), bdecode_node::none_t); TEST_EQUAL(ra->userdata.get(), reinterpret_cast(123456)); } abort.emplace_back(responder.abort()); abort.emplace_back(requester.abort()); #endif // #if !defined TORRENT_DISABLE_EXTENSIONS && !defined TORRENT_DISABLE_DHT }