improved natpmp logging and handling of mapped ports in session

This commit is contained in:
Arvid Norberg 2008-11-16 02:11:04 +00:00
parent e9a33e6a05
commit a48ffe36e0
6 changed files with 89 additions and 43 deletions

View File

@ -176,6 +176,7 @@ namespace libtorrent
void start_dht(entry const& startup_state);
void stop_dht();
entry dht_state() const;
void maybe_update_udp_mapping(int nat, int local_port, int external_port);
#endif
#ifndef TORRENT_DISABLE_ENCRYPTION

View File

@ -63,6 +63,7 @@ public:
enum protocol_type { none = 0, udp = 1, tcp = 2 };
int add_mapping(protocol_type 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;
void close();
@ -88,6 +89,7 @@ private:
, local_port(0)
, external_port(0)
, protocol(none)
, map_sent(false)
{}
// indicates that the mapping has changed
@ -107,6 +109,9 @@ private:
int external_port;
int protocol;
// set to true when the first map request is sent
bool map_sent;
};
portmap_callback_t m_callback;

View File

@ -79,6 +79,7 @@ public:
enum protocol_type { none = 0, udp = 1, tcp = 2 };
int add_mapping(protocol_type 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;
void discover_device();
void close();

View File

@ -114,6 +114,18 @@ void natpmp::rebind(address const& listen_interface)
}
}
bool natpmp::get_mapping(int index, int& local_port, int& external_port, int& protocol) const
{
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;
local_port = m.local_port;
external_port = m.external_port;
protocol = m.protocol;
return true;
}
void natpmp::log(std::string const& msg)
{
m_callback(-1, 0, msg);
@ -132,6 +144,7 @@ void natpmp::disable(char const* message)
}
close();
}
void natpmp::delete_mapping(int index)
{
TORRENT_ASSERT(index < int(m_mappings.size()) && index >= 0);
@ -139,6 +152,12 @@ void natpmp::delete_mapping(int index)
mapping_t& m = m_mappings[index];
if (m.protocol == none) return;
if (!m.map_sent)
{
m.action = mapping_t::action_none;
m.protocol = none;
return;
}
m.action = mapping_t::action_delete;
update_mapping(index);
@ -270,7 +289,7 @@ void natpmp::send_map_request(int i)
write_uint32(ttl, out); // port mapping lifetime
std::stringstream msg;
msg << "port map [ action: " << (m.action == mapping_t::action_add ? "add" : "delete")
msg << "==> port map [ action: " << (m.action == mapping_t::action_add ? "add" : "delete")
<< " proto: " << (m.protocol == udp ? "udp" : "tcp")
<< " local: " << m.local_port << " external: " << m.external_port
<< " ttl: " << ttl << " ]";
@ -278,6 +297,7 @@ void natpmp::send_map_request(int i)
error_code ec;
m_socket.send_to(asio::buffer(buf, 12), m_nat_endpoint, 0, ec);
m.map_sent = true;
// linear back-off instead of exponential
++m_retry_count;
m_send_timer.expires_from_now(milliseconds(250 * m_retry_count), ec);
@ -348,7 +368,7 @@ void natpmp::on_reply(error_code const& e
(void)time; // to remove warning
std::stringstream msg;
msg << "port map ["
msg << "<== port map ["
<< " protocol: " << (cmd - 128 == 1 ? "udp" : "tcp")
<< " local: " << private_port << " external: " << public_port
<< " ttl: " << lifetime << " ]";
@ -486,7 +506,7 @@ void natpmp::close()
{
mutex_t::scoped_lock l(m_mutex);
m_abort = true;
error_code ec;
log("closing");
/*
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
m_log << time_now_string() << " close" << std::endl;
@ -511,6 +531,7 @@ void natpmp::close()
if (i->protocol == none) continue;
i->action = mapping_t::action_delete;
}
error_code ec;
m_refresh_timer.cancel(ec);
update_mapping(0);
}

View File

@ -1990,20 +1990,9 @@ namespace aux {
m_dht_settings.service_port = new_interface.port();
// the listen interface changed, rebind the dht listen socket as well
m_dht_socket.bind(m_dht_settings.service_port);
if (m_natpmp.get())
{
if (m_udp_mapping[0] != -1) m_natpmp->delete_mapping(m_udp_mapping[0]);
m_udp_mapping[0] = m_natpmp->add_mapping(natpmp::tcp
, m_dht_settings.service_port
, m_dht_settings.service_port);
}
if (m_upnp.get())
{
if (m_udp_mapping[1] != -1) m_upnp->delete_mapping(m_udp_mapping[1]);
m_udp_mapping[1] = m_upnp->add_mapping(upnp::tcp
, m_dht_settings.service_port
, m_dht_settings.service_port);
}
maybe_update_udp_mapping(0, m_dht_settings.service_port, m_dht_settings.service_port);
maybe_update_udp_mapping(1, m_dht_settings.service_port, m_dht_settings.service_port);
}
#endif
@ -2194,18 +2183,8 @@ namespace aux {
m_dht_settings.service_port = 45000 + (rand() % 10000);
}
m_external_udp_port = m_dht_settings.service_port;
if (m_natpmp.get() && m_udp_mapping[0] == -1)
{
m_udp_mapping[0] = m_natpmp->add_mapping(natpmp::udp
, m_dht_settings.service_port
, m_dht_settings.service_port);
}
if (m_upnp.get() && m_udp_mapping[1] == -1)
{
m_udp_mapping[1] = m_upnp->add_mapping(upnp::udp
, m_dht_settings.service_port
, m_dht_settings.service_port);
}
maybe_update_udp_mapping(0, m_dht_settings.service_port, m_dht_settings.service_port);
maybe_update_udp_mapping(1, m_dht_settings.service_port, m_dht_settings.service_port);
m_dht = new dht::dht_tracker(*this, m_dht_socket, m_dht_settings, &startup_state);
if (!m_dht_socket.is_open() || m_dht_socket.local_port() != m_dht_settings.service_port)
{
@ -2222,6 +2201,45 @@ namespace aux {
m_dht->start(startup_state);
}
#ifndef TORRENT_DISABLE_DHT
void session_impl::maybe_update_udp_mapping(int nat, int local_port, int external_port)
{
int local, external, protocol;
if (nat == 0 && m_natpmp.get())
{
if (m_udp_mapping[nat] != -1)
{
if (m_natpmp->get_mapping(m_udp_mapping[nat], local, external, protocol))
{
// we already have a mapping. If it's the same, don't do anything
if (local == local_port && external == external_port && protocol == natpmp::udp)
return;
}
m_natpmp->delete_mapping(m_udp_mapping[nat]);
}
m_udp_mapping[nat] = m_natpmp->add_mapping(natpmp::udp
, local_port, external_port);
return;
}
else if (nat == 1 && m_upnp.get())
{
if (m_udp_mapping[nat] != -1)
{
if (m_upnp->get_mapping(m_udp_mapping[nat], local, external, protocol))
{
// we already have a mapping. If it's the same, don't do anything
if (local == local_port && external == external_port && protocol == natpmp::udp)
return;
}
m_upnp->delete_mapping(m_udp_mapping[nat]);
}
m_udp_mapping[nat] = m_upnp->add_mapping(upnp::udp
, local_port, external_port);
return;
}
}
#endif
void session_impl::stop_dht()
{
mutex_t::scoped_lock l(m_mutex);
@ -2246,20 +2264,8 @@ namespace aux {
{
m_dht_socket.bind(settings.service_port);
if (m_natpmp.get())
{
if (m_udp_mapping[0] != -1) m_upnp->delete_mapping(m_udp_mapping[0]);
m_udp_mapping[0] = m_natpmp->add_mapping(natpmp::udp
, m_dht_settings.service_port
, m_dht_settings.service_port);
}
if (m_upnp.get())
{
if (m_udp_mapping[1] != -1) m_upnp->delete_mapping(m_udp_mapping[1]);
m_udp_mapping[1] = m_upnp->add_mapping(upnp::udp
, m_dht_settings.service_port
, m_dht_settings.service_port);
}
maybe_update_udp_mapping(0, settings.service_port, settings.service_port);
maybe_update_udp_mapping(1, settings.service_port, settings.service_port);
m_external_udp_port = settings.service_port;
}
m_dht_settings = settings;

View File

@ -228,6 +228,18 @@ void upnp::delete_mapping(int mapping)
}
}
bool upnp::get_mapping(int index, int& local_port, int& external_port, int& protocol) const
{
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;
local_port = m.local_port;
external_port = m.external_port;
protocol = m.protocol;
return true;
}
void upnp::resend_request(error_code const& e)
{
if (e) return;