Merge pull request #23 from Chocobo1/igd_version

Add support for IGD version 2
This commit is contained in:
Arvid Norberg 2015-07-10 19:20:51 -04:00
commit bbe51268d3
5 changed files with 80 additions and 97 deletions

View File

@ -848,20 +848,11 @@ namespace
struct parse_state struct parse_state
{ {
parse_state(): in_service(false), service_type(0) {} parse_state(): in_service(false) {}
void reset(char const* st)
{
in_service = false;
service_type = st;
tag_stack.clear();
control_url.clear();
model.clear();
url_base.clear();
}
bool in_service; bool in_service;
std::list<std::string> tag_stack; std::list<std::string> tag_stack;
std::string control_url; std::string control_url;
char const* service_type; std::string service_type;
std::string model; std::string model;
std::string url_base; std::string url_base;
bool top_tags(const char* str1, const char* str2) 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) else if (type == xml_string)
{ {
if (state.tag_stack.empty()) return; 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 (!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; 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 // default to the first (or only) control url in the router's listing
state.control_url = string; state.control_url = string;
@ -966,36 +962,21 @@ void upnp::on_upnp_xml(error_code const& e
} }
parse_state s; parse_state s;
s.reset("urn:schemas-upnp-org:service:WANIPConnection:1");
xml_parse((char*)p.get_body().begin, (char*)p.get_body().end xml_parse((char*)p.get_body().begin, (char*)p.get_body().end
, boost::bind(&find_control_url, _1, _2, boost::ref(s))); , 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; char msg[500];
if (!s.model.empty()) m_model = s.model; snprintf(msg, sizeof(msg), "could not find a port mapping interface in response from: %s"
} , d.url.c_str());
else log(msg, l);
{ d.disabled = true;
// we didn't find the WAN IP connection, look for return;
// 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://") if (!s.url_base.empty() && s.control_url.substr(0, 7) != "http://")
{ {

View File

@ -189,6 +189,7 @@ test_session_SOURCES = test_session.cpp
test_web_seed_SOURCES = test_web_seed.cpp test_web_seed_SOURCES = test_web_seed.cpp
test_url_seed_SOURCES = test_url_seed.cpp test_url_seed_SOURCES = test_url_seed.cpp
test_remap_files_SOURCES = test_remap_files.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 LDADD = libtest.la $(top_builddir)/src/libtorrent-rasterbar.la

1
test/root3.xml Normal file
View File

@ -0,0 +1 @@
<root><specVersion><major>1</major><minor>0</minor></specVersion><URLBase>http://127.0.0.1:%d</URLBase><device><deviceType>urn:schemas-upnp-org:device:InternetGatewayDevice:2</deviceType><presentationURL>http://192.168.0.1:80</presentationURL><friendlyName>D-Link Router</friendlyName><manufacturer>D-Link</manufacturer><manufacturerURL>http://www.dlink.com</manufacturerURL><modelDescription>Internet Access Router</modelDescription><modelName>D-Link Router</modelName><UDN>uuid:upnp-InternetGatewayDevice-2_0-12345678900001</UDN><UPC>123456789001</UPC><serviceList><service><serviceType>urn:schemas-upnp-org:service:Layer3Forwarding:1</serviceType><serviceId>urn:upnp-org:serviceId:L3Forwarding1</serviceId><controlURL>/Layer3Forwarding</controlURL><eventSubURL>/Layer3Forwarding</eventSubURL><SCPDURL>/Layer3Forwarding.xml</SCPDURL></service></serviceList><deviceList><device><deviceType>urn:schemas-upnp-org:device:WANDevice:2</deviceType><friendlyName>WANDevice</friendlyName><manufacturer>D-Link</manufacturer><manufacturerURL>http://www.dlink.com</manufacturerURL><modelDescription>Internet Access Router</modelDescription><modelName>D-Link Router</modelName><modelNumber>1</modelNumber><modelURL>http://support.dlink.com</modelURL><serialNumber>12345678900001</serialNumber><UDN>uuid:upnp-WANDevice-1_0-12345678900001</UDN><UPC>123456789001</UPC><serviceList><service><serviceType>urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1</serviceType><serviceId>urn:upnp-org:serviceId:WANCommonInterfaceConfig</serviceId><controlURL>/WANCommonInterfaceConfig</controlURL><eventSubURL>/WANCommonInterfaceConfig</eventSubURL><SCPDURL>/WANCommonInterfaceConfig.xml</SCPDURL></service></serviceList><deviceList><device><deviceType>urn:schemas-upnp-org:device:WANConnectionDevice:2</deviceType><friendlyName>WAN Connection Device</friendlyName><manufacturer>D-Link</manufacturer><manufacturerURL>http://www.dlink.com</manufacturerURL><modelDescription>Internet Access Router</modelDescription><modelName>D-Link Router</modelName><modelNumber>1</modelNumber><modelURL>http://support.dlink.com</modelURL><serialNumber>12345678900001</serialNumber><UDN>uuid:upnp-WANConnectionDevice-2_0-12345678900001</UDN><UPC>123456789001</UPC><serviceList><service><serviceType>urn:schemas-upnp-org:service:WANIPConnection:2</serviceType><serviceId>urn:upnp-org:serviceId:WANIPConnection</serviceId><controlURL>/WANIPConnection</controlURL><eventSubURL>/WANIPConnection</eventSubURL><SCPDURL>/WANIPConnection.xml</SCPDURL></service></serviceList></device></deviceList></device></deviceList></device></root>

View File

@ -46,17 +46,25 @@ using namespace libtorrent;
broadcast_socket* sock = 0; broadcast_socket* sock = 0;
int g_port = 0; int g_port = 0;
char soap_add_response[] = char const* soap_add_response[] = {
"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" " "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
"s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
"<s:Body><u:AddPortMapping xmlns:u=\"urn:schemas-upnp-org:service:WANIPConnection:1\">" "<s:Body><u:AddPortMapping xmlns:u=\"urn:schemas-upnp-org:service:WANIPConnection:1\">"
"</u:AddPortMapping></s:Body></s:Envelope>"; "</u:AddPortMapping></s:Body></s:Envelope>",
"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
"s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
"<s:Body><u:AddPortMapping xmlns:u=\"urn:schemas-upnp-org:service:WANIPConnection:2\">"
"</u:AddPortMapping></s:Body></s:Envelope>"};
char soap_delete_response[] = char const* soap_delete_response[] = {
"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" " "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
"s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
"<s:Body><u:DeletePortMapping xmlns:u=\"urn:schemas-upnp-org:service:WANIPConnection:1\">" "<s:Body><u:DeletePortMapping xmlns:u=\"urn:schemas-upnp-org:service:WANIPConnection:1\">"
"</u:DeletePortMapping></s:Body></s:Envelope>"; "</u:DeletePortMapping></s:Body></s:Envelope>",
"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
"s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
"<s:Body><u:DeletePortMapping xmlns:u=\"urn:schemas-upnp-org:service:WANIPConnection:2\">"
"</u:DeletePortMapping></s:Body></s:Envelope>"};
void incoming_msearch(udp::endpoint const& from, char* buffer void incoming_msearch(udp::endpoint const& from, char* buffer
, int size) , int size)
@ -119,7 +127,7 @@ void callback(int mapping, address const& ip, int port, error_code const& err)
<< ", error: \"" << err.message() << "\"\n"; << ", 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; 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); fclose(xml_file);
std::ofstream xml(control_name, std::ios::trunc); 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(); xml.close();
sock = new broadcast_socket(udp::endpoint(address_v4::from_string("239.255.255.250") 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); TEST_EQUAL(std::count(callbacks.begin(), callbacks.end(), expected2), 1);
xml.open(control_name, std::ios::trunc); 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(); xml.close();
upnp_handler->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) TORRENT_TEST(upnp)
{ {
run_upnp_test(combine_path("..", "root1.xml").c_str(), "Xtreme N GIGABIT Router", "wipconn"); 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"); 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);
} }

View File

@ -239,20 +239,11 @@ namespace libtorrent {
struct parse_state struct parse_state
{ {
parse_state(): in_service(false), service_type("") {} parse_state(): in_service(false){}
void reset(char const* st)
{
in_service = false;
service_type = st;
tag_stack.clear();
control_url.clear();
model.clear();
url_base.clear();
}
bool in_service; bool in_service;
std::list<std::string> tag_stack; std::list<std::string> tag_stack;
std::string control_url; std::string control_url;
char const* service_type; std::string service_type;
std::string model; std::string model;
std::string url_base; 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) TORRENT_TEST(xml)
{ {
// test upnp xml parser // 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; std::cerr << "namespace " << xml_s.service_type << std::endl;
xml_s.reset("urn:schemas-upnp-org:service:WANIPConnection:1"); std::cerr << "url_base: " << xml_s.url_base << std::endl;
xml_parse(upnp_xml, upnp_xml + sizeof(upnp_xml) std::cerr << "control_url: " << xml_s.control_url << std::endl;
, boost::bind(&find_control_url, _1, _2, boost::ref(xml_s))); 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 << "namespace " << xml_s.service_type << std::endl;
std::cerr << "url_base: " << xml_s.url_base << std::endl; std::cerr << "url_base: " << xml_s.url_base << std::endl;
std::cerr << "control_url: " << xml_s.control_url << std::endl; std::cerr << "control_url: " << xml_s.control_url << std::endl;
std::cerr << "model: " << xml_s.model << 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.url_base == "http://192.168.1.1:49152");
TEST_CHECK(xml_s.control_url == "/WANIPConnection"); TEST_CHECK(xml_s.control_url == "/upnp/control/WANPPPConn1");
TEST_CHECK(xml_s.model == "D-Link Router"); TEST_CHECK(xml_s.model == "Wireless-G ADSL Home Gateway");
}
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");
{ {
// test xml parser // test xml parser