forked from premiere/premiere-libtorrent
backport fix upnp xml_parse
This commit is contained in:
parent
db65eaaa00
commit
d62b980278
|
@ -130,9 +130,30 @@ struct parse_state
|
|||
}
|
||||
};
|
||||
|
||||
struct error_code_parse_state
|
||||
{
|
||||
error_code_parse_state(): in_error_code(false), exit(false), error_code(-1) {}
|
||||
bool in_error_code;
|
||||
bool exit;
|
||||
int error_code;
|
||||
};
|
||||
|
||||
struct ip_address_parse_state: error_code_parse_state
|
||||
{
|
||||
ip_address_parse_state(): in_ip_address(false) {}
|
||||
bool in_ip_address;
|
||||
std::string ip_address;
|
||||
};
|
||||
|
||||
TORRENT_EXTRA_EXPORT void find_control_url(int type, char const* string
|
||||
, int str_len, parse_state& state);
|
||||
|
||||
TORRENT_EXTRA_EXPORT void find_error_code(int type, char const* string
|
||||
, int str_len, error_code_parse_state& state);
|
||||
|
||||
TORRENT_EXTRA_EXPORT void find_ip_address(int type, char const* string
|
||||
, int str_len, ip_address_parse_state& state);
|
||||
|
||||
// TODO: support using the windows API for UPnP operations as well
|
||||
class TORRENT_EXTRA_EXPORT upnp : public boost::enable_shared_from_this<upnp>
|
||||
{
|
||||
|
|
82
src/upnp.cpp
82
src/upnp.cpp
|
@ -1063,53 +1063,39 @@ void upnp::disable(error_code const& ec, mutex::scoped_lock& l)
|
|||
m_socket.close();
|
||||
}
|
||||
|
||||
void find_error_code(int type, char const* string, int str_len, error_code_parse_state& state)
|
||||
{
|
||||
if (state.exit) return;
|
||||
if (type == xml_start_tag && !std::strncmp("errorCode", string, size_t(str_len)))
|
||||
{
|
||||
state.in_error_code = true;
|
||||
}
|
||||
else if (type == xml_string && state.in_error_code)
|
||||
{
|
||||
std::string error_code_str(string, str_len);
|
||||
state.error_code = std::atoi(error_code_str.c_str());
|
||||
state.exit = true;
|
||||
}
|
||||
}
|
||||
|
||||
void find_ip_address(int type, char const* string, int str_len, ip_address_parse_state& state)
|
||||
{
|
||||
find_error_code(type, string, str_len, state);
|
||||
if (state.exit) return;
|
||||
|
||||
if (type == xml_start_tag && !std::strncmp("NewExternalIPAddress", string, size_t(str_len)))
|
||||
{
|
||||
state.in_ip_address = true;
|
||||
}
|
||||
else if (type == xml_string && state.in_ip_address)
|
||||
{
|
||||
state.ip_address.assign(string, str_len);
|
||||
state.exit = true;
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
struct error_code_parse_state
|
||||
{
|
||||
error_code_parse_state(): in_error_code(false), exit(false), error_code(-1) {}
|
||||
bool in_error_code;
|
||||
bool exit;
|
||||
int error_code;
|
||||
};
|
||||
|
||||
void find_error_code(int type, char const* string, error_code_parse_state& state)
|
||||
{
|
||||
if (state.exit) return;
|
||||
if (type == xml_start_tag && !std::strcmp("errorCode", string))
|
||||
{
|
||||
state.in_error_code = true;
|
||||
}
|
||||
else if (type == xml_string && state.in_error_code)
|
||||
{
|
||||
state.error_code = std::atoi(string);
|
||||
state.exit = true;
|
||||
}
|
||||
}
|
||||
|
||||
struct ip_address_parse_state: public error_code_parse_state
|
||||
{
|
||||
ip_address_parse_state(): in_ip_address(false) {}
|
||||
bool in_ip_address;
|
||||
std::string ip_address;
|
||||
};
|
||||
|
||||
void find_ip_address(int type, char const* string, ip_address_parse_state& state)
|
||||
{
|
||||
find_error_code(type, string, state);
|
||||
if (state.exit) return;
|
||||
|
||||
if (type == xml_start_tag && !std::strcmp("NewExternalIPAddress", string))
|
||||
{
|
||||
state.in_ip_address = true;
|
||||
}
|
||||
else if (type == xml_string && state.in_ip_address)
|
||||
{
|
||||
state.ip_address = string;
|
||||
state.exit = true;
|
||||
}
|
||||
}
|
||||
|
||||
struct error_code_t
|
||||
{
|
||||
int code;
|
||||
|
@ -1239,7 +1225,7 @@ void upnp::on_upnp_get_ip_address_response(error_code const& e
|
|||
|
||||
ip_address_parse_state s;
|
||||
xml_parse(const_cast<char*>(p.get_body().begin), const_cast<char*>(p.get_body().end)
|
||||
, boost::bind(&find_ip_address, _1, _2, boost::ref(s)));
|
||||
, boost::bind(&find_ip_address, _1, _2, _3, boost::ref(s)));
|
||||
if (s.error_code != -1)
|
||||
{
|
||||
char msg[500];
|
||||
|
@ -1333,7 +1319,7 @@ void upnp::on_upnp_map_response(error_code const& e
|
|||
error_code_parse_state s;
|
||||
xml_parse(const_cast<char*>(p.get_body().begin)
|
||||
, const_cast<char*>(p.get_body().end)
|
||||
, boost::bind(&find_error_code, _1, _2, boost::ref(s)));
|
||||
, boost::bind(&find_error_code, _1, _2, _3, boost::ref(s)));
|
||||
|
||||
if (s.error_code != -1)
|
||||
{
|
||||
|
@ -1476,7 +1462,7 @@ void upnp::on_upnp_unmap_response(error_code const& e
|
|||
{
|
||||
xml_parse(const_cast<char*>(p.get_body().begin)
|
||||
, const_cast<char*>(p.get_body().end)
|
||||
, boost::bind(&find_error_code, _1, _2, boost::ref(s)));
|
||||
, boost::bind(&find_error_code, _1, _2, _3, boost::ref(s)));
|
||||
}
|
||||
|
||||
int const proto = m_mappings[mapping].protocol;
|
||||
|
|
|
@ -233,6 +233,36 @@ char upnp_xml2[] =
|
|||
"</device>"
|
||||
"</root>";
|
||||
|
||||
char upnp_xml3[] =
|
||||
"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\""
|
||||
" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
|
||||
"<s:Body>"
|
||||
"<s:Fault>"
|
||||
"<faultcode>s:Client</faultcode>"
|
||||
"<faultstring>UPnPError</faultstring>"
|
||||
"<detail>"
|
||||
"<UPnPErrorxmlns=\"urn:schemas-upnp-org:control-1-0\">"
|
||||
"<errorCode>402</errorCode>"
|
||||
"<errorDescription>Invalid Args</errorDescription>"
|
||||
"</UPnPError>"
|
||||
"</detail>"
|
||||
"</s:Fault>"
|
||||
"</s:Body>"
|
||||
"</s:Envelope>";
|
||||
|
||||
char upnp_xml4[] =
|
||||
"<?xml version=\"1.0\"?>"
|
||||
"<s:Envelope"
|
||||
" xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\""
|
||||
" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
|
||||
"<s:Body>"
|
||||
"<u:GetExternalIPAddressResponse"
|
||||
" xmlns:u=\"urn:schemas-upnp-org:service:WANIPConnection:1\">"
|
||||
"<NewExternalIPAddress>123.10.20.30</NewExternalIPAddress>"
|
||||
"</u:GetExternalIPAddressResponse>"
|
||||
"</s:Body>"
|
||||
"</s:Envelope>";
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
void parser_callback(std::string& out, int token, char const* s, int len
|
||||
|
@ -304,6 +334,28 @@ TORRENT_TEST(upnp_parser2)
|
|||
TEST_EQUAL(xml_s.model, "Wireless-G ADSL Home Gateway");
|
||||
}
|
||||
|
||||
TORRENT_TEST(upnp_parser3)
|
||||
{
|
||||
error_code_parse_state xml_s;
|
||||
xml_parse(upnp_xml3, upnp_xml3 + sizeof(upnp_xml3)
|
||||
, boost::bind(&find_error_code, _1, _2, _3, boost::ref(xml_s)));
|
||||
|
||||
std::cout << "error_code " << xml_s.error_code << std::endl;
|
||||
TEST_EQUAL(xml_s.error_code, 402);
|
||||
}
|
||||
|
||||
TORRENT_TEST(upnp_parser4)
|
||||
{
|
||||
ip_address_parse_state xml_s;
|
||||
xml_parse(upnp_xml4, upnp_xml4 + sizeof(upnp_xml4)
|
||||
, boost::bind(&find_ip_address, _1, _2, _3, boost::ref(xml_s)));
|
||||
|
||||
std::cout << "error_code " << xml_s.error_code << std::endl;
|
||||
std::cout << "ip_address " << xml_s.ip_address << std::endl;
|
||||
TEST_EQUAL(xml_s.error_code, -1);
|
||||
TEST_EQUAL(xml_s.ip_address, "123.10.20.30");
|
||||
}
|
||||
|
||||
TORRENT_TEST(tags)
|
||||
{
|
||||
test_parse("<a>foo<b/>bar</a>", "BaSfooEbSbarFa");
|
||||
|
|
Loading…
Reference in New Issue