From 7a41f6daaf42e0eb1201116726ab6d79be5e5bde Mon Sep 17 00:00:00 2001 From: cryptocode Date: Wed, 23 Jan 2019 20:33:10 +0100 Subject: [PATCH] Add size expressions to bootstrap types (#1580) --- nano/node/bootstrap.cpp | 35 +++++++++++++---------------------- nano/node/bootstrap.hpp | 1 + nano/node/common.cpp | 41 ++++++++++++++++++++++++++++++++++++----- nano/node/common.hpp | 13 +++++++------ 4 files changed, 57 insertions(+), 33 deletions(-) diff --git a/nano/node/bootstrap.cpp b/nano/node/bootstrap.cpp index 097fb3da..d7ab1360 100644 --- a/nano/node/bootstrap.cpp +++ b/nano/node/bootstrap.cpp @@ -14,6 +14,8 @@ constexpr double bootstrap_minimum_termination_time_sec = 30.0; constexpr unsigned bootstrap_max_new_connections = 10; constexpr unsigned bulk_push_cost_limit = 200; +size_t constexpr nano::frontier_req_client::size_frontier; + nano::socket::socket (std::shared_ptr node_a) : socket_m (node_a->io_ctx), cutoff (std::numeric_limits::max ()), @@ -239,11 +241,10 @@ nano::frontier_req_client::~frontier_req_client () void nano::frontier_req_client::receive_frontier () { auto this_l (shared_from_this ()); - size_t size_l (sizeof (nano::uint256_union) + sizeof (nano::uint256_union)); - connection->socket->async_read (connection->receive_buffer, size_l, [this_l, size_l](boost::system::error_code const & ec, size_t size_a) { + connection->socket->async_read (connection->receive_buffer, nano::frontier_req_client::size_frontier, [this_l](boost::system::error_code const & ec, size_t size_a) { // An issue with asio is that sometimes, instead of reporting a bad file descriptor during disconnect, // we simply get a size of 0. - if (size_a == size_l) + if (size_a == nano::frontier_req_client::size_frontier) { this_l->received_frontier (ec, size_a); } @@ -251,7 +252,7 @@ void nano::frontier_req_client::receive_frontier () { if (this_l->connection->node->config.logging.network_message_logging ()) { - BOOST_LOG (this_l->connection->node->log) << boost::str (boost::format ("Invalid size: expected %1%, got %2%") % size_l % size_a); + BOOST_LOG (this_l->connection->node->log) << boost::str (boost::format ("Invalid size: expected %1%, got %2%") % nano::frontier_req_client::size_frontier % size_a); } } }); @@ -277,13 +278,13 @@ void nano::frontier_req_client::received_frontier (boost::system::error_code con { if (!ec) { - assert (size_a == sizeof (nano::uint256_union) + sizeof (nano::uint256_union)); + assert (size_a == nano::frontier_req_client::size_frontier); nano::account account; - nano::bufferstream account_stream (connection->receive_buffer->data (), sizeof (nano::uint256_union)); + nano::bufferstream account_stream (connection->receive_buffer->data (), sizeof (account)); auto error1 (nano::read (account_stream, account)); assert (!error1); nano::block_hash latest; - nano::bufferstream latest_stream (connection->receive_buffer->data () + sizeof (nano::uint256_union), sizeof (nano::uint256_union)); + nano::bufferstream latest_stream (connection->receive_buffer->data () + sizeof (account), sizeof (latest)); auto error2 (nano::read (latest_stream, latest)); assert (!error2); if (count == 0) @@ -1999,20 +2000,10 @@ void nano::bootstrap_server::receive_header_action (boost::system::error_code co { case nano::message_type::bulk_pull: { - uint32_t extended_size; node->stats.inc (nano::stat::type::bootstrap, nano::stat::detail::bulk_pull, nano::stat::dir::in); - if (header.bulk_pull_is_count_present ()) - { - extended_size = nano::bulk_pull::extended_parameters_size; - } - else - { - extended_size = 0; - } - auto this_l (shared_from_this ()); - socket->async_read (receive_buffer, sizeof (nano::uint256_union) + sizeof (nano::uint256_union) + extended_size, [this_l, header](boost::system::error_code const & ec, size_t size_a) { + socket->async_read (receive_buffer, header.payload_length_bytes (), [this_l, header](boost::system::error_code const & ec, size_t size_a) { this_l->receive_bulk_pull_action (ec, size_a, header); }); break; @@ -2021,7 +2012,7 @@ void nano::bootstrap_server::receive_header_action (boost::system::error_code co { node->stats.inc (nano::stat::type::bootstrap, nano::stat::detail::bulk_pull_account, nano::stat::dir::in); auto this_l (shared_from_this ()); - socket->async_read (receive_buffer, sizeof (nano::uint256_union) + sizeof (nano::uint128_union) + sizeof (uint8_t), [this_l, header](boost::system::error_code const & ec, size_t size_a) { + socket->async_read (receive_buffer, header.payload_length_bytes (), [this_l, header](boost::system::error_code const & ec, size_t size_a) { this_l->receive_bulk_pull_account_action (ec, size_a, header); }); break; @@ -2030,7 +2021,7 @@ void nano::bootstrap_server::receive_header_action (boost::system::error_code co { node->stats.inc (nano::stat::type::bootstrap, nano::stat::detail::frontier_req, nano::stat::dir::in); auto this_l (shared_from_this ()); - socket->async_read (receive_buffer, sizeof (nano::uint256_union) + sizeof (uint32_t) + sizeof (uint32_t), [this_l, header](boost::system::error_code const & ec, size_t size_a) { + socket->async_read (receive_buffer, header.payload_length_bytes (), [this_l, header](boost::system::error_code const & ec, size_t size_a) { this_l->receive_frontier_req_action (ec, size_a, header); }); break; @@ -2085,7 +2076,7 @@ void nano::bootstrap_server::receive_bulk_pull_account_action (boost::system::er if (!ec) { auto error (false); - assert (size_a == (sizeof (nano::uint256_union) + sizeof (nano::uint128_union) + sizeof (uint8_t))); + assert (size_a == header_a.payload_length_bytes ()); nano::bufferstream stream (receive_buffer->data (), size_a); std::unique_ptr request (new nano::bulk_pull_account (error, stream, header_a)); if (!error) @@ -2105,7 +2096,7 @@ void nano::bootstrap_server::receive_frontier_req_action (boost::system::error_c if (!ec) { auto error (false); - nano::bufferstream stream (receive_buffer->data (), sizeof (nano::uint256_union) + sizeof (uint32_t) + sizeof (uint32_t)); + nano::bufferstream stream (receive_buffer->data (), header_a.payload_length_bytes ()); std::unique_ptr request (new nano::frontier_req (error, stream, header_a)); if (!error) { diff --git a/nano/node/bootstrap.hpp b/nano/node/bootstrap.hpp index c9567347..a9f6fc8b 100644 --- a/nano/node/bootstrap.hpp +++ b/nano/node/bootstrap.hpp @@ -155,6 +155,7 @@ public: /** A very rough estimate of the cost of `bulk_push`ing missing blocks */ uint64_t bulk_push_cost; std::deque> accounts; + static size_t constexpr size_frontier = sizeof (nano::account) + sizeof (nano::block_hash); }; class bulk_pull_client : public std::enable_shared_from_this { diff --git a/nano/node/common.cpp b/nano/node/common.cpp index ec06c218..c8ffc41f 100644 --- a/nano/node/common.cpp +++ b/nano/node/common.cpp @@ -88,6 +88,37 @@ bool nano::message_header::bulk_pull_is_count_present () const return result; } +size_t nano::message_header::payload_length_bytes () const +{ + switch (type) + { + case nano::message_type::bulk_pull: + { + return nano::bulk_pull::size + (bulk_pull_is_count_present () ? nano::bulk_pull::extended_parameters_size : 0); + } + case nano::message_type::bulk_push: + { + // bulk_push doesn't have a payload + return 0; + } + case nano::message_type::frontier_req: + { + return nano::frontier_req::size; + } + case nano::message_type::bulk_pull_account: + { + return nano::bulk_pull_account::size; + } + // Add realtime network messages once they get framing support; currently the + // realtime messages all fit in a datagram from which they're deserialized. + default: + { + assert (false); + return 0; + } + } +} + // MTU - IP header - UDP header const size_t nano::message_parser::max_safe_udp_message_size = 508; @@ -613,17 +644,17 @@ bool nano::bulk_pull::deserialize (nano::stream & stream_a) { if (is_count_present ()) { - std::array count_buffer; - static_assert (sizeof (count) < (count_buffer.size () - 1), "count must fit within buffer"); + std::array extended_parameters_buffers; + static_assert (sizeof (count) < (extended_parameters_buffers.size () - 1), "count must fit within buffer"); - result = read (stream_a, count_buffer); - if (count_buffer[0] != 0) + result = read (stream_a, extended_parameters_buffers); + if (extended_parameters_buffers[0] != 0) { result = true; } else { - memcpy (&count, count_buffer.data () + 1, sizeof (count)); + memcpy (&count, extended_parameters_buffers.data () + 1, sizeof (count)); boost::endian::little_to_native_inplace (count); } } diff --git a/nano/node/common.hpp b/nano/node/common.hpp index e425edc3..633edd0f 100644 --- a/nano/node/common.hpp +++ b/nano/node/common.hpp @@ -202,15 +202,13 @@ public: uint8_t version_min; nano::message_type type; std::bitset<16> extensions; - //static size_t constexpr ipv4_only_position = 1; // Not in use, deprecated, was conflicting - //static size_t constexpr bootstrap_server_position = 2; // Not in use, deprecated - /* - * A better approach might be to return the size of the message - * payload based on the header - */ + static size_t constexpr bulk_pull_count_present_flag = 0; bool bulk_pull_is_count_present () const; + /** Size of the payload in bytes. For some messages, the payload size is based on header flags. */ + size_t payload_length_bytes () const; + static std::bitset<16> constexpr block_type_mask = std::bitset<16> (0x0f00); bool valid_magic () const { @@ -329,6 +327,7 @@ public: nano::account start; uint32_t age; uint32_t count; + static size_t constexpr size = sizeof (start) + sizeof (age) + sizeof (count); }; class bulk_pull : public message { @@ -346,6 +345,7 @@ public: void set_count_present (bool); static size_t constexpr count_present_flag = nano::message_header::bulk_pull_count_present_flag; static size_t constexpr extended_parameters_size = 8; + static size_t constexpr size = sizeof (start) + sizeof (end); }; class bulk_pull_account : public message { @@ -358,6 +358,7 @@ public: nano::uint256_union account; nano::uint128_union minimum_amount; bulk_pull_account_flags flags; + static size_t constexpr size = sizeof (account) + sizeof (minimum_amount) + sizeof (bulk_pull_account_flags); }; class bulk_push : public message {