From a8e31fd8ca0021e2713758743a4478458961f9eb Mon Sep 17 00:00:00 2001 From: arvidn Date: Thu, 26 Nov 2015 21:18:58 -0500 Subject: [PATCH 1/2] add first coverage of test_transfer as a proper sim --- include/libtorrent/bt_peer_connection.hpp | 2 +- simulation/Jamfile | 1 + simulation/create_torrent.cpp | 20 +- simulation/create_torrent.hpp | 4 +- simulation/libsimulator | 2 +- simulation/make_proxy_settings.hpp | 57 ++++ simulation/setup_swarm.cpp | 13 +- simulation/swarm_suite.cpp | 1 - simulation/test_dht_storage.cpp | 10 +- simulation/test_http_connection.cpp | 16 +- simulation/test_ip_filter.cpp | 79 ++--- simulation/test_transfer.cpp | 339 ++++++++++++++++++++++ src/bt_peer_connection.cpp | 34 +-- src/peer_connection.cpp | 6 - test/test_transfer.cpp | 29 +- 15 files changed, 472 insertions(+), 141 deletions(-) create mode 100644 simulation/make_proxy_settings.hpp create mode 100644 simulation/test_transfer.cpp diff --git a/include/libtorrent/bt_peer_connection.hpp b/include/libtorrent/bt_peer_connection.hpp index e94960f71..eca21e8f4 100644 --- a/include/libtorrent/bt_peer_connection.hpp +++ b/include/libtorrent/bt_peer_connection.hpp @@ -327,7 +327,7 @@ private: read_packet_size, read_packet }; - + #if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS) enum { diff --git a/simulation/Jamfile b/simulation/Jamfile index 8db34abd3..0c53d4a67 100644 --- a/simulation/Jamfile +++ b/simulation/Jamfile @@ -24,6 +24,7 @@ project ; alias libtorrent-sims : + [ run test_transfer.cpp ] [ run test_http_connection.cpp ] [ run test_auto_manage.cpp ] [ run test_torrent_status.cpp ] diff --git a/simulation/create_torrent.cpp b/simulation/create_torrent.cpp index 8b504e1a9..b8a5a126c 100644 --- a/simulation/create_torrent.cpp +++ b/simulation/create_torrent.cpp @@ -37,6 +37,15 @@ POSSIBILITY OF SUCH DAMAGE. namespace lt = libtorrent; +std::string save_path(int idx) +{ + int swarm_id = test_counter(); + char path[200]; + snprintf(path, sizeof(path), "swarm-%04d-peer-%02d" + , swarm_id, idx); + return path; +} + lt::add_torrent_params create_torrent(int idx, bool seed) { // TODO: if we want non-seeding torrents, that could be a bit cheaper to @@ -44,17 +53,14 @@ lt::add_torrent_params create_torrent(int idx, bool seed) lt::add_torrent_params params; int swarm_id = test_counter(); char name[200]; - snprintf(name, sizeof(name), "temp-%02d", idx); - char path[200]; - snprintf(path, sizeof(path), "swarm-%04d-peer-%02d" - , swarm_id, idx); + snprintf(name, sizeof(name), "temp-%02d", swarm_id); + std::string path = save_path(idx); lt::error_code ec; lt::create_directory(path, ec); if (ec) fprintf(stderr, "failed to create directory: \"%s\": %s\n" - , path, ec.message().c_str()); + , path.c_str(), ec.message().c_str()); std::ofstream file(lt::combine_path(path, name).c_str()); - params.ti = ::create_torrent(&file, name - , 0x4000, 9 + idx, false); + params.ti = ::create_torrent(&file, name, 0x4000, 9 + idx, false); file.close(); // by setting the save path to a dummy path, it won't be seeding diff --git a/simulation/create_torrent.hpp b/simulation/create_torrent.hpp index a72c2cee9..ebb9bb870 100644 --- a/simulation/create_torrent.hpp +++ b/simulation/create_torrent.hpp @@ -33,9 +33,11 @@ POSSIBILITY OF SUCH DAMAGE. #ifndef TORRENT_CREATE_TORRENT_HPP_INCLUDED #define TORRENT_CREATE_TORRENT_HPP_INCLUDED +#include #include "libtorrent/add_torrent_params.hpp" -libtorrent::add_torrent_params create_torrent(int idx, bool seed); +std::string save_path(int idx); +libtorrent::add_torrent_params create_torrent(int idx, bool seed = true); #endif diff --git a/simulation/libsimulator b/simulation/libsimulator index a4b10668e..df7a6e308 160000 --- a/simulation/libsimulator +++ b/simulation/libsimulator @@ -1 +1 @@ -Subproject commit a4b10668ea22e9328a2668baf8990b3685fe7578 +Subproject commit df7a6e308f2c414e4ed5ffe760b8c15f7dc5f17c diff --git a/simulation/make_proxy_settings.hpp b/simulation/make_proxy_settings.hpp new file mode 100644 index 000000000..67bd3f942 --- /dev/null +++ b/simulation/make_proxy_settings.hpp @@ -0,0 +1,57 @@ +/* + +Copyright (c) 2015, Arvid Norberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + * Neither the name of the author nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef TORRENT_MAKE_PROXY_SETTINGS_HPP +#define TORRENT_MAKE_PROXY_SETTINGS_HPP + +#include "libtorrent/aux_/proxy_settings.hpp" + +inline libtorrent::aux::proxy_settings make_proxy_settings( + libtorrent::settings_pack::proxy_type_t proxy_type) +{ + using namespace libtorrent; + + aux::proxy_settings ps; + ps.type = proxy_type; + ps.proxy_hostnames = false; + if (proxy_type != settings_pack::none) + { + ps.hostname = "50.50.50.50"; + ps.port = 4444; + ps.username = "testuser"; + ps.password = "testpass"; + } + return ps; +} + +#endif + diff --git a/simulation/setup_swarm.cpp b/simulation/setup_swarm.cpp index 29c151636..e071fda5e 100644 --- a/simulation/setup_swarm.cpp +++ b/simulation/setup_swarm.cpp @@ -85,7 +85,11 @@ struct swarm if (!params.save_path.empty()) ses->async_add_torrent(params); - ses->set_alert_notify(boost::bind(&swarm::on_alert_notify, this, i)); + ses->set_alert_notify([i,this] { + // this function is called inside libtorrent and we cannot perform work + // immediately in it. We have to notify the outside to pull all the alerts + m_io_service[i]->post(boost::bind(&swarm::on_alerts, this, i)); + }); } m_timer.expires_from_now(lt::seconds(1)); @@ -108,13 +112,6 @@ struct swarm m_timer.async_wait(boost::bind(&swarm::on_tick, this, _1)); } - void on_alert_notify(int session_index) - { - // this function is called inside libtorrent and we cannot perform work - // immediately in it. We have to notify the outside to pull all the alerts - m_io_service[session_index]->post(boost::bind(&swarm::on_alerts, this, session_index)); - } - void on_alerts(int session_index) { std::vector alerts; diff --git a/simulation/swarm_suite.cpp b/simulation/swarm_suite.cpp index 1a7b0b527..4a7aed4ba 100644 --- a/simulation/swarm_suite.cpp +++ b/simulation/swarm_suite.cpp @@ -37,7 +37,6 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/time.hpp" // for clock_type #include "test.hpp" -#include "setup_transfer.hpp" // for create_torrent (factor this out!) #include "setup_swarm.hpp" #include "swarm_suite.hpp" #include "swarm_config.hpp" diff --git a/simulation/test_dht_storage.cpp b/simulation/test_dht_storage.cpp index f669c6b75..f45f2f4f3 100644 --- a/simulation/test_dht_storage.cpp +++ b/simulation/test_dht_storage.cpp @@ -36,7 +36,6 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/kademlia/node.hpp" // for verify_message #include "libtorrent/kademlia/dht_storage.hpp" -#include "libtorrent/kademlia/item.hpp" #include "libtorrent/io_service.hpp" #include "libtorrent/address.hpp" @@ -63,7 +62,7 @@ namespace return sett; } - static sha1_hash to_hash(char const *s) { + sha1_hash to_hash(char const *s) { sha1_hash ret; from_hex(s, 40, (char *) &ret[0]); return ret; @@ -117,13 +116,10 @@ TORRENT_TEST(dht_storage_counters) tcp::endpoint p4 = tcp::endpoint(address::from_string("124.31.75.24"), 1); s->announce_peer(n1, p1, "torrent_name", false); - s->announce_peer(n2, p2, "torrent_name1", false); s->announce_peer(n2, p3, "torrent_name1", false); s->announce_peer(n3, p4, "torrent_name2", false); - entry item; - s->put_immutable_item(n4, "123", 3, address::from_string("124.31.75.21")); s->put_immutable_item(n1, "123", 3, address::from_string("124.31.75.21")); @@ -132,7 +128,8 @@ TORRENT_TEST(dht_storage_counters) char public_key[item_pk_len]; char signature[item_sig_len]; - s->put_mutable_item(n4, "123", 3, signature, 1, public_key, "salt", 4, address::from_string("124.31.75.21")); + s->put_mutable_item(n4, "123", 3, signature, 1, public_key, "salt", 4 + , address::from_string("124.31.75.21")); dht_storage_counters c; // note that we are using the aux global timer @@ -155,3 +152,4 @@ TORRENT_TEST(dht_storage_counters) c.mutable_data = 0; test_expiration(hours(1), s, c); // test expiration of everything after 3 hours } + diff --git a/simulation/test_http_connection.cpp b/simulation/test_http_connection.cpp index 5a9793bf2..6bb126657 100644 --- a/simulation/test_http_connection.cpp +++ b/simulation/test_http_connection.cpp @@ -42,6 +42,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/http_connection.hpp" #include "libtorrent/resolver.hpp" #include "libtorrent/io.hpp" +#include "make_proxy_settings.hpp" #include @@ -262,21 +263,6 @@ void run_suite(lt::aux::proxy_settings ps) } -lt::aux::proxy_settings make_proxy_settings(lt::settings_pack::proxy_type_t proxy_type) -{ - lt::aux::proxy_settings ps; - ps.type = proxy_type; - ps.proxy_hostnames = false; - if (proxy_type != settings_pack::none) - { - ps.hostname = "50.50.50.50"; - ps.port = 4444; - ps.username = "testuser"; - ps.password = "testpass"; - } - return ps; -} - void run_test(lt::aux::proxy_settings ps, std::string url, int expect_size, int expect_status , boost::system::error_condition expect_error, std::vector expect_counters) { diff --git a/simulation/test_ip_filter.cpp b/simulation/test_ip_filter.cpp index 072bcb9f9..756f0380a 100644 --- a/simulation/test_ip_filter.cpp +++ b/simulation/test_ip_filter.cpp @@ -85,6 +85,8 @@ void run_test(Setup const& setup , HandleAlerts const& on_alert , Test const& test) { + const lt::time_point start_time = lt::clock_type::now(); + // setup the simulation sim::default_config network_cfg; sim::simulation sim{network_cfg}; @@ -96,6 +98,9 @@ void run_test(Setup const& setup // create session std::shared_ptr ses = std::make_shared(pack, ios); + // TODO: 2 ideally this test should also try to connect to the session, + // making sure incoming connections from banned IPs are rejected + fake_peer p1(sim, "60.0.0.0"); fake_peer p2(sim, "60.0.0.1"); fake_peer p3(sim, "60.0.0.2"); @@ -113,7 +118,13 @@ void run_test(Setup const& setup std::vector alerts; ses->pop_alerts(&alerts); // call the user handler - if (!alerts.empty()) on_alert(*ses, alerts); + for (auto const a : alerts) + { + printf("%-3d %s\n", int(lt::duration_cast(a->timestamp() + - start_time).count()), a->message().c_str()); + + on_alert(*ses, a); + } } ); } ); lt::deadline_timer timer(ios); @@ -171,8 +182,6 @@ void add_ip_filter(lt::session& ses) // connected to TORRENT_TEST(apply_ip_filter) { - lt::time_point start_time = lt::clock_type::now(); - run_test( [](lt::session& ses) { @@ -184,18 +193,12 @@ TORRENT_TEST(apply_ip_filter) ses.async_add_torrent(params); }, - [&](lt::session& ses, std::vector const& alerts) + [&](lt::session& ses, lt::alert const* a) { - for (lt::alert const* a : alerts) + if (auto at = lt::alert_cast(a)) { - printf("%-3d %s\n", int(lt::duration_cast(a->timestamp() - - start_time).count()), a->message().c_str()); - - if (lt::add_torrent_alert const* at = lt::alert_cast(a)) - { - lt::torrent_handle h = at->handle; - add_fake_peers(h); - } + lt::torrent_handle h = at->handle; + add_fake_peers(h); } }, @@ -210,8 +213,6 @@ TORRENT_TEST(apply_ip_filter) // connected to TORRENT_TEST(update_ip_filter) { - lt::time_point start_time = lt::clock_type::now(); - run_test( [](lt::session& ses) { @@ -221,22 +222,16 @@ TORRENT_TEST(update_ip_filter) ses.async_add_torrent(params); }, - [&](lt::session& ses, std::vector const& alerts) + [&](lt::session& ses, lt::alert const* a) { - for (lt::alert const* a : alerts) + if (auto at = lt::alert_cast(a)) { - printf("%-3d %s\n", int(lt::duration_cast(a->timestamp() - - start_time).count()), a->message().c_str()); + // here we add the IP filter after the torrent has already been + // added + add_ip_filter(ses); - if (lt::add_torrent_alert const* at = lt::alert_cast(a)) - { - // here we add the IP filter after the torrent has already been - // added - add_ip_filter(ses); - - lt::torrent_handle h = at->handle; - add_fake_peers(h); - } + lt::torrent_handle h = at->handle; + add_fake_peers(h); } }, @@ -249,8 +244,6 @@ TORRENT_TEST(update_ip_filter) TORRENT_TEST(apply_ip_filter_to_torrent) { - lt::time_point start_time = lt::clock_type::now(); - run_test( [](lt::session& ses) { @@ -265,18 +258,12 @@ TORRENT_TEST(apply_ip_filter_to_torrent) ses.async_add_torrent(params); }, - [&](lt::session& ses, std::vector const& alerts) + [&](lt::session& ses, lt::alert const* a) { - for (lt::alert const* a : alerts) + if (auto at = lt::alert_cast(a)) { - printf("%-3d %s\n", int(lt::duration_cast(a->timestamp() - - start_time).count()), a->message().c_str()); - - if (lt::add_torrent_alert const* at = lt::alert_cast(a)) - { - lt::torrent_handle h = at->handle; - add_fake_peers(h); - } + lt::torrent_handle h = at->handle; + add_fake_peers(h); } }, @@ -292,8 +279,6 @@ TORRENT_TEST(apply_ip_filter_to_torrent) // make sure IP filters apply to trackers TORRENT_TEST(ip_filter_trackers) { - lt::time_point start_time = lt::clock_type::now(); - run_test( [](lt::session& ses) { @@ -312,15 +297,7 @@ TORRENT_TEST(ip_filter_trackers) ses.async_add_torrent(params); }, - [&](lt::session& ses, std::vector const& alerts) - { - for (lt::alert const* a : alerts) - { - printf("%-3d %s\n", int(lt::duration_cast(a->timestamp() - - start_time).count()), a->message().c_str()); - } - }, - + [](lt::session& ses, lt::alert const* a) {}, [](lt::session& ses, std::array& test_peers) { check_tripped(test_peers, {{false, false, false, true, true}} ); diff --git a/simulation/test_transfer.cpp b/simulation/test_transfer.cpp new file mode 100644 index 000000000..8c8370830 --- /dev/null +++ b/simulation/test_transfer.cpp @@ -0,0 +1,339 @@ +/* + +Copyright (c) 2015, Arvid Norberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + * Neither the name of the author nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include +#include "test.hpp" +#include "create_torrent.hpp" +#include "settings.hpp" +#include "libtorrent/session.hpp" +#include "libtorrent/deadline_timer.hpp" +#include "libtorrent/settings_pack.hpp" +#include "libtorrent/ip_filter.hpp" +#include "libtorrent/alert_types.hpp" +#include "libtorrent/aux_/proxy_settings.hpp" +#include "libtorrent/settings_pack.hpp" +#include "simulator/simulator.hpp" +#include "simulator/socks_server.hpp" + +using namespace sim; + +namespace lt = libtorrent; + +template +void run_test( + Setup const& setup + , HandleAlerts const& on_alert + , Test const& test) +{ + using namespace libtorrent; + + lt::time_point start_time = lt::clock_type::now(); + + // setup the simulation + sim::default_config network_cfg; + sim::simulation sim{network_cfg}; + sim::asio::io_service ios0 { sim, asio::ip::address_v4::from_string("50.0.0.1") }; + sim::asio::io_service ios1 { sim, asio::ip::address_v4::from_string("50.0.0.2") }; + + lt::session_proxy zombie[2]; + + sim::asio::io_service proxy_ios{sim, asio::ip::address_v4::from_string("50.50.50.50")}; + sim::socks_server socks4(proxy_ios, 4444, 4); + sim::socks_server socks5(proxy_ios, 5555, 5); + + // setup settings pack to use for the session (customization point) + lt::settings_pack pack = settings(); + + // disable utp by default + pack.set_bool(settings_pack::enable_outgoing_utp, false); + pack.set_bool(settings_pack::enable_incoming_utp, false); + + // disable encryption by default + pack.set_bool(settings_pack::prefer_rc4, false); + pack.set_int(settings_pack::in_enc_policy, settings_pack::pe_disabled); + pack.set_int(settings_pack::out_enc_policy, settings_pack::pe_disabled); + pack.set_int(settings_pack::allowed_enc_level, settings_pack::pe_plaintext); + + // create session + std::shared_ptr ses[] = { + std::make_shared(pack, ios0) + , std::make_shared(pack, ios1) }; + + setup(*ses[0], *ses[1]); + + // only monitor alerts for session 0 (the downloader) + ses[0]->set_alert_notify([&] { ios0.post([&] { + std::vector alerts; + ses[0]->pop_alerts(&alerts); + + for (lt::alert const* a : alerts) + { + printf("%-3d [0] %s\n", int(lt::duration_cast(a->timestamp() + - start_time).count()), a->message().c_str()); + if (auto ta = alert_cast(a)) + { + ta->handle.connect_peer(lt::tcp::endpoint(lt::address::from_string("50.0.0.2"), 6881)); + } + // call the user handler + on_alert(*ses[0], a); + } + } ); } ); + + ses[1]->set_alert_notify([&] { ios0.post([&] { + std::vector alerts; + ses[1]->pop_alerts(&alerts); + for (lt::alert const* a : alerts) + { + printf("%-3d [1] %s\n", int(lt::duration_cast(a->timestamp() + - start_time).count()), a->message().c_str()); + } + } ); } ); + + // the first peer is a downloader, the second peer is a seed + lt::add_torrent_params params = create_torrent(1); + params.flags &= ~lt::add_torrent_params::flag_auto_managed; + params.flags &= ~lt::add_torrent_params::flag_paused; + + params.save_path = save_path(0); + ses[0]->async_add_torrent(params); + + params.save_path = save_path(1); + ses[1]->async_add_torrent(params); + + lt::deadline_timer timer(ios0); + timer.expires_from_now(lt::seconds(60)); + timer.async_wait([&](lt::error_code const& ec) + { + test(ses); + + // shut down + int idx = 0; + for (auto& s : ses) + { + s->set_alert_notify([]{}); + zombie[idx++] = s->abort(); + s.reset(); + } + }); + + sim.run(); +} + +void enable_utp(lt::session& ses) +{ + using namespace libtorrent; + settings_pack p; + 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); + ses.apply_settings(p); +} + +void enable_enc(lt::session& ses) +{ + using namespace libtorrent; + settings_pack p; + 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); + ses.apply_settings(p); +} + +void filter_ips(lt::session& ses) +{ + using namespace libtorrent; + ip_filter filter; + filter.add_rule(asio::ip::address_v4::from_string("50.0.0.1") + , asio::ip::address_v4::from_string("50.0.0.2"), ip_filter::blocked); + ses.set_ip_filter(filter); +} + +void set_proxy(lt::session& ses, int proxy_type, bool proxy_peer_connections = true) +{ + // apply the proxy settings to session 0 + using namespace libtorrent; + 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); + 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, proxy_peer_connections); + p.set_bool(settings_pack::proxy_tracker_connections, true); + + ses.apply_settings(p); +} + +bool is_seed(lt::session& ses) +{ + lt::torrent_handle h = ses.get_torrents()[0]; + return h.status().is_seeding; +} + +TORRENT_TEST(socks4_tcp) +{ + using namespace libtorrent; + run_test( + [](lt::session& ses0, lt::session& ses1) + { + set_proxy(ses0, settings_pack::socks4); + filter_ips(ses1); + }, + [](lt::session& ses, lt::alert const* alert) {}, + [](std::shared_ptr ses[2]) { + TEST_EQUAL(is_seed(*ses[0]), true); + } + ); +} + +TORRENT_TEST(socks5_tcp) +{ + using namespace libtorrent; + run_test( + [](lt::session& ses0, lt::session& ses1) + { + set_proxy(ses0, settings_pack::socks5); + filter_ips(ses1); + }, + [](lt::session& ses, lt::alert const* alert) {}, + [](std::shared_ptr ses[2]) { + TEST_EQUAL(is_seed(*ses[0]), true); + } + ); +} + +TORRENT_TEST(encryption_tcp) +{ + using namespace libtorrent; + run_test( + [](lt::session& ses0, lt::session& ses1) + { enable_enc(ses0); enable_enc(ses1); }, + [](lt::session& ses, lt::alert const* alert) {}, + [](std::shared_ptr ses[2]) { + TEST_EQUAL(is_seed(*ses[0]), true); + } + ); +} + +TORRENT_TEST(no_proxy_tcp) +{ + using namespace libtorrent; + run_test( + [](lt::session& ses0, lt::session& ses1) {}, + [](lt::session& ses, lt::alert const* alert) {}, + [](std::shared_ptr ses[2]) { + TEST_EQUAL(is_seed(*ses[0]), true); + } + ); +} + +TORRENT_TEST(no_proxy_utp) +{ + using namespace libtorrent; + run_test( + [](lt::session& ses0, lt::session& ses1) {}, + [](lt::session& ses, lt::alert const* alert) {}, + [](std::shared_ptr ses[2]) { + TEST_EQUAL(is_seed(*ses[0]), true); + } + ); +} + +// TODO: test allow-fast +// TODO: test the different storage allocation modes +// TODO: test contiguous buffers + +// TODO: the socks server does not support UDP yet + +/* +TORRENT_TEST(encryption_utp) +{ + using namespace libtorrent; + run_test( + [](lt::session& ses0, lt::session& ses1) + { enable_enc(ses0); enable_enc(ses1); enable_utp(ses0); }, + [](lt::session& ses, lt::alert const* alert) {}, + [](std::shared_ptr ses[2]) { + TEST_EQUAL(is_seed(*ses[0]), true); + } + ); +} + +TORRENT_TEST(socks5_utp) +{ + using namespace libtorrent; + run_test( + [](lt::session& ses0, lt::session& ses1) + { + set_proxy(ses0, settings_pack::socks5); + enable_utp(ses0); + filter_ips(ses1); + }, + [](lt::session& ses, lt::alert const* alert) {}, + [](std::shared_ptr ses[2]) { + TEST_EQUAL(is_seed(*ses[0]), true); + } + ); +} +*/ + +// the purpose of these tests is to make sure that the sessions can't actually +// talk directly to each other. i.e. they are negative tests. If they can talk +// directly to each other, all other tests in here may be broken. +TORRENT_TEST(no_proxy_tcp_banned) +{ + using namespace libtorrent; + run_test( + [](lt::session& ses0, lt::session& ses1) { filter_ips(ses1); }, + [](lt::session& ses, lt::alert const* alert) {}, + [](std::shared_ptr ses[2]) { + TEST_EQUAL(is_seed(*ses[0]), false); + } + ); +} + +TORRENT_TEST(no_proxy_utp_banned) +{ + using namespace libtorrent; + run_test( + [](lt::session& ses0, lt::session& ses1) { filter_ips(ses1); }, + [](lt::session& ses, lt::alert const* alert) {}, + [](std::shared_ptr ses[2]) { + TEST_EQUAL(is_seed(*ses[0]), false); + } + ); +} + diff --git a/src/bt_peer_connection.cpp b/src/bt_peer_connection.cpp index be7ceac77..46914eaa8 100644 --- a/src/bt_peer_connection.cpp +++ b/src/bt_peer_connection.cpp @@ -1466,7 +1466,7 @@ namespace libtorrent r.piece = detail::read_int32(ptr); r.start = detail::read_int32(ptr); r.length = detail::read_int32(ptr); - + incoming_reject_request(r); } @@ -1485,7 +1485,7 @@ namespace libtorrent buffer::const_interval recv_buffer = m_recv_buffer.get(); const char* ptr = recv_buffer.begin + 1; int index = detail::read_int32(ptr); - + incoming_allowed_fast(index); } @@ -2039,7 +2039,7 @@ namespace libtorrent void bt_peer_connection::write_share_mode() { INVARIANT_CHECK; - + boost::shared_ptr t = associated_torrent().lock(); if (m_share_mode_id == 0) return; @@ -2157,7 +2157,7 @@ namespace libtorrent m_sent_bitfield = true; return; } - + const int num_pieces = t->torrent_file().num_pieces(); TORRENT_ASSERT(num_pieces > 0); if (num_pieces <= 0) @@ -2665,12 +2665,12 @@ namespace libtorrent TORRENT_ASSERT(recv_buffer == m_recv_buffer.get()); if (!m_recv_buffer.packet_finished()) return; - + // write our dh public key. m_dh_key_exchange is // initialized in write_pe1_2_dhkey() if (!is_outgoing()) write_pe1_2_dhkey(); if (is_disconnecting()) return; - + // read dh key, generate shared secret if (m_dh_key_exchange->compute_secret(recv_buffer.begin) != 0) { @@ -2825,7 +2825,7 @@ namespace libtorrent t = associated_torrent().lock(); TORRENT_ASSERT(t); } - + init_pe_rc4_handler(m_dh_key_exchange->get_secret(), ti->info_hash()); #ifndef TORRENT_DISABLE_LOGGING peer_log(peer_log_alert::info, "ENCRYPTION", "stream key found, torrent located"); @@ -2864,7 +2864,7 @@ namespace libtorrent TORRENT_ASSERT(!m_encrypted); TORRENT_ASSERT(!m_rc4_encrypted); TORRENT_ASSERT(recv_buffer == m_recv_buffer.get()); - + if (recv_buffer.left() < 8) { received_bytes(0, bytes_transferred); @@ -2874,7 +2874,7 @@ namespace libtorrent } // generate the verification constant - if (!m_sync_vc.get()) + if (!m_sync_vc.get()) { TORRENT_ASSERT(m_sync_bytes_read == 0); @@ -2892,7 +2892,7 @@ namespace libtorrent int syncoffset = get_syncoffset(m_sync_vc.get(), 8 , recv_buffer.begin, recv_buffer.left()); - // No sync + // No sync if (syncoffset == -1) { std::size_t bytes_processed = recv_buffer.left() - 8; @@ -2940,14 +2940,14 @@ namespace libtorrent TORRENT_ASSERT(m_recv_buffer.packet_size() == 4+2); received_bytes(0, bytes_transferred); bytes_transferred = 0; - + if (!m_recv_buffer.packet_finished()) return; buffer::interval wr_buf = m_recv_buffer.mutable_buffer(); rc4_decrypt(wr_buf.begin, m_recv_buffer.packet_size()); recv_buffer = m_recv_buffer.get(); - + boost::uint32_t crypto_field = detail::read_uint32(recv_buffer.begin); #ifndef TORRENT_DISABLE_LOGGING @@ -2962,7 +2962,7 @@ namespace libtorrent // select a crypto method int allowed_encryption = m_settings.get_int(settings_pack::allowed_enc_level); boost::uint32_t crypto_select = crypto_field & allowed_encryption; - + // when prefer_rc4 is set, keep the most significant bit // otherwise keep the least significant one if (m_settings.get_bool(settings_pack::prefer_rc4)) @@ -2998,7 +2998,7 @@ namespace libtorrent // check if crypto select is valid int allowed_encryption = m_settings.get_int(settings_pack::allowed_enc_level); - crypto_field &= allowed_encryption; + crypto_field &= allowed_encryption; if (crypto_field == 0) { // we don't allow any of the offered encryption levels @@ -3018,7 +3018,7 @@ namespace libtorrent disconnect(errors::invalid_pad_size, op_encryption, 2); return; } - + m_state = read_pe_pad; if (!is_outgoing()) m_recv_buffer.reset(len_pad + 2); // len(IA) at the end of pad @@ -3057,8 +3057,8 @@ namespace libtorrent { recv_buffer.begin += pad_size; int len_ia = detail::read_int16(recv_buffer.begin); - - if (len_ia < 0) + + if (len_ia < 0) { disconnect(errors::invalid_encrypt_handshake, op_encryption, 2); return; diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index 46a8d502d..380e2bf74 100644 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -6120,12 +6120,6 @@ namespace libtorrent m_counters.inc_stats_counter(counters::on_read_counter); m_ses.received_buffer(bytes_transferred); -#ifndef TORRENT_DISABLE_LOGGING - peer_log(peer_log_alert::incoming, "ON_RECEIVE_DATA" - , "bytes: %d error: %s" - , int(bytes_transferred), error.message().c_str()); -#endif - if (m_extension_outstanding_bytes > 0) m_extension_outstanding_bytes -= (std::min)(m_extension_outstanding_bytes, int(bytes_transferred)); diff --git a/test/test_transfer.cpp b/test/test_transfer.cpp index e943f74e8..b51f448f9 100644 --- a/test/test_transfer.cpp +++ b/test/test_transfer.cpp @@ -59,13 +59,9 @@ const int mask = alert::all_categories & ~(alert::performance_warning | alert::s int peer_disconnects = 0; -int tracker_responses = 0; - bool on_alert(alert const* a) { - if (alert_cast(a)) - ++tracker_responses; - else if (alert_cast(a)) + if (alert_cast(a)) ++peer_disconnects; else if (alert_cast(a)) ++peer_disconnects; @@ -216,6 +212,7 @@ void test_transfer(int proxy_type, settings_pack const& sett pack.set_bool(settings_pack::allow_multiple_connections_per_ip, false); + // TODO: these settings_pack tests belong in their own test pack.set_int(settings_pack::unchoke_slots_limit, 0); ses1.apply_settings(pack); TEST_CHECK(ses1.get_settings().get_int(settings_pack::unchoke_slots_limit) == 0); @@ -265,7 +262,6 @@ void test_transfer(int proxy_type, settings_pack const& sett // to make sure it can handle switching paths bool test_move_storage = false; - tracker_responses = 0; int upload_mode_timer = 0; wait_for_downloading(ses2, "ses2"); @@ -379,27 +375,6 @@ TORRENT_TEST(no_contiguous_buffers) } // test with all kinds of proxies -TORRENT_TEST(no_proxy) -{ - using namespace libtorrent; - test_transfer(settings_pack::none, settings_pack()); - cleanup(); -} - -TORRENT_TEST(socks4) -{ - using namespace libtorrent; - test_transfer(settings_pack::socks4, settings_pack()); - cleanup(); -} - -TORRENT_TEST(socks5) -{ - using namespace libtorrent; - test_transfer(settings_pack::socks5, settings_pack()); - cleanup(); -} - TORRENT_TEST(socks5_pw) { using namespace libtorrent; From 7b84c8122eaaedc465bd89e4dcd4f4e07c576d91 Mon Sep 17 00:00:00 2001 From: arvidn Date: Fri, 27 Nov 2015 18:35:30 -0500 Subject: [PATCH 2/2] extend test_transfer to include IPv6-only networks --- simulation/libsimulator | 2 +- simulation/test_transfer.cpp | 94 ++++++++++++++++++++++++++++++++---- 2 files changed, 85 insertions(+), 11 deletions(-) diff --git a/simulation/libsimulator b/simulation/libsimulator index df7a6e308..a4b10668e 160000 --- a/simulation/libsimulator +++ b/simulation/libsimulator @@ -1 +1 @@ -Subproject commit df7a6e308f2c414e4ed5ffe760b8c15f7dc5f17c +Subproject commit a4b10668ea22e9328a2668baf8990b3685fe7578 diff --git a/simulation/test_transfer.cpp b/simulation/test_transfer.cpp index 8c8370830..be978e538 100644 --- a/simulation/test_transfer.cpp +++ b/simulation/test_transfer.cpp @@ -48,25 +48,46 @@ using namespace sim; namespace lt = libtorrent; +enum flags_t +{ + ipv6 = 1, +}; + +asio::ip::address addr(char const* str) +{ + return asio::ip::address::from_string(str); +} + template void run_test( Setup const& setup , HandleAlerts const& on_alert - , Test const& test) + , Test const& test + , int flags = 0) { using namespace libtorrent; lt::time_point start_time = lt::clock_type::now(); + const bool use_ipv6 = flags & ipv6; + + char const* peer0_ip[2] = { "50.0.0.1", "feed:face:baad:f00d::1" }; + char const* peer1_ip[2] = { "50.0.0.2", "feed:face:baad:f00d::2" }; + + using asio::ip::address; + address peer0 = addr(peer0_ip[use_ipv6]); + address peer1 = addr(peer1_ip[use_ipv6]); + address proxy = (flags & ipv6) ? addr("2001::2") : addr("50.50.50.50"); + // setup the simulation sim::default_config network_cfg; sim::simulation sim{network_cfg}; - sim::asio::io_service ios0 { sim, asio::ip::address_v4::from_string("50.0.0.1") }; - sim::asio::io_service ios1 { sim, asio::ip::address_v4::from_string("50.0.0.2") }; + sim::asio::io_service ios0 { sim, peer0 }; + sim::asio::io_service ios1 { sim, peer1 }; lt::session_proxy zombie[2]; - sim::asio::io_service proxy_ios{sim, asio::ip::address_v4::from_string("50.50.50.50")}; + sim::asio::io_service proxy_ios{sim, proxy }; sim::socks_server socks4(proxy_ios, 4444, 4); sim::socks_server socks5(proxy_ios, 5555, 5); @@ -83,10 +104,14 @@ void run_test( pack.set_int(settings_pack::out_enc_policy, settings_pack::pe_disabled); pack.set_int(settings_pack::allowed_enc_level, settings_pack::pe_plaintext); + pack.set_str(settings_pack::listen_interfaces, peer0_ip[use_ipv6] + std::string(":6881")); + // create session - std::shared_ptr ses[] = { - std::make_shared(pack, ios0) - , std::make_shared(pack, ios1) }; + std::shared_ptr ses[2]; + ses[0] = std::make_shared(pack, ios0); + + pack.set_str(settings_pack::listen_interfaces, peer1_ip[use_ipv6] + std::string(":6881")); + ses[1] = std::make_shared(pack, ios1); setup(*ses[0], *ses[1]); @@ -101,7 +126,7 @@ void run_test( - start_time).count()), a->message().c_str()); if (auto ta = alert_cast(a)) { - ta->handle.connect_peer(lt::tcp::endpoint(lt::address::from_string("50.0.0.2"), 6881)); + ta->handle.connect_peer(lt::tcp::endpoint(peer1, 6881)); } // call the user handler on_alert(*ses[0], a); @@ -179,7 +204,7 @@ void filter_ips(lt::session& ses) ses.set_ip_filter(filter); } -void set_proxy(lt::session& ses, int proxy_type, bool proxy_peer_connections = true) +void set_proxy(lt::session& ses, int proxy_type, int flags = 0, bool proxy_peer_connections = true) { // apply the proxy settings to session 0 using namespace libtorrent; @@ -189,7 +214,10 @@ void set_proxy(lt::session& ses, int proxy_type, bool proxy_peer_connections = t p.set_int(settings_pack::proxy_port, 4444); else p.set_int(settings_pack::proxy_port, 5555); - p.set_str(settings_pack::proxy_hostname, "50.50.50.50"); + if (flags & 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, proxy_peer_connections); p.set_bool(settings_pack::proxy_tracker_connections, true); @@ -248,6 +276,52 @@ TORRENT_TEST(encryption_tcp) ); } +TORRENT_TEST(no_proxy_tcp_ipv6) +{ + using namespace libtorrent; + run_test( + [](lt::session& ses0, lt::session& ses1) {}, + [](lt::session& ses, lt::alert const* alert) {}, + [](std::shared_ptr ses[2]) { + TEST_EQUAL(is_seed(*ses[0]), true); + }, + ipv6 + ); +} + +TORRENT_TEST(no_proxy_utp_ipv6) +{ + using namespace libtorrent; + run_test( + [](lt::session& ses0, lt::session& ses1) {}, + [](lt::session& ses, lt::alert const* alert) {}, + [](std::shared_ptr ses[2]) { + TEST_EQUAL(is_seed(*ses[0]), true); + }, + ipv6 + ); +} + +// TODO: the socks server does not support IPv6 addresses yet +/* +TORRENT_TEST(socks5_tcp_ipv6) +{ + using namespace libtorrent; + run_test( + [](lt::session& ses0, lt::session& ses1) + { + set_proxy(ses0, settings_pack::socks5); + filter_ips(ses1); + }, + [](lt::session& ses, lt::alert const* alert) {}, + [](std::shared_ptr ses[2]) { + TEST_EQUAL(is_seed(*ses[0]), true); + }, + ipv6 + ); +} +*/ + TORRENT_TEST(no_proxy_tcp) { using namespace libtorrent;