From 6d77000ab02255a2c57e43ccea6d6478df742fef Mon Sep 17 00:00:00 2001 From: arvidn Date: Mon, 8 Feb 2016 02:01:25 -0500 Subject: [PATCH] deprecate ssl_listen setting. instead ssl sockets are specified by an 's' suffix of the port in listen_interfaces. --- include/libtorrent/aux_/session_impl.hpp | 23 +- include/libtorrent/aux_/session_interface.hpp | 1 + include/libtorrent/settings_pack.hpp | 42 ++- include/libtorrent/string_util.hpp | 14 +- src/session_impl.cpp | 273 ++++++++++-------- src/settings_pack.cpp | 2 +- src/string_util.cpp | 43 ++- src/torrent.cpp | 3 + test/test_ssl.cpp | 48 +-- test/test_string.cpp | 42 ++- 10 files changed, 306 insertions(+), 185 deletions(-) diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp index d05db0118..263cbd9d4 100644 --- a/include/libtorrent/aux_/session_impl.hpp +++ b/include/libtorrent/aux_/session_impl.hpp @@ -628,6 +628,11 @@ namespace libtorrent libtorrent::utp_socket_manager* utp_socket_manager() TORRENT_OVERRIDE { return &m_utp_socket_manager; } +#ifdef TORRENT_USE_OPENSSL + libtorrent::utp_socket_manager* ssl_utp_socket_manager() TORRENT_OVERRIDE + { return &m_ssl_utp_socket_manager; } +#endif + void inc_boost_connections() TORRENT_OVERRIDE { ++m_boost_connections; } #ifndef TORRENT_NO_DEPRECATE @@ -637,6 +642,13 @@ namespace libtorrent // update any rss feeds that need updating and // recalculate m_next_rss_update void update_rss_feeds(); + + void update_ssl_listen(); + void update_dht_upload_rate_limit(); + void update_local_download_rate(); + void update_local_upload_rate(); + void update_rate_limit_utp(); + void update_ignore_rate_limits_on_local_network(); #endif void update_proxy(); @@ -647,9 +659,6 @@ namespace libtorrent void update_connection_speed(); void update_queued_disk_bytes(); void update_alert_queue_size(); -#ifndef TORRENT_NO_DEPRECATE - void update_dht_upload_rate_limit(); -#endif void update_disk_threads(); void update_network_threads(); void update_cache_buffer_chunk_size(); @@ -674,12 +683,6 @@ namespace libtorrent void update_download_rate(); void update_upload_rate(); void update_connections_limit(); -#ifndef TORRENT_NO_DEPRECATE - void update_local_download_rate(); - void update_local_upload_rate(); - void update_rate_limit_utp(); - void update_ignore_rate_limits_on_local_network(); -#endif void update_alert_mask(); void trigger_auto_manage() TORRENT_OVERRIDE; @@ -847,7 +850,7 @@ namespace libtorrent // the addresses or device names of the interfaces we are supposed to // listen on. if empty, it means that we should let the os decide // which interface to listen on - std::vector > m_listen_interfaces; + std::vector m_listen_interfaces; // the network interfaces outgoing connections are opened through. If // there is more then one, they are used in a round-robin fashion diff --git a/include/libtorrent/aux_/session_interface.hpp b/include/libtorrent/aux_/session_interface.hpp index 480d51e64..0d746656c 100644 --- a/include/libtorrent/aux_/session_interface.hpp +++ b/include/libtorrent/aux_/session_interface.hpp @@ -319,6 +319,7 @@ namespace libtorrent { namespace aux virtual std::vector& block_info_storage() = 0; #ifdef TORRENT_USE_OPENSSL + virtual libtorrent::utp_socket_manager* ssl_utp_socket_manager() = 0; virtual boost::asio::ssl::context* ssl_ctx() = 0 ; #endif diff --git a/include/libtorrent/settings_pack.hpp b/include/libtorrent/settings_pack.hpp index 32374ebc0..c2fdd0309 100644 --- a/include/libtorrent/settings_pack.hpp +++ b/include/libtorrent/settings_pack.hpp @@ -163,20 +163,29 @@ namespace libtorrent // connections. outgoing_interfaces, - // a comma-separated list of IP port-pairs. These - // are the listen ports that will be opened for accepting incoming uTP - // and TCP connections. It is possible to listen on multiple - // IPs and multiple ports. Binding to port 0 will make the - // operating system pick the port. The default is "0.0.0.0:6881", which - // binds to all interfaces on port 6881. - // - // if binding fails, the listen_failed_alert is posted, potentially - // more than once. Once/if binding the listen socket(s) succeed, - // listen_succeeded_alert is posted. - // - // Each port will attempt to open both a UDP and a TCP listen socket, - // to allow accepting uTP connections as well as TCP. If using the DHT, - // this will also make the DHT use the same UDP ports. + // a comma-separated list of (IP or device name, port) pairs. These are + // the listen ports that will be opened for accepting incoming uTP and + // TCP connections. It is possible to listen on multiple interfaces and + // multiple ports. Binding to port 0 will make the operating system + // pick the port. The default is "0.0.0.0:6881,[::]:6881", which binds + // to all interfaces on port 6881. + // + // a port that has an "s" suffix will accept SSL connections. (note + // that SSL sockets are not enabled by default). + // + // if binding fails, the listen_failed_alert is posted. If or once a + // socket binding succeeds, the listen_succeeded_alert is posted. There + // may be multiple failures before a success. + // + // For example: + // ``[::1]:8888`` - will only accept connections on the IPv6 loopback + // address on port 8888. + // + // ``eth0:4444,eth1:4444`` - will accept connections on port 4444 on + // any IP address bound to device ``eth0`` or ``eth1``. + // + // ``[::]:0s`` - will accept SSL connections on a port chosen by the + // OS. And not accept non-SSL connections at all. // // .. note:: // The current support for opening arbitrary UDP sockets is limited. @@ -1418,12 +1427,17 @@ namespace libtorrent // SSL encryption as well. network_threads, +#ifndef TORRENT_NO_DEPRECATE // ``ssl_listen`` sets the listen port for SSL connections. If this is // set to 0, no SSL listen port is opened. Otherwise a socket is // opened on this port. This setting is only taken into account when // opening the regular listen port, and won't re-open the listen // socket simply by changing this setting. ssl_listen, +#else + // hidden + deprecated9, +#endif // ``tracker_backoff`` determines how aggressively to back off from // retrying failing trackers. This value determines *x* in the diff --git a/include/libtorrent/string_util.hpp b/include/libtorrent/string_util.hpp index e8d90d427..a2fd24b16 100644 --- a/include/libtorrent/string_util.hpp +++ b/include/libtorrent/string_util.hpp @@ -67,11 +67,21 @@ namespace libtorrent TORRENT_EXTRA_EXPORT void url_random(char* begin, char* end); + struct listen_interface_t + { + std::string device; + int port; + bool ssl; + }; + // this parses the string that's used as the liste_interfaces setting. // it is a comma-separated list of IP or device names with ports. For // example: "eth0:6881,eth1:6881" or "127.0.0.1:6881" - TORRENT_EXTRA_EXPORT void parse_comma_separated_string_port( - std::string const& in, std::vector >& out); + TORRENT_EXTRA_EXPORT void parse_listen_interfaces( + std::string const& in, std::vector& out); + + TORRENT_EXTRA_EXPORT std::string print_listen_interfaces( + std::vector const& in); // this parses the string that's used as the outgoing_interfaces setting. // it is a comma separated list of IPs and device names. For example: diff --git a/src/session_impl.cpp b/src/session_impl.cpp index da4f388c0..07fc7de7d 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -1256,6 +1256,9 @@ namespace aux { #ifdef TORRENT_USE_OPENSSL // SSL torrents use the SSL listen port + // TODO: 2 this need to be more thought through. There isn't necessarily + // just _one_ SSL listen port, which one we use depends on which interface + // we announce from. if (req.ssl_ctx) req.listen_port = ssl_listen_port(); req.ssl_ctx = &m_ssl_ctx; #endif @@ -1584,10 +1587,13 @@ namespace aux { void session_impl::apply_settings_pack_impl(settings_pack const& pack) { bool reopen_listen_port = +#ifndef TORRENT_NO_DEPRECATE (pack.has_val(settings_pack::ssl_listen) && pack.get_int(settings_pack::ssl_listen) != m_settings.get_int(settings_pack::ssl_listen)) - || (pack.has_val(settings_pack::listen_interfaces) + || +#endif + (pack.has_val(settings_pack::listen_interfaces) && pack.get_str(settings_pack::listen_interfaces) != m_settings.get_str(settings_pack::listen_interfaces)); @@ -1661,7 +1667,7 @@ namespace aux { ? listen_failed_alert::tcp_ssl : listen_failed_alert::tcp; ret.sock.reset(new tcp::acceptor(m_io_service)); - ret.sock->open(bind_ep.address().is_v4() ? tcp::v4() : tcp::v6(), ec); + ret.sock->open(bind_ep.protocol(), ec); last_op = listen_failed_alert::open; if (ec) { @@ -1779,6 +1785,7 @@ namespace aux { m_alerts.emplace_alert(device, bind_ep , last_op, ec, sock_type); } + ret.sock.reset(); return ret; } ret.local_endpoint = ret.sock->local_endpoint(ec); @@ -1855,44 +1862,27 @@ namespace aux { for (int i = 0; i < m_listen_interfaces.size(); ++i) { - std::string const& device = m_listen_interfaces[i].first; - int const port = m_listen_interfaces[i].second; + std::string const& device = m_listen_interfaces[i].device; + int const port = m_listen_interfaces[i].port; + bool const ssl = m_listen_interfaces[i].ssl; // now we have a device to bind to. This device may actually just be an // IP address or a device name. In case it's a device name, we want to // (potentially) end up binding a socket for each IP address associated // with that device. - + // First, check to see if it's an IP address error_code err; address adr = address::from_string(device.c_str(), err); if (!err) { listen_socket_t s = setup_listener(device, tcp::endpoint(adr, port) - , flags, ec); + , flags | (ssl ? open_ssl_socket : 0), ec); if (!ec && s.sock) { - TORRENT_ASSERT(!m_abort); m_listen_sockets.push_back(s); } - -#ifdef TORRENT_USE_OPENSSL - // TODO: 3 it would probably be better to specify if we want an SSL - // port open as another entry in the listen_interfaces (like in - // mongoose) - if (m_settings.get_int(settings_pack::ssl_listen)) - { - listen_socket_t s = setup_listener(device - , tcp::endpoint(adr, m_settings.get_int(settings_pack::ssl_listen)) - , flags | open_ssl_socket, ec); - - if (!ec && s.sock) - { - m_listen_sockets.push_back(s); - } - } -#endif // TORRENT_USE_OPENSSL } else { @@ -1923,36 +1913,13 @@ namespace aux { if (device != ifs[k].name) continue; listen_socket_t s = setup_listener(device - , tcp::endpoint(ifs[k].interface_address, port), flags, ec); + , tcp::endpoint(ifs[k].interface_address, port) + , flags | (ssl ? open_ssl_socket : 0), ec); if (!ec && s.sock) { - // update the listen_interface member with the - // actual port we ended up listening on, so that the other - // sockets can be bound to the same one - m_listen_interface.port(s.external_port); - - TORRENT_ASSERT(!m_abort); m_listen_sockets.push_back(s); } - -#ifdef TORRENT_USE_OPENSSL - // TODO: 3 it would probably be better to specify if we want an SSL - // port open as another entry in the listen_interfaces (like in - // mongoose) - if (m_settings.get_int(settings_pack::ssl_listen)) - { - int const ssl_port = m_settings.get_int(settings_pack::ssl_listen); - listen_socket_t s = setup_listener(device - , tcp::endpoint(ifs[k].interface_address, port) - , flags | open_ssl_socket, ec); - - if (!ec && s.sock) - { - m_listen_sockets.push_back(s); - } - } -#endif // TORRENT_USE_OPENSSL } } } @@ -1965,80 +1932,99 @@ namespace aux { return; } - // TODO: 3 the udp socket(s) should be using the same generic - // mechanism and not be restricted to a single one - // we should open a one listen socket for each entry in the - // listen_interfaces list - // for now, remember the first successful port, and bind the UDP socket to - // that as well - udp::endpoint udp_bind_ep(m_listen_sockets.begin()->local_endpoint.address() - , m_listen_sockets.begin()->local_endpoint.port()); - int retries = m_settings.get_int(settings_pack::max_retry_port_bind); + // TODO: 3 this loop should be entirely merged with the one above and the + // udp sockets should be opened in parallel with the TCP ones, being held + // by listen_socket_t. + // until the UDP sockets fully honor the listen_interfaces setting, just + // create the two sockets based on the first matching (ssl vs. non-ssl) + // TCP socket +#ifdef TORRENT_USE_OPENSSL + bool created_ssl_udp_socket = false; +#endif + bool created_udp_socket = false; + for (std::list::const_iterator i = m_listen_sockets.begin() + , end(m_listen_sockets.end()); i != end; ++i) + { + listen_socket_t const& s = *i; #ifdef TORRENT_USE_OPENSSL - // TODO: 3 remove ssl_listen setting. Instead, specify the port in the - // listen_interfaces to have an "s" suffix. Just like mongoose - int const ssl_port = m_settings.get_int(settings_pack::ssl_listen); - - // if ssl port is 0, we don't want to listen on an SSL port - if (ssl_port != 0) - { - udp::endpoint ssl_bind_ep(udp_bind_ep.address(), ssl_port); - do + if (!created_ssl_udp_socket && s.ssl) { - ec.clear(); - m_ssl_udp_socket.bind(ssl_bind_ep, ec); - if (ec) + int retries = m_settings.get_int(settings_pack::max_retry_port_bind); + udp::endpoint bind_ep(s.local_endpoint.address(), s.local_endpoint.port()); + do { -#ifndef TORRENT_DISABLE_LOGGING - session_log("SSL: cannot bind to UDP interface \"%s\": %s" - , print_endpoint(ssl_bind_ep).c_str(), ec.message().c_str()); -#endif - if (m_alerts.should_post()) + ec.clear(); + m_ssl_udp_socket.bind(bind_ep, ec); + if (ec) { - error_code err; - m_alerts.emplace_alert(ssl_bind_ep.address().to_string(err) - , tcp::endpoint(ssl_bind_ep.address(), ssl_bind_ep.port()) - , listen_failed_alert::bind, ec, listen_failed_alert::utp_ssl); +#ifndef TORRENT_DISABLE_LOGGING + session_log("SSL: cannot bind to UDP interface \"%s\": %s" + , print_endpoint(bind_ep).c_str(), ec.message().c_str()); +#endif + if (m_alerts.should_post()) + { + error_code err; + m_alerts.emplace_alert(bind_ep.address().to_string(err) + , tcp::endpoint(bind_ep.address(), bind_ep.port()) + , listen_failed_alert::bind, ec, listen_failed_alert::utp_ssl); + } + --retries; + bind_ep.port(bind_ep.port() + 1); } - --retries; - ssl_bind_ep.port(ssl_bind_ep.port() + 1); - } - // TODO: 3 port map SSL udp socket here - } while (ec == error_code(error::address_in_use) && retries > 0); - } - - retries = m_settings.get_int(settings_pack::max_retry_port_bind); + else + { + created_ssl_udp_socket = true; + // TODO: 3 port map SSL udp socket here + } + } while (ec == error_code(error::address_in_use) && retries > 0); + } #endif // TORRENT_USE_OPENSSL - do - { - ec.clear(); - m_udp_socket.bind(udp_bind_ep, ec); - if (ec) + if (!created_udp_socket && !s.ssl) { -#ifndef TORRENT_DISABLE_LOGGING - session_log("cannot bind to UDP interface \"%s\": %s" - , print_endpoint(udp_bind_ep).c_str(), ec.message().c_str()); -#endif - if (m_alerts.should_post()) + int retries = m_settings.get_int(settings_pack::max_retry_port_bind); + udp::endpoint bind_ep(s.local_endpoint.address(), s.local_endpoint.port()); + do { - error_code err; - m_alerts.emplace_alert(udp_bind_ep.address().to_string(err) - , tcp::endpoint(udp_bind_ep.address(), udp_bind_ep.port()) - , listen_failed_alert::bind - , ec, listen_failed_alert::udp); - } - --retries; - udp_bind_ep.port(udp_bind_ep.port() + 1); + ec.clear(); + m_udp_socket.bind(bind_ep, ec); + if (ec) + { +#ifndef TORRENT_DISABLE_LOGGING + session_log("cannot bind to UDP interface \"%s\": %s" + , print_endpoint(bind_ep).c_str(), ec.message().c_str()); +#endif + if (m_alerts.should_post()) + { + error_code err; + m_alerts.emplace_alert(bind_ep.address().to_string(err) + , tcp::endpoint(bind_ep.address(), bind_ep.port()) + , listen_failed_alert::bind + , ec, listen_failed_alert::udp); + } + --retries; + bind_ep.port(bind_ep.port() + 1); + } + else + { + created_udp_socket = true; + m_external_udp_port = m_udp_socket.local_port(); + maybe_update_udp_mapping(0, bind_ep.port(), bind_ep.port()); + maybe_update_udp_mapping(1, bind_ep.port(), bind_ep.port()); + } + } while (ec == error_code(error::address_in_use) && retries > 0); } - else - { - m_external_udp_port = m_udp_socket.local_port(); - maybe_update_udp_mapping(0, udp_bind_ep.port(), udp_bind_ep.port()); - maybe_update_udp_mapping(1, udp_bind_ep.port(), udp_bind_ep.port()); - } - } while (ec == error_code(error::address_in_use) && retries > 0); + } + + // if we did not end up opening a udp socket, make sure we close any + // previous one +#ifdef TORRENT_USE_OPENSSL + if (!created_ssl_udp_socket) + m_ssl_udp_socket.close(); +#endif + if (!created_udp_socket) + m_udp_socket.close(); // we made it! now post all the listen_succeeded_alerts @@ -2061,18 +2047,20 @@ namespace aux { #ifdef TORRENT_USE_OPENSSL if (m_ssl_udp_socket.is_open()) { + error_code err; if (m_alerts.should_post()) m_alerts.emplace_alert( - tcp::endpoint(ssl_bind_ep.address(), ssl_bind_ep.port()) + m_ssl_udp_socket.local_endpoint(err) , listen_succeeded_alert::utp_ssl); } #endif if (m_udp_socket.is_open()) { + error_code err; if (m_alerts.should_post()) m_alerts.emplace_alert( - tcp::endpoint(udp_bind_ep.address(), udp_bind_ep.port()) + m_udp_socket.local_endpoint(err) , listen_succeeded_alert::udp); } @@ -5078,15 +5066,62 @@ namespace aux { TORRENT_ASSERT(m_torrents.find(i_hash) == m_torrents.end()); } +#ifndef TORRENT_NO_DEPRECATE + namespace + { + listen_interface_t set_ssl_flag(listen_interface_t in) + { + in.ssl = true; + return in; + } + } + + void session_impl::update_ssl_listen() + { + INVARIANT_CHECK; + + // this function maps the previous functionality of just setting the ssl + // listen port in order to enable the ssl listen sockets, to the new + // mechanism where SSL sockets are specified in listen_interfaces. + std::vector current_ifaces; + parse_listen_interfaces(m_settings.get_str(settings_pack::listen_interfaces) + , current_ifaces); + // these are the current interfaces we have, first remove all the SSL + // interfaces + current_ifaces.erase(std::remove_if(current_ifaces.begin(), current_ifaces.end() + , boost::bind(&listen_interface_t::ssl, _1)), current_ifaces.end()); + + int const ssl_listen_port = m_settings.get_int(settings_pack::ssl_listen); + + // setting a port of 0 means to disable listening on SSL, so just update + // the interface list with the new list, and we're done + if (ssl_listen_port == 0) + { + m_settings.set_str(settings_pack::listen_interfaces + , print_listen_interfaces(current_ifaces)); + return; + } + + std::vector new_ifaces; + std::transform(current_ifaces.begin(), current_ifaces.end() + , std::back_inserter(new_ifaces), &set_ssl_flag); + + current_ifaces.insert(current_ifaces.end(), new_ifaces.begin(), new_ifaces.end()); + + m_settings.set_str(settings_pack::listen_interfaces + , print_listen_interfaces(current_ifaces)); + } +#endif // TORRENT_NO_DEPRECATE + void session_impl::update_listen_interfaces() { INVARIANT_CHECK; std::string net_interfaces = m_settings.get_str(settings_pack::listen_interfaces); - std::vector > new_listen_interfaces; + std::vector new_listen_interfaces; // declared in string_util.hpp - parse_comma_separated_string_port(net_interfaces, new_listen_interfaces); + parse_listen_interfaces(net_interfaces, new_listen_interfaces); #ifndef TORRENT_DISABLE_LOGGING session_log("update listen interfaces: %s", net_interfaces.c_str()); @@ -5225,6 +5260,8 @@ namespace aux { return m_listen_sockets.front().tcp_external_port; } + // TODO: 2 this function should be removed and users need to deal with the + // more generic case of having multiple ssl ports boost::uint16_t session_impl::ssl_listen_port() const { #ifdef TORRENT_USE_OPENSSL @@ -6500,7 +6537,7 @@ namespace aux { } } #ifdef TORRENT_USE_OPENSSL - if (m_ssl_udp_socket.is_open() && ssl_port > 0) + if (m_ssl_udp_socket.is_open()) { error_code ec; tcp::endpoint ep = m_ssl_udp_socket.local_endpoint(ec); @@ -6551,7 +6588,7 @@ namespace aux { } } #ifdef TORRENT_USE_OPENSSL - if (m_ssl_udp_socket.is_open() && ssl_port > 0) + if (m_ssl_udp_socket.is_open()) { error_code ec; tcp::endpoint ep = m_ssl_udp_socket.local_endpoint(ec); diff --git a/src/settings_pack.cpp b/src/settings_pack.cpp index 7d5145f55..ee640418a 100644 --- a/src/settings_pack.cpp +++ b/src/settings_pack.cpp @@ -330,7 +330,7 @@ namespace libtorrent SET(aio_threads, 4, &session_impl::update_disk_threads), SET(aio_max, 300, 0), SET(network_threads, 0, &session_impl::update_network_threads), - SET(ssl_listen, 4433, 0), + DEPRECATED_SET(ssl_listen, 4433, &session_impl::update_ssl_listen), SET(tracker_backoff, 250, 0), SET_NOPREV(share_ratio_limit, 200, 0), SET_NOPREV(seed_time_ratio_limit, 700, 0), diff --git a/src/string_util.cpp b/src/string_util.cpp index 2bea4ff41..15df6e554 100644 --- a/src/string_util.cpp +++ b/src/string_util.cpp @@ -35,6 +35,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/random.hpp" #include "libtorrent/error_code.hpp" #include "libtorrent/parse_url.hpp" +#include "libtorrent/address.hpp" #include "libtorrent/aux_/disable_warnings_push.hpp" @@ -168,11 +169,40 @@ namespace libtorrent return static_cast(p) + (8 - offset); } + std::string print_listen_interfaces(std::vector const& in) + { + std::string ret; + for (std::vector::const_iterator i = in.begin() + , end(in.end()); i != end; ++i) + { + if (i != in.begin()) ret += ","; + + error_code ec; + address_v6::from_string(i->device, ec); + if (!ec) + { + // IPv6 addresses must be wrapped in square brackets + ret += "["; + ret += i->device; + ret += "]"; + } + else + { + ret += i->device; + } + ret += ":"; + ret += to_string(i->port).elems; + if (i->ssl) ret += "s"; + } + + return ret; + } + // this parses the string that's used as the liste_interfaces setting. // it is a comma-separated list of IP or device names with ports. For // example: "eth0:6881,eth1:6881" or "127.0.0.1:6881" - void parse_comma_separated_string_port(std::string const& in - , std::vector >& out) + void parse_listen_interfaces(std::string const& in + , std::vector& out) { out.clear(); @@ -193,7 +223,11 @@ namespace libtorrent if (colon != std::string::npos && colon > start) { - int port = atoi(in.substr(colon + 1, end - colon - 1).c_str()); + listen_interface_t iface; + + std::string port_string = in.substr(colon + 1, end - colon - 1); + iface.ssl = !port_string.empty() && port_string[port_string.size()-1] == 's'; + iface.port = atoi(port_string.c_str()); // skip trailing spaces std::string::size_type soft_end = colon; @@ -206,7 +240,8 @@ namespace libtorrent if (in[start] == '[') ++start; if (soft_end > start && in[soft_end-1] == ']') --soft_end; - out.push_back(std::make_pair(in.substr(start, soft_end - start), port)); + iface.device = in.substr(start, soft_end - start); + out.push_back(iface); } start = end + 1; diff --git a/src/torrent.cpp b/src/torrent.cpp index 81115d2ac..e666f8dcf 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -7629,6 +7629,9 @@ namespace libtorrent if (is_ssl_torrent() && settings().get_int(settings_pack::ssl_listen) != 0) { userdata = m_ssl_ctx.get(); + // if we're creating a uTP socket, since this is SSL now, make sure + // to pass in the corresponding utp socket manager + if (sm) sm = m_ses.ssl_utp_socket_manager(); } #endif diff --git a/test/test_ssl.cpp b/test/test_ssl.cpp index 83073433d..4c3f13d06 100644 --- a/test/test_ssl.cpp +++ b/test/test_ssl.cpp @@ -100,8 +100,11 @@ bool on_alert(alert const* a) if (peer_disconnected_alert const* e = alert_cast(a)) { ++peer_disconnects; - if (e->error.category() == boost::asio::error::get_ssl_category()) + if (strcmp(e->error.category().name(), boost::asio::error::get_ssl_category().name()) == 0) ++ssl_peer_disconnects; + + fprintf(stderr, "--- peer_errors: %d ssl_disconnects: %d\n" + , peer_errors, ssl_peer_disconnects); } if (peer_error_alert const* e = alert_cast(a)) @@ -109,8 +112,11 @@ bool on_alert(alert const* a) ++peer_disconnects; ++peer_errors; - if (e->error.category() == boost::asio::error::get_ssl_category()) + if (strcmp(e->error.category().name(), boost::asio::error::get_ssl_category().name()) == 0) ++ssl_peer_disconnects; + + fprintf(stderr, "--- peer_errors: %d ssl_disconnects: %d\n" + , peer_errors, ssl_peer_disconnects); } return false; } @@ -132,11 +138,14 @@ void test_ssl(int test_idx, bool use_utp) remove_all("tmp1_ssl", ec); remove_all("tmp2_ssl", ec); - int ssl_port = 1024 + rand() % 50000; + int port = 1024 + rand() % 50000; settings_pack sett; sett.set_int(settings_pack::alert_mask, alert_mask); sett.set_int(settings_pack::max_retry_port_bind, 100); - sett.set_str(settings_pack::listen_interfaces, "0.0.0.0:48075"); + + char listen_iface[100]; + snprintf(listen_iface, sizeof(listen_iface), "0.0.0.0:%ds", port); + sett.set_str(settings_pack::listen_interfaces, listen_iface); sett.set_bool(settings_pack::enable_incoming_utp, use_utp); sett.set_bool(settings_pack::enable_outgoing_utp, use_utp); sett.set_bool(settings_pack::enable_incoming_tcp, !use_utp); @@ -147,14 +156,19 @@ void test_ssl(int test_idx, bool use_utp) sett.set_bool(settings_pack::enable_natpmp, false); // if a peer fails once, don't try it again sett.set_int(settings_pack::max_failcount, 1); - sett.set_int(settings_pack::ssl_listen, ssl_port); libtorrent::session ses1(sett, 0); + // this +20 is here to use a different port as ses1 + port += 20; + + // the +20 below is the port we use for non-SSL connections if (test.downloader_has_ssl_listen_port) - sett.set_int(settings_pack::ssl_listen, ssl_port + 20); + snprintf(listen_iface, sizeof(listen_iface), "0.0.0.0:%d,0.0.0.0:%ds", port + 20, port); else - sett.set_int(settings_pack::ssl_listen, 0); + snprintf(listen_iface, sizeof(listen_iface), "0.0.0.0:%d", port + 20); + + sett.set_str(settings_pack::listen_interfaces, listen_iface); libtorrent::session ses2(sett, 0); @@ -213,15 +227,7 @@ void test_ssl(int test_idx, bool use_utp) wait_for_downloading(ses2, "ses2"); // connect the peers after setting the certificates - int port = 0; - if (test.use_ssl_ports) - if (test.downloader_has_ssl_listen_port) - port = ses2.ssl_listen_port(); - else - port = 13512; - else - port = ses2.listen_port(); - + if (test.use_ssl_ports == false) port += 20; fprintf(stderr, "\n\n%s: ses1: connecting peer port: %d\n\n\n" , time_now_string(), port); tor1.connect_peer(tcp::endpoint(address::from_string("127.0.0.1", ec) @@ -541,12 +547,14 @@ void test_malicious_peer() remove_all("tmp3_ssl", ec); // set up session - int ssl_port = 1024 + rand() % 50000; + int port = 1024 + rand() % 50000; settings_pack sett; sett.set_int(settings_pack::alert_mask, alert_mask); sett.set_int(settings_pack::max_retry_port_bind, 100); - sett.set_str(settings_pack::listen_interfaces, "0.0.0.0:48075"); - sett.set_int(settings_pack::ssl_listen, ssl_port); + + char listen_iface[100]; + snprintf(listen_iface, sizeof(listen_iface), "0.0.0.0:%ds", port); + sett.set_str(settings_pack::listen_interfaces, listen_iface); sett.set_bool(settings_pack::enable_dht, false); sett.set_bool(settings_pack::enable_lsd, false); sett.set_bool(settings_pack::enable_upnp, false); @@ -588,7 +596,7 @@ void test_malicious_peer() for (int i = 0; i < num_attacks; ++i) { - bool success = try_connect(ses1, ssl_port, t, attacks[i].flags); + bool const success = try_connect(ses1, port, t, attacks[i].flags); TEST_EQUAL(success, attacks[i].expect); } } diff --git a/test/test_string.cpp b/test/test_string.cpp index 6c74457dd..5795158f0 100644 --- a/test/test_string.cpp +++ b/test/test_string.cpp @@ -257,24 +257,34 @@ TORRENT_TEST(string) TEST_EQUAL(list[5], "foobar"); TEST_EQUAL(list[6], "[::1]"); - std::vector > list2; - parse_comma_separated_string_port(" a:4,b:35, c : 1000, d: 351 ,e \t:42,foobar:1337\n\r,[2001::1]:6881", list2); + std::vector list2; + parse_listen_interfaces(" a:4,b:35, c : 1000s, d: 351 ,e \t:42,foobar:1337s\n\r,[2001::1]:6881", list2); TEST_EQUAL(list2.size(), 7); - TEST_EQUAL(list2[0].first, "a"); - TEST_EQUAL(list2[1].first, "b"); - TEST_EQUAL(list2[2].first, "c"); - TEST_EQUAL(list2[3].first, "d"); - TEST_EQUAL(list2[4].first, "e"); - TEST_EQUAL(list2[5].first, "foobar"); - TEST_EQUAL(list2[6].first, "2001::1"); + TEST_EQUAL(list2[0].device, "a"); + TEST_EQUAL(list2[1].device, "b"); + TEST_EQUAL(list2[2].device, "c"); + TEST_EQUAL(list2[3].device, "d"); + TEST_EQUAL(list2[4].device, "e"); + TEST_EQUAL(list2[5].device, "foobar"); + TEST_EQUAL(list2[6].device, "2001::1"); - TEST_EQUAL(list2[0].second, 4); - TEST_EQUAL(list2[1].second, 35); - TEST_EQUAL(list2[2].second, 1000); - TEST_EQUAL(list2[3].second, 351); - TEST_EQUAL(list2[4].second, 42); - TEST_EQUAL(list2[5].second, 1337); - TEST_EQUAL(list2[6].second, 6881); + TEST_EQUAL(list2[0].port, 4); + TEST_EQUAL(list2[1].port, 35); + TEST_EQUAL(list2[2].port, 1000); + TEST_EQUAL(list2[3].port, 351); + TEST_EQUAL(list2[4].port, 42); + TEST_EQUAL(list2[5].port, 1337); + TEST_EQUAL(list2[6].port, 6881); + + TEST_EQUAL(list2[0].ssl, false); + TEST_EQUAL(list2[1].ssl, false); + TEST_EQUAL(list2[2].ssl, true); + TEST_EQUAL(list2[3].ssl, false); + TEST_EQUAL(list2[4].ssl, false); + TEST_EQUAL(list2[5].ssl, true); + TEST_EQUAL(list2[6].ssl, false); + + TEST_EQUAL(print_listen_interfaces(list2), "a:4,b:35,c:1000s,d:351,e:42,foobar:1337s,[2001::1]:6881"); // test string_tokenize