Files
libtorrent/test/test_direct_dht.cpp
2026-04-29 21:37:05 +02:00

128 lines
3.6 KiB
C++

/*
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<alert*> alerts;
ses.pop_alerts(&alerts);
for (std::vector<alert*>::iterator i = alerts.begin(); i != alerts.end(); ++i)
{
if ((*i)->type() == dht_direct_response_alert::alert_type)
return static_cast<dht_direct_response_alert*>(&**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<lt::session_proxy> 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<test_plugin>());
// 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<int*>(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<int>(), reinterpret_cast<int*>(12345));
}
// failed request
requester.dht_direct_request(uep("127.0.0.1", 53545)
, r, client_data_t(reinterpret_cast<int*>(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<int>(), reinterpret_cast<int*>(123456));
}
abort.emplace_back(responder.abort());
abort.emplace_back(requester.abort());
#endif // #if !defined TORRENT_DISABLE_EXTENSIONS && !defined TORRENT_DISABLE_DHT
}