transition part of http_parser to use span (#936)
transition parts of http_parser to use span
This commit is contained in:
parent
ec30daeaa5
commit
4f803353cf
|
@ -55,7 +55,7 @@ namespace libtorrent { namespace aux
|
||||||
ret <<= 8;
|
ret <<= 8;
|
||||||
ret |= static_cast<std::uint8_t>(view[i]);
|
ret |= static_cast<std::uint8_t>(view[i]);
|
||||||
}
|
}
|
||||||
view = view.cut_first(sizeof(T));
|
view = view.subspan(sizeof(T));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ namespace libtorrent { namespace aux
|
||||||
shift -= 8;
|
shift -= 8;
|
||||||
view[i] = static_cast<unsigned char>((val >> shift) & 0xff);
|
view[i] = static_cast<unsigned char>((val >> shift) & 0xff);
|
||||||
}
|
}
|
||||||
view = view.cut_first(sizeof(T));
|
view = view.subspan(sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- adaptors
|
// -- adaptors
|
||||||
|
|
|
@ -75,6 +75,7 @@ class buffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
// TODO: 3 remove interval and const_interval
|
||||||
struct interval
|
struct interval
|
||||||
{
|
{
|
||||||
interval()
|
interval()
|
||||||
|
@ -208,20 +209,8 @@ public:
|
||||||
|
|
||||||
~buffer() { std::free(m_begin); }
|
~buffer() { std::free(m_begin); }
|
||||||
|
|
||||||
// TODO: 3 fix the naming convention here
|
char* data() { return m_begin; }
|
||||||
char* ptr() { return m_begin; }
|
char const* data() const { return m_begin; }
|
||||||
char const* ptr() const { return m_begin; }
|
|
||||||
|
|
||||||
buffer::interval data()
|
|
||||||
{ return interval(m_begin, m_begin + m_size); }
|
|
||||||
buffer::const_interval data() const
|
|
||||||
{ return interval(m_begin, m_begin + m_size); }
|
|
||||||
|
|
||||||
operator span<char>()
|
|
||||||
{ return span<char>(m_begin, int(m_size)); }
|
|
||||||
operator span<char const>() const
|
|
||||||
{ return span<char const>(m_begin, int(m_size)); }
|
|
||||||
|
|
||||||
std::size_t size() const { return m_size; }
|
std::size_t size() const { return m_size; }
|
||||||
|
|
||||||
bool empty() const { return m_size == 0; }
|
bool empty() const { return m_size == 0; }
|
||||||
|
@ -239,6 +228,7 @@ public:
|
||||||
swap(m_begin, b.m_begin);
|
swap(m_begin, b.m_begin);
|
||||||
swap(m_size, b.m_size);
|
swap(m_size, b.m_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char* m_begin = nullptr;
|
char* m_begin = nullptr;
|
||||||
// m_begin points to an allocation of this size.
|
// m_begin points to an allocation of this size.
|
||||||
|
|
|
@ -77,7 +77,7 @@ namespace libtorrent
|
||||||
buffer::const_interval get_body() const;
|
buffer::const_interval get_body() const;
|
||||||
bool header_finished() const { return m_state == read_body; }
|
bool header_finished() const { return m_state == read_body; }
|
||||||
bool finished() const { return m_finished; }
|
bool finished() const { return m_finished; }
|
||||||
std::tuple<int, int> incoming(buffer::const_interval recv_buffer
|
std::tuple<int, int> incoming(span<char const> recv_buffer
|
||||||
, bool& error);
|
, bool& error);
|
||||||
int body_start() const { return m_body_start_pos; }
|
int body_start() const { return m_body_start_pos; }
|
||||||
std::int64_t content_length() const { return m_content_length; }
|
std::int64_t content_length() const { return m_content_length; }
|
||||||
|
@ -110,7 +110,7 @@ namespace libtorrent
|
||||||
// if the function returns false, the chunk size and header
|
// if the function returns false, the chunk size and header
|
||||||
// size may still have been modified, but their values are
|
// size may still have been modified, but their values are
|
||||||
// undefined
|
// undefined
|
||||||
bool parse_chunk_header(buffer::const_interval buf
|
bool parse_chunk_header(span<char const> buf
|
||||||
, std::int64_t* chunk_size, int* header_size);
|
, std::int64_t* chunk_size, int* header_size);
|
||||||
|
|
||||||
// reset the whole state and start over
|
// reset the whole state and start over
|
||||||
|
@ -122,18 +122,18 @@ namespace libtorrent
|
||||||
std::vector<std::pair<std::int64_t, std::int64_t> > const& chunks() const { return m_chunked_ranges; }
|
std::vector<std::pair<std::int64_t, std::int64_t> > const& chunks() const { return m_chunked_ranges; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::int64_t m_recv_pos;
|
std::int64_t m_recv_pos = 0;
|
||||||
std::string m_method;
|
std::string m_method;
|
||||||
std::string m_path;
|
std::string m_path;
|
||||||
std::string m_protocol;
|
std::string m_protocol;
|
||||||
std::string m_server_message;
|
std::string m_server_message;
|
||||||
|
|
||||||
std::int64_t m_content_length;
|
std::int64_t m_content_length = -1;
|
||||||
std::int64_t m_range_start;
|
std::int64_t m_range_start = -1;
|
||||||
std::int64_t m_range_end;
|
std::int64_t m_range_end = -1;
|
||||||
|
|
||||||
std::multimap<std::string, std::string> m_header;
|
std::multimap<std::string, std::string> m_header;
|
||||||
buffer::const_interval m_recv_buffer;
|
span<char const> m_recv_buffer;
|
||||||
// contains offsets of the first and one-past-end of
|
// contains offsets of the first and one-past-end of
|
||||||
// each chunked range in the response
|
// each chunked range in the response
|
||||||
std::vector<std::pair<std::int64_t, std::int64_t> > m_chunked_ranges;
|
std::vector<std::pair<std::int64_t, std::int64_t> > m_chunked_ranges;
|
||||||
|
@ -141,27 +141,27 @@ namespace libtorrent
|
||||||
// while reading a chunk, this is the offset where the
|
// while reading a chunk, this is the offset where the
|
||||||
// current chunk will end (it refers to the first character
|
// current chunk will end (it refers to the first character
|
||||||
// in the chunk tail header or the next chunk header)
|
// in the chunk tail header or the next chunk header)
|
||||||
std::int64_t m_cur_chunk_end;
|
std::int64_t m_cur_chunk_end = -1;
|
||||||
|
|
||||||
int m_status_code;
|
int m_status_code = -1;
|
||||||
|
|
||||||
// the sum of all chunk headers read so far
|
// the sum of all chunk headers read so far
|
||||||
int m_chunk_header_size;
|
int m_chunk_header_size = 0;
|
||||||
|
|
||||||
int m_partial_chunk_header;
|
int m_partial_chunk_header = 0;
|
||||||
|
|
||||||
// controls some behaviors of the parser
|
// controls some behaviors of the parser
|
||||||
int m_flags;
|
int m_flags;
|
||||||
|
|
||||||
int m_body_start_pos;
|
int m_body_start_pos = 0;
|
||||||
|
|
||||||
enum { read_status, read_header, read_body, error_state } m_state;
|
enum { read_status, read_header, read_body, error_state } m_state = read_status;
|
||||||
|
|
||||||
// this is true if the server is HTTP/1.0 or
|
// this is true if the server is HTTP/1.0 or
|
||||||
// if it sent "connection: close"
|
// if it sent "connection: close"
|
||||||
bool m_connection_close;
|
bool m_connection_close = false;
|
||||||
bool m_chunked_encoding;
|
bool m_chunked_encoding = false;
|
||||||
bool m_finished;
|
bool m_finished = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,6 +85,7 @@ struct TORRENT_EXTRA_EXPORT receive_buffer
|
||||||
|
|
||||||
// return the interval between the start of the buffer to the read cursor.
|
// return the interval between the start of the buffer to the read cursor.
|
||||||
// This is the "current" packet.
|
// This is the "current" packet.
|
||||||
|
// TODO: 3 use span
|
||||||
buffer::const_interval get() const;
|
buffer::const_interval get() const;
|
||||||
|
|
||||||
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
|
@ -198,6 +199,7 @@ struct crypto_receive_buffer
|
||||||
|
|
||||||
int advance_pos(int bytes);
|
int advance_pos(int bytes);
|
||||||
|
|
||||||
|
// TODO: 3 use span
|
||||||
buffer::const_interval get() const;
|
buffer::const_interval get() const;
|
||||||
|
|
||||||
aux::mutable_buffer mutable_buffer(std::size_t bytes);
|
aux::mutable_buffer mutable_buffer(std::size_t bytes);
|
||||||
|
|
|
@ -92,10 +92,17 @@ namespace libtorrent
|
||||||
return { data() + size() - n, n };
|
return { data() + size() - n, n };
|
||||||
}
|
}
|
||||||
|
|
||||||
span<T> cut_first(size_t const n) const
|
span<T> subspan(size_t const offset) const
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(size() >= n);
|
TORRENT_ASSERT(size() >= offset);
|
||||||
return { data() + n, int(size()) - n };
|
return { data() + offset, size() - offset };
|
||||||
|
}
|
||||||
|
|
||||||
|
span<T> subspan(size_t const offset, size_t count) const
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(size() >= offset);
|
||||||
|
TORRENT_ASSERT(size() >= offset + count);
|
||||||
|
return { data() + offset, count };
|
||||||
}
|
}
|
||||||
|
|
||||||
T& operator[](size_t const idx)
|
T& operator[](size_t const idx)
|
||||||
|
|
|
@ -743,10 +743,9 @@ void http_connection::on_read(error_code const& e
|
||||||
|
|
||||||
if (m_bottled || !m_parser.header_finished())
|
if (m_bottled || !m_parser.header_finished())
|
||||||
{
|
{
|
||||||
libtorrent::buffer::const_interval rcv_buf(&m_recvbuffer[0]
|
span<char const> rcv_buf(m_recvbuffer);
|
||||||
, &m_recvbuffer[0] + m_read_pos);
|
|
||||||
bool error = false;
|
bool error = false;
|
||||||
m_parser.incoming(rcv_buf, error);
|
m_parser.incoming(rcv_buf.subspan(0, m_read_pos), error);
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
// HTTP parse error
|
// HTTP parse error
|
||||||
|
|
|
@ -132,33 +132,17 @@ namespace libtorrent
|
||||||
|
|
||||||
http_parser::~http_parser() = default;
|
http_parser::~http_parser() = default;
|
||||||
|
|
||||||
http_parser::http_parser(int flags)
|
http_parser::http_parser(int const flags) : m_flags(flags) {}
|
||||||
: m_recv_pos(0)
|
|
||||||
, m_content_length(-1)
|
|
||||||
, m_range_start(-1)
|
|
||||||
, m_range_end(-1)
|
|
||||||
, m_recv_buffer(nullptr, nullptr)
|
|
||||||
, m_cur_chunk_end(-1)
|
|
||||||
, m_status_code(-1)
|
|
||||||
, m_chunk_header_size(0)
|
|
||||||
, m_partial_chunk_header(0)
|
|
||||||
, m_flags(flags)
|
|
||||||
, m_body_start_pos(0)
|
|
||||||
, m_state(read_status)
|
|
||||||
, m_connection_close(false)
|
|
||||||
, m_chunked_encoding(false)
|
|
||||||
, m_finished(false)
|
|
||||||
{}
|
|
||||||
|
|
||||||
std::tuple<int, int> http_parser::incoming(
|
std::tuple<int, int> http_parser::incoming(
|
||||||
buffer::const_interval recv_buffer, bool& error)
|
span<char const> recv_buffer, bool& error)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(recv_buffer.left() >= m_recv_buffer.left());
|
TORRENT_ASSERT(recv_buffer.size() >= m_recv_buffer.size());
|
||||||
std::tuple<int, int> ret(0, 0);
|
std::tuple<int, int> ret(0, 0);
|
||||||
int start_pos = m_recv_buffer.left();
|
size_t start_pos = m_recv_buffer.size();
|
||||||
|
|
||||||
// early exit if there's nothing new in the receive buffer
|
// early exit if there's nothing new in the receive buffer
|
||||||
if (start_pos == recv_buffer.left()) return ret;
|
if (start_pos == recv_buffer.size()) return ret;
|
||||||
m_recv_buffer = recv_buffer;
|
m_recv_buffer = recv_buffer;
|
||||||
|
|
||||||
if (m_state == error_state)
|
if (m_state == error_state)
|
||||||
|
@ -167,19 +151,19 @@ namespace libtorrent
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
char const* pos = recv_buffer.begin + m_recv_pos;
|
char const* pos = recv_buffer.data() + m_recv_pos;
|
||||||
|
|
||||||
restart_response:
|
restart_response:
|
||||||
|
|
||||||
if (m_state == read_status)
|
if (m_state == read_status)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(!m_finished);
|
TORRENT_ASSERT(!m_finished);
|
||||||
TORRENT_ASSERT(pos <= recv_buffer.end);
|
TORRENT_ASSERT(pos <= recv_buffer.end());
|
||||||
char const* newline = std::find(pos, recv_buffer.end, '\n');
|
char const* newline = std::find(pos, recv_buffer.end(), '\n');
|
||||||
// if we don't have a full line yet, wait.
|
// if we don't have a full line yet, wait.
|
||||||
if (newline == recv_buffer.end)
|
if (newline == recv_buffer.end())
|
||||||
{
|
{
|
||||||
std::get<1>(ret) += m_recv_buffer.left() - start_pos;
|
std::get<1>(ret) += int(m_recv_buffer.size() - start_pos);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,7 +182,7 @@ restart_response:
|
||||||
TORRENT_ASSERT(newline >= pos);
|
TORRENT_ASSERT(newline >= pos);
|
||||||
int incoming = int(newline - pos);
|
int incoming = int(newline - pos);
|
||||||
m_recv_pos += incoming;
|
m_recv_pos += incoming;
|
||||||
std::get<1>(ret) += newline - (m_recv_buffer.begin + start_pos);
|
std::get<1>(ret) += int(newline - (m_recv_buffer.data() + start_pos));
|
||||||
pos = newline;
|
pos = newline;
|
||||||
|
|
||||||
m_protocol = read_until(line, ' ', line_end);
|
m_protocol = read_until(line, ' ', line_end);
|
||||||
|
@ -223,17 +207,17 @@ restart_response:
|
||||||
m_status_code = 0;
|
m_status_code = 0;
|
||||||
}
|
}
|
||||||
m_state = read_header;
|
m_state = read_header;
|
||||||
start_pos = pos - recv_buffer.begin;
|
start_pos = pos - recv_buffer.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_state == read_header)
|
if (m_state == read_header)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(!m_finished);
|
TORRENT_ASSERT(!m_finished);
|
||||||
TORRENT_ASSERT(pos <= recv_buffer.end);
|
TORRENT_ASSERT(pos <= recv_buffer.end());
|
||||||
char const* newline = std::find(pos, recv_buffer.end, '\n');
|
char const* newline = std::find(pos, recv_buffer.end(), '\n');
|
||||||
std::string line;
|
std::string line;
|
||||||
|
|
||||||
while (newline != recv_buffer.end && m_state == read_header)
|
while (newline != recv_buffer.end() && m_state == read_header)
|
||||||
{
|
{
|
||||||
// if the LF character is preceeded by a CR
|
// if the LF character is preceeded by a CR
|
||||||
// charachter, don't copy it into the line string.
|
// charachter, don't copy it into the line string.
|
||||||
|
@ -338,16 +322,16 @@ restart_response:
|
||||||
m_chunked_encoding = string_begins_no_case("chunked", value.c_str());
|
m_chunked_encoding = string_begins_no_case("chunked", value.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
TORRENT_ASSERT(m_recv_pos <= recv_buffer.left());
|
TORRENT_ASSERT(m_recv_pos <= recv_buffer.size());
|
||||||
TORRENT_ASSERT(pos <= recv_buffer.end);
|
TORRENT_ASSERT(pos <= recv_buffer.end());
|
||||||
newline = std::find(pos, recv_buffer.end, '\n');
|
newline = std::find(pos, recv_buffer.end(), '\n');
|
||||||
}
|
}
|
||||||
std::get<1>(ret) += newline - (m_recv_buffer.begin + start_pos);
|
std::get<1>(ret) += int(newline - (m_recv_buffer.data() + start_pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_state == read_body)
|
if (m_state == read_body)
|
||||||
{
|
{
|
||||||
int incoming = recv_buffer.end - pos;
|
int incoming = recv_buffer.end() - pos;
|
||||||
|
|
||||||
if (m_chunked_encoding && (m_flags & dont_parse_chunks) == 0)
|
if (m_chunked_encoding && (m_flags & dont_parse_chunks) == 0)
|
||||||
{
|
{
|
||||||
|
@ -364,7 +348,8 @@ restart_response:
|
||||||
std::get<0>(ret) += int(payload);
|
std::get<0>(ret) += int(payload);
|
||||||
incoming -= int(payload);
|
incoming -= int(payload);
|
||||||
}
|
}
|
||||||
buffer::const_interval buf(recv_buffer.begin + m_cur_chunk_end, recv_buffer.end);
|
auto const buf = span<char const>(recv_buffer)
|
||||||
|
.subspan(m_cur_chunk_end);
|
||||||
std::int64_t chunk_size;
|
std::int64_t chunk_size;
|
||||||
int header_size;
|
int header_size;
|
||||||
if (parse_chunk_header(buf, &chunk_size, &header_size))
|
if (parse_chunk_header(buf, &chunk_size, &header_size))
|
||||||
|
@ -393,7 +378,7 @@ restart_response:
|
||||||
// std::fprintf(stderr, "parse_chunk_header(%d, -> %d, -> %d) -> %d\n"
|
// std::fprintf(stderr, "parse_chunk_header(%d, -> %d, -> %d) -> %d\n"
|
||||||
// " incoming = %d\n m_recv_pos = %d\n m_cur_chunk_end = %d\n"
|
// " incoming = %d\n m_recv_pos = %d\n m_cur_chunk_end = %d\n"
|
||||||
// " content-length = %d\n"
|
// " content-length = %d\n"
|
||||||
// , buf.left(), int(chunk_size), header_size, 1, incoming, int(m_recv_pos)
|
// , buf.size(), int(chunk_size), header_size, 1, incoming, int(m_recv_pos)
|
||||||
// , m_cur_chunk_end, int(m_content_length));
|
// , m_cur_chunk_end, int(m_content_length));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -404,7 +389,7 @@ restart_response:
|
||||||
// std::fprintf(stderr, "parse_chunk_header(%d, -> %d, -> %d) -> %d\n"
|
// std::fprintf(stderr, "parse_chunk_header(%d, -> %d, -> %d) -> %d\n"
|
||||||
// " incoming = %d\n m_recv_pos = %d\n m_cur_chunk_end = %d\n"
|
// " incoming = %d\n m_recv_pos = %d\n m_cur_chunk_end = %d\n"
|
||||||
// " content-length = %d\n"
|
// " content-length = %d\n"
|
||||||
// , buf.left(), int(chunk_size), header_size, 0, incoming, int(m_recv_pos)
|
// , buf.size(), int(chunk_size), header_size, 0, incoming, int(m_recv_pos)
|
||||||
// , m_cur_chunk_end, int(m_content_length));
|
// , m_cur_chunk_end, int(m_content_length));
|
||||||
}
|
}
|
||||||
m_chunk_header_size += header_size;
|
m_chunk_header_size += header_size;
|
||||||
|
@ -445,23 +430,22 @@ restart_response:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool http_parser::parse_chunk_header(buffer::const_interval buf
|
bool http_parser::parse_chunk_header(span<char const> buf
|
||||||
, std::int64_t* chunk_size, int* header_size)
|
, std::int64_t* chunk_size, int* header_size)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(buf.begin <= buf.end);
|
char const* pos = buf.data();
|
||||||
char const* pos = buf.begin;
|
|
||||||
|
|
||||||
// ignore one optional new-line. This is since each chunk
|
// ignore one optional new-line. This is since each chunk
|
||||||
// is terminated by a newline. we're likely to see one
|
// is terminated by a newline. we're likely to see one
|
||||||
// before the actual header.
|
// before the actual header.
|
||||||
|
|
||||||
if (pos < buf.end && pos[0] == '\r') ++pos;
|
if (pos < buf.end() && pos[0] == '\r') ++pos;
|
||||||
if (pos < buf.end && pos[0] == '\n') ++pos;
|
if (pos < buf.end() && pos[0] == '\n') ++pos;
|
||||||
if (pos == buf.end) return false;
|
if (pos == buf.end()) return false;
|
||||||
|
|
||||||
TORRENT_ASSERT(pos <= buf.end);
|
TORRENT_ASSERT(pos <= buf.end());
|
||||||
char const* newline = std::find(pos, buf.end, '\n');
|
char const* newline = std::find(pos, buf.end(), '\n');
|
||||||
if (newline == buf.end) return false;
|
if (newline == buf.end()) return false;
|
||||||
++newline;
|
++newline;
|
||||||
|
|
||||||
// the chunk header is a single line, a hex length of the
|
// the chunk header is a single line, a hex length of the
|
||||||
|
@ -476,19 +460,19 @@ restart_response:
|
||||||
|
|
||||||
if (*chunk_size != 0)
|
if (*chunk_size != 0)
|
||||||
{
|
{
|
||||||
*header_size = newline - buf.begin;
|
*header_size = newline - buf.data();
|
||||||
// the newline alone is two bytes
|
// the newline alone is two bytes
|
||||||
TORRENT_ASSERT(newline - buf.begin > 2);
|
TORRENT_ASSERT(newline - buf.data() > 2);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is the terminator of the stream. Also read headers
|
// this is the terminator of the stream. Also read headers
|
||||||
std::map<std::string, std::string> tail_headers;
|
std::map<std::string, std::string> tail_headers;
|
||||||
pos = newline;
|
pos = newline;
|
||||||
newline = std::find(pos, buf.end, '\n');
|
newline = std::find(pos, buf.end(), '\n');
|
||||||
|
|
||||||
std::string line;
|
std::string line;
|
||||||
while (newline != buf.end)
|
while (newline != buf.end())
|
||||||
{
|
{
|
||||||
// if the LF character is preceeded by a CR
|
// if the LF character is preceeded by a CR
|
||||||
// charachter, don't copy it into the line string.
|
// charachter, don't copy it into the line string.
|
||||||
|
@ -504,10 +488,10 @@ restart_response:
|
||||||
// this means we got a blank line,
|
// this means we got a blank line,
|
||||||
// the header is finished and the body
|
// the header is finished and the body
|
||||||
// starts.
|
// starts.
|
||||||
*header_size = newline - buf.begin;
|
*header_size = newline - buf.data();
|
||||||
|
|
||||||
// the newline alone is two bytes
|
// the newline alone is two bytes
|
||||||
TORRENT_ASSERT(newline - buf.begin > 2);
|
TORRENT_ASSERT(newline - buf.data() > 2);
|
||||||
|
|
||||||
// we were successfull in parsing the headers.
|
// we were successfull in parsing the headers.
|
||||||
// add them to the headers in the parser
|
// add them to the headers in the parser
|
||||||
|
@ -529,7 +513,7 @@ restart_response:
|
||||||
tail_headers.insert(std::make_pair(name, value));
|
tail_headers.insert(std::make_pair(name, value));
|
||||||
// std::fprintf(stderr, "tail_header: %s: %s\n", name.c_str(), value.c_str());
|
// std::fprintf(stderr, "tail_header: %s: %s\n", name.c_str(), value.c_str());
|
||||||
|
|
||||||
newline = std::find(pos, buf.end, '\n');
|
newline = std::find(pos, buf.end(), '\n');
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -543,8 +527,9 @@ restart_response:
|
||||||
? m_recv_pos : (std::min)(m_body_start_pos + m_content_length, m_recv_pos);
|
? m_recv_pos : (std::min)(m_body_start_pos + m_content_length, m_recv_pos);
|
||||||
|
|
||||||
TORRENT_ASSERT(last_byte >= m_body_start_pos);
|
TORRENT_ASSERT(last_byte >= m_body_start_pos);
|
||||||
return buffer::const_interval(m_recv_buffer.begin + m_body_start_pos
|
return buffer::const_interval(m_recv_buffer.data()
|
||||||
, m_recv_buffer.begin + last_byte);
|
+ m_body_start_pos
|
||||||
|
, m_recv_buffer.data() + last_byte);
|
||||||
}
|
}
|
||||||
|
|
||||||
void http_parser::reset()
|
void http_parser::reset()
|
||||||
|
@ -558,8 +543,7 @@ restart_response:
|
||||||
m_range_end = -1;
|
m_range_end = -1;
|
||||||
m_finished = false;
|
m_finished = false;
|
||||||
m_state = read_status;
|
m_state = read_status;
|
||||||
m_recv_buffer.begin = nullptr;
|
m_recv_buffer = span<char const>();
|
||||||
m_recv_buffer.end = nullptr;
|
|
||||||
m_header.clear();
|
m_header.clear();
|
||||||
m_chunked_encoding = false;
|
m_chunked_encoding = false;
|
||||||
m_chunked_ranges.clear();
|
m_chunked_ranges.clear();
|
||||||
|
|
|
@ -247,7 +247,8 @@ namespace libtorrent
|
||||||
bool parse_error = false;
|
bool parse_error = false;
|
||||||
int protocol = 0;
|
int protocol = 0;
|
||||||
int payload = 0;
|
int payload = 0;
|
||||||
std::tie(payload, protocol) = m_parser.incoming(recv_buffer, parse_error);
|
std::tie(payload, protocol) = m_parser.incoming(span<char const>(
|
||||||
|
recv_buffer.begin, recv_buffer.left()), parse_error);
|
||||||
received_bytes(0, protocol);
|
received_bytes(0, protocol);
|
||||||
bytes_transferred -= protocol;
|
bytes_transferred -= protocol;
|
||||||
#if TORRENT_USE_ASSERTS
|
#if TORRENT_USE_ASSERTS
|
||||||
|
@ -362,17 +363,16 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
int header_size = 0;
|
int header_size = 0;
|
||||||
std::int64_t chunk_size = 0;
|
std::int64_t chunk_size = 0;
|
||||||
buffer::const_interval chunk_start = recv_buffer;
|
span<char const> chunk_start(recv_buffer.begin + m_chunk_pos, recv_buffer.left() - m_chunk_pos);
|
||||||
chunk_start.begin += m_chunk_pos;
|
TORRENT_ASSERT(chunk_start[0] == '\r'
|
||||||
TORRENT_ASSERT(chunk_start.begin[0] == '\r'
|
|| aux::is_hex(chunk_start.data(), 1));
|
||||||
|| aux::is_hex(chunk_start.begin, 1));
|
|
||||||
bool ret = m_parser.parse_chunk_header(chunk_start, &chunk_size, &header_size);
|
bool ret = m_parser.parse_chunk_header(chunk_start, &chunk_size, &header_size);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(bytes_transferred >= size_t(chunk_start.left() - m_partial_chunk_header));
|
TORRENT_ASSERT(bytes_transferred >= size_t(chunk_start.size() - m_partial_chunk_header));
|
||||||
bytes_transferred -= chunk_start.left() - m_partial_chunk_header;
|
bytes_transferred -= chunk_start.size() - m_partial_chunk_header;
|
||||||
received_bytes(0, chunk_start.left() - m_partial_chunk_header);
|
received_bytes(0, int(chunk_start.size() - m_partial_chunk_header));
|
||||||
m_partial_chunk_header = chunk_start.left();
|
m_partial_chunk_header = int(chunk_start.size());
|
||||||
if (bytes_transferred == 0) return;
|
if (bytes_transferred == 0) return;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -388,7 +388,7 @@ namespace libtorrent
|
||||||
|
|
||||||
received_bytes(0, header_size - m_partial_chunk_header);
|
received_bytes(0, header_size - m_partial_chunk_header);
|
||||||
m_partial_chunk_header = 0;
|
m_partial_chunk_header = 0;
|
||||||
TORRENT_ASSERT(chunk_size != 0 || chunk_start.left() <= header_size || chunk_start.begin[header_size] == 'H');
|
TORRENT_ASSERT(chunk_size != 0 || chunk_start.size() <= header_size || chunk_start[header_size] == 'H');
|
||||||
// cut out the chunk header from the receive buffer
|
// cut out the chunk header from the receive buffer
|
||||||
TORRENT_ASSERT(m_chunk_pos + m_body_start < INT_MAX);
|
TORRENT_ASSERT(m_chunk_pos + m_body_start < INT_MAX);
|
||||||
m_recv_buffer.cut(header_size, t->block_size() + 1024, int(m_chunk_pos + m_body_start));
|
m_recv_buffer.cut(header_size, t->block_size() + 1024, int(m_chunk_pos + m_body_start));
|
||||||
|
|
|
@ -214,8 +214,7 @@ void lsd::on_announce(udp::endpoint const& from, char* buf
|
||||||
http_parser p;
|
http_parser p;
|
||||||
|
|
||||||
bool error = false;
|
bool error = false;
|
||||||
p.incoming(buffer::const_interval(buf, buf + bytes_transferred)
|
p.incoming(span<char const>(buf, bytes_transferred), error);
|
||||||
, error);
|
|
||||||
|
|
||||||
if (!p.header_finished() || error)
|
if (!p.header_finished() || error)
|
||||||
{
|
{
|
||||||
|
|
|
@ -51,7 +51,7 @@ boost::asio::mutable_buffer receive_buffer::reserve(int size)
|
||||||
{
|
{
|
||||||
int const new_size = std::max(m_recv_end + size, m_packet_size);
|
int const new_size = std::max(m_recv_end + size, m_packet_size);
|
||||||
buffer new_buffer(new_size
|
buffer new_buffer(new_size
|
||||||
, span<char const>(m_recv_buffer.ptr(), m_recv_end));
|
, span<char const>(m_recv_buffer.data(), m_recv_end));
|
||||||
m_recv_buffer = std::move(new_buffer);
|
m_recv_buffer = std::move(new_buffer);
|
||||||
|
|
||||||
// since we just increased the size of the buffer, reset the watermark to
|
// since we just increased the size of the buffer, reset the watermark to
|
||||||
|
@ -73,7 +73,7 @@ void receive_buffer::grow(int const limit)
|
||||||
|
|
||||||
// re-allcoate the buffer and copy over the part of it that's used
|
// re-allcoate the buffer and copy over the part of it that's used
|
||||||
buffer new_buffer(new_size
|
buffer new_buffer(new_size
|
||||||
, span<char const>(m_recv_buffer.ptr(), m_recv_end));
|
, span<char const>(m_recv_buffer.data(), m_recv_end));
|
||||||
m_recv_buffer = std::move(new_buffer);
|
m_recv_buffer = std::move(new_buffer);
|
||||||
|
|
||||||
// since we just increased the size of the buffer, reset the watermark to
|
// since we just increased the size of the buffer, reset the watermark to
|
||||||
|
@ -186,12 +186,12 @@ void receive_buffer::normalize(int force_shrink)
|
||||||
&& m_watermark.mean() > (m_recv_end - m_recv_start);
|
&& m_watermark.mean() > (m_recv_end - m_recv_start);
|
||||||
|
|
||||||
span<char const> bytes_to_shift(
|
span<char const> bytes_to_shift(
|
||||||
m_recv_buffer.ptr() + m_recv_start
|
m_recv_buffer.data() + m_recv_start
|
||||||
, m_recv_end - m_recv_start);
|
, m_recv_end - m_recv_start);
|
||||||
|
|
||||||
if (force_shrink)
|
if (force_shrink)
|
||||||
{
|
{
|
||||||
const int target_size = std::max(std::max(force_shrink
|
int const target_size = std::max(std::max(force_shrink
|
||||||
, int(bytes_to_shift.size())), m_packet_size);
|
, int(bytes_to_shift.size())), m_packet_size);
|
||||||
buffer new_buffer(target_size, bytes_to_shift);
|
buffer new_buffer(target_size, bytes_to_shift);
|
||||||
m_recv_buffer = std::move(new_buffer);
|
m_recv_buffer = std::move(new_buffer);
|
||||||
|
@ -204,7 +204,7 @@ void receive_buffer::normalize(int force_shrink)
|
||||||
else if (m_recv_end > m_recv_start
|
else if (m_recv_end > m_recv_start
|
||||||
&& m_recv_start > 0)
|
&& m_recv_start > 0)
|
||||||
{
|
{
|
||||||
std::memmove(m_recv_buffer.ptr(), bytes_to_shift.data()
|
std::memmove(m_recv_buffer.data(), bytes_to_shift.data()
|
||||||
, bytes_to_shift.size());
|
, bytes_to_shift.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -460,7 +460,7 @@ namespace libtorrent
|
||||||
restart_read_timeout();
|
restart_read_timeout();
|
||||||
|
|
||||||
// skip header
|
// skip header
|
||||||
buf = buf.cut_first(8);
|
buf = buf.subspan(8);
|
||||||
|
|
||||||
// reset transaction
|
// reset transaction
|
||||||
update_transaction_id();
|
update_transaction_id();
|
||||||
|
@ -592,7 +592,7 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
if (buf.size() < 20) return false;
|
if (buf.size() < 20) return false;
|
||||||
|
|
||||||
buf = buf.cut_first(8);
|
buf = buf.subspan(8);
|
||||||
restart_read_timeout();
|
restart_read_timeout();
|
||||||
|
|
||||||
tracker_response resp;
|
tracker_response resp;
|
||||||
|
@ -628,7 +628,7 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
ipv4_peer_entry e;
|
ipv4_peer_entry e;
|
||||||
memcpy(&e.ip[0], buf.data(), 4);
|
memcpy(&e.ip[0], buf.data(), 4);
|
||||||
buf = buf.cut_first(4);
|
buf = buf.subspan(4);
|
||||||
e.port = aux::read_uint16(buf);
|
e.port = aux::read_uint16(buf);
|
||||||
resp.peers4.push_back(e);
|
resp.peers4.push_back(e);
|
||||||
}
|
}
|
||||||
|
@ -719,9 +719,9 @@ namespace libtorrent
|
||||||
aux::write_int32(action_announce, out); // action (announce)
|
aux::write_int32(action_announce, out); // action (announce)
|
||||||
aux::write_int32(m_transaction_id, out); // transaction_id
|
aux::write_int32(m_transaction_id, out); // transaction_id
|
||||||
std::copy(req.info_hash.begin(), req.info_hash.end(), out.data()); // info_hash
|
std::copy(req.info_hash.begin(), req.info_hash.end(), out.data()); // info_hash
|
||||||
out.cut_first(20);
|
out.subspan(20);
|
||||||
std::copy(req.pid.begin(), req.pid.end(), out.data()); // peer_id
|
std::copy(req.pid.begin(), req.pid.end(), out.data()); // peer_id
|
||||||
out.cut_first(20);
|
out.subspan(20);
|
||||||
aux::write_int64(stats ? req.downloaded : 0, out); // downloaded
|
aux::write_int64(stats ? req.downloaded : 0, out); // downloaded
|
||||||
aux::write_int64(stats ? req.left : 0, out); // left
|
aux::write_int64(stats ? req.left : 0, out); // left
|
||||||
aux::write_int64(stats ? req.uploaded : 0, out); // uploaded
|
aux::write_int64(stats ? req.uploaded : 0, out); // uploaded
|
||||||
|
|
|
@ -435,8 +435,7 @@ void upnp::on_reply(udp::endpoint const& from, char* buffer
|
||||||
|
|
||||||
http_parser p;
|
http_parser p;
|
||||||
bool error = false;
|
bool error = false;
|
||||||
p.incoming(buffer::const_interval(buffer
|
p.incoming(span<char const>(buffer, bytes_transferred), error);
|
||||||
, buffer + bytes_transferred), error);
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
#ifndef TORRENT_DISABLE_LOGGING
|
||||||
|
|
|
@ -655,7 +655,7 @@ void web_peer_connection::on_receive(error_code const& error
|
||||||
|
|
||||||
// in case the first file on this series of requests is a padfile
|
// in case the first file on this series of requests is a padfile
|
||||||
// we need to handle it right now
|
// we need to handle it right now
|
||||||
buffer::const_interval recv_buffer = m_recv_buffer.get();
|
span<char const> recv_buffer(m_recv_buffer.get().begin, m_recv_buffer.get().left());
|
||||||
handle_padfile();
|
handle_padfile();
|
||||||
if (associated_torrent().expired()) return;
|
if (associated_torrent().expired()) return;
|
||||||
|
|
||||||
|
@ -669,21 +669,21 @@ void web_peer_connection::on_receive(error_code const& error
|
||||||
bool failed = false;
|
bool failed = false;
|
||||||
std::tie(payload, protocol) = m_parser.incoming(recv_buffer, failed);
|
std::tie(payload, protocol) = m_parser.incoming(recv_buffer, failed);
|
||||||
received_bytes(0, protocol);
|
received_bytes(0, protocol);
|
||||||
TORRENT_ASSERT(int(recv_buffer.left()) >= protocol);
|
TORRENT_ASSERT(int(recv_buffer.size()) >= protocol);
|
||||||
|
|
||||||
if (failed)
|
if (failed)
|
||||||
{
|
{
|
||||||
received_bytes(0, recv_buffer.left());
|
received_bytes(0, int(recv_buffer.size()));
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
#ifndef TORRENT_DISABLE_LOGGING
|
||||||
peer_log(peer_log_alert::info, "RECEIVE_BYTES"
|
peer_log(peer_log_alert::info, "RECEIVE_BYTES"
|
||||||
, "%s", std::string(recv_buffer.begin, recv_buffer.end).c_str());
|
, "%s", std::string(recv_buffer.data(), recv_buffer.size()).c_str());
|
||||||
#endif
|
#endif
|
||||||
disconnect(errors::http_parse_error, op_bittorrent, 2);
|
disconnect(errors::http_parse_error, op_bittorrent, 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TORRENT_ASSERT(recv_buffer.left() == 0 || *recv_buffer.begin == 'H');
|
TORRENT_ASSERT(recv_buffer.empty() || recv_buffer[0] == 'H');
|
||||||
TORRENT_ASSERT(recv_buffer.left() <= m_recv_buffer.packet_size());
|
TORRENT_ASSERT(recv_buffer.size() <= m_recv_buffer.packet_size());
|
||||||
|
|
||||||
// this means the entire status line hasn't been received yet
|
// this means the entire status line hasn't been received yet
|
||||||
if (m_parser.status_code() == -1)
|
if (m_parser.status_code() == -1)
|
||||||
|
@ -726,26 +726,26 @@ void web_peer_connection::on_receive(error_code const& error
|
||||||
// if the status code is not one of the accepted ones, abort
|
// if the status code is not one of the accepted ones, abort
|
||||||
if (!is_ok_status(m_parser.status_code()))
|
if (!is_ok_status(m_parser.status_code()))
|
||||||
{
|
{
|
||||||
handle_error(recv_buffer.left());
|
handle_error(int(recv_buffer.size()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_redirect(m_parser.status_code()))
|
if (is_redirect(m_parser.status_code()))
|
||||||
{
|
{
|
||||||
handle_redirect(recv_buffer.left());
|
handle_redirect(int(recv_buffer.size()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_server_string = get_peer_name(m_parser, m_host);
|
m_server_string = get_peer_name(m_parser, m_host);
|
||||||
|
|
||||||
recv_buffer.begin += m_body_start;
|
recv_buffer = recv_buffer.subspan(m_body_start);
|
||||||
|
|
||||||
m_body_start = m_parser.body_start();
|
m_body_start = m_parser.body_start();
|
||||||
m_received_body = 0;
|
m_received_body = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// we only received the header, no data
|
// we only received the header, no data
|
||||||
if (recv_buffer.left() == 0) break;
|
if (recv_buffer.size() == 0) break;
|
||||||
|
|
||||||
// ===================================
|
// ===================================
|
||||||
// ======= RESPONSE BYTE RANGE =======
|
// ======= RESPONSE BYTE RANGE =======
|
||||||
|
@ -760,7 +760,7 @@ void web_peer_connection::on_receive(error_code const& error
|
||||||
std::tie(range_start, range_end) = get_range(m_parser, ec);
|
std::tie(range_start, range_end) = get_range(m_parser, ec);
|
||||||
if (ec)
|
if (ec)
|
||||||
{
|
{
|
||||||
received_bytes(0, recv_buffer.left());
|
received_bytes(0, int(recv_buffer.size()));
|
||||||
// we should not try this server again.
|
// we should not try this server again.
|
||||||
t->remove_web_seed_conn(this, ec, op_bittorrent, 2);
|
t->remove_web_seed_conn(this, ec, op_bittorrent, 2);
|
||||||
m_web = nullptr;
|
m_web = nullptr;
|
||||||
|
@ -774,7 +774,7 @@ void web_peer_connection::on_receive(error_code const& error
|
||||||
|| range_end != file_req.start + file_req.length)
|
|| range_end != file_req.start + file_req.length)
|
||||||
{
|
{
|
||||||
// the byte range in the http response is different what we expected
|
// the byte range in the http response is different what we expected
|
||||||
received_bytes(0, recv_buffer.left());
|
received_bytes(0, int(recv_buffer.size()));
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
#ifndef TORRENT_DISABLE_LOGGING
|
||||||
peer_log(peer_log_alert::incoming, "INVALID HTTP RESPONSE"
|
peer_log(peer_log_alert::incoming, "INVALID HTTP RESPONSE"
|
||||||
|
@ -793,19 +793,19 @@ void web_peer_connection::on_receive(error_code const& error
|
||||||
// === CHUNKED ENCODING ===
|
// === CHUNKED ENCODING ===
|
||||||
// =========================
|
// =========================
|
||||||
|
|
||||||
while (m_chunk_pos >= 0 && recv_buffer.left() > 0)
|
while (m_chunk_pos >= 0 && recv_buffer.size() > 0)
|
||||||
{
|
{
|
||||||
// first deliver any payload we have in the buffer so far, ahead of
|
// first deliver any payload we have in the buffer so far, ahead of
|
||||||
// the next chunk header.
|
// the next chunk header.
|
||||||
if (m_chunk_pos > 0)
|
if (m_chunk_pos > 0)
|
||||||
{
|
{
|
||||||
int const copy_size = (std::min)(m_chunk_pos, recv_buffer.left());
|
int const copy_size = (std::min)(m_chunk_pos, int(recv_buffer.size()));
|
||||||
TORRENT_ASSERT(copy_size > 0);
|
TORRENT_ASSERT(copy_size > 0);
|
||||||
|
|
||||||
if (m_received_body + copy_size > file_req.length)
|
if (m_received_body + copy_size > file_req.length)
|
||||||
{
|
{
|
||||||
// the byte range in the http response is different what we expected
|
// the byte range in the http response is different what we expected
|
||||||
received_bytes(0, recv_buffer.left());
|
received_bytes(0, int(recv_buffer.size()));
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
#ifndef TORRENT_DISABLE_LOGGING
|
||||||
peer_log(peer_log_alert::incoming, "INVALID HTTP RESPONSE"
|
peer_log(peer_log_alert::incoming, "INVALID HTTP RESPONSE"
|
||||||
|
@ -815,27 +815,26 @@ void web_peer_connection::on_receive(error_code const& error
|
||||||
disconnect(errors::invalid_range, op_bittorrent, 2);
|
disconnect(errors::invalid_range, op_bittorrent, 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
incoming_payload(recv_buffer.begin, copy_size);
|
incoming_payload(recv_buffer.data(), copy_size);
|
||||||
|
|
||||||
recv_buffer.begin += copy_size;
|
recv_buffer = recv_buffer.subspan(copy_size);
|
||||||
m_chunk_pos -= copy_size;
|
m_chunk_pos -= copy_size;
|
||||||
|
|
||||||
if (recv_buffer.left() == 0) goto done;
|
if (recv_buffer.size() == 0) goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
TORRENT_ASSERT(m_chunk_pos == 0);
|
TORRENT_ASSERT(m_chunk_pos == 0);
|
||||||
|
|
||||||
int header_size = 0;
|
int header_size = 0;
|
||||||
std::int64_t chunk_size = 0;
|
std::int64_t chunk_size = 0;
|
||||||
buffer::const_interval chunk_start = recv_buffer;
|
span<char const> chunk_start = recv_buffer.subspan(m_chunk_pos);
|
||||||
chunk_start.begin += m_chunk_pos;
|
TORRENT_ASSERT(chunk_start[0] == '\r'
|
||||||
TORRENT_ASSERT(chunk_start.begin[0] == '\r'
|
|| aux::is_hex(chunk_start.data(), 1));
|
||||||
|| aux::is_hex(chunk_start.begin, 1));
|
bool const ret = m_parser.parse_chunk_header(chunk_start, &chunk_size, &header_size);
|
||||||
bool ret = m_parser.parse_chunk_header(chunk_start, &chunk_size, &header_size);
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
{
|
{
|
||||||
received_bytes(0, chunk_start.left() - m_partial_chunk_header);
|
received_bytes(0, int(chunk_start.size() - m_partial_chunk_header));
|
||||||
m_partial_chunk_header = chunk_start.left();
|
m_partial_chunk_header = int(chunk_start.size());
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
#ifndef TORRENT_DISABLE_LOGGING
|
||||||
|
@ -846,10 +845,10 @@ void web_peer_connection::on_receive(error_code const& error
|
||||||
received_bytes(0, header_size - m_partial_chunk_header);
|
received_bytes(0, header_size - m_partial_chunk_header);
|
||||||
m_partial_chunk_header = 0;
|
m_partial_chunk_header = 0;
|
||||||
TORRENT_ASSERT(chunk_size != 0
|
TORRENT_ASSERT(chunk_size != 0
|
||||||
|| chunk_start.left() <= header_size || chunk_start.begin[header_size] == 'H');
|
|| chunk_start.size() <= header_size || chunk_start[header_size] == 'H');
|
||||||
TORRENT_ASSERT(m_body_start + m_chunk_pos < INT_MAX);
|
TORRENT_ASSERT(m_body_start + m_chunk_pos < INT_MAX);
|
||||||
m_chunk_pos += chunk_size;
|
m_chunk_pos += chunk_size;
|
||||||
recv_buffer.begin += header_size;
|
recv_buffer = recv_buffer.subspan(header_size);
|
||||||
|
|
||||||
// a chunk size of zero means the request is complete. Make sure the
|
// a chunk size of zero means the request is complete. Make sure the
|
||||||
// number of payload bytes we've received matches the number we
|
// number of payload bytes we've received matches the number we
|
||||||
|
@ -859,9 +858,8 @@ void web_peer_connection::on_receive(error_code const& error
|
||||||
TORRENT_ASSERT_VAL(m_chunk_pos == 0, m_chunk_pos);
|
TORRENT_ASSERT_VAL(m_chunk_pos == 0, m_chunk_pos);
|
||||||
|
|
||||||
#if TORRENT_USE_ASSERTS
|
#if TORRENT_USE_ASSERTS
|
||||||
buffer::const_interval chunk = recv_buffer;
|
span<char const> chunk = recv_buffer.subspan(m_chunk_pos);
|
||||||
chunk.begin += m_chunk_pos;
|
TORRENT_ASSERT(chunk.size() == 0 || chunk[0] == 'H');
|
||||||
TORRENT_ASSERT(chunk.left() == 0 || chunk.begin[0] == 'H');
|
|
||||||
#endif
|
#endif
|
||||||
m_chunk_pos = -1;
|
m_chunk_pos = -1;
|
||||||
|
|
||||||
|
@ -869,7 +867,7 @@ void web_peer_connection::on_receive(error_code const& error
|
||||||
if (m_received_body != file_req.length)
|
if (m_received_body != file_req.length)
|
||||||
{
|
{
|
||||||
// the byte range in the http response is different what we expected
|
// the byte range in the http response is different what we expected
|
||||||
received_bytes(0, recv_buffer.left());
|
received_bytes(0, int(recv_buffer.size()));
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
#ifndef TORRENT_DISABLE_LOGGING
|
||||||
peer_log(peer_log_alert::incoming, "INVALID HTTP RESPONSE"
|
peer_log(peer_log_alert::incoming, "INVALID HTTP RESPONSE"
|
||||||
|
@ -895,7 +893,7 @@ void web_peer_connection::on_receive(error_code const& error
|
||||||
|
|
||||||
// if all of the receive buffer was just consumed as chunk
|
// if all of the receive buffer was just consumed as chunk
|
||||||
// header, we're done
|
// header, we're done
|
||||||
if (recv_buffer.left() == 0) goto done;
|
if (recv_buffer.size() == 0) goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -903,9 +901,9 @@ void web_peer_connection::on_receive(error_code const& error
|
||||||
// this is the simple case, where we don't have chunked encoding
|
// this is the simple case, where we don't have chunked encoding
|
||||||
TORRENT_ASSERT(m_received_body <= file_req.length);
|
TORRENT_ASSERT(m_received_body <= file_req.length);
|
||||||
int const copy_size = (std::min)(file_req.length - m_received_body
|
int const copy_size = (std::min)(file_req.length - m_received_body
|
||||||
, recv_buffer.left());
|
, int(recv_buffer.size()));
|
||||||
incoming_payload(recv_buffer.begin, copy_size);
|
incoming_payload(recv_buffer.data(), copy_size);
|
||||||
recv_buffer.begin += copy_size;
|
recv_buffer = recv_buffer.subspan(copy_size);
|
||||||
|
|
||||||
TORRENT_ASSERT(m_received_body <= file_req.length);
|
TORRENT_ASSERT(m_received_body <= file_req.length);
|
||||||
if (m_received_body == file_req.length)
|
if (m_received_body == file_req.length)
|
||||||
|
@ -924,12 +922,12 @@ void web_peer_connection::on_receive(error_code const& error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (recv_buffer.left() == 0) break;
|
if (recv_buffer.size() == 0) break;
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
|
|
||||||
// now, remove all the bytes we've processed from the receive buffer
|
// now, remove all the bytes we've processed from the receive buffer
|
||||||
m_recv_buffer.cut(recv_buffer.begin - m_recv_buffer.get().begin
|
m_recv_buffer.cut(recv_buffer.data() - m_recv_buffer.get().begin
|
||||||
, t->block_size() + request_size_overhead);
|
, t->block_size() + request_size_overhead);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ TORRENT_TEST(buffer_constructor)
|
||||||
|
|
||||||
{
|
{
|
||||||
buffer b(50, data);
|
buffer b(50, data);
|
||||||
TEST_CHECK(std::memcmp(b.ptr(), data, 10) == 0);
|
TEST_CHECK(std::memcmp(b.data(), data, 10) == 0);
|
||||||
TEST_CHECK(b.size() >= 50);
|
TEST_CHECK(b.size() >= 50);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,13 +80,13 @@ TORRENT_TEST(buffer_swap)
|
||||||
|
|
||||||
TEST_CHECK(b2.size() == 0);
|
TEST_CHECK(b2.size() == 0);
|
||||||
TEST_CHECK(b1.size() == b2_size);
|
TEST_CHECK(b1.size() == b2_size);
|
||||||
TEST_CHECK(std::memcmp(b1.ptr(), data, 10) == 0);
|
TEST_CHECK(std::memcmp(b1.data(), data, 10) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
TORRENT_TEST(buffer_subscript)
|
TORRENT_TEST(buffer_subscript)
|
||||||
{
|
{
|
||||||
buffer b(50, data);
|
buffer b(50, data);
|
||||||
TEST_CHECK(std::memcmp(b.ptr(), data, 10) == 0);
|
TEST_CHECK(std::memcmp(b.data(), data, 10) == 0);
|
||||||
TEST_CHECK(b.size() >= 50);
|
TEST_CHECK(b.size() >= 50);
|
||||||
|
|
||||||
for (int i = 0; i < int(sizeof(data)/sizeof(data[0])); ++i)
|
for (int i = 0; i < int(sizeof(data)/sizeof(data[0])); ++i)
|
||||||
|
@ -108,21 +108,21 @@ TORRENT_TEST(buffer_subscript2)
|
||||||
TORRENT_TEST(buffer_move_construct)
|
TORRENT_TEST(buffer_move_construct)
|
||||||
{
|
{
|
||||||
buffer b1(50, data);
|
buffer b1(50, data);
|
||||||
TEST_CHECK(std::memcmp(b1.ptr(), data, 10) == 0);
|
TEST_CHECK(std::memcmp(b1.data(), data, 10) == 0);
|
||||||
TEST_CHECK(b1.size() >= 50);
|
TEST_CHECK(b1.size() >= 50);
|
||||||
|
|
||||||
buffer b2(std::move(b1));
|
buffer b2(std::move(b1));
|
||||||
|
|
||||||
TEST_CHECK(b1.size() == 0);
|
TEST_CHECK(b1.size() == 0);
|
||||||
|
|
||||||
TEST_CHECK(std::memcmp(b2.ptr(), data, 10) == 0);
|
TEST_CHECK(std::memcmp(b2.data(), data, 10) == 0);
|
||||||
TEST_CHECK(b2.size() >= 50);
|
TEST_CHECK(b2.size() >= 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
TORRENT_TEST(buffer_move_assign)
|
TORRENT_TEST(buffer_move_assign)
|
||||||
{
|
{
|
||||||
buffer b1(50, data);
|
buffer b1(50, data);
|
||||||
TEST_CHECK(std::memcmp(b1.ptr(), data, 10) == 0);
|
TEST_CHECK(std::memcmp(b1.data(), data, 10) == 0);
|
||||||
TEST_CHECK(b1.size() >= 50);
|
TEST_CHECK(b1.size() >= 50);
|
||||||
|
|
||||||
buffer b2;
|
buffer b2;
|
||||||
|
@ -132,7 +132,7 @@ TORRENT_TEST(buffer_move_assign)
|
||||||
|
|
||||||
TEST_CHECK(b1.size() == 0);
|
TEST_CHECK(b1.size() == 0);
|
||||||
|
|
||||||
TEST_CHECK(std::memcmp(b2.ptr(), data, 10) == 0);
|
TEST_CHECK(std::memcmp(b2.data(), data, 10) == 0);
|
||||||
TEST_CHECK(b2.size() >= 50);
|
TEST_CHECK(b2.size() >= 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
using namespace libtorrent;
|
using namespace libtorrent;
|
||||||
|
|
||||||
|
// TODO: 3 use span here instead of zero-terminated string
|
||||||
std::tuple<int, int, bool> feed_bytes(http_parser& parser, char const* str)
|
std::tuple<int, int, bool> feed_bytes(http_parser& parser, char const* str)
|
||||||
{
|
{
|
||||||
std::tuple<int, int, bool> ret(0, 0, false);
|
std::tuple<int, int, bool> ret(0, 0, false);
|
||||||
|
@ -46,12 +47,12 @@ std::tuple<int, int, bool> feed_bytes(http_parser& parser, char const* str)
|
||||||
{
|
{
|
||||||
ret = std::make_tuple(0, 0, false);
|
ret = std::make_tuple(0, 0, false);
|
||||||
parser.reset();
|
parser.reset();
|
||||||
buffer::const_interval recv_buf(str, str);
|
span<char const> recv_buf(str, 0);
|
||||||
for (; *str;)
|
for (;;)
|
||||||
{
|
{
|
||||||
int chunk_size = (std::min)(chunks, int(strlen(recv_buf.end)));
|
int chunk_size = (std::min)(chunks, int(strlen(recv_buf.end())));
|
||||||
if (chunk_size == 0) break;
|
if (chunk_size == 0) break;
|
||||||
recv_buf.end += chunk_size;
|
recv_buf = span<char const>(recv_buf.data(), recv_buf.size() + chunk_size);
|
||||||
int payload, protocol;
|
int payload, protocol;
|
||||||
bool error = false;
|
bool error = false;
|
||||||
std::tie(payload, protocol) = parser.incoming(recv_buf, error);
|
std::tie(payload, protocol) = parser.incoming(recv_buf, error);
|
||||||
|
@ -332,10 +333,10 @@ TORRENT_TEST(http_parser)
|
||||||
char const chunk_header1[] = "f;this is a comment\r\n";
|
char const chunk_header1[] = "f;this is a comment\r\n";
|
||||||
std::int64_t chunk_size;
|
std::int64_t chunk_size;
|
||||||
int header_size;
|
int header_size;
|
||||||
bool ret = parser.parse_chunk_header(buffer::const_interval(chunk_header1, chunk_header1 + 10)
|
bool ret = parser.parse_chunk_header(span<char const>(chunk_header1, 10)
|
||||||
, &chunk_size, &header_size);
|
, &chunk_size, &header_size);
|
||||||
TEST_EQUAL(ret, false);
|
TEST_EQUAL(ret, false);
|
||||||
ret = parser.parse_chunk_header(buffer::const_interval(chunk_header1, chunk_header1 + sizeof(chunk_header1))
|
ret = parser.parse_chunk_header(span<char const>(chunk_header1, sizeof(chunk_header1))
|
||||||
, &chunk_size, &header_size);
|
, &chunk_size, &header_size);
|
||||||
TEST_EQUAL(ret, true);
|
TEST_EQUAL(ret, true);
|
||||||
TEST_EQUAL(chunk_size, 15);
|
TEST_EQUAL(chunk_size, 15);
|
||||||
|
@ -347,7 +348,7 @@ TORRENT_TEST(http_parser)
|
||||||
"test2: bar\r\n"
|
"test2: bar\r\n"
|
||||||
"\r\n";
|
"\r\n";
|
||||||
|
|
||||||
ret = parser.parse_chunk_header(buffer::const_interval(chunk_header2, chunk_header2 + sizeof(chunk_header2))
|
ret = parser.parse_chunk_header(span<char const>(chunk_header2, sizeof(chunk_header2))
|
||||||
, &chunk_size, &header_size);
|
, &chunk_size, &header_size);
|
||||||
TEST_EQUAL(ret, true);
|
TEST_EQUAL(ret, true);
|
||||||
TEST_EQUAL(chunk_size, 0);
|
TEST_EQUAL(chunk_size, 0);
|
||||||
|
|
|
@ -73,7 +73,7 @@ void incoming_msearch(udp::endpoint const& from, char* buffer
|
||||||
{
|
{
|
||||||
http_parser p;
|
http_parser p;
|
||||||
bool error = false;
|
bool error = false;
|
||||||
p.incoming(buffer::const_interval(buffer, buffer + size), error);
|
p.incoming(span<char const>(buffer, size), error);
|
||||||
if (error || !p.header_finished())
|
if (error || !p.header_finished())
|
||||||
{
|
{
|
||||||
std::cerr << "*** malformed HTTP from "
|
std::cerr << "*** malformed HTTP from "
|
||||||
|
|
Loading…
Reference in New Issue