use a handle class for listen sockets instead of raw pointers

Listen socket handles need to be week_ptr so that they can detect when a listen
socket is removed in the middle of a tracker announce on it. Use a wrapper class
to enforce that no one outside of session_impl can hold ownership of the socket
across event boundaries.

To support unit tests, listen_socket_t is also split into a base class which
holds the members needed to support the public listen socket API.
This commit is contained in:
Steven Siloti 2017-07-20 20:19:28 -07:00
parent e0dcd34352
commit f0ae2145ea
29 changed files with 331 additions and 225 deletions

View File

@ -48,6 +48,7 @@ set(sources
ip_filter
ip_notifier
ip_voter
listen_socket_handle
performance_counters
peer_class
peer_class_set

View File

@ -604,6 +604,7 @@ SOURCES =
ip_filter
ip_notifier
ip_voter
listen_socket_handle
merkle
peer_connection
platform_util

View File

@ -174,12 +174,12 @@ nobase_include_HEADERS = \
aux_/deque.hpp \
aux_/escape_string.hpp \
aux_/io.hpp \
aux_/listen_socket_handle.hpp \
aux_/max_path.hpp \
aux_/path.hpp \
aux_/merkle.hpp \
aux_/session_call.hpp \
aux_/session_impl.hpp \
aux_/session_listen_socket.hpp \
aux_/session_settings.hpp \
aux_/session_udp_sockets.hpp \
aux_/proxy_settings.hpp \

View File

@ -38,6 +38,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/error_code.hpp"
#include "libtorrent/string_view.hpp"
#include "libtorrent/socket.hpp"
#include "libtorrent/aux_/listen_socket_handle.hpp"
#include <string>
#include <cstdint>
@ -45,8 +46,6 @@ POSSIBILITY OF SUCH DAMAGE.
namespace libtorrent {
namespace aux { struct session_listen_socket; }
// announces are sent to each tracker using every listen socket
// this class holds information about one listen socket for one tracker
struct TORRENT_EXPORT announce_endpoint
@ -55,7 +54,7 @@ namespace libtorrent {
friend struct announce_entry;
// internal
explicit announce_endpoint(aux::session_listen_socket* s);
explicit announce_endpoint(aux::listen_socket_handle const& s);
// if this tracker has returned an error or warning message
// that message is stored here
@ -76,7 +75,7 @@ namespace libtorrent {
private:
// internal
aux::session_listen_socket* socket;
aux::listen_socket_handle socket;
public:
// TODO: include the number of peers received from this tracker, at last
@ -227,7 +226,7 @@ namespace libtorrent {
#endif
// internal
announce_endpoint* find_endpoint(aux::session_listen_socket* s);
announce_endpoint* find_endpoint(aux::listen_socket_handle const& s);
// trims whitespace characters from the beginning of the URL.
void trim();

View File

@ -0,0 +1,101 @@
/*
Copyright (c) 2017, 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.
*/
#ifndef TORRENT_LISTEN_SOCKET_HANDLE_HPP_INCLUDED
#define TORRENT_LISTEN_SOCKET_HANDLE_HPP_INCLUDED
#include "libtorrent/address.hpp"
#include "libtorrent/socket.hpp" // for tcp::endpoint
#include "libtorrent/ip_voter.hpp"
#include "libtorrent/aux_/session_udp_sockets.hpp"
#include <memory>
namespace libtorrent { namespace aux {
struct listen_socket_base
{
// this may be empty but can be set
// to the WAN IP address of a NAT router
ip_voter external_address;
// this is a cached local endpoint for the listen TCP socket
tcp::endpoint local_endpoint;
// indicates whether this is an SSL listen socket or not
transport ssl = transport::plaintext;
};
struct TORRENT_EXTRA_EXPORT listen_socket_handle
{
friend struct session_impl;
listen_socket_handle() {}
listen_socket_handle(std::shared_ptr<listen_socket_base> s) // NOLINT
: m_sock(s)
{}
explicit operator bool() const { return !m_sock.expired(); }
address get_external_address() const;
tcp::endpoint get_local_endpoint() const;
bool is_ssl() const;
bool operator==(listen_socket_handle const& o) const
{
return !m_sock.owner_before(o.m_sock) && !o.m_sock.owner_before(m_sock);
}
bool operator!=(listen_socket_handle const& o) const
{
return !(*this == o);
}
bool operator<(listen_socket_handle const& o) const
{ return m_sock.owner_before(o.m_sock); }
listen_socket_handle& operator=(listen_socket_handle const& o)
{
m_sock = o.m_sock;
return *this;
}
listen_socket_base* impl() const;
private:
std::weak_ptr<listen_socket_base> m_sock;
};
} }
#endif

View File

@ -48,7 +48,6 @@ POSSIBILITY OF SUCH DAMAGE.
#endif
#include "libtorrent/session.hpp" // for user_load_function_t
#include "libtorrent/ip_voter.hpp"
#include "libtorrent/entry.hpp"
#include "libtorrent/socket.hpp"
#include "libtorrent/peer_id.hpp"
@ -133,7 +132,7 @@ namespace aux {
TORRENT_EXTRA_EXPORT entry save_dht_settings(dht_settings const& settings);
#endif
struct listen_socket_t final : aux::session_listen_socket
struct listen_socket_t : listen_socket_base
{
listen_socket_t()
{
@ -148,22 +147,6 @@ namespace aux {
listen_socket_t& operator=(listen_socket_t const&) = delete;
listen_socket_t& operator=(listen_socket_t&&) = delete;
address get_external_address() override
{ return external_address.external_address(); }
tcp::endpoint get_local_endpoint() override
{ return local_endpoint; }
bool is_ssl() override
{ return ssl == transport::ssl; }
// this may be empty but can be set
// to the WAN IP address of a NAT router
ip_voter external_address;
// this is a cached local endpoint for the listen TCP socket
tcp::endpoint local_endpoint;
// the name of the device the socket is bound to, may be empty
// if the socket is not bound to a device
std::string device;
@ -187,14 +170,13 @@ namespace aux {
int tcp_port_mapping[2];
int udp_port_mapping[2];
// indicates whether this is an SSL listen socket or not
transport ssl = transport::plaintext;
// the actual sockets (TCP listen socket and UDP socket)
// An entry does not necessarily have a UDP or TCP socket. One of these
// pointers may be nullptr!
// These must be shared_ptr to avoid a dangling reference if an
// incoming packet is in the event queue when the socket is erased
// TODO: make these direct members and generate shared_ptrs to them
// which alias the listen_socket_t shared_ptr
std::shared_ptr<tcp::acceptor> sock;
std::shared_ptr<aux::session_udp_socket> udp_sock;
};
@ -584,11 +566,11 @@ namespace aux {
std::uint16_t ssl_listen_port() const override;
std::uint16_t ssl_listen_port(listen_socket_t* sock) const;
void for_each_listen_socket(std::function<void(aux::session_listen_socket*)> f) override
void for_each_listen_socket(std::function<void(aux::listen_socket_handle const&)> f) override
{
for (auto& s : m_listen_sockets)
{
f(s.get());
f(listen_socket_handle(s));
}
}
@ -656,7 +638,7 @@ namespace aux {
int send_buffer_size() const override { return send_buffer_size_impl; }
// implements dht_observer
virtual void set_external_address(aux::session_listen_socket* iface
virtual void set_external_address(aux::listen_socket_handle const& iface
, address const& ip, address const& source) override;
virtual void get_peers(sha1_hash const& ih) override;
virtual void announce(sha1_hash const& ih, address const& addr, int port) override;
@ -778,7 +760,7 @@ namespace aux {
void on_lsd_peer(tcp::endpoint const& peer, sha1_hash const& ih) override;
void setup_socket_buffers(socket_type& s) override;
void set_external_address(listen_socket_t& sock, address const& ip
void set_external_address(std::shared_ptr<listen_socket_t> const& sock, address const& ip
, int const source_type, address const& source);
void interface_to_endpoints(std::string const& device, int const port
@ -1098,14 +1080,19 @@ namespace aux {
, error_code& ec
, int flags);
void send_udp_packet_hostname_listen(aux::session_listen_socket* sock
void send_udp_packet_hostname_listen(aux::listen_socket_handle const& sock
, char const* hostname
, int port
, span<char const> p
, error_code& ec
, int flags)
{
listen_socket_t* s = static_cast<listen_socket_t*>(sock);
auto s = static_cast<listen_socket_t*>(sock.impl());
if (!s)
{
ec = boost::asio::error::bad_descriptor;
return;
}
send_udp_packet_hostname(s->udp_sock, hostname, port, p, ec, flags);
}
@ -1115,13 +1102,18 @@ namespace aux {
, error_code& ec
, int flags);
void send_udp_packet_listen(aux::session_listen_socket* sock
void send_udp_packet_listen(aux::listen_socket_handle const& sock
, udp::endpoint const& ep
, span<char const> p
, error_code& ec
, int flags)
{
listen_socket_t* s = static_cast<listen_socket_t*>(sock);
auto s = static_cast<listen_socket_t*>(sock.impl());
if (!s)
{
ec = boost::asio::error::bad_descriptor;
return;
}
send_udp_packet(s->udp_sock, ep, p, ec, flags);
}

View File

@ -42,7 +42,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/error_code.hpp"
#include "libtorrent/socket.hpp" // for tcp::endpoint
#include "libtorrent/aux_/vector.hpp"
#include "libtorrent/aux_/session_listen_socket.hpp"
#include "libtorrent/aux_/listen_socket_handle.hpp"
#include <functional>
#include <memory>
@ -198,7 +198,7 @@ namespace libtorrent { namespace aux {
virtual std::uint16_t listen_port() const = 0;
virtual std::uint16_t ssl_listen_port() const = 0;
virtual void for_each_listen_socket(std::function<void(aux::session_listen_socket*)> 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
virtual tcp::endpoint bind_outgoing_socket(socket_type& s, address const&

View File

@ -323,6 +323,8 @@ namespace libtorrent {
banned_by_port_filter,
// The session_handle is not referring to a valid session_impl
invalid_session_handle,
// the listen socket associated with this request was closed
invalid_listen_socket,
// The NAT-PMP router responded with an unsupported protocol version

View File

@ -39,7 +39,7 @@ POSSIBILITY OF SUCH DAMAGE.
namespace libtorrent {
namespace aux { struct session_listen_socket; }
namespace aux { struct listen_socket_handle; }
namespace dht {
@ -73,7 +73,7 @@ namespace dht {
struct TORRENT_EXTRA_EXPORT dht_observer : dht_logger
{
virtual void set_external_address(aux::session_listen_socket* iface
virtual void set_external_address(aux::listen_socket_handle const& iface
, address const& addr, address const& source) = 0;
virtual void get_peers(sha1_hash const& ih) = 0;
virtual void outgoing_get_peers(sha1_hash const& target

View File

@ -39,7 +39,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <libtorrent/kademlia/dos_blocker.hpp>
#include <libtorrent/kademlia/dht_state.hpp>
#include <libtorrent/aux_/session_listen_socket.hpp>
#include <libtorrent/aux_/listen_socket_handle.hpp>
#include <libtorrent/socket.hpp>
#include <libtorrent/deadline_timer.hpp>
#include <libtorrent/span.hpp>
@ -61,7 +61,7 @@ namespace libtorrent { namespace dht {
, std::enable_shared_from_this<dht_tracker>
{
using send_fun_t = std::function<void(
aux::session_listen_socket*, udp::endpoint const&
aux::listen_socket_handle const&, udp::endpoint const&
, span<char const>, error_code&, int)>;
dht_tracker(dht_observer* observer
@ -84,10 +84,10 @@ namespace libtorrent { namespace dht {
// tell the node to recalculate its node id based on the current
// understanding of its external address (which may have changed)
void update_node_id(aux::session_listen_socket* s);
void update_node_id(aux::listen_socket_handle const& s);
void new_socket(aux::session_listen_socket* s);
void delete_socket(aux::session_listen_socket* s);
void new_socket(aux::listen_socket_handle const& s);
void delete_socket(aux::listen_socket_handle const& s);
void add_node(udp::endpoint const& node);
void add_router_node(udp::endpoint const& node);
@ -147,7 +147,7 @@ namespace libtorrent { namespace dht {
struct tracker_node
{
tracker_node(io_service& ios
, aux::session_listen_socket* s, socket_manager* sock
, aux::listen_socket_handle const& s, socket_manager* sock
, libtorrent::dht_settings const& settings
, node_id const& nid
, dht_observer* observer, counters& cnt
@ -157,12 +157,12 @@ namespace libtorrent { namespace dht {
node dht;
deadline_timer connection_timer;
};
using tracker_nodes_t = std::map<aux::session_listen_socket*, tracker_node>;
using tracker_nodes_t = std::map<aux::listen_socket_handle, tracker_node>;
std::shared_ptr<dht_tracker> self()
{ return shared_from_this(); }
void connection_timeout(aux::session_listen_socket* s, error_code const& e);
void connection_timeout(aux::listen_socket_handle const& s, error_code const& e);
void refresh_timeout(error_code const& e);
void refresh_key(error_code const& e);
void update_storage_node_ids();
@ -170,7 +170,7 @@ namespace libtorrent { namespace dht {
// implements socket_manager
virtual bool has_quota() override;
virtual bool send_packet(aux::session_listen_socket* s, entry& e, udp::endpoint const& addr) override;
virtual bool send_packet(aux::listen_socket_handle const& s, entry& e, udp::endpoint const& addr) override;
// this is the bdecode_node DHT messages are parsed into. It's a member
// in order to avoid having to deallocate and re-allocate it for every

View File

@ -48,13 +48,13 @@ POSSIBILITY OF SUCH DAMAGE.
#include <libtorrent/socket.hpp> // for udp::endpoint
#include <libtorrent/string_view.hpp>
#include <libtorrent/aux_/listen_socket_handle.hpp>
namespace libtorrent {
struct counters;
struct dht_routing_bucket;
struct dht_settings;
namespace aux { struct session_listen_socket; }
}
namespace libtorrent { namespace dht {
@ -79,7 +79,7 @@ public:
struct socket_manager
{
virtual bool has_quota() = 0;
virtual bool send_packet(aux::session_listen_socket* s, entry& e, udp::endpoint const& addr) = 0;
virtual bool send_packet(aux::listen_socket_handle const& s, entry& e, udp::endpoint const& addr) = 0;
protected:
~socket_manager() = default;
};
@ -90,7 +90,7 @@ using get_foreign_node_t = std::function<node*(node_id const&, std::string const
class TORRENT_EXTRA_EXPORT node : boost::noncopyable
{
public:
node(aux::session_listen_socket* sock, socket_manager* sock_man
node(aux::listen_socket_handle const& sock, socket_manager* sock_man
, libtorrent::dht_settings const& settings
, node_id const& nid
, dht_observer* observer, counters& cnt
@ -266,7 +266,7 @@ private:
std::uint32_t m_secret[2];
socket_manager* m_sock_man;
aux::session_listen_socket* m_sock;
aux::listen_socket_handle m_sock;
counters& m_counters;
dht_storage_interface& m_storage;

View File

@ -44,8 +44,9 @@ POSSIBILITY OF SUCH DAMAGE.
#include <libtorrent/time.hpp>
#include <libtorrent/kademlia/node_id.hpp>
#include <libtorrent/kademlia/observer.hpp>
#include <libtorrent/aux_/listen_socket_handle.hpp>
namespace libtorrent { struct dht_settings; class entry; namespace aux { struct session_listen_socket; } }
namespace libtorrent { struct dht_settings; class entry; }
namespace libtorrent { namespace dht {
@ -68,7 +69,7 @@ public:
rpc_manager(node_id const& our_id
, dht_settings const& settings
, routing_table& table
, aux::session_listen_socket* sock
, aux::listen_socket_handle const& sock
, socket_manager* sock_man
, dht_logger* log);
~rpc_manager();
@ -119,7 +120,7 @@ private:
std::unordered_multimap<int, observer_ptr> m_transactions;
aux::session_listen_socket* m_sock;
aux::listen_socket_handle m_sock;
socket_manager* m_sock_man;
#ifndef TORRENT_DISABLE_LOGGING
dht_logger* m_log;

View File

@ -62,6 +62,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/time.hpp"
#include "libtorrent/debug.hpp"
#include "libtorrent/error_code.hpp"
#include "libtorrent/aux_/listen_socket_handle.hpp"
namespace libtorrent {
@ -76,7 +77,7 @@ namespace libtorrent {
#if TORRENT_USE_I2P
class i2p_connection;
#endif
namespace aux { struct session_listen_socket; struct session_logger; struct session_settings; }
namespace aux { struct session_logger; struct session_settings; }
// returns -1 if gzip header is invalid or the header size in bytes
TORRENT_EXTRA_EXPORT int gzip_header(const char* buf, int size);
@ -94,7 +95,6 @@ namespace libtorrent {
, kind(announce_request)
, key(0)
, num_want(0)
, outgoing_socket(nullptr)
, private_torrent(false)
, triggered_manually(false)
#ifdef TORRENT_USE_OPENSSL
@ -152,7 +152,7 @@ namespace libtorrent {
#endif
sha1_hash info_hash;
peer_id pid;
aux::session_listen_socket* outgoing_socket;
aux::listen_socket_handle outgoing_socket;
// set to true if the .torrent file this tracker announce is for is marked
// as private (i.e. has the "priv": 1 key)
@ -308,7 +308,7 @@ namespace libtorrent {
virtual void start() = 0;
virtual void close() = 0;
address bind_interface() const;
aux::session_listen_socket* bind_socket() const { return m_req.outgoing_socket; }
aux::listen_socket_handle const& bind_socket() const { return m_req.outgoing_socket; }
void sent_bytes(int bytes);
void received_bytes(int bytes);
@ -338,11 +338,11 @@ namespace libtorrent {
{
public:
typedef std::function<void(aux::session_listen_socket*
typedef std::function<void(aux::listen_socket_handle const&
, udp::endpoint const&
, span<char const>
, error_code&, int)> send_fun_t;
typedef std::function<void(aux::session_listen_socket*
typedef std::function<void(aux::listen_socket_handle const&
, char const*, int
, span<char const>
, error_code&, int)> send_fun_hostname_t;
@ -389,11 +389,11 @@ namespace libtorrent {
aux::session_settings const& settings() const { return m_settings; }
resolver_interface& host_resolver() { return m_host_resolver; }
void send_hostname(aux::session_listen_socket* sock
void send_hostname(aux::listen_socket_handle const& sock
, char const* hostname, int port, span<char const> p
, error_code& ec, int flags = 0);
void send(aux::session_listen_socket* sock
void send(aux::listen_socket_handle const& sock
, udp::endpoint const& ep, span<char const> p
, error_code& ec, int flags = 0);

View File

@ -44,7 +44,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/random.hpp"
#include "libtorrent/crc32c.hpp"
#include "libtorrent/alert_types.hpp" // for dht_routing_bucket
#include "libtorrent/aux_/session_listen_socket.hpp"
#include "libtorrent/aux_/listen_socket_handle.hpp"
#include "setup_dht.hpp"
@ -76,9 +76,17 @@ namespace {
return dht::generate_id(addr);
}
std::shared_ptr<lt::aux::listen_socket_base> sim_listen_socket(tcp::endpoint ep)
{
auto ls = std::make_shared<lt::aux::listen_socket_base>();
ls->external_address.cast_vote(ep.address(), 1, lt::address());
ls->local_endpoint = ep;
return ls;
}
} // anonymous namespace
struct dht_node final : lt::dht::socket_manager, lt::aux::session_listen_socket
struct dht_node final : lt::dht::socket_manager
{
dht_node(sim::simulation& sim, lt::dht_settings const& sett, lt::counters& cnt
, int const idx, std::uint32_t const flags)
@ -87,7 +95,8 @@ struct dht_node final : lt::dht::socket_manager, lt::aux::session_listen_socket
, m_add_dead_nodes((flags & dht_network::add_dead_nodes) != 0)
, m_ipv6((flags & dht_network::bind_ipv6) != 0)
, m_socket(m_io_service)
, m_dht(this, this, sett, id_from_addr(m_io_service.get_ips().front())
, m_ls(sim_listen_socket(tcp::endpoint(m_io_service.get_ips().front(), 6881)))
, m_dht(m_ls, this, sett, id_from_addr(m_io_service.get_ips().front())
, nullptr, cnt
, [](lt::dht::node_id const&, std::string const&) -> lt::dht::node* { return nullptr; }
, *m_dht_storage)
@ -143,7 +152,7 @@ struct dht_node final : lt::dht::socket_manager, lt::aux::session_listen_socket
}
bool has_quota() override { return true; }
bool send_packet(lt::aux::session_listen_socket* s, entry& e, udp::endpoint const& addr) override
bool send_packet(lt::aux::listen_socket_handle const& s, entry& e, udp::endpoint const& addr) override
{
// since the simulaton is single threaded, we can get away with allocating
// just a single send buffer
@ -157,20 +166,6 @@ struct dht_node final : lt::dht::socket_manager, lt::aux::session_listen_socket
return true;
}
address get_external_address() override
{
return get_local_endpoint().address();
}
tcp::endpoint get_local_endpoint() override
{
if (sock().is_open()) return tcp::endpoint(sock().local_endpoint().address(), sock().local_endpoint().port());
if (m_ipv6) return tcp::endpoint(address_v6(), 0);
return tcp::endpoint(address_v4(), 0);
}
bool is_ssl() override { return false; }
// the node_id and IP address of this node
std::pair<dht::node_id, lt::udp::endpoint> node_info() const
{
@ -246,6 +241,7 @@ private:
bool const m_ipv6;
lt::udp::socket m_socket;
lt::udp::socket& sock() { return m_socket; }
std::shared_ptr<lt::aux::listen_socket_base> m_ls;
lt::dht::node m_dht;
lt::udp::endpoint m_ep;
char m_buffer[1300];

View File

@ -34,7 +34,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "simulator/simulator.hpp"
#include "libtorrent/aux_/session_listen_socket.hpp"
#include "libtorrent/aux_/listen_socket_handle.hpp"
#include "libtorrent/udp_socket.hpp"
#include "libtorrent/kademlia/dht_tracker.hpp"
#include "libtorrent/kademlia/dht_state.hpp"
@ -56,7 +56,7 @@ using namespace std::placeholders;
struct obs : dht::dht_observer
{
void set_external_address(lt::aux::session_listen_socket*, address const& /* addr */
void set_external_address(lt::aux::listen_socket_handle const&, address const& /* addr */
, address const& /* source */) override
{}
void get_peers(sha1_hash const&) override {}
@ -84,22 +84,7 @@ struct obs : dht::dht_observer
#endif
};
struct mock_socket : lt::aux::session_listen_socket
{
address get_external_address() override
{
return get_local_endpoint().address();
}
tcp::endpoint get_local_endpoint() override
{
return tcp::endpoint(address_v4::from_string("40.30.20.10"), 8888);
}
bool is_ssl() override { return false; }
};
void send_packet(lt::udp_socket& sock, lt::aux::session_listen_socket*, udp::endpoint const& ep
void send_packet(lt::udp_socket& sock, lt::aux::listen_socket_handle const&, udp::endpoint const& ep
, span<char const> p, error_code& ec, int flags)
{
sock.send(ep, p, ec, flags);
@ -118,7 +103,9 @@ TORRENT_TEST(dht_rate_limit)
// receiver (the DHT under test)
lt::udp_socket sock(dht_ios);
obs o;
mock_socket ds;
auto ls = std::make_shared<lt::aux::listen_socket_base>();
ls->external_address.cast_vote(address_v4::from_string("40.30.20.10"), 1, lt::address());
ls->local_endpoint = tcp::endpoint(address_v4::from_string("40.30.20.10"), 8888);
error_code ec;
sock.bind(udp::endpoint(address_v4::from_string("40.30.20.10"), 8888), ec);
dht_settings dhtsett;
@ -134,7 +121,7 @@ TORRENT_TEST(dht_rate_limit)
auto dht = std::make_shared<lt::dht::dht_tracker>(
&o, dht_ios, std::bind(&send_packet, std::ref(sock), _1, _2, _3, _4, _5)
, dhtsett, cnt, *dht_storage, state);
dht->new_socket(&ds);
dht->new_socket(ls);
bool stop = false;
std::function<void(error_code const&, size_t)> on_read
@ -244,7 +231,9 @@ TORRENT_TEST(dht_delete_socket)
sock.bind(udp::endpoint(address_v4::from_string("40.30.20.10"), 8888), ec);
obs o;
mock_socket ds;
auto ls = std::make_shared<lt::aux::listen_socket_base>();
ls->external_address.cast_vote(address_v4::from_string("40.30.20.10"), 1, lt::address());
ls->local_endpoint = tcp::endpoint(address_v4::from_string("40.30.20.10"), 8888);
dht_settings dhtsett;
counters cnt;
dht::dht_state state;
@ -254,7 +243,7 @@ TORRENT_TEST(dht_delete_socket)
, dhtsett, cnt, *dht_storage, state);
dht->start([](std::vector<std::pair<dht::node_entry, std::string>> const&){});
dht->new_socket(&ds);
dht->new_socket(ls);
// schedule the removal of the socket at exactly 2 second,
// this simulates the fact that the internal scheduled call
@ -264,7 +253,7 @@ TORRENT_TEST(dht_delete_socket)
t1.expires_from_now(chrono::seconds(2));
t1.async_wait([&](error_code const&)
{
dht->delete_socket(&ds);
dht->delete_socket(ls);
});
// stop the DHT

View File

@ -94,6 +94,7 @@ libtorrent_rasterbar_la_SOURCES = \
ip_notifier.cpp \
ip_voter.cpp \
lazy_bdecode.cpp \
listen_socket_handle.cpp \
lsd.cpp \
magnet_uri.cpp \
merkle.cpp \

View File

@ -35,7 +35,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/string_util.hpp" // for is_space
#include "libtorrent/aux_/time.hpp"
#include "libtorrent/aux_/session_settings.hpp"
#include "libtorrent/aux_/session_listen_socket.hpp"
#include "libtorrent/aux_/listen_socket_handle.hpp"
namespace libtorrent {
@ -47,8 +47,8 @@ namespace libtorrent {
minutes32 constexpr tracker_retry_delay_max{60};
}
announce_endpoint::announce_endpoint(aux::session_listen_socket* s)
: local_endpoint(s ? s->get_local_endpoint() : tcp::endpoint())
announce_endpoint::announce_endpoint(aux::listen_socket_handle const& s)
: local_endpoint(s ? s.get_local_endpoint() : tcp::endpoint())
, socket(s)
, fails(0)
, updating(false)
@ -143,7 +143,7 @@ namespace libtorrent {
}
#endif
announce_endpoint* announce_entry::find_endpoint(aux::session_listen_socket* s)
announce_endpoint* announce_entry::find_endpoint(aux::listen_socket_handle const& s)
{
auto aep = std::find_if(endpoints.begin(), endpoints.end()
, [&](announce_endpoint const& a) { return a.socket == s; });

View File

@ -68,7 +68,7 @@ namespace libtorrent {
if (attr.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) return file_storage::attribute_hidden;
return 0;
#else
struct stat s;
struct ::stat s;
if (::lstat(convert_to_native(p).c_str(), &s) < 0) return 0;
std::uint32_t file_attr = 0;
if (s.st_mode & S_IXUSR)

View File

@ -193,6 +193,12 @@ namespace libtorrent {
}
#endif
if (!tracker_req().outgoing_socket)
{
fail(errors::invalid_listen_socket, -1, "outgoing socket was closed");
return;
}
m_tracker_connection = std::make_shared<http_connection>(get_io_service(), m_man.host_resolver()
, std::bind(&http_tracker_connection::on_response, shared_from_this(), _1, _2, _3, _4)
, true, settings.get_int(settings_pack::max_http_recv_buffer_size)

View File

@ -106,7 +106,7 @@ namespace libtorrent { namespace dht {
m_blocker.set_rate_limit(m_settings.block_ratelimit);
}
void dht_tracker::update_node_id(aux::session_listen_socket* s)
void dht_tracker::update_node_id(aux::listen_socket_handle const& s)
{
auto n = m_nodes.find(s);
if (n != m_nodes.end())
@ -114,11 +114,11 @@ namespace libtorrent { namespace dht {
update_storage_node_ids();
}
void dht_tracker::new_socket(aux::session_listen_socket* s)
void dht_tracker::new_socket(aux::listen_socket_handle const& s)
{
if (s->is_ssl()) return;
if (s.is_ssl()) return;
address local_address = s->get_local_endpoint().address();
address local_address = s.get_local_endpoint().address();
#if TORRENT_USE_IPV6
// don't try to start dht nodes on non-global IPv6 addresses
// with IPv4 the interface might be behind NAT so we can't skip them based on the scope of the local address
@ -156,12 +156,12 @@ namespace libtorrent { namespace dht {
}
}
void dht_tracker::delete_socket(aux::session_listen_socket* s)
void dht_tracker::delete_socket(aux::listen_socket_handle const& s)
{
if (s->is_ssl()) return;
if (s.is_ssl()) return;
#if TORRENT_USE_IPV6
address local_address = s->get_local_endpoint().address();
address local_address = s.get_local_endpoint().address();
// since we don't start nodes on local IPv6 interfaces we don't need to remove them either
if (local_address.is_v6() && is_local(local_address))
return;
@ -182,7 +182,7 @@ namespace libtorrent { namespace dht {
n.second.connection_timer.async_wait(
std::bind(&dht_tracker::connection_timeout, self(), n.first, _1));
#if TORRENT_USE_IPV6
if (n.first->get_local_endpoint().protocol() == tcp::v6())
if (n.first.get_local_endpoint().protocol() == tcp::v6())
n.second.dht.bootstrap(concat(m_state.nodes6, m_state.nodes), f);
else
#endif
@ -246,7 +246,7 @@ namespace libtorrent { namespace dht {
add_dht_counters(n.second.dht, c);
}
void dht_tracker::connection_timeout(aux::session_listen_socket* s, error_code const& e)
void dht_tracker::connection_timeout(aux::listen_socket_handle const& s, error_code const& e)
{
if (e || !m_running) return;
@ -339,7 +339,7 @@ namespace libtorrent { namespace dht {
{
for (auto& n : m_nodes)
{
if (ep.protocol() != (n.first->get_external_address().is_v4() ? udp::v4() : udp::v6()))
if (ep.protocol() != (n.first.get_external_address().is_v4() ? udp::v4() : udp::v6()))
continue;
n.second.dht.sample_infohashes(ep, target, f);
break;
@ -473,7 +473,7 @@ namespace libtorrent { namespace dht {
{
for (auto& n : m_nodes)
{
if (ep.protocol() != (n.first->get_external_address().is_v4() ? udp::v4() : udp::v6()))
if (ep.protocol() != (n.first.get_external_address().is_v4() ? udp::v4() : udp::v6()))
continue;
n.second.dht.direct_request(ep, e, f);
break;
@ -569,7 +569,7 @@ namespace libtorrent { namespace dht {
}
dht_tracker::tracker_node::tracker_node(io_service& ios
, aux::session_listen_socket* s, socket_manager* sock
, aux::listen_socket_handle const& s, socket_manager* sock
, libtorrent::dht_settings const& settings
, node_id const& nid
, dht_observer* observer, counters& cnt
@ -616,7 +616,7 @@ namespace libtorrent { namespace dht {
{
// use the local rather than external address because if the user is behind NAT
// we won't know the external IP on startup
ret.nids.push_back(std::make_pair(n.first->get_local_endpoint().address(), n.second.dht.nid()));
ret.nids.push_back(std::make_pair(n.first.get_local_endpoint().address(), n.second.dht.nid()));
auto nodes = save_nodes(n.second.dht);
ret.nodes.insert(ret.nodes.end(), nodes.begin(), nodes.end());
}
@ -652,7 +652,7 @@ namespace libtorrent { namespace dht {
return m_send_quota > 0;
}
bool dht_tracker::send_packet(aux::session_listen_socket* s, entry& e, udp::endpoint const& addr)
bool dht_tracker::send_packet(aux::listen_socket_handle const& s, entry& e, udp::endpoint const& addr)
{
TORRENT_ASSERT(m_nodes.find(s) != m_nodes.end());
@ -669,14 +669,14 @@ namespace libtorrent { namespace dht {
m_send_quota -= int(m_send_buf.size());
error_code ec;
if (s->get_local_endpoint().protocol().family() != addr.protocol().family())
if (s.get_local_endpoint().protocol().family() != addr.protocol().family())
{
// the node is trying to send a packet to a different address family
// than its socket, this can happen during bootstrap
// pick a node with the right address family and use its socket
auto n = std::find_if(m_nodes.begin(), m_nodes.end()
, [&](tracker_nodes_t::value_type const& v)
{ return v.first->get_local_endpoint().protocol().family() == addr.protocol().family(); });
{ return v.first.get_local_endpoint().protocol().family() == addr.protocol().family(); });
if (n != m_nodes.end())
m_send_fun(n->first, addr, m_send_buf, ec, 0);

View File

@ -48,7 +48,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/hasher.hpp"
#include "libtorrent/random.hpp"
#include <libtorrent/assert.hpp>
#include "libtorrent/aux_/session_listen_socket.hpp"
#include <libtorrent/aux_/time.hpp>
#include "libtorrent/aux_/throw.hpp"
#include "libtorrent/alert_types.hpp" // for dht_lookup
@ -74,10 +73,10 @@ namespace {
void nop() {}
node_id calculate_node_id(node_id const& nid, aux::session_listen_socket* sock)
node_id calculate_node_id(node_id const& nid, aux::listen_socket_handle const& sock)
{
address external_address;
external_address = sock->get_external_address();
external_address = sock.get_external_address();
// if we don't have an observer, don't pretend that external_address is valid
// generating an ID based on 0.0.0.0 would be terrible. random is better
@ -103,7 +102,7 @@ void incoming_error(entry& e, char const* msg, int error_code = 203)
} // anonymous namespace
node::node(aux::session_listen_socket* sock, socket_manager* sock_man
node::node(aux::listen_socket_handle const& sock, socket_manager* sock_man
, dht_settings const& settings
, node_id const& nid
, dht_observer* observer
@ -112,11 +111,11 @@ node::node(aux::session_listen_socket* sock, socket_manager* sock_man
, dht_storage_interface& storage)
: m_settings(settings)
, m_id(calculate_node_id(nid, sock))
, m_table(m_id, sock->get_local_endpoint().protocol() == tcp::v4() ? udp::v4() : udp::v6(), 8, settings, observer)
, m_table(m_id, sock.get_local_endpoint().protocol() == tcp::v4() ? udp::v4() : udp::v6(), 8, settings, observer)
, m_rpc(m_id, m_settings, m_table, sock, sock_man, observer)
, m_get_foreign_node(get_foreign_node)
, m_observer(observer)
, m_protocol(map_protocol_to_descriptor(sock->get_local_endpoint().protocol() == tcp::v4() ? udp::v4() : udp::v6()))
, m_protocol(map_protocol_to_descriptor(sock.get_local_endpoint().protocol() == tcp::v4() ? udp::v4() : udp::v6()))
, m_last_tracker_tick(aux::time_now())
, m_last_self_refresh(min_time())
, m_sock_man(sock_man)
@ -137,9 +136,11 @@ void node::update_node_id()
// can just stop here in that case.
if (m_observer == nullptr) return;
auto ext_address = m_sock.get_external_address();
// it's possible that our external address hasn't actually changed. If our
// current ID is still valid, don't do anything.
if (verify_id(m_id, m_sock->get_external_address()))
if (verify_id(m_id, ext_address))
return;
#ifndef TORRENT_DISABLE_LOGGING
@ -147,7 +148,7 @@ void node::update_node_id()
, "updating node ID (because external IP address changed)");
#endif
m_id = generate_id(m_sock->get_external_address());
m_id = generate_id(ext_address);
m_table.update_node_id(m_id);
m_rpc.update_node_id(m_id);

View File

@ -151,7 +151,7 @@ using observer_storage = aux::aligned_union<1
rpc_manager::rpc_manager(node_id const& our_id
, dht_settings const& settings
, routing_table& table
, aux::session_listen_socket* sock
, aux::listen_socket_handle const& sock
, socket_manager* sock_man
, dht_logger* log)
: m_pool_allocator(sizeof(observer_storage), 10)

View File

@ -30,33 +30,37 @@ POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TORRENT_SESSION_LISTEN_SOCKET_HPP_INCLUDED
#define TORRENT_SESSION_LISTEN_SOCKET_HPP_INCLUDED
#include "libtorrent/address.hpp"
#include "libtorrent/socket.hpp" // for tcp::endpoint
#include "libtorrent/aux_/listen_socket_handle.hpp"
namespace libtorrent { namespace aux {
// abstract interface for a listen socket owned by session_impl
// pointers to this type serve as a handle for the listen socket
// use a separate abstract type to prohibit outside access to private fields of listen_socket_t
// and because some users of these handles should not be coupled to session_impl
struct TORRENT_EXTRA_EXPORT session_listen_socket
address listen_socket_handle::get_external_address() const
{
virtual address get_external_address() = 0;
virtual tcp::endpoint get_local_endpoint() = 0;
auto s = m_sock.lock();
TORRENT_ASSERT(s);
if (!s) throw_ex<std::bad_weak_ptr>();
return s->external_address.external_address();
}
virtual bool is_ssl() = 0;
tcp::endpoint listen_socket_handle::get_local_endpoint() const
{
auto s = m_sock.lock();
TORRENT_ASSERT(s);
if (!s) throw_ex<std::bad_weak_ptr>();
return s->local_endpoint;
}
session_listen_socket() = default;
bool listen_socket_handle::is_ssl() const
{
auto s = m_sock.lock();
TORRENT_ASSERT(s);
if (!s) throw_ex<std::bad_weak_ptr>();
return s->ssl == transport::ssl;
}
protected:
session_listen_socket(session_listen_socket const&) = default;
session_listen_socket& operator=(session_listen_socket const&) = default;
~session_listen_socket() = default;
};
listen_socket_base* listen_socket_handle::impl() const
{
return m_sock.lock().get();
}
} }
#endif

View File

@ -1212,7 +1212,7 @@ namespace {
if (req.outgoing_socket)
{
listen_socket_t* ls = static_cast<listen_socket_t*>(req.outgoing_socket);
auto ls = static_cast<listen_socket_t*>(req.outgoing_socket.impl());
req.listen_port = listen_port(ls);
#ifdef TORRENT_USE_OPENSSL
// SSL torrents use the SSL listen port
@ -1229,7 +1229,7 @@ namespace {
// SSL torrents use the SSL listen port
if (use_ssl) req.listen_port = ssl_listen_port(&ls);
#endif
req.outgoing_socket = ls.get();
req.outgoing_socket = listen_socket_handle(ls);
m_tracker_manager.queue_request(get_io_service(), req, c);
}
}
@ -1954,7 +1954,7 @@ namespace {
{
#ifndef TORRENT_DISABLE_DHT
if (m_dht)
m_dht->delete_socket(remove_iter->get());
m_dht->delete_socket(listen_socket_handle(*remove_iter));
#endif
#ifndef TORRENT_DISABLE_LOGGING
@ -1984,7 +1984,7 @@ namespace {
#ifndef TORRENT_DISABLE_DHT
if (m_dht)
m_dht->new_socket(m_listen_sockets.back().get());
m_dht->new_socket(listen_socket_handle(m_listen_sockets.back()));
#endif
}
}
@ -5678,7 +5678,7 @@ namespace {
m_dht = std::make_shared<dht::dht_tracker>(
static_cast<dht::dht_observer*>(this)
, m_io_service
, [=](aux::session_listen_socket* sock
, [=](aux::listen_socket_handle const& sock
, udp::endpoint const& ep
, span<char const> p
, error_code& ec
@ -5690,7 +5690,7 @@ namespace {
, std::move(m_dht_state));
for (auto& s : m_listen_sockets)
m_dht->new_socket(s.get());
m_dht->new_socket(listen_socket_handle(s));
for (auto const& n : m_dht_router_nodes)
{
@ -6704,11 +6704,13 @@ namespace {
}
// this is the DHT observer version. DHT is the implied source
void session_impl::set_external_address(aux::session_listen_socket* iface, address const& ip
void session_impl::set_external_address(aux::listen_socket_handle const& iface, address const& ip
, address const& source)
{
TORRENT_ASSERT(iface);
set_external_address(*static_cast<listen_socket_t*>(iface), ip, source_dht, source);
auto i = iface.m_sock.lock();
TORRENT_ASSERT(i);
if (!i) return;
set_external_address(std::static_pointer_cast<listen_socket_t>(i), ip, source_dht, source);
}
void session_impl::get_peers(sha1_hash const& ih)
@ -6815,7 +6817,7 @@ namespace {
if (i->local_endpoint.address().is_v4() != ip.is_v4())
continue;
set_external_address(*i, ip, source_type, source);
set_external_address(i, ip, source_type, source);
break;
}
}
@ -6828,10 +6830,10 @@ namespace {
, [&](std::shared_ptr<listen_socket_t> const& v) { return v->local_endpoint == local_endpoint; });
if (sock != m_listen_sockets.end())
set_external_address(**sock, ip, source_type, source);
set_external_address(*sock, ip, source_type, source);
}
void session_impl::set_external_address(listen_socket_t& sock
void session_impl::set_external_address(std::shared_ptr<listen_socket_t> const& sock
, address const& ip, int const source_type, address const& source)
{
#ifndef TORRENT_DISABLE_LOGGING
@ -6842,7 +6844,7 @@ namespace {
}
#endif
if (!sock.external_address.cast_vote(ip, source_type, source)) return;
if (!sock->external_address.cast_vote(ip, source_type, source)) return;
#ifndef TORRENT_DISABLE_LOGGING
session_log(" external IP updated");
@ -6860,7 +6862,7 @@ namespace {
// restart the DHT with a new node ID
#ifndef TORRENT_DISABLE_DHT
if (m_dht) m_dht->update_node_id(&sock);
if (m_dht) m_dht->update_node_id(listen_socket_handle(sock));
#endif
}

View File

@ -2632,10 +2632,10 @@ namespace libtorrent {
{
struct announce_state
{
explicit announce_state(aux::session_listen_socket* s)
explicit announce_state(aux::listen_socket_handle const& s)
: socket(s) {}
aux::session_listen_socket* socket;
aux::listen_socket_handle socket;
// the tier is kept as INT_MAX until we find the first
// tracker that works, then it's set to that tracker's
@ -2756,8 +2756,8 @@ namespace libtorrent {
// update the endpoint list by adding entries for new listen sockets
// and removing entries for non-existent ones
std::vector<announce_endpoint>::size_type valid_endpoints = 0;
m_ses.for_each_listen_socket([&](aux::session_listen_socket* s) {
if (s->is_ssl() != is_ssl_torrent())
m_ses.for_each_listen_socket([&](aux::listen_socket_handle const& s) {
if (s.is_ssl() != is_ssl_torrent())
return;
for (auto& aep : ae.endpoints)
{
@ -3073,7 +3073,7 @@ namespace libtorrent {
// out external IP counter (and pass along the IP of the tracker to know
// who to attribute this vote to)
if (resp.external_ip != address() && !is_any(tracker_ip))
m_ses.set_external_address(r.outgoing_socket->get_local_endpoint()
m_ses.set_external_address(r.outgoing_socket.get_local_endpoint()
, resp.external_ip
, aux::session_interface::source_tracker, tracker_ip);
@ -8713,10 +8713,10 @@ namespace libtorrent {
{
struct timer_state
{
explicit timer_state(aux::session_listen_socket* s)
explicit timer_state(aux::listen_socket_handle const& s)
: socket(s) {}
aux::session_listen_socket* socket;
aux::listen_socket_handle socket;
int tier = INT_MAX;
bool found_working = false;
@ -10894,10 +10894,10 @@ namespace {
debug_log("*** increment tracker fail count [%d]", aep->fails);
#endif
}
else
else if (r.outgoing_socket)
{
#ifndef TORRENT_DISABLE_LOGGING
debug_log("*** no matching endpoint for request [%s, %s]", r.url.c_str(), print_endpoint(r.outgoing_socket->get_local_endpoint()).c_str());
debug_log("*** no matching endpoint for request [%s, %s]", r.url.c_str(), print_endpoint(r.outgoing_socket.get_local_endpoint()).c_str());
#endif
}

View File

@ -173,7 +173,7 @@ namespace libtorrent {
address tracker_connection::bind_interface() const
{
return m_req.outgoing_socket->get_local_endpoint().address();
return m_req.outgoing_socket.get_local_endpoint().address();
}
void tracker_connection::sent_bytes(int bytes)
@ -375,7 +375,7 @@ namespace libtorrent {
return p->on_receive_hostname(hostname, buf);
}
void tracker_manager::send_hostname(aux::session_listen_socket* sock
void tracker_manager::send_hostname(aux::listen_socket_handle const& sock
, char const* hostname, int const port
, span<char const> p, error_code& ec, int const flags)
{
@ -383,7 +383,7 @@ namespace libtorrent {
m_send_fun_hostname(sock, hostname, port, p, ec, flags);
}
void tracker_manager::send(aux::session_listen_socket* sock
void tracker_manager::send(aux::listen_socket_handle const& sock
, udp::endpoint const& ep
, span<char const> p
, error_code& ec, int const flags)

View File

@ -134,8 +134,9 @@ namespace libtorrent {
if (i != m_endpoints.end()) m_endpoints.erase(i);
// if that was the last one, fail the whole announce
if (m_endpoints.empty())
// if that was the last one, or the listen socket was closed
// fail the whole announce
if (m_endpoints.empty() || !tracker_req().outgoing_socket)
{
tracker_connection::fail(ec, code, msg, interval, min_interval);
return;
@ -194,12 +195,20 @@ namespace libtorrent {
restart_read_timeout();
if (!tracker_req().outgoing_socket)
{
fail(error_code(errors::invalid_listen_socket));
return;
}
auto bind_address = bind_interface();
// look for an address that has the same kind as the one
// we're listening on. To make sure the tracker get our
// correct listening address.
bool is_v4 = bind_interface().is_v4();
bool is_v4 = bind_address.is_v4();
#if TORRENT_USE_IPV6
auto scope = is_v4 ? 0 : bind_interface().to_v6().scope_id();
auto scope = is_v4 ? 0 : bind_address.to_v6().scope_id();
#endif
for (auto const& addr : addresses)
{

View File

@ -49,7 +49,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/bloom_filter.hpp"
#include "libtorrent/hasher.hpp"
#include "libtorrent/aux_/time.hpp"
#include "libtorrent/aux_/session_listen_socket.hpp"
#include "libtorrent/aux_/listen_socket_handle.hpp"
#include "libtorrent/kademlia/node_id.hpp"
#include "libtorrent/kademlia/routing_table.hpp"
@ -114,7 +114,7 @@ std::list<std::pair<udp::endpoint, entry>> g_sent_packets;
struct mock_socket final : socket_manager
{
bool has_quota() override { return true; }
bool send_packet(aux::session_listen_socket* s, entry& msg, udp::endpoint const& ep) override
bool send_packet(aux::listen_socket_handle const& s, entry& msg, udp::endpoint const& ep) override
{
// TODO: 3 ideally the mock_socket would contain this queue of packets, to
// make tests independent
@ -123,31 +123,30 @@ struct mock_socket final : socket_manager
}
};
struct mock_dht_socket final : aux::session_listen_socket
std::shared_ptr<aux::listen_socket_base> dummy_listen_socket(udp::endpoint src)
{
mock_dht_socket() : m_external_address(addr4("236.0.0.1")), m_local_endpoint(addr4("192.168.4.1"), 6881) {}
explicit mock_dht_socket(address ep) : m_external_address(ep), m_local_endpoint(ep, 6881) {}
auto ret = std::make_shared<aux::listen_socket_base>();
ret->local_endpoint = tcp::endpoint(src.address(), src.port());
ret->external_address.cast_vote(src.address(), 1, rand_v4());
return ret;
}
address get_external_address() override { return m_external_address; }
tcp::endpoint get_local_endpoint() override { return m_local_endpoint; }
bool is_ssl() override { return false; }
address m_external_address;
tcp::endpoint m_local_endpoint;
};
std::shared_ptr<aux::listen_socket_base> dummy_listen_socket4()
{
auto ret = std::make_shared<aux::listen_socket_base>();
ret->local_endpoint = tcp::endpoint(addr4("192.168.4.1"), 6881);
ret->external_address.cast_vote(addr4("236.0.0.1"), 1, rand_v4());
return ret;
}
#if TORRENT_USE_IPV6
struct mock_dht_socket6 final : aux::session_listen_socket
std::shared_ptr<aux::listen_socket_base> dummy_listen_socket6()
{
address get_external_address() override { return m_external_address; }
tcp::endpoint get_local_endpoint() override { return m_local_endpoint; }
bool is_ssl() override { return false; }
address m_external_address = addr6("2002::1");
tcp::endpoint m_local_endpoint = tcp::endpoint(addr6("2002::1"), 6881);
};
auto ret = std::make_shared<aux::listen_socket_base>();
ret->local_endpoint = tcp::endpoint(addr6("2002::1"), 6881);
ret->external_address.cast_vote(addr6("2002::1"), 1, rand_v6());
return ret;
}
#endif
node* get_foreign_node_stub(node_id const&, std::string const&)
@ -516,10 +515,10 @@ void put_immutable_item_cb(int num, int expect)
struct obs : dht::dht_observer
{
void set_external_address(aux::session_listen_socket* s, address const& addr
void set_external_address(aux::listen_socket_handle const& s, address const& addr
, address const& source) override
{
static_cast<mock_dht_socket*>(s)->m_external_address = addr;
s.impl()->external_address.cast_vote(addr, 1, rand_v4());
}
void get_peers(sha1_hash const& ih) override {}
@ -562,10 +561,10 @@ struct dht_test_setup
{
explicit dht_test_setup(udp::endpoint src)
: sett(test_settings())
, ds(src.address())
, ls(dummy_listen_socket(src))
, dht_storage(dht_default_storage_constructor(sett))
, source(src)
, dht_node(&ds, &s, sett
, dht_node(ls, &s, sett
, node_id(nullptr), &observer, cnt, get_foreign_node_stub, *dht_storage)
{
dht_storage->update_node_ids({node_id::min()});
@ -573,7 +572,7 @@ struct dht_test_setup
dht_settings sett;
mock_socket s;
mock_dht_socket ds;
std::shared_ptr<aux::listen_socket_base> ls;
obs observer;
counters cnt;
std::unique_ptr<dht_storage_interface> dht_storage;
@ -2630,8 +2629,8 @@ TORRENT_TEST(dht_dual_stack)
// TODO: 3 use dht_test_setup class to simplify the node setup
dht_settings sett = test_settings();
mock_socket s;
mock_dht_socket sock4;
mock_dht_socket6 sock6;
auto sock4 = dummy_listen_socket4();
auto sock6 = dummy_listen_socket6();
obs observer;
counters cnt;
node* node4p = nullptr, *node6p = nullptr;
@ -2644,8 +2643,8 @@ TORRENT_TEST(dht_dual_stack)
};
std::unique_ptr<dht_storage_interface> dht_storage(dht_default_storage_constructor(sett));
dht_storage->update_node_ids({node_id(nullptr)});
dht::node node4(&sock4, &s, sett, node_id(nullptr), &observer, cnt, get_foreign_node, *dht_storage);
dht::node node6(&sock6, &s, sett, node_id(nullptr), &observer, cnt, get_foreign_node, *dht_storage);
dht::node node4(sock4, &s, sett, node_id(nullptr), &observer, cnt, get_foreign_node, *dht_storage);
dht::node node6(sock6, &s, sett, node_id(nullptr), &observer, cnt, get_foreign_node, *dht_storage);
node4p = &node4;
node6p = &node6;
@ -3113,7 +3112,9 @@ TORRENT_TEST(node_set_id)
{
dht_test_setup t(udp::endpoint(rand_v4(), 20));
node_id old_nid = t.dht_node.nid();
t.observer.set_external_address(&t.ds, addr4("237.0.0.1"), rand_v4());
// put in a few votes to make sure the address really changes
for (int i = 0; i < 25; ++i)
t.observer.set_external_address(aux::listen_socket_handle(t.ls), addr4("237.0.0.1"), rand_v4());
t.dht_node.update_node_id();
TEST_CHECK(old_nid != t.dht_node.nid());
// now that we've changed the node's id, make sure the id sent in outgoing messages
@ -3142,13 +3143,13 @@ TORRENT_TEST(read_only_node)
dht_settings sett = test_settings();
sett.read_only = true;
mock_socket s;
mock_dht_socket ds;
auto ls = dummy_listen_socket4();
obs observer;
counters cnt;
std::unique_ptr<dht_storage_interface> dht_storage(dht_default_storage_constructor(sett));
dht_storage->update_node_ids({node_id(nullptr)});
dht::node node(&ds, &s, sett, node_id(nullptr), &observer, cnt, get_foreign_node_stub, *dht_storage);
dht::node node(ls, &s, sett, node_id(nullptr), &observer, cnt, get_foreign_node_stub, *dht_storage);
udp::endpoint source(addr("10.0.0.1"), 20);
bdecode_node response;
msg_args args;
@ -3231,13 +3232,13 @@ TORRENT_TEST(invalid_error_msg)
// TODO: 3 use dht_test_setup class to simplify the node setup
dht_settings sett = test_settings();
mock_socket s;
mock_dht_socket ds;
auto ls = dummy_listen_socket4();
obs observer;
counters cnt;
std::unique_ptr<dht_storage_interface> dht_storage(dht_default_storage_constructor(sett));
dht_storage->update_node_ids({node_id(nullptr)});
dht::node node(&ds, &s, sett, node_id(nullptr), &observer, cnt, get_foreign_node_stub, *dht_storage);
dht::node node(ls, &s, sett, node_id(nullptr), &observer, cnt, get_foreign_node_stub, *dht_storage);
udp::endpoint source(addr("10.0.0.1"), 20);
entry e;
@ -3319,15 +3320,15 @@ TORRENT_TEST(rpc_invalid_error_msg)
// TODO: 3 use dht_test_setup class to simplify the node setup
dht_settings sett = test_settings();
mock_socket s;
mock_dht_socket ds;
auto ls = dummy_listen_socket4();
obs observer;
counters cnt;
dht::routing_table table(node_id(), udp::v4(), 8, sett, &observer);
dht::rpc_manager rpc(node_id(), sett, table, &ds, &s, &observer);
dht::rpc_manager rpc(node_id(), sett, table, ls, &s, &observer);
std::unique_ptr<dht_storage_interface> dht_storage(dht_default_storage_constructor(sett));
dht_storage->update_node_ids({node_id(nullptr)});
dht::node node(&ds, &s, sett, node_id(nullptr), &observer, cnt, get_foreign_node_stub, *dht_storage);
dht::node node(ls, &s, sett, node_id(nullptr), &observer, cnt, get_foreign_node_stub, *dht_storage);
udp::endpoint source(addr("10.0.0.1"), 20);

View File

@ -49,7 +49,7 @@ TORRENT_TEST(primitives)
// make sure the retry interval keeps growing
// on failing announces
announce_entry ae("dummy");
ae.endpoints.emplace_back(nullptr);
ae.endpoints.emplace_back(aux::listen_socket_handle());
int last = 0;
auto const tracker_backoff = 250;
for (int i = 0; i < 10; ++i)