remove outgoing udp sockets and replace with listen_socket_t
This commit is contained in:
parent
4ceb2ea467
commit
8be7ab559a
|
@ -338,7 +338,6 @@ set(sources
|
||||||
session_handle
|
session_handle
|
||||||
session_impl
|
session_impl
|
||||||
session_settings
|
session_settings
|
||||||
session_udp_sockets
|
|
||||||
proxy_settings
|
proxy_settings
|
||||||
session_stats
|
session_stats
|
||||||
settings_pack
|
settings_pack
|
||||||
|
|
1
Jamfile
1
Jamfile
|
@ -665,7 +665,6 @@ SOURCES =
|
||||||
session_handle
|
session_handle
|
||||||
session_impl
|
session_impl
|
||||||
session_call
|
session_call
|
||||||
session_udp_sockets
|
|
||||||
settings_pack
|
settings_pack
|
||||||
sha1
|
sha1
|
||||||
sha1_hash
|
sha1_hash
|
||||||
|
|
|
@ -77,6 +77,8 @@ namespace libtorrent { namespace aux {
|
||||||
|
|
||||||
listen_socket_t* get() const;
|
listen_socket_t* get() const;
|
||||||
|
|
||||||
|
std::weak_ptr<listen_socket_t> get_ptr() const { return m_sock; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::weak_ptr<listen_socket_t> m_sock;
|
std::weak_ptr<listen_socket_t> m_sock;
|
||||||
};
|
};
|
||||||
|
|
|
@ -137,7 +137,7 @@ namespace aux {
|
||||||
int port = 0;
|
int port = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TORRENT_EXTRA_EXPORT listen_socket_t
|
struct TORRENT_EXTRA_EXPORT listen_socket_t : utp_socket_interface
|
||||||
{
|
{
|
||||||
static constexpr listen_socket_flags_t accept_incoming = 0_bit;
|
static constexpr listen_socket_flags_t accept_incoming = 0_bit;
|
||||||
static constexpr listen_socket_flags_t has_gateway = 1_bit;
|
static constexpr listen_socket_flags_t has_gateway = 1_bit;
|
||||||
|
@ -154,6 +154,13 @@ namespace aux {
|
||||||
listen_socket_t& operator=(listen_socket_t const&) = delete;
|
listen_socket_t& operator=(listen_socket_t const&) = delete;
|
||||||
listen_socket_t& operator=(listen_socket_t&&) = delete;
|
listen_socket_t& operator=(listen_socket_t&&) = delete;
|
||||||
|
|
||||||
|
udp::endpoint get_local_endpoint() override
|
||||||
|
{
|
||||||
|
error_code ec;
|
||||||
|
if (udp_sock) return udp_sock->sock.local_endpoint(ec);
|
||||||
|
return {local_endpoint.address(), local_endpoint.port()};
|
||||||
|
}
|
||||||
|
|
||||||
// returns true if this listen socket/interface can reach and be reached
|
// returns true if this listen socket/interface can reach and be reached
|
||||||
// by the given address. This is useful to know whether it should be
|
// by the given address. This is useful to know whether it should be
|
||||||
// annoucned to a tracker (given the tracker's IP) or whether it should
|
// annoucned to a tracker (given the tracker's IP) or whether it should
|
||||||
|
@ -737,9 +744,8 @@ namespace aux {
|
||||||
mutable std::condition_variable cond;
|
mutable std::condition_variable cond;
|
||||||
|
|
||||||
// implements session_interface
|
// implements session_interface
|
||||||
bool has_udp_outgoing_sockets() const override;
|
tcp::endpoint bind_outgoing_socket(socket_type& s
|
||||||
tcp::endpoint bind_outgoing_socket(socket_type& s, address
|
, address const& remote_address, error_code& ec) const override;
|
||||||
const& remote_address, error_code& ec) const override;
|
|
||||||
bool verify_incoming_interface(address const& addr);
|
bool verify_incoming_interface(address const& addr);
|
||||||
bool verify_bound_address(address const& addr, bool utp
|
bool verify_bound_address(address const& addr, bool utp
|
||||||
, error_code& ec) override;
|
, error_code& ec) override;
|
||||||
|
@ -984,8 +990,6 @@ namespace aux {
|
||||||
// we might need more than one listen socket
|
// we might need more than one listen socket
|
||||||
std::vector<std::shared_ptr<listen_socket_t>> m_listen_sockets;
|
std::vector<std::shared_ptr<listen_socket_t>> m_listen_sockets;
|
||||||
|
|
||||||
outgoing_sockets m_outgoing_sockets;
|
|
||||||
|
|
||||||
#if TORRENT_USE_I2P
|
#if TORRENT_USE_I2P
|
||||||
i2p_connection m_i2p_conn;
|
i2p_connection m_i2p_conn;
|
||||||
std::shared_ptr<socket_type> m_i2p_listen_socket;
|
std::shared_ptr<socket_type> m_i2p_listen_socket;
|
||||||
|
@ -1147,7 +1151,7 @@ namespace aux {
|
||||||
ec = boost::asio::error::bad_descriptor;
|
ec = boost::asio::error::bad_descriptor;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
send_udp_packet_hostname(s->udp_sock, hostname, port, p, ec, flags);
|
send_udp_packet_hostname(sock.get_ptr(), hostname, port, p, ec, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void send_udp_packet(std::weak_ptr<utp_socket_interface> sock
|
void send_udp_packet(std::weak_ptr<utp_socket_interface> sock
|
||||||
|
@ -1168,7 +1172,7 @@ namespace aux {
|
||||||
ec = boost::asio::error::bad_descriptor;
|
ec = boost::asio::error::bad_descriptor;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
send_udp_packet(s->udp_sock, ep, p, ec, flags);
|
send_udp_packet(sock.get_ptr(), ep, p, ec, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_udp_writeable(std::weak_ptr<session_udp_socket> s, error_code const& ec);
|
void on_udp_writeable(std::weak_ptr<session_udp_socket> s, error_code const& ec);
|
||||||
|
|
|
@ -208,7 +208,6 @@ namespace aux {
|
||||||
virtual void for_each_listen_socket(std::function<void(aux::listen_socket_handle const&)> f) = 0;
|
virtual void for_each_listen_socket(std::function<void(aux::listen_socket_handle const&)> f) = 0;
|
||||||
|
|
||||||
// ask for which interface and port to bind outgoing peer connections on
|
// ask for which interface and port to bind outgoing peer connections on
|
||||||
virtual bool has_udp_outgoing_sockets() const = 0;
|
|
||||||
virtual tcp::endpoint bind_outgoing_socket(socket_type& s, address const&
|
virtual tcp::endpoint bind_outgoing_socket(socket_type& s, address const&
|
||||||
remote_address, error_code& ec) const = 0;
|
remote_address, error_code& ec) const = 0;
|
||||||
virtual bool verify_bound_address(address const& addr, bool utp
|
virtual bool verify_bound_address(address const& addr, bool utp
|
||||||
|
|
|
@ -52,12 +52,12 @@ namespace aux {
|
||||||
|
|
||||||
enum class transport : std::uint8_t { plaintext, ssl };
|
enum class transport : std::uint8_t { plaintext, ssl };
|
||||||
|
|
||||||
struct session_udp_socket : utp_socket_interface
|
struct session_udp_socket
|
||||||
{
|
{
|
||||||
explicit session_udp_socket(io_service& ios, listen_socket_handle ls)
|
explicit session_udp_socket(io_service& ios, listen_socket_handle ls)
|
||||||
: sock(ios, std::move(ls)) {}
|
: sock(ios, std::move(ls)) {}
|
||||||
|
|
||||||
udp::endpoint local_endpoint() override { return sock.local_endpoint(); }
|
udp::endpoint local_endpoint() { return sock.local_endpoint(); }
|
||||||
|
|
||||||
udp_socket sock;
|
udp_socket sock;
|
||||||
|
|
||||||
|
@ -72,44 +72,6 @@ namespace aux {
|
||||||
bool write_blocked = false;
|
bool write_blocked = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct outgoing_udp_socket final : session_udp_socket
|
|
||||||
{
|
|
||||||
outgoing_udp_socket(io_service& ios, std::string const& dev, transport ssl_)
|
|
||||||
: session_udp_socket(ios, listen_socket_handle{}), device(dev), ssl(ssl_) {}
|
|
||||||
|
|
||||||
// the name of the device the socket is bound to, may be empty
|
|
||||||
// if the socket is not bound to a device
|
|
||||||
std::string const device;
|
|
||||||
|
|
||||||
// set to true if this is an SSL socket
|
|
||||||
transport const ssl;
|
|
||||||
};
|
|
||||||
|
|
||||||
// sockets used for outgoing utp connections
|
|
||||||
struct TORRENT_EXTRA_EXPORT outgoing_sockets
|
|
||||||
{
|
|
||||||
// partitions sockets based on whether they match one of the given endpoints
|
|
||||||
// all matched sockets are ordered before unmatched sockets
|
|
||||||
// matched endpoints are removed from the vector
|
|
||||||
// returns an iterator to the first unmatched socket
|
|
||||||
std::vector<std::shared_ptr<outgoing_udp_socket>>::iterator
|
|
||||||
partition_outgoing_sockets(std::vector<listen_endpoint_t>& eps);
|
|
||||||
|
|
||||||
tcp::endpoint bind(socket_type& s, address const& remote_address
|
|
||||||
, error_code& ec) const;
|
|
||||||
|
|
||||||
void update_proxy(proxy_settings const& settings, alert_manager& alerts);
|
|
||||||
|
|
||||||
// close all sockets
|
|
||||||
void close();
|
|
||||||
|
|
||||||
std::vector<std::shared_ptr<outgoing_udp_socket>> sockets;
|
|
||||||
private:
|
|
||||||
// round-robin index into sockets
|
|
||||||
// one dimension for IPv4/IPv6 and a second for SSL/non-SSL
|
|
||||||
mutable std::array<std::array<std::uint8_t, 2>, 2> index = {{ {{0, 0}}, {{0, 0}} }};
|
|
||||||
};
|
|
||||||
|
|
||||||
} }
|
} }
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -52,7 +52,7 @@ namespace libtorrent {
|
||||||
// interface/handle to the underlying udp socket
|
// interface/handle to the underlying udp socket
|
||||||
struct TORRENT_EXTRA_EXPORT utp_socket_interface
|
struct TORRENT_EXTRA_EXPORT utp_socket_interface
|
||||||
{
|
{
|
||||||
virtual udp::endpoint local_endpoint() = 0;
|
virtual udp::endpoint get_local_endpoint() = 0;
|
||||||
protected:
|
protected:
|
||||||
virtual ~utp_socket_interface() = default;
|
virtual ~utp_socket_interface() = default;
|
||||||
};
|
};
|
||||||
|
|
|
@ -278,8 +278,6 @@ TORRENT_TEST(socks5_udp_retry)
|
||||||
|
|
||||||
// number of UDP ASSOCIATE commands invoked on the socks proxy
|
// number of UDP ASSOCIATE commands invoked on the socks proxy
|
||||||
// We run for 60 seconds. The sokcks5 retry interval is expected to be 5
|
// We run for 60 seconds. The sokcks5 retry interval is expected to be 5
|
||||||
// seconds, meaning there should have been 12 connection attempts since we
|
// seconds, meaning there should have been 12 connection attempts
|
||||||
// have an outgoing_udp_socket as well, it will also attempt to establish a
|
TEST_EQUAL(socks5.cmd_counts()[2], 12);
|
||||||
// SOCKS5 UDP tunnel, so it will bring it to 24 attempts
|
|
||||||
TEST_EQUAL(socks5.cmd_counts()[2], 24);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,7 +120,6 @@ libtorrent_rasterbar_la_SOURCES = \
|
||||||
session_handle.cpp \
|
session_handle.cpp \
|
||||||
session_impl.cpp \
|
session_impl.cpp \
|
||||||
session_settings.cpp \
|
session_settings.cpp \
|
||||||
session_udp_sockets.cpp \
|
|
||||||
proxy_settings.cpp \
|
proxy_settings.cpp \
|
||||||
settings_pack.cpp \
|
settings_pack.cpp \
|
||||||
sha1_hash.cpp \
|
sha1_hash.cpp \
|
||||||
|
|
|
@ -333,7 +333,7 @@ namespace aux {
|
||||||
|
|
||||||
bool listen_socket_t::can_route(address const& addr) const
|
bool listen_socket_t::can_route(address const& addr) const
|
||||||
{
|
{
|
||||||
if (local_endpoint.address().is_v4() != addr.is_v4()) return false;
|
if (is_v4(local_endpoint) != addr.is_v4()) return false;
|
||||||
|
|
||||||
if (local_endpoint.address().is_v6()
|
if (local_endpoint.address().is_v6()
|
||||||
&& local_endpoint.address().to_v6().scope_id() != addr.to_v6().scope_id())
|
&& local_endpoint.address().to_v6().scope_id() != addr.to_v6().scope_id())
|
||||||
|
@ -654,7 +654,6 @@ namespace aux {
|
||||||
// apply all m_settings to this session
|
// apply all m_settings to this session
|
||||||
run_all_updates(*this);
|
run_all_updates(*this);
|
||||||
reopen_listen_sockets(false);
|
reopen_listen_sockets(false);
|
||||||
reopen_outgoing_sockets();
|
|
||||||
|
|
||||||
#if TORRENT_USE_INVARIANT_CHECKS
|
#if TORRENT_USE_INVARIANT_CHECKS
|
||||||
check_invariant();
|
check_invariant();
|
||||||
|
@ -978,8 +977,6 @@ namespace aux {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_outgoing_sockets.close();
|
|
||||||
|
|
||||||
// we need to give all the sockets an opportunity to actually have their handlers
|
// we need to give all the sockets an opportunity to actually have their handlers
|
||||||
// called and cancelled before we continue the shutdown. This is a bit
|
// called and cancelled before we continue the shutdown. This is a bit
|
||||||
// complicated, if there are no "undead" peers, it's safe to resume the
|
// complicated, if there are no "undead" peers, it's safe to resume the
|
||||||
|
@ -1345,11 +1342,6 @@ namespace aux {
|
||||||
&& pack.get_str(settings_pack::listen_interfaces)
|
&& pack.get_str(settings_pack::listen_interfaces)
|
||||||
!= m_settings.get_str(settings_pack::listen_interfaces));
|
!= m_settings.get_str(settings_pack::listen_interfaces));
|
||||||
|
|
||||||
bool const reopen_outgoing_port =
|
|
||||||
(pack.has_val(settings_pack::outgoing_interfaces)
|
|
||||||
&& pack.get_str(settings_pack::outgoing_interfaces)
|
|
||||||
!= m_settings.get_str(settings_pack::outgoing_interfaces));
|
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
#ifndef TORRENT_DISABLE_LOGGING
|
||||||
session_log("applying settings pack, reopen_listen_port=%s"
|
session_log("applying settings pack, reopen_listen_port=%s"
|
||||||
, reopen_listen_port ? "true" : "false");
|
, reopen_listen_port ? "true" : "false");
|
||||||
|
@ -1369,9 +1361,6 @@ namespace aux {
|
||||||
{
|
{
|
||||||
reopen_listen_sockets();
|
reopen_listen_sockets();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reopen_outgoing_port)
|
|
||||||
reopen_outgoing_sockets();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<listen_socket_t> session_impl::setup_listener(
|
std::shared_ptr<listen_socket_t> session_impl::setup_listener(
|
||||||
|
@ -2030,139 +2019,9 @@ namespace aux {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void session_impl::reopen_outgoing_sockets()
|
|
||||||
{
|
|
||||||
// first build a list of endpoints we should be listening on
|
|
||||||
// we need to remove any unneeded sockets first to avoid the possibility
|
|
||||||
// of a new socket failing to bind due to a conflict with a stale socket
|
|
||||||
std::vector<listen_endpoint_t> eps;
|
|
||||||
|
|
||||||
for (auto const& iface : m_outgoing_interfaces)
|
|
||||||
{
|
|
||||||
interface_to_endpoints(iface, 0, transport::plaintext, listen_socket_t::accept_incoming, eps);
|
|
||||||
#ifdef TORRENT_USE_OPENSSL
|
|
||||||
interface_to_endpoints(iface, 0, transport::ssl, listen_socket_t::accept_incoming, eps);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// if no outgoing interfaces are specified, create sockets to use
|
|
||||||
// any interface
|
|
||||||
if (eps.empty())
|
|
||||||
{
|
|
||||||
eps.emplace_back(address_v4(), 0, "", transport::plaintext, listen_socket_flags_t{});
|
|
||||||
eps.emplace_back(address_v6(), 0, "", transport::plaintext, listen_socket_flags_t{});
|
|
||||||
#ifdef TORRENT_USE_OPENSSL
|
|
||||||
eps.emplace_back(address_v4(), 0, "", transport::ssl, listen_socket_flags_t{});
|
|
||||||
eps.emplace_back(address_v6(), 0, "", transport::ssl, listen_socket_flags_t{});
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
auto remove_iter = m_outgoing_sockets.partition_outgoing_sockets(eps);
|
|
||||||
|
|
||||||
for (auto i = remove_iter; i != m_outgoing_sockets.sockets.end(); ++i)
|
|
||||||
{
|
|
||||||
auto& remove_sock = *i;
|
|
||||||
m_utp_socket_manager.remove_udp_socket(remove_sock);
|
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
|
||||||
if (should_log())
|
|
||||||
{
|
|
||||||
session_log("Closing outgoing UDP socket for %s on device \"%s\""
|
|
||||||
, print_endpoint(remove_sock->local_endpoint()).c_str()
|
|
||||||
, remove_sock->device.c_str());
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
remove_sock->sock.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_outgoing_sockets.sockets.erase(remove_iter, m_outgoing_sockets.sockets.end());
|
|
||||||
|
|
||||||
// open new sockets on any endpoints that didn't match with
|
|
||||||
// an existing socket
|
|
||||||
for (auto const& ep : eps)
|
|
||||||
{
|
|
||||||
error_code ec;
|
|
||||||
udp::endpoint const udp_bind_ep(ep.addr, 0);
|
|
||||||
|
|
||||||
auto udp_sock = std::make_shared<outgoing_udp_socket>(m_io_service, ep.device, ep.ssl);
|
|
||||||
udp_sock->sock.open(udp_bind_ep.protocol(), ec);
|
|
||||||
if (ec)
|
|
||||||
{
|
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
|
||||||
if (should_log())
|
|
||||||
{
|
|
||||||
session_log("failed to open UDP socket: %s: %s"
|
|
||||||
, ep.device.c_str(), ec.message().c_str());
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (m_alerts.should_post<udp_error_alert>())
|
|
||||||
m_alerts.emplace_alert<udp_error_alert>(udp_bind_ep
|
|
||||||
, operation_t::sock_open, ec);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if TORRENT_HAS_BINDTODEVICE
|
|
||||||
if (!ep.device.empty())
|
|
||||||
{
|
|
||||||
udp_sock->sock.set_option(bind_to_device(ep.device.c_str()), ec);
|
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
|
||||||
if (ec && should_log())
|
|
||||||
{
|
|
||||||
session_log("bind to device failed (device: %s): %s"
|
|
||||||
, ep.device.c_str(), ec.message().c_str());
|
|
||||||
}
|
|
||||||
#endif // TORRENT_DISABLE_LOGGING
|
|
||||||
ec.clear();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
udp_sock->sock.bind(udp_bind_ep, ec);
|
|
||||||
|
|
||||||
if (ec)
|
|
||||||
{
|
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
|
||||||
if (should_log())
|
|
||||||
{
|
|
||||||
session_log("failed to bind UDP socket: %s: %s"
|
|
||||||
, ep.device.c_str(), ec.message().c_str());
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (m_alerts.should_post<udp_error_alert>())
|
|
||||||
m_alerts.emplace_alert<udp_error_alert>(udp_bind_ep
|
|
||||||
, operation_t::sock_bind, ec);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
error_code err;
|
|
||||||
set_socket_buffer_size(udp_sock->sock, m_settings, err);
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
if (m_alerts.should_post<udp_error_alert>())
|
|
||||||
m_alerts.emplace_alert<udp_error_alert>(udp_sock->sock.local_endpoint(ec)
|
|
||||||
, operation_t::alloc_recvbuf, err);
|
|
||||||
}
|
|
||||||
|
|
||||||
// this call is necessary here because, unless the settings actually
|
|
||||||
// change after the session is up and listening, at no other point
|
|
||||||
// set_proxy_settings is called with the correct proxy configuration,
|
|
||||||
// internally, this method handle the SOCKS5's connection logic
|
|
||||||
udp_sock->sock.set_proxy_settings(proxy(), m_alerts);
|
|
||||||
|
|
||||||
ADD_OUTSTANDING_ASYNC("session_impl::on_udp_packet");
|
|
||||||
udp_sock->sock.async_read(aux::make_handler(std::bind(&session_impl::on_udp_packet
|
|
||||||
, this, udp_sock, std::weak_ptr<listen_socket_t>(), ep.ssl, _1)
|
|
||||||
, udp_sock->udp_handler_storage, *this));
|
|
||||||
|
|
||||||
if (!ec && udp_sock)
|
|
||||||
{
|
|
||||||
m_outgoing_sockets.sockets.push_back(udp_sock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void session_impl::reopen_network_sockets(reopen_network_flags_t const options)
|
void session_impl::reopen_network_sockets(reopen_network_flags_t const options)
|
||||||
{
|
{
|
||||||
reopen_listen_sockets(bool(options & session_handle::reopen_map_ports));
|
reopen_listen_sockets(bool(options & session_handle::reopen_map_ports));
|
||||||
reopen_outgoing_sockets();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -2333,7 +2192,7 @@ namespace aux {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto s = std::static_pointer_cast<session_udp_socket>(si);
|
auto s = std::static_pointer_cast<aux::listen_socket_t>(si)->udp_sock;
|
||||||
|
|
||||||
s->sock.send_hostname(hostname, port, p, ec, flags);
|
s->sock.send_hostname(hostname, port, p, ec, flags);
|
||||||
|
|
||||||
|
@ -2360,7 +2219,7 @@ namespace aux {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto s = std::static_pointer_cast<session_udp_socket>(si);
|
auto s = std::static_pointer_cast<aux::listen_socket_t>(si)->udp_sock;
|
||||||
|
|
||||||
TORRENT_ASSERT(s->sock.is_closed() || s->sock.local_endpoint().protocol() == ep.protocol());
|
TORRENT_ASSERT(s->sock.is_closed() || s->sock.local_endpoint().protocol() == ep.protocol());
|
||||||
|
|
||||||
|
@ -2474,7 +2333,7 @@ namespace aux {
|
||||||
|
|
||||||
// give the uTP socket manager first dibs on the packet. Presumably
|
// give the uTP socket manager first dibs on the packet. Presumably
|
||||||
// the majority of packets are uTP packets.
|
// the majority of packets are uTP packets.
|
||||||
if (!mgr.incoming_packet(socket, packet.from, buf))
|
if (!mgr.incoming_packet(ls, packet.from, buf))
|
||||||
{
|
{
|
||||||
// if it wasn't a uTP packet, try the other users of the UDP
|
// if it wasn't a uTP packet, try the other users of the UDP
|
||||||
// socket
|
// socket
|
||||||
|
@ -5031,13 +4890,8 @@ namespace aux {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool session_impl::has_udp_outgoing_sockets() const
|
tcp::endpoint session_impl::bind_outgoing_socket(socket_type& s
|
||||||
{
|
, address const& remote_address, error_code& ec) const
|
||||||
return !m_outgoing_sockets.sockets.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
tcp::endpoint session_impl::bind_outgoing_socket(socket_type& s, address
|
|
||||||
const& remote_address, error_code& ec) const
|
|
||||||
{
|
{
|
||||||
tcp::endpoint bind_ep(address_v4(), 0);
|
tcp::endpoint bind_ep(address_v4(), 0);
|
||||||
if (m_settings.get_int(settings_pack::outgoing_port) > 0)
|
if (m_settings.get_int(settings_pack::outgoing_port) > 0)
|
||||||
|
@ -5060,9 +4914,46 @@ namespace aux {
|
||||||
|
|
||||||
if (is_utp(s))
|
if (is_utp(s))
|
||||||
{
|
{
|
||||||
auto const ep = m_outgoing_sockets.bind(s, remote_address, ec);
|
// TODO: factor out this logic into a separate function for unit
|
||||||
if (ep.port() != 0 || ec)
|
// testing
|
||||||
return ep;
|
|
||||||
|
utp_socket_impl* impl = nullptr;
|
||||||
|
transport ssl = transport::plaintext;
|
||||||
|
#ifdef TORRENT_USE_OPENSSL
|
||||||
|
if (s.get<ssl_stream<utp_stream>>() != nullptr)
|
||||||
|
{
|
||||||
|
impl = s.get<ssl_stream<utp_stream>>()->next_layer().get_impl();
|
||||||
|
ssl = transport::ssl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
impl = s.get<utp_stream>()->get_impl();
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<listen_socket_t>> with_gateways;
|
||||||
|
std::shared_ptr<listen_socket_t> match;
|
||||||
|
for (auto& ls : m_listen_sockets)
|
||||||
|
{
|
||||||
|
if (is_v4(ls->local_endpoint) != remote_address.is_v4()) continue;
|
||||||
|
if (ls->ssl != ssl) continue;
|
||||||
|
if (ls->flags & listen_socket_t::has_gateway)
|
||||||
|
with_gateways.push_back(ls);
|
||||||
|
|
||||||
|
if (match_addr_mask(ls->local_endpoint.address(), remote_address, ls->netmask))
|
||||||
|
{
|
||||||
|
// is this better than the previous match?
|
||||||
|
match = ls;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!match && !with_gateways.empty())
|
||||||
|
match = with_gateways[random(with_gateways.size() - 1)];
|
||||||
|
|
||||||
|
if (match)
|
||||||
|
{
|
||||||
|
utp_init_socket(impl, match);
|
||||||
|
return match->local_endpoint;
|
||||||
|
}
|
||||||
|
ec.assign(boost::system::errc::not_supported, generic_category());
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_outgoing_interfaces.empty())
|
if (!m_outgoing_interfaces.empty())
|
||||||
|
@ -5333,7 +5224,6 @@ namespace aux {
|
||||||
{
|
{
|
||||||
for (auto& i : m_listen_sockets)
|
for (auto& i : m_listen_sockets)
|
||||||
i->udp_sock->sock.set_proxy_settings(proxy(), m_alerts);
|
i->udp_sock->sock.set_proxy_settings(proxy(), m_alerts);
|
||||||
m_outgoing_sockets.update_proxy(proxy(), m_alerts);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void session_impl::update_ip_notifier()
|
void session_impl::update_ip_notifier()
|
||||||
|
|
|
@ -1,123 +0,0 @@
|
||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2017, Arvid Norberg, Steven Siloti
|
|
||||||
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.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "libtorrent/aux_/session_udp_sockets.hpp"
|
|
||||||
#include "libtorrent/aux_/session_impl.hpp"
|
|
||||||
#include "libtorrent/error_code.hpp"
|
|
||||||
|
|
||||||
namespace libtorrent { namespace aux {
|
|
||||||
|
|
||||||
std::vector<std::shared_ptr<outgoing_udp_socket>>::iterator
|
|
||||||
outgoing_sockets::partition_outgoing_sockets(std::vector<listen_endpoint_t>& eps)
|
|
||||||
{
|
|
||||||
return std::partition(sockets.begin(), sockets.end()
|
|
||||||
, [&eps](std::shared_ptr<outgoing_udp_socket> const& sock)
|
|
||||||
{
|
|
||||||
auto match = std::find_if(eps.begin(), eps.end()
|
|
||||||
, [&sock](listen_endpoint_t const& ep)
|
|
||||||
{
|
|
||||||
return ep.device == sock->device
|
|
||||||
&& ep.addr == sock->sock.local_endpoint().address()
|
|
||||||
&& ep.ssl == sock->ssl;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (match != eps.end())
|
|
||||||
{
|
|
||||||
// remove the matched endpoint to signal the caller that it
|
|
||||||
// doesn't need to create a socket for the endpoint
|
|
||||||
eps.erase(match);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
tcp::endpoint outgoing_sockets::bind(socket_type& s
|
|
||||||
, address const& remote_address, error_code& ec) const
|
|
||||||
{
|
|
||||||
if (sockets.empty())
|
|
||||||
{
|
|
||||||
ec.assign(boost::system::errc::not_supported, generic_category());
|
|
||||||
return tcp::endpoint();
|
|
||||||
}
|
|
||||||
|
|
||||||
utp_socket_impl* impl = nullptr;
|
|
||||||
transport ssl = transport::plaintext;
|
|
||||||
#ifdef TORRENT_USE_OPENSSL
|
|
||||||
if (s.get<ssl_stream<utp_stream>>() != nullptr)
|
|
||||||
{
|
|
||||||
impl = s.get<ssl_stream<utp_stream>>()->next_layer().get_impl();
|
|
||||||
ssl = transport::ssl;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
impl = s.get<utp_stream>()->get_impl();
|
|
||||||
|
|
||||||
auto& idx = index[remote_address.is_v4() ? 0 : 1][ssl == transport::ssl ? 1 : 0];
|
|
||||||
auto const index_begin = idx;
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if (++idx >= sockets.size())
|
|
||||||
idx = 0;
|
|
||||||
|
|
||||||
if (is_v4(sockets[idx]->local_endpoint()) != remote_address.is_v4()
|
|
||||||
|| sockets[idx]->ssl != ssl)
|
|
||||||
{
|
|
||||||
if (idx == index_begin) break;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
utp_init_socket(impl, sockets[idx]);
|
|
||||||
auto udp_ep = sockets[idx]->local_endpoint();
|
|
||||||
return tcp::endpoint(udp_ep.address(), udp_ep.port());
|
|
||||||
}
|
|
||||||
|
|
||||||
return tcp::endpoint();
|
|
||||||
}
|
|
||||||
|
|
||||||
void outgoing_sockets::update_proxy(proxy_settings const& settings, alert_manager& alerts)
|
|
||||||
{
|
|
||||||
for (auto const& i : sockets)
|
|
||||||
i->sock.set_proxy_settings(settings, alerts);
|
|
||||||
}
|
|
||||||
|
|
||||||
void outgoing_sockets::close()
|
|
||||||
{
|
|
||||||
for (auto const& l : sockets)
|
|
||||||
l->sock.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
} }
|
|
|
@ -6617,8 +6617,7 @@ bool is_downloading_state(int const st)
|
||||||
if (settings().get_bool(settings_pack::enable_outgoing_utp)
|
if (settings().get_bool(settings_pack::enable_outgoing_utp)
|
||||||
&& (!settings().get_bool(settings_pack::enable_outgoing_tcp)
|
&& (!settings().get_bool(settings_pack::enable_outgoing_tcp)
|
||||||
|| peerinfo->supports_utp
|
|| peerinfo->supports_utp
|
||||||
|| peerinfo->confirmed_supports_utp)
|
|| peerinfo->confirmed_supports_utp))
|
||||||
&& m_ses.has_udp_outgoing_sockets())
|
|
||||||
{
|
{
|
||||||
sm = m_ses.utp_socket_manager();
|
sm = m_ses.utp_socket_manager();
|
||||||
}
|
}
|
||||||
|
|
|
@ -821,7 +821,7 @@ utp_stream::endpoint_type utp_stream::local_endpoint(error_code& ec) const
|
||||||
return endpoint_type();
|
return endpoint_type();
|
||||||
}
|
}
|
||||||
|
|
||||||
udp::endpoint ep = s->local_endpoint();
|
udp::endpoint ep = s->get_local_endpoint();
|
||||||
return endpoint_type(ep.address(), ep.port());
|
return endpoint_type(ep.address(), ep.port());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue