transition part of http_parser to use span (#936)

transition parts of http_parser to use span
This commit is contained in:
Arvid Norberg 2016-07-24 00:52:20 -07:00 committed by GitHub
parent ec30daeaa5
commit 4f803353cf
16 changed files with 152 additions and 173 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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());
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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