/* 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 on_alert , int const idx) { lt::time_point start_time = lt::clock_type::now(); static std::vector 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(ts).count()) , int(lt::duration_cast(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 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, 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; }