upnp and natpmp modernization and cleanup (#1103)

upnp and natpmp modernization and cleanup
This commit is contained in:
Arvid Norberg 2016-09-18 10:11:56 -04:00 committed by GitHub
parent 527772420a
commit 219b2c36b4
10 changed files with 166 additions and 173 deletions

View File

@ -40,10 +40,14 @@ namespace aux
{
// TODO: move this for a better place and integrate it with
// portmap error alerts
enum class portmap_transport
enum class portmap_transport : std::uint8_t
{
natpmp = 0,
upnp = 1
natpmp, upnp
};
enum class portmap_protocol : std::uint8_t
{
none, tcp, udp
};
struct TORRENT_EXTRA_EXPORT portmap_callback
@ -55,7 +59,7 @@ namespace aux
// error_code: error, an empty error means success
// int: transport is 0 for NAT-PMP and 1 for UPnP
virtual void on_port_mapping(int mapping, address const& ip, int port
, int protocol, error_code const& ec, portmap_transport transport) = 0;
, portmap_protocol proto, error_code const& ec, portmap_transport transport) = 0;
#ifndef TORRENT_DISABLE_LOGGING
virtual bool should_log_portmap(portmap_transport transport) const = 0;
virtual void log_portmap(portmap_transport transport, char const* msg) const = 0;

View File

@ -386,7 +386,7 @@ namespace libtorrent
// called when a port mapping is successful, or a router returns
// a failure to map a port
void on_port_mapping(int mapping, address const& ip, int port
, int protocol, error_code const& ec
, portmap_protocol proto, error_code const& ec
, aux::portmap_transport transport) override;
bool is_aborted() const override { return m_abort; }

View File

@ -55,10 +55,10 @@ struct TORRENT_EXTRA_EXPORT natpmp
// maps the ports, if a port is set to 0
// it will not be mapped
enum protocol_type { none = 0, udp = 1, tcp = 2 };
int add_mapping(protocol_type p, int external_port, int local_port);
int add_mapping(aux::portmap_protocol p, int external_port, int local_port);
void delete_mapping(int mapping_index);
bool get_mapping(int mapping_index, int& local_port, int& external_port, int& protocol) const;
bool get_mapping(int mapping_index, int& local_port, int& external_port
, aux::portmap_protocol& protocol) const;
void close();
@ -86,39 +86,31 @@ private:
struct mapping_t
{
enum action_t { action_none, action_add, action_delete };
mapping_t()
: action(action_none)
, local_port(0)
, external_port(0)
, protocol(none)
, map_sent(false)
, outstanding_request(false)
{}
enum class action : std::uint8_t { none, add, del };
// indicates that the mapping has changed
// and needs an update
int action;
action act = action::none;
// the time the port mapping will expire
time_point expires;
// the local port for this mapping. If this is set
// to 0, the mapping is not in use
int local_port;
int local_port = 0;
// the external (on the NAT router) port
// for the mapping. This is the port we
// should announce to others
int external_port;
int external_port = 0;
int protocol;
aux::portmap_protocol protocol = aux::portmap_protocol::none;
// set to true when the first map request is sent
bool map_sent;
bool map_sent = false;
// set to true while we're waiting for a response
bool outstanding_request;
bool outstanding_request = false;
};
aux::portmap_callback& m_callback;
@ -131,10 +123,10 @@ private:
// this is the mapping that is currently
// being updated. It is -1 in case no
// mapping is being updated at the moment
int m_currently_mapping;
int m_currently_mapping = -1;
// current retry count
int m_retry_count;
int m_retry_count = 0;
// used to receive responses in
char m_response_buffer[16];
@ -157,11 +149,11 @@ private:
deadline_timer m_refresh_timer;
// the mapping index that will expire next
int m_next_refresh;
int m_next_refresh = -1;
bool m_disabled;
bool m_disabled = false;
bool m_abort;
bool m_abort = false;
};
}

View File

