Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions include/bitcoin/network/channels/channel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ class BCT_API channel
/// Configuration settings.
const settings_t& settings() const NOEXCEPT;

/// TCP server options.
const options_t& options() const NOEXCEPT;

protected:
/// Construct a channel to encapsulated and communicate on the socket.
channel(const logger& log, const socket::ptr& socket, uint64_t identifier,
Expand All @@ -112,6 +115,7 @@ class BCT_API channel
void handle_monitor(const code& ec) NOEXCEPT;

// These are thread safe (const).
const options_t& options_;
const settings_t& settings_;
const uint64_t identifier_;
const uint64_t nonce_
Expand Down
13 changes: 6 additions & 7 deletions include/bitcoin/network/channels/channel_http.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,28 +52,27 @@ class BCT_API channel_http
dispatcher_.subscribe(std::forward<signature>(handler));
}

// TODO: network.minimum_buffer is being overloaded here.
/// Construct http channel to encapsulate and communicate on the socket.
inline channel_http(const logger& log, const socket::ptr& socket,
uint64_t identifier, const settings_t& settings,
const options_t& options) NOEXCEPT
: channel(log, socket, identifier, settings, options),
response_buffer_(system::to_shared<http::flat_buffer>()),
request_buffer_(settings.minimum_buffer)
request_buffer_(options.minimum_buffer)
{
}

/// Serialize and write http message to client (requires strand).
/// Completion handler is always invoked on the channel strand.
void send(http::response&& response,
result_handler&& handler) NOEXCEPT;

/// Resume reading from the socket (requires strand).
void resume() NOEXCEPT override;

/// Must call after successful message handling if no stop.
virtual void receive() NOEXCEPT;

/// Serialize and write http message to client (requires strand).
/// Completion handler is always invoked on the channel strand.
virtual void send(http::response&& response,
result_handler&& handler) NOEXCEPT;

protected:
/// Stranded handler invoked from stop().
void stopping(const code& ec) NOEXCEPT override;
Expand Down
3 changes: 1 addition & 2 deletions include/bitcoin/network/channels/channel_rpc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,13 @@ class BCT_API channel_rpc
dispatcher_.subscribe(std::forward<Handler>(handler));
}

// TODO: network.minimum_buffer is being overloaded here.
/// Construct rpc channel to encapsulate and communicate on the socket.
inline channel_rpc(const logger& log, const socket::ptr& socket,
uint64_t identifier, const settings_t& settings,
const options_t& options) NOEXCEPT
: channel(log, socket, identifier, settings, options),
response_buffer_(system::to_shared<http::flat_buffer>()),
request_buffer_(settings.minimum_buffer)
request_buffer_(options.minimum_buffer)
{
}

Expand Down
1 change: 1 addition & 0 deletions include/bitcoin/network/net/socket.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ class BCT_API socket
std::atomic_bool stopped_{};

