diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a269ae9fe..b37defc9b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -578,17 +578,6 @@ jobs: platform: "x64" version: "vs2022" tests: "*" - - image: windows-2025-vs2026 - configuration: "StaticRelease" - platform: "x64" - version: "vs2026" - tests: "*" - - - image: windows-2025-vs2026 - configuration: "StaticDebug" - platform: "x64" - version: "vs2026" - tests: "*" runs-on: ${{ matrix.image }} diff --git a/Makefile.am b/Makefile.am index ecf96dd63..1bbe3d5f1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -45,7 +45,6 @@ src_libbitcoin_network_la_SOURCES = \ src/channels/channel.cpp \ src/channels/channel_http.cpp \ src/channels/channel_peer.cpp \ - src/channels/channel_ws.cpp \ src/config/address.cpp \ src/config/authority.cpp \ src/config/endpoint.cpp \ @@ -222,7 +221,6 @@ test_libbitcoin_network_test_SOURCES = \ test/channels/channel_http.cpp \ test/channels/channel_peer.cpp \ test/channels/channel_rpc.cpp \ - test/channels/channel_ws.cpp \ test/config/address.cpp \ test/config/authority.cpp \ test/config/endpoint.cpp \ @@ -513,7 +511,6 @@ include_bitcoin_network_channels_HEADERS = \ include/bitcoin/network/channels/channel_http.hpp \ include/bitcoin/network/channels/channel_peer.hpp \ include/bitcoin/network/channels/channel_rpc.hpp \ - include/bitcoin/network/channels/channel_ws.hpp \ include/bitcoin/network/channels/channels.hpp include_bitcoin_network_configdir = ${includedir}/bitcoin/network/config @@ -693,7 +690,6 @@ include_bitcoin_network_protocols_HEADERS = \ include/bitcoin/network/protocols/protocol_version_70001.hpp \ include/bitcoin/network/protocols/protocol_version_70002.hpp \ include/bitcoin/network/protocols/protocol_version_70016.hpp \ - include/bitcoin/network/protocols/protocol_ws.hpp \ include/bitcoin/network/protocols/protocols.hpp include_bitcoin_network_sessionsdir = ${includedir}/bitcoin/network/sessions 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 3be694f54..6fd2bc26d 100644 --- a/builds/msvc/vs2022/libbitcoin-network-test/libbitcoin-network-test.vcxproj +++ b/builds/msvc/vs2022/libbitcoin-network-test/libbitcoin-network-test.vcxproj @@ -134,7 +134,6 @@ - $(IntDir)test_config_address.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 264dbeca4..1d5ff0a3c 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 @@ -153,9 +153,6 @@ src\channels - - src\channels - src\config diff --git a/builds/msvc/vs2022/libbitcoin-network/libbitcoin-network.vcxproj b/builds/msvc/vs2022/libbitcoin-network/libbitcoin-network.vcxproj index f8f5c2729..f1eeba864 100644 --- a/builds/msvc/vs2022/libbitcoin-network/libbitcoin-network.vcxproj +++ b/builds/msvc/vs2022/libbitcoin-network/libbitcoin-network.vcxproj @@ -128,7 +128,6 @@ - $(IntDir)src_config_address.obj @@ -312,7 +311,6 @@ - @@ -427,7 +425,6 @@ - diff --git a/builds/msvc/vs2022/libbitcoin-network/libbitcoin-network.vcxproj.filters b/builds/msvc/vs2022/libbitcoin-network/libbitcoin-network.vcxproj.filters index 341431d97..b428ac415 100644 --- a/builds/msvc/vs2022/libbitcoin-network/libbitcoin-network.vcxproj.filters +++ b/builds/msvc/vs2022/libbitcoin-network/libbitcoin-network.vcxproj.filters @@ -189,9 +189,6 @@ src\channels - - src\channels - src\config @@ -701,9 +698,6 @@ include\bitcoin\network\channels - - include\bitcoin\network\channels - include\bitcoin\network\channels @@ -1046,9 +1040,6 @@ include\bitcoin\network\protocols - - include\bitcoin\network\protocols - include\bitcoin\network\protocols diff --git a/include/bitcoin/network.hpp b/include/bitcoin/network.hpp index ce81ce1a5..9773e2e38 100644 --- a/include/bitcoin/network.hpp +++ b/include/bitcoin/network.hpp @@ -45,7 +45,6 @@ #include #include #include -#include #include #include #include @@ -154,7 +153,6 @@ #include #include #include -#include #include #include #include diff --git a/include/bitcoin/network/channels/channel_rpc.hpp b/include/bitcoin/network/channels/channel_rpc.hpp index a97ee278c..a7f55724e 100644 --- a/include/bitcoin/network/channels/channel_rpc.hpp +++ b/include/bitcoin/network/channels/channel_rpc.hpp @@ -26,39 +26,19 @@ #include #include +// TODO: This template can be re-based on channel_http giving it the ability to +// TODO: support RPC over both tcp and http/ws. In that case the settings type +// TODO: can be templatized and reader/writer configured at compile. Without an +// TODO: http reader the socket cannot be upgraded to ws and thus operates as a +// TODO: simple TCP socket, and TLS remains possible with all protocols. Http +// TODO: methods are dispatched from channel to base protocol and re-dispatched +// TODO: to subscribers. TCP/WS are dispatched to protocol as a custom method. +// TODO: this allows the base protocol to differentiate these as non-http for +// TODO: selection of the proper response path. As http is half duplex, notify +// TODO: is only provided to a TCP or upgraded (WS) socket. + namespace libbitcoin { namespace network { - -// TODO: Interface argument provides templated dispatch for rpc protocols. -// TODO: transport independent sender methods in each are duck typed for rpc protocol. -// TODO: network::channel_trpc : network::channel -// TODO: network::channel_wrpc : network::channel_ws -// : network::channel_http -// : network::channel -// -// TODO: reused channel state unique to electrum/bitcoind. -// TODO: server::channel_electrum_base -// TODO: server::channel_bitcoind_base -// -// TODO: aliases. -// TODO: server::channel_electrum_tcp : channel_electrum_base, network::channel_trpc -// TODO: server::channel_electrum_web : channel_electrum_base, network::channel_wrpc -// TODO: server::channel_bitcoind_tcp : channel_bitcoind_base, network::channel_trpc -// TODO: server::channel_bitcoind_web : channel_bitcoind_base, network::channel_wrpc -// -// TODO: base sender methods for passthrough to channel senders. -// TODO: these could be implemented in the two protocols to reduce compile time. -// TODO: network::protocol_rpc : network::protocol -// -// TODO: reused protocol logic unique to electrum/bitcoind. -// TODO: server::protocol_electrum : network::protocol_rpc -// TODO: server::protocol_bitcoind : network::protocol_rpc -// -// TODO: aliases. -// TODO: server::protocol_electrum_tcp : network::protocol_electrum -// TODO: server::protocol_electrum_web : network::protocol_electrum -// TODO: server::protocol_bitcoind_tcp : network::protocol_bitcoind -// TODO: server::protocol_bitcoind_web : network::protocol_bitcoind /// Read rpc-request and send rpc-response, dispatch to Interface. template diff --git a/include/bitcoin/network/channels/channel_ws.hpp b/include/bitcoin/network/channels/channel_ws.hpp deleted file mode 100644 index 30d315099..000000000 --- a/include/bitcoin/network/channels/channel_ws.hpp +++ /dev/null @@ -1,71 +0,0 @@ -/** - * Copyright (c) 2011-2026 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_CHANNELS_CHANNEL_WS_HPP -#define LIBBITCOIN_NETWORK_CHANNELS_CHANNEL_WS_HPP - -#include -#include -#include -#include -#include -#include - -namespace libbitcoin { -namespace network { - -/// Abstract base websocket tcp/ip channel, on base http channel. -class BCT_API channel_ws - : public channel_http -{ -public: - typedef std::shared_ptr ptr; - using options_t = settings_t::websocket_server; - -protected: - inline channel_ws(const logger& log, const socket::ptr& socket, - uint64_t identifier, const settings_t& settings, - const options_t& options) NOEXCEPT - : channel_http(log, socket, identifier, settings, options) - { - } - - /// Reads are never buffered, restart the reader. - void receive() NOEXCEPT override; - - /// Pre-upgrade http read. - void handle_receive(const code& ec, size_t bytes, - const http::request_cptr& request) NOEXCEPT override; - - /// Post-upgrade websocket read. - virtual void handle_receive_ws(const code& ec, size_t bytes) NOEXCEPT; - - /// Dispatch websocket buffer via derived handlers (override to handle). - /// Override to handle dispatch, must invoke receive() on complete. - virtual void dispatch_ws(const http::flat_buffer& buffer, - size_t bytes) NOEXCEPT; - -private: - // This is protected by strand. - bool upgraded_{ false }; -}; - -} // namespace network -} // namespace libbitcoin - -#endif diff --git a/include/bitcoin/network/channels/channels.hpp b/include/bitcoin/network/channels/channels.hpp index 9cfdf2b5d..e73bf5deb 100644 --- a/include/bitcoin/network/channels/channels.hpp +++ b/include/bitcoin/network/channels/channels.hpp @@ -23,6 +23,5 @@ #include #include #include -#include #endif diff --git a/include/bitcoin/network/net/proxy.hpp b/include/bitcoin/network/net/proxy.hpp index 004b612a4..0fbd56db5 100644 --- a/include/bitcoin/network/net/proxy.hpp +++ b/include/bitcoin/network/net/proxy.hpp @@ -132,10 +132,10 @@ class BCT_API proxy /// Binary or text mode applies to websockets (no-op for tcp). /// Write the provided buffer to socket, handler posted to socket strand. - virtual void write(const asio::const_buffer& in, - count_handler&& handler, bool binary) NOEXCEPT; + virtual void write(const asio::const_buffer& in, bool binary, + count_handler&& handler) NOEXCEPT; - /// P2P (generic, fixed size). + /// P2P (generic, fixed size, WS: always binary). /// ----------------------------------------------------------------------- /// Read fixed-size TCP message from the remote endpoint into buffer. diff --git a/include/bitcoin/network/net/socket.hpp b/include/bitcoin/network/net/socket.hpp index ed75b1f8f..72c3f854e 100644 --- a/include/bitcoin/network/net/socket.hpp +++ b/include/bitcoin/network/net/socket.hpp @@ -120,8 +120,8 @@ class BCT_API socket /// Binary or text mode applies to websockets (no-op for tcp). /// Write the provided buffer to socket, handler posted to socket strand. - virtual void raw_write(const asio::const_buffer& in, - count_handler&& handler, bool binary=true) NOEXCEPT; + virtual void raw_write(const asio::const_buffer& in, bool binary, + count_handler&& handler) NOEXCEPT; /// P2P (generic, fixed size). /// ----------------------------------------------------------------------- diff --git a/include/bitcoin/network/protocols/protocol_ws.hpp b/include/bitcoin/network/protocols/protocol_ws.hpp deleted file mode 100644 index cde800a6f..000000000 --- a/include/bitcoin/network/protocols/protocol_ws.hpp +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Copyright (c) 2011-2026 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_PROTOCOL_WS_HPP -#define LIBBITCOIN_NETWORK_PROTOCOL_WS_HPP - -#include -#include -#include -#include - -namespace libbitcoin { -namespace network { - -class BCT_API protocol_ws - : public protocol_http -{ -public: - typedef std::shared_ptr ptr; - using channel_t = channel_ws; - using options_t = channel_t::options_t; - -protected: - inline protocol_ws(const session::ptr& session, - const channel::ptr& channel, const options_t& options) NOEXCEPT - : protocol_http(session, channel, options) - { - } -}; - -} // namespace network -} // namespace libbitcoin - -#endif diff --git a/include/bitcoin/network/protocols/protocols.hpp b/include/bitcoin/network/protocols/protocols.hpp index 688b0d153..070119a37 100644 --- a/include/bitcoin/network/protocols/protocols.hpp +++ b/include/bitcoin/network/protocols/protocols.hpp @@ -38,6 +38,5 @@ // server #include #include -#include #endif diff --git a/src/channels/channel_ws.cpp b/src/channels/channel_ws.cpp deleted file mode 100644 index 066fd4327..000000000 --- a/src/channels/channel_ws.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/** - * Copyright (c) 2011-2026 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 { - -#define CLASS channel_ws - -using namespace system; -using namespace network::http; -using namespace std::placeholders; - -BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT) - -// public/virtual -// ---------------------------------------------------------------------------- - -void channel_ws::receive() NOEXCEPT -{ - BC_ASSERT(stranded()); - - if (stopped() || paused() || !upgraded_) - { - channel_http::receive(); - return; - } - - read(request_buffer(), - std::bind(&channel_ws::handle_receive_ws, - shared_from_base(), _1, _2)); -} - -// upgraded -// ---------------------------------------------------------------------------- - -void channel_ws::handle_receive_ws(const code& ec, size_t bytes) NOEXCEPT -{ - BC_ASSERT(stranded()); - - if (stopped()) - { - LOGQ("Websocket read abort [" << endpoint() << "]"); - return; - } - - if (ec) - { - // Don't log common conditions. - if (ec != error::peer_disconnect && ec != error::operation_canceled) - { - LOGF("Websocket read failure [" << endpoint() << "] " - << ec.message()); - } - - stop(ec); - return; - } - - dispatch_ws(request_buffer(), bytes); -} - -void channel_ws::dispatch_ws(const http::flat_buffer&, - size_t LOG_ONLY(bytes)) NOEXCEPT -{ - LOGA("Websocket read of " << bytes << " bytes [" << endpoint() << "]"); - - // TODO: dispatch and restart upon completion. - - // Restart reader. - receive(); -} - -// pre-upgrade -// ---------------------------------------------------------------------------- - -void channel_ws::handle_receive(const code& ec, size_t bytes, - const http::request_cptr& request) NOEXCEPT -{ - BC_ASSERT(stranded()); - - if (upgraded_) - { - LOGF("Http request in websocket state [" << endpoint() << "]"); - stop(network::error::operation_failed); - return; - } - - if (ec != error::upgraded) - { - channel_http::handle_receive(ec, bytes, request); - return; - } - - upgraded_ = true; - LOGA("Websocket upgraded [" << endpoint() << "]"); - receive(); -} - -BC_POP_WARNING() - -} // namespace network -} // namespace libbitcoin diff --git a/src/net/deadline.cpp b/src/net/deadline.cpp index c886a04fa..6b3c428f7 100644 --- a/src/net/deadline.cpp +++ b/src/net/deadline.cpp @@ -39,12 +39,12 @@ deadline::deadline(const logger& log, asio::strand& strand, timer_(strand), tracker(log) { - timer_.expires_after(timeout); + // Timer is disarmed (epoch) at construct. } deadline::~deadline() NOEXCEPT { - BC_ASSERT_MSG(timer_.expiry() == epoch, ""); + BC_ASSERT(timer_.expiry() == epoch); } // Start/stop must not be called concurrently. diff --git a/src/net/proxy_actions.cpp b/src/net/proxy_actions.cpp index 291c608b1..bd9403888 100644 --- a/src/net/proxy_actions.cpp +++ b/src/net/proxy_actions.cpp @@ -52,8 +52,8 @@ void proxy::read(http::flat_buffer& out, count_handler&& handler) NOEXCEPT socket_->raw_read(out, std::move(handler)); } -void proxy::write(const asio::const_buffer& in, count_handler&& handler, - bool binary) NOEXCEPT +void proxy::write(const asio::const_buffer& in, bool binary, + count_handler&& handler) NOEXCEPT { writer call = std::bind(&proxy::do_raw_write, shared_from_this(), in, binary, std::move(handler)); @@ -67,9 +67,9 @@ void proxy::write(const asio::const_buffer& in, count_handler&& handler, void proxy::do_raw_write(const asio::const_buffer& payload, bool binary, const count_handler& handler) NOEXCEPT { - socket_->raw_write({ payload.data(), payload.size() }, + socket_->raw_write({ payload.data(), payload.size() }, binary, std::bind(&proxy::handle_write, - shared_from_this(), _1, _2, handler), binary); + shared_from_this(), _1, _2, handler)); } // P2P (generic, fixed size). diff --git a/src/net/socket_p2p.cpp b/src/net/socket_p2p.cpp index 442b7b817..4a4412100 100644 --- a/src/net/socket_p2p.cpp +++ b/src/net/socket_p2p.cpp @@ -54,7 +54,7 @@ void socket::do_p2p_read(const asio::mutable_buffer& out, void socket::p2p_write(const asio::const_buffer& in, count_handler&& handler) NOEXCEPT { - raw_write(in, std::move(handler), true); + raw_write(in, true, std::move(handler)); } BC_POP_WARNING() diff --git a/src/net/socket_raw.cpp b/src/net/socket_raw.cpp index ffe859fbb..59145e936 100644 --- a/src/net/socket_raw.cpp +++ b/src/net/socket_raw.cpp @@ -32,6 +32,9 @@ BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT) // RAW (read). // ---------------------------------------------------------------------------- +// The flat_buffer must have sufficient capacity already allocated before the +// RAW read is initiated. If the incoming WebSocket message exceeds the current +// capacity, the read will fail or truncate. void socket::raw_read(http::flat_buffer& out, count_handler&& handler) NOEXCEPT { @@ -51,8 +54,10 @@ void socket::do_raw_read(ref out, // RAW (write). // ---------------------------------------------------------------------------- -void socket::raw_write(const asio::const_buffer& in, - count_handler&& handler, bool binary) NOEXCEPT +// The const_buffer is fully allocated before write, so this is currently +// identical to p2p write. +void socket::raw_write(const asio::const_buffer& in, bool binary, + count_handler&& handler) NOEXCEPT { boost::asio::dispatch(strand_, std::bind(&socket::do_raw_write, diff --git a/src/net/socket_rpc.cpp b/src/net/socket_rpc.cpp index 7ad6f5122..564a92108 100644 --- a/src/net/socket_rpc.cpp +++ b/src/net/socket_rpc.cpp @@ -148,7 +148,7 @@ void socket::do_rpc_write(boost_code ec, size_t total, BC_ASSERT(buffer.has_value()); - async_write(buffer.value().first, true, + async_write(buffer.value().first, false, std::bind(&socket::handle_rpc_write, shared_from_this(), _1, _2, total, out, handler)); } @@ -210,7 +210,7 @@ void socket::do_rpc_notify(boost_code ec, size_t total, BC_ASSERT(buffer.has_value()); - async_write(buffer.value().first, true, + async_write(buffer.value().first, false, std::bind(&socket::handle_rpc_notify, shared_from_this(), _1, _2, total, out, handler)); } diff --git a/test/channels/channel_ws.cpp b/test/channels/channel_ws.cpp deleted file mode 100644 index 6d7c3eb62..000000000 --- a/test/channels/channel_ws.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Copyright (c) 2011-2026 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(channel_ws_tests) - -BOOST_AUTO_TEST_CASE(channel_ws_tests) -{ - BOOST_REQUIRE(true); -} - -BOOST_AUTO_TEST_SUITE_END()