upnp and natpmp modernization and cleanup (#1103)
upnp and natpmp modernization and cleanup
This commit is contained in:
parent
527772420a
commit
219b2c36b4
|
@ -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;
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
107
src/natpmp.cpp
107
src/natpmp.cpp
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
70
src/upnp.cpp
70
src/upnp.cpp
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue