forked from premiere/premiere-libtorrent
don't move listen_socket_t when deleting sockets
Pointers to listen_socket_t are stored in dht_tracker, so they cannot be copied or moved once they are added to m_listen_sockets. listen_socket_t should really be made non-copyable and non-moveable, but the socket creation path needs to be refactored before that can be done.
This commit is contained in:
parent
80036f0377
commit
718c5f0dcb
|
@ -207,14 +207,8 @@ namespace aux {
|
|||
transport ssl;
|
||||
};
|
||||
|
||||
// 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
|
||||
TORRENT_EXTRA_EXPORT std::list<listen_socket_t>::iterator
|
||||
partition_listen_sockets(
|
||||
std::vector<listen_endpoint_t>& eps
|
||||
, std::list<listen_socket_t>& sockets);
|
||||
TORRENT_EXTRA_EXPORT bool operator==(listen_endpoint_t const& ep
|
||||
, listen_socket_t const& sock);
|
||||
|
||||
// expand [::] to all IPv6 interfaces for BEP 45 compliance
|
||||
TORRENT_EXTRA_EXPORT void expand_unspecified_address(
|
||||
|
@ -776,6 +770,10 @@ namespace aux {
|
|||
void interface_to_endpoints(std::string const& device, int const port
|
||||
, bool const ssl, std::vector<listen_endpoint_t>& eps);
|
||||
|
||||
// remove any sockets which do not match one of the given endpoints
|
||||
// matched endpoints will be removed from the vector
|
||||
void remove_listen_sockets(std::vector<listen_endpoint_t>& eps);
|
||||
|
||||
// the settings for the client
|
||||
aux::session_settings m_settings;
|
||||
|
||||
|
|
|
@ -260,35 +260,12 @@ namespace aux {
|
|||
}
|
||||
#endif // TORRENT_DISABLE_DHT
|
||||
|
||||
std::list<listen_socket_t>::iterator partition_listen_sockets(
|
||||
std::vector<listen_endpoint_t>& eps
|
||||
, std::list<listen_socket_t>& sockets)
|
||||
bool operator==(listen_endpoint_t const& ep, listen_socket_t const& sock)
|
||||
{
|
||||
return std::partition(sockets.begin(), sockets.end()
|
||||
, [&eps](listen_socket_t const& sock)
|
||||
{
|
||||
auto match = std::find_if(eps.begin(), eps.end()
|
||||
, [&sock](listen_endpoint_t const& ep)
|
||||
{
|
||||
return ep.ssl == sock.ssl
|
||||
&& ep.port == sock.original_port
|
||||
&& ep.device == sock.device
|
||||
&& ep.addr == sock.local_endpoint.address();
|
||||
});
|
||||
|
||||
if (match != eps.end())
|
||||
{
|
||||
// remove the matched endpoint so that another socket can't match it
|
||||
// this also signals to the caller that it doesn't need to create a
|
||||
// socket for the endpoint
|
||||
eps.erase(match);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
});
|
||||
return ep.ssl == sock.ssl
|
||||
&& ep.port == sock.original_port
|
||||
&& ep.device == sock.device
|
||||
&& ep.addr == sock.local_endpoint.address();
|
||||
}
|
||||
|
||||
// To comply with BEP 45 multi homed clients must run separate DHT nodes
|
||||
|
@ -1887,6 +1864,50 @@ namespace {
|
|||
}
|
||||
}
|
||||
|
||||
void session_impl::remove_listen_sockets(std::vector<listen_endpoint_t>& eps)
|
||||
{
|
||||
m_listen_sockets.remove_if([&eps, this](listen_socket_t const& sock)
|
||||
{
|
||||
auto match = std::find_if(eps.begin(), eps.end()
|
||||
, [&sock](listen_endpoint_t const& ep)
|
||||
{
|
||||
return ep == sock;
|
||||
});
|
||||
|
||||
if (match != eps.end())
|
||||
{
|
||||
// remove the matched endpoint so that another socket can't match it
|
||||
// this also signals to the caller that it doesn't need to create a
|
||||
// socket for the endpoint
|
||||
eps.erase(match);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
if (m_dht)
|
||||
// const_cast only because the dht holds non-const pointers
|
||||
m_dht->delete_socket(const_cast<listen_socket_t*>(&sock));
|
||||
#endif
|
||||
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
if (should_log())
|
||||
{
|
||||
session_log("closing listen socket for %s on device \"%s\""
|
||||
, print_endpoint(sock.local_endpoint).c_str()
|
||||
, sock.device.c_str());
|
||||
}
|
||||
#endif
|
||||
|
||||
error_code ec;
|
||||
if (sock.sock) sock.sock->close(ec);
|
||||
if (sock.udp_sock) sock.udp_sock->sock.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void session_impl::reopen_listen_sockets()
|
||||
{
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
|
@ -1948,27 +1969,7 @@ namespace {
|
|||
}
|
||||
#endif
|
||||
|
||||
auto remove_iter = partition_listen_sockets(eps, m_listen_sockets);
|
||||
|
||||
while (remove_iter != m_listen_sockets.end())
|
||||
{
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
if (m_dht)
|
||||
m_dht->delete_socket(&*remove_iter);
|
||||
#endif
|
||||
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
if (should_log())
|
||||
{
|
||||
session_log("closing listen socket for %s on device \"%s\""
|
||||
, print_endpoint(remove_iter->local_endpoint).c_str()
|
||||
, remove_iter->device.c_str());
|
||||
}
|
||||
#endif
|
||||
if (remove_iter->sock) remove_iter->sock->close(ec);
|
||||
if (remove_iter->udp_sock) remove_iter->udp_sock->sock.close();
|
||||
remove_iter = m_listen_sockets.erase(remove_iter);
|
||||
}
|
||||
remove_listen_sockets(eps);
|
||||
|
||||
// open new sockets on any endpoints that didn't match with
|
||||
// an existing socket
|
||||
|
|
|
@ -39,24 +39,6 @@ namespace
|
|||
{
|
||||
using tp = aux::transport;
|
||||
|
||||
void test_equal(aux::listen_socket_t const& s, address addr, int port
|
||||
, std::string dev, tp ssl)
|
||||
{
|
||||
TEST_CHECK(s.ssl == ssl);
|
||||
TEST_EQUAL(s.local_endpoint.address(), addr);
|
||||
TEST_EQUAL(s.original_port, port);
|
||||
TEST_EQUAL(s.device, dev);
|
||||
}
|
||||
|
||||
void test_equal(aux::listen_endpoint_t const& e1, address addr, int port
|
||||
, std::string dev, tp ssl)
|
||||
{
|
||||
TEST_CHECK(e1.ssl == ssl);
|
||||
TEST_EQUAL(e1.port, port);
|
||||
TEST_EQUAL(e1.addr, addr);
|
||||
TEST_EQUAL(e1.device, dev);
|
||||
}
|
||||
|
||||
ip_interface ifc(char const* ip, char const* device)
|
||||
{
|
||||
ip_interface ipi;
|
||||
|
@ -80,15 +62,19 @@ namespace
|
|||
}
|
||||
|
||||
aux::listen_socket_t sock(char const* ip, int const port
|
||||
, int const original_port, char const* device = "")
|
||||
, int const original_port, char const* device = "", tp ssl = tp::plaintext)
|
||||
{
|
||||
aux::listen_socket_t s;
|
||||
s.local_endpoint = tcp::endpoint(address::from_string(ip), port);
|
||||
s.original_port = original_port;
|
||||
s.device = device;
|
||||
s.ssl = ssl;
|
||||
return s;
|
||||
}
|
||||
|
||||
aux::listen_socket_t sock(char const* ip, int const port, tp ssl)
|
||||
{ return sock(ip, port, port, "", ssl); }
|
||||
|
||||
aux::listen_socket_t sock(char const* ip, int const port, char const* dev)
|
||||
{ return sock(ip, port, port, dev); }
|
||||
|
||||
|
@ -97,133 +83,31 @@ namespace
|
|||
|
||||
} // anonymous namespace
|
||||
|
||||
TORRENT_TEST(partition_listen_sockets_wildcard2specific)
|
||||
bool operator!=(aux::listen_endpoint_t const& ep, aux::listen_socket_t const& socket)
|
||||
{
|
||||
std::list<aux::listen_socket_t> sockets = {
|
||||
sock("0.0.0.0", 6881), sock("4.4.4.4", 6881)
|
||||
};
|
||||
|
||||
// remove the wildcard socket and replace it with a specific IP
|
||||
std::vector<aux::listen_endpoint_t> eps = {
|
||||
ep("4.4.4.4", 6881), ep("4.4.4.5", 6881)
|
||||
};
|
||||
|
||||
auto remove_iter = aux::partition_listen_sockets(eps, sockets);
|
||||
TEST_EQUAL(eps.size(), 1);
|
||||
TEST_EQUAL(std::distance(sockets.begin(), remove_iter), 1);
|
||||
TEST_EQUAL(std::distance(remove_iter, sockets.end()), 1);
|
||||
test_equal(sockets.front(), address_v4::from_string("4.4.4.4"), 6881, "", tp::plaintext);
|
||||
test_equal(sockets.back(), address_v4(), 6881, "", tp::plaintext);
|
||||
test_equal(eps.front(), address_v4::from_string("4.4.4.5"), 6881, "", tp::plaintext);
|
||||
return !(ep == socket);
|
||||
}
|
||||
|
||||
TORRENT_TEST(partition_listen_sockets_port_change)
|
||||
TORRENT_TEST(listen_socket_endpoint_compare)
|
||||
{
|
||||
std::list<aux::listen_socket_t> sockets = {
|
||||
sock("4.4.4.4", 6881), sock("4.4.4.5", 6881)
|
||||
};
|
||||
TEST_CHECK(ep("4.4.4.4", 6881) != sock("0.0.0.0", 6881));
|
||||
TEST_CHECK(ep("4.4.4.4", 6881) == sock("4.4.4.4", 6881));
|
||||
TEST_CHECK(ep("4.4.4.4", 6881) != sock("4.4.4.5", 6881));
|
||||
|
||||
// change the ports
|
||||
std::vector<aux::listen_endpoint_t> eps = {
|
||||
ep("4.4.4.4", 6882), ep("4.4.4.5", 6882)
|
||||
};
|
||||
auto remove_iter = aux::partition_listen_sockets(eps, sockets);
|
||||
TEST_CHECK(sockets.begin() == remove_iter);
|
||||
TEST_EQUAL(eps.size(), 2);
|
||||
}
|
||||
TEST_CHECK(ep("4.4.4.4", 6881) != sock("4.4.4.4", 6882));
|
||||
|
||||
TORRENT_TEST(partition_listen_sockets_device_bound)
|
||||
{
|
||||
std::list<aux::listen_socket_t> sockets = {
|
||||
sock("4.4.4.5", 6881), sock("0.0.0.0", 6881)
|
||||
};
|
||||
TEST_CHECK(ep("4.4.4.6", 6881, "eth1") == sock("4.4.4.6", 6881, "eth1"));
|
||||
TEST_CHECK(ep("4.4.4.6", 6881, "eth1") != sock("4.4.4.6", 6881, "enp3s0"));
|
||||
TEST_CHECK(ep("4.4.4.6", 6881, "eth1") != sock("4.4.4.6", 6881));
|
||||
|
||||
// replace the wildcard socket with a pair of device bound sockets
|
||||
std::vector<aux::listen_endpoint_t> eps = {
|
||||
ep("4.4.4.5", 6881)
|
||||
, ep("4.4.4.6", 6881, "eth1")
|
||||
, ep("4.4.4.7", 6881, "eth1")
|
||||
};
|
||||
TEST_CHECK(ep("4.4.4.4", 6881, "eth1") != sock("4.4.4.6", 6881, "eth1"));
|
||||
|
||||
auto remove_iter = aux::partition_listen_sockets(eps, sockets);
|
||||
TEST_EQUAL(std::distance(sockets.begin(), remove_iter), 1);
|
||||
TEST_EQUAL(std::distance(remove_iter, sockets.end()), 1);
|
||||
test_equal(sockets.front(), address_v4::from_string("4.4.4.5"), 6881, "", tp::plaintext);
|
||||
test_equal(sockets.back(), address_v4(), 6881, "", tp::plaintext);
|
||||
TEST_EQUAL(eps.size(), 2);
|
||||
}
|
||||
TEST_CHECK(ep("4.4.4.4", 6881) == sock("4.4.4.4", 6883, 6881));
|
||||
|
||||
TORRENT_TEST(partition_listen_sockets_device_ip_change)
|
||||
{
|
||||
std::list<aux::listen_socket_t> sockets = {
|
||||
sock("10.10.10.10", 6881, "enp3s0")
|
||||
, sock("4.4.4.4", 6881, "enp3s0")
|
||||
};
|
||||
TEST_CHECK(ep("4.4.4.4", 6881, tp::ssl) == sock("4.4.4.4", 6881, tp::ssl));
|
||||
TEST_CHECK(ep("4.4.4.4", 6881, tp::ssl) != sock("4.4.4.4", 6881));
|
||||
|
||||
// change the IP of a device bound socket
|
||||
std::vector<aux::listen_endpoint_t> eps = {
|
||||
ep("10.10.10.10", 6881, "enp3s0")
|
||||
, ep("4.4.4.5", 6881, "enp3s0")
|
||||
};
|
||||
auto remove_iter = aux::partition_listen_sockets(eps, sockets);
|
||||
TEST_EQUAL(std::distance(sockets.begin(), remove_iter), 1);
|
||||
TEST_EQUAL(std::distance(remove_iter, sockets.end()), 1);
|
||||
test_equal(sockets.front(), address_v4::from_string("10.10.10.10"), 6881, "enp3s0", tp::plaintext);
|
||||
test_equal(sockets.back(), address_v4::from_string("4.4.4.4"), 6881, "enp3s0", tp::plaintext);
|
||||
TEST_EQUAL(eps.size(), 1);
|
||||
test_equal(eps.front(), address_v4::from_string("4.4.4.5"), 6881, "enp3s0", tp::plaintext);
|
||||
}
|
||||
|
||||
TORRENT_TEST(partition_listen_sockets_original_port)
|
||||
{
|
||||
std::list<aux::listen_socket_t> sockets = {
|
||||
sock("10.10.10.10", 6883, 6881), sock("4.4.4.4", 6883, 6881)
|
||||
};
|
||||
|
||||
// make sure all sockets are kept when the actual port is different from the original
|
||||
std::vector<aux::listen_endpoint_t> eps = {
|
||||
ep("10.10.10.10", 6881)
|
||||
, ep("4.4.4.4", 6881)
|
||||
};
|
||||
|
||||
auto remove_iter = aux::partition_listen_sockets(eps, sockets);
|
||||
TEST_CHECK(remove_iter == sockets.end());
|
||||
TEST_CHECK(eps.empty());
|
||||
}
|
||||
|
||||
TORRENT_TEST(partition_listen_sockets_ssl)
|
||||
{
|
||||
std::list<aux::listen_socket_t> sockets = {
|
||||
sock("10.10.10.10", 6881), sock("4.4.4.4", 6881)
|
||||
};
|
||||
|
||||
// add ssl sockets
|
||||
std::vector<aux::listen_endpoint_t> eps = {
|
||||
ep("10.10.10.10", 6881)
|
||||
, ep("4.4.4.4", 6881)
|
||||
, ep("10.10.10.10", 6881, tp::ssl)
|
||||
, ep("4.4.4.4", 6881, tp::ssl)
|
||||
};
|
||||
|
||||
auto remove_iter = aux::partition_listen_sockets(eps, sockets);
|
||||
TEST_CHECK(remove_iter == sockets.end());
|
||||
TEST_EQUAL(eps.size(), 2);
|
||||
}
|
||||
|
||||
TORRENT_TEST(partition_listen_sockets_op_ports)
|
||||
{
|
||||
std::list<aux::listen_socket_t> sockets = {
|
||||
sock("10.10.10.10", 6881, 0), sock("4.4.4.4", 6881)
|
||||
};
|
||||
|
||||
// replace OS assigned ports with explicit ports
|
||||
std::vector<aux::listen_endpoint_t> eps ={
|
||||
ep("10.10.10.10", 6882),
|
||||
ep("4.4.4.4", 6882),
|
||||
};
|
||||
auto remove_iter = aux::partition_listen_sockets(eps, sockets);
|
||||
TEST_CHECK(remove_iter == sockets.begin());
|
||||
TEST_EQUAL(eps.size(), 2);
|
||||
TEST_CHECK(ep("4.4.4.4", 6882) != sock("4.4.4.4", 6881, 0));
|
||||
}
|
||||
|
||||
TORRENT_TEST(expand_unspecified)
|
||||
|
|
Loading…
Reference in New Issue