forked from premiere/premiere-libtorrent
add base_mapping_t (#2025)
factor out parts of mapping struct from NATPMP and UPnP
This commit is contained in:
parent
4709c03ab1
commit
4cee8104d7
|
@ -48,6 +48,11 @@ namespace libtorrent { namespace aux {
|
|||
none, tcp, udp
|
||||
};
|
||||
|
||||
enum class portmap_action : std::uint8_t
|
||||
{
|
||||
none, add, del
|
||||
};
|
||||
|
||||
struct TORRENT_EXTRA_EXPORT portmap_callback
|
||||
{
|
||||
// int: port-mapping index
|
||||
|
@ -66,6 +71,30 @@ namespace libtorrent { namespace aux {
|
|||
protected:
|
||||
~portmap_callback() {}
|
||||
};
|
||||
|
||||
struct base_mapping
|
||||
{
|
||||
// the time the port mapping will expire
|
||||
time_point expires;
|
||||
|
||||
portmap_action act = portmap_action::none;
|
||||
|
||||
// the external (on the NAT router) port
|
||||
// for the mapping. This is the port we
|
||||
// should announce to others
|
||||
int external_port = 0;
|
||||
|
||||
portmap_protocol protocol = portmap_protocol::none;
|
||||
};
|
||||
|
||||
inline char const* to_string(portmap_protocol const p)
|
||||
{
|
||||
return p == portmap_protocol::udp ? "UDP" : "TCP";
|
||||
}
|
||||
inline char const* to_string(portmap_action const act)
|
||||
{
|
||||
return act == portmap_action::none ? "none" : act == portmap_action::add ? "add" : "delete";
|
||||
}
|
||||
}}
|
||||
|
||||
#endif // LIBTORRENT_PORTMAP_HPP
|
||||
|
|
|
@ -77,35 +77,14 @@ private:
|
|||
void mapping_expired(error_code const& e, int i);
|
||||
void close_impl();
|
||||
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
bool should_log() const;
|
||||
void log(char const* fmt, ...) const TORRENT_FORMAT(2, 3);
|
||||
#endif
|
||||
|
||||
void disable(error_code const& ec);
|
||||
|
||||
struct mapping_t
|
||||
struct mapping_t : public aux::base_mapping
|
||||
{
|
||||
enum class action : std::uint8_t { none, add, del };
|
||||
|
||||
// indicates that the mapping has changed
|
||||
// and needs an update
|
||||
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 = 0;
|
||||
|
||||
// the external (on the NAT router) port
|
||||
// for the mapping. This is the port we
|
||||
// should announce to others
|
||||
int external_port = 0;
|
||||
|
||||
aux::portmap_protocol protocol = aux::portmap_protocol::none;
|
||||
|
||||
// set to true when the first map request is sent
|
||||
bool map_sent = false;
|
||||
|
||||
|
@ -113,6 +92,12 @@ private:
|
|||
bool outstanding_request = false;
|
||||
};
|
||||
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
bool should_log() const;
|
||||
void log(char const* fmt, ...) const TORRENT_FORMAT(2, 3);
|
||||
void mapping_log(char const* op, mapping_t const& m) const;
|
||||
#endif
|
||||
|
||||
aux::portmap_callback& m_callback;
|
||||
|
||||
aux::vector<mapping_t> m_mappings;
|
||||
|
|
|
@ -252,15 +252,8 @@ private:
|
|||
tcp::endpoint local_ep;
|
||||
};
|
||||
|
||||
struct mapping_t
|
||||
struct mapping_t : public aux::base_mapping
|
||||
{
|
||||
enum class action : std::uint8_t { none, add, del };
|
||||
|
||||
// the time the port mapping will expire
|
||||
time_point expires;
|
||||
|
||||
action act = action::none;
|
||||
|
||||
// the local port for this mapping. If this is set
|
||||
// to 0, the mapping is not in use
|
||||
tcp::endpoint local_ep;
|
||||
|
@ -270,9 +263,6 @@ private:
|
|||
// should announce to others
|
||||
int external_port = 0;
|
||||
|
||||
// 2 = udp, 1 = tcp
|
||||
aux::portmap_protocol protocol = aux::portmap_protocol::none;
|
||||
|
||||
// the number of times this mapping has failed
|
||||
int failcount = 0;
|
||||
};
|
||||
|
|
|
@ -131,9 +131,9 @@ void natpmp::start()
|
|||
, end(m_mappings.end()); i != end; ++i)
|
||||
{
|
||||
if (i->protocol == portmap_protocol::none
|
||||
|| i->act != mapping_t::action::none)
|
||||
|| i->act != portmap_action::none)
|
||||
continue;
|
||||
i->act = mapping_t::action::add;
|
||||
i->act = portmap_action::add;
|
||||
update_mapping(int(i - m_mappings.begin()));
|
||||
}
|
||||
}
|
||||
|
@ -176,6 +176,21 @@ bool natpmp::should_log() const
|
|||
return m_callback.should_log_portmap(aux::portmap_transport::natpmp);
|
||||
}
|
||||
|
||||
void natpmp::mapping_log(char const* op, mapping_t const& m) const
|
||||
{
|
||||
if (should_log())
|
||||
{
|
||||
log("%s-mapping: proto: %s port: %d local-port: %d action: %s ttl: %" PRId64
|
||||
, op
|
||||
, m.protocol == portmap_protocol::none
|
||||
? "none" : to_string(m.protocol)
|
||||
, m.external_port
|
||||
, m.local_port
|
||||
, to_string(m.act)
|
||||
, total_seconds(m.expires - aux::time_now()));
|
||||
}
|
||||
}
|
||||
|
||||
TORRENT_FORMAT(2, 3)
|
||||
void natpmp::log(char const* fmt, ...) const
|
||||
{
|
||||
|
@ -219,12 +234,12 @@ void natpmp::delete_mapping(int const index)
|
|||
if (m.protocol == portmap_protocol::none) return;
|
||||
if (!m.map_sent)
|
||||
{
|
||||
m.act = mapping_t::action::none;
|
||||
m.act = portmap_action::none;
|
||||
m.protocol = portmap_protocol::none;
|
||||
return;
|
||||
}
|
||||
|
||||
m.act = mapping_t::action::del;
|
||||
m.act = portmap_action::del;
|
||||
update_mapping(index);
|
||||
}
|
||||
|
||||
|
@ -245,22 +260,11 @@ int natpmp::add_mapping(portmap_protocol const p, int const external_port
|
|||
i->protocol = p;
|
||||
i->external_port = external_port;
|
||||
i->local_port = local_ep.port();
|
||||
i->act = mapping_t::action::add;
|
||||
i->act = portmap_action::add;
|
||||
|
||||
int const mapping_index = int(i - m_mappings.begin());
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
if (should_log())
|
||||
{
|
||||
natpmp::mapping_t const& m = *i;
|
||||
log("add-mapping: proto: %s port: %d local-port: %d action: %s ttl: %" PRId64
|
||||
, (m.protocol == portmap_protocol::none
|
||||
? "none" : m.protocol == portmap_protocol::tcp ? "tcp" : "udp")
|
||||
, m.external_port
|
||||
, m.local_port
|
||||
, (m.act == mapping_t::action::none
|
||||
? "none" : m.act == mapping_t::action::add ? "add" : "delete")
|
||||
, total_seconds(m.expires - aux::time_now()));
|
||||
}
|
||||
mapping_log("add",*i);
|
||||
#endif
|
||||
|
||||
update_mapping(mapping_index);
|
||||
|
@ -278,7 +282,7 @@ void natpmp::try_next_mapping(int const i)
|
|||
|
||||
auto const m = std::find_if(
|
||||
m_mappings.begin(), m_mappings.end()
|
||||
, [] (mapping_t const& ma) { return ma.act != mapping_t::action::none
|
||||
, [] (mapping_t const& ma) { return ma.act != portmap_action::none
|
||||
&& ma.protocol != portmap_protocol::none; });
|
||||
|
||||
if (m == m_mappings.end())
|
||||
|
@ -312,20 +316,10 @@ void natpmp::update_mapping(int const i)
|
|||
natpmp::mapping_t const& m = m_mappings[i];
|
||||
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
if (should_log())
|
||||
{
|
||||
log("update-mapping: proto: %s port: %d local-port: %d action: %s ttl: %" PRId64
|
||||
, (m.protocol == portmap_protocol::none
|
||||
? "none" : m.protocol == portmap_protocol::tcp ? "tcp" : "udp")
|
||||
, m.external_port
|
||||
, m.local_port
|
||||
, (m.act == mapping_t::action::none
|
||||
? "none" : m.act == mapping_t::action::add ? "add" : "delete")
|
||||
, total_seconds(m.expires - aux::time_now()));
|
||||
}
|
||||
mapping_log("update", m);
|
||||
#endif
|
||||
|
||||
if (m.act == mapping_t::action::none
|
||||
if (m.act == portmap_action::none
|
||||
|| m.protocol == portmap_protocol::none)
|
||||
{
|
||||
try_next_mapping(i);
|
||||
|
@ -350,7 +344,7 @@ 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.act != mapping_t::action::none);
|
||||
TORRENT_ASSERT(m.act != portmap_action::none);
|
||||
char buf[12];
|
||||
char* out = buf;
|
||||
write_uint8(0, out); // NAT-PMP version
|
||||
|
@ -358,7 +352,7 @@ void natpmp::send_map_request(int const i)
|
|||
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.act == mapping_t::action::add ? 3600 : 0;
|
||||
int ttl = m.act == portmap_action::add ? 3600 : 0;
|
||||
write_uint32(ttl, out); // port mapping lifetime
|
||||
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
|
@ -366,8 +360,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.act == mapping_t::action::add ? "add" : "delete"
|
||||
, m.protocol == portmap_protocol::udp ? "udp" : "tcp"
|
||||
, i, to_string(m.act)
|
||||
, to_string(m.protocol)
|
||||
, m.local_port, m.external_port, ttl);
|
||||
}
|
||||
#endif
|
||||
|
@ -382,7 +376,7 @@ void natpmp::send_map_request(int const i)
|
|||
// responses and just remove all mappings
|
||||
// immediately
|
||||
m_currently_mapping = -1;
|
||||
m.act = mapping_t::action::none;
|
||||
m.act = portmap_action::none;
|
||||
try_next_mapping(i);
|
||||
}
|
||||
else
|
||||
|
@ -407,7 +401,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].act = mapping_t::action::none;
|
||||
m_mappings[i].act = portmap_action::none;
|
||||
// try again in two hours
|
||||
m_mappings[i].expires = aux::time_now() + hours(2);
|
||||
try_next_mapping(i);
|
||||
|
@ -565,13 +559,13 @@ void natpmp::on_reply(error_code const& e
|
|||
if (result != 0)
|
||||
{
|
||||
// TODO: 3 it would be nice to have a separate NAT-PMP error category
|
||||
errors::error_code_enum errors[] =
|
||||
static errors::error_code_enum const errors[] =
|
||||
{
|
||||
errors::unsupported_protocol_version,
|
||||
errors::natpmp_not_authorized,
|
||||
errors::network_failure,
|
||||
errors::no_resources,
|
||||
errors::unsupported_opcode,
|
||||
errors::unsupported_opcode
|
||||
};
|
||||
errors::error_code_enum ev = errors::no_error;
|
||||
if (result >= 1 && result <= 5) ev = errors[result - 1];
|
||||
|
@ -581,7 +575,7 @@ void natpmp::on_reply(error_code const& e
|
|||
m_callback.on_port_mapping(index, address(), 0, proto
|
||||
, ev, aux::portmap_transport::natpmp);
|
||||
}
|
||||
else if (m->act == mapping_t::action::add)
|
||||
else if (m->act == portmap_action::add)
|
||||
{
|
||||
portmap_protocol const proto = m->protocol;
|
||||
m_callback.on_port_mapping(index, m_external_ip, m->external_port, proto
|
||||
|
@ -591,7 +585,7 @@ void natpmp::on_reply(error_code const& e
|
|||
if (m_abort) return;
|
||||
|
||||
m_currently_mapping = -1;
|
||||
m->act = mapping_t::action::none;
|
||||
m->act = portmap_action::none;
|
||||
m_send_timer.cancel(ec);
|
||||
update_expiration_timer();
|
||||
try_next_mapping(index);
|
||||
|
@ -609,14 +603,14 @@ void natpmp::update_expiration_timer()
|
|||
, end(m_mappings.end()); i != end; ++i)
|
||||
{
|
||||
if (i->protocol == portmap_protocol::none
|
||||
|| i->act != mapping_t::action::none) continue;
|
||||
|| i->act != portmap_action::none) continue;
|
||||
int const index = int(i - m_mappings.begin());
|
||||
if (i->expires < now)
|
||||
{
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
log("mapping %u expired", index);
|
||||
#endif
|
||||
i->act = mapping_t::action::add;
|
||||
i->act = portmap_action::add;
|
||||
if (m_next_refresh == index) m_next_refresh = -1;
|
||||
update_mapping(index);
|
||||
}
|
||||
|
@ -654,7 +648,7 @@ void natpmp::mapping_expired(error_code const& e, int const i)
|
|||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
log("mapping %u expired", i);
|
||||
#endif
|
||||
m_mappings[i].act = mapping_t::action::add;
|
||||
m_mappings[i].act = portmap_action::add;
|
||||
if (m_next_refresh == i) m_next_refresh = -1;
|
||||
update_mapping(i);
|
||||
}
|
||||
|
@ -676,7 +670,7 @@ void natpmp::close_impl()
|
|||
for (auto& m : m_mappings)
|
||||
{
|
||||
if (m.protocol == portmap_protocol::none) continue;
|
||||
m.act = mapping_t::action::del;
|
||||
m.act = portmap_action::del;
|
||||
}
|
||||
error_code ec;
|
||||
m_refresh_timer.cancel(ec);
|
||||
|
|
39
src/upnp.cpp
39
src/upnp.cpp
|
@ -221,7 +221,7 @@ int upnp::add_mapping(portmap_protocol const p, int const external_port
|
|||
d.mapping.resize(mapping_index + 1);
|
||||
mapping_t& m = d.mapping[mapping_index];
|
||||
|
||||
m.act = mapping_t::action::add;
|
||||
m.act = portmap_action::add;
|
||||
m.protocol = p;
|
||||
m.external_port = external_port;
|
||||
m.local_ep = local_ep;
|
||||
|
@ -238,7 +238,7 @@ void upnp::delete_mapping(int const mapping)
|
|||
|
||||
if (mapping >= int(m_mappings.size())) return;
|
||||
|
||||
global_mapping_t& m = m_mappings[mapping];
|
||||
global_mapping_t const& m = m_mappings[mapping];
|
||||
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
log("deleting port map: [ protocol: %s ext_port: %u "
|
||||
|
@ -254,7 +254,7 @@ void upnp::delete_mapping(int const mapping)
|
|||
TORRENT_ASSERT(d.magic == 1337);
|
||||
|
||||
TORRENT_ASSERT(mapping < d.mapping.end_index());
|
||||
d.mapping[mapping].act = mapping_t::action::del;
|
||||
d.mapping[mapping].act = portmap_action::del;
|
||||
|
||||
if (!d.service_namespace.empty()) update_map(d, mapping);
|
||||
}
|
||||
|
@ -585,7 +585,7 @@ void upnp::on_reply(udp::endpoint const& from, char* buffer
|
|||
for (auto const& j : m_mappings)
|
||||
{
|
||||
mapping_t m;
|
||||
m.act = mapping_t::action::add;
|
||||
m.act = portmap_action::add;
|
||||
m.local_ep = j.local_ep;
|
||||
m.external_port = j.external_port;
|
||||
m.protocol = j.protocol;
|
||||
|
@ -743,7 +743,7 @@ void upnp::create_port_mapping(http_connection& c, rootdevice& d, int const i)
|
|||
"<NewLeaseDuration>%u</NewLeaseDuration>"
|
||||
"</u:%s></s:Body></s:Envelope>"
|
||||
, soap_action, d.service_namespace.c_str(), d.mapping[i].external_port
|
||||
, (d.mapping[i].protocol == portmap_protocol::udp ? "UDP" : "TCP")
|
||||
, to_string(d.mapping[i].protocol)
|
||||
, d.mapping[i].local_ep.port()
|
||||
, local_endpoint.c_str()
|
||||
, m_user_agent.c_str(), local_endpoint.c_str(), d.mapping[i].local_ep.port()
|
||||
|
@ -762,7 +762,7 @@ void upnp::next(rootdevice& d, int const i)
|
|||
else
|
||||
{
|
||||
auto const j = std::find_if(d.mapping.begin(), d.mapping.end()
|
||||
, [] (mapping_t const& m) { return m.act != mapping_t::action::none; });
|
||||
, [] (mapping_t const& m) { return m.act != portmap_action::none; });
|
||||
if (j == d.mapping.end()) return;
|
||||
|
||||
update_map(d, int(j - d.mapping.begin()));
|
||||
|
@ -782,13 +782,13 @@ void upnp::update_map(rootdevice& d, int const i)
|
|||
|
||||
mapping_t& m = d.mapping[i];
|
||||
|
||||
if (m.act == mapping_t::action::none
|
||||
if (m.act == portmap_action::none
|
||||
|| m.protocol == portmap_protocol::none)
|
||||
{
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
log("mapping %u does not need updating, skipping", i);
|
||||
#endif
|
||||
m.act = mapping_t::action::none;
|
||||
m.act = portmap_action::none;
|
||||
next(d, i);
|
||||
return;
|
||||
}
|
||||
|
@ -799,11 +799,11 @@ void upnp::update_map(rootdevice& d, int const i)
|
|||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
log("connecting to %s", d.hostname.c_str());
|
||||
#endif
|
||||
if (m.act == mapping_t::action::add)
|
||||
if (m.act == portmap_action::add)
|
||||
{
|
||||
if (m.failcount > 5)
|
||||
{
|
||||
m.act = mapping_t::action::none;
|
||||
m.act = portmap_action::none;
|
||||
// giving up
|
||||
next(d, i);
|
||||
return;
|
||||
|
@ -819,7 +819,7 @@ void upnp::update_map(rootdevice& d, int const i)
|
|||
d.upnp_connection->start(d.hostname, d.port
|
||||
, seconds(10), 1, NULL, false, 5, m.local_ep.address());
|
||||
}
|
||||
else if (m.act == mapping_t::action::del)
|
||||
else if (m.act == portmap_action::del)
|
||||
{
|
||||
if (d.upnp_connection) d.upnp_connection->close();
|
||||
d.upnp_connection = std::make_shared<http_connection>(m_io_service
|
||||
|
@ -831,7 +831,7 @@ void upnp::update_map(rootdevice& d, int const i)
|
|||
, seconds(10), 1, NULL, false, 5, m.local_ep.address());
|
||||
}
|
||||
|
||||
m.act = mapping_t::action::none;
|
||||
m.act = portmap_action::none;
|
||||
}
|
||||
|
||||
void upnp::delete_port_mapping(rootdevice& d, int const i)
|
||||
|
@ -863,7 +863,7 @@ void upnp::delete_port_mapping(rootdevice& d, int const i)
|
|||
"</u:%s></s:Body></s:Envelope>"
|
||||
, soap_action, d.service_namespace.c_str()
|
||||
, d.mapping[i].external_port
|
||||
, (d.mapping[i].protocol == portmap_protocol::udp ? "UDP" : "TCP")
|
||||
, to_string(d.mapping[i].protocol)
|
||||
, soap_action);
|
||||
|
||||
post(d, soap, soap_action);
|
||||
|
@ -1106,8 +1106,7 @@ void find_error_code(int const type, string_view string, error_code_parse_state&
|
|||
}
|
||||
else if (type == xml_string && state.in_error_code)
|
||||
{
|
||||
std::string error_code_str(string.begin(), string.end());
|
||||
state.error_code = std::atoi(error_code_str.c_str());
|
||||
state.error_code = std::atoi(string.to_string().c_str());
|
||||
state.exit = true;
|
||||
}
|
||||
}
|
||||
|
@ -1380,7 +1379,7 @@ void upnp::on_upnp_map_response(error_code const& e
|
|||
{
|
||||
// only permanent leases supported
|
||||
d.lease_duration = 0;
|
||||
m.act = mapping_t::action::add;
|
||||
m.act = portmap_action::add;
|
||||
++m.failcount;
|
||||
update_map(d, mapping);
|
||||
return;
|
||||
|
@ -1395,7 +1394,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 + int(random(10000));
|
||||
m.act = mapping_t::action::add;
|
||||
m.act = portmap_action::add;
|
||||
++m.failcount;
|
||||
update_map(d, mapping);
|
||||
return;
|
||||
|
@ -1594,12 +1593,12 @@ void upnp::close()
|
|||
, end2(d.mapping.end()); j != end2; ++j)
|
||||
{
|
||||
if (j->protocol == portmap_protocol::none) continue;
|
||||
if (j->act == mapping_t::action::add)
|
||||
if (j->act == portmap_action::add)
|
||||
{
|
||||
j->act = mapping_t::action::none;
|
||||
j->act = portmap_action::none;
|
||||
continue;
|
||||
}
|
||||
j->act = mapping_t::action::del;
|
||||
j->act = portmap_action::del;
|
||||
m_mappings[int(j - d.mapping.begin())].protocol = portmap_protocol::none;
|
||||
}
|
||||
if (num_mappings() > 0) update_map(d, 0);
|
||||
|
|
Loading…
Reference in New Issue