diff --git a/src/upnp.cpp b/src/upnp.cpp index 801c091d6..e022229ff 100644 --- a/src/upnp.cpp +++ b/src/upnp.cpp @@ -143,7 +143,7 @@ void upnp::log(char const* msg, mutex::scoped_lock& l) void upnp::discover_device_impl(mutex::scoped_lock& l) { - const char msearch[] = + const char msearch[] = "M-SEARCH * HTTP/1.1\r\n" "HOST: 239.255.255.250:1900\r\n" "ST:upnp:rootdevice\r\n" @@ -246,7 +246,7 @@ void upnp::delete_mapping(int mapping) log(msg, l); if (m.protocol == none) return; - + for (std::set::iterator i = m_devices.begin() , end(m_devices.end()); i != end; ++i) { @@ -297,7 +297,7 @@ void upnp::resend_request(error_code const& ec) disable(errors::no_router, l); return; } - + for (std::set::iterator i = m_devices.begin() , end(m_devices.end()); i != end; ++i) { @@ -691,7 +691,7 @@ void upnp::create_port_mapping(http_connection& c, rootdevice& d, int i) log(msg, l); return; } - + char const* soap_action = "AddPortMapping"; std::string local_endpoint = print_address(c.socket().local_endpoint(ec).address()); @@ -848,20 +848,11 @@ namespace struct parse_state { - parse_state(): in_service(false), service_type(0) {} - void reset(char const* st) - { - in_service = false; - service_type = st; - tag_stack.clear(); - control_url.clear(); - model.clear(); - url_base.clear(); - } + parse_state(): in_service(false) {} bool in_service; std::list tag_stack; std::string control_url; - char const* service_type; + std::string service_type; std::string model; std::string url_base; bool top_tags(const char* str1, const char* str2) @@ -898,13 +889,18 @@ TORRENT_EXTRA_EXPORT void find_control_url(int type, char const* string, parse_s else if (type == xml_string) { if (state.tag_stack.empty()) return; -// std::cout << " " << string << std::endl; +// std::cout << " " << string << std::endl;} if (!state.in_service && state.top_tags("service", "servicetype")) { - if (string_equal_no_case(string, state.service_type)) + if (string_equal_no_case(string, "urn:schemas-upnp-org:service:WANIPConnection:1") + || string_equal_no_case(string, "urn:schemas-upnp-org:service:WANIPConnection:2") + || string_equal_no_case(string, "urn:schemas-upnp-org:service:WANPPPConnection:1")) + { + state.service_type = string; state.in_service = true; + } } - else if (state.control_url.empty() && state.in_service && state.top_tags("service", "controlurl")) + else if (state.control_url.empty() && state.in_service && state.top_tags("service", "controlurl") && strlen(string) > 0) { // default to the first (or only) control url in the router's listing state.control_url = string; @@ -966,37 +962,22 @@ void upnp::on_upnp_xml(error_code const& e } parse_state s; - s.reset("urn:schemas-upnp-org:service:WANIPConnection:1"); xml_parse((char*)p.get_body().begin, (char*)p.get_body().end , boost::bind(&find_control_url, _1, _2, boost::ref(s))); - if (!s.control_url.empty()) + if (s.control_url.empty()) { - d.service_namespace = s.service_type; - if (!s.model.empty()) m_model = s.model; + char msg[500]; + snprintf(msg, sizeof(msg), "could not find a port mapping interface in response from: %s" + , d.url.c_str()); + log(msg, l); + d.disabled = true; + return; } - else - { - // we didn't find the WAN IP connection, look for - // a PPP connection - s.reset("urn:schemas-upnp-org:service:WANPPPConnection:1"); - xml_parse((char*)p.get_body().begin, (char*)p.get_body().end - , boost::bind(&find_control_url, _1, _2, boost::ref(s))); - if (!s.control_url.empty()) - { - d.service_namespace = s.service_type; - if (!s.model.empty()) m_model = s.model; - } - else - { - char msg[500]; - snprintf(msg, sizeof(msg), "could not find a port mapping interface in response from: %s" - , d.url.c_str()); - log(msg, l); - d.disabled = true; - return; - } - } - + static std::string service_type; + service_type.swap(s.service_type); + d.service_namespace = service_type.c_str(); + if (!s.model.empty()) m_model = s.model; + if (!s.url_base.empty() && s.control_url.substr(0, 7) != "http://") { // avoid double slashes in path @@ -1044,7 +1025,7 @@ void upnp::on_upnp_xml(error_code const& e d.upnp_connection.reset(new http_connection(m_io_service , m_resolver , boost::bind(&upnp::on_upnp_get_ip_address_response, self(), _1, _2 - , boost::ref(d), _5), true, default_max_bottled_buffer_size + , boost::ref(d), _5), true, default_max_bottled_buffer_size , boost::bind(&upnp::get_ip_address, self(), boost::ref(d)))); d.upnp_connection->start(d.hostname, d.port , seconds(10), 1); @@ -1094,7 +1075,7 @@ void upnp::disable(error_code const& ec, mutex::scoped_lock& l) m_callback(i - m_mappings.begin(), address(), 0, ec); l.lock(); } - + // we cannot clear the devices since there // might be outstanding requests relying on // the device entry being present when they @@ -1115,7 +1096,7 @@ namespace bool exit; int error_code; }; - + void find_error_code(int type, char const* string, error_code_parse_state& state) { if (state.exit) return; @@ -1158,7 +1139,7 @@ namespace int code; char const* msg; }; - + error_code_t error_codes[] = { {0, "no error"} @@ -1319,9 +1300,9 @@ void upnp::on_upnp_map_response(error_code const& e d.disabled = true; return; } - + if (m_closing) return; - + // error code response may look like this: // @@ -1376,7 +1357,7 @@ void upnp::on_upnp_map_response(error_code const& e , s.error_code); log(msg, l); } - + mapping_t& m = d.mapping[mapping]; if (s.error_code == 725) diff --git a/test/Makefile.am b/test/Makefile.am index 820451bbb..7cfefc375 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -189,6 +189,7 @@ test_session_SOURCES = test_session.cpp test_web_seed_SOURCES = test_web_seed.cpp test_url_seed_SOURCES = test_url_seed.cpp test_remap_files_SOURCES = test_remap_files.cpp +test_file_progress_SOURCES = test_file_progress.cpp LDADD = libtest.la $(top_builddir)/src/libtorrent-rasterbar.la diff --git a/test/root3.xml b/test/root3.xml new file mode 100644 index 000000000..654411195 --- /dev/null +++ b/test/root3.xml @@ -0,0 +1 @@ +10http://127.0.0.1:%durn:schemas-upnp-org:device:InternetGatewayDevice:2http://192.168.0.1:80D-Link RouterD-Linkhttp://www.dlink.comInternet Access RouterD-Link Routeruuid:upnp-InternetGatewayDevice-2_0-12345678900001123456789001urn:schemas-upnp-org:service:Layer3Forwarding:1urn:upnp-org:serviceId:L3Forwarding1/Layer3Forwarding/Layer3Forwarding/Layer3Forwarding.xmlurn:schemas-upnp-org:device:WANDevice:2WANDeviceD-Linkhttp://www.dlink.comInternet Access RouterD-Link Router1http://support.dlink.com12345678900001uuid:upnp-WANDevice-1_0-12345678900001123456789001urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1urn:upnp-org:serviceId:WANCommonInterfaceConfig/WANCommonInterfaceConfig/WANCommonInterfaceConfig/WANCommonInterfaceConfig.xmlurn:schemas-upnp-org:device:WANConnectionDevice:2WAN Connection DeviceD-Linkhttp://www.dlink.comInternet Access RouterD-Link Router1http://support.dlink.com12345678900001uuid:upnp-WANConnectionDevice-2_0-12345678900001123456789001urn:schemas-upnp-org:service:WANIPConnection:2urn:upnp-org:serviceId:WANIPConnection/WANIPConnection/WANIPConnection/WANIPConnection.xml diff --git a/test/test_upnp.cpp b/test/test_upnp.cpp index 8bbb136f9..6d0cb5f66 100644 --- a/test/test_upnp.cpp +++ b/test/test_upnp.cpp @@ -46,17 +46,25 @@ using namespace libtorrent; broadcast_socket* sock = 0; int g_port = 0; -char soap_add_response[] = +char const* soap_add_response[] = { "" "" - ""; + "", + "" + "" + ""}; -char soap_delete_response[] = +char const* soap_delete_response[] = { "" "" - ""; + "", + "" + "" + ""}; void incoming_msearch(udp::endpoint const& from, char* buffer , int size) @@ -119,7 +127,7 @@ void callback(int mapping, address const& ip, int port, error_code const& err) << ", error: \"" << err.message() << "\"\n"; } -void run_upnp_test(char const* root_filename, char const* router_model, char const* control_name) +void run_upnp_test(char const* root_filename, char const* router_model, char const* control_name, int igd_version) { libtorrent::io_service ios; @@ -141,7 +149,7 @@ void run_upnp_test(char const* root_filename, char const* router_model, char con fclose(xml_file); std::ofstream xml(control_name, std::ios::trunc); - xml.write(soap_add_response, sizeof(soap_add_response)-1); + xml.write(soap_add_response[igd_version-1], sizeof(soap_add_response[igd_version-1])-1); xml.close(); sock = new broadcast_socket(udp::endpoint(address_v4::from_string("239.255.255.250") @@ -197,7 +205,7 @@ void run_upnp_test(char const* root_filename, char const* router_model, char con TEST_EQUAL(std::count(callbacks.begin(), callbacks.end(), expected2), 1); xml.open(control_name, std::ios::trunc); - xml.write(soap_delete_response, sizeof(soap_delete_response)-1); + xml.write(soap_delete_response[igd_version-1], sizeof(soap_delete_response[igd_version-1])-1); xml.close(); upnp_handler->close(); @@ -229,7 +237,7 @@ void run_upnp_test(char const* root_filename, char const* router_model, char con TORRENT_TEST(upnp) { - run_upnp_test(combine_path("..", "root1.xml").c_str(), "Xtreme N GIGABIT Router", "wipconn"); - run_upnp_test(combine_path("..", "root2.xml").c_str(), "D-Link Router", "WANIPConnection"); + run_upnp_test(combine_path("..", "root1.xml").c_str(), "Xtreme N GIGABIT Router", "wipconn", 1); + run_upnp_test(combine_path("..", "root2.xml").c_str(), "D-Link Router", "WANIPConnection", 1); + run_upnp_test(combine_path("..", "root3.xml").c_str(), "D-Link Router", "WANIPConnection_2", 2); } - diff --git a/test/test_xml.cpp b/test/test_xml.cpp index ea8ed04f9..bc535e2f8 100644 --- a/test/test_xml.cpp +++ b/test/test_xml.cpp @@ -35,7 +35,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "test.hpp" #include -char upnp_xml[] = +char upnp_xml[] = "" "" "1" @@ -239,20 +239,11 @@ namespace libtorrent { struct parse_state { - parse_state(): in_service(false), service_type("") {} - void reset(char const* st) - { - in_service = false; - service_type = st; - tag_stack.clear(); - control_url.clear(); - model.clear(); - url_base.clear(); - } + parse_state(): in_service(false){} bool in_service; std::list tag_stack; std::string control_url; - char const* service_type; + std::string service_type; std::string model; std::string url_base; }; @@ -292,31 +283,32 @@ void parser_callback(std::string& out, int token, char const* s, char const* val TORRENT_TEST(xml) { // test upnp xml parser + { + parse_state xml_s; + xml_parse(upnp_xml, upnp_xml + sizeof(upnp_xml) + , boost::bind(&find_control_url, _1, _2, boost::ref(xml_s))); - parse_state xml_s; - xml_s.reset("urn:schemas-upnp-org:service:WANIPConnection:1"); - xml_parse(upnp_xml, upnp_xml + sizeof(upnp_xml) - , boost::bind(&find_control_url, _1, _2, boost::ref(xml_s))); + std::cerr << "namespace " << xml_s.service_type << std::endl; + std::cerr << "url_base: " << xml_s.url_base << std::endl; + std::cerr << "control_url: " << xml_s.control_url << std::endl; + std::cerr << "model: " << xml_s.model << std::endl; + TEST_CHECK(xml_s.url_base == "http://192.168.0.1:5678"); + TEST_CHECK(xml_s.control_url == "/WANIPConnection"); + TEST_CHECK(xml_s.model == "D-Link Router"); + } + { + parse_state xml_s; + xml_parse(upnp_xml2, upnp_xml2 + sizeof(upnp_xml2) + , boost::bind(&find_control_url, _1, _2, boost::ref(xml_s))); - std::cerr << "namespace " << xml_s.service_type << std::endl; - std::cerr << "url_base: " << xml_s.url_base << std::endl; - std::cerr << "control_url: " << xml_s.control_url << std::endl; - std::cerr << "model: " << xml_s.model << std::endl; - TEST_CHECK(xml_s.url_base == "http://192.168.0.1:5678"); - TEST_CHECK(xml_s.control_url == "/WANIPConnection"); - TEST_CHECK(xml_s.model == "D-Link Router"); - - xml_s.reset("urn:schemas-upnp-org:service:WANPPPConnection:1"); - xml_parse(upnp_xml2, upnp_xml2 + sizeof(upnp_xml2) - , boost::bind(&find_control_url, _1, _2, boost::ref(xml_s))); - - std::cerr << "namespace " << xml_s.service_type << std::endl; - std::cerr << "url_base: " << xml_s.url_base << std::endl; - std::cerr << "control_url: " << xml_s.control_url << std::endl; - std::cerr << "model: " << xml_s.model << std::endl; - TEST_CHECK(xml_s.url_base == "http://192.168.1.1:49152"); - TEST_CHECK(xml_s.control_url == "/upnp/control/WANPPPConn1"); - TEST_CHECK(xml_s.model == "Wireless-G ADSL Home Gateway"); + std::cerr << "namespace " << xml_s.service_type << std::endl; + std::cerr << "url_base: " << xml_s.url_base << std::endl; + std::cerr << "control_url: " << xml_s.control_url << std::endl; + std::cerr << "model: " << xml_s.model << std::endl; + TEST_CHECK(xml_s.url_base == "http://192.168.1.1:49152"); + TEST_CHECK(xml_s.control_url == "/upnp/control/WANPPPConn1"); + TEST_CHECK(xml_s.model == "Wireless-G ADSL Home Gateway"); + } { // test xml parser