upnp fixes and more debug asserts and more logging. Might fix #167

This commit is contained in:
Arvid Norberg 2007-10-26 00:47:30 +00:00
parent ee61db101e
commit 636d5f2005
2 changed files with 81 additions and 33 deletions

View File

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

View File

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