@ -130,8 +130,6 @@ struct TORRENT_EXTRA_EXPORT upnp final
void start();
enum protocol_type { none = 0, udp = 1, tcp = 2 };
// Attempts to add a port mapping for the specified protocol. Valid protocols are
// ``upnp::tcp`` and ``upnp::udp`` for the UPnP class and ``natpmp::tcp`` and
// ``natpmp::udp`` for the NAT-PMP class.
@ -149,13 +147,14 @@ struct TORRENT_EXTRA_EXPORT upnp final
// portmap_alert_ respectively. If The mapping fails immediately, the return value
// is -1, which means failure. There will not be any error alert notification for
// mappings that fail with a -1 return value.
int add_mapping(protocol_type p, int external_port, int local_port);
int add_mapping(aux::portmap_protocol p, int external_port, int local_port);
// This function removes a port mapping. ``mapping_index`` is the index that refers
// to the mapping you want to remove, which was returned from add_mapping().
void delete_mapping(int mapping_index);
bool get_mapping(int mapping_index, int& local_port, int& external_port, int& protocol) const;
bool get_mapping(int mapping_index, int& local_port, int& external_port
, aux::portmap_protocol& protocol) const;
void discover_device();
void close();
@ -224,63 +223,40 @@ private:
struct global_mapping_t
{
global_mapping_t()
: protocol(none)
, external_port(0)
, local_port(0)
{}
int protocol;
int external_port;
int local_port;
aux::portmap_protocol protocol = aux::portmap_protocol::none;
int external_port = 0;
int local_port = 0;
};
struct mapping_t
{
enum action_t { action_none, action_add, action_delete };
mapping_t()
: action(action_none)
, local_port(0)
, external_port(0)
, protocol(none)
, failcount(0)
{}
enum class action : std::uint8_t { none, add, del };
// the time the port mapping will expire
time_point expires;
int action;
action act = action::none;
// the local port for this mapping. If this is set
// to 0, the mapping is not in use
int local_port;
int local_port = 0;
// the external (on the NAT router) port
// for the mapping. This is the port we
// should announce to others
int external_port;
int external_port = 0;
// 2 = udp, 1 = tcp
int protocol;
aux::portmap_protocol protocol = aux::portmap_protocol::none;
// the number of times this mapping has failed
int failcount;
int failcount = 0;
};
struct rootdevice
{
rootdevice(): service_namespace(0)
, port(0)
, lease_duration(default_lease_time)
, supports_specific_external(true)
, disabled(false)
, non_router(false)
{
#if TORRENT_USE_ASSERTS
magic = 1337;
#endif
}
#if TORRENT_USE_ASSERTS
rootdevice() {}
~rootdevice()
{
TORRENT_ASSERT(magic == 1337);
@ -297,7 +273,7 @@ private:
// the url to the WANIP or WANPPP interface
std::string control_url;
// either the WANIP namespace or the WANPPP namespace
char const* service_namespace;
char const* service_namespace = nullptr;
std::vector<mapping_t> mapping;
@ -305,28 +281,29 @@ private:
// component of the url or the control_url
// if it has been found
std::string hostname;
int port;
int port = 0;
std::string path;
address external_ip;
int lease_duration;
int lease_duration = default_lease_time;
// true if the device supports specifying a
// specific external port, false if it doesn't
bool supports_specific_external;
bool supports_specific_external = true;
bool disabled;
bool disabled = false;
// this is true if the IP of this device is not
// one of our default routes. i.e. it may be someone
// else's router, we just happen to have multicast
// enabled across networks
// this is only relevant if ignore_non_routers is set.
bool non_router;
bool non_router = false;
mutable std::shared_ptr<http_connection> upnp_connection;
#if TORRENT_USE_ASSERTS
int magic;
int magic = 1337;
#endif
void close() const
{

View File

@ -56,20 +56,17 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/debug.hpp"
#include "libtorrent/aux_/escape_string.hpp"
using namespace libtorrent;
namespace libtorrent {
using namespace aux;
using namespace std::placeholders;
natpmp::natpmp(io_service& ios
, aux::portmap_callback& cb)
: m_callback(cb)
, m_currently_mapping(-1)
, m_retry_count(0)
, m_socket(ios)
, m_send_timer(ios)
, m_refresh_timer(ios)
, m_next_refresh(-1)
, m_disabled(false)
, m_abort(false)
{
// unfortunately async operations rely on the storage
// for this array not to be reallocated, by passing
@ -132,10 +129,10 @@ void natpmp::start()
for (std::vector<mapping_t>::iterator i = m_mappings.begin()
, end(m_mappings.end()); i != end; ++i)
{
if (i->protocol != none
|| i->action != mapping_t::action_none)
if (i->protocol != portmap_protocol::none
|| i->act != mapping_t::action::none)
continue;
i->action = mapping_t::action_add;
i->act = mapping_t::action::add;
update_mapping(i - m_mappings.begin());
}
}
@ -157,14 +154,15 @@ void natpmp::send_get_ip_address_request()
m_socket.send_to(boost::asio::buffer(buf, sizeof(buf)), m_nat_endpoint, 0, ec);
}
bool natpmp::get_mapping(int index, int& local_port, int& external_port, int& protocol) const
bool natpmp::get_mapping(int const index, int& local_port
, int& external_port, portmap_protocol& protocol) const
{
TORRENT_ASSERT(is_single_thread());
TORRENT_ASSERT(index < int(m_mappings.size()) && index >= 0);
if (index >= int(m_mappings.size()) || index < 0) return false;
mapping_t const& m = m_mappings[index];
if (m.protocol == none) return false;
if (m.protocol == portmap_protocol::none) return false;
local_port = m.local_port;
external_port = m.external_port;
protocol = m.protocol;
@ -199,10 +197,10 @@ void natpmp::disable(error_code const& ec)
for (std::vector<mapping_t>::iterator i = m_mappings.begin()
, end(m_mappings.end()); i != end; ++i)
{
if (i->protocol == none) continue;
int const proto = i->protocol;
i->protocol = none;
int index = i - m_mappings.begin();
if (i->protocol == portmap_protocol::none) continue;
portmap_protocol const proto = i->protocol;
i->protocol = portmap_protocol::none;
int const index = i - m_mappings.begin();
m_callback.on_port_mapping(index, address(), 0, proto, ec
, aux::portmap_transport::natpmp);
}
@ -217,19 +215,19 @@ void natpmp::delete_mapping(int index)
if (index >= int(m_mappings.size()) || index < 0) return;
mapping_t& m = m_mappings[index];
if (m.protocol == none) return;
if (m.protocol == portmap_protocol::none) return;
if (!m.map_sent)
{
m.action = mapping_t::action_none;
m.protocol = none;
m.act = mapping_t::action::none;
m.protocol = portmap_protocol::none;
return;
}
m.action = mapping_t::action_delete;
m.act = mapping_t::action::del;
update_mapping(index);
}
int natpmp::add_mapping(protocol_type p, int const external_port
int natpmp::add_mapping(portmap_protocol const p, int const external_port
, int const local_port)
{
TORRENT_ASSERT(is_single_thread());
@ -237,7 +235,7 @@ int natpmp::add_mapping(protocol_type p, int const external_port
if (m_disabled) return -1;
std::vector<mapping_t>::iterator i = std::find_if(m_mappings.begin()
, m_mappings.end(), [] (mapping_t const& m) { return m.protocol == none; });
, m_mappings.end(), [] (mapping_t const& m) { return m.protocol == portmap_protocol::none; });
if (i == m_mappings.end())
{
m_mappings.push_back(mapping_t());
@ -246,7 +244,7 @@ int natpmp::add_mapping(protocol_type p, int const external_port
i->protocol = p;
i->external_port = external_port;
i->local_port = local_port;
i->action = mapping_t::action_add;
i->act = mapping_t::action::add;
int const mapping_index = i - m_mappings.begin();
#ifndef TORRENT_DISABLE_LOGGING
@ -254,12 +252,12 @@ int natpmp::add_mapping(protocol_type p, int const external_port
{
natpmp::mapping_t const& m = *i;
log("add-mapping: proto: %s port: %d local-port: %d action: %s ttl: %" PRId64
, (m.protocol == none
? "none" : m.protocol == tcp ? "tcp" : "udp")
, (m.protocol == portmap_protocol::none
? "none" : m.protocol == portmap_protocol::tcp ? "tcp" : "udp")
, m.external_port
, m.local_port
, (m.action == mapping_t::action_none
? "none" : m.action == mapping_t::action_add ? "add" : "delete")
, (m.act == mapping_t::action::none
? "none" : m.act == mapping_t::action::add ? "add" : "delete")
, total_seconds(m.expires - aux::time_now()));
}
#endif
@ -279,7 +277,7 @@ void natpmp::try_next_mapping(int const i)
std::vector<mapping_t>::iterator const m = std::find_if(
m_mappings.begin(), m_mappings.end()
, [] (mapping_t const& ma) { return ma.action != mapping_t::action_none; });
, [] (mapping_t const& ma) { return ma.act != mapping_t::action::none; });
if (m == m_mappings.end())
{
@ -315,18 +313,18 @@ void natpmp::update_mapping(int const i)
if (should_log())
{
log("update-mapping: proto: %s port: %d local-port: %d action: %s ttl: %" PRId64
, (m.protocol == none
? "none" : m.protocol == tcp ? "tcp" : "udp")
, (m.protocol == portmap_protocol::none
? "none" : m.protocol == portmap_protocol::tcp ? "tcp" : "udp")
, m.external_port
, m.local_port
, (m.action == mapping_t::action_none
? "none" : m.action == mapping_t::action_add ? "add" : "delete")
, (m.act == mapping_t::action::none
? "none" : m.act == mapping_t::action::add ? "add" : "delete")
, total_seconds(m.expires - aux::time_now()));
}
#endif
if (m.action == mapping_t::action_none
|| m.protocol == none)
if (m.act == mapping_t::action::none
|| m.protocol == portmap_protocol::none)
{
try_next_mapping(i);
return;
@ -350,15 +348,15 @@ void natpmp::send_map_request(int const i)
|| m_currently_mapping == i);
m_currently_mapping = i;
mapping_t& m = m_mappings[i];
TORRENT_ASSERT(m.action != mapping_t::action_none);
TORRENT_ASSERT(m.act != mapping_t::action::none);
char buf[12];
char* out = buf;
write_uint8(0, out); // NAT-PMP version
write_uint8(m.protocol, out); // map "protocol"
write_uint8(m.protocol == portmap_protocol::udp ? 1 : 2, out); // map "protocol"
write_uint16(0, out); // reserved
write_uint16(m.local_port, out); // private port
write_uint16(m.external_port, out); // requested public port
int ttl = m.action == mapping_t::action_add ? 3600 : 0;
int ttl = m.act == mapping_t::action::add ? 3600 : 0;
write_uint32(ttl, out); // port mapping lifetime
#ifndef TORRENT_DISABLE_LOGGING
@ -366,8 +364,8 @@ void natpmp::send_map_request(int const i)
{
log("==> port map [ mapping: %d action: %s"
" proto: %s local: %u external: %u ttl: %u ]"
, i, m.action == mapping_t::action_add ? "add" : "delete"
, m.protocol == udp ? "udp" : "tcp"
, i, m.act == mapping_t::action::add ? "add" : "delete"
, m.protocol == portmap_protocol::udp ? "udp" : "tcp"
, m.local_port, m.external_port, ttl);
}
#endif
@ -382,7 +380,7 @@ void natpmp::send_map_request(int const i)
// responses and just remove all mappings
// immediately
m_currently_mapping = -1;
m.action = mapping_t::action_none;
m.act = mapping_t::action::none;
try_next_mapping(i);
}
else
@ -407,7 +405,7 @@ void natpmp::resend_request(int const i, error_code const& e)
if (m_retry_count >= 9 || m_abort)
{
m_currently_mapping = -1;
m_mappings[i].action = mapping_t::action_none;
m_mappings[i].act = mapping_t::action::none;
// try again in two hours
m_mappings[i].expires = aux::time_now() + hours(2);
try_next_mapping(i);
@ -504,7 +502,9 @@ void natpmp::on_reply(error_code const& e
int const public_port = read_uint16(in);
int const lifetime = read_uint32(in);
int const protocol = (cmd - 128 == 1)?udp:tcp;
portmap_protocol const protocol = (cmd - 128 == 1)
? portmap_protocol::udp
: portmap_protocol::tcp;
#ifndef TORRENT_DISABLE_LOGGING
char msg[200];
@ -553,7 +553,7 @@ void natpmp::on_reply(error_code const& e
{
// this means the mapping was
// successfully closed
m->protocol = none;
m->protocol = portmap_protocol::none;
}
else
{
@ -575,14 +575,14 @@ void natpmp::on_reply(error_code const& e
if (result >= 1 && result <= 5) ev = errors[result - 1];
m->expires = aux::time_now() + hours(2);
int const proto = m->protocol;
portmap_protocol const proto = m->protocol;
m_callback.on_port_mapping(index, address(), 0, proto
, error_code(ev, get_libtorrent_category())
, aux::portmap_transport::natpmp);
}
else if (m->action == mapping_t::action_add)
else if (m->act == mapping_t::action::add)
{
int const proto = m->protocol;
portmap_protocol const proto = m->protocol;
m_callback.on_port_mapping(index, m_external_ip, m->external_port, proto
, error_code(errors::no_error, get_libtorrent_category())
, aux::portmap_transport::natpmp);
@ -591,7 +591,7 @@ void natpmp::on_reply(error_code const& e
if (m_abort) return;
m_currently_mapping = -1;
m->action = mapping_t::action_none;
m->act = mapping_t::action::none;
m_send_timer.cancel(ec);
update_expiration_timer();
try_next_mapping(index);
@ -608,15 +608,15 @@ void natpmp::update_expiration_timer()
for (std::vector<mapping_t>::iterator i = m_mappings.begin()
, end(m_mappings.end()); i != end; ++i)
{
if (i->protocol == none
|| i->action != mapping_t::action_none) continue;
if (i->protocol == portmap_protocol::none
|| i->act != mapping_t::action::none) continue;
int index = i - m_mappings.begin();
if (i->expires < now)
{
#ifndef TORRENT_DISABLE_LOGGING
log("mapping %u expired", index);
#endif
i->action = mapping_t::action_add;
i->act = mapping_t::action::add;
if (m_next_refresh == index) m_next_refresh = -1;
update_mapping(index);
}
@ -654,7 +654,7 @@ void natpmp::mapping_expired(error_code const& e, int i)
#ifndef TORRENT_DISABLE_LOGGING
log("mapping %u expired", i);
#endif
m_mappings[i].action = mapping_t::action_add;
m_mappings[i].act = mapping_t::action::add;
if (m_next_refresh == i) m_next_refresh = -1;
update_mapping(i);
}
@ -675,11 +675,14 @@ void natpmp::close_impl()
if (m_disabled) return;
for (auto& m : m_mappings)
{
if (m.protocol == none) continue;
m.action = mapping_t::action_delete;
if (m.protocol == portmap_protocol::none) continue;
m.act = mapping_t::action::del;
}
error_code ec;
m_refresh_timer.cancel(ec);
m_currently_mapping = -1;
update_mapping(0);
}
} // namespace libtorrent

View File

@ -2010,13 +2010,13 @@ namespace aux {
if ((mask & remap_natpmp) && m_natpmp)
{
map_port(*m_natpmp, natpmp::tcp, tcp_ep, s.tcp_port_mapping[0]);
map_port(*m_natpmp, natpmp::udp, udp_ep, s.udp_port_mapping[0]);
map_port(*m_natpmp, portmap_protocol::tcp, tcp_ep, s.tcp_port_mapping[0]);
map_port(*m_natpmp, portmap_protocol::udp, udp_ep, s.udp_port_mapping[0]);
}
if ((mask & remap_upnp) && m_upnp)
{
map_port(*m_upnp, upnp::tcp, tcp_ep, s.tcp_port_mapping[1]);
map_port(*m_upnp, upnp::udp, udp_ep, s.udp_port_mapping[1]);
map_port(*m_upnp, portmap_protocol::tcp, tcp_ep, s.tcp_port_mapping[1]);
map_port(*m_upnp, portmap_protocol::udp, udp_ep, s.udp_port_mapping[1]);
}
}
@ -5407,7 +5407,7 @@ namespace aux {
// transport is 0 for NAT-PMP and 1 for UPnP
void session_impl::on_port_mapping(int mapping, address const& ip, int port
, int const protocol, error_code const& ec
, portmap_protocol const proto, error_code const& ec
, aux::portmap_transport transport)
{
TORRENT_ASSERT(is_single_thread());
@ -5454,7 +5454,7 @@ namespace aux {
if (!ec && m_alerts.should_post<portmap_alert>())
{
m_alerts.emplace_alert<portmap_alert>(mapping, port
, map_transport, protocol == natpmp::udp
, map_transport, proto == portmap_protocol::udp
? portmap_alert::udp : portmap_alert::tcp);
}
}
@ -6539,9 +6539,9 @@ namespace aux {
, int local_port)
{
int ret = 0;
if (m_upnp) ret = m_upnp->add_mapping(static_cast<upnp::protocol_type>(t), external_port
if (m_upnp) ret = m_upnp->add_mapping(static_cast<portmap_protocol>(t), external_port
, local_port);
if (m_natpmp) ret = m_natpmp->add_mapping(static_cast<natpmp::protocol_type>(t), external_port
if (m_natpmp) ret = m_natpmp->add_mapping(static_cast<portmap_protocol>(t), external_port
, local_port);
return ret;
}

View File

@ -56,6 +56,8 @@ using namespace std::placeholders;
namespace libtorrent {
using namespace aux;
namespace upnp_errors
{
boost::system::error_code make_error_code(error_code_enum e)
@ -178,7 +180,8 @@ void upnp::discover_device_impl()
}
// returns a reference to a mapping or -1 on failure
int upnp::add_mapping(upnp::protocol_type p, int external_port, int local_port)
int upnp::add_mapping(portmap_protocol const p, int const external_port
, int const local_port)
{
TORRENT_ASSERT(is_single_thread());
// external port 0 means _every_ port
@ -186,14 +189,15 @@ int upnp::add_mapping(upnp::protocol_type p, int external_port, int local_port)
#ifndef TORRENT_DISABLE_LOGGING
log("adding port map: [ protocol: %s ext_port: %u "
"local_port: %u ] %s", (p == tcp?"tcp":"udp"), external_port
"local_port: %u ] %s", (p == portmap_protocol::tcp?"tcp":"udp")
, external_port
, local_port, m_disabled ? "DISABLED": "");
#endif
if (m_disabled) return -1;
std::vector<global_mapping_t>::iterator mapping_it = std::find_if(
m_mappings.begin(), m_mappings.end()
, [](global_mapping_t const& m) { return m.protocol == none; });
, [](global_mapping_t const& m) { return m.protocol == portmap_protocol::none; });
if (mapping_it == m_mappings.end())
{
@ -216,7 +220,7 @@ int upnp::add_mapping(upnp::protocol_type p, int external_port, int local_port)
d.mapping.resize(mapping_index + 1);
mapping_t& m = d.mapping[mapping_index];
m.action = mapping_t::action_add;
m.act = mapping_t::action::add;
m.protocol = p;
m.external_port = external_port;
m.local_port = local_port;
@ -237,11 +241,11 @@ void upnp::delete_mapping(int mapping)
#ifndef TORRENT_DISABLE_LOGGING
log("deleting port map: [ protocol: %s ext_port: %u "
"local_port: %u ]", (m.protocol == tcp?"tcp":"udp"), m.external_port
"local_port: %u ]", (m.protocol == portmap_protocol::tcp?"tcp":"udp"), m.external_port
, m.local_port);
#endif
if (m.protocol == none) return;
if (m.protocol == portmap_protocol::none) return;
for (auto const& dev : m_devices)
{
@ -249,7 +253,7 @@ void upnp::delete_mapping(int mapping)
TORRENT_ASSERT(d.magic == 1337);
TORRENT_ASSERT(mapping < int(d.mapping.size()));
d.mapping[mapping].action = mapping_t::action_delete;
d.mapping[mapping].act = mapping_t::action::del;
if (d.service_namespace) update_map(d, mapping);
}
@ -258,13 +262,13 @@ void upnp::delete_mapping(int mapping)
bool upnp::get_mapping(int const index
, int& local_port
, int& external_port
, int& protocol) const
, portmap_protocol& protocol) const
{
TORRENT_ASSERT(is_single_thread());
TORRENT_ASSERT(index < int(m_mappings.size()) && index >= 0);
if (index >= int(m_mappings.size()) || index < 0) return false;
global_mapping_t const& m = m_mappings[index];
if (m.protocol == none) return false;
if (m.protocol == portmap_protocol::none) return false;
local_port = m.local_port;
external_port = m.external_port;
protocol = m.protocol;
@ -582,7 +586,7 @@ void upnp::on_reply(udp::endpoint const& from, char* buffer
for (auto const& j : m_mappings)
{
mapping_t m;
m.action = mapping_t::action_add;
m.act = mapping_t::action::add;
m.local_port = j.local_port;
m.external_port = j.external_port;
m.protocol = j.protocol;
@ -740,7 +744,7 @@ void upnp::create_port_mapping(http_connection& c, rootdevice& d, int i)
"<NewLeaseDuration>%u</NewLeaseDuration>"
"</u:%s></s:Body></s:Envelope>"
, soap_action, d.service_namespace, d.mapping[i].external_port
, (d.mapping[i].protocol == udp ? "UDP" : "TCP")
, (d.mapping[i].protocol == portmap_protocol::udp ? "UDP" : "TCP")
, d.mapping[i].local_port
, local_endpoint.c_str()
, m_user_agent.c_str(), local_endpoint.c_str(), d.mapping[i].local_port
@ -759,7 +763,7 @@ void upnp::next(rootdevice& d, int i)
else
{
std::vector<mapping_t>::iterator j = std::find_if(d.mapping.begin(), d.mapping.end()
, [] (mapping_t const& m) { return m.action != mapping_t::action_none; });
, [] (mapping_t const& m) { return m.act != mapping_t::action::none; });
if (j == d.mapping.end()) return;
update_map(d, j - d.mapping.begin());
@ -779,13 +783,13 @@ void upnp::update_map(rootdevice& d, int i)
mapping_t& m = d.mapping[i];
if (m.action == mapping_t::action_none
|| m.protocol == none)
if (m.act == mapping_t::action::none
|| m.protocol == portmap_protocol::none)
{
#ifndef TORRENT_DISABLE_LOGGING
log("mapping %u does not need updating, skipping", i);
#endif
m.action = mapping_t::action_none;
m.act = mapping_t::action::none;
next(d, i);
return;
}
@ -796,11 +800,11 @@ void upnp::update_map(rootdevice& d, int i)
#ifndef TORRENT_DISABLE_LOGGING
log("connecting to %s", d.hostname.c_str());
#endif
if (m.action == mapping_t::action_add)
if (m.act == mapping_t::action::add)
{
if (m.failcount > 5)
{
m.action = mapping_t::action_none;
m.act = mapping_t::action::none;
// giving up
next(d, i);
return;
@ -816,7 +820,7 @@ void upnp::update_map(rootdevice& d, int i)
d.upnp_connection->start(d.hostname, d.port
, seconds(10), 1);
}
else if (m.action == mapping_t::action_delete)
else if (m.act == mapping_t::action::del)
{
if (d.upnp_connection) d.upnp_connection->close();
d.upnp_connection.reset(new http_connection(m_io_service
@ -828,7 +832,7 @@ void upnp::update_map(rootdevice& d, int i)
, seconds(10), 1);
}
m.action = mapping_t::action_none;
m.act = mapping_t::action::none;
}
void upnp::delete_port_mapping(rootdevice& d, int i)
@ -860,7 +864,7 @@ void upnp::delete_port_mapping(rootdevice& d, int i)
"</u:%s></s:Body></s:Envelope>"
, soap_action, d.service_namespace
, d.mapping[i].external_port
, (d.mapping[i].protocol == udp ? "UDP" : "TCP")
, (d.mapping[i].protocol == portmap_protocol::udp ? "UDP" : "TCP")
, soap_action);
post(d, soap, soap_action);
@ -1095,9 +1099,9 @@ void upnp::disable(error_code const& ec)
for (std::vector<global_mapping_t>::iterator i = m_mappings.begin()
, end(m_mappings.end()); i != end; ++i)
{
if (i->protocol == none) continue;
int const proto = i->protocol;
i->protocol = none;
if (i->protocol == portmap_protocol::none) continue;
portmap_protocol const proto = i->protocol;
i->protocol = portmap_protocol::none;
m_callback.on_port_mapping(i - m_mappings.begin(), address(), 0, proto, ec
, aux::portmap_transport::upnp);
}
@ -1410,7 +1414,7 @@ void upnp::on_upnp_map_response(error_code const& e
{
// only permanent leases supported
d.lease_duration = 0;
m.action = mapping_t::action_add;
m.act = mapping_t::action::add;
++m.failcount;
update_map(d, mapping);
return;
@ -1425,7 +1429,7 @@ void upnp::on_upnp_map_response(error_code const& e
// The external port conflicts with another mapping
// pick a random port
m.external_port = 40000 + random(10000);
m.action = mapping_t::action_add;
m.act = mapping_t::action::add;
++m.failcount;
update_map(d, mapping);
return;
@ -1488,7 +1492,7 @@ void upnp::return_error(int mapping, int code)
error_string += ": ";
error_string += e->msg;
}
const int proto = m_mappings[mapping].protocol;
portmap_protocol const proto = m_mappings[mapping].protocol;
m_callback.on_port_mapping(mapping, address(), 0, proto, error_code(code, get_upnp_category())
, aux::portmap_transport::upnp);
}
@ -1551,14 +1555,14 @@ void upnp::on_upnp_unmap_response(error_code const& e
xml_parse(p.get_body(), std::bind(&find_error_code, _1, _2, std::ref(s)));
}
int const proto = m_mappings[mapping].protocol;
portmap_protocol const proto = m_mappings[mapping].protocol;
m_callback.on_port_mapping(mapping, address(), 0, proto, p.status_code() != 200
? error_code(p.status_code(), get_http_category())
: error_code(s.error_code, get_upnp_category())
, aux::portmap_transport::upnp);
d.mapping[mapping].protocol = none;
d.mapping[mapping].protocol = portmap_protocol::none;
next(d, mapping);
}
@ -1622,14 +1626,14 @@ void upnp::close()
for (std::vector<mapping_t>::iterator j = d.mapping.begin()
, end2(d.mapping.end()); j != end2; ++j)
{
if (j->protocol == none) continue;
if (j->action == mapping_t::action_add)
if (j->protocol == portmap_protocol::none) continue;
if (j->act == mapping_t::action::add)
{
j->action = mapping_t::action_none;
j->act = mapping_t::action::none;
continue;
}
j->action = mapping_t::action_delete;
m_mappings[j - d.mapping.begin()].protocol = none;
j->act = mapping_t::action::del;
m_mappings[j - d.mapping.begin()].protocol = portmap_protocol::none;
}
if (num_mappings() > 0) update_map(d, 0);
}

View File

@ -7,6 +7,8 @@ exe test_natpmp : test_natpmp.cpp
: # requirements
<library>/torrent//torrent
<export-extra>on
# disable warning C4373: virtual function overrides, previous versions of the compiler did not override when parameters only differed by const/volatile qualifiers
<toolset>msvc:<cflags>/wd4373
: # default-build
<threading>multi
<asserts>on
@ -21,6 +23,8 @@ exe enum_if : enum_if.cpp
: # requirements
<library>/torrent//torrent
<export-extra>on
# disable warning C4373: virtual function overrides, previous versions of the compiler did not override when parameters only differed by const/volatile qualifiers
<toolset>msvc:<cflags>/wd4373
: # default-build
<threading>multi
<asserts>on
@ -62,6 +66,8 @@ lib libtorrent_test
<toolset>darwin:<cflags>-Wno-unused-command-line-argument
# disable warning C4275: non DLL-interface classkey 'identifier' used as base for DLL-interface classkey 'identifier'
<toolset>msvc:<cflags>/wd4275
# disable warning C4373: virtual function overrides, previous versions of the compiler did not override when parameters only differed by const/volatile qualifiers
<toolset>msvc:<cflags>/wd4373
: # default build
<link>shared
@ -83,6 +89,8 @@ project
<toolset>darwin:<cflags>-Wno-unused-command-line-argument
# disable warning C4275: non DLL-interface classkey 'identifier' used as base for DLL-interface classkey 'identifier'
<toolset>msvc:<cflags>/wd4275
# disable warning C4373: virtual function overrides, previous versions of the compiler did not override when parameters only differed by const/volatile qualifiers
<toolset>msvc:<cflags>/wd4373
<toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS
<export-extra>on
: default-build

View File

@ -39,18 +39,20 @@ POSSIBILITY OF SUCH DAMAGE.
using namespace libtorrent;
using libtorrent::aux::portmap_protocol;
namespace
{
struct natpmp_callback : aux::portmap_callback
{
void on_port_mapping(int mapping, address const& ip, int port
, int protocol, error_code const& err
, portmap_protocol const protocol, error_code const& err
, aux::portmap_transport transport) override
{
std::cerr
<< "mapping: " << mapping
<< ", port: " << port
<< ", protocol: " << protocol
<< ", protocol: " << static_cast<int>(protocol)
<< ", external-IP: " << print_address(ip)
<< ", error: \"" << err.message() << "\"\n";
}
@ -84,8 +86,8 @@ int main(int argc, char* argv[])
deadline_timer timer(ios);
int const tcp_map = natpmp_handler->add_mapping(natpmp::tcp, atoi(argv[1]), atoi(argv[1]));
natpmp_handler->add_mapping(natpmp::udp, atoi(argv[2]), atoi(argv[2]));
int const tcp_map = natpmp_handler->add_mapping(portmap_protocol::tcp, atoi(argv[1]), atoi(argv[1]));
natpmp_handler->add_mapping(portmap_protocol::udp, atoi(argv[2]), atoi(argv[2]));
error_code ec;
timer.expires_from_now(seconds(2), ec);

View File

@ -43,6 +43,8 @@ POSSIBILITY OF SUCH DAMAGE.
namespace lt = libtorrent;
using namespace libtorrent;
using libtorrent::aux::portmap_protocol;
broadcast_socket* sock = nullptr;
int g_port = 0;
@ -118,13 +120,14 @@ namespace
struct upnp_callback : aux::portmap_callback
{
void on_port_mapping(int mapping, address const& ip, int port
, int protocol, error_code const& err
, portmap_protocol const protocol, error_code const& err
, aux::portmap_transport transport) override
{
callback_info info = {mapping, port, err};
callbacks.push_back(info);
std::cerr << "mapping: " << mapping << ", port: " << port << ", IP: " << ip
<< ", proto: " << protocol << ", error: \"" << err.message() << "\"\n";
<< ", proto: " << static_cast<int>(protocol)
<< ", error: \"" << err.message() << "\"\n";
}
#ifndef TORRENT_DISABLE_LOGGING
virtual bool should_log_portmap(aux::portmap_transport transport) const override
@ -195,8 +198,8 @@ void run_upnp_test(char const* root_filename, char const* router_model, char con
std::cerr << "router: " << upnp_handler->router_model() << std::endl;
TEST_EQUAL(upnp_handler->router_model(), router_model);
int mapping1 = upnp_handler->add_mapping(upnp::tcp, 500, 500);
int mapping2 = upnp_handler->add_mapping(upnp::udp, 501, 501);
int mapping1 = upnp_handler->add_mapping(portmap_protocol::tcp, 500, 500);
int mapping2 = upnp_handler->add_mapping(portmap_protocol::udp, 501, 501);
for (int i = 0; i < 40; ++i)
{