improve support for listening on multiple sockets and interfaces, with the listen_interfaces setting

This commit is contained in:
arvidn 2016-02-07 02:09:19 -05:00
parent 3842a0a197
commit 887e79eb22
11 changed files with 414 additions and 452 deletions

View File

@ -1,3 +1,4 @@
* improved support for listening on multiple sockets and interfaces
* resume data no longer has timestamps of files * resume data no longer has timestamps of files
1.1.0 release 1.1.0 release

View File

@ -1268,7 +1268,7 @@ namespace libtorrent
listen_failed_alert( listen_failed_alert(
aux::stack_allocator& alloc aux::stack_allocator& alloc
, std::string const& iface , std::string const& iface
, int port , tcp::endpoint const& ep
, int op , int op
, error_code const& ec , error_code const& ec
, socket_type_t t); , socket_type_t t);
@ -1278,7 +1278,7 @@ namespace libtorrent
static const int static_category = alert::status_notification | alert::error_notification; static const int static_category = alert::status_notification | alert::error_notification;
virtual std::string message() const TORRENT_OVERRIDE; virtual std::string message() const TORRENT_OVERRIDE;
// the interface libtorrent attempted to listen on that failed. // the network device libtorrent attempted to listen on, or the IP address
char const* listen_interface() const; char const* listen_interface() const;
// the error the system returned // the error the system returned
@ -1286,7 +1286,7 @@ namespace libtorrent
enum op_t enum op_t
{ {
parse_addr, open, bind, listen, get_peer_name, accept parse_addr, open, bind, listen, get_socket_name, accept, enum_if
}; };
// the specific low level operation that failed. See op_t. // the specific low level operation that failed. See op_t.

View File

@ -124,12 +124,21 @@ namespace libtorrent
struct listen_socket_t struct listen_socket_t
{ {
listen_socket_t(): external_port(0), ssl(false) {} listen_socket_t()
: tcp_external_port(0)
, ssl(false)
{
tcp_port_mapping[0] = -1;
tcp_port_mapping[1] = -1;
}
// this is typically empty but can be set // this is typically empty but can be set
// to the WAN IP address of NAT-PMP or UPnP router // to the WAN IP address of NAT-PMP or UPnP router
address external_address; address external_address;
// this is a cached local endpoint for the listen socket
tcp::endpoint local_endpoint;
// this is typically set to the same as the local // this is typically set to the same as the local
// listen port. In case a NAT port forward was // listen port. In case a NAT port forward was
// successfully opened, this will be set to the // successfully opened, this will be set to the
@ -137,7 +146,10 @@ namespace libtorrent
// on the NAT box itself. This is the port that has // on the NAT box itself. This is the port that has
// to be published to peers, since this is the port // to be published to peers, since this is the port
// the client is reachable through. // the client is reachable through.
int external_port; int tcp_external_port;
// 0 is natpmp 1 is upnp
int tcp_port_mapping[2];
// set to true if this is an SSL listen socket // set to true if this is an SSL listen socket
bool ssl; bool ssl;
@ -837,10 +849,6 @@ namespace libtorrent
// which interface to listen on // which interface to listen on
std::vector<std::pair<std::string, int> > m_listen_interfaces; std::vector<std::pair<std::string, int> > m_listen_interfaces;
// keep this around until everything uses the list of interfaces
// instead.
tcp::endpoint m_listen_interface;
// the network interfaces outgoing connections are opened through. If // the network interfaces outgoing connections are opened through. If
// there is more then one, they are used in a round-robin fashion // there is more then one, they are used in a round-robin fashion
// each element is a device name or IP address (in string form) and // each element is a device name or IP address (in string form) and
@ -850,12 +858,6 @@ namespace libtorrent
// socket fails. // socket fails.
std::vector<std::string> m_outgoing_interfaces; std::vector<std::string> m_outgoing_interfaces;
// if we're listening on an IPv6 interface
// this is one of the non local IPv6 interfaces
// on this machine
tcp::endpoint m_ipv6_interface;
tcp::endpoint m_ipv4_interface;
// since we might be listening on multiple interfaces // since we might be listening on multiple interfaces
// we might need more than one listen socket // we might need more than one listen socket
std::list<listen_socket_t> m_listen_sockets; std::list<listen_socket_t> m_listen_sockets;
@ -887,8 +889,7 @@ namespace libtorrent
}; };
listen_socket_t setup_listener(std::string const& device listen_socket_t setup_listener(std::string const& device
, boost::asio::ip::tcp const& protocol, int port, int flags , tcp::endpoint bind_ep, int flags, error_code& ec);
, error_code& ec);
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT
entry m_dht_state; entry m_dht_state;
@ -1026,6 +1027,7 @@ namespace libtorrent
// see m_external_listen_port. This is the same // see m_external_listen_port. This is the same
// but for the udp port used by the DHT. // but for the udp port used by the DHT.
// TODO: 3 once udp sockets are part of m_listen_sockets, remove this
int m_external_udp_port; int m_external_udp_port;
udp_socket m_udp_socket; udp_socket m_udp_socket;
@ -1046,18 +1048,18 @@ namespace libtorrent
boost::shared_ptr<upnp> m_upnp; boost::shared_ptr<upnp> m_upnp;
boost::shared_ptr<lsd> m_lsd; boost::shared_ptr<lsd> m_lsd;
// TODO: 3 once the udp socket is in listen_socket_t, these should
// move in there too
// 0 is natpmp 1 is upnp
int m_udp_mapping[2];
#ifdef TORRENT_USE_OPENSSL
int m_ssl_udp_mapping[2];
#endif
// mask is a bitmask of which protocols to remap on: // mask is a bitmask of which protocols to remap on:
// 1: NAT-PMP // 1: NAT-PMP
// 2: UPnP // 2: UPnP
void remap_tcp_ports(boost::uint32_t mask, int tcp_port, int ssl_port); void remap_ports(boost::uint32_t mask, listen_socket_t& s);
// 0 is natpmp 1 is upnp
int m_tcp_mapping[2];
int m_udp_mapping[2];
#ifdef TORRENT_USE_OPENSSL
int m_ssl_tcp_mapping[2];
int m_ssl_udp_mapping[2];
#endif
// the timer used to fire the tick // the timer used to fire the tick
deadline_timer m_timer; deadline_timer m_timer;

