diff --git a/Makefile.am b/Makefile.am index 202c9b91a..74750152b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -54,8 +54,8 @@ src_libbitcoin_network_la_SOURCES = \ src/log/capture.cpp \ src/log/logger.cpp \ src/log/reporter.cpp \ - src/messages/http/body.cpp \ src/messages/http/fields.cpp \ + src/messages/http/head.cpp \ src/messages/http/enums/mime_type.cpp \ src/messages/http/enums/target.cpp \ src/messages/json/body.cpp \ @@ -100,6 +100,8 @@ src_libbitcoin_network_la_SOURCES = \ src/messages/peer/version.cpp \ src/messages/peer/version_acknowledge.cpp \ src/messages/peer/witness_tx_id_relay.cpp \ + src/messages/variant/body.cpp \ + src/messages/variant/head.cpp \ src/net/acceptor.cpp \ src/net/broadcaster.cpp \ src/net/connector.cpp \ @@ -170,10 +172,9 @@ test_libbitcoin_network_test_SOURCES = \ test/config/utilities.cpp \ test/log/timer.cpp \ test/log/tracker.cpp \ - test/messages/http/body_reader.cpp \ - test/messages/http/body_writer.cpp \ test/messages/http/fields.cpp \ - test/messages/http/method.cpp \ + test/messages/http/head_reader.cpp \ + test/messages/http/head_writer.cpp \ test/messages/http/enums/magic_numbers.cpp \ test/messages/http/enums/mime_type.cpp \ test/messages/http/enums/target.cpp \ @@ -224,6 +225,11 @@ test_libbitcoin_network_test_SOURCES = \ test/messages/peer/enums/level.cpp \ test/messages/peer/enums/magic_numbers.cpp \ test/messages/peer/enums/service.cpp \ + test/messages/variant/body_reader.cpp \ + test/messages/variant/body_writer.cpp \ + test/messages/variant/head_reader.cpp \ + test/messages/variant/head_writer.cpp \ + test/messages/variant/method.cpp \ test/net/acceptor.cpp \ test/net/broadcaster.cpp \ test/net/connector.cpp \ @@ -347,14 +353,9 @@ include_bitcoin_network_log_HEADERS = \ include_bitcoin_network_messages_httpdir = ${includedir}/bitcoin/network/messages/http include_bitcoin_network_messages_http_HEADERS = \ - include/bitcoin/network/messages/http/body.hpp \ include/bitcoin/network/messages/http/fields.hpp \ include/bitcoin/network/messages/http/head.hpp \ - include/bitcoin/network/messages/http/http.hpp \ - include/bitcoin/network/messages/http/method.hpp \ - include/bitcoin/network/messages/http/request.hpp \ - include/bitcoin/network/messages/http/response.hpp \ - include/bitcoin/network/messages/http/types.hpp + include/bitcoin/network/messages/http/http.hpp include_bitcoin_network_messages_http_enumsdir = ${includedir}/bitcoin/network/messages/http/enums include_bitcoin_network_messages_http_enums_HEADERS = \ @@ -421,6 +422,15 @@ include_bitcoin_network_messages_peer_enums_HEADERS = \ include/bitcoin/network/messages/peer/enums/magic_numbers.hpp \ include/bitcoin/network/messages/peer/enums/service.hpp +include_bitcoin_network_messages_variantdir = ${includedir}/bitcoin/network/messages/variant +include_bitcoin_network_messages_variant_HEADERS = \ + include/bitcoin/network/messages/variant/body.hpp \ + include/bitcoin/network/messages/variant/head.hpp \ + include/bitcoin/network/messages/variant/method.hpp \ + include/bitcoin/network/messages/variant/request.hpp \ + include/bitcoin/network/messages/variant/response.hpp \ + include/bitcoin/network/messages/variant/variant.hpp + include_bitcoin_network_netdir = ${includedir}/bitcoin/network/net include_bitcoin_network_net_HEADERS = \ include/bitcoin/network/net/acceptor.hpp \ diff --git a/builds/cmake/CMakeLists.txt b/builds/cmake/CMakeLists.txt index 2e3164fb3..e1afc020d 100644 --- a/builds/cmake/CMakeLists.txt +++ b/builds/cmake/CMakeLists.txt @@ -236,8 +236,8 @@ add_library( ${CANONICAL_LIB_NAME} "../../src/log/capture.cpp" "../../src/log/logger.cpp" "../../src/log/reporter.cpp" - "../../src/messages/http/body.cpp" "../../src/messages/http/fields.cpp" + "../../src/messages/http/head.cpp" "../../src/messages/http/enums/mime_type.cpp" "../../src/messages/http/enums/target.cpp" "../../src/messages/json/body.cpp" @@ -282,6 +282,8 @@ add_library( ${CANONICAL_LIB_NAME} "../../src/messages/peer/version.cpp" "../../src/messages/peer/version_acknowledge.cpp" "../../src/messages/peer/witness_tx_id_relay.cpp" + "../../src/messages/variant/body.cpp" + "../../src/messages/variant/head.cpp" "../../src/net/acceptor.cpp" "../../src/net/broadcaster.cpp" "../../src/net/connector.cpp" @@ -376,10 +378,9 @@ if (with-tests) "../../test/config/utilities.cpp" "../../test/log/timer.cpp" "../../test/log/tracker.cpp" - "../../test/messages/http/body_reader.cpp" - "../../test/messages/http/body_writer.cpp" "../../test/messages/http/fields.cpp" - "../../test/messages/http/method.cpp" + "../../test/messages/http/head_reader.cpp" + "../../test/messages/http/head_writer.cpp" "../../test/messages/http/enums/magic_numbers.cpp" "../../test/messages/http/enums/mime_type.cpp" "../../test/messages/http/enums/target.cpp" @@ -430,6 +431,11 @@ if (with-tests) "../../test/messages/peer/enums/level.cpp" "../../test/messages/peer/enums/magic_numbers.cpp" "../../test/messages/peer/enums/service.cpp" + "../../test/messages/variant/body_reader.cpp" + "../../test/messages/variant/body_writer.cpp" + "../../test/messages/variant/head_reader.cpp" + "../../test/messages/variant/head_writer.cpp" + "../../test/messages/variant/method.cpp" "../../test/net/acceptor.cpp" "../../test/net/broadcaster.cpp" "../../test/net/connector.cpp" diff --git a/builds/msvc/vs2022/libbitcoin-network-test/libbitcoin-network-test.vcxproj b/builds/msvc/vs2022/libbitcoin-network-test/libbitcoin-network-test.vcxproj index fc969320d..171cc5185 100644 --- a/builds/msvc/vs2022/libbitcoin-network-test/libbitcoin-network-test.vcxproj +++ b/builds/msvc/vs2022/libbitcoin-network-test/libbitcoin-network-test.vcxproj @@ -146,20 +146,17 @@ - - $(IntDir)test_messages_http_body_reader.obj - - - $(IntDir)test_messages_http_body_writer.obj - $(IntDir)test_messages_http_enums_magic_numbers.obj - - $(IntDir)test_messages_http_method.obj + + $(IntDir)test_messages_http_head_reader.obj + + + $(IntDir)test_messages_http_head_writer.obj $(IntDir)test_messages_json_body_reader.obj @@ -216,6 +213,21 @@ + + $(IntDir)test_messages_variant_body_reader.obj + + + $(IntDir)test_messages_variant_body_writer.obj + + + $(IntDir)test_messages_variant_head_reader.obj + + + $(IntDir)test_messages_variant_head_writer.obj + + + $(IntDir)test_messages_variant_method.obj + diff --git a/builds/msvc/vs2022/libbitcoin-network-test/libbitcoin-network-test.vcxproj.filters b/builds/msvc/vs2022/libbitcoin-network-test/libbitcoin-network-test.vcxproj.filters index 1eff17b42..9b3ef8ad5 100644 --- a/builds/msvc/vs2022/libbitcoin-network-test/libbitcoin-network-test.vcxproj.filters +++ b/builds/msvc/vs2022/libbitcoin-network-test/libbitcoin-network-test.vcxproj.filters @@ -32,7 +32,7 @@ {D28FC18A-8B81-4247-0000-00000000000B} - {D28FC18A-8B81-4247-0000-00000000000E} + {D28FC18A-8B81-4247-0000-00000000000F} {D28FC18A-8B81-4247-0000-00000000000C} @@ -41,7 +41,10 @@ {D28FC18A-8B81-4247-0000-00000000000D} - {D28FC18A-8B81-4247-0000-00000000000F} + {D28FC18A-8B81-4247-0000-000000000001} + + + {D28FC18A-8B81-4247-0000-00000000000E} {D28FC18A-8B81-4247-0000-000000000006} @@ -135,12 +138,6 @@ src - - src\messages\http - - - src\messages\http - src\messages\http\enums @@ -153,7 +150,10 @@ src\messages\http - + + src\messages\http + + src\messages\http @@ -297,6 +297,21 @@ src\messages\peer + + src\messages\variant + + + src\messages\variant + + + src\messages\variant + + + src\messages\variant + + + src\messages\variant + src diff --git a/builds/msvc/vs2022/libbitcoin-network/libbitcoin-network.vcxproj b/builds/msvc/vs2022/libbitcoin-network/libbitcoin-network.vcxproj index 861337ebd..8b35ec874 100644 --- a/builds/msvc/vs2022/libbitcoin-network/libbitcoin-network.vcxproj +++ b/builds/msvc/vs2022/libbitcoin-network/libbitcoin-network.vcxproj @@ -140,12 +140,12 @@ - - $(IntDir)src_messages_http_body.obj - + + $(IntDir)src_messages_http_head.obj + $(IntDir)src_messages_json_body.obj @@ -192,6 +192,12 @@ + + $(IntDir)src_messages_variant_body.obj + + + $(IntDir)src_messages_variant_head.obj + @@ -265,7 +271,6 @@ - @@ -274,10 +279,6 @@ - - - - @@ -326,6 +327,12 @@ + + + + + + diff --git a/builds/msvc/vs2022/libbitcoin-network/libbitcoin-network.vcxproj.filters b/builds/msvc/vs2022/libbitcoin-network/libbitcoin-network.vcxproj.filters index a63aa69e6..76dcc8d6c 100644 --- a/builds/msvc/vs2022/libbitcoin-network/libbitcoin-network.vcxproj.filters +++ b/builds/msvc/vs2022/libbitcoin-network/libbitcoin-network.vcxproj.filters @@ -8,79 +8,82 @@ - {564EB540-D6B6-425C-0000-00000000000E} + {564EB540-D6B6-425C-0000-00000000000F} - {564EB540-D6B6-425C-0000-00000000000F} + {564EB540-D6B6-425C-0000-000000000001} - {564EB540-D6B6-425C-0000-000000000001} + {564EB540-D6B6-425C-0000-000000000002} - {564EB540-D6B6-425C-0000-000000000002} + {564EB540-D6B6-425C-0000-000000000003} - {564EB540-D6B6-425C-0000-0000000000B1} + {564EB540-D6B6-425C-0000-0000000000C1} - {564EB540-D6B6-425C-0000-000000000003} + {564EB540-D6B6-425C-0000-000000000004} - {564EB540-D6B6-425C-0000-000000000004} + {564EB540-D6B6-425C-0000-000000000005} - {564EB540-D6B6-425C-0000-000000000005} + {564EB540-D6B6-425C-0000-000000000006} - {564EB540-D6B6-425C-0000-0000000000C1} + {564EB540-D6B6-425C-0000-0000000000D1} - {564EB540-D6B6-425C-0000-0000000000E1} + {564EB540-D6B6-425C-0000-0000000000F1} - {564EB540-D6B6-425C-0000-0000000000D1} + {564EB540-D6B6-425C-0000-0000000000E1} - {564EB540-D6B6-425C-0000-000000000006} + {564EB540-D6B6-425C-0000-000000000007} - {564EB540-D6B6-425C-0000-000000000007} + {564EB540-D6B6-425C-0000-000000000008} - {564EB540-D6B6-425C-0000-0000000000F1} + {564EB540-D6B6-425C-0000-000000000002} - {564EB540-D6B6-425C-0000-000000000004} + {564EB540-D6B6-425C-0000-000000000006} - {564EB540-D6B6-425C-0000-000000000002} + {564EB540-D6B6-425C-0000-000000000003} - {564EB540-D6B6-425C-0000-000000000003} + {564EB540-D6B6-425C-0000-000000000004} + {564EB540-D6B6-425C-0000-000000000007} + + {564EB540-D6B6-425C-0000-000000000005} - {564EB540-D6B6-425C-0000-000000000008} + {564EB540-D6B6-425C-0000-000000000009} - {564EB540-D6B6-425C-0000-000000000009} + {564EB540-D6B6-425C-0000-000000000010} - {564EB540-D6B6-425C-0000-000000000010} + {564EB540-D6B6-425C-0000-0000000000A1} - {564EB540-D6B6-425C-0000-000000000006} + {564EB540-D6B6-425C-0000-000000000008} - {564EB540-D6B6-425C-0000-000000000007} + {564EB540-D6B6-425C-0000-000000000009} - {564EB540-D6B6-425C-0000-0000000000A1} + {564EB540-D6B6-425C-0000-0000000000B1} - {564EB540-D6B6-425C-0000-000000000008} + {564EB540-D6B6-425C-0000-000000000010} {564EB540-D6B6-425C-0000-000000000000} @@ -104,7 +107,7 @@ {564EB540-D6B6-425C-0000-00000000000A} - {564EB540-D6B6-425C-0000-00000000000D} + {564EB540-D6B6-425C-0000-00000000000E} {564EB540-D6B6-425C-0000-00000000000B} @@ -112,6 +115,9 @@ {564EB540-D6B6-425C-0000-00000000000C} + + {564EB540-D6B6-425C-0000-00000000000D} + {564EB540-D6B6-425C-0000-000000000006} @@ -177,9 +183,6 @@ src - - src\messages\http - src\messages\http\enums @@ -189,6 +192,9 @@ src\messages\http + + src\messages\http + src\messages\json @@ -315,6 +321,12 @@ src\messages\peer + + src\messages\variant + + + src\messages\variant + src @@ -530,9 +542,6 @@ include\bitcoin\network - - include\bitcoin\network\messages\http - include\bitcoin\network\messages\http\enums @@ -557,18 +566,6 @@ include\bitcoin\network\messages\http - - include\bitcoin\network\messages\http - - - include\bitcoin\network\messages\http - - - include\bitcoin\network\messages\http - - - include\bitcoin\network\messages\http - include\bitcoin\network\messages\json @@ -713,6 +710,24 @@ include\bitcoin\network\messages\peer + + include\bitcoin\network\messages\variant + + + include\bitcoin\network\messages\variant + + + include\bitcoin\network\messages\variant + + + include\bitcoin\network\messages\variant + + + include\bitcoin\network\messages\variant + + + include\bitcoin\network\messages\variant + include\bitcoin\network diff --git a/include/bitcoin/network.hpp b/include/bitcoin/network.hpp index af55cf6a3..42379fa9e 100644 --- a/include/bitcoin/network.hpp +++ b/include/bitcoin/network.hpp @@ -57,14 +57,9 @@ #include #include #include -#include #include #include #include -#include -#include -#include -#include #include #include #include @@ -118,6 +113,12 @@ #include #include #include +#include +#include +#include +#include +#include +#include #include #include #include diff --git a/include/bitcoin/network/beast.hpp b/include/bitcoin/network/beast.hpp index 80e5c738b..c8f4fcaf9 100644 --- a/include/bitcoin/network/beast.hpp +++ b/include/bitcoin/network/beast.hpp @@ -40,93 +40,24 @@ constexpr int32_t version_1_0 = 10; /// beast::http::empty_body using empty_body = boost::beast::http::empty_body; -using empty_request = boost::beast::http::request; -using empty_response = boost::beast::http::response; -using empty_parser = boost::beast::http::request_parser; -using empty_serializer = boost::beast::http::serializer; -using empty_response_cptr = std::shared_ptr; -using empty_request_cptr = std::shared_ptr; -using empty_response_ptr = std::shared_ptr; -using empty_request_ptr = std::shared_ptr; // TODO: rename to chunk_body etc., to highlight the allocator. /// beast::http::vector_body> using data_body = boost::beast::http::vector_body>; -using data_request = boost::beast::http::request; -using data_response = boost::beast::http::response; -using data_parser = boost::beast::http::request_parser; -using data_serializer = boost::beast::http::serializer; -using data_response_cptr = std::shared_ptr; -using data_request_cptr = std::shared_ptr; -using data_response_ptr = std::shared_ptr; -using data_request_ptr = std::shared_ptr; /// beast::http::file_body using file_body = boost::beast::http::file_body; -using file_request = boost::beast::http::request; -using file_response = boost::beast::http::response; -using file_parser = boost::beast::http::request_parser; -using file_serializer = boost::beast::http::serializer; -using file_response_cptr = std::shared_ptr; -using file_request_cptr = std::shared_ptr; -using file_response_ptr = std::shared_ptr; -using file_request_ptr = std::shared_ptr; /// beast::http::span_body /// Must cast write span uint8_t* to non-const. using span_body = boost::beast::http::span_body; -using span_request = boost::beast::http::request; -using span_response = boost::beast::http::response; -using span_parser = boost::beast::http::request_parser; -using span_serializer = boost::beast::http::serializer; -using span_response_cptr = std::shared_ptr; -using span_request_cptr = std::shared_ptr; -using span_response_ptr = std::shared_ptr; -using span_request_ptr = std::shared_ptr; /// beast::http::buffer_body /// Must cast write buffer void* to non-const. using buffer_body = boost::beast::http::buffer_body; -using buffer_request = boost::beast::http::request; -using buffer_response = boost::beast::http::response; -using buffer_parser = boost::beast::http::request_parser; -using buffer_serializer = boost::beast::http::serializer; -using buffer_response_cptr = std::shared_ptr; -using buffer_request_cptr = std::shared_ptr; -using buffer_response_ptr = std::shared_ptr; -using buffer_request_ptr = std::shared_ptr; /// beast::http::string_body using string_body = boost::beast::http::string_body; -using string_request = boost::beast::http::request; -using string_response = boost::beast::http::response; -using string_parser = boost::beast::http::request_parser; -using string_serializer = boost::beast::http::serializer; -using string_request_cptr = std::shared_ptr; -using string_response_cptr = std::shared_ptr; -using string_response_ptr = std::shared_ptr; -using string_request_ptr = std::shared_ptr; - -/////// http::json::body -////using json_request = boost::beast::http::request; -////using json_response = boost::beast::http::response; -////using json_parser = boost::beast::http::request_parser; -////using json_serializer = boost::beast::http::serializer; -////using json_response_cptr = std::shared_ptr; -////using json_request_cptr = std::shared_ptr; -////using json_response_ptr = std::shared_ptr; -////using json_request_ptr = std::shared_ptr; - -// Defined in types.hpp. -/////// http::body (variant) -////using request = boost::beast::http::request; -////using response = boost::beast::http::response; -////using parser = boost::beast::http::request_parser; -////using serializer = boost::beast::http::serializer; -////using response_cptr = std::shared_ptr; -////using request_cptr = std::shared_ptr; -////using response_ptr = std::shared_ptr; -////using request_ptr = std::shared_ptr; /// general purpose using file = file_body::value_type; diff --git a/include/bitcoin/network/channels/channel_http.hpp b/include/bitcoin/network/channels/channel_http.hpp index c01489b05..9f035796e 100644 --- a/include/bitcoin/network/channels/channel_http.hpp +++ b/include/bitcoin/network/channels/channel_http.hpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include diff --git a/include/bitcoin/network/messages/http/head.hpp b/include/bitcoin/network/messages/http/head.hpp index 04ba59ef4..dcf73118d 100644 --- a/include/bitcoin/network/messages/http/head.hpp +++ b/include/bitcoin/network/messages/http/head.hpp @@ -19,13 +19,15 @@ #ifndef LIBBITCOIN_NETWORK_MESSAGES_HTTP_HEAD_HPP #define LIBBITCOIN_NETWORK_MESSAGES_HTTP_HEAD_HPP -#include #include namespace libbitcoin { namespace network { namespace http { +using empty_request = boost::beast::http::request; +using empty_response = boost::beast::http::response; + } // namespace http } // namespace network } // namespace libbitcoin diff --git a/include/bitcoin/network/messages/http/http.hpp b/include/bitcoin/network/messages/http/http.hpp index 4b5e05818..ba2bf6fad 100644 --- a/include/bitcoin/network/messages/http/http.hpp +++ b/include/bitcoin/network/messages/http/http.hpp @@ -19,7 +19,6 @@ #ifndef LIBBITCOIN_NETWORK_MESSAGES_HTTP_HTTP_HPP #define LIBBITCOIN_NETWORK_MESSAGES_HTTP_HTTP_HPP -#include #include #include #include @@ -27,9 +26,5 @@ #include #include #include -#include -#include -#include -#include #endif diff --git a/include/bitcoin/network/messages/http/types.hpp b/include/bitcoin/network/messages/http/types.hpp deleted file mode 100644 index eda2b9bdb..000000000 --- a/include/bitcoin/network/messages/http/types.hpp +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Copyright (c) 2011-2025 libbitcoin developers (see AUTHORS) - * - * This file is part of libbitcoin. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -#ifndef LIBBITCOIN_NETWORK_MESSAGES_HTTP_TYPES_HPP -#define LIBBITCOIN_NETWORK_MESSAGES_HTTP_TYPES_HPP - -#include -#include -#include -#include -#include - -namespace libbitcoin { -namespace network { -namespace http { - -/// http::json::body -using json_request = boost::beast::http::request; -using json_response = boost::beast::http::response; -using json_parser = boost::beast::http::request_parser; -using json_serializer = boost::beast::http::serializer; -using json_response_cptr = std::shared_ptr; -using json_request_cptr = std::shared_ptr; -using json_response_ptr = std::shared_ptr; -using json_request_ptr = std::shared_ptr; - -/// http::body (variant) -using request = boost::beast::http::request; -using response = boost::beast::http::response; -using parser = boost::beast::http::request_parser; -using serializer = boost::beast::http::serializer; -using response_cptr = std::shared_ptr; -using request_cptr = std::shared_ptr; -using response_ptr = std::shared_ptr; -using request_ptr = std::shared_ptr; - -} // namespace http -} // namespace network -} // namespace libbitcoin - -#endif diff --git a/include/bitcoin/network/messages/json/body.hpp b/include/bitcoin/network/messages/json/body.hpp index a2bd21cce..e5f944aaf 100644 --- a/include/bitcoin/network/messages/json/body.hpp +++ b/include/bitcoin/network/messages/json/body.hpp @@ -32,7 +32,6 @@ namespace json { /// is movable and as such must be in-place contructed (e.g. variant contruct). struct BCT_API body { - /// Content passed to/from reader/writer via request/response. /// `static uint64_t size(const value_type&)` must be defined for beast to /// produce `content_length`, otherwise the response is chunked. Predeter- diff --git a/include/bitcoin/network/messages/http/body.hpp b/include/bitcoin/network/messages/variant/body.hpp similarity index 66% rename from include/bitcoin/network/messages/http/body.hpp rename to include/bitcoin/network/messages/variant/body.hpp index 4cc97327f..6f17f7e5d 100644 --- a/include/bitcoin/network/messages/http/body.hpp +++ b/include/bitcoin/network/messages/variant/body.hpp @@ -16,28 +16,30 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -#ifndef LIBBITCOIN_NETWORK_MESSAGES_HTTP_BODY_HPP -#define LIBBITCOIN_NETWORK_MESSAGES_HTTP_BODY_HPP +#ifndef LIBBITCOIN_NETWORK_MESSAGES_VARIANT_BODY_HPP +#define LIBBITCOIN_NETWORK_MESSAGES_VARIANT_BODY_HPP #include #include +#include #include -#include -#include #include +#include + +// TODO: relies on http::header, length_type, get_buffer, mime_type. namespace libbitcoin { namespace network { -namespace http { +namespace variant { -using empty_reader = empty_body::reader; -using json_reader = json_body::reader; -using data_reader = data_body::reader; -using file_reader = file_body::reader; -using span_reader = span_body::reader; -using buffer_reader = buffer_body::reader; -using string_reader = string_body::reader; -using variant_reader = std::variant +using empty_reader = http::empty_body::reader; +using json_reader = json::body::reader; +using data_reader = http::data_body::reader; +using file_reader = http::file_body::reader; +using span_reader = http::span_body::reader; +using buffer_reader = http::buffer_body::reader; +using string_reader = http::string_body::reader; +using body_reader = std::variant < empty_reader, json_reader, @@ -48,14 +50,14 @@ using variant_reader = std::variant string_reader >; -using empty_writer = empty_body::writer; -using json_writer = json_body::writer; -using data_writer = data_body::writer; -using file_writer = file_body::writer; -using span_writer = span_body::writer; -using buffer_writer = buffer_body::writer; -using string_writer = string_body::writer; -using variant_writer = std::variant +using empty_writer = http::empty_body::writer; +using json_writer = json::body::writer; +using data_writer = http::data_body::writer; +using file_writer = http::file_body::writer; +using span_writer = http::span_body::writer; +using buffer_writer = http::buffer_body::writer; +using string_writer = http::string_body::writer; +using body_writer = std::variant < empty_writer, json_writer, @@ -66,14 +68,14 @@ using variant_writer = std::variant string_writer >; -using empty_value = empty_body::value_type; -using json_value = json_body::value_type; -using data_value = data_body::value_type; -using file_value = file_body::value_type; -using span_value = span_body::value_type; -using buffer_value = buffer_body::value_type; -using string_value = string_body::value_type; -using variant_value = std::variant +using empty_value = http::empty_body::value_type; +using json_value = json::body::value_type; +using data_value = http::data_body::value_type; +using file_value = http::file_body::value_type; +using span_value = http::span_body::value_type; +using buffer_value = http::buffer_body::value_type; +using string_value = http::string_body::value_type; +using body_value = std::variant < empty_value, json_value, @@ -84,7 +86,7 @@ using variant_value = std::variant string_value >; -/// boost::beast::http body template for all known message types. +/// body template for all known message types. /// This encapsulates a variant of supported body types, selects a type upon /// reader or writer construction, and then passes all calls through to it. struct BCT_API body @@ -112,12 +114,12 @@ struct BCT_API body return inner_.has_value(); } - inline variant_value& value() NOEXCEPT + inline body_value& value() NOEXCEPT { return inner_.value(); } - inline const variant_value& value() const NOEXCEPT + inline const body_value& value() const NOEXCEPT { return inner_.value(); } @@ -136,7 +138,7 @@ struct BCT_API body } private: - std::optional inner_{}; + std::optional inner_{}; }; class reader @@ -145,32 +147,32 @@ struct BCT_API body using buffer_type = asio::const_buffer; template - inline explicit reader(header& header, + inline explicit reader(http::header& header, value_type& value) NOEXCEPT : reader_{ to_reader(header, value) } { } - void init(const length_type& length, boost_code& ec) NOEXCEPT; + void init(const http::length_type& length, boost_code& ec) NOEXCEPT; size_t put(const buffer_type& buffer, boost_code& ec) NOEXCEPT; void finish(boost_code& ec) NOEXCEPT; protected: /// Select reader based on content-type header. template - inline static variant_reader to_reader(Header& header, + inline static body_reader to_reader(Header& header, value_type& value) NOEXCEPT { - switch (content_mime_type(header)) + switch (http::content_mime_type(header)) { - case mime_type::application_json: + case http::mime_type::application_json: value = json_value{}; break; - case mime_type::text_plain: + case http::mime_type::text_plain: value = string_value{}; break; - case mime_type::application_octet_stream: - if (has_attachment(header)) + case http::mime_type::application_octet_stream: + if (http::has_attachment(header)) value = file_value{}; else value = data_value{}; @@ -183,50 +185,50 @@ struct BCT_API body { [&](empty_value& value) NOEXCEPT { - return variant_reader{ empty_reader{ header, value } }; + return body_reader{ empty_reader{ header, value } }; }, [&](json_value& value) NOEXCEPT { // json_reader not copy or assignable (by contained parser). // So *requires* in-place construction for variant populate. - return variant_reader{ std::in_place_type, + return body_reader{ std::in_place_type, header, value }; }, [&](data_value& value) NOEXCEPT { - return variant_reader{ data_reader{ header, value } }; + return body_reader{ data_reader{ header, value } }; }, [&](file_value& value) NOEXCEPT { - return variant_reader{ file_reader{ header, value } }; + return body_reader{ file_reader{ header, value } }; }, [&](span_value& value) NOEXCEPT { - return variant_reader{ span_reader{ header, value } }; + return body_reader{ span_reader{ header, value } }; }, [&](buffer_value& value) NOEXCEPT { - return variant_reader{ buffer_reader{ header, value } }; + return body_reader{ buffer_reader{ header, value } }; }, [&](string_value& value) NOEXCEPT { - return variant_reader{ string_reader{ header, value } }; + return body_reader{ string_reader{ header, value } }; } }, value.value()); } private: - variant_reader reader_; + body_reader reader_; }; class writer { public: using const_buffers_type = asio::const_buffer; - using out_buffer = get_buffer; + using out_buffer = http::get_buffer; template - inline explicit writer(header& header, + inline explicit writer(http::header& header, value_type& value) NOEXCEPT : writer_{ to_writer(header, value) } { @@ -238,7 +240,7 @@ struct BCT_API body protected: /// Create writer matching the caller-defined body inner variant type. template - inline static variant_writer to_writer(Header& header, + inline static body_writer to_writer(Header& header, value_type& value) NOEXCEPT { // Caller should have set optional<>, otherwise set to empty_value. @@ -249,44 +251,44 @@ struct BCT_API body { [&](empty_value& value) NOEXCEPT { - return variant_writer{ empty_writer{ header, value } }; + return body_writer{ empty_writer{ header, value } }; }, [&](json_value& value) NOEXCEPT { // json_writer is not movable (by contained serializer). // So *requires* in-place construction for variant populate. - return variant_writer{ std::in_place_type, + return body_writer{ std::in_place_type, header, value }; }, [&](data_value& value) NOEXCEPT { - return variant_writer{ data_writer{ header, value } }; + return body_writer{ data_writer{ header, value } }; }, [&](file_value& value) NOEXCEPT { - return variant_writer{ file_writer{ header, value } }; + return body_writer{ file_writer{ header, value } }; }, [&](span_value& value) NOEXCEPT { - return variant_writer{ span_writer{ header, value } }; + return body_writer{ span_writer{ header, value } }; }, [&](buffer_value& value) NOEXCEPT { - return variant_writer{ buffer_writer{ header, value } }; + return body_writer{ buffer_writer{ header, value } }; }, [&](string_value& value) NOEXCEPT { - return variant_writer{ string_writer{ header, value } }; + return body_writer{ string_writer{ header, value } }; } }, value.value()); } private: - variant_writer writer_; + body_writer writer_; }; }; -} // namespace http +} // namespace variant } // namespace network } // namespace libbitcoin diff --git a/include/bitcoin/network/messages/variant/head.hpp b/include/bitcoin/network/messages/variant/head.hpp new file mode 100644 index 000000000..a8e74057e --- /dev/null +++ b/include/bitcoin/network/messages/variant/head.hpp @@ -0,0 +1,206 @@ +/** + * Copyright (c) 2011-2025 libbitcoin developers (see AUTHORS) + * + * This file is part of libbitcoin. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#ifndef LIBBITCOIN_NETWORK_MESSAGES_VARIANT_HEAD_HPP +#define LIBBITCOIN_NETWORK_MESSAGES_VARIANT_HEAD_HPP + +#include +#include +#include +#include +#include + +// TODO: relies on http::length_type, get_buffer. + +namespace libbitcoin { +namespace network { +namespace variant { + +/// Variant head<> template, analogous to the variant body<> template. +/// Allows universal request and response message types with single asio async +/// read(request) and write(response) implementations. body<> is auto-selected +/// in the read(request) through its access to the header (e.g. content-type). +/// TODO: move out of http namespace once generalized. + +// TODO: expand these variants to support: +// http framing: request, response [asymmetrical] (using beast). +// line framing: electrum, strantum_v1 (custom head). +// websockets framing: rest API (using beast). +// stratum_v2 framing: stratum_v2 (custom head). +// zeromq framing: rest API (custom head). + +using request_reader = boost::beast::http::parser; +using response_reader = boost::beast::http::parser; +using head_reader = std::variant +< + request_reader, + response_reader +>; + +using request_writer = boost::beast::http::serializer; +using response_writer = boost::beast::http::serializer; +using head_writer = std::variant +< + request_writer, + response_writer +>; + +using request_header = boost::beast::http::header; +using response_header = boost::beast::http::header; +using head_value = std::variant +< + request_header, + response_header +>; + +using empty_request = boost::beast::http::message; +using empty_response = boost::beast::http::message; + +/// header template for all known message types. +/// Request head is selected by reader and response by writer (i.e. channel). +struct BCT_API head +{ + struct head_type + { + head_type() NOEXCEPT = default; + + FORWARD_VARIANT_CONSTRUCT(head_type, inner_) + FORWARD_VARIANT_ASSIGNMENT(head_type, inner_) + FORWARD_ALTERNATIVE_VARIANT_ASSIGNMENT(head_type, request_header, inner_) + FORWARD_ALTERNATIVE_VARIANT_ASSIGNMENT(head_type, response_header, inner_) + + inline bool has_value() const NOEXCEPT + { + return inner_.has_value(); + } + + inline head_value& value() NOEXCEPT + { + return inner_.value(); + } + + inline const head_value& value() const NOEXCEPT + { + return inner_.value(); + } + + template + inline bool contains() const NOEXCEPT + { + return has_value() && std::holds_alternative(value()); + } + + template + inline const Inner& get() const NOEXCEPT + { + BC_ASSERT(contains()); + return std::get(value()); + } + + private: + std::optional inner_{}; + }; + + class reader + { + public: + using buffer_type = asio::const_buffer; + + inline explicit reader(head_type& value) NOEXCEPT + : reader_{ to_reader(value) }, value_{ value } + { + } + + void init(const http::length_type&, boost_code& ec) NOEXCEPT; + size_t put(const buffer_type& buffer, boost_code& ec) NOEXCEPT; + void finish(boost_code& ec) NOEXCEPT; + + protected: + inline static head_reader to_reader(head_type& value) NOEXCEPT + { + // Caller should have set optional<>, otherwise set invalid read. + if (!value.has_value()) + value = response_header{}; + + return std::visit(overload + { + [&](request_header&) NOEXCEPT + { + return head_reader{ std::in_place_type }; + }, + [&](response_header&) NOEXCEPT + { + // Server doesn't read responses. + return head_reader{ std::in_place_type }; + } + }, value.value()); + } + + private: + head_reader reader_; + head_type& value_; + }; + + class writer + { + public: + using const_buffers_type = asio::const_buffer; + using out_buffer = http::get_buffer; + + inline explicit writer(head_type& value) NOEXCEPT + : writer_{ to_writer(value) } + { + } + + void init(boost_code& ec) NOEXCEPT; + out_buffer get(boost_code& ec) NOEXCEPT; + + protected: + /// Create writer matching caller-defined header inner variant type. + inline static head_writer to_writer(head_type& value) NOEXCEPT + { + // Caller should have set optional<>, otherwise set invalid write. + if (!value.has_value()) + value = response_header{}; + + return std::visit(overload + { + [&] (request_header& value) NOEXCEPT + { + // Server doesn't write requests. + return head_writer{ request_writer{ + empty_request{ std::move(value) } } }; + }, + [&](response_header& value) NOEXCEPT + { + return head_writer{ response_writer{ + empty_response{ std::move(value) } } }; + } + }, value.value()); + } + + private: + head_writer writer_; + }; +}; + +} // namespace variant +} // namespace network +} // namespace libbitcoin + +#endif diff --git a/include/bitcoin/network/messages/http/method.hpp b/include/bitcoin/network/messages/variant/method.hpp similarity index 90% rename from include/bitcoin/network/messages/http/method.hpp rename to include/bitcoin/network/messages/variant/method.hpp index 6bd0283cf..33deaf458 100644 --- a/include/bitcoin/network/messages/http/method.hpp +++ b/include/bitcoin/network/messages/variant/method.hpp @@ -16,16 +16,18 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -#ifndef LIBBITCOIN_NETWORK_MESSAGES_HTTP_METHOD_HPP -#define LIBBITCOIN_NETWORK_MESSAGES_HTTP_METHOD_HPP +#ifndef LIBBITCOIN_NETWORK_MESSAGES_VARIANT_METHOD_HPP +#define LIBBITCOIN_NETWORK_MESSAGES_VARIANT_METHOD_HPP #include #include #include -#include +#include /// Type-differentiation for request message distribution. +// TODO: move to variant namespace. + namespace libbitcoin { namespace network { namespace http { diff --git a/include/bitcoin/network/messages/variant/request.hpp b/include/bitcoin/network/messages/variant/request.hpp new file mode 100644 index 000000000..3aa358b88 --- /dev/null +++ b/include/bitcoin/network/messages/variant/request.hpp @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2011-2025 libbitcoin developers (see AUTHORS) + * + * This file is part of libbitcoin. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#ifndef LIBBITCOIN_NETWORK_MESSAGES_VARIANT_REQUEST_HPP +#define LIBBITCOIN_NETWORK_MESSAGES_VARIANT_REQUEST_HPP + +#include +#include + +// TODO: move to variant namespace. +namespace libbitcoin { +namespace network { +namespace http { + +// TODO: move to variant::request. +using request = boost::beast::http::request; +using parser = boost::beast::http::request_parser; +using request_cptr = std::shared_ptr; +using request_ptr = std::shared_ptr; + +} // namespace http +} // namespace network +} // namespace libbitcoin + +#endif diff --git a/include/bitcoin/network/messages/variant/response.hpp b/include/bitcoin/network/messages/variant/response.hpp new file mode 100644 index 000000000..6b79b4602 --- /dev/null +++ b/include/bitcoin/network/messages/variant/response.hpp @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2011-2025 libbitcoin developers (see AUTHORS) + * + * This file is part of libbitcoin. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#ifndef LIBBITCOIN_NETWORK_MESSAGES_VARIANT_RESPONSE_HPP +#define LIBBITCOIN_NETWORK_MESSAGES_VARIANT_RESPONSE_HPP + +#include +#include + + // TODO: move to variant namespace. +namespace libbitcoin { +namespace network { +namespace http { + +// TODO: move to variant::response. +using response = boost::beast::http::response; +using serializer = boost::beast::http::response_serializer; +using response_cptr = std::shared_ptr; +using response_ptr = std::shared_ptr; + +} // namespace http +} // namespace network +} // namespace libbitcoin + +#endif diff --git a/include/bitcoin/network/messages/variant/variant.hpp b/include/bitcoin/network/messages/variant/variant.hpp new file mode 100644 index 000000000..7c768f7ed --- /dev/null +++ b/include/bitcoin/network/messages/variant/variant.hpp @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2011-2025 libbitcoin developers (see AUTHORS) + * + * This file is part of libbitcoin. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#ifndef LIBBITCOIN_NETWORK_MESSAGES_VARIANT_VARIANT_HPP +#define LIBBITCOIN_NETWORK_MESSAGES_VARIANT_VARIANT_HPP + +#include +#include +#include +#include +#include + +#endif diff --git a/include/bitcoin/network/net/proxy.hpp b/include/bitcoin/network/net/proxy.hpp index fe696b46d..9f7a71926 100644 --- a/include/bitcoin/network/net/proxy.hpp +++ b/include/bitcoin/network/net/proxy.hpp @@ -26,8 +26,7 @@ #include #include #include -#include -#include +#include #include namespace libbitcoin { diff --git a/include/bitcoin/network/net/socket.hpp b/include/bitcoin/network/net/socket.hpp index 5fa24721a..ff37d5309 100644 --- a/include/bitcoin/network/net/socket.hpp +++ b/include/bitcoin/network/net/socket.hpp @@ -26,8 +26,7 @@ #include #include #include -#include -#include +#include namespace libbitcoin { namespace network { diff --git a/include/bitcoin/network/protocols/protocol_http.hpp b/include/bitcoin/network/protocols/protocol_http.hpp index 8d150085b..712342a31 100644 --- a/include/bitcoin/network/protocols/protocol_http.hpp +++ b/include/bitcoin/network/protocols/protocol_http.hpp @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/bitcoin/network/rpc/interfaces/http.hpp b/include/bitcoin/network/rpc/interfaces/http.hpp index 574a198a8..1005351c1 100644 --- a/include/bitcoin/network/rpc/interfaces/http.hpp +++ b/include/bitcoin/network/rpc/interfaces/http.hpp @@ -21,7 +21,7 @@ #include #include -#include +#include #include namespace libbitcoin { diff --git a/src/channels/channel_http.cpp b/src/channels/channel_http.cpp index be160c7c0..49dd53880 100644 --- a/src/channels/channel_http.cpp +++ b/src/channels/channel_http.cpp @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include namespace libbitcoin { @@ -166,11 +166,11 @@ void channel_http::send(response&& response, result_handler&& handler) NOEXCEPT void channel_http::set_buffer(response& response) NOEXCEPT { if (const auto& body = response.body(); - body.contains()) + body.contains()) { - const auto& value = body.get(); + const auto& value = body.get(); response_buffer_->max_size(value.size_hint); - body.get().buffer = response_buffer_; + body.get().buffer = response_buffer_; } } diff --git a/src/channels/channel_ws.cpp b/src/channels/channel_ws.cpp index 3b689690c..f084d344a 100644 --- a/src/channels/channel_ws.cpp +++ b/src/channels/channel_ws.cpp @@ -20,7 +20,7 @@ #include #include -#include +#include namespace libbitcoin { namespace network { diff --git a/src/messages/http/fields.cpp b/src/messages/http/fields.cpp index d3afaa121..4c6598b6a 100644 --- a/src/messages/http/fields.cpp +++ b/src/messages/http/fields.cpp @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -#include +#include #include diff --git a/src/messages/http/head.cpp b/src/messages/http/head.cpp new file mode 100644 index 000000000..cad9a6924 --- /dev/null +++ b/src/messages/http/head.cpp @@ -0,0 +1,187 @@ +/////** +//// * Copyright (c) 2011-2025 libbitcoin developers (see AUTHORS) +//// * +//// * This file is part of libbitcoin. +//// * +//// * This program is free software: you can redistribute it and/or modify +//// * it under the terms of the GNU Affero General Public License as published by +//// * the Free Software Foundation, either version 3 of the License, or +//// * (at your option) any later version. +//// * +//// * This program is distributed in the hope that it will be useful, +//// * but WITHOUT ANY WARRANTY; without even the implied warranty of +//// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//// * GNU Affero General Public License for more details. +//// * +//// * You should have received a copy of the GNU Affero General Public License +//// * along with this program. If not, see . +//// */ +////#include +//// +////#include +////#include +////#include +//// +////namespace libbitcoin { +////namespace network { +////namespace http { +//// +////using namespace system; +////using namespace network::error; +//// +////// http::head::reader +////// ---------------------------------------------------------------------------- +//// +////void head::reader::init(const length_type& length, boost_code& ec) NOEXCEPT +////{ +//// std::visit(overload +//// { +//// [&](request_reader& read) NOEXCEPT +//// { +//// try +//// { +//// if (length.has_value()) +//// read.header_limit(narrow_cast(length.value())); +//// +//// read.eager(true); +//// ec.clear(); +//// } +//// catch (...) +//// { +//// ec = to_boost_code(boost_error_t::io_error); +//// } +//// }, +//// [&](response_reader&) NOEXCEPT +//// { +//// // Server doesn't read responses. +//// ec = to_boost_code(boost_error_t::operation_not_supported); +//// } +//// }, reader_); +////} +//// +////size_t head::reader::put(const buffer_type& buffer, boost_code& ec) NOEXCEPT +////{ +//// return std::visit(overload +//// { +//// [&](request_reader& read) NOEXCEPT +//// { +//// try +//// { +//// const auto consumed = read.put(boost::asio::buffer(buffer), ec); +//// if (ec == boost::beast::http::error::need_more) +//// { +//// ec.clear(); +//// return buffer.size(); +//// } +//// +//// if (ec) +//// return zero; +//// +//// if (read.is_header_done()) +//// value_.value().emplace() = read.get(); +//// +//// return consumed; +//// } +//// catch (...) +//// { +//// ec = to_boost_code(boost_error_t::io_error); +//// return zero; +//// } +//// }, +//// [&](response_reader&) NOEXCEPT +//// { +//// // Server doesn't read responses. +//// ec = to_boost_code(boost_error_t::operation_not_supported); +//// return zero; +//// } +//// }, reader_); +////} +//// +////void head::reader::finish(boost_code& ec) NOEXCEPT +////{ +//// std::visit(overload +//// { +//// [&] (request_reader& read) NOEXCEPT +//// { +//// try +//// { +//// if (read.is_header_done()) +//// { +//// ec.clear(); +//// return; +//// } +//// +//// ec = boost::beast::http::error::partial_message; +//// } +//// catch (...) +//// { +//// ec = to_boost_code(boost_error_t::io_error); +//// } +//// }, +//// [&](response_reader&) NOEXCEPT +//// { +//// // Server doesn't read responses. +//// ec = error::operation_failed; +//// } +//// }, reader_); +////} +//// +////// http::head::writer +////// ---------------------------------------------------------------------------- +//// +////void head::writer::init(boost_code& ec) NOEXCEPT +////{ +//// return std::visit(overload +//// { +//// [&] (request_writer&) NOEXCEPT +//// { +//// // Server doesn't write requests. +//// ec = to_boost_code(boost_error_t::operation_not_supported); +//// }, +//// [&](response_writer&) NOEXCEPT +//// { +//// ec.clear(); +//// } +//// }, writer_); +////} +//// +////head::writer::out_buffer head::writer::get(boost_code& ec) NOEXCEPT +////{ +//// std::visit(overload +//// { +//// [&](request_writer&) NOEXCEPT -> out_buffer +//// { +//// // Server doesn't write requests. +//// ec = to_boost_code(boost_error_t::operation_not_supported); +//// return {}; +//// }, +//// [&](response_writer& write) NOEXCEPT -> out_buffer +//// { +//// try +//// { +//// if (write.is_done()) +//// { +//// ec = to_boost_code(boost_error_t::success); +//// return {}; +//// } +//// +//// out_buffer buffer{}; +//// write.next(ec, [&](boost_code&, const auto& buffers) NOEXCEPT +//// { +//// constexpr auto more = true; +//// }); +//// +//// return buffer; +//// } +//// catch (...) +//// { +//// ec = to_boost_code(boost_error_t::io_error); +//// return {}; +//// } +//// } +//// }, writer_); +////} +//// +////} // namespace http +////} // namespace network +////} // namespace libbitcoin diff --git a/src/messages/http/body.cpp b/src/messages/variant/body.cpp similarity index 92% rename from src/messages/http/body.cpp rename to src/messages/variant/body.cpp index 260783351..6b64568e9 100644 --- a/src/messages/http/body.cpp +++ b/src/messages/variant/body.cpp @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -#include +#include #include #include @@ -24,11 +24,12 @@ namespace libbitcoin { namespace network { -namespace http { +namespace variant { +using namespace network::http; using namespace network::error; -// http::body::reader +// variant::body::reader // ---------------------------------------------------------------------------- void body::reader::init(const length_type& length, boost_code& ec) NOEXCEPT @@ -49,8 +50,7 @@ void body::reader::init(const length_type& length, boost_code& ec) NOEXCEPT }, reader_); } -size_t body::reader::put(const buffer_type& buffer, - boost_code& ec) NOEXCEPT +size_t body::reader::put(const buffer_type& buffer, boost_code& ec) NOEXCEPT { return std::visit(overload { @@ -87,7 +87,7 @@ void body::reader::finish(boost_code& ec) NOEXCEPT }, reader_); } -// http::body::writer +// variant::body::writer // ---------------------------------------------------------------------------- void body::writer::init(boost_code& ec) NOEXCEPT @@ -127,6 +127,6 @@ body::writer::out_buffer body::writer::get(boost_code& ec) NOEXCEPT }, writer_); } -} // namespace http +} // namespace variant } // namespace network } // namespace libbitcoin diff --git a/src/messages/variant/head.cpp b/src/messages/variant/head.cpp new file mode 100644 index 000000000..d9b3d7963 --- /dev/null +++ b/src/messages/variant/head.cpp @@ -0,0 +1,188 @@ +/** + * Copyright (c) 2011-2025 libbitcoin developers (see AUTHORS) + * + * This file is part of libbitcoin. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#include + +#include +#include +#include + +namespace libbitcoin { +namespace network { +namespace variant { + +using namespace system; +using namespace network::http; +using namespace network::error; + +// variant::head::reader +// ---------------------------------------------------------------------------- + +void head::reader::init(const length_type& length, boost_code& ec) NOEXCEPT +{ + std::visit(overload + { + [&](request_reader& read) NOEXCEPT + { + try + { + if (length.has_value()) + read.header_limit(narrow_cast(length.value())); + + read.eager(true); + ec.clear(); + } + catch (...) + { + ec = to_boost_code(boost_error_t::io_error); + } + }, + [&](response_reader&) NOEXCEPT + { + // Server doesn't read responses. + ec = to_boost_code(boost_error_t::operation_not_supported); + } + }, reader_); +} + +size_t head::reader::put(const buffer_type& buffer, boost_code& ec) NOEXCEPT +{ + return std::visit(overload + { + [&](request_reader& read) NOEXCEPT + { + try + { + const auto consumed = read.put(boost::asio::buffer(buffer), ec); + if (ec == boost::beast::http::error::need_more) + { + ec.clear(); + return buffer.size(); + } + + if (ec) + return zero; + + if (read.is_header_done()) + value_.value().emplace() = read.get(); + + return consumed; + } + catch (...) + { + ec = to_boost_code(boost_error_t::io_error); + return zero; + } + }, + [&](response_reader&) NOEXCEPT + { + // Server doesn't read responses. + ec = to_boost_code(boost_error_t::operation_not_supported); + return zero; + } + }, reader_); +} + +void head::reader::finish(boost_code& ec) NOEXCEPT +{ + std::visit(overload + { + [&] (request_reader& read) NOEXCEPT + { + try + { + if (read.is_header_done()) + { + ec.clear(); + return; + } + + ec = boost::beast::http::error::partial_message; + } + catch (...) + { + ec = to_boost_code(boost_error_t::io_error); + } + }, + [&](response_reader&) NOEXCEPT + { + // Server doesn't read responses. + ec = error::operation_failed; + } + }, reader_); +} + +// variant::head::writer +// ---------------------------------------------------------------------------- + +void head::writer::init(boost_code& ec) NOEXCEPT +{ + return std::visit(overload + { + [&] (request_writer&) NOEXCEPT + { + // Server doesn't write requests. + ec = to_boost_code(boost_error_t::operation_not_supported); + }, + [&](response_writer&) NOEXCEPT + { + ec.clear(); + } + }, writer_); +} + +head::writer::out_buffer head::writer::get(boost_code& ec) NOEXCEPT +{ + return std::visit(overload + { + [&](request_writer&) NOEXCEPT -> out_buffer + { + // Server doesn't write requests. + ec = to_boost_code(boost_error_t::operation_not_supported); + return {}; + }, + [&](response_writer& write) NOEXCEPT -> out_buffer + { + try + { + if (write.is_done()) + { + ec = to_boost_code(boost_error_t::success); + return {}; + } + + out_buffer buffer{}; + write.next(ec, [&](boost_code&, const auto&) NOEXCEPT + { + ////constexpr auto more = true; + }); + + return buffer; + } + catch (...) + { + ec = to_boost_code(boost_error_t::io_error); + return {}; + } + } + }, writer_); +} + +} // namespace variant +} // namespace network +} // namespace libbitcoin diff --git a/src/protocols/protocol_http.cpp b/src/protocols/protocol_http.cpp index 3df297944..fdaaa7764 100644 --- a/src/protocols/protocol_http.cpp +++ b/src/protocols/protocol_http.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include @@ -33,7 +33,7 @@ namespace libbitcoin { namespace network { #define CLASS protocol_http - + using namespace http; using namespace std::placeholders; diff --git a/include/bitcoin/network/messages/http/request.hpp b/test/messages/http/head_reader.cpp similarity index 72% rename from include/bitcoin/network/messages/http/request.hpp rename to test/messages/http/head_reader.cpp index 6e1173b06..165c36c18 100644 --- a/include/bitcoin/network/messages/http/request.hpp +++ b/test/messages/http/head_reader.cpp @@ -16,18 +16,18 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -#ifndef LIBBITCOIN_NETWORK_MESSAGES_HTTP_REQUEST_HPP -#define LIBBITCOIN_NETWORK_MESSAGES_HTTP_REQUEST_HPP +#include "../../test.hpp" -#include -#include +BOOST_AUTO_TEST_SUITE(http_head_reader_tests) -namespace libbitcoin { -namespace network { -namespace http { +using namespace network::http; -} // namespace http -} // namespace network -} // namespace libbitcoin +////struct accessor +//// : public head::reader +////{ +//// using base = head::reader; +//// using base::reader; +//// using base::to_reader; +////}; -#endif +BOOST_AUTO_TEST_SUITE_END() diff --git a/include/bitcoin/network/messages/http/response.hpp b/test/messages/http/head_writer.cpp similarity index 72% rename from include/bitcoin/network/messages/http/response.hpp rename to test/messages/http/head_writer.cpp index 74eae8530..2d3d46dc7 100644 --- a/include/bitcoin/network/messages/http/response.hpp +++ b/test/messages/http/head_writer.cpp @@ -16,18 +16,18 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -#ifndef LIBBITCOIN_NETWORK_MESSAGES_HTTP_RESPONSE_HPP -#define LIBBITCOIN_NETWORK_MESSAGES_HTTP_RESPONSE_HPP +#include "../../test.hpp" -#include -#include +BOOST_AUTO_TEST_SUITE(http_head_writer_tests) -namespace libbitcoin { -namespace network { -namespace http { +using namespace network::http; -} // namespace http -} // namespace network -} // namespace libbitcoin +////struct accessor +//// : public head::writer +////{ +//// using base = head::writer; +//// using base::writer; +//// using base::to_writer; +////}; -#endif +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/messages/http/body_reader.cpp b/test/messages/variant/body_reader.cpp similarity index 80% rename from test/messages/http/body_reader.cpp rename to test/messages/variant/body_reader.cpp index 44af8dcab..5761ea98b 100644 --- a/test/messages/http/body_reader.cpp +++ b/test/messages/variant/body_reader.cpp @@ -18,9 +18,8 @@ */ #include "../../test.hpp" -BOOST_AUTO_TEST_SUITE(http_body_reader_tests) - -using namespace network::http; +using namespace http; +using namespace network::variant; struct accessor : public body::reader @@ -30,7 +29,9 @@ struct accessor using base::to_reader; }; -BOOST_AUTO_TEST_CASE(http_body_reader__to_reader__bogus__constructs_empty_reader) +BOOST_AUTO_TEST_SUITE(variant_body_reader_tests) + +BOOST_AUTO_TEST_CASE(variant_body_reader__to_reader__bogus__constructs_empty_reader) { header header{}; header.set(http::field::content_type, "bogus"); @@ -40,7 +41,7 @@ BOOST_AUTO_TEST_CASE(http_body_reader__to_reader__bogus__constructs_empty_reader BOOST_REQUIRE(std::holds_alternative(variant)); } -BOOST_AUTO_TEST_CASE(http_body_reader__to_reader__json__constructs_json_reader) +BOOST_AUTO_TEST_CASE(variant_body_reader__to_reader__json__constructs_json_reader) { header header{}; header.set(http::field::content_type, "application/json"); @@ -50,7 +51,7 @@ BOOST_AUTO_TEST_CASE(http_body_reader__to_reader__json__constructs_json_reader) BOOST_REQUIRE(std::holds_alternative(variant)); } -BOOST_AUTO_TEST_CASE(http_body_reader__to_reader__application_octet_stream__constructs_data_reader) +BOOST_AUTO_TEST_CASE(variant_body_reader__to_reader__application_octet_stream__constructs_data_reader) { header header{}; header.set(http::field::content_type, "application/octet-stream"); @@ -61,7 +62,7 @@ BOOST_AUTO_TEST_CASE(http_body_reader__to_reader__application_octet_stream__cons BOOST_REQUIRE(std::holds_alternative(variant)); } -BOOST_AUTO_TEST_CASE(http_body_reader__to_reader__application_octet_stream_with_attachment__constructs_file_reader) +BOOST_AUTO_TEST_CASE(variant_body_reader__to_reader__application_octet_stream_with_attachment__constructs_file_reader) { header header{}; header.set(http::field::content_type, "application/octet-stream"); @@ -72,7 +73,7 @@ BOOST_AUTO_TEST_CASE(http_body_reader__to_reader__application_octet_stream_with_ BOOST_REQUIRE(std::holds_alternative(variant)); } -BOOST_AUTO_TEST_CASE(http_body_reader__to_reader__application_octet_stream_with_dirty_attachment__constructs_file_reader) +BOOST_AUTO_TEST_CASE(variant_body_reader__to_reader__application_octet_stream_with_dirty_attachment__constructs_file_reader) { header header{}; header.set(http::field::content_type, "application/octet-stream"); @@ -83,7 +84,7 @@ BOOST_AUTO_TEST_CASE(http_body_reader__to_reader__application_octet_stream_with_ BOOST_REQUIRE(std::holds_alternative(variant)); } -BOOST_AUTO_TEST_CASE(http_body_reader__to_reader__text_plain__constructs_string_reader) +BOOST_AUTO_TEST_CASE(variant_body_reader__to_reader__text_plain__constructs_string_reader) { header header{}; header.set(http::field::content_type, "text/plain"); diff --git a/test/messages/http/body_writer.cpp b/test/messages/variant/body_writer.cpp similarity index 77% rename from test/messages/http/body_writer.cpp rename to test/messages/variant/body_writer.cpp index d1f50cd2a..ebf5d2c6e 100644 --- a/test/messages/http/body_writer.cpp +++ b/test/messages/variant/body_writer.cpp @@ -18,19 +18,20 @@ */ #include "../../test.hpp" -using namespace network::http; +using namespace http; +using namespace network::variant; struct accessor - : public body::writer + : public body::writer { using base = body::writer; using base::writer; using base::to_writer; }; -BOOST_AUTO_TEST_SUITE(http_body_writer_tests) +BOOST_AUTO_TEST_SUITE(variant_body_writer_tests) -BOOST_AUTO_TEST_CASE(http_body_writer__to_writer__undefined__constructs_empty_writer) +BOOST_AUTO_TEST_CASE(variant_body_writer__to_writer__undefined__constructs_empty_writer) { header header{}; body::value_type value{}; @@ -39,7 +40,7 @@ BOOST_AUTO_TEST_CASE(http_body_writer__to_writer__undefined__constructs_empty_wr BOOST_REQUIRE(std::holds_alternative(variant)); } -BOOST_AUTO_TEST_CASE(http_body_writer__to_writer__empty__constructs_empty_writer) +BOOST_AUTO_TEST_CASE(variant_body_writer__to_writer__empty__constructs_empty_writer) { header header{}; body::value_type value{}; @@ -48,7 +49,7 @@ BOOST_AUTO_TEST_CASE(http_body_writer__to_writer__empty__constructs_empty_writer BOOST_REQUIRE(std::holds_alternative(variant)); } -BOOST_AUTO_TEST_CASE(http_body_writer__to_writer__json__constructs_json_writer) +BOOST_AUTO_TEST_CASE(variant_body_writer__to_writer__json__constructs_json_writer) { header header{}; body::value_type value{}; @@ -57,7 +58,7 @@ BOOST_AUTO_TEST_CASE(http_body_writer__to_writer__json__constructs_json_writer) BOOST_REQUIRE(std::holds_alternative(variant)); } -BOOST_AUTO_TEST_CASE(http_body_writer__to_writer__data__constructs_data_writer) +BOOST_AUTO_TEST_CASE(variant_body_writer__to_writer__data__constructs_data_writer) { header header{}; body::value_type value{}; @@ -66,7 +67,7 @@ BOOST_AUTO_TEST_CASE(http_body_writer__to_writer__data__constructs_data_writer) BOOST_REQUIRE(std::holds_alternative(variant)); } -BOOST_AUTO_TEST_CASE(http_body_writer__to_writer__span__constructs_span_writer) +BOOST_AUTO_TEST_CASE(variant_body_writer__to_writer__span__constructs_span_writer) { header header{}; body::value_type value{}; @@ -75,7 +76,7 @@ BOOST_AUTO_TEST_CASE(http_body_writer__to_writer__span__constructs_span_writer) BOOST_REQUIRE(std::holds_alternative(variant)); } -BOOST_AUTO_TEST_CASE(http_body_writer__to_writer__buffer__constructs_buffer_writer) +BOOST_AUTO_TEST_CASE(variant_body_writer__to_writer__buffer__constructs_buffer_writer) { header header{}; body::value_type value{}; @@ -84,7 +85,7 @@ BOOST_AUTO_TEST_CASE(http_body_writer__to_writer__buffer__constructs_buffer_writ BOOST_REQUIRE(std::holds_alternative(variant)); } -BOOST_AUTO_TEST_CASE(http_body_writer__to_writer__string__constructs_string_writer) +BOOST_AUTO_TEST_CASE(variant_body_writer__to_writer__string__constructs_string_writer) { header header{}; body::value_type value{}; @@ -95,9 +96,9 @@ BOOST_AUTO_TEST_CASE(http_body_writer__to_writer__string__constructs_string_writ BOOST_AUTO_TEST_SUITE_END() -BOOST_FIXTURE_TEST_SUITE(http_body_writer_file_body_tests, test::directory_setup_fixture) +BOOST_FIXTURE_TEST_SUITE(variant_body_writer_file_body_tests, test::directory_setup_fixture) -BOOST_AUTO_TEST_CASE(http_body_writer__to_writer__file__constructs_file_writer) +BOOST_AUTO_TEST_CASE(variant_body_writer__to_writer__file__constructs_file_writer) { // In dubug builds boost asserts that the file is open. // BOOST_ASSERT(body_.file_.is_open()); diff --git a/test/messages/variant/head_reader.cpp b/test/messages/variant/head_reader.cpp new file mode 100644 index 000000000..228e702e3 --- /dev/null +++ b/test/messages/variant/head_reader.cpp @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2011-2025 libbitcoin developers (see AUTHORS) + * + * This file is part of libbitcoin. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#include "../../test.hpp" + +BOOST_AUTO_TEST_SUITE(variant_head_reader_tests) + +using namespace network::variant; + +////struct accessor +//// : public head::reader +////{ +//// using base = head::reader; +//// using base::reader; +//// using base::to_reader; +////}; + +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/messages/variant/head_writer.cpp b/test/messages/variant/head_writer.cpp new file mode 100644 index 000000000..903034587 --- /dev/null +++ b/test/messages/variant/head_writer.cpp @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2011-2025 libbitcoin developers (see AUTHORS) + * + * This file is part of libbitcoin. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#include "../../test.hpp" + +BOOST_AUTO_TEST_SUITE(variant_head_writer_tests) + +using namespace network::variant; + +////struct accessor +//// : public head::writer +////{ +//// using base = head::writer; +//// using base::writer; +//// using base::to_writer; +////}; + +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/messages/http/method.cpp b/test/messages/variant/method.cpp similarity index 97% rename from test/messages/http/method.cpp rename to test/messages/variant/method.cpp index a536573bf..136533077 100644 --- a/test/messages/http/method.cpp +++ b/test/messages/variant/method.cpp @@ -18,7 +18,7 @@ */ #include "../../test.hpp" -BOOST_AUTO_TEST_SUITE(http_method_tests) +BOOST_AUTO_TEST_SUITE(variant_method_tests) using namespace network::http::method;