diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp index d2dff894a..c0197fdb0 100644 --- a/include/libtorrent/aux_/session_impl.hpp +++ b/include/libtorrent/aux_/session_impl.hpp @@ -151,6 +151,7 @@ namespace libtorrent // this will return one of the IPv6 addresses on this // machine, otherwise just an empty endpoint tcp::endpoint get_ipv6_interface() const; + tcp::endpoint get_ipv4_interface() const; void async_accept(boost::shared_ptr const& listener); void on_accept_connection(boost::shared_ptr const& s @@ -431,6 +432,7 @@ namespace libtorrent // this is one of the non local IPv6 interfaces // on this machine tcp::endpoint m_ipv6_interface; + tcp::endpoint m_ipv4_interface; struct listen_socket_t { diff --git a/include/libtorrent/tracker_manager.hpp b/include/libtorrent/tracker_manager.hpp index 834473682..d76aea6c6 100644 --- a/include/libtorrent/tracker_manager.hpp +++ b/include/libtorrent/tracker_manager.hpp @@ -109,6 +109,7 @@ namespace libtorrent int key; int num_want; std::string ipv6; + std::string ipv4; }; struct TORRENT_EXPORT request_callback diff --git a/src/http_tracker_connection.cpp b/src/http_tracker_connection.cpp index bad7b90fe..63012b402 100644 --- a/src/http_tracker_connection.cpp +++ b/src/http_tracker_connection.cpp @@ -164,8 +164,17 @@ namespace libtorrent #ifndef TORRENT_DISABLE_ENCRYPTION url += "&supportcrypto=1"; #endif - url += "&ipv6="; - url += tracker_req().ipv6; + if (!tracker_req().ipv6.empty()) + { + url += "&ipv6="; + url += tracker_req().ipv6; + } + + if (!tracker_req().ipv4.empty()) + { + url += "&ipv4="; + url += tracker_req().ipv4; + } // extension that tells the tracker that // we don't need any peer_id's in the response diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 1efe34bd2..70a04db6f 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -634,6 +634,11 @@ namespace aux { return m_ipv6_interface; } + tcp::endpoint session_impl::get_ipv4_interface() const + { + return m_ipv4_interface; + } + session_impl::listen_socket_t session_impl::setup_listener(tcp::endpoint ep , int retries, bool v6_only) { @@ -713,6 +718,9 @@ namespace aux { m_listen_sockets.clear(); m_incoming_connection = false; + m_ipv6_interface = tcp::endpoint(); + m_ipv4_interface = tcp::endpoint(); + if (is_any(m_listen_interface.address())) { // this means we should open two listen sockets @@ -751,6 +759,20 @@ namespace aux { } #endif #endif // TORRENT_USE_IPV6 + + // set our main IPv4 and IPv6 interfaces + // used to send to the tracker + error_code ec; + std::vector ifs = enum_net_interfaces(m_io_service, ec); + for (std::vector::const_iterator i = ifs.begin() + , end(ifs.end()); i != end; ++i) + { + address const& addr = i->interface_address; + if (addr.is_v6() && !is_local(addr) && !is_loopback(addr)) + m_ipv6_interface = tcp::endpoint(addr, m_listen_interface.port()); + else if (addr.is_v4() && !is_local(addr) && !is_loopback(addr)) + m_ipv4_interface = tcp::endpoint(addr, m_listen_interface.port()); + } } else { @@ -764,49 +786,16 @@ namespace aux { { m_listen_sockets.push_back(s); async_accept(s.sock); + + if (m_listen_interface.address().is_v6()) + m_ipv6_interface = m_listen_interface; + else + m_ipv4_interface = m_listen_interface; } } open_new_incoming_socks_connection(); - // figure out which IPv6 address we're listening on - // or at least one of them. This is used to announce - // to the tracker - m_ipv6_interface = tcp::endpoint(); - -#if TORRENT_USE_IPV6 - for (std::list::const_iterator i = m_listen_sockets.begin() - , end(m_listen_sockets.end()); i != end; ++i) - { - error_code ec; - tcp::endpoint ep = i->sock->local_endpoint(ec); - if (ec || ep.address().is_v4()) continue; - - if (ep.address().to_v6() != address_v6::any()) - { - // if we're listening on a specific address - // pick it - m_ipv6_interface = ep; - } - else - { - // if we're listening on any IPv6 address, enumerate them and - // pick the first non-local address - std::vector const& ifs = enum_net_interfaces(m_io_service, ec); - for (std::vector::const_iterator i = ifs.begin() - , end(ifs.end()); i != end; ++i) - { - if (i->interface_address.is_v4() - || i->interface_address.to_v6().is_link_local() - || i->interface_address.to_v6().is_loopback()) continue; - m_ipv6_interface = tcp::endpoint(i->interface_address, ep.port()); - break; - } - break; - } - } -#endif // TORRENT_USE_IPV6 - if (!m_listen_sockets.empty()) { error_code ec; diff --git a/src/torrent.cpp b/src/torrent.cpp index 97c385d72..8b9eea5a0 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -1021,10 +1021,12 @@ namespace libtorrent req.left = bytes_left(); if (req.left == -1) req.left = 16*1024; req.event = e; - tcp::endpoint ep = m_ses.get_ipv6_interface(); error_code ec; - if (ep != tcp::endpoint()) - req.ipv6 = ep.address().to_string(ec); + tcp::endpoint ep; + ep = m_ses.get_ipv6_interface(); + if (ep != tcp::endpoint()) req.ipv6 = ep.address().to_string(ec); + ep = m_ses.get_ipv4_interface(); + if (ep != tcp::endpoint()) req.ipv4 = ep.address().to_string(ec); // if we are aborting. we don't want any new peers req.num_want = (req.event == tracker_request::stopped)