minor cleanup of listen sockets

This commit is contained in:
arvidn 2016-01-31 19:40:31 -05:00
parent 9bb0181087
commit e113e8cdf3
5 changed files with 39 additions and 49 deletions

View File

@ -896,7 +896,8 @@ namespace libtorrent
}; };
listen_socket_t setup_listener(std::string const& device listen_socket_t setup_listener(std::string const& device
, bool ipv4, int port, int flags, error_code& ec); , boost::asio::ip::tcp const& protocol, int port, int flags
, error_code& ec);
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT
entry m_dht_state; entry m_dht_state;

View File

@ -117,7 +117,8 @@ namespace libtorrent
// in case SO_BINDTODEVICE succeeded and we don't need to verify it). // in case SO_BINDTODEVICE succeeded and we don't need to verify it).
template <class Socket> template <class Socket>
address bind_to_device(io_service& ios, Socket& sock address bind_to_device(io_service& ios, Socket& sock
, bool ipv4, char const* device_name, int port, error_code& ec) , boost::asio::ip::tcp const& protocol
, char const* device_name, int port, error_code& ec)
{ {
tcp::endpoint bind_ep(address_v4::any(), port); tcp::endpoint bind_ep(address_v4::any(), port);
@ -127,8 +128,8 @@ namespace libtorrent
#if TORRENT_USE_IPV6 #if TORRENT_USE_IPV6
// this is to cover the case where "0.0.0.0" is considered any IPv4 or // this is to cover the case where "0.0.0.0" is considered any IPv4 or
// IPv6 address. If we're asking to be bound to an IPv6 address and // IPv6 address. If we're asking to be bound to an IPv6 address and
// providing 0.0.0.0 as the device, turn it into "::0" // providing 0.0.0.0 as the device, turn it into "::"
if (ip == address_v4::any() && !ipv4) if (ip == address_v4::any() && protocol == boost::asio::ip::tcp::v6())
ip = address_v6::any(); ip = address_v6::any();
#endif #endif
bind_ep.address(ip); bind_ep.address(ip);
@ -160,7 +161,7 @@ namespace libtorrent
// (which must be of the same family as the address we're // (which must be of the same family as the address we're
// connecting to) // connecting to)
if (strcmp(ifs[i].name, device_name) != 0) continue; if (strcmp(ifs[i].name, device_name) != 0) continue;
if (ifs[i].interface_address.is_v4() != ipv4) if (ifs[i].interface_address.is_v4() != (protocol == boost::asio::ip::tcp::v4()))
continue; continue;
bind_ep.address(ifs[i].interface_address); bind_ep.address(ifs[i].interface_address);

View File

@ -84,29 +84,16 @@ namespace libtorrent
using boost::asio::null_buffers; using boost::asio::null_buffers;
#endif #endif
#if TORRENT_USE_IPV6
#ifdef IPV6_V6ONLY
struct v6only
{
v6only(bool enable): m_value(enable) {}
template<class Protocol>
int level(Protocol const&) const { return IPPROTO_IPV6; }
template<class Protocol>
int name(Protocol const&) const { return IPV6_V6ONLY; }
template<class Protocol>
int const* data(Protocol const&) const { return &m_value; }
template<class Protocol>
size_t size(Protocol const&) const { return sizeof(m_value); }
int m_value;
};
#endif
#endif
#ifdef TORRENT_WINDOWS #ifdef TORRENT_WINDOWS
#ifndef PROTECTION_LEVEL_UNRESTRICTED
#define PROTECTION_LEVEL_UNRESTRICTED 10
#endif
#ifndef IPV6_PROTECTION_LEVEL #ifndef IPV6_PROTECTION_LEVEL
#define IPV6_PROTECTION_LEVEL 30 #define IPV6_PROTECTION_LEVEL 30
#endif #endif
struct v6_protection_level struct v6_protection_level
{ {
v6_protection_level(int level): m_value(level) {} v6_protection_level(int level): m_value(level) {}

View File

@ -51,6 +51,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include <boost/function_equal.hpp> #include <boost/function_equal.hpp>
#include <boost/make_shared.hpp> #include <boost/make_shared.hpp>
#include <boost/asio/ip/v6_only.hpp>
#ifdef TORRENT_USE_VALGRIND #ifdef TORRENT_USE_VALGRIND
#include <valgrind/memcheck.h> #include <valgrind/memcheck.h>
@ -1683,7 +1684,7 @@ namespace aux {
enum { listen_no_system_port = 0x02 }; enum { listen_no_system_port = 0x02 };
listen_socket_t session_impl::setup_listener(std::string const& device listen_socket_t session_impl::setup_listener(std::string const& device
, bool ipv4, int port, int flags, error_code& ec) , boost::asio::ip::tcp const& protocol, int port, int flags, error_code& ec)
{ {
int retries = m_settings.get_int(settings_pack::max_retry_port_bind); int retries = m_settings.get_int(settings_pack::max_retry_port_bind);
@ -1693,7 +1694,7 @@ namespace aux {
listen_failed_alert::socket_type_t sock_type = (flags & open_ssl_socket) listen_failed_alert::socket_type_t sock_type = (flags & open_ssl_socket)
? listen_failed_alert::tcp_ssl : listen_failed_alert::tcp; ? listen_failed_alert::tcp_ssl : listen_failed_alert::tcp;
ret.sock.reset(new tcp::acceptor(m_io_service)); ret.sock.reset(new tcp::acceptor(m_io_service));
ret.sock->open(ipv4 ? tcp::v4() : tcp::v6(), ec); ret.sock->open(protocol, ec);
last_op = listen_failed_alert::open; last_op = listen_failed_alert::open;
if (ec) if (ec)
{ {
@ -1718,25 +1719,18 @@ namespace aux {
} }
#if TORRENT_USE_IPV6 #if TORRENT_USE_IPV6
if (!ipv4) if (protocol == boost::asio::ip::tcp::v6())
{ {
error_code err; // ignore errors here error_code err; // ignore errors here
#ifdef IPV6_V6ONLY ret.sock->set_option(boost::asio::ip::v6_only(true), err);
ret.sock->set_option(v6only(true), err);
#endif
#ifdef TORRENT_WINDOWS #ifdef TORRENT_WINDOWS
#ifndef PROTECTION_LEVEL_UNRESTRICTED
#define PROTECTION_LEVEL_UNRESTRICTED 10
#endif
// enable Teredo on windows // enable Teredo on windows
ret.sock->set_option(v6_protection_level(PROTECTION_LEVEL_UNRESTRICTED), err); ret.sock->set_option(v6_protection_level(PROTECTION_LEVEL_UNRESTRICTED), err);
#endif // TORRENT_WINDOWS #endif // TORRENT_WINDOWS
} }
#endif // TORRENT_USE_IPV6 #endif // TORRENT_USE_IPV6
address bind_ip = bind_to_device(m_io_service, *ret.sock, ipv4 address bind_ip = bind_to_device(m_io_service, *ret.sock, protocol
, device.c_str(), port, ec); , device.c_str(), port, ec);
while (ec == error_code(error::address_in_use) && retries > 0) while (ec == error_code(error::address_in_use) && retries > 0)
@ -1753,7 +1747,7 @@ namespace aux {
TORRENT_ASSERT_VAL(!ec, ec); TORRENT_ASSERT_VAL(!ec, ec);
--retries; --retries;
port += 1; port += 1;
bind_ip = bind_to_device(m_io_service, *ret.sock, ipv4 bind_ip = bind_to_device(m_io_service, *ret.sock, protocol
, device.c_str(), port, ec); , device.c_str(), port, ec);
last_op = listen_failed_alert::bind; last_op = listen_failed_alert::bind;
} }
@ -1763,7 +1757,7 @@ namespace aux {
// instead of giving up, try let the OS pick a port // instead of giving up, try let the OS pick a port
port = 0; port = 0;
ec.clear(); ec.clear();
bind_ip = bind_to_device(m_io_service, *ret.sock, ipv4 bind_ip = bind_to_device(m_io_service, *ret.sock, protocol
, device.c_str(), port, ec); , device.c_str(), port, ec);
last_op = listen_failed_alert::bind; last_op = listen_failed_alert::bind;
} }
@ -1857,13 +1851,13 @@ retry:
m_ipv4_interface = tcp::endpoint(); m_ipv4_interface = tcp::endpoint();
// TODO: instead of having a special case for this, just make the // TODO: instead of having a special case for this, just make the
// default listen interfaces be "0.0.0.0:6881,[::1]:6881" and use // default listen interfaces be "0.0.0.0:6881,[::]:6881" and use
// the generic path. That would even allow for not listening at all. // the generic path. That would even allow for not listening at all.
if (m_listen_interfaces.empty()) if (m_listen_interfaces.empty())
{ {
// this means we should open two listen sockets // this means we should open two listen sockets
// one for IPv4 and one for IPv6 // one for IPv4 and one for IPv6
listen_socket_t s = setup_listener("0.0.0.0", true listen_socket_t s = setup_listener("0.0.0.0", boost::asio::ip::tcp::v4()
, m_listen_interface.port() , m_listen_interface.port()
, flags, ec); , flags, ec);
@ -1881,7 +1875,7 @@ retry:
#ifdef TORRENT_USE_OPENSSL #ifdef TORRENT_USE_OPENSSL
if (m_settings.get_int(settings_pack::ssl_listen)) if (m_settings.get_int(settings_pack::ssl_listen))
{ {
s = setup_listener("0.0.0.0", true s = setup_listener("0.0.0.0", boost::asio::ip::tcp::v4()
, m_settings.get_int(settings_pack::ssl_listen) , m_settings.get_int(settings_pack::ssl_listen)
, flags | open_ssl_socket, ec); , flags | open_ssl_socket, ec);
@ -1897,7 +1891,8 @@ retry:
// only try to open the IPv6 port if IPv6 is installed // only try to open the IPv6 port if IPv6 is installed
if (supports_ipv6()) if (supports_ipv6())
{ {
s = setup_listener("::1", false, m_listen_interface.port() s = setup_listener("::", boost::asio::ip::tcp::v6()
, m_listen_interface.port()
, flags, ec); , flags, ec);
if (!ec && s.sock) if (!ec && s.sock)
@ -1910,7 +1905,7 @@ retry:
if (m_settings.get_int(settings_pack::ssl_listen)) if (m_settings.get_int(settings_pack::ssl_listen))
{ {
s.ssl = true; s.ssl = true;
s = setup_listener("::1", false s = setup_listener("::", boost::asio::ip::tcp::v6()
, m_settings.get_int(settings_pack::ssl_listen) , m_settings.get_int(settings_pack::ssl_listen)
, flags | open_ssl_socket, ec); , flags | open_ssl_socket, ec);
@ -1955,6 +1950,9 @@ retry:
#else #else
const int first_family = 1; const int first_family = 1;
#endif #endif
boost::asio::ip::tcp protocol[]
= { boost::asio::ip::tcp::v6(), boost::asio::ip::tcp::v4() };
for (int address_family = first_family; address_family < 2; ++address_family) for (int address_family = first_family; address_family < 2; ++address_family)
{ {
error_code err; error_code err;
@ -1964,8 +1962,8 @@ retry:
&& !is_any(test_family)) && !is_any(test_family))
continue; continue;
listen_socket_t s = setup_listener(device, address_family, port listen_socket_t s = setup_listener(device, protocol[address_family]
, flags, ec); , port, flags, ec);
if (ec == error_code(boost::system::errc::no_such_device, generic_category())) if (ec == error_code(boost::system::errc::no_such_device, generic_category()))
{ {
@ -1990,7 +1988,8 @@ retry:
#ifdef TORRENT_USE_OPENSSL #ifdef TORRENT_USE_OPENSSL
if (m_settings.get_int(settings_pack::ssl_listen)) if (m_settings.get_int(settings_pack::ssl_listen))
{ {
listen_socket_t ssl_s = setup_listener(device, address_family listen_socket_t ssl_s = setup_listener(device
, protocol[address_family]
, m_settings.get_int(settings_pack::ssl_listen) , m_settings.get_int(settings_pack::ssl_listen)
, flags | open_ssl_socket, ec); , flags | open_ssl_socket, ec);
@ -4914,7 +4913,10 @@ retry:
if (ec) return bind_ep; if (ec) return bind_ep;
bind_ep.address(bind_to_device(m_io_service, s, remote_address.is_v4() bind_ep.address(bind_to_device(m_io_service, s
, remote_address.is_v4()
? boost::asio::ip::tcp::v4()
: boost::asio::ip::tcp::v6()
, ifname.c_str(), bind_ep.port(), ec)); , ifname.c_str(), bind_ep.port(), ec));
return bind_ep; return bind_ep;
} }

View File

@ -48,6 +48,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <boost/system/system_error.hpp> #include <boost/system/system_error.hpp>
#include <boost/system/error_code.hpp> #include <boost/system/error_code.hpp>
#include <boost/asio/read.hpp> #include <boost/asio/read.hpp>
#include <boost/asio/ip/v6_only.hpp>
#if defined TORRENT_ASIO_DEBUGGING #if defined TORRENT_ASIO_DEBUGGING
#include "libtorrent/debug.hpp" #include "libtorrent/debug.hpp"
@ -822,9 +823,7 @@ void udp_socket::bind(udp::endpoint const& ep, error_code& ec)
m_ipv4_sock.set_option(exclusive_address_use(true), err); m_ipv4_sock.set_option(exclusive_address_use(true), err);
#endif #endif
m_ipv4_sock.set_option(boost::asio::socket_base::reuse_address(true), err); m_ipv4_sock.set_option(boost::asio::socket_base::reuse_address(true), err);
#ifdef IPV6_V6ONLY m_ipv6_sock.set_option(boost::asio::ip::v6_only(true), err);
m_ipv6_sock.set_option(v6only(true), err);
#endif
m_ipv6_sock.bind(ep6, ec); m_ipv6_sock.bind(ep6, ec);
if (ec != error_code(boost::system::errc::address_not_available if (ec != error_code(boost::system::errc::address_not_available