forked from premiere/premiere-libtorrent
Merge pull request #464 from arvidn/listen-multi-homed
improve support for listening on multiple sockets and interfaces
This commit is contained in:
commit
a69de84482
|
@ -1,3 +1,6 @@
|
|||
* improved support for bind-to-device
|
||||
* deprecated ssl_listen, SSL sockets are specified in listen_interfaces now
|
||||
* improved support for listening on multiple sockets and interfaces
|
||||
* resume data no longer has timestamps of files
|
||||
|
||||
1.1.0 release
|
||||
|
|
|
@ -588,13 +588,11 @@ int print_peer_info(std::string& out
|
|||
return pos;
|
||||
}
|
||||
|
||||
int listen_port = 6881;
|
||||
int allocation_mode = libtorrent::storage_mode_sparse;
|
||||
std::string save_path(".");
|
||||
int torrent_upload_limit = 0;
|
||||
int torrent_download_limit = 0;
|
||||
std::string monitor_dir;
|
||||
std::string bind_to_interface = "";
|
||||
int poll_interval = 5;
|
||||
int max_connections_per_torrent = 50;
|
||||
bool seed_mode = false;
|
||||
|
@ -1238,7 +1236,6 @@ int main(int argc, char* argv[])
|
|||
" -v <limit> Set the max number of active downloads\n"
|
||||
" -^ <limit> Set the max number of active seeds\n"
|
||||
"\n NETWORK OPTIONS\n"
|
||||
" -p <port> sets the listen port\n"
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
" -o <limit> limits the number of simultaneous\n"
|
||||
" half-open TCP connections to the\n"
|
||||
|
@ -1257,10 +1254,14 @@ int main(int argc, char* argv[])
|
|||
" incoming TCP connections)\n"
|
||||
" -J Disable uTP connections (disable outgoing uTP and reject\n"
|
||||
" incoming uTP connections)\n"
|
||||
" -b <IP> sets IP of the interface to bind the\n"
|
||||
" -b <iface-list> sets the listen interfaces string. This is a\n"
|
||||
" comma separated list of IP:port pairs. Instead\n"
|
||||
" of an IP, a network interface device name can\n"
|
||||
" be specified\n"
|
||||
" listen socket to\n"
|
||||
" -I <IP> sets the IP of the interface to bind\n"
|
||||
" outgoing peer connections to\n"
|
||||
" -I <iface-list> sets the IPs or network interface devices to bind\n"
|
||||
" outgoing peer connections to. This can be a\n"
|
||||
" comma-separated list"
|
||||
#if TORRENT_USE_I2P
|
||||
" -i <i2p-host> the hostname to an I2P SAM bridge to use\n"
|
||||
#endif
|
||||
|
@ -1361,7 +1362,6 @@ int main(int argc, char* argv[])
|
|||
case 'o': settings.set_int(settings_pack::half_open_limit, atoi(arg)); break;
|
||||
#endif
|
||||
case 'h': settings.set_bool(settings_pack::allow_multiple_connections_per_ip, true); --i; break;
|
||||
case 'p': listen_port = atoi(arg); break;
|
||||
case 'k': high_performance_seed(settings); --i; break;
|
||||
case 'j': settings.set_bool(settings_pack::use_disk_read_ahead, false); --i; break;
|
||||
case 'z': settings.set_bool(settings_pack::disable_hash_checks, true); --i; break;
|
||||
|
@ -1386,7 +1386,7 @@ int main(int argc, char* argv[])
|
|||
case 'D': torrent_download_limit = atoi(arg) * 1000; break;
|
||||
case 'm': monitor_dir = arg; break;
|
||||
case 'Q': share_mode = true; --i; break;
|
||||
case 'b': bind_to_interface = arg; break;
|
||||
case 'b': settings.set_str(settings_pack::listen_interfaces, arg); break;
|
||||
case 'w': settings.set_int(settings_pack::urlseed_wait_retry, atoi(arg)); break;
|
||||
case 't': poll_interval = atoi(arg); break;
|
||||
case 'F': refresh_delay = atoi(arg); break;
|
||||
|
@ -1533,12 +1533,6 @@ int main(int argc, char* argv[])
|
|||
fprintf(stderr, "failed to create resume file directory: (%d) %s\n"
|
||||
, errno, strerror(errno));
|
||||
|
||||
if (bind_to_interface.empty()) bind_to_interface = "0.0.0.0";
|
||||
char iface_str[100];
|
||||
snprintf(iface_str, sizeof(iface_str), "%s:%d", bind_to_interface.c_str()
|
||||
, listen_port);
|
||||
settings.set_str(settings_pack::listen_interfaces, iface_str);
|
||||
|
||||
settings.set_str(settings_pack::user_agent, "client_test/" LIBTORRENT_VERSION);
|
||||
settings.set_int(settings_pack::alert_mask, alert::all_categories
|
||||
& ~(alert::dht_notification
|
||||
|
|
|
@ -17,6 +17,7 @@ nobase_include_HEADERS = \
|
|||
bandwidth_queue_entry.hpp \
|
||||
bencode.hpp \
|
||||
bdecode.hpp \
|
||||
bind_to_device.hpp \
|
||||
bitfield.hpp \
|
||||
block_cache.hpp \
|
||||
bloom_filter.hpp \
|
||||
|
|
|
@ -1268,7 +1268,7 @@ namespace libtorrent
|
|||
listen_failed_alert(
|
||||
aux::stack_allocator& alloc
|
||||
, std::string const& iface
|
||||
, int port
|
||||
, tcp::endpoint const& ep
|
||||
, int op
|
||||
, error_code const& ec
|
||||
, socket_type_t t);
|
||||
|
@ -1278,7 +1278,7 @@ namespace libtorrent
|
|||
static const int static_category = alert::status_notification | alert::error_notification;
|
||||
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;
|
||||
|
||||
// the error the system returned
|
||||
|
@ -1286,7 +1286,7 @@ namespace libtorrent
|
|||
|
||||
enum op_t
|
||||
{
|
||||
parse_addr, open, bind, listen, get_peer_name, accept
|
||||
parse_addr, open, bind, listen, get_socket_name, accept, enum_if, bind_to_device
|
||||
};
|
||||
|
||||
// the specific low level operation that failed. See op_t.
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2016, 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.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TORRENT_BIND_TO_DEVICE_HPP_INCLUDED
|
||||
#define TORRENT_BIND_TO_DEVICE_HPP_INCLUDED
|
||||
|
||||
#include "libtorrent/config.hpp"
|
||||
#include "libtorrent/socket.hpp"
|
||||
|
||||
#if TORRENT_USE_IFCONF || TORRENT_USE_NETLINK || TORRENT_USE_SYSCTL
|
||||
#include <sys/socket.h> // for SO_BINDTODEVICE
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
namespace libtorrent { namespace aux {
|
||||
|
||||
#if defined SO_BINDTODEVICE
|
||||
|
||||
struct bind_to_device
|
||||
{
|
||||
bind_to_device(char const* device): m_value(device) {}
|
||||
template<class Protocol>
|
||||
int level(Protocol const&) const { return SOL_SOCKET; }
|
||||
template<class Protocol>
|
||||
int name(Protocol const&) const { return SO_BINDTODEVICE; }
|
||||
template<class Protocol>
|
||||
char const* data(Protocol const&) const { return m_value; }
|
||||
template<class Protocol>
|
||||
size_t size(Protocol const&) const { return strlen(m_value) + 1; }
|
||||
private:
|
||||
char const* m_value;
|
||||
};
|
||||
|
||||
#define TORRENT_HAS_BINDTODEVICE 1
|
||||
|
||||
#elif defined IP_BOUND_IF
|
||||
|
||||
struct bind_to_device
|
||||
{
|
||||
bind_to_device(char const* device): m_value(if_nametoindex(device)) {}
|
||||
template<class Protocol>
|
||||
int level(Protocol const&) const { return IPPROTO_IP; }
|
||||
template<class Protocol>
|
||||
int name(Protocol const&) const { return IP_BOUND_IF; }
|
||||
template<class Protocol>
|
||||
char const* data(Protocol const&) const { return reinterpret_cast<char const*>(&m_value); }
|
||||
template<class Protocol>
|
||||
size_t size(Protocol const&) const { return sizeof(m_value); }
|
||||
private:
|
||||
unsigned int m_value;
|
||||
};
|
||||
|
||||
#define TORRENT_HAS_BINDTODEVICE 1
|
||||
|
||||
#elif defined IP_FORCE_OUT_IFP
|
||||
|
||||
struct bind_to_device
|
||||
{
|
||||
bind_to_device(char const* device): m_value(device) {}
|
||||
template<class Protocol>
|
||||
int level(Protocol const&) const { return SOL_SOCKET; }
|
||||
template<class Protocol>
|
||||
int name(Protocol const&) const { return IP_FORCE_OUT_IFP; }
|
||||
template<class Protocol>
|
||||
char const* data(Protocol const&) const { return m_value; }
|
||||
template<class Protocol>
|
||||
size_t size(Protocol const&) const { return strlen(m_value) + 1; }
|
||||
private:
|
||||
char const* m_value;
|
||||
};
|
||||
|
||||
#define TORRENT_HAS_BINDTODEVICE 1
|
||||
|
||||
#else
|
||||
|
||||
#define TORRENT_HAS_BINDTODEVICE 0
|
||||
|
||||
#endif
|
||||
|
||||
} }
|
||||
|
||||
#endif
|
||||
|
|
@ -124,12 +124,21 @@ namespace libtorrent
|
|||
|
||||
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
|
||||
// to the WAN IP address of NAT-PMP or UPnP router
|
||||
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
|
||||
// listen port. In case a NAT port forward was
|
||||
// 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
|
||||
// to be published to peers, since this is the port
|
||||
// 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
|
||||
bool ssl;
|
||||
|
@ -616,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
|
||||
|
@ -625,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();
|
||||
|
@ -635,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();
|
||||
|
@ -662,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;
|
||||
|
@ -835,11 +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<std::pair<std::string, int> > m_listen_interfaces;
|
||||
|
||||
// keep this around until everything uses the list of interfaces
|
||||
// instead.
|
||||
tcp::endpoint m_listen_interface;
|
||||
std::vector<listen_interface_t> 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
|
||||
|
@ -850,12 +861,6 @@ namespace libtorrent
|
|||
// socket fails.
|
||||
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
|
||||
// we might need more than one listen socket
|
||||
std::list<listen_socket_t> m_listen_sockets;
|
||||
|
@ -887,8 +892,7 @@ namespace libtorrent
|
|||
};
|
||||
|
||||
listen_socket_t setup_listener(std::string const& device
|
||||
, boost::asio::ip::tcp const& protocol, int port, int flags
|
||||
, error_code& ec);
|
||||
, tcp::endpoint bind_ep, int flags, error_code& ec);
|
||||
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
entry m_dht_state;
|
||||
|
@ -1026,6 +1030,7 @@ namespace libtorrent
|
|||
|
||||
// see m_external_listen_port. This is the same
|
||||
// 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;
|
||||
|
||||
udp_socket m_udp_socket;
|
||||
|
@ -1046,18 +1051,18 @@ namespace libtorrent
|
|||
boost::shared_ptr<upnp> m_upnp;
|
||||
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:
|
||||
// 1: NAT-PMP
|
||||
// 2: UPnP
|
||||
void remap_tcp_ports(boost::uint32_t mask, int tcp_port, int ssl_port);
|
||||
|
||||
// 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
|
||||
void remap_ports(boost::uint32_t mask, listen_socket_t& s);
|
||||
|
||||
// the timer used to fire the tick
|
||||
deadline_timer m_timer;
|
||||
|
|
|
@ -246,6 +246,7 @@ namespace libtorrent { namespace aux
|
|||
|
||||
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_ipv4_interface() const = 0;
|
||||
|
||||
|
@ -318,6 +319,7 @@ namespace libtorrent { namespace aux
|
|||
virtual std::vector<block_info>& 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
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/address.hpp"
|
||||
#include "libtorrent/error_code.hpp"
|
||||
#include "libtorrent/socket.hpp"
|
||||
#include "libtorrent/aux_/bind_to_device.hpp"
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
@ -93,22 +94,6 @@ namespace libtorrent
|
|||
|
||||
TORRENT_EXTRA_EXPORT address get_default_gateway(io_service& ios, error_code& ec);
|
||||
|
||||
#ifdef SO_BINDTODEVICE
|
||||
struct bind_to_device_opt
|
||||
{
|
||||
bind_to_device_opt(char const* device): m_value(device) {}
|
||||
template<class Protocol>
|
||||
int level(Protocol const&) const { return SOL_SOCKET; }
|
||||
template<class Protocol>
|
||||
int name(Protocol const&) const { return SO_BINDTODEVICE; }
|
||||
template<class Protocol>
|
||||
const char* data(Protocol const&) const { return m_value; }
|
||||
template<class Protocol>
|
||||
size_t size(Protocol const&) const { return IFNAMSIZ; }
|
||||
char const* m_value;
|
||||
};
|
||||
#endif
|
||||
|
||||
// attempt to bind socket to the device with the specified name. For systems
|
||||
// that don't support SO_BINDTODEVICE the socket will be bound to one of the
|
||||
// IP addresses of the specified device. In this case it is necessary to
|
||||
|
@ -116,7 +101,7 @@ namespace libtorrent
|
|||
// the returned address is the ip the socket was bound to (or address_v4::any()
|
||||
// in case SO_BINDTODEVICE succeeded and we don't need to verify it).
|
||||
template <class Socket>
|
||||
address bind_to_device(io_service& ios, Socket& sock
|
||||
address bind_socket_to_device(io_service& ios, Socket& sock
|
||||
, boost::asio::ip::tcp const& protocol
|
||||
, char const* device_name, int port, error_code& ec)
|
||||
{
|
||||
|
@ -140,10 +125,10 @@ namespace libtorrent
|
|||
|
||||
ec.clear();
|
||||
|
||||
#ifdef SO_BINDTODEVICE
|
||||
#if TORRENT_HAS_BINDTODEVICE
|
||||
// try to use SO_BINDTODEVICE here, if that exists. If it fails,
|
||||
// fall back to the mechanism we have below
|
||||
sock.set_option(bind_to_device_opt(device_name), ec);
|
||||
sock.set_option(aux::bind_to_device(device_name), ec);
|
||||
if (ec)
|
||||
#endif
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<std::pair<std::string, int> >& out);
|
||||
TORRENT_EXTRA_EXPORT void parse_listen_interfaces(
|
||||
std::string const& in, std::vector<listen_interface_t>& out);
|
||||
|
||||
TORRENT_EXTRA_EXPORT std::string print_listen_interfaces(
|
||||
std::vector<listen_interface_t> 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:
|
||||
|
|
|
@ -723,8 +723,7 @@ namespace libtorrent
|
|||
void force_tracker_request(time_point, int tracker_idx);
|
||||
void scrape_tracker(int idx, bool user_triggered);
|
||||
void announce_with_tracker(boost::uint8_t e
|
||||
= tracker_request::none
|
||||
, address const& bind_interface = address_v4::any());
|
||||
= tracker_request::none);
|
||||
int seconds_since_last_scrape() const
|
||||
{
|
||||
return m_last_scrape == (std::numeric_limits<boost::int16_t>::min)()
|
||||
|
|
|
@ -134,7 +134,7 @@ class TORRENT_EXTRA_EXPORT upnp : public boost::enable_shared_from_this<upnp>
|
|||
{
|
||||
public:
|
||||
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
|
||||
, bool ignore_nonrouters);
|
||||
~upnp();
|
||||
|
|
|
@ -786,26 +786,19 @@ namespace libtorrent {
|
|||
"HTTPS",
|
||||
"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(
|
||||
aux::stack_allocator& alloc
|
||||
, std::string const& iface
|
||||
, int prt
|
||||
, tcp::endpoint const& ep
|
||||
, int op
|
||||
, error_code const& ec
|
||||
, socket_type_t t)
|
||||
: error(ec)
|
||||
, operation(op)
|
||||
, sock_type(t)
|
||||
, endpoint(parse_interface(iface, prt))
|
||||
, endpoint(ep)
|
||||
, m_alloc(alloc)
|
||||
, m_interface_idx(alloc.copy_string(iface))
|
||||
{}
|
||||
|
@ -823,11 +816,14 @@ namespace libtorrent {
|
|||
"open",
|
||||
"bind",
|
||||
"listen",
|
||||
"get_peer_name",
|
||||
"accept"
|
||||
"get_socket_name",
|
||||
"accept",
|
||||
"enum_if",
|
||||
"bind_to_device"
|
||||
};
|
||||
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()
|
||||
, op_str[operation]
|
||||
, sock_type_str[sock_type]
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -125,6 +125,12 @@ namespace libtorrent
|
|||
|
||||
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] =
|
||||
{
|
||||
SET(user_agent, "libtorrent/" LIBTORRENT_VERSION, &session_impl::update_user_agent),
|
||||
|
@ -132,7 +138,7 @@ namespace libtorrent
|
|||
SET(mmap_cache, 0, 0),
|
||||
SET(handshake_client_version, 0, 0),
|
||||
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_username, "", &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)
|
||||
};
|
||||
|
||||
#undef DEFAULT_LISTEN_INTERFACE
|
||||
|
||||
bool_setting_entry_t bool_settings[settings_pack::num_bool_settings] =
|
||||
{
|
||||
SET(allow_multiple_connections_per_ip, false, 0),
|
||||
|
@ -322,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),
|
||||
|
|
|
@ -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,42 @@ namespace libtorrent
|
|||
return static_cast<char*>(p) + (8 - offset);
|
||||
}
|
||||
|
||||
std::string print_listen_interfaces(std::vector<listen_interface_t> const& in)
|
||||
{
|
||||
std::string ret;
|
||||
for (std::vector<listen_interface_t>::const_iterator i = in.begin()
|
||||
, end(in.end()); i != end; ++i)
|
||||
{
|
||||
if (i != in.begin()) ret += ",";
|
||||
|
||||
#if TORRENT_USE_IPV6
|
||||
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
|
||||
#endif
|
||||
{
|
||||
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<std::pair<std::string, int> >& out)
|
||||
void parse_listen_interfaces(std::string const& in
|
||||
, std::vector<listen_interface_t>& out)
|
||||
{
|
||||
out.clear();
|
||||
|
||||
|
@ -193,7 +225,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 +242,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;
|
||||
|
|
|
@ -3058,8 +3058,7 @@ namespace libtorrent
|
|||
|
||||
#endif
|
||||
|
||||
void torrent::announce_with_tracker(boost::uint8_t e
|
||||
, address const& bind_interface)
|
||||
void torrent::announce_with_tracker(boost::uint8_t e)
|
||||
{
|
||||
TORRENT_ASSERT(is_single_thread());
|
||||
INVARIANT_CHECK;
|
||||
|
@ -3183,8 +3182,6 @@ namespace libtorrent
|
|||
req.triggered_manually = ae.triggered_manually;
|
||||
ae.triggered_manually = false;
|
||||
|
||||
req.bind_ip = bind_interface;
|
||||
|
||||
if (settings().get_bool(settings_pack::force_proxy))
|
||||
{
|
||||
// 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
|
||||
// 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())
|
||||
|| (!is_any(m_ses.get_ipv4_interface().address()) && tracker_ip.is_v6()))
|
||||
&& r.bind_ip != m_ses.get_ipv4_interface().address()
|
||||
|
@ -7630,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
|
||||
|
||||
|
|
11
src/upnp.cpp
11
src/upnp.cpp
|
@ -69,8 +69,11 @@ namespace upnp_errors
|
|||
|
||||
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
|
||||
, address const& listen_interface, std::string const& user_agent
|
||||
, std::string const& user_agent
|
||||
, portmap_callback_t const& cb, log_callback_t const& lcb
|
||||
, bool ignore_nonrouters)
|
||||
: m_user_agent(user_agent)
|
||||
|
@ -90,12 +93,6 @@ upnp::upnp(io_service& ios
|
|||
, m_last_if_update(min_time())
|
||||
{
|
||||
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()
|
||||
|
|
|
@ -100,8 +100,11 @@ bool on_alert(alert const* a)
|
|||
if (peer_disconnected_alert const* e = alert_cast<peer_disconnected_alert>(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<peer_error_alert>(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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -257,24 +257,34 @@ TORRENT_TEST(string)
|
|||
TEST_EQUAL(list[5], "foobar");
|
||||
TEST_EQUAL(list[6], "[::1]");
|
||||
|
||||
std::vector<std::pair<std::string, int> > 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<listen_interface_t> 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
|
||||
|
||||
|
|
Loading…
Reference in New Issue