forked from premiere/premiere-libtorrent
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 |= static_cast<std::uint8_t>(view[i]);
|
||||
}
|
||||
view = view.cut_first(sizeof(T));
|
||||
view = view.subspan(sizeof(T));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,7 @@ namespace libtorrent { namespace aux
|
|||
shift -= 8;
|
||||
view[i] = static_cast<unsigned char>((val >> shift) & 0xff);
|
||||
}
|
||||
view = view.cut_first(sizeof(T));
|
||||
view = view.subspan(sizeof(T));
|
||||
}
|
||||
|
||||
// -- adaptors
|
||||
|
|
|
@ -75,6 +75,7 @@ class buffer
|
|||
{
|
||||
public:
|
||||
|
||||
// TODO: 3 remove interval and const_interval
|
||||
struct interval
|
||||
{
|
||||
interval()
|
||||
|
@ -208,20 +209,8 @@ public:
|
|||
|
||||
~buffer() { std::free(m_begin); }
|
||||
|
||||
// TODO: 3 fix the naming convention here
|
||||
char* ptr() { 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)); }
|
||||
|
||||
char* data() { return m_begin; }
|
||||
char const* data() const { return m_begin; }
|
||||
std::size_t size() const { return m_size; }
|
||||
|
||||
bool empty() const { return m_size == 0; }
|
||||
|
@ -239,6 +228,7 @@ public:
|
|||
swap(m_begin, b.m_begin);
|
||||
swap(m_size, b.m_size);
|
||||
}
|
||||
|
||||
private:
|
||||
char* m_begin = nullptr;
|
||||
// m_begin points to an allocation of this size.
|
||||
|
|
|
@ -77,7 +77,7 @@ namespace libtorrent
|
|||
buffer::const_interval get_body() const;
|
||||
bool header_finished() const { return m_state == read_body; }
|
||||
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);
|
||||
int body_start() const { return m_body_start_pos; }
|
||||
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
|
||||
// size may still have been modified, but their values are
|
||||
// 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);
|
||||
|
||||
// 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; }
|
||||
|
||||
private:
|
||||
std::int64_t m_recv_pos;
|
||||
std::int64_t m_recv_pos = 0;
|
||||
std::string m_method;
|
||||
std::string m_path;
|
||||
std::string m_protocol;
|
||||
std::string m_server_message;
|
||||
|
||||
std::int64_t m_content_length;
|
||||
std::int64_t m_range_start;
|
||||
std::int64_t m_range_end;
|
||||
std::int64_t m_content_length = -1;
|
||||
std::int64_t m_range_start = -1;
|
||||
std::int64_t m_range_end = -1;
|
||||
|
||||
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
|
||||
// each chunked range in the response
|
||||
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
|
||||
// current chunk will end (it refers to the first character
|
||||
// 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
|
||||
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
|
||||
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
|
||||
// if it sent "connection: close"
|
||||
bool m_connection_close;
|
||||
bool m_chunked_encoding;
|
||||
bool m_finished;
|
||||
bool m_connection_close = false;
|
||||
bool m_chunked_encoding = false;
|
||||
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.
|
||||
// This is the "current" packet.
|
||||
// TODO: 3 use span
|
||||
buffer::const_interval get() const;
|
||||
|
||||
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||
|
@ -198,6 +199,7 @@ struct crypto_receive_buffer
|
|||
|
||||
int advance_pos(int bytes);
|
||||
|
||||
// TODO: 3 use span
|
||||
buffer::const_interval get() const;
|
||||
|
||||
aux::mutable_buffer mutable_buffer(std::size_t bytes);
|
||||
|
|
|
@ -92,10 +92,17 @@ namespace libtorrent
|
|||
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);
|
||||
return { data() + n, int(size()) - n };
|
||||
TORRENT_ASSERT(size() >= offset);
|
||||
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)
|
||||
|
|
|
@ -743,10 +743,9 @@ void http_connection::on_read(error_code const& e
|
|||
|
||||
if (m_bottled || !m_parser.header_finished())
|
||||
{
|
||||
libtorrent::buffer::const_interval rcv_buf(&m_recvbuffer[0]
|
||||
, &m_recvbuffer[0] + m_read_pos);
|
||||
span<char const> rcv_buf(m_recvbuffer);
|
||||
bool error = false;
|
||||
m_parser.incoming(rcv_buf, error);
|
||||
m_parser.incoming(rcv_buf.subspan(0, m_read_pos), error);
|
||||
if (error)
|
||||
{
|
||||
// HTTP parse error
|
||||
|
|
|
@ -132,33 +132,17 @@ namespace libtorrent
|
|||
|
||||
http_parser::~http_parser() = default;
|
||||
|
||||
http_parser::http_parser(int 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)
|
||||
{}
|
||||
http_parser::http_parser(int const flags) : m_flags(flags) {}
|
||||
|
||||
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);
|
||||
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
|
||||
if (start_pos == recv_buffer.left()) return ret;
|
||||
if (start_pos == recv_buffer.size()) return ret;
|
||||
m_recv_buffer = recv_buffer;
|
||||
|
||||
if (m_state == error_state)
|
||||
|
@ -167,19 +151,19 @@ namespace libtorrent
|
|||
return ret;
|
||||
}
|
||||
|
||||
char const* pos = recv_buffer.begin + m_recv_pos;
|
||||
char const* pos = recv_buffer.data() + m_recv_pos;
|
||||
|
||||
restart_response:
|
||||
|
||||
if (m_state == read_status)
|
||||
{
|
||||
TORRENT_ASSERT(!m_finished);
|
||||
TORRENT_ASSERT(pos <= recv_buffer.end);
|
||||
char const* newline = std::find(pos, recv_buffer.end, '\n');
|
||||
TORRENT_ASSERT(pos <= recv_buffer.end());
|
||||
char const* newline = std::find(pos, recv_buffer.end(), '\n');
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
@ -198,7 +182,7 @@ restart_response:
|
|||
TORRENT_ASSERT(newline >= pos);
|
||||
int incoming = int(newline - pos);
|
||||
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;
|
||||
|
||||
m_protocol = read_until(line, ' ', line_end);
|
||||
|
@ -223,17 +207,17 @@ restart_response:
|
|||
m_status_code = 0;
|
||||
}
|
||||
m_state = read_header;
|
||||
start_pos = pos - recv_buffer.begin;
|
||||
start_pos = pos - recv_buffer.data();
|
||||
}
|
||||
|
||||
if (m_state == read_header)
|
||||
{
|
||||
TORRENT_ASSERT(!m_finished);
|
||||
TORRENT_ASSERT(pos <= recv_buffer.end);
|
||||
char const* newline = std::find(pos, recv_buffer.end, '\n');
|
||||
TORRENT_ASSERT(pos <= recv_buffer.end());
|
||||
char const* newline = std::find(pos, recv_buffer.end(), '\n');
|
||||
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
|
||||
// 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());
|
||||
}
|
||||
|
||||
TORRENT_ASSERT(m_recv_pos <= recv_buffer.left());
|
||||
TORRENT_ASSERT(pos <= recv_buffer.end);
|
||||
newline = std::find(pos, recv_buffer.end, '\n');
|
||||
TORRENT_ASSERT(m_recv_pos <= recv_buffer.size());
|
||||
TORRENT_ASSERT(pos <= recv_buffer.end());
|
||||
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)
|
||||
{
|
||||
int incoming = recv_buffer.end - pos;
|
||||
int incoming = recv_buffer.end() - pos;
|
||||
|
||||
if (m_chunked_encoding && (m_flags & dont_parse_chunks) == 0)
|
||||
{
|
||||
|
@ -364,7 +348,8 @@ restart_response:
|
|||
std::get<0>(ret) += 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;
|
||||
int 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"
|
||||
// " incoming = %d\n m_recv_pos = %d\n m_cur_chunk_end = %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));
|
||||
}
|
||||
else
|
||||
|
@ -404,7 +389,7 @@ restart_response:
|
|||
// 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"
|
||||
// " 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_chunk_header_size += header_size;
|
||||
|
@ -445,23 +430,22 @@ restart_response:
|
|||
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)
|
||||
{
|
||||
TORRENT_ASSERT(buf.begin <= buf.end);
|
||||
char const* pos = buf.begin;
|
||||
char const* pos = buf.data();
|
||||
|
||||
// ignore one optional new-line. This is since each chunk
|
||||
// is terminated by a newline. we're likely to see one
|
||||
// before the actual header.
|
||||
|
||||
if (pos < buf.end && pos[0] == '\r') ++pos;
|
||||
if (pos < buf.end && pos[0] == '\n') ++pos;
|
||||
if (pos == buf.end) return false;
|
||||
if (pos < buf.end() && pos[0] == '\r') ++pos;
|
||||
if (pos < buf.end() && pos[0] == '\n') ++pos;
|
||||
if (pos == buf.end()) return false;
|
||||
|
||||
TORRENT_ASSERT(pos <= buf.end);
|
||||
char const* newline = std::find(pos, buf.end, '\n');
|
||||
if (newline == buf.end) return false;
|
||||
TORRENT_ASSERT(pos <= buf.end());
|
||||
char const* newline = std::find(pos, buf.end(), '\n');
|
||||
if (newline == buf.end()) return false;
|
||||
++newline;
|
||||
|
||||
// the chunk header is a single line, a hex length of the
|
||||
|
@ -476,19 +460,19 @@ restart_response:
|
|||
|
||||
if (*chunk_size != 0)
|
||||
{
|
||||
*header_size = newline - buf.begin;
|
||||
*header_size = newline - buf.data();
|
||||
// the newline alone is two bytes
|
||||
TORRENT_ASSERT(newline - buf.begin > 2);
|
||||
TORRENT_ASSERT(newline - buf.data() > 2);
|
||||
return true;
|
||||
}
|
||||
|
||||
// this is the terminator of the stream. Also read headers
|
||||
std::map<std::string, std::string> tail_headers;
|
||||
pos = newline;
|
||||
newline = std::find(pos, buf.end, '\n');
|
||||
newline = std::find(pos, buf.end(), '\n');
|
||||
|
||||
std::string line;
|
||||
while (newline != buf.end)
|
||||
while (newline != buf.end())
|
||||
{
|
||||
// if the LF character is preceeded by a CR
|
||||
// charachter, don't copy it into the line string.
|
||||
|
@ -504,10 +488,10 @@ restart_response:
|
|||
// this means we got a blank line,
|
||||
// the header is finished and the body
|
||||
// starts.
|
||||
*header_size = newline - buf.begin;
|
||||
*header_size = newline - buf.data();
|
||||
|
||||
// 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.
|
||||
// add them to the headers in the parser
|
||||
|
@ -529,7 +513,7 @@ restart_response:
|
|||
tail_headers.insert(std::make_pair(name, value));
|
||||
// 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;
|
||||
}
|
||||
|
@ -543,8 +527,9 @@ restart_response:
|
|||
? m_recv_pos : (std::min)(m_body_start_pos + m_content_length, m_recv_pos);
|
||||
|
||||
TORRENT_ASSERT(last_byte >= m_body_start_pos);
|
||||
return buffer::const_interval(m_recv_buffer.begin + m_body_start_pos
|
||||
, m_recv_buffer.begin + last_byte);
|
||||
return buffer::const_interval(m_recv_buffer.data()
|
||||
+ m_body_start_pos
|
||||
, m_recv_buffer.data() + last_byte);
|
||||
}
|
||||
|
||||
void http_parser::reset()
|
||||
|
@ -558,8 +543,7 @@ restart_response:
|
|||
m_range_end = -1;
|
||||
m_finished = false;
|
||||
m_state = read_status;
|
||||
m_recv_buffer.begin = nullptr;
|
||||
m_recv_buffer.end = nullptr;
|
||||
m_recv_buffer = span<char const>();
|
||||
m_header.clear();
|
||||
m_chunked_encoding = false;
|
||||
m_chunked_ranges.clear();
|
||||
|
|
|
@ -247,7 +247,8 @@ namespace libtorrent
|
|||
bool parse_error = false;
|
||||
int protocol = 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);
|
||||
bytes_transferred -= protocol;
|
||||
#if TORRENT_USE_ASSERTS
|
||||
|
@ -362,17 +363,16 @@ namespace libtorrent
|
|||
{
|
||||
int header_size = 0;
|
||||
std::int64_t chunk_size = 0;
|
||||
buffer::const_interval chunk_start = recv_buffer;
|
||||
chunk_start.begin += m_chunk_pos;
|
||||
TORRENT_ASSERT(chunk_start.begin[0] == '\r'
|
||||
|| aux::is_hex(chunk_start.begin, 1));
|
||||
span<char const> chunk_start(recv_buffer.begin + m_chunk_pos, recv_buffer.left() - m_chunk_pos);
|
||||
TORRENT_ASSERT(chunk_start[0] == '\r'
|
||||
|| aux::is_hex(chunk_start.data(), 1));
|
||||
bool ret = m_parser.parse_chunk_header(chunk_start, &chunk_size, &header_size);
|
||||
if (!ret)
|
||||
{
|
||||
TORRENT_ASSERT(bytes_transferred >= size_t(chunk_start.left() - m_partial_chunk_header));
|
||||
bytes_transferred -= chunk_start.left() - m_partial_chunk_header;
|
||||
received_bytes(0, chunk_start.left() - m_partial_chunk_header);
|
||||
m_partial_chunk_header = chunk_start.left();
|
||||
TORRENT_ASSERT(bytes_transferred >= size_t(chunk_start.size() - m_partial_chunk_header));
|
||||
bytes_transferred -= chunk_start.size() - m_partial_chunk_header;
|
||||
received_bytes(0, int(chunk_start.size() - m_partial_chunk_header));
|
||||
m_partial_chunk_header = int(chunk_start.size());
|
||||
if (bytes_transferred == 0) return;
|
||||
break;
|
||||
}
|
||||
|
@ -388,7 +388,7 @@ namespace libtorrent
|
|||
|
||||
received_bytes(0, header_size - m_partial_chunk_header);
|
||||
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
|
||||
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));
|
||||
|
|
|
@ -214,8 +214,7 @@ void lsd::on_announce(udp::endpoint const& from, char* buf
|
|||
http_parser p;
|
||||
|
||||
bool error = false;
|
||||
p.incoming(buffer::const_interval(buf, buf + bytes_transferred)
|
||||
, error);
|
||||
p.incoming(span<char const>(buf, bytes_transferred), 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);
|
||||
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);
|
||||
|
||||
// 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
|
||||
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);
|
||||
|
||||
// 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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
buffer new_buffer(target_size, bytes_to_shift);
|
||||
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
|
||||
&& 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());
|
||||
}
|
||||
|
||||
|
|
|
@ -460,7 +460,7 @@ namespace libtorrent
|
|||
restart_read_timeout();
|
||||
|
||||
// skip header
|
||||
buf = buf.cut_first(8);
|
||||
buf = buf.subspan(8);
|
||||
|
||||
// reset transaction
|
||||
update_transaction_id();
|
||||
|
@ -592,7 +592,7 @@ namespace libtorrent
|
|||
{
|
||||
if (buf.size() < 20) return false;
|
||||
|
||||
buf = buf.cut_first(8);
|
||||
buf = buf.subspan(8);
|
||||
restart_read_timeout();
|
||||
|
||||
tracker_response resp;
|
||||
|
@ -628,7 +628,7 @@ namespace libtorrent
|
|||
{
|
||||
ipv4_peer_entry e;
|
||||
memcpy(&e.ip[0], buf.data(), 4);
|
||||
buf = buf.cut_first(4);
|
||||
buf = buf.subspan(4);
|
||||
e.port = aux::read_uint16(buf);
|
||||
resp.peers4.push_back(e);
|
||||
}
|
||||
|
@ -719,9 +719,9 @@ namespace libtorrent
|
|||
aux::write_int32(action_announce, out); // action (announce)
|
||||
aux::write_int32(m_transaction_id, out); // transaction_id
|
||||
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
|
||||
out.cut_first(20);
|
||||
out.subspan(20);
|
||||
aux::write_int64(stats ? req.downloaded : 0, out); // downloaded
|
||||
aux::write_int64(stats ? req.left : 0, out); // left
|
||||
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;
|
||||
bool error = false;
|
||||
p.incoming(buffer::const_interval(buffer
|
||||
, buffer + bytes_transferred), error);
|
||||
p.incoming(span<char const>(buffer, bytes_transferred), error);
|
||||
if (error)
|
||||
{
|
||||
#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
|
||||
// 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();
|
||||
if (associated_torrent().expired()) return;
|
||||
|
||||
|
@ -669,21 +669,21 @@ void web_peer_connection::on_receive(error_code const& error
|
|||
bool failed = false;
|
||||
std::tie(payload, protocol) = m_parser.incoming(recv_buffer, failed);
|
||||
received_bytes(0, protocol);
|
||||
TORRENT_ASSERT(int(recv_buffer.left()) >= protocol);
|
||||
TORRENT_ASSERT(int(recv_buffer.size()) >= protocol);
|
||||
|
||||
if (failed)
|
||||
{
|
||||
received_bytes(0, recv_buffer.left());
|
||||
received_bytes(0, int(recv_buffer.size()));
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
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
|
||||
disconnect(errors::http_parse_error, op_bittorrent, 2);
|
||||
return;
|
||||
}
|
||||
|
||||
TORRENT_ASSERT(recv_buffer.left() == 0 || *recv_buffer.begin == 'H');
|
||||
TORRENT_ASSERT(recv_buffer.left() <= m_recv_buffer.packet_size());
|
||||
TORRENT_ASSERT(recv_buffer.empty() || recv_buffer[0] == 'H');
|
||||
TORRENT_ASSERT(recv_buffer.size() <= m_recv_buffer.packet_size());
|
||||
|
||||
// this means the entire status line hasn't been received yet
|
||||
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 (!is_ok_status(m_parser.status_code()))
|
||||
{
|
||||
handle_error(recv_buffer.left());
|
||||
handle_error(int(recv_buffer.size()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_redirect(m_parser.status_code()))
|
||||
{
|
||||
handle_redirect(recv_buffer.left());
|
||||
handle_redirect(int(recv_buffer.size()));
|
||||
return;
|
||||
}
|
||||
|
||||
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_received_body = 0;
|
||||
}
|
||||
|
||||
// we only received the header, no data
|
||||
if (recv_buffer.left() == 0) break;
|
||||
if (recv_buffer.size() == 0) break;
|
||||
|
||||
// ===================================
|
||||
// ======= 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);
|
||||
if (ec)
|
||||
{
|
||||
received_bytes(0, recv_buffer.left());
|
||||
received_bytes(0, int(recv_buffer.size()));
|
||||
// we should not try this server again.
|
||||
t->remove_web_seed_conn(this, ec, op_bittorrent, 2);
|
||||
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)
|
||||
{
|
||||
// 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
|
||||
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 ===
|
||||
// =========================
|
||||
|
||||
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
|
||||
// the next chunk header.
|
||||
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);
|
||||
|
||||
if (m_received_body + copy_size > file_req.length)
|
||||
{
|
||||
// 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
|
||||
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);
|
||||
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;
|
||||
|
||||
if (recv_buffer.left() == 0) goto done;
|
||||
if (recv_buffer.size() == 0) goto done;
|
||||
}
|
||||
|
||||
TORRENT_ASSERT(m_chunk_pos == 0);
|
||||
|
||||
int header_size = 0;
|
||||
std::int64_t chunk_size = 0;
|
||||
buffer::const_interval chunk_start = recv_buffer;
|
||||
chunk_start.begin += m_chunk_pos;
|
||||
TORRENT_ASSERT(chunk_start.begin[0] == '\r'
|
||||
|| aux::is_hex(chunk_start.begin, 1));
|
||||
bool ret = m_parser.parse_chunk_header(chunk_start, &chunk_size, &header_size);
|
||||
span<char const> chunk_start = recv_buffer.subspan(m_chunk_pos);
|
||||
TORRENT_ASSERT(chunk_start[0] == '\r'
|
||||
|| aux::is_hex(chunk_start.data(), 1));
|
||||
bool const ret = m_parser.parse_chunk_header(chunk_start, &chunk_size, &header_size);
|
||||
if (!ret)
|
||||
{
|
||||
received_bytes(0, chunk_start.left() - m_partial_chunk_header);
|
||||
m_partial_chunk_header = chunk_start.left();
|
||||
received_bytes(0, int(chunk_start.size() - m_partial_chunk_header));
|
||||
m_partial_chunk_header = int(chunk_start.size());
|
||||
goto done;
|
||||
}
|
||||
#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);
|
||||
m_partial_chunk_header = 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);
|
||||
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
|
||||
// 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);
|
||||
|
||||
#if TORRENT_USE_ASSERTS
|
||||
buffer::const_interval chunk = recv_buffer;
|
||||
chunk.begin += m_chunk_pos;
|
||||
TORRENT_ASSERT(chunk.left() == 0 || chunk.begin[0] == 'H');
|
||||
span<char const> chunk = recv_buffer.subspan(m_chunk_pos);
|
||||
TORRENT_ASSERT(chunk.size() == 0 || chunk[0] == 'H');
|
||||
#endif
|
||||
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)
|
||||
{
|
||||
// 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
|
||||
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
|
||||
// header, we're done
|
||||
if (recv_buffer.left() == 0) goto done;
|
||||
if (recv_buffer.size() == 0) goto done;
|
||||
}
|
||||
}
|
||||
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
|
||||
TORRENT_ASSERT(m_received_body <= file_req.length);
|
||||
int const copy_size = (std::min)(file_req.length - m_received_body
|
||||
, recv_buffer.left());
|
||||
incoming_payload(recv_buffer.begin, copy_size);
|
||||
recv_buffer.begin += copy_size;
|
||||
, int(recv_buffer.size()));
|
||||
incoming_payload(recv_buffer.data(), copy_size);
|
||||
recv_buffer = recv_buffer.subspan(copy_size);
|
||||
|
||||
TORRENT_ASSERT(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:
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ TORRENT_TEST(buffer_constructor)
|
|||
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -80,13 +80,13 @@ TORRENT_TEST(buffer_swap)
|
|||
|
||||
TEST_CHECK(b2.size() == 0);
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
buffer b2(std::move(b1));
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
TORRENT_TEST(buffer_move_assign)
|
||||
{
|
||||
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);
|
||||
|
||||
buffer b2;
|
||||
|
@ -132,7 +132,7 @@ TORRENT_TEST(buffer_move_assign)
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
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> 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);
|
||||
parser.reset();
|
||||
buffer::const_interval recv_buf(str, str);
|
||||
for (; *str;)
|
||||
span<char const> recv_buf(str, 0);
|
||||
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;
|
||||
recv_buf.end += chunk_size;
|
||||
recv_buf = span<char const>(recv_buf.data(), recv_buf.size() + chunk_size);
|
||||
int payload, protocol;
|
||||
bool error = false;
|
||||
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";
|
||||
std::int64_t chunk_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);
|
||||
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);
|
||||
TEST_EQUAL(ret, true);
|
||||
TEST_EQUAL(chunk_size, 15);
|
||||
|
@ -347,7 +348,7 @@ TORRENT_TEST(http_parser)
|
|||
"test2: bar\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);
|
||||
TEST_EQUAL(ret, true);
|
||||
TEST_EQUAL(chunk_size, 0);
|
||||
|
|
|
@ -73,7 +73,7 @@ void incoming_msearch(udp::endpoint const& from, char* buffer
|
|||
{
|
||||
http_parser p;
|
||||
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())
|
||||
{
|
||||
std::cerr << "*** malformed HTTP from "
|
||||
|
|
Loading…
Reference in New Issue