View File

@ -246,6 +246,7 @@ namespace libtorrent { namespace aux
virtual void prioritize_connections(boost::weak_ptr<torrent> t) = 0; virtual void prioritize_connections(boost::weak_ptr<torrent> t) = 0;
// TODO: 3 these should go away!
virtual tcp::endpoint get_ipv6_interface() const = 0; virtual tcp::endpoint get_ipv6_interface() const = 0;
virtual tcp::endpoint get_ipv4_interface() const = 0; virtual tcp::endpoint get_ipv4_interface() const = 0;

View File

@ -723,8 +723,7 @@ namespace libtorrent
void force_tracker_request(time_point, int tracker_idx); void force_tracker_request(time_point, int tracker_idx);
void scrape_tracker(int idx, bool user_triggered); void scrape_tracker(int idx, bool user_triggered);
void announce_with_tracker(boost::uint8_t e void announce_with_tracker(boost::uint8_t e
= tracker_request::none = tracker_request::none);
, address const& bind_interface = address_v4::any());
int seconds_since_last_scrape() const int seconds_since_last_scrape() const
{ {
return m_last_scrape == (std::numeric_limits<boost::int16_t>::min)() return m_last_scrape == (std::numeric_limits<boost::int16_t>::min)()

View File

@ -134,7 +134,7 @@ class TORRENT_EXTRA_EXPORT upnp : public boost::enable_shared_from_this<upnp>
{ {
public: public:
upnp(io_service& ios upnp(io_service& ios
, address const& listen_interface, std::string const& user_agent , std::string const& user_agent
, portmap_callback_t const& cb, log_callback_t const& lcb , portmap_callback_t const& cb, log_callback_t const& lcb
, bool ignore_nonrouters); , bool ignore_nonrouters);
~upnp(); ~upnp();

View File

@ -786,26 +786,19 @@ namespace libtorrent {
"HTTPS", "HTTPS",
"SSL/uTP" "SSL/uTP"
}; };
tcp::endpoint parse_interface(std::string const& iface, int port)
{
// ignore errors
error_code ec;
return tcp::endpoint(address::from_string(iface, ec), port);
}
} }
listen_failed_alert::listen_failed_alert( listen_failed_alert::listen_failed_alert(
aux::stack_allocator& alloc aux::stack_allocator& alloc
, std::string const& iface , std::string const& iface
, int prt , tcp::endpoint const& ep
, int op , int op
, error_code const& ec , error_code const& ec
, socket_type_t t) , socket_type_t t)
: error(ec) : error(ec)
, operation(op) , operation(op)
, sock_type(t) , sock_type(t)
, endpoint(parse_interface(iface, prt)) , endpoint(ep)
, m_alloc(alloc) , m_alloc(alloc)
, m_interface_idx(alloc.copy_string(iface)) , m_interface_idx(alloc.copy_string(iface))
{} {}
@ -823,11 +816,13 @@ namespace libtorrent {
"open", "open",
"bind", "bind",
"listen", "listen",
"get_peer_name", "get_socket_name",
"accept" "accept",
"enum_if"
}; };
char ret[300]; char ret[300];
snprintf(ret, sizeof(ret), "listening on %s failed: [%s] [%s] %s" snprintf(ret, sizeof(ret), "listening on %s (device: %s) failed: [%s] [%s] %s"
, print_endpoint(endpoint).c_str()
, listen_interface() , listen_interface()
, op_str[operation] , op_str[operation]
, sock_type_str[sock_type] , sock_type_str[sock_type]

File diff suppressed because it is too large Load Diff

View File

@ -125,6 +125,12 @@ namespace libtorrent
using aux::session_impl; using aux::session_impl;
#if TORRENT_USE_IPV6
#define DEFAULT_LISTEN_INTERFACE "0.0.0.0:6881,[::]:6881"
#else
#define DEFAULT_LISTEN_INTERFACE "0.0.0.0:6881"
#endif
str_setting_entry_t str_settings[settings_pack::num_string_settings] = str_setting_entry_t str_settings[settings_pack::num_string_settings] =
{ {
SET(user_agent, "libtorrent/" LIBTORRENT_VERSION, &session_impl::update_user_agent), SET(user_agent, "libtorrent/" LIBTORRENT_VERSION, &session_impl::update_user_agent),
@ -132,7 +138,7 @@ namespace libtorrent
SET(mmap_cache, 0, 0), SET(mmap_cache, 0, 0),
SET(handshake_client_version, 0, 0), SET(handshake_client_version, 0, 0),
SET_NOPREV(outgoing_interfaces, "", &session_impl::update_outgoing_interfaces), SET_NOPREV(outgoing_interfaces, "", &session_impl::update_outgoing_interfaces),
SET_NOPREV(listen_interfaces, "0.0.0.0:6881", &session_impl::update_listen_interfaces), SET_NOPREV(listen_interfaces, DEFAULT_LISTEN_INTERFACE, &session_impl::update_listen_interfaces),
SET_NOPREV(proxy_hostname, "", &session_impl::update_proxy), SET_NOPREV(proxy_hostname, "", &session_impl::update_proxy),
SET_NOPREV(proxy_username, "", &session_impl::update_proxy), SET_NOPREV(proxy_username, "", &session_impl::update_proxy),
SET_NOPREV(proxy_password, "", &session_impl::update_proxy), SET_NOPREV(proxy_password, "", &session_impl::update_proxy),
@ -140,6 +146,8 @@ namespace libtorrent
SET_NOPREV(peer_fingerprint, "-LT1100-", &session_impl::update_peer_fingerprint) SET_NOPREV(peer_fingerprint, "-LT1100-", &session_impl::update_peer_fingerprint)
}; };
#undef DEFAULT_LISTEN_INTERFACE
bool_setting_entry_t bool_settings[settings_pack::num_bool_settings] = bool_setting_entry_t bool_settings[settings_pack::num_bool_settings] =
{ {
SET(allow_multiple_connections_per_ip, false, 0), SET(allow_multiple_connections_per_ip, false, 0),

View File

@ -3058,8 +3058,7 @@ namespace libtorrent
#endif #endif
void torrent::announce_with_tracker(boost::uint8_t e void torrent::announce_with_tracker(boost::uint8_t e)
, address const& bind_interface)
{ {
TORRENT_ASSERT(is_single_thread()); TORRENT_ASSERT(is_single_thread());
INVARIANT_CHECK; INVARIANT_CHECK;
@ -3183,8 +3182,6 @@ namespace libtorrent
req.triggered_manually = ae.triggered_manually; req.triggered_manually = ae.triggered_manually;
ae.triggered_manually = false; ae.triggered_manually = false;
req.bind_ip = bind_interface;
if (settings().get_bool(settings_pack::force_proxy)) if (settings().get_bool(settings_pack::force_proxy))
{ {
// in force_proxy mode we don't talk directly to trackers // in force_proxy mode we don't talk directly to trackers
@ -3574,6 +3571,8 @@ namespace libtorrent
// matches one of the listen interfaces, since that means this // matches one of the listen interfaces, since that means this
// announce was the second one // announce was the second one
// TODO: 3 instead of announcing once per IP version, announce once per
// listen interface (i.e. m_listen_sockets)
if (((!is_any(m_ses.get_ipv6_interface().address()) && tracker_ip.is_v4()) if (((!is_any(m_ses.get_ipv6_interface().address()) && tracker_ip.is_v4())
|| (!is_any(m_ses.get_ipv4_interface().address()) && tracker_ip.is_v6())) || (!is_any(m_ses.get_ipv4_interface().address()) && tracker_ip.is_v6()))
&& r.bind_ip != m_ses.get_ipv4_interface().address() && r.bind_ip != m_ses.get_ipv4_interface().address()

View File

@ -69,8 +69,11 @@ namespace upnp_errors
static error_code ignore_error; static error_code ignore_error;
// TODO: 3 bind the broadcast socket. it would probably have to be changed to a vector of interfaces to
// bind to, since the broadcast socket opens one socket per local
// interface by default
upnp::upnp(io_service& ios upnp::upnp(io_service& ios
, address const& listen_interface, std::string const& user_agent , std::string const& user_agent
, portmap_callback_t const& cb, log_callback_t const& lcb , portmap_callback_t const& cb, log_callback_t const& lcb
, bool ignore_nonrouters) , bool ignore_nonrouters)
: m_user_agent(user_agent) : m_user_agent(user_agent)
@ -90,12 +93,6 @@ upnp::upnp(io_service& ios
, m_last_if_update(min_time()) , m_last_if_update(min_time())
{ {
TORRENT_ASSERT(cb); TORRENT_ASSERT(cb);
// TODO: 3 listen_interface is not used. It's meant to bind the broadcast
// socket. it would probably have to be changed to a vector of interfaces to
// bind to though, since the broadcast socket opens one socket per local
// interface by default
TORRENT_UNUSED(listen_interface);
} }
void upnp::start() void upnp::start()