Revert "don't move listen_socket_t when deleting sockets"

This reverts commit 718c5f0dcb.
This commit is contained in:
Steven Siloti 2017-07-11 20:39:28 -07:00
parent 87ca4bb26f
commit 0f30815d8f
3 changed files with 193 additions and 76 deletions

View File

@ -222,8 +222,14 @@ namespace aux {
transport ssl;
};
TORRENT_EXTRA_EXPORT bool operator==(listen_endpoint_t const& ep
, listen_socket_t const& sock);
// 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);
// expand [::] to all IPv6 interfaces for BEP 45 compliance
TORRENT_EXTRA_EXPORT void expand_unspecified_address(
@ -785,10 +791,6 @@ 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;

View File

@ -260,12 +260,35 @@ namespace aux {
}
#endif // TORRENT_DISABLE_DHT
bool operator==(listen_endpoint_t const& ep, listen_socket_t const& sock)
std::list<listen_socket_t>::iterator partition_listen_sockets(
std::vector<listen_endpoint_t>& eps
, std::list<listen_socket_t>& sockets)
{
return ep.ssl == sock.ssl
&& ep.port == sock.original_port
&& ep.device == sock.device
&& ep.addr == sock.local_endpoint.address();
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;
}
});
}
// To comply with BEP 45 multi homed clients must run separate DHT nodes
@ -1864,50 +1887,6 @@ 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
@ -1969,7 +1948,27 @@ namespace {
}
#endif
remove_listen_sockets(eps);
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);
}
// open new sockets on any endpoints that didn't match with
// an existing socket

View File

@ -39,6 +39,24 @@ 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;
@ -62,19 +80,15 @@ namespace
}
aux::listen_socket_impl sock(char const* ip, int const port
, int const original_port, char const* device = "", tp ssl = tp::plaintext)
, int const original_port, char const* device = "")
{
aux::listen_socket_impl 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_impl sock(char const* ip, int const port, tp ssl)
{ return sock(ip, port, port, "", ssl); }
aux::listen_socket_impl sock(char const* ip, int const port, char const* dev)
{ return sock(ip, port, port, dev); }
@ -83,31 +97,133 @@ namespace
} // anonymous namespace
bool operator!=(aux::listen_endpoint_t const& ep, aux::listen_socket_t const& socket)
TORRENT_TEST(partition_listen_sockets_wildcard2specific)
{
return !(ep == 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);
}
TORRENT_TEST(listen_socket_endpoint_compare)
TORRENT_TEST(partition_listen_sockets_port_change)
{
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));
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("4.4.4.4", 6882));
// 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.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));
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.4", 6881, "eth1") != sock("4.4.4.6", 6881, "eth1"));
// 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) == sock("4.4.4.4", 6883, 6881));
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, 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));
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", 6882) != sock("4.4.4.4", 6881, 0));
// 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);
}
TORRENT_TEST(expand_unspecified)