From d36093af55b8769899527458db15503129b17421 Mon Sep 17 00:00:00 2001 From: clemahieu Date: Tue, 12 Jul 2022 06:16:39 +0100 Subject: [PATCH] Adding block_deserializer class which handles deserializing type-prefixed block streams. --- nano/core_test/bootstrap.cpp | 6 ++ nano/node/CMakeLists.txt | 2 + nano/node/bootstrap/block_deserializer.cpp | 65 ++++++++++++++++++++++ nano/node/bootstrap/block_deserializer.hpp | 47 ++++++++++++++++ 4 files changed, 120 insertions(+) create mode 100644 nano/node/bootstrap/block_deserializer.cpp create mode 100644 nano/node/bootstrap/block_deserializer.hpp diff --git a/nano/core_test/bootstrap.cpp b/nano/core_test/bootstrap.cpp index 22cbcf5de..02d77876f 100644 --- a/nano/core_test/bootstrap.cpp +++ b/nano/core_test/bootstrap.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -2032,3 +2033,8 @@ TEST (bulk_pull_account, basics) ASSERT_EQ (nullptr, block_data.second.get ()); } } + +TEST (block_deserializer, construction) +{ + auto deserializer = std::make_shared (); +} diff --git a/nano/node/CMakeLists.txt b/nano/node/CMakeLists.txt index ba02c0f19..47830d23a 100644 --- a/nano/node/CMakeLists.txt +++ b/nano/node/CMakeLists.txt @@ -18,6 +18,8 @@ add_library( active_transactions.cpp blockprocessor.hpp blockprocessor.cpp + bootstrap/block_deserializer.hpp + bootstrap/block_deserializer.cpp bootstrap/bootstrap_attempt.hpp bootstrap/bootstrap_attempt.cpp bootstrap/bootstrap_bulk_pull.hpp diff --git a/nano/node/bootstrap/block_deserializer.cpp b/nano/node/bootstrap/block_deserializer.cpp new file mode 100644 index 000000000..34b6370cf --- /dev/null +++ b/nano/node/bootstrap/block_deserializer.cpp @@ -0,0 +1,65 @@ +#include +#include +#include +#include + +nano::bootstrap::block_deserializer::block_deserializer () : + read_buffer{ std::make_shared> () } +{ +} + +void nano::bootstrap::block_deserializer::read (nano::socket & socket, callback_type const && callback) +{ + debug_assert (callback); + read_buffer->resize (1); + socket.async_read (read_buffer, 1, [this_l = shared_from_this (), &socket, callback = std::move (callback)] (boost::system::error_code const & ec, std::size_t size_a) { + if (ec) + { + callback (ec, nullptr); + return; + } + if (size_a != 1) + { + callback (boost::asio::error::fault, nullptr); + return; + } + this_l->received_type (socket, std::move (callback)); + }); +} + +void nano::bootstrap::block_deserializer::received_type (nano::socket & socket, callback_type const && callback) +{ + nano::block_type type = static_cast (read_buffer->data ()[0]); + if (type == nano::block_type::not_a_block) + { + callback (boost::system::error_code{}, nullptr); + return; + } + auto size = nano::block::size (type); + if (size == 0) + { + callback (boost::asio::error::fault, nullptr); + return; + } + read_buffer->resize (size); + socket.async_read (read_buffer, size, [this_l = shared_from_this (), size, type, callback = std::move (callback)] (boost::system::error_code const & ec, std::size_t size_a) { + if (ec) + { + callback (ec, nullptr); + return; + } + if (size_a != size) + { + callback (boost::asio::error::fault, nullptr); + return; + } + this_l->received_block (type, std::move (callback)); + }); +} + +void nano::bootstrap::block_deserializer::received_block (nano::block_type type, callback_type const && callback) +{ + nano::bufferstream stream{ read_buffer->data (), read_buffer->size () }; + auto block = nano::deserialize_block (stream, type); + callback (boost::system::error_code{}, block); +} diff --git a/nano/node/bootstrap/block_deserializer.hpp b/nano/node/bootstrap/block_deserializer.hpp new file mode 100644 index 000000000..84720bae0 --- /dev/null +++ b/nano/node/bootstrap/block_deserializer.hpp @@ -0,0 +1,47 @@ +#pragma once + +#include + +#include + +#include +#include + +namespace nano +{ +class block; +class socket; +namespace bootstrap +{ + /** + * Class to read a block-type byte followed by a serialised block from a stream. + * It is typically used to used to read a series of block-types and blocks terminated by a not-a-block type. + */ + class block_deserializer : public std::enable_shared_from_this + { + public: + using callback_type = std::function)>; + + block_deserializer (); + /** + * Read a type-prefixed block from 'socket' and pass the result, or an error, to 'callback' + * A normal end to series of blocks is a marked by return no error and a nullptr for block. + */ + void read (nano::socket & socket, callback_type const && callback); + + private: + /** + * Called by read method on receipt of a block type byte. + * The type byte will be in the read_buffer. + */ + void received_type (nano::socket & socket, callback_type const && callback); + + /** + * Called by received_type when a block is received, it parses the block and calls the callback. + */ + void received_block (nano::block_type type, callback_type const && callback); + + std::shared_ptr> read_buffer; + }; +} +}