changed http_parser slightly. uses http_parser in lsd.cpp. added more tests to the http_parser

This commit is contained in:
Arvid Norberg 2007-09-25 03:14:05 +00:00
parent 1df7c2006a
commit d48236a738
7 changed files with 99 additions and 61 deletions

View File

@ -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
{

View File

@ -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

View File

@ -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 + "\"");

View File

@ -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)

View File

@ -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

View File

@ -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.

View File

@ -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>";