upnp/lsd/natpmp fixes 1699

This commit is contained in:
Marcos Pinto 2007-10-26 01:38:04 +00:00
parent 4bb1f06fd3
commit 38471aa832
5 changed files with 91 additions and 38 deletions

View File

@ -148,8 +148,19 @@ private:
{
mapping[0].protocol = 0;
mapping[1].protocol = 1;
#ifndef NDEBUG
magic = 1337;
#endif
}
#ifndef NDEBUG
~rootdevice()
{
TORRENT_ASSERT(magic == 1337);
magic = 0;
}
#endif
// the interface url, through which the list of
// supported interfaces are fetched
std::string url;
@ -174,8 +185,12 @@ private:
mutable boost::shared_ptr<http_connection> upnp_connection;
#ifndef NDEBUG
int magic;
#endif
void close() const
{
TORRENT_ASSERT(magic == 1337);
if (!upnp_connection) return;
upnp_connection->close();
upnp_connection.reset();

View File

@ -48,8 +48,8 @@ namespace aux
template<class IO_Control_Command>
struct io_control_visitor_ec: boost::static_visitor<>
{
io_control_visitor_ec(IO_Control_Command& ioc, asio::error_code& ec)
: ioc(ioc), ec(ec) {}
io_control_visitor_ec(IO_Control_Command& ioc, asio::error_code& ec_)
: ioc(ioc), ec(ec_) {}
template <class T>
void operator()(T* p) const
@ -188,7 +188,7 @@ namespace aux
: boost::static_visitor<>
{
close_visitor_ec(asio::error_code& ec_)
: ec(ec)
: ec(ec_)
{}
template <class T>
@ -329,9 +329,9 @@ namespace aux
struct read_some_visitor_ec
: boost::static_visitor<std::size_t>
{
read_some_visitor_ec(Mutable_Buffers const& buffers, asio::error_code& ec)
read_some_visitor_ec(Mutable_Buffers const& buffers, asio::error_code& ec_)
: buffers(buffers)
, ec(ec)
, ec(ec_)
{}
template <class T>

View File

@ -184,5 +184,6 @@ void lsd::on_announce(udp::endpoint const& from, char* buffer
void lsd::close()
{
m_socket.close();
m_broadcast_timer.cancel();
}

View File

@ -382,6 +382,8 @@ void natpmp::try_next_mapping(int i)
void natpmp::close()
{
asio::error_code ec;
m_socket.close(ec);
if (m_disabled) return;
for (int i = 0; i < num_mappings; ++i)
{
@ -390,5 +392,7 @@ void natpmp::close()
m_mappings[i].external_port = 0;
refresh_mapping(i);
}
m_refresh_timer.cancel();
m_send_timer.cancel();
}

View File

@ -148,6 +148,7 @@ void upnp::set_mappings(int tcp, int udp)
, end(m_devices.end()); i != end; ++i)
{
rootdevice& d = const_cast<rootdevice&>(*i);
TORRENT_ASSERT(d.magic == 1337);
if (d.mapping[0].local_port != m_tcp_local_port)
{
if (d.mapping[0].external_port == 0)
@ -200,8 +201,13 @@ try
// we don't have a WANIP or WANPPP url for this device,
// ask for it
rootdevice& d = const_cast<rootdevice&>(*i);
TORRENT_ASSERT(d.magic == 1337);
try
{
#ifdef TORRENT_UPNP_LOGGING
m_log << time_now_string()
<< " ==> connecting to " << d.url << std::endl;
#endif
d.upnp_connection.reset(new http_connection(m_io_service
, m_cc, m_strand.wrap(bind(&upnp::on_upnp_xml, self(), _1, _2
, boost::ref(d)))));
@ -270,7 +276,7 @@ try
{
#ifdef TORRENT_UPNP_LOGGING
m_log << time_now_string()
<< " <== Rootdevice responded with incorrect HTTP packet. Ignoring device (" << e.what() << ")" << std::endl;
<< " <== (" << from << ") Rootdevice responded with incorrect HTTP packet. Ignoring device (" << e.what() << ")" << std::endl;
#endif
return;
}
@ -280,11 +286,11 @@ try
#ifdef TORRENT_UPNP_LOGGING
if (p.method().empty())
m_log << time_now_string()
<< " <== Device responded with HTTP status: " << p.status_code()
<< " <== (" << from << ") Device responded with HTTP status: " << p.status_code()
<< ". Ignoring device" << std::endl;
else
m_log << time_now_string()
<< " <== Device with HTTP method: " << p.method()
<< " <== (" << from << ") Device with HTTP method: " << p.method()
<< ". Ignoring device" << std::endl;
#endif
return;
@ -294,7 +300,7 @@ try
{
#ifdef TORRENT_UPNP_LOGGING
m_log << time_now_string()
<< " <== Rootdevice responded with incomplete HTTP "
<< " <== (" << from << ") Rootdevice responded with incomplete HTTP "
"packet. Ignoring device" << std::endl;
#endif
return;
@ -305,7 +311,7 @@ try
{
#ifdef TORRENT_UPNP_LOGGING
m_log << time_now_string()
<< " <== Rootdevice response is missing a location header. "
<< " <== (" << from << ") Rootdevice response is missing a location header. "
"Ignoring device" << std::endl;
#endif
return;
@ -332,7 +338,7 @@ try
{
#ifdef TORRENT_UPNP_LOGGING
m_log << time_now_string()
<< " <== Rootdevice uses unsupported protocol: '" << protocol
<< " <== (" << from << ") Rootdevice uses unsupported protocol: '" << protocol
<< "'. Ignoring device" << std::endl;
#endif
return;
@ -342,16 +348,27 @@ try
{
#ifdef TORRENT_UPNP_LOGGING
m_log << time_now_string()
<< " <== Rootdevice responded with a url with port 0. "
<< " <== (" << from << ") Rootdevice responded with a url with port 0. "
"Ignoring device" << std::endl;
#endif
return;
}
#ifdef TORRENT_UPNP_LOGGING
m_log << time_now_string()
<< " <== Found rootdevice: " << d.url << std::endl;
<< " <== (" << from << ") Found rootdevice: " << d.url
<< " total: " << m_devices.size() << std::endl;
#endif
if (m_devices.size() >= 50)
{
#ifdef TORRENT_UPNP_LOGGING
m_log << time_now_string()
<< " <== (" << from << ") Too many devices (" << m_devices.size() << "), "
"ignoring: " << d.url << std::endl;
#endif
return;
}
if (m_tcp_local_port != 0)
{
d.mapping[0].need_update = true;
@ -390,8 +407,13 @@ try
// we don't have a WANIP or WANPPP url for this device,
// ask for it
rootdevice& d = const_cast<rootdevice&>(*i);
TORRENT_ASSERT(d.magic == 1337);
try
{
#ifdef TORRENT_UPNP_LOGGING
m_log << time_now_string()
<< " ==> connecting to " << d.url << std::endl;
#endif
d.upnp_connection.reset(new http_connection(m_io_service
, m_cc, m_strand.wrap(bind(&upnp::on_upnp_xml, self(), _1, _2
, boost::ref(d)))));
@ -420,6 +442,7 @@ catch (std::exception&)
void upnp::post(upnp::rootdevice const& d, std::string const& soap
, std::string const& soap_action)
{
TORRENT_ASSERT(d.magic == 1337);
std::stringstream header;
header << "POST " << d.control_url << " HTTP/1.1\r\n"
@ -439,6 +462,7 @@ void upnp::post(upnp::rootdevice const& d, std::string const& soap
void upnp::create_port_mapping(http_connection& c, rootdevice& d, int i)
{
TORRENT_ASSERT(d.magic == 1337);
std::string soap_action = "AddPortMapping";
std::stringstream soap;
@ -463,6 +487,7 @@ void upnp::create_port_mapping(http_connection& c, rootdevice& d, int i)
void upnp::map_port(rootdevice& d, int i)
{
TORRENT_ASSERT(d.magic == 1337);
if (d.upnp_connection) return;
if (!d.mapping[i].need_update)
@ -479,6 +504,10 @@ void upnp::map_port(rootdevice& d, int i)
TORRENT_ASSERT(!d.upnp_connection);
TORRENT_ASSERT(d.service_namespace);
#ifdef TORRENT_UPNP_LOGGING
m_log << time_now_string()
<< " ==> connecting to " << d.hostname << std::endl;
#endif
d.upnp_connection.reset(new http_connection(m_io_service
, m_cc, m_strand.wrap(bind(&upnp::on_upnp_map_response, self(), _1, _2
, boost::ref(d), i)), true
@ -490,6 +519,7 @@ void upnp::map_port(rootdevice& d, int i)
void upnp::delete_port_mapping(rootdevice& d, int i)
{
TORRENT_ASSERT(d.magic == 1337);
std::stringstream soap;
std::string soap_action = "DeletePortMapping";
@ -510,23 +540,24 @@ void upnp::delete_port_mapping(rootdevice& d, int i)
// requires the mutex to be locked
void upnp::unmap_port(rootdevice& d, int i)
{
if (d.mapping[i].external_port == 0)
TORRENT_ASSERT(d.magic == 1337);
if (d.mapping[i].external_port == 0
|| d.disabled)
{
if (i < num_mappings - 1)
{
unmap_port(d, i + 1);
}
else
{
m_devices.erase(d);
}
return;
}
#ifdef TORRENT_UPNP_LOGGING
m_log << time_now_string()
<< " ==> connecting to " << d.hostname << std::endl;
#endif
d.upnp_connection.reset(new http_connection(m_io_service
, m_cc, m_strand.wrap(bind(&upnp::on_upnp_unmap_response, self(), _1, _2
, boost::ref(d), i)), true
, bind(&upnp::delete_port_mapping, self(), boost::ref(d), i)));
d.upnp_connection->start(d.hostname, boost::lexical_cast<std::string>(d.port)
, seconds(10));
}
@ -591,6 +622,7 @@ namespace
void upnp::on_upnp_xml(asio::error_code const& e
, libtorrent::http_parser const& p, rootdevice& d) try
{
TORRENT_ASSERT(d.magic == 1337);
if (d.upnp_connection)
{
d.upnp_connection->close();
@ -601,8 +633,10 @@ void upnp::on_upnp_xml(asio::error_code const& e
{
#ifdef TORRENT_UPNP_LOGGING
m_log << time_now_string()
<< " <== error while fetching control url: " << e.message() << std::endl;
<< " <== (" << d.url << ") error while fetching control url: "
<< e.message() << std::endl;
#endif
d.disabled = true;
return;
}
@ -610,8 +644,9 @@ void upnp::on_upnp_xml(asio::error_code const& e
{
#ifdef TORRENT_UPNP_LOGGING
m_log << time_now_string()
<< " <== error while fetching control url: incomplete http message" << std::endl;
<< " <== (" << d.url << ") error while fetching control url: incomplete http message" << std::endl;
#endif
d.disabled = true;
return;
}
@ -619,8 +654,9 @@ void upnp::on_upnp_xml(asio::error_code const& e
{
#ifdef TORRENT_UPNP_LOGGING
m_log << time_now_string()
<< " <== error while fetching control url: " << p.message() << std::endl;
<< " <== (" << d.url << ") error while fetching control url: " << p.message() << std::endl;
#endif
d.disabled = true;
return;
}
@ -647,15 +683,17 @@ void upnp::on_upnp_xml(asio::error_code const& e
{
#ifdef TORRENT_UPNP_LOGGING
m_log << time_now_string()
<< " <== Rootdevice response, did not find a port mapping interface" << std::endl;
<< " <== (" << d.url << ") Rootdevice response, did not find "
"a port mapping interface" << std::endl;
#endif
d.disabled = true;
return;
}
}
#ifdef TORRENT_UPNP_LOGGING
m_log << time_now_string()
<< " <== Rootdevice response, found control URL: " << s.control_url
<< " <== (" << d.url << ") Rootdevice response, found control URL: " << s.control_url
<< " namespace: " << d.service_namespace << std::endl;
#endif
@ -732,6 +770,7 @@ namespace
void upnp::on_upnp_map_response(asio::error_code const& e
, libtorrent::http_parser const& p, rootdevice& d, int mapping) try
{
TORRENT_ASSERT(d.magic == 1337);
if (d.upnp_connection)
{
d.upnp_connection->close();
@ -744,7 +783,7 @@ void upnp::on_upnp_map_response(asio::error_code const& e
m_log << time_now_string()
<< " <== error while adding portmap: " << e.message() << std::endl;
#endif
m_devices.erase(d);
d.disabled = true;
return;
}
@ -773,7 +812,7 @@ void upnp::on_upnp_map_response(asio::error_code const& e
m_log << time_now_string()
<< " <== error while adding portmap: incomplete http message" << std::endl;
#endif
m_devices.erase(d);
d.disabled = true;
return;
}
@ -877,6 +916,7 @@ catch (std::exception&)
void upnp::on_upnp_unmap_response(asio::error_code const& e
, libtorrent::http_parser const& p, rootdevice& d, int mapping) try
{
TORRENT_ASSERT(d.magic == 1337);
if (d.upnp_connection)
{
d.upnp_connection->close();
@ -906,7 +946,7 @@ void upnp::on_upnp_unmap_response(asio::error_code const& e
m_log << time_now_string()
<< " <== error while deleting portmap: " << p.message() << std::endl;
#endif
m_devices.erase(d);
d.disabled = true;
return;
}
@ -922,10 +962,6 @@ void upnp::on_upnp_unmap_response(asio::error_code const& e
unmap_port(d, mapping + 1);
return;
}
// the main thread is likely to be waiting for
// all the unmap operations to complete
m_devices.erase(d);
}
catch (std::exception&)
{
@ -943,6 +979,7 @@ void upnp::on_expire(asio::error_code const& e) try
, end(m_devices.end()); i != end; ++i)
{
rootdevice& d = const_cast<rootdevice&>(*i);
TORRENT_ASSERT(d.magic == 1337);
for (int m = 0; m < num_mappings; ++m)
{
if (d.mapping[m].expires != max_time())
@ -984,15 +1021,11 @@ void upnp::close()
}
for (std::set<rootdevice>::iterator i = m_devices.begin()
, end(m_devices.end()); i != end;)
, end(m_devices.end()); i != end; ++i)
{
rootdevice& d = const_cast<rootdevice&>(*i);
if (d.control_url.empty())
{
m_devices.erase(i++);
continue;
}
++i;
TORRENT_ASSERT(d.magic == 1337);
if (d.control_url.empty()) continue;
unmap_port(d, 0);
}
}