added reopen_network_sockets method to allow manual reopen of listen/outgoing sockets (#2476)

This commit is contained in:
Alden Torres 2017-10-28 06:15:35 -04:00 committed by Arvid Norberg
parent 50bef25786
commit f040d6d860
9 changed files with 108 additions and 5 deletions

View File

@ -318,6 +318,7 @@ void bind_converters()
to_python_converter<lt::save_state_flags_t, from_bitfield_flag<lt::save_state_flags_t>>();
to_python_converter<lt::session_flags_t, from_bitfield_flag<lt::session_flags_t>>();
to_python_converter<lt::remove_flags_t, from_bitfield_flag<lt::remove_flags_t>>();
to_python_converter<lt::reopen_network_flags_t, from_bitfield_flag<lt::reopen_network_flags_t>>();
to_python_converter<lt::file_flags_t, from_bitfield_flag<lt::file_flags_t>>();
to_python_converter<lt::create_flags_t, from_bitfield_flag<lt::create_flags_t>>();
@ -379,6 +380,7 @@ void bind_converters()
to_bitfield_flag<lt::save_state_flags_t>();
to_bitfield_flag<lt::session_flags_t>();
to_bitfield_flag<lt::remove_flags_t>();
to_bitfield_flag<lt::reopen_network_flags_t>();
to_bitfield_flag<lt::file_flags_t>();
to_bitfield_flag<lt::create_flags_t>();
}

View File

@ -993,6 +993,7 @@ void bind_session()
.def("get_cache_info", &get_cache_info1, (arg("handle") = torrent_handle(), arg("flags") = 0))
.def("add_port_mapping", allow_threads(&lt::session::add_port_mapping))
.def("delete_port_mapping", allow_threads(&lt::session::delete_port_mapping))
.def("reopen_network_sockets", allow_threads(&lt::session::reopen_network_sockets))
.def("set_peer_class_filter", &lt::session::set_peer_class_filter)
.def("set_peer_class_type_filter", &lt::session::set_peer_class_type_filter)
.def("create_peer_class", &lt::session::create_peer_class)
@ -1055,6 +1056,8 @@ void bind_session()
s.attr("global_peer_class_id") = session::global_peer_class_id;
s.attr("tcp_peer_class_id") = session::tcp_peer_class_id;
s.attr("local_peer_class_id") = session::local_peer_class_id;
s.attr("reopen_map_ports") = lt::session::reopen_map_ports;
}
#ifndef TORRENT_NO_DEPRECATE

View File

@ -211,3 +211,4 @@ dn
pe
lt
tex
natpmp

View File

