From 4f803353cf5843ce398cb5a121a6894a44f606d3 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Sun, 24 Jul 2016 00:52:20 -0700 Subject: [PATCH] transition part of http_parser to use span (#936) transition parts of http_parser to use span --- include/libtorrent/aux_/io.hpp | 4 +- include/libtorrent/buffer.hpp | 18 +---- include/libtorrent/http_parser.hpp | 32 ++++---- include/libtorrent/receive_buffer.hpp | 2 + include/libtorrent/span.hpp | 13 +++- src/http_connection.cpp | 5 +- src/http_parser.cpp | 102 +++++++++++--------------- src/http_seed_connection.cpp | 20 ++--- src/lsd.cpp | 3 +- src/receive_buffer.cpp | 10 +-- src/udp_tracker_connection.cpp | 10 +-- src/upnp.cpp | 3 +- src/web_peer_connection.cpp | 72 +++++++++--------- test/test_buffer.cpp | 14 ++-- test/test_http_parser.cpp | 15 ++-- test/test_upnp.cpp | 2 +- 16 files changed, 152 insertions(+), 173 deletions(-) diff --git a/include/libtorrent/aux_/io.hpp b/include/libtorrent/aux_/io.hpp index 9bd9f7cce..01ef60f99 100644 --- a/include/libtorrent/aux_/io.hpp +++ b/include/libtorrent/aux_/io.hpp @@ -55,7 +55,7 @@ namespace libtorrent { namespace aux ret <<= 8; ret |= static_cast(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((val >> shift) & 0xff); } - view = view.cut_first(sizeof(T)); + view = view.subspan(sizeof(T)); } // -- adaptors diff --git a/include/libtorrent/buffer.hpp b/include/libtorrent/buffer.hpp index 214fbb428..7d9f5133f 100644 --- a/include/libtorrent/buffer.hpp +++ b/include/libtorrent/buffer.hpp @@ -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() - { return span(m_begin, int(m_size)); } - operator span() const - { return span(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. diff --git a/include/libtorrent/http_parser.hpp b/include/libtorrent/http_parser.hpp index 7176c4c3b..9bdabfd41 100644 --- a/include/libtorrent/http_parser.hpp +++ b/include/libtorrent/http_parser.hpp @@ -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 incoming(buffer::const_interval recv_buffer + std::tuple incoming(span 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 buf , std::int64_t* chunk_size, int* header_size); // reset the whole state and start over @@ -122,18 +122,18 @@ namespace libtorrent std::vector > 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 m_header; - buffer::const_interval m_recv_buffer; + span m_recv_buffer; // contains offsets of the first and one-past-end of // each chunked range in the response std::vector > 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; }; } diff --git a/include/libtorrent/receive_buffer.hpp b/include/libtorrent/receive_buffer.hpp index e618a709a..0f3fe00ce 100644 --- a/include/libtorrent/receive_buffer.hpp +++ b/include/libtorrent/receive_buffer.hpp @@ -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); diff --git a/include/libtorrent/span.hpp b/include/libtorrent/span.hpp index 10440b71e..8a333b19b 100644 --- a/include/libtorrent/span.hpp +++ b/include/libtorrent/span.hpp @@ -92,10 +92,17 @@ namespace libtorrent return { data() + size() - n, n }; } - span cut_first(size_t const n) const + span 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 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) diff --git a/src/http_connection.cpp b/src/http_connection.cpp index a8cc8df57..5f5a949f6 100644 --- a/src/http_connection.cpp +++ b/src/http_connection.cpp @@ -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 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 diff --git a/src/http_parser.cpp b/src/http_parser.cpp index ed4864d2d..1a37a93a3 100644 --- a/src/http_parser.cpp +++ b/src/http_parser.cpp @@ -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 http_parser::incoming( - buffer::const_interval recv_buffer, bool& error) + span recv_buffer, bool& error) { - TORRENT_ASSERT(recv_buffer.left() >= m_recv_buffer.left()); + TORRENT_ASSERT(recv_buffer.size() >= m_recv_buffer.size()); std::tuple 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(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 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 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(); m_header.clear(); m_chunked_encoding = false; m_chunked_ranges.clear(); diff --git a/src/http_seed_connection.cpp b/src/http_seed_connection.cpp index 5fa4d4bf3..33fd2c9ce 100644 --- a/src/http_seed_connection.cpp +++ b/src/http_seed_connection.cpp @@ -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( + 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 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)); diff --git a/src/lsd.cpp b/src/lsd.cpp index c87be0d79..771bfcc7d 100644 --- a/src/lsd.cpp +++ b/src/lsd.cpp @@ -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(buf, bytes_transferred), error); if (!p.header_finished() || error) { diff --git a/src/receive_buffer.cpp b/src/receive_buffer.cpp index aded7f2b1..4360e8910 100644 --- a/src/receive_buffer.cpp +++ b/src/receive_buffer.cpp @@ -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(m_recv_buffer.ptr(), m_recv_end)); + , span(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(m_recv_buffer.ptr(), m_recv_end)); + , span(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 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()); } diff --git a/src/udp_tracker_connection.cpp b/src/udp_tracker_connection.cpp index 1a19dafdb..b4991a93c 100644 --- a/src/udp_tracker_connection.cpp +++ b/src/udp_tracker_connection.cpp @@ -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 diff --git a/src/upnp.cpp b/src/upnp.cpp index 8af0bf39c..209571145 100644 --- a/src/upnp.cpp +++ b/src/upnp.cpp @@ -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(buffer, bytes_transferred), error); if (error) { #ifndef TORRENT_DISABLE_LOGGING diff --git a/src/web_peer_connection.cpp b/src/web_peer_connection.cpp index 1d206bacc..41dcedb74 100644 --- a/src/web_peer_connection.cpp +++ b/src/web_peer_connection.cpp @@ -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 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 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 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); } diff --git a/test/test_buffer.cpp b/test/test_buffer.cpp index 881db3266..6d1e561ea 100644 --- a/test/test_buffer.cpp +++ b/test/test_buffer.cpp @@ -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); } diff --git a/test/test_http_parser.cpp b/test/test_http_parser.cpp index 45f38d8bd..0e8897cf3 100644 --- a/test/test_http_parser.cpp +++ b/test/test_http_parser.cpp @@ -38,6 +38,7 @@ POSSIBILITY OF SUCH DAMAGE. using namespace libtorrent; +// TODO: 3 use span here instead of zero-terminated string std::tuple feed_bytes(http_parser& parser, char const* str) { std::tuple ret(0, 0, false); @@ -46,12 +47,12 @@ std::tuple 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 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(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(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(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(chunk_header2, sizeof(chunk_header2)) , &chunk_size, &header_size); TEST_EQUAL(ret, true); TEST_EQUAL(chunk_size, 0); diff --git a/test/test_upnp.cpp b/test/test_upnp.cpp index d62a6f550..0ed8a6bae 100644 --- a/test/test_upnp.cpp +++ b/test/test_upnp.cpp @@ -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(buffer, size), error); if (error || !p.header_finished()) { std::cerr << "*** malformed HTTP from "