diff --git a/include/libtorrent/alert_types.hpp b/include/libtorrent/alert_types.hpp index e2e61ccb2..882cde0f5 100644 --- a/include/libtorrent/alert_types.hpp +++ b/include/libtorrent/alert_types.hpp @@ -523,8 +523,7 @@ namespace libtorrent TORRENT_DEFINE_ALERT(peer_disconnected_alert); const static int static_category = alert::debug_notification; - virtual std::string message() const - { return peer_alert::message() + " disconnecting: " + error.message(); } + virtual std::string message() const; error_code error; diff --git a/include/libtorrent/session.hpp b/include/libtorrent/session.hpp index 563301321..2b1ff1a03 100644 --- a/include/libtorrent/session.hpp +++ b/include/libtorrent/session.hpp @@ -600,6 +600,7 @@ namespace libtorrent , const char* net_interface = 0 , int flags = 0); unsigned short listen_port() const; + unsigned short ssl_listen_port() const; bool is_listening() const; // if the listen port failed in some way diff --git a/include/libtorrent/session_settings.hpp b/include/libtorrent/session_settings.hpp index eefbcb9a5..ad8778868 100644 --- a/include/libtorrent/session_settings.hpp +++ b/include/libtorrent/session_settings.hpp @@ -931,6 +931,7 @@ namespace libtorrent bool lock_files; // open an ssl listen socket for ssl torrents on this port + // if this is 0, outgoing SSL connections are disabled int ssl_listen; // this is the factor X in the formula to calculate the diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index ccfa9fbbb..4b60baaf0 100644 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -863,12 +863,13 @@ namespace libtorrent TORRENT_ASSERT(m_num_connecting > 0); --m_num_connecting; } + + bool is_ssl_torrent() const { return m_ssl_torrent; } #ifdef TORRENT_USE_OPENSSL void set_ssl_cert(std::string const& certificate , std::string const& private_key , std::string const& dh_params , std::string const& passphrase); - bool is_ssl_torrent() const { return m_ssl_ctx; } boost::asio::ssl::context* ssl_ctx() const { return m_ssl_ctx.get(); } #endif @@ -1378,6 +1379,11 @@ namespace libtorrent bool m_is_active_download:1; bool m_is_active_finished:1; + // even if we're not built to support SSL torrents, + // remember that this is an SSL torrent, so that we don't + // accidentally start seeding it without any authentication. + bool m_ssl_torrent:1; + #if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS public: // set to false until we've loaded resume data diff --git a/include/libtorrent/torrent_info.hpp b/include/libtorrent/torrent_info.hpp index e09ea8487..7abfd5e4a 100644 --- a/include/libtorrent/torrent_info.hpp +++ b/include/libtorrent/torrent_info.hpp @@ -474,6 +474,11 @@ namespace libtorrent #ifdef TORRENT_USE_OPENSSL std::string const& ssl_cert() const { return m_ssl_root_cert; } +#else + std::string ssl_cert() const + { + return m_info_dict.dict_find_string_value("ssl-cert"); + } #endif bool is_valid() const { return m_files.is_valid(); } diff --git a/src/alert.cpp b/src/alert.cpp index 12c4a1637..e60451d97 100644 --- a/src/alert.cpp +++ b/src/alert.cpp @@ -508,5 +508,12 @@ namespace libtorrent { return msg; } + std::string peer_disconnected_alert::message() const + { + char msg[600]; + snprintf(msg, sizeof(msg), "%s disconnecting: [%s] %s", peer_alert::message().c_str() + , error.category().name(), error.message().c_str()); + return msg; + } } // namespace libtorrent diff --git a/src/session.cpp b/src/session.cpp index b59b16159..df52311aa 100644 --- a/src/session.cpp +++ b/src/session.cpp @@ -757,6 +757,12 @@ namespace libtorrent return r; } + unsigned short session::ssl_listen_port() const + { + TORRENT_SYNC_CALL_RET(unsigned short, ssl_listen_port); + return r; + } + session_status session::status() const { TORRENT_SYNC_CALL_RET(session_status, status); diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 592040370..dc4a4152a 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -581,10 +581,12 @@ namespace aux { if (!t) return SSL_TLSEXT_ERR_ALERT_FATAL; // if the torrent we found isn't an SSL torrent, also fail. - // the torrent doesn't have an SSL context and should not allow - // incoming SSL connections if (!t->is_ssl_torrent()) return SSL_TLSEXT_ERR_ALERT_FATAL; + // if the torrent doesn't have an SSL context and should not allow + // incoming SSL connections + if (!t->ssl_ctx()) return SSL_TLSEXT_ERR_ALERT_FATAL; + // use this torrent's certificate SSL_set_SSL_CTX(s, t->ssl_ctx()->native_handle()); diff --git a/src/torrent.cpp b/src/torrent.cpp index a98659e91..fa688f521 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -427,6 +427,7 @@ namespace libtorrent , m_in_state_updates(false) , m_is_active_download(false) , m_is_active_finished(false) + , m_ssl_torrent(false) { // if there is resume data already, we don't need to trigger the initial save // resume data @@ -1363,6 +1364,12 @@ namespace libtorrent if (!preverified) return false; // we're only interested in checking the certificate at the end of the chain. + // TODO: is verify_peer_cert called once per certificate in the chain, and + // this function just tells us which depth we're at right now? If so, the comment + // makes sense. + // any certificate that isn't the leaf (i.e. the one presented by the peer) + // should be accepted automatically, given preverified is true. The leaf certificate + // need to be verified to make sure its DN matches the info-hash int depth = X509_STORE_CTX_get_error_depth(ctx.native_handle()); if (depth > 0) return true; @@ -1585,10 +1592,14 @@ namespace libtorrent if (m_file_priority.size() > m_torrent_file->num_files()) m_file_priority.resize(m_torrent_file->num_files()); -#ifdef TORRENT_USE_OPENSSL std::string cert = m_torrent_file->ssl_cert(); - if (!cert.empty()) init_ssl(cert); + if (!cert.empty()) + { + m_ssl_torrent = true; +#ifdef TORRENT_USE_OPENSSL + init_ssl(cert); #endif + } m_file_priority.resize(m_torrent_file->num_files(), 1); m_file_progress.resize(m_torrent_file->num_files(), 0); @@ -5781,13 +5792,13 @@ namespace libtorrent void* userdata = 0; #ifdef TORRENT_USE_OPENSSL - if (is_ssl_torrent()) + if (is_ssl_torrent() && m_ses.settings().ssl_listen != 0) { userdata = m_ssl_ctx.get(); // SSL handshakes are slow timeout_extend = 10; - // we don't support SSL over uTP yet + // TODO: 3 support SSL over uTP sm = 0; } #endif @@ -5979,6 +5990,13 @@ namespace libtorrent return false; } + if (!m_ssl_ctx) + { + // we don't have a valid cert, don't accept any connection! + p->disconnect(errors::invalid_ssl_cert); + return false; + } + if (SSL_get_SSL_CTX(ssl_conn) != m_ssl_ctx->native_handle()) { // if the SSL_CTX associated with this connection is @@ -5997,6 +6015,14 @@ namespace libtorrent return false; } #endif +#else // TORRENT_USE_OPENSSL + if (is_ssl_torrent()) + { + // Don't accidentally allow seeding of SSL torrents, just + // because libtorrent wasn't built with SSL support + p->disconnect(errors::requires_ssl_connection); + return false; + } #endif // TORRENT_USE_OPENSSL TORRENT_ASSERT(p != 0); diff --git a/test/Jamfile b/test/Jamfile index 2a6636e62..e3083e98d 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -59,6 +59,7 @@ test-suite libtorrent : [ run test_session.cpp ] [ run test_upnp.cpp ] + [ run test_ssl.cpp ] [ run test_tracker.cpp ] [ run test_checking.cpp ] [ run test_web_seed.cpp ] diff --git a/test/setup_transfer.cpp b/test/setup_transfer.cpp index 7f70097dc..9bfb1c05e 100644 --- a/test/setup_transfer.cpp +++ b/test/setup_transfer.cpp @@ -51,6 +51,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/socket_io.hpp" // print_endpoint #include "libtorrent/socket_type.hpp" #include "libtorrent/instantiate_connection.hpp" +#include "setup_transfer.hpp" #ifdef TORRENT_USE_OPENSSL #include @@ -172,14 +173,14 @@ bool print_alerts(libtorrent::session& ses, char const* name if (predicate && predicate(*i)) ret = true; if (peer_disconnected_alert* p = alert_cast(*i)) { - fprintf(stderr, " %s(%s): %s\n", name, print_endpoint(p->ip).c_str(), p->message().c_str()); + fprintf(stderr, "%s: %s(%s): %s\n", time_now_string(), name, print_endpoint(p->ip).c_str(), p->message().c_str()); } else if ((*i)->message() != "block downloading" && (*i)->message() != "block finished" && (*i)->message() != "piece finished" && !no_output) { - fprintf(stderr, " %s: %s\n", name, (*i)->message().c_str()); + fprintf(stderr, "%s: %s: %s\n", time_now_string(), name, (*i)->message().c_str()); } TEST_CHECK(alert_cast(*i) == 0 || allow_failed_fastresume); @@ -187,7 +188,7 @@ bool print_alerts(libtorrent::session& ses, char const* name peer_error_alert* pea = alert_cast(*i); if (pea) { - fprintf(stderr, " peer error: %s\n", pea->error.message().c_str()); + fprintf(stderr, "%s: peer error: %s\n", time_now_string(), pea->error.message().c_str()); TEST_CHECK((!handles.empty() && h.status().is_seeding) || pea->error.message() == "connecting to peer" || pea->error.message() == "closing connection to ourself" @@ -359,7 +360,7 @@ void create_random_files(std::string const& path, const int file_sizes[], int nu } boost::intrusive_ptr create_torrent(std::ostream* file, int piece_size - , int num_pieces, bool add_tracker, bool encrypted_torrent) + , int num_pieces, bool add_tracker, std::string ssl_certificate) { char const* tracker_url = "http://non-existent-name.com/announce"; // excercise the path when encountering invalid urls @@ -377,6 +378,23 @@ boost::intrusive_ptr create_torrent(std::ostream* file, int piece_ t.add_tracker(invalid_tracker_protocol); } + if (!ssl_certificate.empty()) + { + std::vector file_buf; + error_code ec; + int res = load_file(ssl_certificate, file_buf, ec); + if (ec || res < 0) + { + fprintf(stderr, "failed to load SSL certificate: %s\n", ec.message().c_str()); + } + else + { + std::string pem; + std::copy(file_buf.begin(), file_buf.end(), std::back_inserter(pem)); + t.set_root_cert(pem); + } + } + std::vector piece(piece_size); for (int i = 0; i < int(piece.size()); ++i) piece[i] = (i % 26) + 'A'; @@ -401,14 +419,6 @@ boost::intrusive_ptr create_torrent(std::ostream* file, int piece_ entry tor = t.generate(); - if (encrypted_torrent) - { - std::string key; - key.resize(32); - std::generate(key.begin(), key.end(), &std::rand); - tor["info"]["encryption-key"] = key; - } - bencode(out, tor); error_code ec; return boost::intrusive_ptr(new torrent_info( @@ -420,7 +430,7 @@ setup_transfer(session* ses1, session* ses2, session* ses3 , bool clear_files, bool use_metadata_transfer, bool connect_peers , std::string suffix, int piece_size , boost::intrusive_ptr* torrent, bool super_seeding - , add_torrent_params const* p, bool stop_lsd, bool encrypted_torrent) + , add_torrent_params const* p, bool stop_lsd, bool use_ssl_ports) { assert(ses1); assert(ses2); @@ -464,7 +474,7 @@ setup_transfer(session* ses1, session* ses2, session* ses3 error_code ec; create_directory("tmp1" + suffix, ec); std::ofstream file(combine_path("tmp1" + suffix, "temporary").c_str()); - t = ::create_torrent(&file, piece_size, 19, true, encrypted_torrent); + t = ::create_torrent(&file, piece_size, 19, true); file.close(); if (clear_files) { @@ -530,21 +540,47 @@ setup_transfer(session* ses1, session* ses2, session* ses3 if (connect_peers) { - fprintf(stderr, "connecting peer\n"); error_code ec; - tor1.connect_peer(tcp::endpoint(address::from_string("127.0.0.1", ec) - , ses2->listen_port())); + if (use_ssl_ports) + { + fprintf(stderr, "ses1: connecting peer port: %d\n", int(ses2->ssl_listen_port())); + tor1.connect_peer(tcp::endpoint(address::from_string("127.0.0.1", ec) + , ses2->ssl_listen_port())); + } + else + { + fprintf(stderr, "ses1: connecting peer port: %d\n", int(ses2->listen_port())); + tor1.connect_peer(tcp::endpoint(address::from_string("127.0.0.1", ec) + , ses2->listen_port())); + } if (ses3) { // give the other peers some time to get an initial // set of pieces before they start sharing with each-other - tor3.connect_peer(tcp::endpoint( - address::from_string("127.0.0.1", ec) - , ses2->listen_port())); - tor3.connect_peer(tcp::endpoint( - address::from_string("127.0.0.1", ec) - , ses1->listen_port())); + + if (use_ssl_ports) + { + fprintf(stderr, "ses3: connecting peer port: %d\n", int(ses2->ssl_listen_port())); + tor3.connect_peer(tcp::endpoint( + address::from_string("127.0.0.1", ec) + , ses2->ssl_listen_port())); + fprintf(stderr, "ses3: connecting peer port: %d\n", int(ses1->ssl_listen_port())); + tor3.connect_peer(tcp::endpoint( + address::from_string("127.0.0.1", ec) + , ses1->ssl_listen_port())); + } + else + { + fprintf(stderr, "ses3: connecting peer port: %d\n", int(ses2->listen_port())); + tor3.connect_peer(tcp::endpoint( + address::from_string("127.0.0.1", ec) + , ses2->listen_port())); + fprintf(stderr, "ses3: connecting peer port: %d\n", int(ses1->listen_port())); + tor3.connect_peer(tcp::endpoint( + address::from_string("127.0.0.1", ec) + , ses1->listen_port())); + } } } @@ -753,19 +789,6 @@ int start_web_server(bool ssl, bool chunked_encoding) web_initialized.clear(l); } - if (ssl) - { - system("echo . > tmp"); - system("echo test province >>tmp"); - system("echo test city >> tmp"); - system("echo test company >> tmp"); - system("echo test department >> tmp"); - system("echo 127.0.0.1 >> tmp"); - system("echo test@test.com >> tmp"); - system("openssl req -new -x509 -keyout server.pem -out server.pem " - "-days 365 -nodes EXPORT create_torrent(std::ostream* file = 0 - , int piece_size = 16 * 1024, int num_pieces = 13, bool add_tracker = true, bool encrypted = false); + , int piece_size = 16 * 1024, int num_pieces = 13, bool add_tracker = true + , std::string ssl_certificate = ""); boost::tuple* torrent = 0, bool super_seeding = false - , libtorrent::add_torrent_params const* p = 0, bool stop_lsd = true, bool encrypted_torrent = false); + , libtorrent::add_torrent_params const* p = 0, bool stop_lsd = true, bool use_ssl_ports = false); int EXPORT start_web_server(bool ssl = false, bool chunked = false); void EXPORT stop_web_server(); diff --git a/test/ssl/cert_request.pem b/test/ssl/cert_request.pem new file mode 100644 index 000000000..b386c9a08 --- /dev/null +++ b/test/ssl/cert_request.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBsTCCARoCAQAwXDELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx +ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEVMBMGA1UEAwwMdGVz +dCB0b3JyZW50MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQClM6eDsvQiXVj7 +ZCrWko+PmlJUMBzPjTbDvSfLfw8zGH3OjPJev1lf3JCPRAGu8CRVFLPZg2RZUfLi +9dITBThnTD2T9/5sHeNpxAU0JW7FPETHay+Q4B1abuYJ+nPmdLbdaiegQjJgoAcH +GlYi6YPNM5n5B8y9vA+k3DOFTAXnLwIDAQABoBUwEwYJKoZIhvcNAQkHMQYMBHRl +c3QwDQYJKoZIhvcNAQEFBQADgYEAJuhp3OEKPqYfF2pz/BooTU5cu/bcgy21M6IM +rEzQSIBO5bNxetK3VlVaclC+QlKMDN5efHw1PiAZPXGGD3BfZyNtf1xEH7urCDqy +McGog59bL/wOwUqGwq5iq18e05XPyrc6JgZUwjKLFu3lSP6FkW0z8c1dbLrMduL+ +M9dvHdk= +-----END CERTIFICATE REQUEST----- diff --git a/test/ssl/dhparams.pem b/test/ssl/dhparams.pem new file mode 100644 index 000000000..9c1489215 --- /dev/null +++ b/test/ssl/dhparams.pem @@ -0,0 +1,4 @@ +-----BEGIN DH PARAMETERS----- +MEYCQQCyiMyueIbvCXyd04Z8CCAB44IKMgYTcBcWUEb8Ka3c5kwrlJOw+zi7MYD3 +yLthYad9KAEOAA7DysJs7G+f3KBjAgEC +-----END DH PARAMETERS----- diff --git a/test/ssl/peer_certificate.pem b/test/ssl/peer_certificate.pem new file mode 100644 index 000000000..6ec5f83db --- /dev/null +++ b/test/ssl/peer_certificate.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 17335853646391593947 (0xf095530ac754cbdb) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=AU, ST=Some-State, O=Internet Widgits Pty Ltd, CN=test root cert + Validity + Not Before: Jul 27 23:50:37 2013 GMT + Not After : Jul 27 23:50:37 2014 GMT + Subject: C=AU, ST=Some-State, O=Internet Widgits Pty Ltd, CN=* + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (1024 bit) + Modulus: + 00:e4:4d:f9:0f:d2:c4:d2:f0:e7:e7:ab:10:ea:75: + 88:be:21:13:29:bd:bf:8a:7a:dc:07:1b:0c:cf:e1: + c8:09:81:04:f9:ce:85:12:92:62:38:23:28:03:27: + c8:0f:b5:5b:63:51:8a:2d:8c:dd:83:a8:ef:90:4c: + 3b:ec:de:91:5c:e6:bd:74:9e:86:10:b0:f0:c0:bf: + de:27:f2:2e:2e:d7:b0:77:35:c0:80:41:b3:20:9b: + 06:62:20:6a:b4:52:8c:b6:44:46:b5:9e:fb:d2:fe: + 53:fe:10:8a:5a:f9:df:14:ad:00:66:29:fb:74:8b: + 8d:29:4c:41:87:d0:d5:a5:35 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + 2A:EE:9B:AF:32:D9:B2:A9:E5:46:42:53:A9:6E:B7:87:7A:EA:E9:63 + X509v3 Authority Key Identifier: + keyid:B7:EA:25:4E:F3:13:05:CB:7F:6E:14:BD:13:BC:84:68:ED:35:8E:74 + + Signature Algorithm: sha1WithRSAEncryption + a8:dd:09:73:90:9e:48:95:8f:cc:fc:d7:0a:53:a8:07:5f:c5: + 6b:1f:f6:e5:52:92:91:de:5d:7f:e5:a5:b4:d0:0c:23:4c:5c: + 1a:7a:96:fc:e5:76:62:e7:ce:c3:2f:4d:54:e1:06:57:af:71: + 10:48:a5:49:95:cf:ab:8c:12:e9:de:93:1f:6c:bd:24:3b:e3: + 1b:ce:a5:19:aa:82:49:9d:44:1e:fb:57:cb:b9:ca:06:9d:44: + d6:5f:72:28:8a:a9:45:26:e8:9f:f5:a5:e3:12:05:5e:5e:d8: + 96:90:4c:78:bc:16:45:fe:49:8e:34:78:e1:16:46:3d:26:90: + e3:5d +-----BEGIN CERTIFICATE----- +MIICqDCCAhGgAwIBAgIJAPCVUwrHVMvbMA0GCSqGSIb3DQEBBQUAMF4xCzAJBgNV +BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQxFzAVBgNVBAMMDnRlc3Qgcm9vdCBjZXJ0MB4XDTEzMDcy +NzIzNTAzN1oXDTE0MDcyNzIzNTAzN1owUTELMAkGA1UEBhMCQVUxEzARBgNVBAgM +ClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEK +MAgGA1UEAwwBKjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA5E35D9LE0vDn +56sQ6nWIviETKb2/inrcBxsMz+HICYEE+c6FEpJiOCMoAyfID7VbY1GKLYzdg6jv +kEw77N6RXOa9dJ6GELDwwL/eJ/IuLtewdzXAgEGzIJsGYiBqtFKMtkRGtZ770v5T +/hCKWvnfFK0AZin7dIuNKUxBh9DVpTUCAwEAAaN7MHkwCQYDVR0TBAIwADAsBglg +hkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0O +BBYEFCrum68y2bKp5UZCU6lut4d66uljMB8GA1UdIwQYMBaAFLfqJU7zEwXLf24U +vRO8hGjtNY50MA0GCSqGSIb3DQEBBQUAA4GBAKjdCXOQnkiVj8z81wpTqAdfxWsf +9uVSkpHeXX/lpbTQDCNMXBp6lvzldmLnzsMvTVThBlevcRBIpUmVz6uMEunekx9s +vSQ74xvOpRmqgkmdRB77V8u5ygadRNZfciiKqUUm6J/1peMSBV5e2JaQTHi8FkX+ +SY40eOEWRj0mkONd +-----END CERTIFICATE----- diff --git a/test/ssl/peer_private_key.pem b/test/ssl/peer_private_key.pem new file mode 100644 index 000000000..910a95dcf --- /dev/null +++ b/test/ssl/peer_private_key.pem @@ -0,0 +1,17 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIICxjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQISENU51R9xoQCAggA +MBQGCCqGSIb3DQMHBAgrubUiGwLYbgSCAoBFbrx1Dhn5drmbUJZIlcBQF7v1mMVZ +Cve/G6tr9Vk7iukKJDe7x90f+CP1GtL96yzWhTEa8DVVq62D0gGDDjcANlkrP8P2 +Zgn1J69DdJZ0boNT1mhYkCnTMYeBGgOdnqgV2IQxNXFntu9PYDnUUYi+5XTMM9SV +P2txFzhm8ZpTKW78VekYki6l83eCEr/dzpqQoSML33OZlwlK2P0ef/SmHf+mvIga +fswG7mpOo0IAuHb7R5W+QGv10XGdSzF+rKV1jtl9KvOlK2GSsika+4FjaAAD78Q0 +37FUakE6tQT27yeGG8/z3a4WTCbMQZPLCcjgmZBcM0Cn8dZsQDCiaM9WfXl1j9PH +FEuc2KDetG0FhTWTCZ9j64Or3UMA1zEtLIG4eVJMrLxcW8OuGuYLcwMc79lvHzzg +/EEfdMW+iQr7FQFltH507245ve7+1aKceCfKB3lcWjQClkSGzrbrSPJaaeweLWlw +XPqqF/xdRtGxTays8ED/HQML+6nsgpoOtFCPeSvxniIVpSVnUhFt7v0G05J1fk1H +Ppm4DF8VbnB6yYPGyGG/LUBJL8aB/0ffhMHLiPKGm/SQeahYeAJgQUEDmIRLnZtv +CSfH/0HsxjuqjZT3kFnZu5x907QBry1kTHi6uVQo2kPtGhQAuAbUyuF/3TQBFNHQ +ah2jxBb5u2SZaFOjpY/wQk76egupfLny/ZOJD3NSjiAm+opOO6zhPQjJ9Hdp1y5H +UxBAAI53b/YfzQDG1Cm9HnYQdGkzwaUMllM0JntXr8T1c7ZNvGiW+DLqxLRxEskP +8itWHr1KxPGXBnAPpVuF7f/P9GzyEVRLuddAWUilFbrYPkZj02Lf/bJ8 +-----END ENCRYPTED PRIVATE KEY----- diff --git a/test/ssl/root_ca_cert.pem b/test/ssl/root_ca_cert.pem new file mode 100644 index 000000000..466ff18a3 --- /dev/null +++ b/test/ssl/root_ca_cert.pem @@ -0,0 +1,57 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 17335853646391593945 (0xf095530ac754cbd9) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=AU, ST=Some-State, O=Internet Widgits Pty Ltd, CN=test root cert + Validity + Not Before: Jul 27 14:26:20 2013 GMT + Not After : Jul 26 14:26:20 2016 GMT + Subject: C=AU, ST=Some-State, O=Internet Widgits Pty Ltd, CN=test root cert + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (1024 bit) + Modulus: + 00:e2:3c:4a:44:9e:81:d3:9a:f4:f1:a8:f7:51:58: + b3:67:b0:58:ca:e3:d0:12:d7:0c:c4:36:cb:0d:f6: + f3:46:24:d2:87:31:6a:25:55:08:21:94:38:83:eb: + b1:b9:cf:90:81:d0:8f:77:fb:de:66:27:3a:6d:9a: + 0d:cd:5d:36:bf:ac:81:9b:15:dd:7e:71:cc:6c:7c: + 86:43:a7:47:24:f2:dc:6d:99:cb:0d:cb:85:11:6f: + 8c:22:c1:63:dc:f3:65:3d:b5:35:51:5e:30:78:09: + 80:27:7f:72:d3:ea:b6:64:d8:b7:93:91:f6:ba:a4: + 8f:ae:69:53:94:95:b5:2f:3d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + B7:EA:25:4E:F3:13:05:CB:7F:6E:14:BD:13:BC:84:68:ED:35:8E:74 + X509v3 Authority Key Identifier: + keyid:B7:EA:25:4E:F3:13:05:CB:7F:6E:14:BD:13:BC:84:68:ED:35:8E:74 + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 56:1e:82:1d:9a:ac:b2:28:b0:36:a9:5a:3c:5c:bf:72:ad:f3: + 4e:d1:a8:48:c0:59:4c:cf:2e:a1:9a:f4:ce:31:7e:53:44:13: + fb:ee:3e:bc:f4:dc:bd:9e:bf:35:3b:84:d8:3c:79:ea:04:66: + ae:0b:d2:84:13:03:0c:f6:d0:da:9a:f8:e1:d2:b3:73:14:c6: + 71:e4:29:77:bf:24:f6:f2:57:c2:3f:30:8b:fa:e0:3f:84:29: + 63:c9:df:54:73:5f:34:15:9c:ce:e6:d4:d8:64:86:20:50:67: + 4d:d2:e1:ad:cf:65:b9:db:c4:22:e7:c9:35:53:fb:3b:e2:e4: + 32:fe +-----BEGIN CERTIFICATE----- +MIICijCCAfOgAwIBAgIJAPCVUwrHVMvZMA0GCSqGSIb3DQEBBQUAMF4xCzAJBgNV +BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQxFzAVBgNVBAMMDnRlc3Qgcm9vdCBjZXJ0MB4XDTEzMDcy +NzE0MjYyMFoXDTE2MDcyNjE0MjYyMFowXjELMAkGA1UEBhMCQVUxEzARBgNVBAgM +ClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEX +MBUGA1UEAwwOdGVzdCByb290IGNlcnQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ +AoGBAOI8SkSegdOa9PGo91FYs2ewWMrj0BLXDMQ2yw3280Yk0ocxaiVVCCGUOIPr +sbnPkIHQj3f73mYnOm2aDc1dNr+sgZsV3X5xzGx8hkOnRyTy3G2Zyw3LhRFvjCLB +Y9zzZT21NVFeMHgJgCd/ctPqtmTYt5OR9rqkj65pU5SVtS89AgMBAAGjUDBOMB0G +A1UdDgQWBBS36iVO8xMFy39uFL0TvIRo7TWOdDAfBgNVHSMEGDAWgBS36iVO8xMF +y39uFL0TvIRo7TWOdDAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAFYe +gh2arLIosDapWjxcv3Kt807RqEjAWUzPLqGa9M4xflNEE/vuPrz03L2evzU7hNg8 +eeoEZq4L0oQTAwz20Nqa+OHSs3MUxnHkKXe/JPbyV8I/MIv64D+EKWPJ31RzXzQV +nM7m1NhkhiBQZ03S4a3PZbnbxCLnyTVT+zvi5DL+ +-----END CERTIFICATE----- diff --git a/test/ssl/root_ca_private.pem b/test/ssl/root_ca_private.pem new file mode 100644 index 000000000..21c870b7f --- /dev/null +++ b/test/ssl/root_ca_private.pem @@ -0,0 +1,17 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIICxjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQI287GvM3Vm/4CAggA +MBQGCCqGSIb3DQMHBAifwngs3IFCzQSCAoCAYvNd9XQqNeDmKIdFS7o5oYDOPt/c +Ctnwy9UAwqBtv+gsAE+LTYwZrJ8o3/0+pt/ZT05sgsUwyy2wDtuBuCI+7OZObiSr +u9xdWfUUiJCRnGWaZ9bC5NLvPRTRZB2pOuVJJV7/mjVuxSz73FResRzGGLyr/+yD +tGotyRHCdYQOU0o2xWsKSIpcbG31lNhVYf5HCq0Rn1rwmDqwNW1GIO0bvPb6ZagU +qcRbZcvkgYMdS2yr55f9rglDByAZU5S7DrkrK92dUE2sujdyC7Iz20fAQ1UbUuch +fIFtrruvEbbWdqLkByfKlok5ho7tRav8dzbC9sMxBR5o7lP+SCe0t5g29hlQpv6N +mRgWakyOytY3/m94MFuVBcz/P86aY8l8HXBuUBxycDFai/MwYo6o0K2IpSKYZqny +BxT3+yZrsFFi3AIPg4ta3aAYDZCLKdxx5YXiF/ZFLr4s4fyD3AJOeGvDhXrRQaXq +NCPlSnFaMqS4cPbj43McYo9NhUT8OV0h73Zf32/e7MpE412DxTTYdtfZD3vTMRfS +4ZGs1PibHiBA5oPkD9xCiuFEIvwuy28YOZF8wILOSE1iEFFGfTNTCE7fs36ApYus +3JzmB94cWDas4Er3LwZrhv+j3DCuR0Q6iPzN9oNZh8vjpSzMyg2Va5soMTbfvQkC +tDE8l8k8Xu38QLOKpGWXY83eXstNmACv5WGEi4Krgpng6ybFMjEPOZ1bdPbPmBJZ +JENpp6Os2O2XPj+U/iBoYMR/3qFKv1Pd2ZIEwscZBMzXUvj8Wui2UeAsjk1M4bkw +S64cN5CR2sA2waauByMFRfyUPWJIKArEFiW7qFCHRCTusAa5nkrJV/iY +-----END ENCRYPTED PRIVATE KEY----- diff --git a/test/ssl/server.pem b/test/ssl/server.pem new file mode 100644 index 000000000..ecb39bcad --- /dev/null +++ b/test/ssl/server.pem @@ -0,0 +1,35 @@ +-----BEGIN PRIVATE KEY----- +MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANOZn52tnufSaCjj +Y23E0Pe4oKhlUToSL4yAnPj1K4v+9nN/IKJz07XHUZD5+Ypx1QUsq1WlBiyY2+il +ODvrhPN7gORIFn4P1tAQO/FuSBgTwTdbFdELAvJ2GpSwwzid6qBtYl82sVaWoLdV +G+jHItRfHG9J9ELTlsC8pTrMB+/DAgMBAAECgYEAq6kya2nBw1HXvGwUaqXD3WPD +ujlPtyuvtW1Va0cCh/VUnIgiwofy1cKYcmPJRL5qUWNWsAlLw/xSUx9OSpYb6S1v +Ddpk3RLnq4axc4fCuZNQ5xepT1lFJQXyZVS7DsVkfjm7vEYl6sXQTFh/7Sv+vhkn +s0XocET0xY95zR7JnekCQQDyq4HcQg+vhkdStj4fh7fHdkMKA91QHLOVcjTeKeIS +mK1h2BXXaA50RAQdA0e9PFdXR+AHhNq79I1dhJPw4N8FAkEA3zk0BEjDt/zWYrJb +zuC6BVYeULsrxO5331sLNmrO4j6NMSLSTV5gclCr4JANfNhHYdVlNjw9y5l2t9GD +nLP+JwJBANq9IecqXP04qp2xzDmbmlrfDPrAFQObe3zgXytK0Y81tEOYBcgO8ch3 +bsXAKTA4bfosvZHJfWkivTJoyPm9mQkCQChVq8KCa2sZcpuO4uv0y2gfcYbg6z3A +YUSorNP+ZLeY2eZhBmMYhJDjZstC/Ezsv6k75/fu1rOtXThF0WRFWc0CQDeCjzUO +PEnd60cvLNvU8v8fcFZkezNOOqhwDt7qKKpxWw8kuCGZAeiD7qNLDrZBlP00CQ3R +xbS/tkvxXibulgI= +-----END PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIDCDCCAnGgAwIBAgIJAJknelvWNnggMA0GCSqGSIb3DQEBBQUAMIGcMQswCQYD +VQQGEwJBVTEWMBQGA1UECAwNdGVzdCBwcm92aW5jZTESMBAGA1UEBwwJdGVzdCBj +aXR5MREwDwYDVQQKDAh0ZXN0IG9yZzEYMBYGA1UECwwPdGVzdCBkZXBhcnRtZW50 +MRIwEAYDVQQDDAkxMjcuMC4wLjExIDAeBgkqhkiG9w0BCQEWEXRlc3RAdGVzdC5j +b25/bX9tMB4XDTEzMDcyNzE0MTExMVoXDTIzMDcyNTE0MTExMVowgZwxCzAJBgNV +BAYTAkFVMRYwFAYDVQQIDA10ZXN0IHByb3ZpbmNlMRIwEAYDVQQHDAl0ZXN0IGNp +dHkxETAPBgNVBAoMCHRlc3Qgb3JnMRgwFgYDVQQLDA90ZXN0IGRlcGFydG1lbnQx +EjAQBgNVBAMMCTEyNy4wLjAuMTEgMB4GCSqGSIb3DQEJARYRdGVzdEB0ZXN0LmNv +bn9tf20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANOZn52tnufSaCjjY23E +0Pe4oKhlUToSL4yAnPj1K4v+9nN/IKJz07XHUZD5+Ypx1QUsq1WlBiyY2+ilODvr +hPN7gORIFn4P1tAQO/FuSBgTwTdbFdELAvJ2GpSwwzid6qBtYl82sVaWoLdVG+jH +ItRfHG9J9ELTlsC8pTrMB+/DAgMBAAGjUDBOMB0GA1UdDgQWBBT3G2k/6L5UdDpQ +Rj4RR6nUVPVTDDAfBgNVHSMEGDAWgBT3G2k/6L5UdDpQRj4RR6nUVPVTDDAMBgNV +HRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBABHQx77KIJlUnCwg3mwYob3NA+uN +njwlrJjC9ZVVwabJiZvbMPqQVc4CkzN3gvVYpMIMzW28idsy5lH/oduC06dLt06E +TyJvolwSVrLf//zbVwgI8RFBDlgGUNGEZXxBUyEiD/YcEIyC40JadUrwyvLdmezj +itBP2eZmwxC1q8GP +-----END CERTIFICATE----- diff --git a/test/test_ssl.cpp b/test/test_ssl.cpp new file mode 100644 index 000000000..c837cb871 --- /dev/null +++ b/test/test_ssl.cpp @@ -0,0 +1,204 @@ +/* + +Copyright (c) 2013, 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 "libtorrent/session.hpp" +#include "libtorrent/alert_types.hpp" +#include "libtorrent/thread.hpp" +#include "libtorrent/file.hpp" +#include +#include + +#include "test.hpp" +#include "setup_transfer.hpp" +#include +#include + +using namespace libtorrent; +using boost::tuples::ignore; + +int const alert_mask = alert::all_categories +& ~alert::progress_notification +& ~alert::stats_notification; + +struct test_config_t +{ + char const* name; + bool use_ssl_ports; + bool seed_has_cert; + bool downloader_has_cert; + bool expected_to_complete; +}; + +test_config_t test_config[] = +{ + {"nobody has a cert (connect to regular port)", false, false, false, false}, + {"nobody has a cert (connect to ssl port)", true, false, false, false}, + {"seed has a cert, but not downloader (connect to regular port)", false, true, false, false}, + {"seed has a cert, but not downloader (connect to ssl port)", true, true, false, false}, + {"downloader has a cert, but not seed (connect to regular port)", false, false, true, false}, + {"downloader has a cert, but not seed (connect to ssl port)", true, false, true, false}, + {"both downloader and seed has a cert (connect to regular port)", false, true, true, false}, +#ifdef TORRENT_USE_OPENSSL + {"both downloader and seed has a cert (connect to ssl port)", true, true, true, true}, +#else + {"both downloader and seed has a cert (connect to ssl port)", true, true, true, false}, +#endif +}; + +int peer_disconnects = 0; + +bool predicate(alert* a) +{ + if (peer_disconnected_alert* p = alert_cast(a)) + ++peer_disconnects; + return false; +} + +void test_ssl(int test_idx) +{ + test_config_t const& test = test_config[test_idx]; + + fprintf(stderr, "\n%s TEST: %s\n\n", time_now_string(), test.name); + + // in case the previous run was terminated + error_code ec; + remove_all("tmp1_ssl", ec); + remove_all("tmp2_ssl", ec); + + session ses1(fingerprint("LT", 0, 1, 0, 0), std::make_pair(48075, 49000), "0.0.0.0", 0, alert_mask); + session ses2(fingerprint("LT", 0, 1, 0, 0), std::make_pair(49075, 50000), "0.0.0.0", 0, alert_mask); + + session_settings sett; + // this disables outgoing SSL connections + sett.ssl_listen = 0; + if (!test.downloader_has_cert) ses2.set_settings(sett); + + torrent_handle tor1; + torrent_handle tor2; + + create_directory("tmp1_ssl", ec); + std::ofstream file("tmp1_ssl/temporary"); + boost::intrusive_ptr t = ::create_torrent(&file, 16 * 1024, 13, false, "ssl/root_ca_cert.pem"); + file.close(); + + add_torrent_params addp; + addp.flags &= ~add_torrent_params::flag_paused; + addp.flags &= ~add_torrent_params::flag_auto_managed; + + wait_for_listen(ses1, "ses1"); + wait_for_listen(ses2, "ses1"); + + peer_disconnects = 0; + + boost::tie(tor1, tor2, ignore) = setup_transfer(&ses1, &ses2, 0 + , true, false, true, "_ssl", 16 * 1024, &t, false, NULL, true, test.use_ssl_ports); + + if (test.seed_has_cert) + { + tor1.set_ssl_certificate(combine_path("ssl", "peer_certificate.pem") + , combine_path("ssl", "peer_private_key.pem") + , combine_path("ssl", "dhparams.pem") + , "test"); + } + + if (test.downloader_has_cert) + { + tor2.set_ssl_certificate(combine_path("ssl", "peer_certificate.pem") + , combine_path("ssl", "peer_private_key.pem") + , combine_path("ssl", "dhparams.pem") + , "test"); + } + + for (int i = 0; i < 15; ++i) + { + print_alerts(ses1, "ses1", true, true, true, &predicate); + print_alerts(ses2, "ses2", true, true, true, &predicate); + + torrent_status st1 = tor1.status(); + torrent_status st2 = tor2.status(); + + if (i % 10 == 0) + { + std::cerr << time_now_string() << " " + << "\033[32m" << int(st1.download_payload_rate / 1000.f) << "kB/s " + << "\033[33m" << int(st1.upload_payload_rate / 1000.f) << "kB/s " + << "\033[0m" << int(st1.progress * 100) << "% " + << st1.num_peers + << ": " + << "\033[32m" << int(st2.download_payload_rate / 1000.f) << "kB/s " + << "\033[31m" << int(st2.upload_payload_rate / 1000.f) << "kB/s " + << "\033[0m" << int(st2.progress * 100) << "% " + << st2.num_peers + << " cc: " << st2.connect_candidates + << std::endl; + } + + if (peer_disconnects == 2) break; + + if (st2.is_finished) break; + + if (st2.state != torrent_status::downloading) + { + static char const* state_str[] = + {"checking (q)", "checking", "dl metadata" + , "downloading", "finished", "seeding", "allocating", "checking (r)"}; + std::cerr << "st2 state: " << state_str[st2.state] << std::endl; + } + + TEST_CHECK(st1.state == torrent_status::seeding + || st1.state == torrent_status::checking_files); + TEST_CHECK(st2.state == torrent_status::downloading); + + test_sleep(100); + } + + TEST_CHECK(tor2.status().is_seeding == test.expected_to_complete); +} + +int test_main() +{ + using namespace libtorrent; + + test_ssl(7); + +// for (int i = 0; i < sizeof(test_config)/sizeof(test_config[0]); ++i) +// test_ssl(i); + + error_code ec; + remove_all("tmp1_ssl", ec); + remove_all("tmp2_ssl", ec); + + return 0; +} + + + diff --git a/test/test_transfer.cpp b/test/test_transfer.cpp index 3ae4e84fc..3bceb8a02 100644 --- a/test/test_transfer.cpp +++ b/test/test_transfer.cpp @@ -53,6 +53,15 @@ int const alert_mask = alert::all_categories & ~alert::progress_notification & ~alert::stats_notification; +int peer_disconnects = 0; + +bool predicate(alert* a) +{ + if (peer_disconnected_alert* p = alert_cast(a)) + ++peer_disconnects; + return false; +} + // test the maximum transfer rate void test_rate() { @@ -77,15 +86,17 @@ void test_rate() wait_for_listen(ses1, "ses1"); wait_for_listen(ses2, "ses1"); + peer_disconnects = 0; + boost::tie(tor1, tor2, ignore) = setup_transfer(&ses1, &ses2, 0 , true, false, true, "_transfer", 0, &t); ptime start = time_now(); - for (int i = 0; i < 70; ++i) + for (int i = 0; i < 50; ++i) { - print_alerts(ses1, "ses1"); - print_alerts(ses2, "ses2"); + print_alerts(ses1, "ses1", true, true, true, &predicate); + print_alerts(ses2, "ses2", true, true, true, &predicate); torrent_status st1 = tor1.status(); torrent_status st2 = tor2.status(); @@ -93,6 +104,7 @@ void test_rate() if (i % 10 == 0) print_ses_rate(i / 10.f, &st1, &st2); + if (peer_disconnects == 2) break; if (st2.is_seeding) break; test_sleep(100); } @@ -221,6 +233,10 @@ bool on_alert(alert* a) { if (alert_cast(a)) ++tracker_responses; + + if (alert_cast(a)) + ++peer_disconnects; + return false; } @@ -326,6 +342,8 @@ void test_transfer(int proxy_type, bool test_disk_full = false, bool test_allowe wait_for_listen(ses1, "ses1"); wait_for_listen(ses2, "ses1"); + peer_disconnects = 0; + // test using piece sizes smaller than 16kB boost::tie(tor1, tor2, ignore) = setup_transfer(&ses1, &ses2, 0 , true, false, true, "_transfer", 8 * 1024, &t, false, test_disk_full?&addp:0); @@ -398,6 +416,8 @@ void test_transfer(int proxy_type, bool test_disk_full = false, bool test_allowe TEST_CHECK(st2.state == torrent_status::downloading || (test_disk_full && !st2.error.empty())); + if (peer_disconnects == 2) break; + test_sleep(100); } @@ -416,10 +436,13 @@ void test_transfer(int proxy_type, bool test_disk_full = false, bool test_allowe std::cerr << "force recheck" << std::endl; tor2.force_recheck(); + peer_disconnects = 0; + for (int i = 0; i < 50; ++i) { test_sleep(100); - print_alerts(ses2, "ses2"); + print_alerts(ses2, "ses2", true, true, true, on_alert); + torrent_status st2 = tor2.status(); if (i % 10 == 0) { @@ -433,7 +456,7 @@ void test_transfer(int proxy_type, bool test_disk_full = false, bool test_allowe for (int i = 0; i < 5; ++i) { - print_alerts(ses2, "ses2"); + print_alerts(ses2, "ses2", true, true, true, on_alert); torrent_status st2 = tor2.status(); TEST_CHECK(st2.state == torrent_status::finished); test_sleep(100); @@ -509,8 +532,8 @@ void test_transfer(int proxy_type, bool test_disk_full = false, bool test_allowe for (int i = 0; i < 5; ++i) { - print_alerts(ses1, "ses1"); - print_alerts(ses2, "ses2"); + print_alerts(ses1, "ses1", true, true, true, on_alert); + print_alerts(ses2, "ses2", true, true, true, on_alert); torrent_status st1 = tor1.status(); torrent_status st2 = tor2.status(); @@ -529,8 +552,8 @@ void test_transfer(int proxy_type, bool test_disk_full = false, bool test_allowe for (int i = 0; i < 130; ++i) { - print_alerts(ses1, "ses1"); - print_alerts(ses2, "ses2"); + print_alerts(ses1, "ses1", true, true, true, on_alert); + print_alerts(ses2, "ses2", true, true, true, on_alert); torrent_status st1 = tor1.status(); torrent_status st2 = tor2.status();