changed http_parser slightly. uses http_parser in lsd.cpp. added more tests to the http_parser
This commit is contained in:
parent
1df7c2006a
commit
d48236a738
|
@ -69,13 +69,20 @@ namespace libtorrent
|
|||
{
|
||||
public:
|
||||
http_parser();
|
||||
template <class T>
|
||||
T header(char const* key) const;
|
||||
std::string const& header(char const* key) const
|
||||
{
|
||||
static std::string empty;
|
||||
std::map<std::string, std::string>::const_iterator i
|
||||
= m_header.find(key);
|
||||
if (i == m_header.end()) return empty;
|
||||
return i->second;
|
||||
}
|
||||
|
||||
std::string const& protocol() const { return m_protocol; }
|
||||
int status_code() const { return m_status_code; }
|
||||
std::string const& method() const { return m_method; }
|
||||
std::string const& path() const { return m_path; }
|
||||
std::string message() const { return m_server_message; }
|
||||
std::string const& message() const { return m_server_message; }
|
||||
buffer::const_interval get_body() const;
|
||||
bool header_finished() const { return m_state == read_body; }
|
||||
bool finished() const { return m_finished; }
|
||||
|
@ -103,15 +110,6 @@ namespace libtorrent
|
|||
bool m_finished;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
T http_parser::header(char const* key) const
|
||||
{
|
||||
std::map<std::string, std::string>::const_iterator i
|
||||
= m_header.find(key);
|
||||
if (i == m_header.end()) return T();
|
||||
return boost::lexical_cast<T>(i->second);
|
||||
}
|
||||
|
||||
class TORRENT_EXPORT http_tracker_connection
|
||||
: public tracker_connection
|
||||
{
|
||||
|
|
|
@ -263,7 +263,7 @@ void http_connection::on_read(asio::error_code const& e
|
|||
if (code >= 300 && code < 400)
|
||||
{
|
||||
// attempt a redirect
|
||||
std::string url = m_parser.header<std::string>("location");
|
||||
std::string const& url = m_parser.header("location");
|
||||
if (url.empty())
|
||||
{
|
||||
// missing location header
|
||||
|
|
|
@ -679,7 +679,7 @@ namespace libtorrent
|
|||
|
||||
if (m_parser.header_finished())
|
||||
{
|
||||
int cl = m_parser.header<int>("content-length");
|
||||
int cl = atoi(m_parser.header("content-length").c_str());
|
||||
if (cl > m_settings.tracker_maximum_response_length)
|
||||
{
|
||||
fail(-1, "content-length is greater than maximum response length");
|
||||
|
@ -718,7 +718,7 @@ namespace libtorrent
|
|||
return;
|
||||
}
|
||||
|
||||
std::string location = m_parser.header<std::string>("location");
|
||||
std::string location = m_parser.header("location");
|
||||
|
||||
boost::shared_ptr<request_callback> cb = requester();
|
||||
|
||||
|
@ -763,7 +763,7 @@ namespace libtorrent
|
|||
|
||||
buffer::const_interval buf(&m_buffer[0] + m_parser.body_start(), &m_buffer[0] + m_recv_pos);
|
||||
|
||||
std::string content_encoding = m_parser.header<std::string>("content-encoding");
|
||||
std::string content_encoding = m_parser.header("content-encoding");
|
||||
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
if (cb) cb->debug_log("content-encoding: \"" + content_encoding + "\"");
|
||||
|
|
73
src/lsd.cpp
73
src/lsd.cpp
|
@ -121,48 +121,53 @@ void lsd::on_announce(udp::endpoint const& from, char* buffer
|
|||
{
|
||||
using namespace libtorrent::detail;
|
||||
|
||||
char* p = buffer;
|
||||
char* end = buffer + bytes_transferred;
|
||||
char* line = std::find(p, end, '\n');
|
||||
for (char* i = p; i < line; ++i) *i = std::tolower(*i);
|
||||
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
|
||||
m_log << time_now_string()
|
||||
<< " <== announce: " << std::string(p, line) << std::endl;
|
||||
#endif
|
||||
if (line == end || (line - p >= 9 && std::memcmp("bt-search", p, 9)))
|
||||
http_parser p;
|
||||
|
||||
p.incoming(buffer::const_interval(buffer, buffer + bytes_transferred));
|
||||
|
||||
if (!p.header_finished())
|
||||
{
|
||||
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
|
||||
m_log << time_now_string()
|
||||
<< " *** assumed 'bt-search', ignoring" << std::endl;
|
||||
m_log << time_now_string()
|
||||
<< " <== announce: incomplete HTTP message\n";
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
p = line + 1;
|
||||
int port = 0;
|
||||
sha1_hash ih(0);
|
||||
while (p != end)
|
||||
|
||||
if (p.method() != "bt-search")
|
||||
{
|
||||
line = std::find(p, end, '\n');
|
||||
if (line == end) break;
|
||||
*line = 0;
|
||||
for (char* i = p; i < line; ++i) *i = std::tolower(*i);
|
||||
if (line - p >= 5 && memcmp(p, "port:", 5) == 0)
|
||||
{
|
||||
p += 5;
|
||||
while (*p == ' ') ++p;
|
||||
port = atoi(p);
|
||||
}
|
||||
else if (line - p >= 9 && memcmp(p, "infohash:", 9) == 0)
|
||||
{
|
||||
p += 9;
|
||||
while (*p == ' ') ++p;
|
||||
if (line - p > 40) p[40] = 0;
|
||||
try { ih = boost::lexical_cast<sha1_hash>(p); }
|
||||
catch (std::exception&) {}
|
||||
}
|
||||
p = line + 1;
|
||||
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
|
||||
m_log << time_now_string()
|
||||
<< " <== announce: invalid HTTP method: " << p.method() << std::endl;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
std::string const& port_str = p.header("port");
|
||||
if (port_str.empty())
|
||||
{
|
||||
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
|
||||
m_log << time_now_string()
|
||||
<< " <== announce: invalid BT-SEARCH, missing port" << std::endl;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
std::string const& ih_str = p.header("infohash");
|
||||
if (ih_str.empty())
|
||||
{
|
||||
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
|
||||
m_log << time_now_string()
|
||||
<< " <== announce: invalid BT-SEARCH, missing infohash" << std::endl;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
sha1_hash ih(0);
|
||||
std::istringstream ih_sstr(ih_str);
|
||||
ih_sstr >> ih;
|
||||
int port = atoi(port_str.c_str());
|
||||
|
||||
if (!ih.is_all_zeros() && port != 0)
|
||||
{
|
||||
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
|
||||
|
|
|
@ -300,7 +300,7 @@ try
|
|||
return;
|
||||
}
|
||||
|
||||
std::string url = p.header<std::string>("location");
|
||||
std::string url = p.header("location");
|
||||
if (url.empty())
|
||||
{
|
||||
#ifdef TORRENT_UPNP_LOGGING
|
||||
|
|
|
@ -387,7 +387,7 @@ namespace libtorrent
|
|||
{
|
||||
// this means we got a redirection request
|
||||
// look for the location header
|
||||
std::string location = m_parser.header<std::string>("location");
|
||||
std::string location = m_parser.header("location");
|
||||
|
||||
if (location.empty())
|
||||
{
|
||||
|
@ -423,7 +423,7 @@ namespace libtorrent
|
|||
throw std::runtime_error("redirecting to " + location);
|
||||
}
|
||||
|
||||
std::string server_version = m_parser.header<std::string>("server");
|
||||
std::string const& server_version = m_parser.header("server");
|
||||
if (!server_version.empty())
|
||||
{
|
||||
m_server_string = "URL seed @ ";
|
||||
|
@ -445,7 +445,7 @@ namespace libtorrent
|
|||
size_type range_end;
|
||||
if (m_parser.status_code() == 206)
|
||||
{
|
||||
std::stringstream range_str(m_parser.header<std::string>("content-range"));
|
||||
std::stringstream range_str(m_parser.header("content-range"));
|
||||
char dummy;
|
||||
std::string bytes;
|
||||
range_str >> bytes >> range_start >> dummy >> range_end;
|
||||
|
@ -461,7 +461,7 @@ namespace libtorrent
|
|||
else
|
||||
{
|
||||
range_start = 0;
|
||||
range_end = m_parser.header<size_type>("content-length");
|
||||
range_end = atol(m_parser.header("content-length").c_str());
|
||||
if (range_end == -1)
|
||||
{
|
||||
// we should not try this server again.
|
||||
|
|
|
@ -102,8 +102,8 @@ int test_main()
|
|||
TEST_CHECK(received == make_tuple(4, 64));
|
||||
TEST_CHECK(parser.finished());
|
||||
TEST_CHECK(std::equal(parser.get_body().begin, parser.get_body().end, "test"));
|
||||
TEST_CHECK(parser.header<std::string>("content-type") == "text/plain");
|
||||
TEST_CHECK(parser.header<int>("content-length") == 4);
|
||||
TEST_CHECK(parser.header("content-type") == "text/plain");
|
||||
TEST_CHECK(atoi(parser.header("content-length").c_str()) == 4);
|
||||
|
||||
parser.reset();
|
||||
|
||||
|
@ -123,11 +123,11 @@ int test_main()
|
|||
|
||||
TEST_CHECK(received == make_tuple(0, int(strlen(upnp_response))));
|
||||
TEST_CHECK(parser.get_body().left() == 0);
|
||||
TEST_CHECK(parser.header<std::string>("st") == "upnp:rootdevice");
|
||||
TEST_CHECK(parser.header<std::string>("location")
|
||||
TEST_CHECK(parser.header("st") == "upnp:rootdevice");
|
||||
TEST_CHECK(parser.header("location")
|
||||
== "http://192.168.1.1:5431/dyndev/uuid:000f-66d6-7296000099dc");
|
||||
TEST_CHECK(parser.header<std::string>("ext") == "");
|
||||
TEST_CHECK(parser.header<std::string>("date") == "Fri, 02 Jan 1970 08:10:38 GMT");
|
||||
TEST_CHECK(parser.header("ext") == "");
|
||||
TEST_CHECK(parser.header("date") == "Fri, 02 Jan 1970 08:10:38 GMT");
|
||||
|
||||
parser.reset();
|
||||
TEST_CHECK(!parser.finished());
|
||||
|
@ -148,6 +148,41 @@ int test_main()
|
|||
TEST_CHECK(parser.method() == "notify");
|
||||
TEST_CHECK(parser.path() == "*");
|
||||
|
||||
parser.reset();
|
||||
TEST_CHECK(!parser.finished());
|
||||
|
||||
char const* bt_lsd = "BT-SEARCH * HTTP/1.1\r\n"
|
||||
"Host: 239.192.152.143:6771\r\n"
|
||||
"Port: 6881\r\n"
|
||||
"Infohash: 12345678901234567890\r\n"
|
||||
"\r\n\r\n";
|
||||
|
||||
received = feed_bytes(parser, bt_lsd);
|
||||
|
||||
TEST_CHECK(received == make_tuple(2, int(strlen(bt_lsd) - 2)));
|
||||
TEST_CHECK(parser.method() == "bt-search");
|
||||
TEST_CHECK(parser.path() == "*");
|
||||
TEST_CHECK(atoi(parser.header("port").c_str()) == 6881);
|
||||
TEST_CHECK(parser.header("infohash") == "12345678901234567890");
|
||||
|
||||
TEST_CHECK(!parser.finished());
|
||||
|
||||
parser.reset();
|
||||
TEST_CHECK(!parser.finished());
|
||||
|
||||
// make sure we support trackers with incorrect line endings
|
||||
char const* tracker_response =
|
||||
"HTTP/1.1 200 OK\n"
|
||||
"content-length: 5\n"
|
||||
"content-type: test/plain\n"
|
||||
"\n"
|
||||
"\ntest";
|
||||
|
||||
received = feed_bytes(parser, tracker_response);
|
||||
|
||||
TEST_CHECK(received == make_tuple(5, int(strlen(tracker_response) - 5)));
|
||||
TEST_CHECK(parser.get_body().left() == 5);
|
||||
|
||||
// test xml parser
|
||||
|
||||
char xml1[] = "<a>foo<b/>bar</a>";
|
||||
|
|
Loading…
Reference in New Issue