Skip to content

Commit 174a2ca

Browse files
aldenmlarvidn
authored andcommitted
add limit of max 50 upnp mappings and recover free global mappings (arvidn#2470)
1 parent 989a65f commit 174a2ca

File tree

2 files changed

+36
-0
lines changed

2 files changed

+36
-0
lines changed

src/upnp.cpp

+21
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ namespace libtorrent {
6363

6464
using namespace aux;
6565

66+
// due to the recursive nature of update_map, it's necessary to
67+
// limit the internal list of global mappings to a small size
68+
// this can be changed once the entire UPnP code is refactored
69+
constexpr std::size_t max_global_mappings = 50;
70+
6671
namespace upnp_errors
6772
{
6873
boost::system::error_code make_error_code(error_code_enum e)
@@ -227,6 +232,14 @@ port_mapping_t upnp::add_mapping(portmap_protocol const p, int const external_po
227232

228233
if (mapping_it == m_mappings.end())
229234
{
235+
TORRENT_ASSERT(m_mappings.size() <= max_global_mappings);
236+
if (m_mappings.size() >= max_global_mappings)
237+
{
238+
#ifndef TORRENT_DISABLE_LOGGING
239+
log("too many mappings registered");
240+
#endif
241+
return port_mapping_t{-1};
242+
}
230243
m_mappings.push_back(global_mapping_t());
231244
mapping_it = m_mappings.end() - 1;
232245
}
@@ -1560,6 +1573,14 @@ void upnp::on_upnp_unmap_response(error_code const& e
15601573

15611574
d.mapping[mapping].protocol = portmap_protocol::none;
15621575

1576+
// free the slot in global mappings
1577+
auto pred = [mapping](rootdevice const& rd)
1578+
{ return rd.mapping[mapping].protocol == portmap_protocol::none; };
1579+
if (std::all_of(m_devices.begin(), m_devices.end(), pred))
1580+
{
1581+
m_mappings[mapping].protocol = portmap_protocol::none;
1582+
}
1583+
15631584
next(d, mapping);
15641585
}
15651586

test/test_upnp.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -260,3 +260,18 @@ TORRENT_TEST(upnp)
260260
run_upnp_test(combine_path("..", "root2.xml").c_str(), "D-Link Router", "WANIPConnection", 1);
261261
run_upnp_test(combine_path("..", "root3.xml").c_str(), "D-Link Router", "WANIPConnection_2", 2);
262262
}
263+
264+
TORRENT_TEST(upnp_max_mappings)
265+
{
266+
lt::io_service ios;
267+
upnp_callback cb;
268+
auto upnp_handler = std::make_shared<upnp>(ios, "test agent", cb, false);
269+
270+
for (int i = 0; i < 50; ++i)
271+
{
272+
auto const mapping = upnp_handler->add_mapping(portmap_protocol::tcp
273+
, 500 + i, ep("127.0.0.1", 500 + i));
274+
275+
TEST_CHECK(mapping != port_mapping_t{-1});
276+
}
277+
}

0 commit comments

Comments
 (0)