forked from premiere/premiere-libtorrent
moved content-range parsing into http_parser and added unittest
This commit is contained in:
parent
a79932c9fd
commit
066d6ce799
|
@ -81,6 +81,8 @@ namespace libtorrent
|
|||
, bool& error);
|
||||
int body_start() const { return m_body_start_pos; }
|
||||
size_type content_length() const { return m_content_length; }
|
||||
std::pair<size_type, size_type> content_range() const
|
||||
{ return std::make_pair(m_range_start, m_range_end); }
|
||||
|
||||
void reset();
|
||||
|
||||
|
@ -95,6 +97,8 @@ namespace libtorrent
|
|||
std::string m_server_message;
|
||||
|
||||
size_type m_content_length;
|
||||
size_type m_range_start;
|
||||
size_type m_range_end;
|
||||
|
||||
enum { read_status, read_header, read_body, error_state } m_state;
|
||||
|
||||
|
|
|
@ -49,6 +49,8 @@ namespace libtorrent
|
|||
: m_recv_pos(0)
|
||||
, m_status_code(-1)
|
||||
, m_content_length(-1)
|
||||
, m_range_start(-1)
|
||||
, m_range_end(-1)
|
||||
, m_state(read_status)
|
||||
, m_recv_buffer(0, 0)
|
||||
, m_body_start_pos(0)
|
||||
|
@ -162,31 +164,37 @@ namespace libtorrent
|
|||
|
||||
if (name == "content-length")
|
||||
{
|
||||
#ifdef TORRENT_WINDOWS
|
||||
m_content_length = _atoi64(value.c_str());
|
||||
#else
|
||||
m_content_length = atoll(value.c_str());
|
||||
#endif
|
||||
m_content_length = strtoll(value.c_str(), 0, 10);
|
||||
}
|
||||
else if (name == "content-range")
|
||||
{
|
||||
std::stringstream range_str(value);
|
||||
char dummy;
|
||||
std::string bytes;
|
||||
size_type range_start, range_end;
|
||||
bool success = true;
|
||||
char const* ptr = value.c_str();
|
||||
|
||||
// apparently some web servers do not send the "bytes"
|
||||
// in their content-range
|
||||
if (value.find(' ') != std::string::npos)
|
||||
range_str >> bytes;
|
||||
range_str >> range_start >> dummy >> range_end;
|
||||
if (!range_str || range_end < range_start)
|
||||
// in their content-range. Don't treat it as an error
|
||||
// if we can't find it, just assume the byte counters
|
||||
// start immediately
|
||||
if (string_begins_no_case("bytes ", ptr)) ptr += 6;
|
||||
char* end;
|
||||
m_range_start = strtoll(ptr, &end, 10);
|
||||
if (end == ptr) success = false;
|
||||
else if (*end != '-') success = false;
|
||||
else
|
||||
{
|
||||
ptr = end + 1;
|
||||
m_range_end = strtoll(ptr, &end, 10);
|
||||
if (end == ptr) success = false;
|
||||
}
|
||||
|
||||
if (!success || m_range_end < m_range_start)
|
||||
{
|
||||
m_state = error_state;
|
||||
error = true;
|
||||
return ret;
|
||||
}
|
||||
// the http range is inclusive
|
||||
m_content_length = range_end - range_start + 1;
|
||||
m_content_length = m_range_end - m_range_start + 1;
|
||||
}
|
||||
|
||||
TORRENT_ASSERT(m_recv_pos <= (int)recv_buffer.left());
|
||||
|
@ -233,6 +241,8 @@ namespace libtorrent
|
|||
m_body_start_pos = 0;
|
||||
m_status_code = -1;
|
||||
m_content_length = -1;
|
||||
m_range_start = -1;
|
||||
m_range_end = -1;
|
||||
m_finished = false;
|
||||
m_state = read_status;
|
||||
m_recv_buffer.begin = 0;
|
||||
|
|
|
@ -480,31 +480,14 @@ namespace libtorrent
|
|||
size_type range_end;
|
||||
if (m_parser.status_code() == 206)
|
||||
{
|
||||
std::string const& range_str = m_parser.header("content-range");
|
||||
|
||||
bool success = true;
|
||||
char const* ptr = range_str.c_str();
|
||||
if (string_begins_no_case("bytes ", ptr)) ptr += 6;
|
||||
else success = false;
|
||||
char* end;
|
||||
range_start = strtoll(ptr, &end, 10);
|
||||
if (end == ptr) success = false;
|
||||
else if (*end != '-') success = false;
|
||||
else
|
||||
{
|
||||
ptr = end + 1;
|
||||
range_end = strtoll(ptr, &end, 10);
|
||||
if (end == ptr) success = false;
|
||||
}
|
||||
|
||||
if (!success)
|
||||
boost::tie(range_start, range_end) = m_parser.content_range();
|
||||
if (range_start < 0 || range_end < range_start)
|
||||
{
|
||||
m_statistics.received_bytes(0, bytes_transferred);
|
||||
// we should not try this server again.
|
||||
t->remove_web_seed(m_url, web_seed_entry::url_seed);
|
||||
char msg[200];
|
||||
snprintf(msg, 200, "invalid range in HTTP response: %s"
|
||||
, range_str.c_str());
|
||||
snprintf(msg, 200, "invalid range in HTTP response");
|
||||
disconnect(msg, 2);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -546,6 +546,22 @@ int test_main()
|
|||
TEST_CHECK(received == make_tuple(5, int(strlen(tracker_response) - 5), false));
|
||||
TEST_CHECK(parser.get_body().left() == 5);
|
||||
|
||||
parser.reset();
|
||||
|
||||
// make sure we support content-range responses
|
||||
// and that we're case insensitive
|
||||
char const* web_seed_response =
|
||||
"HTTP/1.1 206 OK\n"
|
||||
"contEnt-rAngE: bYTes 0-4\n"
|
||||
"conTent-TyPe: test/plain\n"
|
||||
"\n"
|
||||
"\ntest";
|
||||
|
||||
received = feed_bytes(parser, web_seed_response);
|
||||
|
||||
TEST_CHECK(received == make_tuple(5, int(strlen(web_seed_response) - 5), false));
|
||||
TEST_CHECK(parser.content_range() == (std::pair<size_type, size_type>(0, 4)));
|
||||
TEST_CHECK(parser.content_length() == 5);
|
||||
// test xml parser
|
||||
|
||||
char xml1[] = "<a>foo<b/>bar</a>";
|
||||
|
|
Loading…
Reference in New Issue