Files
2021-12-26 11:54:36 +01:00

234 lines
5.6 KiB
C++

/*
Copyright (c) 2016-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 "utils.hpp"
#include "test.hpp"
#include "libtorrent/session.hpp"
#include "libtorrent/settings_pack.hpp"
#include "libtorrent/address.hpp"
#include "libtorrent/ip_filter.hpp"
#include "libtorrent/alert_types.hpp"
#include "libtorrent/session_stats.hpp"
#include "libtorrent/alert.hpp"
#include "libtorrent/io_context.hpp"
#include "libtorrent/aux_/random.hpp"
#include "setup_swarm.hpp"
#include "setup_transfer.hpp" // for addr()
using namespace lt;
#ifdef _MSC_VER
namespace libtorrent {
namespace aux {
// see test_error_handling.cpp for a description of this variable
// TODO: in C++17, make this inline
thread_local int g_must_not_fail = 0;
}
}
#endif
std::string make_ep_string(char const* address, bool const is_v6
, char const* port)
{
std::string ret;
if (is_v6) ret += '[';
ret += address;
if (is_v6) ret += ']';
ret += ':';
ret += port;
return ret;
}
void utp_only(lt::session& ses)
{
settings_pack p;
utp_only(p);
ses.apply_settings(p);
}
void enable_enc(lt::session& ses)
{
settings_pack p;
enable_enc(p);
ses.apply_settings(p);
}
void filter_ips(lt::session& ses)
{
ip_filter filter;
filter.add_rule(make_address_v4("50.0.0.1")
, make_address_v4("50.0.0.2"), ip_filter::blocked);
ses.set_ip_filter(filter);
}
void utp_only(lt::settings_pack& p)
{
using namespace lt;
p.set_bool(settings_pack::enable_outgoing_tcp, false);
p.set_bool(settings_pack::enable_incoming_tcp, false);
p.set_bool(settings_pack::enable_outgoing_utp, true);
p.set_bool(settings_pack::enable_incoming_utp, true);
}
void enable_enc(lt::settings_pack& p)
{
using namespace lt;
p.set_bool(settings_pack::prefer_rc4, true);
p.set_int(settings_pack::in_enc_policy, settings_pack::pe_forced);
p.set_int(settings_pack::out_enc_policy, settings_pack::pe_forced);
p.set_int(settings_pack::allowed_enc_level, settings_pack::pe_both);
}
std::string save_path(int swarm_id, int idx)
{
char path[200];
std::snprintf(path, sizeof(path), "swarm-%04d-peer-%02d"
, swarm_id, idx);
return path;
}
void add_extra_peers(lt::session& ses)
{
auto handles = ses.get_torrents();
TEST_EQUAL(handles.size(), 1);
auto h = handles[0];
for (int i = 0; i < 30; ++i)
{
char ep[30];
std::snprintf(ep, sizeof(ep), "60.0.0.%d", i + 1);
h.connect_peer(lt::tcp::endpoint(addr(ep), 6881));
}
}
lt::torrent_status get_status(lt::session& ses)
{
auto handles = ses.get_torrents();
TEST_EQUAL(handles.size(), 1);
if (handles.empty()) return lt::torrent_status();
auto h = handles[0];
return h.status();
}
bool has_metadata(lt::session& ses)
{
auto handles = ses.get_torrents();
TEST_EQUAL(handles.size(), 1);
if (handles.empty()) return false;
auto h = handles[0];
return h.status().has_metadata;
}
bool is_seed(lt::session& ses)
{
auto handles = ses.get_torrents();
TEST_EQUAL(handles.size(), 1);
if (handles.empty()) return false;
auto h = handles[0];
return h.status().is_seeding;
}
bool is_finished(lt::session& ses)
{
auto handles = ses.get_torrents();
TEST_EQUAL(handles.size(), 1);
if (handles.empty()) return false;
auto h = handles[0];
return h.status().is_finished;
}
int completed_pieces(lt::session& ses)
{
auto handles = ses.get_torrents();
TEST_EQUAL(handles.size(), 1);
if (handles.empty()) return 0;
auto h = handles[0];
return h.status().num_pieces;
}
void set_proxy(lt::session& ses, int proxy_type, test_transfer_flags_t const flags
, bool const proxy_peers)
{
// apply the proxy settings to session 0
settings_pack p;
p.set_int(settings_pack::proxy_type, proxy_type);
if (proxy_type == settings_pack::socks4)
p.set_int(settings_pack::proxy_port, 4444);
else
p.set_int(settings_pack::proxy_port, 5555);
if (flags & tx::ipv6)
p.set_str(settings_pack::proxy_hostname, "2001::2");
else
p.set_str(settings_pack::proxy_hostname, "50.50.50.50");
p.set_bool(settings_pack::proxy_hostnames, true);
p.set_bool(settings_pack::proxy_peer_connections, bool(flags & tx::proxy_peers));
p.set_bool(settings_pack::proxy_tracker_connections, proxy_peers);
p.set_bool(settings_pack::socks5_udp_send_local_ep, true);
ses.apply_settings(p);
}
void print_alerts(lt::session& ses
, std::function<void(lt::session&, lt::alert const*)> on_alert
, int const idx)
{
lt::time_point start_time = lt::clock_type::now();
static std::vector<lt::alert*> alerts;
ses.set_alert_notify([&ses,start_time,on_alert,idx] {
post(ses.get_context(), [&ses,start_time,on_alert,idx] {
try {
alerts.clear();
ses.pop_alerts(&alerts);
for (lt::alert const* a : alerts)
{
auto const ts = a->timestamp() - start_time;
std::printf("\x1b[%dm%3d.%03d %s\n"
, idx == 0 ? 0 : 34
, int(lt::duration_cast<lt::seconds>(ts).count())
, int(lt::duration_cast<lt::milliseconds>(ts).count() % 1000)
, a->message().c_str());
// call the user handler
on_alert(ses, a);
}
} catch (std::exception const& e) {
std::printf("print alerts: ERROR failed with exception: %s"
, e.what());
} catch (...) {
std::printf("print alerts: ERROR failed with (unknown) exception");
}
} ); } );
}
std::unique_ptr<sim::asio::io_context> make_io_context(sim::simulation& sim, int i)
{
char ep[30];
std::snprintf(ep, sizeof(ep), "50.0.%d.%d", (i + 1) >> 8, (i + 1) & 0xff);
return std::make_unique<sim::asio::io_context>(sim, lt::make_address_v4(ep));
}
sha256_hash rand_sha256()
{
sha256_hash ret;
aux::random_bytes(ret);
return ret;
}
sha1_hash rand_sha1()
{
sha1_hash ret;
aux::random_bytes(ret);
return ret;
}