From 64304b459cf266ed6d36648bc337c21cbba17528 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Wed, 4 Dec 2024 06:15:45 -0800 Subject: [PATCH] retyping --- .clang-format | 24 +++++- include/oxen/quic/address.hpp | 32 ++++---- include/oxen/quic/btstream.hpp | 34 ++++----- include/oxen/quic/connection.hpp | 42 +++++------ include/oxen/quic/context.hpp | 6 +- include/oxen/quic/crypto.hpp | 21 +++--- include/oxen/quic/datagram.hpp | 18 +++-- include/oxen/quic/endpoint.hpp | 44 ++++++----- include/oxen/quic/format.hpp | 35 ++++++--- include/oxen/quic/gnutls_crypto.hpp | 57 +++++++------- include/oxen/quic/iochannel.hpp | 22 ++++-- include/oxen/quic/ip.hpp | 4 +- include/oxen/quic/loop.hpp | 8 +- include/oxen/quic/messages.hpp | 23 +++--- include/oxen/quic/network.hpp | 4 +- include/oxen/quic/opt.hpp | 57 ++++++-------- include/oxen/quic/stream.hpp | 24 +++--- include/oxen/quic/udp.hpp | 20 ++--- include/oxen/quic/utils.hpp | 86 +++++++++------------ src/address.cpp | 4 +- src/btstream.cpp | 56 +++++++------- src/connection.cpp | 52 +++++++------ src/connection_ids.cpp | 4 +- src/datagram.cpp | 6 +- src/endpoint.cpp | 65 +++++++++------- src/gnutls_creds.cpp | 2 +- src/gnutls_session.cpp | 50 ++++++------ src/internal.hpp | 7 +- src/messages.cpp | 20 ++--- src/network.cpp | 8 +- src/stream.cpp | 19 +++-- src/udp.cpp | 12 +-- src/utils.cpp | 6 +- tests/001-handshake.cpp | 20 ++--- tests/002-send-receive.cpp | 53 +++++++------ tests/003-multiclient.cpp | 7 +- tests/004-streams.cpp | 113 +++++++++++++--------------- tests/005-chunked-sender.cpp | 8 +- tests/006-server-send.cpp | 17 ++--- tests/007-datagrams.cpp | 39 ++++------ tests/008-conn_hooks.cpp | 3 - tests/009-alpns.cpp | 37 ++++----- tests/010-migration.cpp | 9 +-- tests/011-manual_transmission.cpp | 27 +++---- tests/012-watermarks.cpp | 33 ++++---- tests/013-eventhandler.cpp | 11 +-- tests/014-0rtt-resets.cpp | 5 -- tests/015-bt-encoding.cpp | 5 -- tests/CMakeLists.txt | 2 +- tests/case_logger.cpp | 5 +- tests/dgram-speed-client.cpp | 28 +++---- tests/dgram-speed-server.cpp | 16 ++-- tests/main.cpp | 4 +- tests/ping-client.cpp | 16 ++-- tests/ping-server.cpp | 16 ++-- tests/speedtest-client.cpp | 15 ++-- tests/speedtest-server.cpp | 18 +++-- tests/utils.hpp | 28 +++++-- 58 files changed, 706 insertions(+), 701 deletions(-) diff --git a/.clang-format b/.clang-format index 997febc0..3e9d226b 100644 --- a/.clang-format +++ b/.clang-format @@ -59,7 +59,29 @@ KeepEmptyLinesAtTheStartOfBlocks: 'true' NamespaceIndentation: All QualifierAlignment: Left RemoveSemicolon: true -SortIncludes: true + +#includes +SortIncludes: CaseInsensitive +IncludeBlocks: Regroup +IncludeCategories: + - Regex: '".+\.h' + Priority: 2 + - Regex: '^<(oxenc|oxen)' + Priority: 3 + - Regex: '^<(event2|ngtcp2)' + Priority: 4 + - Regex: '' + Priority: 5 + - Regex: '' + Priority: 6 + - Regex: '^$' + Priority: 9 + - Regex: '(<)(.)+(>)' + Priority: 10 # spacing SpaceBeforeParens: ControlStatements diff --git a/include/oxen/quic/address.hpp b/include/oxen/quic/address.hpp index 08b6af03..0417469d 100644 --- a/include/oxen/quic/address.hpp +++ b/include/oxen/quic/address.hpp @@ -1,13 +1,13 @@ #pragma once -#include - -#include - #include "formattable.hpp" #include "ip.hpp" #include "types.hpp" +#include + +#include + #if defined(__OpenBSD__) || defined(__DragonFly__) // These systems are known to disallow dual stack binding, and so on such systems when // invoked with an empty address we default to the IPv4 any address rather than the IPv6 any @@ -292,28 +292,32 @@ namespace oxen::quic struct RemoteAddress : public Address { private: - ustring remote_pubkey; + std::vector _remote_pubkey; public: RemoteAddress() = delete; template RemoteAddress(std::string_view remote_pk, Opt&&... opts) : - Address{std::forward(opts)...}, remote_pubkey{to_usv(remote_pk)} - {} + Address{std::forward(opts)...}, _remote_pubkey(remote_pk.size()) + { + std::memcpy(_remote_pubkey.data(), remote_pk.data(), remote_pk.size()); + } template - RemoteAddress(ustring_view remote_pk, Opt&&... opts) : Address{std::forward(opts)...}, remote_pubkey{remote_pk} - {} + RemoteAddress(uspan remote_pk, Opt&&... opts) : Address{std::forward(opts)...} + { + _remote_pubkey.assign(remote_pk.data(), remote_pk.data() + remote_pk.size()); + } - ustring_view view_remote_key() const { return remote_pubkey; } - const ustring& get_remote_key() const& { return remote_pubkey; } - ustring&& get_remote_key() && { return std::move(remote_pubkey); } + uspan view_remote_key() const { return _remote_pubkey; } + const std::vector& get_remote_key() const& { return _remote_pubkey; } + std::vector&& get_remote_key() && { return std::move(_remote_pubkey); } - RemoteAddress(const RemoteAddress& obj) : Address{obj}, remote_pubkey{obj.remote_pubkey} {} + RemoteAddress(const RemoteAddress& obj) : Address{obj}, _remote_pubkey{obj._remote_pubkey} {} RemoteAddress& operator=(const RemoteAddress& obj) { - remote_pubkey = obj.remote_pubkey; + _remote_pubkey = obj._remote_pubkey; Address::operator=(obj); _copy_internals(obj); return *this; diff --git a/include/oxen/quic/btstream.hpp b/include/oxen/quic/btstream.hpp index 66564eef..d194e25d 100644 --- a/include/oxen/quic/btstream.hpp +++ b/include/oxen/quic/btstream.hpp @@ -1,9 +1,9 @@ -#include - #include "endpoint.hpp" #include "stream.hpp" #include "utils.hpp" +#include + namespace oxen::quic { using time_point = std::chrono::steady_clock::time_point; @@ -37,7 +37,7 @@ namespace oxen::quic private: int64_t req_id; - bstring data; + std::vector data; // We keep the locations of variables fields as relative positions inside `data` *rather* // than using std::string_view members because the string_views are more difficult to @@ -54,15 +54,15 @@ namespace oxen::quic // didn't get any reply from the other side in time. This *can* happen earlier than the // requested timeout in cases where we detect early that the response cannot arrive, such // as the connection closing. - message(BTRequestStream& bp, bstring req, bool is_timeout = false); + message(BTRequestStream& bp, std::vector req, bool is_timeout = false); public: inline static constexpr auto TYPE_REPLY = "R"sv; inline static constexpr auto TYPE_ERROR = "E"sv; inline static constexpr auto TYPE_COMMAND = "C"sv; - void respond(bstring_view body, bool error = false) const; - void respond(std::string_view body, bool error = false) const { respond(convert_sv(body), error); } + void respond(bspan body, bool error = false) const; + void respond(std::string_view body, bool error = false) const { respond(str_to_bspan(body), error); } const bool timed_out{false}; bool is_error() const { return type() == TYPE_ERROR; } @@ -152,7 +152,7 @@ namespace oxen::quic bool is_expired(time_point now) const { return expiry < now; } - message to_timeout() && { return {return_sender, ""_bs, true}; } + message to_timeout() && { return {return_sender, {}, true}; } private: void handle_req_opts(std::function func) { cb = std::move(func); } @@ -178,8 +178,8 @@ namespace oxen::quic std::unordered_map> func_map; std::function generic_handler; - bstring buf; - std::string size_buf; + std::vector buf; + std::vector size_buf; size_t current_len{0}; @@ -216,7 +216,7 @@ namespace oxen::quic std::chrono::milliseconds timeout - request timeout (defaults to 10 seconds) */ template - void command(std::string ep, bstring_view body, Opt&&... opts) + void command(std::string ep, bspan body, Opt&&... opts) { auto rid = next_rid++; auto req = std::make_shared(*this, encode_command(ep, rid, body), rid, std::forward(opts)...); @@ -233,10 +233,10 @@ namespace oxen::quic template void command(std::string ep, std::string_view body, Opt&&... opts) { - command(std::move(ep), convert_sv(body), std::forward(opts)...); + command(std::move(ep), str_to_bspan(body), std::forward(opts)...); } - void respond(int64_t rid, bstring_view body, bool error = false); + void respond(int64_t rid, bspan body, bool error = false); /// Registers an individual endpoint to be recognized by this BTRequestStream object. Can be /// called multiple times to set up multiple commands. See also register_generic_handler. @@ -255,7 +255,7 @@ namespace oxen::quic void check_timeouts() override; void check_timeouts(std::optional now); - void receive(bstring_view data) override; + void receive(bspan data) override; void closed(uint64_t app_code) override; @@ -269,15 +269,15 @@ namespace oxen::quic void handle_input(message msg); - void process_incoming(std::string_view req); + void process_incoming(bspan req); - std::string encode_command(std::string_view endpoint, int64_t rid, bstring_view body); + std::string encode_command(std::string_view endpoint, int64_t rid, bspan body); - std::string encode_response(int64_t rid, bstring_view body, bool error); + std::string encode_response(int64_t rid, bspan body, bool error); sent_request* add_sent_request(std::shared_ptr req); - size_t parse_length(std::string_view req); + size_t parse_length(cspan req); size_t num_pending_impl() const { return user_buffers.size(); } }; diff --git a/include/oxen/quic/connection.hpp b/include/oxen/quic/connection.hpp index 8e502ce7..c898b0aa 100644 --- a/include/oxen/quic/connection.hpp +++ b/include/oxen/quic/connection.hpp @@ -1,5 +1,10 @@ #pragma once +#include "connection_ids.hpp" +#include "context.hpp" +#include "format.hpp" +#include "types.hpp" + #include #include #include @@ -11,11 +16,6 @@ #include #include -#include "connection_ids.hpp" -#include "context.hpp" -#include "format.hpp" -#include "types.hpp" - namespace oxen::quic { struct dgram_interface; @@ -34,7 +34,7 @@ namespace oxen::quic virtual std::shared_ptr get_stream_impl(int64_t id) = 0; public: - virtual ustring_view selected_alpn() const = 0; + virtual uspan selected_alpn() const = 0; /// Queues an incoming stream of the given StreamT type, forwarding the given arguments to /// the StreamT constructor. The stream will be given the next unseen incoming connection @@ -119,7 +119,7 @@ namespace oxen::quic requires(!std::same_as) void send_datagram(std::basic_string_view data, std::shared_ptr keep_alive = nullptr) { - send_datagram(convert_sv(data), std::move(keep_alive)); + send_datagram(str_to_bspan(data), std::move(keep_alive)); } template @@ -127,7 +127,7 @@ namespace oxen::quic { auto keep_alive = std::make_shared>(std::move(buf)); std::basic_string_view view{keep_alive->data(), keep_alive->size()}; - send_datagram(view, std::move(keep_alive)); + send_datagram(str_to_bspan(view), std::move(keep_alive)); } template @@ -135,10 +135,10 @@ namespace oxen::quic { auto keep_alive = std::make_shared>(std::move(data)); std::basic_string_view view{*keep_alive}; - send_datagram(view, std::move(keep_alive)); + send_datagram(str_to_bspan(view), std::move(keep_alive)); } - virtual void send_datagram(bstring_view data, std::shared_ptr keep_alive = nullptr) = 0; + virtual void send_datagram(bspan data, std::shared_ptr keep_alive = nullptr) = 0; virtual Endpoint& endpoint() = 0; virtual const Endpoint& endpoint() const = 0; @@ -150,7 +150,7 @@ namespace oxen::quic virtual const ConnectionID& reference_id() const = 0; virtual bool is_validated() const = 0; virtual Direction direction() const = 0; - virtual ustring_view remote_key() const = 0; + virtual uspan remote_key() const = 0; virtual bool is_inbound() const = 0; virtual bool is_outbound() const = 0; virtual std::string direction_str() = 0; @@ -269,9 +269,9 @@ namespace oxen::quic const quic_cid& dcid, const Path& path, std::shared_ptr ctx, - const std::vector& alpns, + const std::vector>& alpns, std::chrono::nanoseconds default_handshake_timeout, - std::optional remote_pk = std::nullopt, + std::optional> remote_pk = std::nullopt, ngtcp2_pkt_hd* hdr = nullptr, std::optional token_type = std::nullopt, ngtcp2_cid* ocid = nullptr); @@ -280,7 +280,7 @@ namespace oxen::quic TLSSession* get_session() const; - ustring_view remote_key() const override; + uspan remote_key() const override; Direction direction() const override { return dir; } @@ -305,7 +305,7 @@ namespace oxen::quic Endpoint& endpoint() override { return _endpoint; } const Endpoint& endpoint() const override { return _endpoint; } - ustring_view selected_alpn() const override; + uspan selected_alpn() const override; uint64_t get_streams_available_impl() const override; size_t get_max_datagram_size_impl() override; @@ -324,7 +324,7 @@ namespace oxen::quic // public debug functions; to be removed with friend test fixture class int last_cleared() const override; - void send_datagram(bstring_view data, std::shared_ptr keep_alive = nullptr) override; + void send_datagram(bspan data, std::shared_ptr keep_alive = nullptr) override; void close_connection(uint64_t error_code = 0) override; @@ -381,9 +381,9 @@ namespace oxen::quic const quic_cid& dcid, const Path& path, std::shared_ptr ctx, - const std::vector& alpns, + const std::vector>& alpns, std::chrono::nanoseconds default_handshake_timeout, - std::optional remote_pk = std::nullopt, + std::optional> remote_pk = std::nullopt, ngtcp2_pkt_hd* hdr = nullptr, std::optional token_type = std::nullopt, ngtcp2_cid* ocid = nullptr); @@ -416,7 +416,7 @@ namespace oxen::quic std::atomic _close_quietly{false}; std::atomic _is_validated{false}; - ustring remote_pubkey{}; + std::vector remote_pubkey{}; std::vector _early_streams; @@ -505,12 +505,12 @@ namespace oxen::quic // these are public so ngtcp2 can access them from callbacks int stream_opened(int64_t id); int stream_ack(int64_t id, size_t size); - int stream_receive(int64_t id, bstring_view data, bool fin); + int stream_receive(int64_t id, bspan data, bool fin); void stream_execute_close(Stream& s, uint64_t app_code); void stream_closed(int64_t id, uint64_t app_code); void close_all_streams(); void check_pending_streams(uint64_t available, bool is_early_stream = false); - int recv_datagram(bstring_view data, bool fin); + int recv_datagram(bspan data, bool fin); int ack_datagram(uint64_t dgram_id); int recv_token(const uint8_t* token, size_t tokenlen); diff --git a/include/oxen/quic/context.hpp b/include/oxen/quic/context.hpp index 954bc0f1..d3f219e4 100644 --- a/include/oxen/quic/context.hpp +++ b/include/oxen/quic/context.hpp @@ -1,8 +1,5 @@ #pragma once -#include -#include - #include "crypto.hpp" #include "datagram.hpp" #include "opt.hpp" @@ -10,6 +7,9 @@ #include "udp.hpp" #include "utils.hpp" +#include +#include + namespace oxen::quic { // created to store user configuration values; more values to be added later diff --git a/include/oxen/quic/crypto.hpp b/include/oxen/quic/crypto.hpp index b7e8b0f1..861dce2e 100644 --- a/include/oxen/quic/crypto.hpp +++ b/include/oxen/quic/crypto.hpp @@ -2,19 +2,20 @@ extern "C" { -#include -#include #include #include -} -#include +#include +#include +} #include "utils.hpp" +#include + namespace oxen::quic { - inline constexpr auto default_alpn_str = "default"_usv; + inline constexpr auto default_alpn_str = "default"_usp; inline constexpr std::chrono::milliseconds DEFAULT_ANTI_REPLAY_WINDOW{10min}; class TLSSession; @@ -25,7 +26,9 @@ namespace oxen::quic { public: virtual std::unique_ptr make_session( - Connection& c, const std::shared_ptr& ctx, const std::vector& alpns) = 0; + Connection& c, + const std::shared_ptr& ctx, + const std::vector>& alpns) = 0; virtual ~TLSCreds() = default; }; @@ -36,9 +39,9 @@ namespace oxen::quic virtual void* get_session() = 0; virtual void* get_anti_replay() const = 0; virtual bool get_early_data_accepted() const = 0; - virtual ustring_view selected_alpn() const = 0; - virtual ustring_view remote_key() const = 0; - virtual void set_expected_remote_key(ustring_view key) = 0; + virtual uspan selected_alpn() const = 0; + virtual uspan remote_key() const = 0; + virtual void set_expected_remote_key(uspan key) = 0; virtual ~TLSSession() = default; virtual int send_session_ticket() = 0; }; diff --git a/include/oxen/quic/datagram.hpp b/include/oxen/quic/datagram.hpp index 5804f962..07c8ddc3 100644 --- a/include/oxen/quic/datagram.hpp +++ b/include/oxen/quic/datagram.hpp @@ -30,13 +30,15 @@ namespace oxen::quic requires(!std::same_as) void reply(std::basic_string_view data, std::shared_ptr keep_alive = nullptr) { - reply(convert_sv(data), std::move(keep_alive)); + reply(str_to_bspan(data), std::move(keep_alive)); } template void send_datagram(std::vector&& buf) { - reply(std::basic_string_view{buf.data(), buf.size()}, std::make_shared>(std::move(buf))); + auto keep_alive = std::make_shared>(std::move(buf)); + auto sp = vec_to_span(*keep_alive); + reply(sp, std::move(keep_alive)); } template @@ -44,16 +46,16 @@ namespace oxen::quic { auto keep_alive = std::make_shared>(std::move(data)); std::basic_string_view view{*keep_alive}; - reply(view, std::move(keep_alive)); + reply(str_to_bspan(view), std::move(keep_alive)); } - void reply(bstring_view data, std::shared_ptr keep_alive = nullptr); + void reply(bspan data, std::shared_ptr keep_alive = nullptr); }; // IO callbacks - using dgram_data_callback = std::function; + using dgram_data_callback = std::function)>; - using dgram_buffer = std::deque>>>; + using dgram_buffer = std::deque>>>; class DatagramIO : public IOChannel { @@ -145,7 +147,7 @@ namespace oxen::quic bool is_stream() const override { return false; } - std::optional to_buffer(bstring_view data, uint16_t dgid); + std::optional> to_buffer(bspan data, uint16_t dgid); int datagrams_stored() const { return recv_buffer.datagrams_stored(); } @@ -159,7 +161,7 @@ namespace oxen::quic protected: bool is_empty_impl() const override { return send_buffer.empty(); } - void send_impl(bstring_view data, std::shared_ptr keep_alive) override; + void send_impl(bspan data, std::shared_ptr keep_alive) override; bool is_closing_impl() const override; bool sent_fin() const override; diff --git a/include/oxen/quic/endpoint.hpp b/include/oxen/quic/endpoint.hpp index a33a6fde..42774c6e 100644 --- a/include/oxen/quic/endpoint.hpp +++ b/include/oxen/quic/endpoint.hpp @@ -9,6 +9,13 @@ extern "C" #endif } +#include "connection.hpp" +#include "context.hpp" +#include "gnutls_crypto.hpp" +#include "network.hpp" +#include "udp.hpp" +#include "utils.hpp" + #include #include #include @@ -19,13 +26,6 @@ extern "C" #include #include -#include "connection.hpp" -#include "context.hpp" -#include "gnutls_crypto.hpp" -#include "network.hpp" -#include "udp.hpp" -#include "utils.hpp" - namespace oxen::quic { class Endpoint : public std::enable_shared_from_this @@ -156,7 +156,7 @@ namespace oxen::quic bool in_event_loop() const; // Returns a random value suitable for use as the Endpoint static secret value. - static ustring make_static_secret(); + static std::vector make_static_secret(); void manually_receive_packet(Packet&& pkt); @@ -167,7 +167,7 @@ namespace oxen::quic int validate_anti_replay(gtls_ticket_ptr ticket, time_t exp); void store_session_ticket(gtls_ticket_ptr ticket); - gtls_ticket_ptr get_session_ticket(const ustring_view& remote_pk); + gtls_ticket_ptr get_session_ticket(const uspan& remote_pk); private: friend class Network; @@ -198,20 +198,20 @@ namespace oxen::quic uint64_t _next_rid{0}; - ustring _static_secret; + std::vector _static_secret; std::shared_ptr outbound_ctx; std::shared_ptr inbound_ctx; - std::vector outbound_alpns; - std::vector inbound_alpns; + std::vector> outbound_alpns; + std::vector> inbound_alpns; std::chrono::nanoseconds handshake_timeout{DEFAULT_HANDSHAKE_TIMEOUT}; - std::unordered_map session_tickets; + std::unordered_map session_tickets; - std::unordered_map encoded_transport_params; + std::unordered_map> encoded_transport_params; - std::unordered_map path_validation_tokens; + std::unordered_map> path_validation_tokens; const std::shared_ptr& get_loop() { return net._loop->loop(); } @@ -227,11 +227,9 @@ namespace oxen::quic quic_cid qcid, ConnectionID rid, std::promise>& p, - std::optional pk = std::nullopt); + std::optional> pk = std::nullopt); void handle_ep_opt(opt::enable_datagrams dc); - void handle_ep_opt(opt::outbound_alpns alpns); - void handle_ep_opt(opt::inbound_alpns alpns); void handle_ep_opt(opt::alpns alpns); void handle_ep_opt(opt::handshake_timeout timeout); void handle_ep_opt(dgram_data_callback dgram_cb); @@ -281,13 +279,13 @@ namespace oxen::quic void connection_established(connection_interface& conn); - void store_0rtt_transport_params(Address remote, ustring encoded_params); + void store_0rtt_transport_params(Address remote, std::vector encoded_params); - std::optional get_0rtt_transport_params(const Address& remote); + std::optional> get_0rtt_transport_params(const Address& remote); - void store_path_validation_token(Address remote, ustring token); + void store_path_validation_token(Address remote, std::vector token); - std::optional get_path_validation_token(const Address& remote); + std::optional> get_path_validation_token(const Address& remote); void initial_association(Connection& conn); @@ -303,7 +301,7 @@ namespace oxen::quic void dissociate_cid(quic_cid qcid, Connection& conn); - const ustring& static_secret() const { return _static_secret; } + const std::vector& static_secret() const { return _static_secret; } Connection* fetch_associated_conn(quic_cid& cid); diff --git a/include/oxen/quic/format.hpp b/include/oxen/quic/format.hpp index cc4d569c..e38d7fa9 100644 --- a/include/oxen/quic/format.hpp +++ b/include/oxen/quic/format.hpp @@ -5,30 +5,36 @@ // available (which is true in libquic itself, but may not be when libquic is installed as a // library). +#include "formattable.hpp" + +#include + #include -#include #include -#include "formattable.hpp" - namespace oxen::quic { struct buffer_printer { + private: std::basic_string_view buf; + public: + template + explicit buffer_printer(const T* data, size_t datalen) : buf{reinterpret_cast(data), datalen} + {} + // Constructed from any type of string_view for a single-byte T (char, std::byte, // uint8_t, etc.) template - explicit buffer_printer(std::basic_string_view buf) : - buf{reinterpret_cast(buf.data()), buf.size()} + explicit buffer_printer(std::basic_string_view data) : buffer_printer{data.data(), data.size()} {} // Constructed from any type of lvalue string for a single-byte T (char, std::byte, // uint8_t, etc.) template - explicit buffer_printer(const std::basic_string& buf) : buffer_printer(std::basic_string_view{buf}) + explicit buffer_printer(const std::basic_string& data) : buffer_printer{data.data(), data.size()} {} // *Not* constructable from a string rvalue (because we only hold a view and do not take @@ -36,9 +42,9 @@ namespace oxen::quic template explicit buffer_printer(std::basic_string&& buf) = delete; - // Constructable from a (T*, size) argument pair, for byte-sized T's. - template - explicit buffer_printer(const T* data, size_t size) : buffer_printer(std::basic_string_view{data, size}) + // Constructed from any type of span + template + explicit buffer_printer(const T& data) : buffer_printer{data.data(), data.size()} {} std::string to_string() const; @@ -57,4 +63,15 @@ namespace fmt return formatter::format(val.to_string(), ctx); } }; + + template + struct formatter : formatter + { + template + auto format(const T& val, FormatContext& ctx) const + { + return formatter::format( + std::string_view{reinterpret_cast(val.data()), val.size()}, ctx); + } + }; } // namespace fmt diff --git a/include/oxen/quic/gnutls_crypto.hpp b/include/oxen/quic/gnutls_crypto.hpp index c154fb15..d6200d2d 100644 --- a/include/oxen/quic/gnutls_crypto.hpp +++ b/include/oxen/quic/gnutls_crypto.hpp @@ -1,5 +1,9 @@ #pragma once +#include "connection_ids.hpp" +#include "crypto.hpp" +#include "types.hpp" + #include #include @@ -7,10 +11,6 @@ #include #include -#include "connection_ids.hpp" -#include "crypto.hpp" -#include "types.hpp" - namespace oxen::quic { using namespace oxenc::literals; @@ -75,7 +75,7 @@ namespace oxen::quic d.size = 0; } - ustring_view view() const { return {d.data, d.size}; } + uspan span() const { return {d.data, d.size}; } const unsigned char* data() const { return d.data; } unsigned char* data() { return d.data; } @@ -104,8 +104,8 @@ namespace oxen::quic public: gtls_key() = default; - gtls_key(std::string_view data) : gtls_key{convert_sv(data)} {} - gtls_key(ustring_view data) : gtls_key{data.data(), data.size()} {} + gtls_key(std::string_view data) : gtls_key{str_to_uspan(data)} {} + gtls_key(uspan data) : gtls_key{data.data(), data.size()} {} // Writes to the internal buffer holding the gnutls key void write(const unsigned char* data, size_t size) @@ -116,7 +116,7 @@ namespace oxen::quic std::memcpy(buf.data(), data, size); } - ustring_view view() const { return {buf.data(), buf.size()}; } + uspan span() const { return {buf.data(), buf.size()}; } gtls_key(const gtls_key& other) { *this = other; } @@ -126,7 +126,7 @@ namespace oxen::quic return *this; } - void operator()(ustring_view data) { write(data.data(), data.size()); } + void operator()(uspan data) { write(data.data(), data.size()); } explicit operator bool() const { return not buf.empty(); } @@ -135,7 +135,7 @@ namespace oxen::quic }; // key: remote key to verify, alpn: negotiated alpn's - using key_verify_callback = std::function; + using key_verify_callback = std::function; inline const gnutls_datum_t GNUTLS_DEFAULT_ALPN{ const_cast(default_alpn_str.data()), default_alpn_str.size()}; @@ -313,14 +313,6 @@ namespace oxen::quic _key{key, key + keysize}, _ticket{ticket, ticket + ticketsize}, _data{_ticket.data(), ticketsize} {} - explicit gtls_session_ticket(ustring_view key, ustring_view ticket) : - gtls_session_ticket{ - key.data(), - static_cast(key.size()), - ticket.data(), - static_cast(ticket.size())} - {} - public: gtls_session_ticket() = delete; gtls_session_ticket(gtls_session_ticket&& t) = delete; @@ -333,7 +325,7 @@ namespace oxen::quic return gtls_ticket_ptr(new gtls_session_ticket{key->data, key->size, ticket->data, ticket->size}); } - static gtls_ticket_ptr make(ustring_view key, const gnutls_datum_t* ticket) + static gtls_ticket_ptr make(uspan key, const gnutls_datum_t* ticket) { return gtls_ticket_ptr( new gtls_session_ticket{key.data(), static_cast(key.size()), ticket->data, ticket->size}); @@ -342,10 +334,10 @@ namespace oxen::quic // Returns a view of the key for this ticket. The view is valid as long as this // gtls_session_ticket object remains alive, and so can be used (for example) as the key of // a map containing the object in the value. - ustring_view key() const { return {_key.data(), _key.size()}; } + uspan span() const { return {_key.data(), _key.size()}; } // Returns a view of the ticket data. - ustring_view ticket() const { return {_ticket.data(), _ticket.size()}; } + uspan ticket() const { return {_ticket.data(), _ticket.size()}; } // Accesses the ticket data pointer as needed by gnutls API const gnutls_datum_t* datum() const { return &_data; } @@ -405,7 +397,9 @@ namespace oxen::quic public: std::unique_ptr make_session( - Connection& c, const std::shared_ptr&, const std::vector& alpns) override; + Connection& c, + const std::shared_ptr&, + const std::vector>& alpns) override; void load_keys(x509_loader& seed, x509_loader& pk); @@ -425,7 +419,7 @@ namespace oxen::quic const bool _is_client; const bool _0rtt_enabled; - ustring _selected_alpn{}; + std::vector _selected_alpn{}; gtls_key _expected_remote_key{}; gtls_key _remote_key{}; @@ -436,7 +430,7 @@ namespace oxen::quic GNUTLSCreds& creds, const std::shared_ptr& ctx, Connection& c, - const std::vector& alpns, + const std::vector>& alpns, std::optional expected_key = std::nullopt); ~GNUTLSSession(); @@ -450,18 +444,21 @@ namespace oxen::quic return gnutls_session_get_flags(session) & GNUTLS_SFLAGS_EARLY_DATA; } - ustring_view remote_key() const override { return _remote_key.view(); } + uspan remote_key() const override { return _remote_key.span(); } - ustring_view selected_alpn() const override { return _selected_alpn; } + uspan selected_alpn() const override { return _selected_alpn; } bool validate_remote_key(); int send_session_ticket() override; - void set_expected_remote_key(ustring_view key) override { _expected_remote_key(key); } + void set_expected_remote_key(uspan key) override { _expected_remote_key.write(key.data(), key.size()); } }; - GNUTLSSession* get_session_from_gnutls(gnutls_session_t g_session); - Connection* get_connection_from_gnutls(gnutls_session_t g_session); - + namespace detail + { + GNUTLSSession* get_session(Connection* conn); + GNUTLSSession* get_session(gnutls_session_t g_session); + Connection* get_connection(gnutls_session_t g_session); + } // namespace detail } // namespace oxen::quic diff --git a/include/oxen/quic/iochannel.hpp b/include/oxen/quic/iochannel.hpp index 89e4da11..2c4bbbe3 100644 --- a/include/oxen/quic/iochannel.hpp +++ b/include/oxen/quic/iochannel.hpp @@ -1,11 +1,11 @@ #pragma once -#include - #include "connection_ids.hpp" #include "messages.hpp" #include "utils.hpp" +#include + namespace oxen::quic { @@ -48,10 +48,18 @@ namespace oxen::quic Address local() const; Address remote() const; + void send(bspan data, std::shared_ptr keep_alive = nullptr) { send_impl(data, std::move(keep_alive)); } + + template + void send(const_span data, std::shared_ptr keep_alive = nullptr) + { + send_impl(span_to_span(data), std::move(keep_alive)); + } + template void send(std::basic_string_view data, std::shared_ptr keep_alive = nullptr) { - send_impl(convert_sv(data), std::move(keep_alive)); + send_impl(str_to_bspan(data), std::move(keep_alive)); } template @@ -59,13 +67,15 @@ namespace oxen::quic { auto keep_alive = std::make_shared>(std::move(data)); std::basic_string_view view{*keep_alive}; - send(view, std::move(keep_alive)); + send_impl(str_to_bspan(view), std::move(keep_alive)); } template void send(std::vector&& buf) { - send(std::basic_string_view{buf.data(), buf.size()}, std::make_shared>(std::move(buf))); + auto keep_alive = std::make_shared>(std::move(buf)); + auto bsp = vec_to_span(*keep_alive); + send_impl(bsp, std::move(keep_alive)); } protected: @@ -76,7 +86,7 @@ namespace oxen::quic // This is the (single) send implementation that implementing classes must provide; other // calls to send are converted into calls to this. - virtual void send_impl(bstring_view, std::shared_ptr keep_alive) = 0; + virtual void send_impl(bspan, std::shared_ptr keep_alive) = 0; virtual std::vector pending() = 0; virtual prepared_datagram pending_datagram(bool) = 0; diff --git a/include/oxen/quic/ip.hpp b/include/oxen/quic/ip.hpp index 42704851..28745dba 100644 --- a/include/oxen/quic/ip.hpp +++ b/include/oxen/quic/ip.hpp @@ -1,10 +1,10 @@ #pragma once -#include - #include "formattable.hpp" #include "utils.hpp" +#include + namespace oxen::quic { struct ipv4 diff --git a/include/oxen/quic/loop.hpp b/include/oxen/quic/loop.hpp index 6e0e46b5..694e2d60 100644 --- a/include/oxen/quic/loop.hpp +++ b/include/oxen/quic/loop.hpp @@ -6,6 +6,10 @@ extern "C" #include } +#include "context.hpp" +#include "crypto.hpp" +#include "utils.hpp" + #include #include #include @@ -13,10 +17,6 @@ extern "C" #include #include -#include "context.hpp" -#include "crypto.hpp" -#include "utils.hpp" - namespace oxen::quic { using Job = std::function; diff --git a/include/oxen/quic/messages.hpp b/include/oxen/quic/messages.hpp index 36464531..609e3056 100644 --- a/include/oxen/quic/messages.hpp +++ b/include/oxen/quic/messages.hpp @@ -1,11 +1,11 @@ #pragma once -#include - #include "address.hpp" #include "types.hpp" #include "utils.hpp" +#include + namespace oxen::quic { class DatagramIO; @@ -14,7 +14,7 @@ namespace oxen::quic struct outbound_dgram { - bstring_view data; + bspan data; uint16_t id; // -1: payload, 1: addendum int8_t type{0}; @@ -44,7 +44,7 @@ namespace oxen::quic std::array data; received_datagram() = default; - explicit received_datagram(uint16_t dgid, bstring_view d) : + explicit received_datagram(uint16_t dgid, bspan d) : id{dgid}, part{(dgid % 4 == 2) ? int8_t{-1} : int8_t{1}}, data_size{static_cast(d.size())} { std::memcpy(data.data(), d.data(), data_size); @@ -55,26 +55,25 @@ namespace oxen::quic { uint16_t pload_id; std::optional add_id; - std::optional payload, addendum; + std::optional payload, addendum; std::shared_ptr keep_alive; dgram type; static datagram_storage make( - bstring_view pload, uint16_t d_id, std::shared_ptr data, dgram type, size_t max_size = 0); + bspan pload, uint16_t d_id, std::shared_ptr data, dgram type, size_t max_size = 0); bool empty() const { return !(payload || addendum); } outbound_dgram fetch(bool b); - size_t size() const { return payload->length() + addendum->length(); } + size_t size() const { return payload->size() + addendum->size(); } private: - explicit datagram_storage(bstring_view pload, uint16_t p_id, std::shared_ptr data) : + explicit datagram_storage(bspan pload, uint16_t p_id, std::shared_ptr data) : pload_id{p_id}, payload{pload}, keep_alive{std::move(data)}, type{dgram::STANDARD} {} - explicit datagram_storage( - bstring_view pload, bstring_view add, uint16_t p_id, uint16_t a_id, std::shared_ptr data) : + explicit datagram_storage(bspan pload, bspan add, uint16_t p_id, uint16_t a_id, std::shared_ptr data) : pload_id{p_id}, add_id{a_id}, payload{pload}, @@ -98,7 +97,7 @@ namespace oxen::quic std::array>, 4> buf; - std::optional receive(bstring_view data, uint16_t dgid); + std::optional> receive(bspan data, uint16_t dgid); void clear_row(int index); int datagrams_stored() const; }; @@ -114,7 +113,7 @@ namespace oxen::quic prepared_datagram prepare(bool b, int is_splitting); - void emplace(bstring_view pload, uint16_t p_id, std::shared_ptr data, dgram type, size_t max_size = 0); + void emplace(bspan pload, uint16_t p_id, std::shared_ptr data, dgram type, size_t max_size = 0); }; } // namespace oxen::quic diff --git a/include/oxen/quic/network.hpp b/include/oxen/quic/network.hpp index 30301014..42a52373 100644 --- a/include/oxen/quic/network.hpp +++ b/include/oxen/quic/network.hpp @@ -1,5 +1,7 @@ #pragma once +#include "loop.hpp" + #include #include @@ -8,8 +10,6 @@ #include #include -#include "loop.hpp" - namespace oxen::quic { class Endpoint; diff --git a/include/oxen/quic/opt.hpp b/include/oxen/quic/opt.hpp index e1bcc393..06702b3f 100644 --- a/include/oxen/quic/opt.hpp +++ b/include/oxen/quic/opt.hpp @@ -1,11 +1,11 @@ #pragma once -#include - #include "address.hpp" #include "gnutls_crypto.hpp" #include "types.hpp" +#include + namespace oxen::quic { class Endpoint; @@ -22,35 +22,28 @@ namespace oxen::quic explicit max_streams(uint64_t s) : stream_count{s} {} }; - // supported ALPNs for outbound connections - struct outbound_alpns + // Sets the ALPNs protocols for a given endpoint. The user can pass protos for inbound, outbound, or both + // simultaneously + struct alpns { - std::vector alpns; - explicit outbound_alpns(std::vector alpns = {}) : alpns{std::move(alpns)} {} - - // Convenience wrapper that sets a single ALPN value from a regular string: - explicit outbound_alpns(std::string_view alpn) : outbound_alpns{{ustring{to_usv(alpn)}}} {} - }; + private: + void _emplace(const uspan& p) { protos.emplace_back(std::vector{p.data(), p.data() + p.size()}); } - // supported ALPNs for inbound connections - struct inbound_alpns - { - std::vector alpns; - explicit inbound_alpns(std::vector alpns = {}) : alpns{std::move(alpns)} {} + public: + enum class DIR { I, O, IO }; - // Convenience wrapper that sets a single ALPN value from a regular string: - explicit inbound_alpns(std::string_view alpn) : inbound_alpns{{ustring{to_usv(alpn)}}} {} - }; + const DIR direction; + std::vector> protos; - // Sets the inbound and outbound ALPNs simulatneous to the same value(s). This is equivalent to - // passing outbound_alpns and inbound_alps, separately, with the same vector argument. - struct alpns - { - std::vector inout_alpns; - explicit alpns(std::vector alpns = {}) : inout_alpns{std::move(alpns)} {} + constexpr alpns(DIR d, std::vector>&& alpns) : direction{d}, protos{std::move(alpns)} + {} - // Convenience wrapper that sets a single ALPN value from a regular string: - explicit alpns(std::string_view alpn) : alpns{{ustring{to_usv(alpn)}}} {} + template + requires(std::same_as && ...) + constexpr alpns(DIR d, arg&&... args) : direction{d} + { + ((void)_emplace(std::forward(args)), ...); + } }; struct handshake_timeout @@ -133,8 +126,8 @@ namespace oxen::quic { inline static constexpr size_t SECRET_MIN_SIZE{16}; - ustring secret; - explicit static_secret(ustring s) : secret{std::move(s)} + std::vector secret; + explicit static_secret(std::vector s) : secret{std::move(s)} { if (secret.size() < SECRET_MIN_SIZE) throw std::invalid_argument{ @@ -147,7 +140,7 @@ namespace oxen::quic // take responsibility for passing packets into the Endpoint via Endpoint::manually_receive_packet(...) struct manual_routing { - using send_handler_t = std::function; + using send_handler_t = std::function; private: friend Endpoint; @@ -163,7 +156,7 @@ namespace oxen::quic throw std::runtime_error{"opt::manual_routing must be constructed with a send handler hook!"}; } - io_result operator()(const Path& p, bstring_view data, size_t& n) + io_result operator()(const Path& p, bspan data, size_t& n) { send_hook(p, data); n = 0; @@ -205,7 +198,7 @@ namespace oxen::quic } // namespace opt using gtls_db_validate_cb = std::function; - using gtls_db_get_cb = std::function; + using gtls_db_get_cb = std::function; using gtls_db_put_cb = std::function; namespace opt @@ -235,7 +228,7 @@ namespace oxen::quic see: https://www.gnutls.org/manual/html_node/Core-TLS-API.html#gnutls_005fanti_005freplay_005fset_005fadd_005ffunction - - `gtls_db_get_cb` : The invocation is provided one ustring_view storing the ticket key. The application will + - `gtls_db_get_cb` : The invocation is provided one uspan storing the ticket key. The application will return the session ticket in a unique ptr, or nullptr if not found. This can be constructed using the static gtls_session_ticket::make(...) overrides provded. If the endpoint successfully fetches the ticket, it must ERASE THE ENTRY. Servers will reject already used tokens in their cb, so the client must not store them. diff --git a/include/oxen/quic/stream.hpp b/include/oxen/quic/stream.hpp index 65946482..57459ecb 100644 --- a/include/oxen/quic/stream.hpp +++ b/include/oxen/quic/stream.hpp @@ -1,5 +1,12 @@ #pragma once +#include "connection_ids.hpp" +#include "error.hpp" +#include "iochannel.hpp" +#include "opt.hpp" +#include "types.hpp" +#include "utils.hpp" + #include #include #include @@ -10,13 +17,6 @@ #include #include -#include "connection_ids.hpp" -#include "error.hpp" -#include "iochannel.hpp" -#include "opt.hpp" -#include "types.hpp" -#include "utils.hpp" - namespace oxen::quic { class Stream; @@ -25,7 +25,7 @@ namespace oxen::quic struct quic_cid; // Stream callbacks - using stream_data_callback = std::function; + using stream_data_callback = std::function; using stream_close_callback = std::function; using stream_constructor_callback = std::function(Connection&, Endpoint&, std::optional)>; @@ -113,7 +113,7 @@ namespace oxen::quic stream_close_callback close_callback; protected: - virtual void receive(bstring_view data) + virtual void receive(bspan data) { if (data_callback) data_callback(*this, data); @@ -130,7 +130,7 @@ namespace oxen::quic /// ain't not good enough isn't false. virtual void check_timeouts() {} - void send_impl(bstring_view data, std::shared_ptr keep_alive = nullptr) override; + void send_impl(bspan data, std::shared_ptr keep_alive = nullptr) override; stream_buffer user_buffers; @@ -171,7 +171,7 @@ namespace oxen::quic void wrote(size_t bytes) override; - void append_buffer(bstring_view buffer, std::shared_ptr keep_alive); + void append_buffer(bspan buffer, std::shared_ptr keep_alive); void acknowledge(size_t bytes); @@ -227,7 +227,7 @@ namespace oxen::quic single_chunk(chunk_sender& cs, Container&& d) : _chunks{cs.shared_from_this()}, _data{std::move(d)} {} ~single_chunk() { _chunks->queue_next_chunk(); } - bstring_view view() const + bspan view() const { if constexpr (is_pointer) { diff --git a/include/oxen/quic/udp.hpp b/include/oxen/quic/udp.hpp index 60b8f41b..47f793be 100644 --- a/include/oxen/quic/udp.hpp +++ b/include/oxen/quic/udp.hpp @@ -4,22 +4,23 @@ extern "C" { #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN -#include #include + +#include #else #include #endif } +#include "address.hpp" +#include "types.hpp" +#include "utils.hpp" + #include #include #include -#include "address.hpp" -#include "types.hpp" -#include "utils.hpp" - namespace oxen::quic { @@ -48,17 +49,18 @@ namespace oxen::quic } /// Constructs a packet from a path and data view: - Packet(Path p, bstring_view d) : path{std::move(p)}, data_sp{d.begin(), d.end()} {} + Packet(Path p, bspan d) : path{std::move(p)}, data_sp{d.begin(), d.end()} {} /// Constructs a packet from a path and transferred data: - Packet(Path p, bstring&& d) : path{std::move(p)}, pkt_data(d.size()), data_sp{pkt_data.data(), d.size()} + Packet(Path p, std::vector&& d) : + path{std::move(p)}, pkt_data(d.size()), data_sp{pkt_data.data(), d.size()} { std::memmove(pkt_data.data(), d.data(), d.size()); } /// Constructs a packet from a local address, data, and the IP header; remote addr and ECN /// data are extracted from the header. - Packet(const Address& local, bstring_view data, msghdr& hdr); + Packet(const Address& local, bspan data, msghdr& hdr); }; /// RAII class wrapping a UDP socket; the socket is bound at construction and closed during @@ -130,7 +132,7 @@ namespace oxen::quic ~UDPSocket(); private: - void process_packet(bstring_view payload, msghdr& hdr); + void process_packet(bspan payload, msghdr& hdr); io_result receive(); socket_t sock_; diff --git a/include/oxen/quic/utils.hpp b/include/oxen/quic/utils.hpp index 00cc87c8..5279c7dd 100644 --- a/include/oxen/quic/utils.hpp +++ b/include/oxen/quic/utils.hpp @@ -11,14 +11,16 @@ extern "C" #include #include #endif -#include #include + +#include } -#include #include #include +#include + #include #include #include @@ -52,11 +54,13 @@ namespace oxen::quic using connection_closed_callback = std::function; using namespace std::literals; - using bstring = std::basic_string; - using ustring = std::basic_string; - using bstring_view = std::basic_string_view; - using ustring_view = std::basic_string_view; - using stream_buffer = std::deque>>; + using namespace oxenc; + + using cspan = oxenc::const_span; + using uspan = oxenc::const_span; + using bspan = oxenc::const_span; + + using stream_buffer = std::deque>>; #ifdef _WIN32 inline constexpr bool IN_HELL = true; @@ -148,64 +152,48 @@ namespace oxen::quic namespace detail { - struct ustring_hasher + struct uspan_hasher { - size_t operator()(const ustring_view& sv) const noexcept + size_t operator()(const uspan& sp) const noexcept { - return std::hash{}({reinterpret_cast(sv.data()), sv.size()}); + return std::hash{}({reinterpret_cast(sp.data()), sp.size()}); } }; - template - struct bsv_literal + struct uspan_comp { - consteval bsv_literal(const char (&s)[N]) - { - for (size_t i = 0; i < N; i++) - str[i] = static_cast(s[i]); - } - std::byte str[N]; // we keep the null on the end, in case you pass .data() to a C func - using size = std::integral_constant; + bool operator()(const uspan& lhs, const uspan& rhs) const noexcept { return lhs == rhs; } }; - template - struct usv_literal + + template + inline const_span to_span(const In* data, size_t datalen) { - consteval usv_literal(const char (&s)[N]) - { - for (size_t i = 0; i < N; i++) - str[i] = static_cast(s[i]); - } - unsigned char str[N]; // we keep the null on the end, in case you pass .data() to a C func - using size = std::integral_constant; - }; + return {reinterpret_cast(data), datalen}; + } } // namespace detail - // strang literals - inline ustring operator""_us(const char* str, size_t len) noexcept - { - return {reinterpret_cast(str), len}; - } - template - constexpr ustring_view operator""_usv() + template + inline bspan str_to_bspan(const T& sv) { - return {UStr.str, decltype(UStr)::size::value}; + return detail::to_span(sv.data(), sv.size()); } - template - constexpr bstring_view operator""_bsv() + template + inline uspan str_to_uspan(const T& sv) { - return {BStr.str, decltype(BStr)::size::value}; + return detail::to_span(sv.data(), sv.size()); } - inline bstring operator""_bs(const char* str, size_t len) noexcept + + template + inline const_span vec_to_span(const std::vector& v) { - return {reinterpret_cast(str), len}; + return detail::to_span(v.data(), v.size()); } - template - requires std::same_as || std::same_as - inline std::string_view to_sv(SV x) + template + inline const_span span_to_span(const const_span& sp) { - return {reinterpret_cast(x.data()), x.size()}; + return detail::to_span(sp.data(), sp.size()); } std::chrono::steady_clock::time_point get_time(); @@ -255,12 +243,8 @@ namespace oxen::quic { void operator()(::event* e) const; }; - using event_ptr = std::unique_ptr<::event, event_deleter>; - inline ustring_view to_usv(std::string_view sv) - { - return {reinterpret_cast(sv.data()), sv.size()}; - } + using event_ptr = std::unique_ptr<::event, event_deleter>; // Stringview conversion function to interoperate between bstring_views and any other potential // user supplied type diff --git a/src/address.cpp b/src/address.cpp index f1f737a9..e55dc812 100644 --- a/src/address.cpp +++ b/src/address.cpp @@ -1,9 +1,9 @@ #include "address.hpp" -#include - #include "internal.hpp" +#include + namespace oxen::quic { Address::Address(const std::string& addr, uint16_t port) diff --git a/src/btstream.cpp b/src/btstream.cpp index 2a29d917..d177cab0 100644 --- a/src/btstream.cpp +++ b/src/btstream.cpp @@ -1,12 +1,12 @@ #include "btstream.hpp" -#include - #include "internal.hpp" +#include + namespace oxen::quic { - static std::pair get_location(bstring& data, std::string_view substr) + static std::pair get_location(std::vector& data, std::string_view substr) { auto* bsubstr = reinterpret_cast(substr.data()); // Make sure the given substr actually is a substr of data: @@ -14,12 +14,12 @@ namespace oxen::quic return {bsubstr - data.data(), substr.size()}; } - message::message(BTRequestStream& bp, bstring req, bool is_timeout) : + message::message(BTRequestStream& bp, std::vector req, bool is_timeout) : data{std::move(req)}, return_sender{bp.weak_from_this()}, _rid{bp.reference_id}, timed_out{is_timeout} { if (!is_timeout) { - oxenc::bt_list_consumer btlc(data); + oxenc::bt_list_consumer btlc(bspan{data}); req_type = get_location(data, btlc.consume_string_view()); req_id = btlc.consume_integer(); @@ -33,7 +33,7 @@ namespace oxen::quic } } - void message::respond(bstring_view body, bool error) const + void message::respond(bspan body, bool error) const { log::trace(log_cat, "{} called", __PRETTY_FUNCTION__); @@ -53,7 +53,7 @@ namespace oxen::quic log::debug(log_cat, "Bparser set generic request handler"); generic_handler = std::move(request_handler); } - void BTRequestStream::respond(int64_t rid, bstring_view body, bool error) + void BTRequestStream::respond(int64_t rid, bspan body, bool error) { log::trace(log_cat, "{} called", __PRETTY_FUNCTION__); @@ -89,7 +89,7 @@ namespace oxen::quic } } - void BTRequestStream::receive(bstring_view data) + void BTRequestStream::receive(bspan data) { log::trace(log_cat, "bparser recv data callback called!"); @@ -98,7 +98,7 @@ namespace oxen::quic try { - process_incoming(to_sv(data)); + process_incoming(data); } catch (const std::exception& e) { @@ -186,7 +186,7 @@ namespace oxen::quic catch (const no_such_endpoint&) { log::warning(log_cat, "No handler found for endpoint {}, returning error response", ep); - respond(req_id, convert_sv("Invalid endpoint '{}'"_format(ep)), true); + respond(req_id, str_to_bspan("Invalid endpoint '{}'"_format(ep)), true); } catch (const std::exception& e) { @@ -195,11 +195,11 @@ namespace oxen::quic "Handler for {} threw an uncaught exception ({}); returning a generic error message", ep, e.what()); - respond(req_id, "An error occurred while processing the request"_bsv, true); + respond(req_id, "An error occurred while processing the request"_bsp, true); } } - void BTRequestStream::process_incoming(std::string_view req) + void BTRequestStream::process_incoming(bspan req) { log::trace(log_cat, "{} called", __PRETTY_FUNCTION__); @@ -212,7 +212,8 @@ namespace oxen::quic if (not size_buf.empty()) { size_t prev_len = size_buf.size(); - size_buf += req.substr(0, MAX_REQ_LEN_ENCODED); + size_buf.resize(prev_len + MAX_REQ_LEN_ENCODED); + std::memcpy(size_buf.data() + prev_len, req.data(), MAX_REQ_LEN_ENCODED); consumed = parse_length(size_buf); @@ -220,18 +221,19 @@ namespace oxen::quic return; size_buf.clear(); - req.remove_prefix(consumed - prev_len); + req = req.subspan(consumed - prev_len); } else { - consumed = parse_length(convert_sv(req)); + consumed = parse_length(span_to_span(req)); if (consumed == 0) { - size_buf += req; + size_buf.resize(req.size()); + std::memcpy(size_buf.data(), req.data(), req.size()); return; } - req.remove_prefix(consumed); + req = req.subspan(consumed); } } @@ -245,8 +247,8 @@ namespace oxen::quic if (buf.size() < current_len) { size_t need = current_len - buf.size(); - buf += convert_sv(req.substr(0, need)); - req.remove_prefix(need); + buf.insert(buf.end(), req.begin(), req.begin() + need); + req = req.subspan(need); } handle_input(message{*this, std::move(buf)}); @@ -260,13 +262,13 @@ namespace oxen::quic // Otherwise we don't have enough data on hand for a complete request, so move what we // got to the buffer to be processed when the next incoming chunk of data arrives. - buf.reserve(current_len); - buf += convert_sv(req); + // buf.reserve(current_len); + buf.insert(buf.end(), req.begin(), req.end()); return; } } - std::string BTRequestStream::encode_command(std::string_view endpoint, int64_t rid, bstring_view body) + std::string BTRequestStream::encode_command(std::string_view endpoint, int64_t rid, bspan body) { oxenc::bt_list_producer btlp; @@ -278,7 +280,7 @@ namespace oxen::quic return std::move(btlp).str(); } - std::string BTRequestStream::encode_response(int64_t rid, bstring_view body, bool error) + std::string BTRequestStream::encode_response(int64_t rid, bspan body, bool error) { oxenc::bt_list_producer btlp; @@ -321,12 +323,12 @@ namespace oxen::quic Error: throws on invalid value */ - size_t BTRequestStream::parse_length(std::string_view req) + size_t BTRequestStream::parse_length(cspan req) { - auto pos = req.find_first_of(':'); + auto itr = std::find(req.begin(), req.end(), ':'); // request is incomplete with no readable request length - if (pos == std::string_view::npos) + if (itr == req.end()) { if (req.size() >= MAX_REQ_LEN_ENCODED) // we didn't find a valid length, but do have enough consumed for the maximum valid @@ -336,6 +338,8 @@ namespace oxen::quic return 0; } + size_t pos = std::distance(req.begin(), itr); + auto [ptr, ec] = std::from_chars(req.data(), req.data() + pos, current_len); const char* bad = nullptr; diff --git a/src/connection.cpp b/src/connection.cpp index 6937199c..68f47310 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -1,14 +1,5 @@ #include "connection.hpp" -#include -#include -#include -#include -#include -#include -#include -#include - #include "datagram.hpp" #include "endpoint.hpp" #include "error.hpp" @@ -18,6 +9,15 @@ #include "stream.hpp" #include "utils.hpp" +#include +#include +#include +#include +#include +#include +#include +#include + namespace oxen::quic { using namespace std::literals; @@ -380,7 +380,7 @@ namespace oxen::quic int Connection::recv_token(const uint8_t* token, size_t tokenlen) { // This should only be called by the client, and therefore this will always have a value - _endpoint.store_path_validation_token(_path.remote, {token, tokenlen}); + _endpoint.store_path_validation_token(_path.remote, {token, token + tokenlen}); return 0; } @@ -399,7 +399,7 @@ namespace oxen::quic } } - ustring data; + std::vector data; data.resize(256); if (auto len = ngtcp2_conn_encode_0rtt_transport_params(conn.get(), data.data(), data.size()); len > 0) @@ -455,7 +455,10 @@ namespace oxen::quic _is_validated = true; if (is_inbound() and not context->disable_key_verification) - remote_pubkey = dynamic_cast(get_session())->remote_key(); + { + auto key = detail::get_session(this)->remote_key(); + remote_pubkey.assign(key.begin(), key.end()); + } } int Connection::last_cleared() const @@ -488,7 +491,7 @@ namespace oxen::quic _associated_cids.erase(cid); } - ustring_view Connection::remote_key() const + uspan Connection::remote_key() const { return remote_pubkey; } @@ -1306,7 +1309,7 @@ namespace oxen::quic return NGTCP2_ERR_CALLBACK_FAILURE; } - int Connection::stream_receive(int64_t id, bstring_view data, bool fin) + int Connection::stream_receive(int64_t id, bspan data, bool fin) { auto str = get_stream(id); @@ -1385,11 +1388,11 @@ namespace oxen::quic return 0; } - int Connection::recv_datagram(bstring_view data, bool fin) + int Connection::recv_datagram(bspan data, bool fin) { log::trace(log_cat, "Connection (CID: {}) received datagram: {}", _source_cid, buffer_printer{data}); - std::optional maybe_data; + std::optional> maybe_data; if (_packet_splitting) { @@ -1400,7 +1403,7 @@ namespace oxen::quic } uint16_t dgid = oxenc::load_big_to_host(data.data()); - data.remove_prefix(2); + data = data.subspan(2); if (dgid % 4 == 0) log::trace(log_cat, "Datagram sent unsplit, bypassing rotating buffer"); @@ -1426,7 +1429,8 @@ namespace oxen::quic try { - datagrams->dgram_data_cb(*di, (maybe_data ? std::move(*maybe_data) : bstring{data.begin(), data.end()})); + datagrams->dgram_data_cb( + *di, (maybe_data ? std::move(*maybe_data) : std::vector{data.begin(), data.end()})); good = true; } catch (const std::exception& e) @@ -1463,12 +1467,12 @@ namespace oxen::quic return 0; } - ustring_view Connection::selected_alpn() const + uspan Connection::selected_alpn() const { return _endpoint.call_get([this]() { return get_session()->selected_alpn(); }); } - void Connection::send_datagram(bstring_view data, std::shared_ptr keep_alive) + void Connection::send_datagram(bspan data, std::shared_ptr keep_alive) { log::trace(log_cat, "{} called", __PRETTY_FUNCTION__); @@ -1611,9 +1615,9 @@ namespace oxen::quic const quic_cid& dcid, const Path& path, std::shared_ptr ctx, - const std::vector& alpns, + const std::vector>& alpns, std::chrono::nanoseconds default_handshake_timeout, - std::optional remote_pk, + std::optional> remote_pk, ngtcp2_pkt_hd* hdr, std::optional token_type, ngtcp2_cid* ocid) : @@ -1829,9 +1833,9 @@ namespace oxen::quic const quic_cid& dcid, const Path& path, std::shared_ptr ctx, - const std::vector& alpns, + const std::vector>& alpns, std::chrono::nanoseconds default_handshake_timeout, - std::optional remote_pk, + std::optional> remote_pk, ngtcp2_pkt_hd* hdr, std::optional token_type, ngtcp2_cid* ocid) diff --git a/src/connection_ids.cpp b/src/connection_ids.cpp index c8be2bb7..5f127eca 100644 --- a/src/connection_ids.cpp +++ b/src/connection_ids.cpp @@ -1,10 +1,10 @@ #include "connection_ids.hpp" -#include - #include "format.hpp" #include "internal.hpp" +#include + namespace oxen::quic { diff --git a/src/datagram.cpp b/src/datagram.cpp index 5ac6d147..9019cae8 100644 --- a/src/datagram.cpp +++ b/src/datagram.cpp @@ -74,12 +74,12 @@ namespace oxen::quic return ci.shared_from_this(); } - void dgram_interface::reply(bstring_view data, std::shared_ptr keep_alive) + void dgram_interface::reply(bspan data, std::shared_ptr keep_alive) { ci.send_datagram(data, std::move(keep_alive)); } - void DatagramIO::send_impl(bstring_view data, std::shared_ptr keep_alive) + void DatagramIO::send_impl(bspan data, std::shared_ptr keep_alive) { // if packet_splitting is lazy OR packet_splitting is off, send as "normal" datagram endpoint.call([this, data, keep_alive = std::move(keep_alive)]() { @@ -134,7 +134,7 @@ namespace oxen::quic return send_buffer.prepare(r, _packet_splitting); } - std::optional DatagramIO::to_buffer(bstring_view data, uint16_t dgid) + std::optional> DatagramIO::to_buffer(bspan data, uint16_t dgid) { log::trace(log_cat, "DatagramIO handed datagram with endian swapped ID: {}", dgid); diff --git a/src/endpoint.cpp b/src/endpoint.cpp index f5a2c9fc..273af11d 100644 --- a/src/endpoint.cpp +++ b/src/endpoint.cpp @@ -11,16 +11,16 @@ extern "C" #endif } -#include -#include -#include - #include "connection.hpp" #include "gnutls_crypto.hpp" #include "internal.hpp" #include "types.hpp" #include "utils.hpp" +#include +#include +#include + namespace oxen::quic { void Endpoint::handle_ep_opt(opt::enable_datagrams dc) @@ -36,20 +36,29 @@ namespace oxen::quic _packet_splitting ? "" : "no"); } - void Endpoint::handle_ep_opt(opt::outbound_alpns alpns) - { - outbound_alpns = std::move(alpns.alpns); - } - - void Endpoint::handle_ep_opt(opt::inbound_alpns alpns) - { - inbound_alpns = std::move(alpns.alpns); - } - void Endpoint::handle_ep_opt(opt::alpns alpns) { - inbound_alpns = std::move(alpns.inout_alpns); - outbound_alpns = inbound_alpns; + // Rather than overwriting the ALPNs that the endpoint holds, we emplace at the back of the vector. This allows the + // user to pass multiple values. For example, one can pass an I/O ALPNs value, followed by an outbound-specific ALPN + // and an inbound-specific ALPN + switch (alpns.direction) + { + case opt::alpns::DIR::I: + for (auto& a : alpns.protos) + inbound_alpns.emplace_back(std::move(a)); + break; + case opt::alpns::DIR::O: + for (auto& a : alpns.protos) + outbound_alpns.emplace_back(std::move(a)); + break; + case opt::alpns::DIR::IO: + for (auto& a : alpns.protos) + { + auto& e = inbound_alpns.emplace_back(std::move(a)); + outbound_alpns.emplace_back(e); + } + break; + } } void Endpoint::handle_ep_opt(opt::handshake_timeout timeout) @@ -92,7 +101,7 @@ namespace oxen::quic _0rtt_window = rtt.window.count(); _validate_0rtt_ticket = rtt.check ? std::move(rtt.check) : [this](gtls_ticket_ptr ticket, time_t current) -> bool { - auto key = ticket->key(); + auto key = ticket->span(); if (auto it = session_tickets.find(key); it != session_tickets.end()) { @@ -109,7 +118,7 @@ namespace oxen::quic return 0; }; - _get_session_ticket = rtt.fetch ? std::move(rtt.fetch) : [this](ustring_view key) -> gtls_ticket_ptr { + _get_session_ticket = rtt.fetch ? std::move(rtt.fetch) : [this](uspan key) -> gtls_ticket_ptr { gtls_ticket_ptr ret = nullptr; if (auto it = session_tickets.find(key); it != session_tickets.end()) { @@ -124,7 +133,7 @@ namespace oxen::quic }; _put_session_ticket = rtt.put ? std::move(rtt.put) : [this](gtls_ticket_ptr ticket, time_t /* exp */) { - auto key = ticket->key(); + auto key = ticket->span(); auto [_, b] = session_tickets.insert_or_assign(std::move(key), std::move(ticket)); log::debug( @@ -145,9 +154,9 @@ namespace oxen::quic return ConnectionID{++_next_rid}; } - ustring Endpoint::make_static_secret() + std::vector Endpoint::make_static_secret() { - ustring secret; + std::vector secret; secret.resize(32); gnutls_rnd(gnutls_rnd_level_t::GNUTLS_RND_KEY, secret.data(), secret.size()); return secret; @@ -203,7 +212,7 @@ namespace oxen::quic quic_cid qcid, ConnectionID rid, std::promise>& p, - std::optional pk) + std::optional> pk) { Path path = Path{_local, std::move(remote)}; @@ -541,19 +550,19 @@ namespace oxen::quic return _put_session_ticket(std::move(ticket), 0); } - gtls_ticket_ptr Endpoint::get_session_ticket(const ustring_view& remote_pk) + gtls_ticket_ptr Endpoint::get_session_ticket(const uspan& remote_pk) { log::trace(log_cat, "Fetching session ticket (remote key: {})...", buffer_printer{remote_pk}); return _get_session_ticket(remote_pk); } - void Endpoint::store_0rtt_transport_params(Address remote, ustring encoded_params) + void Endpoint::store_0rtt_transport_params(Address remote, std::vector encoded_params) { log::trace(log_cat, "Storing 0rtt tranpsport params..."); encoded_transport_params.insert_or_assign(std::move(remote), std::move(encoded_params)); } - std::optional Endpoint::get_0rtt_transport_params(const Address& remote) + std::optional> Endpoint::get_0rtt_transport_params(const Address& remote) { log::trace(log_cat, "Fetching 0rtt transport params..."); if (auto itr = encoded_transport_params.find(remote); itr != encoded_transport_params.end()) @@ -812,12 +821,12 @@ namespace oxen::quic send_or_queue_packet(pkt.path, std::move(buf), /* ecn */ 0); } - void Endpoint::store_path_validation_token(Address remote, ustring token) + void Endpoint::store_path_validation_token(Address remote, std::vector token) { path_validation_tokens.insert_or_assign(std::move(remote), std::move(token)); } - std::optional Endpoint::get_path_validation_token(const Address& remote) + std::optional> Endpoint::get_path_validation_token(const Address& remote) { if (auto itr = path_validation_tokens.find(remote); itr != path_validation_tokens.end()) return itr->second; @@ -999,7 +1008,7 @@ namespace oxen::quic if (_manual_routing) { - return _manual_routing(path, bstring_view{buf, *bufsize}, n_pkts); + return _manual_routing(path, bspan{buf, *bufsize}, n_pkts); } if (!socket) diff --git a/src/gnutls_creds.cpp b/src/gnutls_creds.cpp index b4dba679..6e589a0c 100644 --- a/src/gnutls_creds.cpp +++ b/src/gnutls_creds.cpp @@ -139,7 +139,7 @@ namespace oxen::quic } std::unique_ptr GNUTLSCreds::make_session( - Connection& c, const std::shared_ptr& ctx, const std::vector& alpns) + Connection& c, const std::shared_ptr& ctx, const std::vector>& alpns) { return std::make_unique(*this, ctx, c, alpns); } diff --git a/src/gnutls_session.cpp b/src/gnutls_session.cpp index 954fa9bf..a2a6deab 100644 --- a/src/gnutls_session.cpp +++ b/src/gnutls_session.cpp @@ -36,7 +36,7 @@ namespace oxen::quic if (htype == GNUTLS_HANDSHAKE_NEW_SESSION_TICKET) { log::debug(log_cat, "Client received new session ticket from server!"); - auto* conn = get_connection_from_gnutls(session); + auto* conn = detail::get_connection(session); auto remote_key = conn->remote_key(); auto& ep = conn->endpoint(); gtls_datum data{}, encoded{}; @@ -63,9 +63,9 @@ namespace oxen::quic int gtls_session_callbacks::cert_verify_callback_gnutls(gnutls_session_t session) { log::debug(log_cat, "{} called", __PRETTY_FUNCTION__); - auto* conn = get_connection_from_gnutls(session); + auto* conn = detail::get_connection(session); - GNUTLSSession* tls_session = dynamic_cast(conn->get_session()); + GNUTLSSession* tls_session = detail::get_session(conn); assert(tls_session); bool success = false; @@ -87,22 +87,30 @@ namespace oxen::quic return !success; } - Connection* get_connection_from_gnutls(gnutls_session_t g_session) + namespace detail { - auto* conn_ref = static_cast(gnutls_session_get_ptr(g_session)); - assert(conn_ref); - auto* conn = static_cast(conn_ref->user_data); - assert(conn); - return conn; - } + Connection* get_connection(gnutls_session_t g_session) + { + auto* conn_ref = static_cast(gnutls_session_get_ptr(g_session)); + assert(conn_ref); + auto* conn = static_cast(conn_ref->user_data); + assert(conn); + return conn; + } - GNUTLSSession* get_session_from_gnutls(gnutls_session_t g_session) - { - auto* conn = get_connection_from_gnutls(g_session); - GNUTLSSession* tls_session = dynamic_cast(conn->get_session()); - assert(tls_session); - return tls_session; - } + GNUTLSSession* get_session(gnutls_session_t g_session) + { + auto* conn = get_connection(g_session); + return get_session(conn); + } + + GNUTLSSession* get_session(Connection* conn) + { + GNUTLSSession* tls = dynamic_cast(conn->get_session()); + assert(tls); + return tls; + } + } // namespace detail GNUTLSSession::~GNUTLSSession() { @@ -118,7 +126,7 @@ namespace oxen::quic GNUTLSCreds& creds, const std::shared_ptr& ctx, Connection& c, - const std::vector& alpns, + const std::vector>& alpns, std::optional expected_key) : creds{creds}, _is_client{c.is_outbound()}, _0rtt_enabled{c.zero_rtt_enabled()} { @@ -242,7 +250,7 @@ namespace oxen::quic if (_0rtt_enabled and _expected_remote_key) { - if (auto maybe_ticket = c.endpoint().get_session_ticket(_expected_remote_key.view())) + if (auto maybe_ticket = c.endpoint().get_session_ticket(_expected_remote_key.span())) { gtls_datum d{}; @@ -287,7 +295,7 @@ namespace oxen::quic log::trace( log_cat, "GNUTLS adding \"{}\" to {} ALPNs", - to_sv(ustring_view{s.data(), s.size()}), + detail::to_span(s.data(), s.size()), direction_string); allowed_alpns.emplace_back( gnutls_datum_t{const_cast(s.data()), static_cast(s.size())}); @@ -454,7 +462,7 @@ namespace oxen::quic // provided a certificate and is only called by the server, we can assume the following returns: // true: the certificate was verified, and the connection is marked as validated // false: the certificate was not verified, and the connection is rejected - success = (creds.key_verify) ? creds.key_verify(_remote_key.view(), selected_alpn()) : true; + success = (creds.key_verify) ? creds.key_verify(_remote_key.span(), selected_alpn()) : true; return success; } diff --git a/src/internal.hpp b/src/internal.hpp index f0220c48..03f4bdbc 100644 --- a/src/internal.hpp +++ b/src/internal.hpp @@ -1,11 +1,12 @@ #pragma once -#include +#include "format.hpp" +#include "utils.hpp" + #include #include -#include "format.hpp" -#include "utils.hpp" +#include namespace oxen::quic { diff --git a/src/messages.cpp b/src/messages.cpp index 5a921fc9..c0cb34ee 100644 --- a/src/messages.cpp +++ b/src/messages.cpp @@ -13,7 +13,7 @@ namespace oxen::quic v.resize(rowsize); } - std::optional rotating_buffer::receive(bstring_view data, uint16_t dgid) + std::optional> rotating_buffer::receive(bspan data, uint16_t dgid) { log::trace(log_cat, "{} called", __PRETTY_FUNCTION__); @@ -58,17 +58,17 @@ namespace oxen::quic row, col); - bstring out; - out.reserve(b->data_size + data.size()); + std::vector out(b->data_size + data.size()); + if (b->part < 0) { // We have the first part already - out.append(b->data.data(), b->data_size); - out.append(data); + std::memcpy(out.data(), b->data.data(), b->data_size); + std::memcpy(out.data() + b->data_size, data.data(), data.size()); } else { - out.append(data); - out.append(b->data.data(), b->data_size); + std::memcpy(out.data() + b->data_size, data.data(), data.size()); + std::memcpy(out.data(), b->data.data(), b->data_size); } b.reset(); @@ -95,7 +95,7 @@ namespace oxen::quic return std::nullopt; } - void buffer_que::emplace(bstring_view pload, uint16_t p_id, std::shared_ptr data, dgram type, size_t max_size) + void buffer_que::emplace(bspan pload, uint16_t p_id, std::shared_ptr data, dgram type, size_t max_size) { auto d_storage = datagram_storage::make(pload, p_id, std::move(data), type, max_size); @@ -190,7 +190,7 @@ namespace oxen::quic } datagram_storage datagram_storage::make( - bstring_view pload, uint16_t d_id, std::shared_ptr data, dgram type, size_t max_size) + bspan pload, uint16_t d_id, std::shared_ptr data, dgram type, size_t max_size) { if (type == dgram::STANDARD) return datagram_storage(pload, d_id, std::move(data)); @@ -198,7 +198,7 @@ namespace oxen::quic assert(max_size != 0); auto half_size = max_size / 2; - auto first_half = pload.substr(0, half_size), second_half = pload.substr(half_size); + auto first_half = pload.subspan(0, half_size), second_half = pload.subspan(half_size); assert(d_id % 4 == 2); diff --git a/src/network.cpp b/src/network.cpp index 951ee2fd..6dc9d736 100644 --- a/src/network.cpp +++ b/src/network.cpp @@ -1,15 +1,15 @@ #include "network.hpp" +#include "connection.hpp" +#include "endpoint.hpp" +#include "internal.hpp" + #include #include #include #include #include -#include "connection.hpp" -#include "endpoint.hpp" -#include "internal.hpp" - namespace oxen::quic { caller_id_t Network::next_net_id = 0; diff --git a/src/stream.cpp b/src/stream.cpp index fe1e9360..2392c16b 100644 --- a/src/stream.cpp +++ b/src/stream.cpp @@ -5,10 +5,6 @@ extern "C" #include } -#include -#include -#include - #include "connection.hpp" #include "context.hpp" #include "endpoint.hpp" @@ -16,6 +12,10 @@ extern "C" #include "network.hpp" #include "types.hpp" +#include +#include +#include + namespace oxen::quic { Stream::Stream(Connection& conn, Endpoint& _ep, stream_data_callback data_cb, stream_close_callback close_cb) : @@ -206,7 +206,7 @@ namespace oxen::quic _is_closing = _is_shutdown = true; } - void Stream::append_buffer(bstring_view buffer, std::shared_ptr keep_alive) + void Stream::append_buffer(bspan buffer, std::shared_ptr keep_alive) { log::trace(log_cat, "{} called", __PRETTY_FUNCTION__); user_buffers.emplace_back(buffer, std::move(keep_alive)); @@ -236,7 +236,10 @@ namespace oxen::quic // advance bsv pointer to cover any remaining acked data if (bytes) - user_buffers.front().first.remove_prefix(bytes); + { + auto& front = user_buffers.front().first; + front = front.subspan(bytes); + } auto sz = size(); @@ -289,7 +292,7 @@ namespace oxen::quic _unacked_size += bytes; } - static auto get_buffer_it(std::deque>>& bufs, size_t offset) + static auto get_buffer_it(std::deque>>& bufs, size_t offset) { log::trace(log_cat, "{} called", __PRETTY_FUNCTION__); auto it = bufs.begin(); @@ -337,7 +340,7 @@ namespace oxen::quic return nbufs; } - void Stream::send_impl(bstring_view data, std::shared_ptr keep_alive) + void Stream::send_impl(bspan data, std::shared_ptr keep_alive) { if (data.empty()) return; diff --git a/src/udp.cpp b/src/udp.cpp index b74d06df..955d3cb1 100644 --- a/src/udp.cpp +++ b/src/udp.cpp @@ -18,11 +18,11 @@ extern "C" #endif } -#include - #include "internal.hpp" #include "udp.hpp" +#include + #ifdef _WIN32 #define CMSG_FIRSTHDR(h) WSA_CMSG_FIRSTHDR(h) @@ -291,7 +291,7 @@ namespace oxen::quic #endif } - void UDPSocket::process_packet(bstring_view payload, msghdr& hdr) + void UDPSocket::process_packet(bspan payload, msghdr& hdr) { if (payload.empty()) { @@ -368,7 +368,7 @@ namespace oxen::quic } for (int i = 0; i < nread; i++) - process_packet(bstring_view{data[i].data(), msgs[i].msg_len}, msgs[i].msg_hdr); + process_packet(bspan{data[i].data(), msgs[i].msg_len}, msgs[i].msg_hdr); count += nread; @@ -440,7 +440,7 @@ namespace oxen::quic } #endif - process_packet(bstring_view{data.data(), static_cast(nbytes)}, hdr); + process_packet(bspan{data.data(), static_cast(nbytes)}, hdr); count++; @@ -784,7 +784,7 @@ namespace oxen::quic event_add(wev_.get(), nullptr); } - Packet::Packet(const Address& local, bstring_view data, msghdr& hdr) : + Packet::Packet(const Address& local, bspan data, msghdr& hdr) : path{local, #ifdef _WIN32 {static_cast(hdr.name), hdr.namelen} diff --git a/src/utils.cpp b/src/utils.cpp index 1e005a28..da092f36 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -1,5 +1,8 @@ #include "utils.hpp" +#include "connection.hpp" +#include "internal.hpp" + #include #include @@ -7,9 +10,6 @@ #include #include -#include "connection.hpp" -#include "internal.hpp" - #ifdef _WIN32 #include #endif diff --git a/tests/001-handshake.cpp b/tests/001-handshake.cpp index 539f1f28..c7aa581c 100644 --- a/tests/001-handshake.cpp +++ b/tests/001-handshake.cpp @@ -1,10 +1,7 @@ -#include -#include -#include -#include - #include "utils.hpp" +#include + namespace oxen::quic::test { using namespace std::literals; @@ -424,7 +421,7 @@ namespace oxen::quic::test auto [client_tls, server_tls] = defaults::tls_creds_from_ed_keys(); - server_tls->set_key_verify_callback([](const ustring_view& key, const ustring_view&) { + server_tls->set_key_verify_callback([](const uspan& key, const uspan&) { return key == convert_sv(std::string_view{defaults::CLIENT_PUBKEY}); }); @@ -447,8 +444,8 @@ namespace oxen::quic::test auto& server_ci = server_cis.front(); CHECK(client_ci->is_validated()); CHECK(server_ci->is_validated()); - CHECK(server_ci->remote_key() == ustring{reinterpret_cast(defaults::CLIENT_PUBKEY.data()), - defaults::CLIENT_PUBKEY.length()}); + + CHECK(server_ci->remote_key() == str_to_uspan(defaults::CLIENT_PUBKEY)); } TEST_CASE("001 - Handshaking: Types - IPv6", "[001][ipv6]") @@ -635,15 +632,14 @@ namespace oxen::quic::test return defer_to_incoming; }; - server_tls->set_key_verify_callback([&](const ustring_view& key, const ustring_view&) { + server_tls->set_key_verify_callback([&](const uspan& key, const uspan&) { std::lock_guard lock{ci_mutex}; return defer_hook({reinterpret_cast(key.data()), key.size()}, S_PUBKEY, C_PUBKEY, server_ci); }); - client_tls->set_key_verify_callback([&](const ustring_view& key, const ustring_view&) { + client_tls->set_key_verify_callback([&](const uspan& key, const uspan&) { std::lock_guard lock{ci_mutex}; - return defer_hook( - std::string{reinterpret_cast(key.data()), key.size()}, C_PUBKEY, S_PUBKEY, client_ci); + return defer_hook(sp_to_sv(key), C_PUBKEY, S_PUBKEY, client_ci); }); Address server_local{}; diff --git a/tests/002-send-receive.cpp b/tests/002-send-receive.cpp index cc9af152..acb4dbcb 100644 --- a/tests/002-send-receive.cpp +++ b/tests/002-send-receive.cpp @@ -1,10 +1,3 @@ -#include -#include -#include -#include -#include -#include - #include "utils.hpp" namespace oxen::quic::test @@ -14,12 +7,12 @@ namespace oxen::quic::test TEST_CASE("002 - Simple client to server transmission", "[002][simple][execute]") { Network test_net{}; - constexpr auto good_msg = "hello from the other siiiii-iiiiide"_bsv; + constexpr auto good_msg = "hello from the other siiiii-iiiiide"_bsp; std::promise d_promise; std::future d_future = d_promise.get_future(); - stream_data_callback server_data_cb = [&](Stream&, bstring_view dat) { + stream_data_callback server_data_cb = [&](Stream&, bspan dat) { log::debug(test_cat, "Calling server stream data callback... data received..."); REQUIRE(good_msg == dat); d_promise.set_value(true); @@ -49,7 +42,7 @@ namespace oxen::quic::test TEST_CASE("002 - Simple client to server transmission", "[002][simple][bidirectional]") { Network test_net{}; - constexpr auto good_msg = "hello from the other siiiii-iiiiide"_bsv; + constexpr auto good_msg = "hello from the other siiiii-iiiiide"_bsp; std::vector> d_promises{2}; std::vector> d_futures{2}; @@ -59,7 +52,7 @@ namespace oxen::quic::test std::atomic index = 0; - stream_data_callback server_data_cb = [&](Stream&, bstring_view dat) { + stream_data_callback server_data_cb = [&](Stream&, bspan dat) { log::debug(test_cat, "Calling server stream data callback... data received..."); REQUIRE(good_msg == dat); d_promises.at(index).set_value(); @@ -101,7 +94,7 @@ namespace oxen::quic::test TEST_CASE("002 - Simple client to server transmission", "[002][simple][2x2]") { Network test_net{}; - constexpr auto good_msg = "hello from the other siiiii-iiiiide"_bsv; + constexpr auto good_msg = "hello from the other siiiii-iiiiide"_bsp; std::vector> d_promises{2}; std::vector> d_futures{2}; @@ -111,7 +104,7 @@ namespace oxen::quic::test std::atomic index = 0; - stream_data_callback server_data_cb = [&](Stream&, bstring_view dat) { + stream_data_callback server_data_cb = [&](Stream&, bspan dat) { log::debug(test_cat, "Calling server stream data callback... data received..."); REQUIRE(good_msg == dat); d_promises.at(index).set_value(); @@ -150,8 +143,8 @@ namespace oxen::quic::test TEST_CASE("002 - Client to server transmission, larger string ownership", "[002][simple][larger][ownership]") { Network test_net{}; - bstring good_msg; - good_msg.reserve(2600); + std::vector good_msg(2600); + for (int i = 0; i < 100; i++) for (char c = 'a'; c <= 'z'; c++) good_msg.push_back(static_cast(c)); @@ -161,18 +154,24 @@ namespace oxen::quic::test int good = 0, bad = 0; std::promise done_receiving; - stream_data_callback server_data_cb = [&](Stream&, bstring_view dat) { + stream_data_callback server_data_cb = [&](Stream&, bspan dat) { log::debug(test_cat, "Server stream data callback -- data received (len {})", dat.size()); - static bstring partial; - partial.append(dat); + + static std::vector partial; + partial.insert(partial.end(), dat.begin(), dat.end()); + if (partial.size() < good_msg.size()) return; + std::lock_guard lock{received_mut}; - if (bstring_view{partial}.substr(0, good_msg.size()) == good_msg) + if (bspan{partial.data(), good_msg.size()} == good_msg) good++; else bad++; - partial = partial.substr(good_msg.size()); + + std::vector replace{std::next(partial.begin(), good_msg.size()), partial.end()}; + partial = std::move(replace); + if (good + bad >= tests) done_receiving.set_value(); }; @@ -192,33 +191,33 @@ namespace oxen::quic::test auto conn_to_a = server_endpoint_b->connect(server_remote_a, server_tls); auto stream_to_a = conn_to_a->open_stream(); - SECTION("Sending bstring_view of long-lived buffer") + SECTION("Sending bspan of long-lived buffer") { for (int i = 0; i < tests; i++) { // There is no ownership issue here: we're just viewing into our `good_msg` which we // are keeping alive already for the duration of this test. - stream_to_a->send(bstring_view{good_msg}); + stream_to_a->send(good_msg); } } - SECTION("Sending bstring buffer with transferred ownership") + SECTION("Sending std::vector buffer with transferred ownership") { for (int i = 0; i < tests; i++) { // Deliberately construct a new temporary string here, and move it into `send()` to // transfer ownership of it off to the stream to manage: - bstring copy{good_msg}; + std::vector copy{good_msg}; stream_to_a->send(std::move(copy)); } } - SECTION("Sending bstring_view buffer with managed keep-alive") + SECTION("Sending bspan buffer with managed keep-alive") { for (int i = 0; i < tests; i++) { // Similar to the above, but keep the data alive via a manual shared_ptr keep-alive // object. - auto ptr = std::make_shared(good_msg); - stream_to_a->send(bstring_view{*ptr}, ptr); + auto ptr = std::make_shared>(good_msg); + stream_to_a->send(bspan{*ptr}, ptr); } } diff --git a/tests/003-multiclient.cpp b/tests/003-multiclient.cpp index 3c8eac86..777681a4 100644 --- a/tests/003-multiclient.cpp +++ b/tests/003-multiclient.cpp @@ -1,6 +1,3 @@ -#include -#include - #include "utils.hpp" namespace oxen::quic::test @@ -31,7 +28,7 @@ namespace oxen::quic::test TEST_CASE("003 - Multi-client to server transmission: Execution", "[003][multi-client][execute]") { Network test_net{}; - constexpr auto msg = "hello from the other siiiii-iiiiide"_bsv; + constexpr auto msg = "hello from the other siiiii-iiiiide"_bsp; std::atomic data_check{0}; std::vector> stream_promises{4}; @@ -49,7 +46,7 @@ namespace oxen::quic::test auto p_itr = stream_promises.begin(); - stream_data_callback server_data_cb = [&](Stream&, bstring_view) { + stream_data_callback server_data_cb = [&](Stream&, bspan) { log::debug(test_cat, "Calling server stream data callback... data received..."); data_check += 1; p_itr->set_value(); diff --git a/tests/004-streams.cpp b/tests/004-streams.cpp index 780854f7..0b1b6462 100644 --- a/tests/004-streams.cpp +++ b/tests/004-streams.cpp @@ -1,10 +1,3 @@ -#include -#include -#include -#include -#include -#include - #include "utils.hpp" namespace oxen::quic::test @@ -39,7 +32,7 @@ namespace oxen::quic::test TEST_CASE("004 - Multiple pending streams: streams available", "[004][streams][pending][config]") { Network test_net{}; - constexpr auto msg = "hello from the other siiiii-iiiiide"_bsv; + constexpr auto msg = "hello from the other siiiii-iiiiide"_bsp; std::promise data_promise; std::future data_future = data_promise.get_future(); @@ -48,7 +41,7 @@ namespace oxen::quic::test Address server_local{}; Address client_local{}; - stream_data_callback server_data_cb = [&](Stream&, bstring_view) { + stream_data_callback server_data_cb = [&](Stream&, bspan) { log::debug(test_cat, "Calling server stream data callback... data received..."); data_promise.set_value(); }; @@ -75,7 +68,7 @@ namespace oxen::quic::test auto client_established = callback_waiter{[](connection_interface&) {}}; Network test_net{}; - constexpr auto msg = "hello from the other siiiii-iiiiide"_bsv; + constexpr auto msg = "hello from the other siiiii-iiiiide"_bsp; std::promise data_promise; std::future data_future = data_promise.get_future(); @@ -86,7 +79,7 @@ namespace oxen::quic::test Address server_local{}; Address client_local{}; - stream_data_callback server_data_cb = [&](Stream&, bstring_view) { + stream_data_callback server_data_cb = [&](Stream&, bspan) { log::debug(test_cat, "Calling server stream data callback... data received..."); data_promise.set_value(); }; @@ -129,7 +122,7 @@ namespace oxen::quic::test auto client_established = callback_waiter{[](connection_interface&) {}}; Network test_net{}; - constexpr auto msg = "hello from the other siiiii-iiiiide"_bsv; + constexpr auto msg = "hello from the other siiiii-iiiiide"_bsp; std::atomic index{0}; std::atomic data_check{0}; @@ -151,7 +144,7 @@ namespace oxen::quic::test } send_futures[n_sends - 1] = send_promises[n_sends - 1].get_future(); - stream_data_callback server_data_cb = [&](Stream&, bstring_view) { + stream_data_callback server_data_cb = [&](Stream&, bspan) { log::debug(test_cat, "Calling server stream data callback... data received... incrementing counter..."); try @@ -235,7 +228,7 @@ namespace oxen::quic::test ClientStream(Connection& _c, Endpoint& _e, std::promise _p) : Stream{_c, _e}, p{std::move(_p)} {} - void receive(bstring_view) override + void receive(bspan) override { log::debug(test_cat, "Calling custom stream data callback... data received..."); p.set_value(); @@ -248,7 +241,7 @@ namespace oxen::quic::test ServerStream(Connection& _c, Endpoint& _e, std::promise _p) : Stream{_c, _e}, p{std::move(_p)} {} - void receive(bstring_view) override + void receive(bspan) override { log::debug(test_cat, "Calling custom stream data callback... data received..."); p.set_value(); @@ -258,20 +251,20 @@ namespace oxen::quic::test TEST_CASE("004 - Subclassing quic::stream, custom to standard", "[004][customstream][cross]") { Network test_net{}; - constexpr auto msg = "hello from the other siiiii-iiiiide"_bsv; + constexpr auto msg = "hello from the other siiiii-iiiiide"_bsp; std::promise ss_p, sc_p, cs_p, cc_p; std::future ss_f = ss_p.get_future(), sc_f = sc_p.get_future(), cs_f = cs_p.get_future(), cc_f = cc_p.get_future(); - stream_data_callback standard_server_cb = [&](Stream& s, bstring_view dat) { + stream_data_callback standard_server_cb = [&](Stream& s, bspan dat) { log::debug(test_cat, "Calling standard stream data callback... data received..."); REQUIRE(msg == dat); ss_p.set_value(); s.send(msg); }; - stream_data_callback standard_client_cb = [&](Stream& s, bstring_view dat) { + stream_data_callback standard_client_cb = [&](Stream& s, bspan dat) { log::debug(test_cat, "Calling standard stream data callback... data received..."); REQUIRE(msg == dat); cs_p.set_value(); @@ -310,7 +303,7 @@ namespace oxen::quic::test TEST_CASE("004 - Subclassing quic::stream, custom to custom", "[004][customstream][subclass]") { Network test_net{}; - constexpr auto msg = "hello from the other siiiii-iiiiide"_bsv; + constexpr auto msg = "hello from the other siiiii-iiiiide"_bsp; std::promise server_promise, client_promise; std::future server_future = server_promise.get_future(); @@ -345,14 +338,14 @@ namespace oxen::quic::test struct CustomStream : public Stream { - std::promise p; + std::promise p; - CustomStream(Connection& _c, Endpoint& _e, std::promise _p) : Stream{_c, _e}, p{std::move(_p)} {} + CustomStream(Connection& _c, Endpoint& _e, std::promise _p) : Stream{_c, _e}, p{std::move(_p)} {} - void receive(bstring_view m) override + void receive(bspan m) override { log::info(test_cat, "Custom stream received data:\n{}", buffer_printer{m}); - p.set_value(std::string{convert_sv(m)}); + p.set_value(m); } }; @@ -375,10 +368,9 @@ namespace oxen::quic::test { Network test_net{}; - std::promise sp1, sp2, sp3, sp4, cp1, cp2, cp3; - std::future sf1 = sp1.get_future(), sf2 = sp2.get_future(), sf3 = sp3.get_future(), - sf4 = sp4.get_future(), cf1 = cp1.get_future(), cf2 = cp2.get_future(), - cf3 = cp3.get_future(); + std::promise sp1, sp2, sp3, sp4, cp1, cp2, cp3; + std::future sf1 = sp1.get_future(), sf2 = sp2.get_future(), sf3 = sp3.get_future(), sf4 = sp4.get_future(), + cf1 = cp1.get_future(), cf2 = cp2.get_future(), cf3 = cp3.get_future(); std::shared_ptr server_a, client_a; std::shared_ptr server_b, client_b; @@ -388,9 +380,9 @@ namespace oxen::quic::test auto client_established = callback_waiter{[](connection_interface&) {}}; auto server_closed = callback_waiter{[](connection_interface&, uint64_t) {}}; - stream_data_callback server_generic_data_cb = [&](Stream&, bstring_view m) { + stream_data_callback server_generic_data_cb = [&](Stream&, bspan m) { log::debug(test_cat, "Server generic data callback called"); - sp4.set_value(std::string{convert_sv(m)}); + sp4.set_value(m); }; auto [client_tls, server_tls] = defaults::tls_creds_from_ed_keys(); @@ -516,26 +508,26 @@ namespace oxen::quic::test log::info(test_cat, "Client opening Custom Stream A!"); client_a = client_ci->open_stream(std::move(cp1)); - REQUIRE_NOTHROW(client_a->send("Stream A!"_bs)); + REQUIRE_NOTHROW(client_a->send("Stream A!"_bsp)); require_future(sf1); - CHECK(sf1.get() == "Stream A!"); + CHECK(sf1.get() == "Stream A!"_bsp); log::info(test_cat, "Client opening Custom Stream B!"); client_b = client_ci->open_stream(std::move(cp2)); - REQUIRE_NOTHROW(client_b->send("Stream B!"_bs)); + REQUIRE_NOTHROW(client_b->send("Stream B!"_bsp)); require_future(sf2); - CHECK(sf2.get() == "Stream B!"); + CHECK(sf2.get() == "Stream B!"_bsp); log::info(test_cat, "Client opening Custom Stream C!"); client_c = client_ci->open_stream(std::move(cp3)); - REQUIRE_NOTHROW(client_c->send("Stream C!"_bs)); + REQUIRE_NOTHROW(client_c->send("Stream C!"_bsp)); require_future(sf3); - CHECK(sf3.get() == "Stream C!"); + CHECK(sf3.get() == "Stream C!"_bsp); client_d = client_ci->open_stream(); - client_d->send("Stream d!"_bs); + client_d->send("Stream d!"_bsp); require_future(sf4); - CHECK(sf4.get() == "Stream d!"); + CHECK(sf4.get() == "Stream d!"_bsp); client_ci->close_connection(); REQUIRE(server_closed.wait()); @@ -558,9 +550,9 @@ namespace oxen::quic::test RemoteAddress client_remote{defaults::SERVER_PUBKEY, LOCALHOST, server_endpoint->local().port()}; auto client_ci = client_endpoint->connect(client_remote, client_tls); - auto a = client_ci->open_stream(std::promise{}); - auto b = client_ci->open_stream(std::promise{}); - auto c = client_ci->open_stream(std::promise{}); + auto a = client_ci->open_stream(std::promise{}); + auto b = client_ci->open_stream(std::promise{}); + auto c = client_ci->open_stream(std::promise{}); auto d = client_ci->open_stream(); // On slower setups, a small amount of time is needed to finish initializing all the streams @@ -608,14 +600,13 @@ namespace oxen::quic::test std::mutex mut; std::map server_seen; - std::promise cp1, cp2, cp3, cp4; - std::future cf1 = cp1.get_future(), cf2 = cp2.get_future(), cf3 = cp3.get_future(), - cf4 = cp4.get_future(); + std::promise cp1, cp2, cp3, cp4; + std::future cf1 = cp1.get_future(), cf2 = cp2.get_future(), cf3 = cp3.get_future(), cf4 = cp4.get_future(); auto client_established = callback_waiter{[](connection_interface&) {}}; auto server_closed = callback_waiter{[](connection_interface&, uint64_t) {}}; - stream_data_callback server_data_cb = [&](Stream& s, bstring_view) { + stream_data_callback server_data_cb = [&](Stream& s, bspan) { std::lock_guard lock{mut}; server_seen[s.stream_id()]++; s.send("🤔 {}"_format(s.stream_id())); @@ -649,9 +640,9 @@ namespace oxen::quic::test return nullptr; }; - auto client_generic_data_cb = [&](Stream&, bstring_view data) { + auto client_generic_data_cb = [&](Stream&, bspan data) { log::debug(test_cat, "Client generic data callback called"); - cp4.set_value(std::string{convert_sv(data)}); + cp4.set_value(data); }; RemoteAddress client_remote{defaults::SERVER_PUBKEY, LOCALHOST, server_endpoint->local().port()}; @@ -678,19 +669,19 @@ namespace oxen::quic::test // This should be a generic Stream, not a CustomStreamA/B/C: REQUIRE_FALSE(std::dynamic_pointer_cast(s4)); - s1->send("Stream A!"_bs); - s2->send("Stream B!"_bs); - s3->send("Stream C!"_bs); - s4->send("Stream D!"_bs); + s1->send("Stream A!"_bsp); + s2->send("Stream B!"_bsp); + s3->send("Stream C!"_bsp); + s4->send("Stream D!"_bsp); require_future(cf1); require_future(cf2); require_future(cf3); require_future(cf4); - CHECK(cf1.get() == "🤔 0"); - CHECK(cf2.get() == "🤔 4"); - CHECK(cf3.get() == "🤔 8"); - CHECK(cf4.get() == "🤔 12"); + CHECK(cf1.get() == "🤔 0"_bsp); + CHECK(cf2.get() == "🤔 4"_bsp); + CHECK(cf3.get() == "🤔 8"_bsp); + CHECK(cf4.get() == "🤔 12"_bsp); { std::lock_guard lock{mut}; @@ -860,7 +851,7 @@ namespace oxen::quic::test REQUIRE(msg.body() == TEST_BODY); }}; - server_tls->set_key_verify_callback([&](const ustring_view&, const ustring_view&) { + server_tls->set_key_verify_callback([&](const uspan&, const uspan&) { // In order to test the queueing ability of streams, we need to attempt to send things // from the client side PRIOR to connection completion. Using the TLS verification callback // is the improper and hacky way to do this, but will function fine for the purposes of this @@ -922,9 +913,9 @@ namespace oxen::quic::test int count = 0; auto server_endpoint = test_net.endpoint(server_local); - server_endpoint->listen(server_tls, [&](Stream& s, bstring_view data) { + server_endpoint->listen(server_tls, [&](Stream& s, bspan data) { count += data.size(); - log::debug(test_cat, "Got some data {}, replying with '{}'", to_sv(data), count); + log::debug(test_cat, "Got some data {}, replying with '{}'", data, count); s.send("{}"_format(count)); }); @@ -942,8 +933,8 @@ namespace oxen::quic::test }; auto conn = client_endpoint->connect(client_remote, client_tls, conn_closed); - auto stream_data_cb = [&](Stream&, bstring_view data) { - REQUIRE(data == "11"_bsv); + auto stream_data_cb = [&](Stream&, bspan data) { + REQUIRE(data == "11"_bsp); got_reply.set_value(); }; auto stream_close_cb = [&](Stream&, uint64_t) { got_closed.set_value(); }; @@ -973,7 +964,7 @@ namespace oxen::quic::test auto [client_tls, server_tls] = defaults::tls_creds_from_ed_keys(); auto server_endpoint = test_net.endpoint(server_local); - server_endpoint->listen(server_tls, [&](Stream& s, bstring_view data) { s.send(data); }); + server_endpoint->listen(server_tls, [&](Stream& s, bspan data) { s.send(data); }); RemoteAddress client_remote{defaults::SERVER_PUBKEY, LOCALHOST, server_endpoint->local().port()}; auto client_endpoint = test_net.endpoint(client_local); @@ -981,7 +972,7 @@ namespace oxen::quic::test std::promise got_data; { auto conn = client_endpoint->connect(client_remote, client_tls); - auto s = conn->open_stream([&](Stream& s, bstring_view) { + auto s = conn->open_stream([&](Stream& s, bspan) { if (auto conn = s.endpoint.get_conn(s.reference_id)) conn->close_connection(); diff --git a/tests/005-chunked-sender.cpp b/tests/005-chunked-sender.cpp index 76e35c6b..18d8478f 100644 --- a/tests/005-chunked-sender.cpp +++ b/tests/005-chunked-sender.cpp @@ -1,9 +1,7 @@ -#include -#include -#include - #include "utils.hpp" +#include + namespace oxen::quic::test { using namespace std::literals; @@ -20,7 +18,7 @@ namespace oxen::quic::test std::promise finished_p; std::future finished_f = finished_p.get_future(); - stream_data_callback server_data_cb = [&](Stream&, bstring_view data) { + stream_data_callback server_data_cb = [&](Stream&, bspan data) { std::lock_guard lock{recv_mut}; received.append(reinterpret_cast(data.data()), data.size()); diff --git a/tests/006-server-send.cpp b/tests/006-server-send.cpp index d45303c7..e6584676 100644 --- a/tests/006-server-send.cpp +++ b/tests/006-server-send.cpp @@ -1,6 +1,3 @@ -#include -#include - #include "utils.hpp" namespace oxen::quic::test @@ -10,7 +7,7 @@ namespace oxen::quic::test TEST_CASE("006 - Server streams: Direct creation and transmission", "[006][server][streams][send][execute]") { Network test_net{}; - constexpr auto msg = "hello from the other siiiii-iiiiide"_bsv; + constexpr auto msg = "hello from the other siiiii-iiiiide"_bsp; std::atomic data_check{0}; @@ -27,13 +24,13 @@ namespace oxen::quic::test return 0; }; - stream_data_callback server_io_data_cb = [&](IOChannel&, bstring_view) { + stream_data_callback server_io_data_cb = [&](IOChannel&, bspan) { log::debug(test_cat, "Calling server stream data callback... data received... incrementing counter..."); data_check += 1; server_promise.set_value(); }; - stream_data_callback client_io_data_cb = [&](IOChannel&, bstring_view) { + stream_data_callback client_io_data_cb = [&](IOChannel&, bspan) { log::debug(test_cat, "Calling client stream data callback... data received... incrementing counter..."); data_check += 1; client_promise.set_value(); @@ -67,8 +64,8 @@ namespace oxen::quic::test TEST_CASE("006 - Server streams: Remote initiation, server send", "[006][server][streams][send][execute]") { Network test_net{}; - constexpr auto msg = "hello from the other siiiii-iiiiide"_bsv; - constexpr auto response = "okay okay i get it already"_bsv; + constexpr auto msg = "hello from the other siiiii-iiiiide"_bsp; + constexpr auto response = "okay okay i get it already"_bsp; std::atomic ci{0}, si{0}; std::atomic data_check{0}; @@ -115,7 +112,7 @@ namespace oxen::quic::test return 0; }; - stream_data_callback server_io_data_cb = [&](Stream&, bstring_view) { + stream_data_callback server_io_data_cb = [&](Stream&, bspan) { log::debug(test_cat, "Calling server stream data callback... data received... incrementing counter..."); data_check += 1; try @@ -129,7 +126,7 @@ namespace oxen::quic::test } }; - stream_data_callback client_io_data_cb = [&](Stream&, bstring_view) { + stream_data_callback client_io_data_cb = [&](Stream&, bspan) { log::debug(test_cat, "Calling client stream data callback... data received... incrementing counter..."); data_check += 1; try diff --git a/tests/007-datagrams.cpp b/tests/007-datagrams.cpp index 96df3579..ea4131b1 100644 --- a/tests/007-datagrams.cpp +++ b/tests/007-datagrams.cpp @@ -1,14 +1,3 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - #include "utils.hpp" namespace oxen::quic::test @@ -153,18 +142,18 @@ namespace oxen::quic::test auto client_established = callback_waiter{[](connection_interface&) {}}; Network test_net{}; - constexpr auto msg = "hello from the other siiiii-iiiiide"_bsv; + constexpr auto msg = "hello from the other siiiii-iiiiide"_bsp; std::promise data_promise; std::future data_future = data_promise.get_future(); - dgram_data_callback recv_dgram_cb = [&](dgram_interface&, bstring) { + dgram_data_callback recv_dgram_cb = [&](dgram_interface&, std::vector) { log::debug(test_cat, "Calling endpoint receive datagram callback... data received..."); data_promise.set_value(); }; std::atomic bad_call = false; - dgram_data_callback overridden_dgram_cb = [&](dgram_interface&, bstring) { + dgram_data_callback overridden_dgram_cb = [&](dgram_interface&, std::vector) { log::critical(test_cat, "Wrong dgram callback invoked!"); bad_call = true; }; @@ -214,10 +203,10 @@ namespace oxen::quic::test std::promise data_promise; std::future data_future = data_promise.get_future(); - dgram_data_callback recv_dgram_cb = [&](dgram_interface&, bstring data) { + dgram_data_callback recv_dgram_cb = [&](dgram_interface&, std::vector data) { log::debug(test_cat, "Calling endpoint receive datagram callback... data received..."); ++data_counter; - if (data == "final"_bs) + if (data == "final"_bsp) data_promise.set_value(); }; @@ -302,7 +291,7 @@ namespace oxen::quic::test for (int i = 0; i < n; ++i) data_futures[i] = data_promises[i].get_future(); - dgram_data_callback recv_dgram_cb = [&](dgram_interface&, bstring) { + dgram_data_callback recv_dgram_cb = [&](dgram_interface&, std::vector) { log::debug(test_cat, "Calling endpoint receive datagram callback... data received..."); try @@ -386,7 +375,7 @@ namespace oxen::quic::test for (size_t i = 0; i < n; ++i) data_futures[i] = data_promises[i].get_future(); - dgram_data_callback recv_dgram_cb = [&](dgram_interface&, bstring) { + dgram_data_callback recv_dgram_cb = [&](dgram_interface&, std::vector) { log::debug(test_cat, "Calling endpoint receive datagram callback... data received..."); try @@ -470,9 +459,9 @@ namespace oxen::quic::test for (int i = 0; i < bufsize; ++i) data_futures[i] = data_promises[i].get_future(); - bstring received{}; + std::vector received{}; - dgram_data_callback recv_dgram_cb = [&](dgram_interface&, bstring data) { + dgram_data_callback recv_dgram_cb = [&](dgram_interface&, std::vector data) { log::debug(test_cat, "Calling endpoint receive datagram callback... data received..."); counter += 1; @@ -508,13 +497,13 @@ namespace oxen::quic::test auto server_ci = server_endpoint->get_all_conns(Direction::INBOUND).front(); - bstring dropped_msg(1500, std::byte{'-'}); - bstring successful_msg(1500, std::byte{'+'}); + std::vector dropped_msg(1500, std::byte{'-'}); + std::vector successful_msg(1500, std::byte{'+'}); TestHelper::enable_dgram_drop(static_cast(*server_ci)); for (int i = 0; i < quarter; ++i) - conn_interface->send_datagram(bstring_view{dropped_msg}); + conn_interface->send_datagram(bspan{dropped_msg}); while (TestHelper::get_dgram_debug_counter(*server_ci) < quarter) std::this_thread::sleep_for(10ms); @@ -522,7 +511,7 @@ namespace oxen::quic::test TestHelper::disable_dgram_drop(*server_ci); for (int i = 0; i < bufsize; ++i) - conn_interface->send_datagram(bstring_view{successful_msg}); + conn_interface->send_datagram(bspan{successful_msg}); for (auto& f : data_futures) require_future(f); @@ -560,7 +549,7 @@ namespace oxen::quic::test for (size_t i = 0; i < n; ++i) data_futures[i] = data_promises[i].get_future(); - dgram_data_callback recv_dgram_cb = [&](dgram_interface&, bstring) { + dgram_data_callback recv_dgram_cb = [&](dgram_interface&, std::vector) { log::debug(test_cat, "Calling endpoint receive datagram callback... data received..."); try diff --git a/tests/008-conn_hooks.cpp b/tests/008-conn_hooks.cpp index e4866e31..216f0d1a 100644 --- a/tests/008-conn_hooks.cpp +++ b/tests/008-conn_hooks.cpp @@ -1,6 +1,3 @@ -#include -#include - #include "utils.hpp" namespace oxen::quic::test diff --git a/tests/009-alpns.cpp b/tests/009-alpns.cpp index f8a7ad35..dbef7570 100644 --- a/tests/009-alpns.cpp +++ b/tests/009-alpns.cpp @@ -1,10 +1,3 @@ -#include - -#include -#include -#include -#include - #include "utils.hpp" namespace oxen::quic::test @@ -38,12 +31,12 @@ namespace oxen::quic::test auto conn = client_endpoint->connect(client_remote, client_tls); REQUIRE(client_established.wait()); - REQUIRE(conn->selected_alpn() == "default"_usv); + REQUIRE(conn->selected_alpn() == "default"_usp); } SECTION("No Server ALPNs specified (defaulted)") { - opt::outbound_alpns client_alpns{{"client"_us}}; + opt::alpns client_alpns{opt::alpns::DIR::O, "client"_usp}; auto server_endpoint = test_net.endpoint(server_local, timeout); REQUIRE_NOTHROW(server_endpoint->listen(server_tls)); @@ -59,7 +52,7 @@ namespace oxen::quic::test SECTION("No Client ALPNs specified (defaulted)") { - opt::inbound_alpns server_alpns{{"client"_us, "relay"_us}}; + opt::alpns server_alpns{opt::alpns::DIR::I, "client"_usp, "relay"_usp}; auto server_endpoint = test_net.endpoint(server_local, server_alpns, timeout); REQUIRE_NOTHROW(server_endpoint->listen(server_tls)); @@ -75,8 +68,8 @@ namespace oxen::quic::test SECTION("Client ALPNs not supported") { - opt::inbound_alpns server_alpns{{"client"_us, "relay"_us}}; - opt::outbound_alpns client_alpns{{"foobar"_us}}; + opt::alpns server_alpns{opt::alpns::DIR::I, "client"_usp, "relay"_usp}; + opt::alpns client_alpns{opt::alpns::DIR::O, "foobar"_usp}; auto server_endpoint = test_net.endpoint(server_local, server_alpns, timeout); REQUIRE_NOTHROW(server_endpoint->listen(server_tls)); @@ -92,9 +85,9 @@ namespace oxen::quic::test SECTION("Select first ALPN both sides support") { - opt::inbound_alpns server_alpns{{"client"_us, "relay"_us}}; - opt::outbound_alpns client_alpns{{"client"_us}}; - opt::outbound_alpns client_alpns2{{"relay"_us}}; + opt::alpns server_alpns{opt::alpns::DIR::I, "client"_usp, "relay"_usp}; + opt::alpns client_alpns{opt::alpns::DIR::O, "client"_usp}; + opt::alpns client_alpns2{opt::alpns::DIR::O, "relay"_usp}; auto server_endpoint = test_net.endpoint(server_local, server_alpns, timeout); REQUIRE_NOTHROW(server_endpoint->listen(server_tls)); @@ -105,25 +98,25 @@ namespace oxen::quic::test auto conn = client_endpoint->connect(client_remote, client_tls); REQUIRE(client_established.wait()); - REQUIRE(conn->selected_alpn() == "client"_usv); + REQUIRE(conn->selected_alpn() == "client"_usp); auto client_endpoint2 = test_net.endpoint(client_local, client_established2, client_alpns2, timeout); auto conn2 = client_endpoint2->connect(client_remote, client_tls); REQUIRE(client_established2.wait()); - REQUIRE(conn2->selected_alpn() == "relay"_usv); + REQUIRE(conn2->selected_alpn() == "relay"_usp); } SECTION("Bidirectional ALPN incoming") { - opt::alpns server_alpns{"special-alpn"}; + opt::alpns server_alpns{opt::alpns::DIR::IO, "special-alpn"_usp}; auto server_endpoint = test_net.endpoint(server_local, server_alpns, timeout); REQUIRE_NOTHROW(server_endpoint->listen(server_tls)); RemoteAddress client_remote{defaults::SERVER_PUBKEY, LOCALHOST, server_endpoint->local().port()}; - opt::outbound_alpns client_alpns{{"foobar"_us}}; + opt::alpns client_alpns{opt::alpns::DIR::O, "foobar"_usp}; auto client_endpoint = test_net.endpoint(client_local, client_established, client_closed, client_alpns, timeout); auto conn = client_endpoint->connect(client_remote, client_tls); @@ -133,19 +126,19 @@ namespace oxen::quic::test SECTION("Bidirectional ALPN outgoing") { - opt::inbound_alpns server_alpns{"special-alpn"}; + opt::alpns server_alpns{opt::alpns::DIR::I, "special-alpn"_usp}; auto server_endpoint = test_net.endpoint(server_local, server_alpns, timeout); REQUIRE_NOTHROW(server_endpoint->listen(server_tls)); RemoteAddress client_remote{defaults::SERVER_PUBKEY, LOCALHOST, server_endpoint->local().port()}; - opt::alpns client_alpns{"special-alpn"}; + opt::alpns client_alpns{opt::alpns::DIR::IO, "special-alpn"_usp}; auto client_endpoint = test_net.endpoint(client_local, client_established, client_alpns, timeout); auto conn = client_endpoint->connect(client_remote, client_tls); REQUIRE(client_established.wait()); - REQUIRE(conn->selected_alpn() == "special-alpn"_usv); + REQUIRE(conn->selected_alpn() == "special-alpn"_usp); } } diff --git a/tests/010-migration.cpp b/tests/010-migration.cpp index e5732422..e614ea2f 100644 --- a/tests/010-migration.cpp +++ b/tests/010-migration.cpp @@ -1,8 +1,3 @@ -#include -#include -#include -#include - #include "utils.hpp" namespace oxen::quic::test @@ -10,7 +5,7 @@ namespace oxen::quic::test TEST_CASE("010 - Migration", "[010][migration]") { Network test_net{}; - constexpr auto good_msg = "hello from the other siiiii-iiiiide"_bsv; + constexpr auto good_msg = "hello from the other siiiii-iiiiide"_bsp; auto [client_tls, server_tls] = defaults::tls_creds_from_ed_keys(); @@ -30,7 +25,7 @@ namespace oxen::quic::test std::shared_ptr client_endpoint; std::shared_ptr server_ci; - stream_data_callback server_data_cb = [&](Stream&, bstring_view dat) { + stream_data_callback server_data_cb = [&](Stream&, bspan dat) { log::debug(test_cat, "Calling server stream data callback... data received..."); REQUIRE(good_msg == dat); d_promise.set_value(); diff --git a/tests/011-manual_transmission.cpp b/tests/011-manual_transmission.cpp index d11f87d2..dce916d8 100644 --- a/tests/011-manual_transmission.cpp +++ b/tests/011-manual_transmission.cpp @@ -1,8 +1,3 @@ -#include -#include -#include -#include - #include "utils.hpp" namespace oxen::quic::test @@ -13,12 +8,12 @@ namespace oxen::quic::test auto server_established = callback_waiter{[](connection_interface&) {}}; Network test_net{}; - constexpr auto good_msg = "hello from the other siiiii-iiiiide"_bsv; + constexpr auto good_msg = "hello from the other siiiii-iiiiide"_bsp; std::promise d_promise; std::future d_future = d_promise.get_future(); - stream_data_callback server_data_cb = [&](Stream&, bstring_view dat) { + stream_data_callback server_data_cb = [&](Stream&, bspan dat) { REQUIRE(good_msg == dat); d_promise.set_value(true); }; @@ -28,11 +23,11 @@ namespace oxen::quic::test Address server_local{}; Address client_local{}; - opt::manual_routing client_sender{[&](const Path& p, bstring_view d) { + opt::manual_routing client_sender{[&](const Path& p, bspan d) { server_endpoint->manually_receive_packet(Packet{p.invert(), d}); }}; - opt::manual_routing server_sender{[&](const Path& p, bstring_view d) { + opt::manual_routing server_sender{[&](const Path& p, bspan d) { client_endpoint->manually_receive_packet(Packet{p.invert(), d}); }}; @@ -83,19 +78,21 @@ namespace oxen::quic::test opt::enable_datagrams enable_dgrams{}; - dgram_data_callback vanilla_client_recv_dgram_cb = [&](dgram_interface&, bstring data) { + dgram_data_callback vanilla_client_recv_dgram_cb = [&](dgram_interface&, std::vector data) { manual_client->manually_receive_packet(Packet{Path{manual_client_addr, manual_server_addr}, std::move(data)}); }; - dgram_data_callback vanilla_server_recv_dgram_cb = [&](dgram_interface&, bstring data) { + dgram_data_callback vanilla_server_recv_dgram_cb = [&](dgram_interface&, std::vector data) { manual_server->manually_receive_packet(Packet{Path{manual_server_addr, manual_client_addr}, std::move(data)}); }; - opt::manual_routing manual_client_sender{ - [&](const Path&, bstring_view d) { vanilla_client_ci->send_datagram(bstring{d}); }}; + opt::manual_routing manual_client_sender{[&](const Path&, bspan d) { + vanilla_client_ci->send_datagram(std::vector{d.begin(), d.end()}); + }}; - opt::manual_routing manual_server_sender{ - [&](const Path&, bstring_view d) { vanilla_server_ci->send_datagram(bstring{d}); }}; + opt::manual_routing manual_server_sender{[&](const Path&, bspan d) { + vanilla_server_ci->send_datagram(std::vector{d.begin(), d.end()}); + }}; auto [client_tls, server_tls] = defaults::tls_creds_from_ed_keys(); diff --git a/tests/012-watermarks.cpp b/tests/012-watermarks.cpp index 1d26fdd8..a440a5eb 100644 --- a/tests/012-watermarks.cpp +++ b/tests/012-watermarks.cpp @@ -1,8 +1,3 @@ -#include -#include -#include -#include - #include "utils.hpp" namespace oxen::quic::test @@ -10,7 +5,7 @@ namespace oxen::quic::test TEST_CASE("012 - Stream Buffer Watermarking", "[012][watermark][streams]") { Network test_net{}; - bstring req_msg(100'000, std::byte{'a'}); + std::vector req_msg(100'000, std::byte{'a'}); auto client_established = callback_waiter{[](connection_interface&) {}}; auto server_established = callback_waiter{[](connection_interface&) {}}; @@ -43,12 +38,12 @@ namespace oxen::quic::test CHECK(client_stream->has_watermarks()); - REQUIRE_NOTHROW(client_stream->send(bstring_view{req_msg})); + REQUIRE_NOTHROW(client_stream->send(bspan{req_msg})); CHECK(low_water.wait()); - REQUIRE_NOTHROW(client_stream->send(bstring_view{req_msg})); - REQUIRE_NOTHROW(client_stream->send(bstring_view{req_msg})); + REQUIRE_NOTHROW(client_stream->send(bspan{req_msg})); + REQUIRE_NOTHROW(client_stream->send(bspan{req_msg})); CHECK(high_water.wait()); @@ -75,17 +70,17 @@ namespace oxen::quic::test }, true}); - REQUIRE_NOTHROW(client_stream->send(bstring_view{req_msg})); + REQUIRE_NOTHROW(client_stream->send(bspan{req_msg})); std::this_thread::sleep_for(100ms); - REQUIRE_NOTHROW(client_stream->send(bstring_view{req_msg})); - REQUIRE_NOTHROW(client_stream->send(bstring_view{req_msg})); + REQUIRE_NOTHROW(client_stream->send(bspan{req_msg})); + REQUIRE_NOTHROW(client_stream->send(bspan{req_msg})); std::this_thread::sleep_for(250ms); - REQUIRE_NOTHROW(client_stream->send(bstring_view{req_msg})); - REQUIRE_NOTHROW(client_stream->send(bstring_view{req_msg})); + REQUIRE_NOTHROW(client_stream->send(bspan{req_msg})); + REQUIRE_NOTHROW(client_stream->send(bspan{req_msg})); std::this_thread::sleep_for(250ms); @@ -118,7 +113,7 @@ namespace oxen::quic::test }, true}); - REQUIRE_NOTHROW(client_stream->send(bstring_view{req_msg})); + REQUIRE_NOTHROW(client_stream->send(bspan{req_msg})); std::this_thread::sleep_for(100ms); @@ -128,10 +123,10 @@ namespace oxen::quic::test server_stream->pause(); REQUIRE(server_stream->is_paused()); - REQUIRE_NOTHROW(client_stream->send(bstring_view{req_msg})); - REQUIRE_NOTHROW(client_stream->send(bstring_view{req_msg})); - REQUIRE_NOTHROW(client_stream->send(bstring_view{req_msg})); - REQUIRE_NOTHROW(client_stream->send(bstring_view{req_msg})); + REQUIRE_NOTHROW(client_stream->send(bspan{req_msg})); + REQUIRE_NOTHROW(client_stream->send(bspan{req_msg})); + REQUIRE_NOTHROW(client_stream->send(bspan{req_msg})); + REQUIRE_NOTHROW(client_stream->send(bspan{req_msg})); server_stream->resume(); REQUIRE_FALSE(server_stream->is_paused()); diff --git a/tests/013-eventhandler.cpp b/tests/013-eventhandler.cpp index 4e508fb4..dfb2d3e2 100644 --- a/tests/013-eventhandler.cpp +++ b/tests/013-eventhandler.cpp @@ -1,10 +1,3 @@ -#include -#include -#include -#include -#include -#include - #include "utils.hpp" namespace oxen::quic::test @@ -19,7 +12,7 @@ namespace oxen::quic::test TEST_CASE("013 - EventHandler event repeater: EventHandler managed lifetime", "[013][repeater][managed]") { Network test_net{}; - constexpr auto msg = "hello from the other siiiii-iiiiide"_bsv; + constexpr auto msg = "hello from the other siiiii-iiiiide"_bsp; std::promise prom_a, prom_b; std::future fut_a = prom_a.get_future(), fut_b = prom_b.get_future(); @@ -28,7 +21,7 @@ namespace oxen::quic::test std::shared_ptr handler; - stream_data_callback server_data_cb = [&](Stream&, bstring_view) { + stream_data_callback server_data_cb = [&](Stream&, bspan) { recv_counter += 1; if (recv_counter == NUM_ITERATIONS) { diff --git a/tests/014-0rtt-resets.cpp b/tests/014-0rtt-resets.cpp index 639b2286..2f9068ba 100644 --- a/tests/014-0rtt-resets.cpp +++ b/tests/014-0rtt-resets.cpp @@ -1,8 +1,3 @@ -#include -#include -#include -#include - #include "utils.hpp" namespace oxen::quic::test diff --git a/tests/015-bt-encoding.cpp b/tests/015-bt-encoding.cpp index f56fd748..d49647cc 100644 --- a/tests/015-bt-encoding.cpp +++ b/tests/015-bt-encoding.cpp @@ -1,8 +1,3 @@ -#include -#include -#include -#include - #include "utils.hpp" namespace oxen::quic::test diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b23c1b61..b9030feb 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -4,7 +4,7 @@ add_subdirectory(CLI11) add_library(tests_common STATIC utils.cpp) target_link_libraries(tests_common PUBLIC - quic CLI11::CLI11 libquic_internal-warnings gnutls::gnutls) + quic CLI11::CLI11 Catch2::Catch2 libquic_internal-warnings gnutls::gnutls) # We need hogweed for generating Ed25519 keys (this is already a gnutls dependency, so we shouldn't # be adding any new dep by requiring it) diff --git a/tests/case_logger.cpp b/tests/case_logger.cpp index ddd70723..7cfe731f 100644 --- a/tests/case_logger.cpp +++ b/tests/case_logger.cpp @@ -3,11 +3,12 @@ // // It runs in its own log level; to activate it, run alltests with `-T`/`--test-tracing`. // +#include +#include + #include #include #include -#include -#include namespace fmt { diff --git a/tests/dgram-speed-client.cpp b/tests/dgram-speed-client.cpp index 82dad32c..527ee42e 100644 --- a/tests/dgram-speed-client.cpp +++ b/tests/dgram-speed-client.cpp @@ -2,24 +2,18 @@ Test client binary */ +#include "utils.hpp" + +#include +#include #include #include -#include #include -#include -#include -#include #include -#include - -#include "utils.hpp" using namespace oxen::quic; -using ustring = std::basic_string; -using ustring_view = std::basic_string_view; - int main(int argc, char* argv[]) { CLI::App cli{"libQUIC test client"}; @@ -63,7 +57,7 @@ int main(int argc, char* argv[]) { std::shared_ptr stream; std::atomic active = false; - ustring msg{}; + std::vector msg{}; uint64_t size; uint64_t dgram_size; uint64_t n_iter; @@ -101,7 +95,7 @@ int main(int argc, char* argv[]) log::critical(test_cat, "Stream {} (rawid={}) closed (error={})", i, s.stream_id(), errcode); }; - dgram_data_callback recv_dgram_cb = [&](dgram_interface, bstring data) { + dgram_data_callback recv_dgram_cb = [&](dgram_interface, std::vector data) { log::critical(test_cat, "Calling endpoint receive datagram callback... data received..."); if (d_ptr->is_sending) @@ -114,7 +108,7 @@ int main(int argc, char* argv[]) log::error(test_cat, "Got unexpected data from the other side: {}B != 5B", data.size()); d_ptr->failed = true; } - else if (data != "DONE!"_bsv) + else if (data != "DONE!"_bsp) { log::error( test_cat, @@ -160,11 +154,11 @@ int main(int argc, char* argv[]) send_data dgram_data{size, max_size}; d_ptr = &dgram_data; - bstring remaining_str; + std::vector remaining_str; remaining_str.resize(8); oxenc::write_host_as_little(d_ptr->n_iter, remaining_str.data()); log::warning(test_cat, "Sending datagram count to remote..."); - client_ci->send_datagram(bstring_view{remaining_str.data(), remaining_str.size()}); + client_ci->send_datagram(bspan{remaining_str.data(), remaining_str.size()}); std::promise send_prom; std::future send_f = send_prom.get_future(); @@ -180,10 +174,10 @@ int main(int argc, char* argv[]) for (uint64_t i = 1; i < d_ptr->n_iter; ++i) { // Just send these with the 0 at the beginning - client_ci->send_datagram(ustring_view{d_ptr->msg}); + client_ci->send_datagram(vec_to_span(d_ptr->msg)); } // Send a final one with the max value in the beginning so the server knows its done - ustring last_payload{d_ptr->msg}; + std::vector last_payload{d_ptr->msg}; last_payload[0] = 1; // Signals that this is the last one client_ci->send_datagram(std::move(last_payload)); diff --git a/tests/dgram-speed-server.cpp b/tests/dgram-speed-server.cpp index cb677bff..116135f2 100644 --- a/tests/dgram-speed-server.cpp +++ b/tests/dgram-speed-server.cpp @@ -2,19 +2,21 @@ Test server binary */ -#include +#include "utils.hpp" + +#include +#include +#include #include #include #include + +#include + #include -#include -#include -#include #include -#include "utils.hpp" - using namespace oxen::quic; int main(int argc, char* argv[]) @@ -65,7 +67,7 @@ int main(int argc, char* argv[]) std::shared_ptr server; - dgram_data_callback recv_dgram_cb = [&](dgram_interface& di, bstring_view data) { + dgram_data_callback recv_dgram_cb = [&](dgram_interface& di, bspan data) { if (dgram_data.n_expected == 0) { // The very first packet should be 8 bytes containing the uint64_t count of total diff --git a/tests/main.cpp b/tests/main.cpp index 2b2e9674..7a359eeb 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -1,7 +1,7 @@ -#include - #include "utils.hpp" +#include + bool oxen::quic::disable_ipv6, oxen::quic::disable_rotating_buffer; int main(int argc, char* argv[]) diff --git a/tests/ping-client.cpp b/tests/ping-client.cpp index f344874e..f8d649a3 100644 --- a/tests/ping-client.cpp +++ b/tests/ping-client.cpp @@ -2,21 +2,23 @@ Ping client binary */ -#include +#include "utils.hpp" + +#include +#include #include #include #include + +#include + #include -#include -#include #include -#include "utils.hpp" - using namespace oxen::quic; -constexpr auto client_msg = "good morning"_bsv; +constexpr auto client_msg = "good morning"_bsp; int main(int argc, char* argv[]) { @@ -105,7 +107,7 @@ int main(int argc, char* argv[]) all_done.set_value(); }; - auto stream_recv = [&](Stream& s, bstring_view) { + auto stream_recv = [&](Stream& s, bspan) { // get the time first, then do ops auto t = get_timestamp().count(); if (not first_data.exchange(true)) diff --git a/tests/ping-server.cpp b/tests/ping-server.cpp index d92b9525..3835a008 100644 --- a/tests/ping-server.cpp +++ b/tests/ping-server.cpp @@ -2,18 +2,20 @@ Ping server binary */ -#include +#include "utils.hpp" + +#include +#include #include #include #include + +#include + #include -#include -#include #include -#include "utils.hpp" - using namespace oxen::quic; int main(int argc, char* argv[]) @@ -94,14 +96,14 @@ int main(int argc, char* argv[]) return 0; }; - auto stream_recv = [&](Stream& s, bstring_view) { + auto stream_recv = [&](Stream& s, bspan) { // get the time first, then do ops auto t = get_timestamp().count(); if (not first_data.exchange(true)) { timing[2] = t; log::critical(test_cat, "Received first data on connection to {}", s.remote()); - s.send("good afternoon"_bsv); + s.send("good afternoon"_bsp); server->get_conn(s.reference_id)->close_connection(); } }; diff --git a/tests/speedtest-client.cpp b/tests/speedtest-client.cpp index 656c9c71..fd53817a 100644 --- a/tests/speedtest-client.cpp +++ b/tests/speedtest-client.cpp @@ -2,18 +2,19 @@ Test client binary */ +#include "utils.hpp" + +#include +#include #include #include + #include #include -#include -#include #include #include -#include "utils.hpp" - using namespace oxen::quic; int main(int argc, char* argv[]) @@ -146,7 +147,7 @@ int main(int argc, char* argv[]) log::critical(test_cat, "Stream {} (rawid={}) closed (error={})", i, s.stream_id(), errcode); }; - stream_data_callback on_stream_data = [&](Stream& s, bstring_view data) { + stream_data_callback on_stream_data = [&](Stream& s, bspan data) { size_t i = s.stream_id() >> 2; if (i >= parallel) { @@ -176,7 +177,7 @@ int main(int argc, char* argv[]) log::error(test_cat, "Got unexpected data from the other side: {}B != 32B", data.size()); sd.failed = true; } - else if (data.substr(0, 32) != sd.hash) + else if (auto first = data.first(32); first != sd.hash) { log::critical( test_cat, @@ -298,7 +299,7 @@ int main(int argc, char* argv[]) { s.remaining = 0; s.done_sending = true; - s.stream->send(bstring_view{s.bufs[0].data(), s.bufs[0].size()}); + s.stream->send(bspan{s.bufs[0].data(), s.bufs[0].size()}); } else { diff --git a/tests/speedtest-server.cpp b/tests/speedtest-server.cpp index bec2df77..d35f5425 100644 --- a/tests/speedtest-server.cpp +++ b/tests/speedtest-server.cpp @@ -2,18 +2,20 @@ Test server binary */ -#include +#include "utils.hpp" + +#include +#include #include #include #include + +#include + #include -#include -#include #include -#include "utils.hpp" - using namespace oxen::quic; int main(int argc, char* argv[]) @@ -78,7 +80,7 @@ int main(int argc, char* argv[]) std::map> csd; - stream_data_callback stream_data = [&](Stream& s, bstring_view data) { + stream_data_callback stream_data = [&](Stream& s, bspan data) { auto& sd = csd[s.reference_id]; auto it = sd.find(s.stream_id()); @@ -91,7 +93,7 @@ int main(int argc, char* argv[]) } auto size = oxenc::load_little_to_host(data.data()); - data.remove_prefix(sizeof(uint64_t)); + data = data.subspan(sizeof(uint64_t)); it = sd.emplace(s.stream_id(), size).first; log::warning(test_cat, "First data from new stream {}, expecting {}B!", s.stream_id(), size); @@ -106,7 +108,7 @@ int main(int argc, char* argv[]) log::critical(test_cat, "Received too much data ({}B > {}B)!", info.received, info.expected); if (!need_more) return; - data.remove_suffix(info.received - info.expected); + data = data.first(data.size() - (info.received + info.expected)); } if (!no_checksum) diff --git a/tests/utils.hpp b/tests/utils.hpp index 2efad42d..77ce5680 100644 --- a/tests/utils.hpp +++ b/tests/utils.hpp @@ -1,19 +1,27 @@ #pragma once #include +#include + +// keep above Catch2 macros to get comparators and other oxenc utils +using namespace oxenc; + +#include +#include +#include #include #include + +#include +#include + #include +#include #include -#include -#include -#include -#include -#include -#include -#include +#include #include +#include #include namespace oxen::quic @@ -73,6 +81,12 @@ namespace oxen::quic // seed and 32-byte pubkey. std::pair generate_ed25519(); + template + inline std::string_view sp_to_sv(const T& sp) + { + return {reinterpret_cast(sp.data()), sp.size()}; + } + // Takes a hex- or base64-encoded byte value of the given byte size and returns the bytes. // Returns nullopt if the encoded value is not a valid byte encoding of the given size. template