diff --git a/src/upnp.cpp b/src/upnp.cpp index 59fa94cda..a61dcbbad 100644 --- a/src/upnp.cpp +++ b/src/upnp.cpp @@ -715,14 +715,17 @@ namespace struct parse_state { - parse_state(): found_service(false) {} + parse_state(): in_service(false) {} void reset(char const* st) { - found_service = false; + in_service = false; service_type = st; tag_stack.clear(); + control_url.clear(); + model.clear(); + url_base.clear(); } - bool found_service; + bool in_service; std::list tag_stack; std::string control_url; char const* service_type; @@ -753,22 +756,26 @@ void find_control_url(int type, char const* string, parse_state& state) else if (type == xml_end_tag) { if (!state.tag_stack.empty()) + { + if (state.in_service && state.tag_stack.back() == "service") + state.in_service = false; state.tag_stack.pop_back(); + } } else if (type == xml_string) { if (state.tag_stack.empty()) return; // std::cout << " " << string << std::endl; - if (!state.found_service && state.top_tags("service", "servicetype")) + if (!state.in_service && state.top_tags("service", "servicetype")) { if (string_equal_nocase(string, state.service_type)) - state.found_service = true; + state.in_service = true; } - else if (state.found_service && state.top_tags("service", "controlurl")) + else if (state.in_service && state.top_tags("service", "controlurl")) { state.control_url = string; } - else if (state.tag_stack.back() == "modelname") + else if (state.model.empty() && state.top_tags("device", "modelname")) { state.model = string; } @@ -823,7 +830,7 @@ void upnp::on_upnp_xml(error_code const& e s.reset("urn:schemas-upnp-org:service:WANIPConnection:1"); xml_parse((char*)p.get_body().begin, (char*)p.get_body().end , bind(&find_control_url, _1, _2, boost::ref(s))); - if (s.found_service) + if (!s.control_url.empty()) { d.service_namespace = s.service_type; if (!s.model.empty()) m_model = s.model; @@ -835,7 +842,7 @@ void upnp::on_upnp_xml(error_code const& e s.reset("urn:schemas-upnp-org:service:WANPPPConnection:1"); xml_parse((char*)p.get_body().begin, (char*)p.get_body().end , bind(&find_control_url, _1, _2, boost::ref(s))); - if (s.found_service) + if (!s.control_url.empty()) { d.service_namespace = s.service_type; if (!s.model.empty()) m_model = s.model; diff --git a/test/test_primitives.cpp b/test/test_primitives.cpp index db0ec409e..1079a3d40 100644 --- a/test/test_primitives.cpp +++ b/test/test_primitives.cpp @@ -204,16 +204,136 @@ char upnp_xml[] = "" ""; +char upnp_xml2[] = +"" +"" +"1" +"0" +"" +"http://192.168.1.1:49152" +"" +"" +"urn:schemas-upnp-org:device:InternetGatewayDevice:1" +"" +"LINKSYS WAG200G Gateway" +"LINKSYS" +"http://www.linksys.com" +"LINKSYS WAG200G Gateway" +"Wireless-G ADSL Home Gateway" +"WAG200G" +"http://www.linksys.com" +"123456789" +"uuid:8d401597-1dd2-11b2-a7d4-001ee5947cac" +"WAG200G" +"" +"" +"urn:schemas-upnp-org:service:Layer3Forwarding:1" +"urn:upnp-org:serviceId:L3Forwarding1" +"/upnp/control/L3Forwarding1" +"/upnp/event/L3Forwarding1" +"/l3frwd.xml" +"" +"" +"" +"" +"urn:schemas-upnp-org:device:WANDevice:1" +"WANDevice" +"LINKSYS" +"http://www.linksys.com/" +"Residential Gateway" +"Internet Connection Sharing" +"1" +"http://www.linksys.com/" +"0000001" +"uuid:8d401596-1dd2-11b2-a7d4-001ee5947cac" +"WAG200G" +"" +"" +"" +"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1" +"" +"urn:upnp-org:serviceId:WANCommonIFC1" +"/upnp/control/WANCommonIFC1" +"/upnp/event/WANCommonIFC1" +"/cmnicfg.xml" +"" +"" +"" +"" +"urn:schemas-upnp-org:device:WANConnectionDevice:1" +"WANConnectionDevice" +"LINKSYS" +"http://www.linksys.com/" +"Residential Gateway" +"Internet Connection Sharing" +"1" +"http://www.linksys.com/" +"0000001" +"uuid:8d401597-1dd2-11b2-a7d3-001ee5947cac" +"WAG200G" +"" +"" +"" +"urn:schemas-upnp-org:service:WANEthernetLinkConfig:1" +"" +"urn:upnp-org:serviceId:WANEthLinkC1" +"/upnp/control/WANEthLinkC1" +"/upnp/event/WANEthLinkC1" +"/wanelcfg.xml" +"" +"" +"urn:schemas-upnp-org:service:WANPPPConnection:1" +"urn:upnp-org:serviceId:WANPPPConn1" +"/upnp/control/WANPPPConn1" +"/upnp/event/WANPPPConn1" +"/pppcfg.xml" +"" +"" +"" +"" +"" +"" +"urn:schemas-upnp-org:device:LANDevice:1" +"LANDevice" +"LINKSYS" +"http://www.linksys.com/" +"Residential Gateway" +"Residential Gateway" +"1" +"http://www.linksys.com/" +"0000001" +"uuid:8d401596-1dd2-11b2-a7d3-001ee5947cac" +"WAG200G" +"" +"" +"" +"urn:schemas-upnp-org:service:LANHostConfigManagement:1" +"" +"urn:upnp-org:serviceId:LANHostCfg1" +"/upnp/control/LANHostCfg1" +"/upnp/event/LANHostCfg1" +"/lanhostc.xml" +"" +"" +"" +"" +"http://192.168.1.1/index.htm" +"" +""; + struct parse_state { - parse_state(): found_service(false) {} + parse_state(): in_service(false) {} void reset(char const* st) { - found_service = false; + in_service = false; service_type = st; tag_stack.clear(); + control_url.clear(); + model.clear(); + url_base.clear(); } - bool found_service; + bool in_service; std::list tag_stack; std::string control_url; char const* service_type; @@ -430,13 +550,26 @@ int test_main() xml_parse((char*)upnp_xml, (char*)upnp_xml + sizeof(upnp_xml) , bind(&find_control_url, _1, _2, boost::ref(xml_s))); - std::cerr << xml_s.url_base << std::endl; - std::cerr << xml_s.control_url << std::endl; - std::cerr << xml_s.model << std::endl; + 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((char*)upnp_xml2, (char*)upnp_xml2 + sizeof(upnp_xml2) + , 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"); + // test network functions error_code ec;