@ -291,8 +291,9 @@ namespace aux {
void on_error(error_code const& ec) override;
void on_ip_change(error_code const& ec);
void reopen_listen_sockets();
void reopen_listen_sockets(bool map_ports = true);
void reopen_outgoing_sockets();
void reopen_network_sockets(reopen_network_flags_t options);
torrent_peer_allocator_interface& get_peer_allocator() override
{ return m_peer_allocator; }

View File

@ -1014,6 +1014,19 @@ namespace libtorrent {
port_mapping_t add_port_mapping(portmap_protocol t, int external_port, int local_port);
void delete_port_mapping(port_mapping_t handle);
// This option indicates if the ports are mapped using natpmp
// and upnp. If mapping was already made, they are deleted and added
// again. This only works if natpmp and/or upnp are configured to be
// enable.
static constexpr reopen_network_flags_t reopen_map_ports = 0_bit;
// Instructs the session to reopen all listen and outgoing sockets.
//
// It's useful in the case your platform doesn't support the built in
// IP notifier mechanism, or if you have a better more reliable way to
// detect changes in the IP routing table.
void reopen_network_sockets(reopen_network_flags_t options = reopen_map_ports);
// This function is intended only for use by plugins. This type does
// not have a stable API and should be relied on as little as possible.
std::shared_ptr<aux::session_impl> native_handle() const

View File

@ -49,6 +49,10 @@ namespace libtorrent {
// hidden
struct remove_flags_tag;
using remove_flags_t = flags::bitfield_flag<std::uint8_t, remove_flags_tag>;
// hidden
struct reopen_network_flags_tag;
using reopen_network_flags_t = flags::bitfield_flag<std::uint8_t, reopen_network_flags_tag>;
}
#endif

View File

@ -71,6 +71,8 @@ namespace libtorrent {
constexpr remove_flags_t session_handle::delete_files;
constexpr remove_flags_t session_handle::delete_partfile;
constexpr reopen_network_flags_t session_handle::reopen_map_ports;
template <typename Fun, typename... Args>
void session_handle::async_call(Fun f, Args&&... a) const
{
@ -1223,4 +1225,9 @@ namespace {
async_call(&session_impl::delete_port_mapping, handle);
}
void session_handle::reopen_network_sockets(reopen_network_flags_t const options)
{
async_call(&session_impl::reopen_network_sockets, options);
}
} // namespace libtorrent

View File

@ -1740,8 +1740,7 @@ namespace {
if (ec || m_abort) return;
m_ip_notifier->async_wait([this] (error_code const& e)
{ this->wrap(&session_impl::on_ip_change, e); });
reopen_listen_sockets();
reopen_outgoing_sockets();
reopen_network_sockets(session_handle::reopen_map_ports);
}
void session_impl::interface_to_endpoints(std::string const& device, int const port
@ -1795,7 +1794,7 @@ namespace {
}
}
void session_impl::reopen_listen_sockets()
void session_impl::reopen_listen_sockets(bool const map_ports)
{
#ifndef TORRENT_DISABLE_LOGGING
session_log("reopen listen sockets");
@ -1953,7 +1952,7 @@ namespace {
for (auto& s : m_listen_sockets)
{
if (s->sock) async_accept(s->sock, s->ssl);
remap_ports(remap_natpmp_and_upnp, *s);
if (map_ports) remap_ports(remap_natpmp_and_upnp, *s);
}
#if TORRENT_USE_I2P
@ -2098,6 +2097,12 @@ namespace {
}
}
void session_impl::reopen_network_sockets(reopen_network_flags_t const options)
{
reopen_listen_sockets(bool(options & session_handle::reopen_map_ports));
reopen_outgoing_sockets();
}
namespace {
template <typename MapProtocol, typename ProtoType, typename EndpointType>
void map_port(MapProtocol& m, ProtoType protocol, EndpointType const& ep

View File

@ -510,3 +510,70 @@ TORRENT_TEST(init_dht)
TEST_EQUAL(count, 1);
}
}
TORRENT_TEST(reopen_network_sockets)
{
auto count_alerts = [](session& ses, int const listen, int const portmap)
{
int count_listen = 0;
int count_portmap = 0;
int num = 50; // this number is adjusted per version, an estimate
time_point const end_time = clock_type::now() + seconds(1);
while (true)
{
time_point const now = clock_type::now();
if (now > end_time)
break;
ses.wait_for_alert(end_time - now);
std::vector<alert*> alerts;
ses.pop_alerts(&alerts);
for (auto a : alerts)
{
std::printf("%d: [%s] %s\n", num, a->what(), a->message().c_str());
std::string const msg = a->message();
if (msg.find("successfully listening on") != std::string::npos)
count_listen++;
// upnp
if (msg.find("adding port map:") != std::string::npos)
count_portmap++;
// natpmp
if (msg.find("add-mapping: proto:") != std::string::npos)
count_portmap++;
num--;
}
if (num <= 0)
break;
}
std::printf("count_listen: %d, count_portmap: %d\n", count_listen, count_portmap);
return count_listen == listen && count_portmap == portmap;
};
settings_pack p = settings();
p.set_int(settings_pack::alert_mask, alert::all_categories);
p.set_str(settings_pack::listen_interfaces, "0.0.0.0:6881");
p.set_bool(settings_pack::enable_upnp, true);
p.set_bool(settings_pack::enable_natpmp, true);
lt::session s(p);
TEST_CHECK(count_alerts(s, 2, 4));
s.reopen_network_sockets(session_handle::reopen_map_ports);
TEST_CHECK(count_alerts(s, 2, 4));
s.reopen_network_sockets(reopen_network_flags_t{0});
TEST_CHECK(count_alerts(s, 2, 0));
p.set_bool(settings_pack::enable_upnp, false);
p.set_bool(settings_pack::enable_natpmp, false);
s.apply_settings(p);
s.reopen_network_sockets(session_handle::reopen_map_ports);
TEST_CHECK(count_alerts(s, 2, 0));
}