// These are protected by strand (see also handle_accept).
size_t maximum_;
asio::socket socket_;
config::address address_;
config::authority authority_{};
Expand Down
16 changes: 10 additions & 6 deletions include/bitcoin/network/settings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@
namespace libbitcoin {
namespace network {

/// The largest p2p payload request when configured for witness blocks.
constexpr uint32_t maximum_request_
{
system::possible_narrow_cast<uint32_t>(
messages::peer::heading::maximum_payload(
messages::peer::level::canonical, true))
};

/// Common network configuration settings, properties not thread safe.
struct BCT_API settings
{
Expand All @@ -44,6 +52,8 @@ struct BCT_API settings
uint16_t connections{ 0 };
uint32_t inactivity_minutes{ 10 };
uint32_t expiration_minutes{ 60 };
uint32_t maximum_request{ maximum_request_ };
uint32_t minimum_buffer{ maximum_request_ };

/// Helpers.
virtual bool enabled() const NOEXCEPT;
Expand Down Expand Up @@ -220,12 +230,6 @@ struct BCT_API settings
uint32_t handshake_timeout_seconds{ 15 };
uint32_t channel_heartbeat_minutes{ 5 };
uint32_t maximum_skew_minutes{ 120 };
uint32_t minimum_buffer
{
system::possible_narrow_cast<uint32_t>(
messages::peer::heading::maximum_payload(
messages::peer::level::canonical, true))
};
uint32_t rate_limit{ 1024 };
std::string user_agent{ BC_USER_AGENT };
std::filesystem::path path{};
Expand Down
10 changes: 9 additions & 1 deletion src/channels/channel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,10 @@ inline deadline::ptr make_timer(const logger& log, asio::strand& strand,
channel::channel(const logger& log, const socket::ptr& socket,
uint64_t identifier, const settings_t& settings,
const options_t& options) NOEXCEPT
: proxy(socket), settings_(settings), identifier_(identifier),
: proxy(socket),
options_(options),
settings_(settings),
identifier_(identifier),
inactivity_(make_timer(log, socket->strand(), options.inactivity())),
expiration_(make_timer(log, socket->strand(), options.expiration()))
{
Expand Down Expand Up @@ -221,6 +224,11 @@ const network::settings& channel::settings() const NOEXCEPT
return settings_;
}

const channel::options_t& channel::options() const NOEXCEPT
{
return options_;
}

BC_POP_WARNING()

} // namespace network
Expand Down
4 changes: 2 additions & 2 deletions src/channels/channel_peer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -304,9 +304,9 @@ void channel_peer::handle_read_payload(const code& ec, size_t payload_size,
///////////////////////////////////////////////////////////////////////////

// Don't retain larger than configured (time-space tradeoff).
if (settings().minimum_buffer < payload_buffer_.capacity())
if (options().minimum_buffer < payload_buffer_.capacity())
{
payload_buffer_.resize(settings().minimum_buffer);
payload_buffer_.resize(options().minimum_buffer);
payload_buffer_.shrink_to_fit();
}

Expand Down
12 changes: 5 additions & 7 deletions src/net/socket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,6 @@ using namespace network::rpc;
using namespace std::placeholders;
namespace beast = boost::beast;

// TODO: move to config.
constexpr size_t client_request_limit = 5u * 1024u * 1024u;

// Shared pointers required in handler parameters so closures control lifetime.
BC_PUSH_WARNING(NO_VALUE_OR_CONST_REF_SHARED_PTR)
BC_PUSH_WARNING(SMART_PTR_NOT_NEEDED)
Expand All @@ -59,6 +56,7 @@ socket::socket(const logger& log, asio::io_context& service) NOEXCEPT
socket::socket(const logger& log, asio::io_context& service,
const config::address& address) NOEXCEPT
: strand_(service.get_executor()),
maximum_(5u * 1024u * 1024u),
socket_(strand_),
service_(service),
address_(address),
Expand Down Expand Up @@ -551,10 +549,10 @@ void socket::do_http_read(std::reference_wrapper<http::flat_buffer> buffer,
auto parser = to_shared<http_parser>();

// Causes http::error::body_limit on completion.
parser->body_limit(client_request_limit);
parser->body_limit(maximum_);

// Causes http::error::header_limit on completion.
parser->header_limit(client_request_limit);
parser->header_limit(limit<uint32_t>(maximum_));

// This operation posts handler to the strand.
beast::http::async_read(socket_, buffer.get(), *parser,
Expand Down Expand Up @@ -675,7 +673,7 @@ void socket::handle_rpc_read(boost_code ec, size_t size, size_t total,
return;
}

if (total > client_request_limit)
if (total > maximum_)
{
handler(error::message_overflow, total);
return;
Expand Down Expand Up @@ -894,7 +892,7 @@ code socket::set_websocket(const http::request& request) NOEXCEPT
websocket_.emplace(std::move(socket_));

// Causes websocket::error::message_too_big on completion.
websocket_->read_message_max(client_request_limit);
websocket_->read_message_max(maximum_);
websocket_->set_option(ws::decorator
{
[](http::fields& header) NOEXCEPT
Expand Down
1 change: 0 additions & 1 deletion test/channels/channel_peer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ BOOST_AUTO_TEST_CASE(channel_peer__properties__default__expected)
BOOST_REQUIRE_EQUAL(channel_ptr->settings().maximum_payload(), payload_maximum(set));
BOOST_REQUIRE_EQUAL(channel_ptr->settings().identifier, set.identifier);
BOOST_REQUIRE_EQUAL(channel_ptr->settings().validate_checksum, set.validate_checksum);
BOOST_REQUIRE_EQUAL(channel_ptr->settings().minimum_buffer, set.minimum_buffer);

// Stop is asynchronous, threadpool destruct blocks until all complete.
// Calling stop here sets channel.stopped and prevents destructor assertion.
Expand Down
8 changes: 7 additions & 1 deletion test/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ BOOST_AUTO_TEST_CASE(settings__construct__default__expected)
BOOST_REQUIRE_EQUAL(instance.handshake_timeout_seconds, 15u);
BOOST_REQUIRE_EQUAL(instance.channel_heartbeat_minutes, 5u);
BOOST_REQUIRE_EQUAL(instance.maximum_skew_minutes, 120u);
BOOST_REQUIRE_EQUAL(instance.minimum_buffer, 4'000'000u);
BOOST_REQUIRE_EQUAL(instance.rate_limit, 1024u);
BOOST_REQUIRE_EQUAL(instance.user_agent, BC_USER_AGENT);
BOOST_REQUIRE(instance.path.empty());
Expand Down Expand Up @@ -344,6 +343,7 @@ BOOST_AUTO_TEST_CASE(settings__excluded__default__true)

// services
// ----------------------------------------------------------------------------
constexpr auto maximum_request = system::chain::max_block_weight;

BOOST_AUTO_TEST_CASE(settings__tcp_server__defaults__expected)
{
Expand All @@ -357,6 +357,7 @@ BOOST_AUTO_TEST_CASE(settings__tcp_server__defaults__expected)
BOOST_REQUIRE_EQUAL(instance.connections, 0u);
BOOST_REQUIRE_EQUAL(instance.inactivity_minutes, 10u);
BOOST_REQUIRE_EQUAL(instance.expiration_minutes, 60u);
BOOST_REQUIRE_EQUAL(instance.maximum_request, maximum_request);
BOOST_REQUIRE(!instance.enabled());
BOOST_REQUIRE(instance.inactivity() == minutes(10));
BOOST_REQUIRE(instance.expiration() == minutes(60));
Expand All @@ -374,6 +375,7 @@ BOOST_AUTO_TEST_CASE(settings__http_server__defaults__expected)
BOOST_REQUIRE_EQUAL(instance.connections, 0u);
BOOST_REQUIRE_EQUAL(instance.inactivity_minutes, 10u);
BOOST_REQUIRE_EQUAL(instance.expiration_minutes, 60u);
BOOST_REQUIRE_EQUAL(instance.maximum_request, maximum_request);
BOOST_REQUIRE(!instance.enabled());
BOOST_REQUIRE(instance.inactivity() == minutes(10));
BOOST_REQUIRE(instance.expiration() == minutes(60));
Expand All @@ -399,6 +401,7 @@ BOOST_AUTO_TEST_CASE(settings__websocket_server__defaults__expected)
BOOST_REQUIRE_EQUAL(instance.connections, 0u);
BOOST_REQUIRE_EQUAL(instance.inactivity_minutes, 10u);
BOOST_REQUIRE_EQUAL(instance.expiration_minutes, 60u);
BOOST_REQUIRE_EQUAL(instance.maximum_request, maximum_request);
BOOST_REQUIRE(!instance.enabled());
BOOST_REQUIRE(instance.inactivity() == minutes(10));
BOOST_REQUIRE(instance.expiration() == minutes(60));
Expand All @@ -425,6 +428,7 @@ BOOST_AUTO_TEST_CASE(settings__peer_outbound__mainnet__expected)
BOOST_REQUIRE_EQUAL(instance.connections, 10u);
BOOST_REQUIRE_EQUAL(instance.inactivity_minutes, 10u);
BOOST_REQUIRE_EQUAL(instance.expiration_minutes, 60u);
BOOST_REQUIRE_EQUAL(instance.maximum_request, maximum_request);
BOOST_REQUIRE(!instance.enabled());
BOOST_REQUIRE(instance.inactivity() == minutes(10));
BOOST_REQUIRE(instance.expiration() == minutes(60));
Expand Down Expand Up @@ -545,6 +549,7 @@ BOOST_AUTO_TEST_CASE(settings__peer_inbound__mainnet__expected)
BOOST_REQUIRE_EQUAL(instance.connections, 0u);
BOOST_REQUIRE_EQUAL(instance.inactivity_minutes, 10u);
BOOST_REQUIRE_EQUAL(instance.expiration_minutes, 60u);
BOOST_REQUIRE_EQUAL(instance.maximum_request, maximum_request);
BOOST_REQUIRE(!instance.enabled());
BOOST_REQUIRE(instance.inactivity() == minutes(10));
BOOST_REQUIRE(instance.expiration() == minutes(60));
Expand Down Expand Up @@ -691,6 +696,7 @@ BOOST_AUTO_TEST_CASE(settings__peer_manual__mainnet__expected)
BOOST_REQUIRE_EQUAL(instance.connections, 0u);
BOOST_REQUIRE_EQUAL(instance.inactivity_minutes, 10u);
BOOST_REQUIRE_EQUAL(instance.expiration_minutes, 60u);
BOOST_REQUIRE_EQUAL(instance.maximum_request, maximum_request);
BOOST_REQUIRE(!instance.enabled());
BOOST_REQUIRE(instance.inactivity() == minutes(10));
BOOST_REQUIRE(instance.expiration() == minutes(60));
Expand Down
Loading