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