diff --git a/nano/node/CMakeLists.txt b/nano/node/CMakeLists.txt index f8f3b5407e..099cbc06ac 100644 --- a/nano/node/CMakeLists.txt +++ b/nano/node/CMakeLists.txt @@ -148,6 +148,8 @@ add_library( telemetry.cpp transport/channel.hpp transport/channel.cpp + transport/common.hpp + transport/common.cpp transport/fake.hpp transport/fake.cpp transport/inproc.hpp diff --git a/nano/node/common.cpp b/nano/node/common.cpp index 9a4de71724..307b154bb2 100644 --- a/nano/node/common.cpp +++ b/nano/node/common.cpp @@ -7,131 +7,6 @@ #include #include -#include - -uint64_t nano::ip_address_hash_raw (boost::asio::ip::address const & ip_a, uint16_t port) -{ - debug_assert (ip_a.is_v6 ()); - uint64_t result; - nano::uint128_union address; - address.bytes = ip_a.to_v6 ().to_bytes (); - blake2b_state state; - blake2b_init (&state, sizeof (result)); - blake2b_update (&state, nano::hardened_constants::get ().random_128.bytes.data (), nano::hardened_constants::get ().random_128.bytes.size ()); - if (port != 0) - { - blake2b_update (&state, &port, sizeof (port)); - } - blake2b_update (&state, address.bytes.data (), address.bytes.size ()); - blake2b_final (&state, &result, sizeof (result)); - return result; -} - -bool nano::parse_port (std::string const & string_a, uint16_t & port_a) -{ - bool result = false; - try - { - port_a = boost::lexical_cast (string_a); - } - catch (...) - { - result = true; - } - return result; -} - -// Can handle both ipv4 & ipv6 addresses (with and without square brackets) -bool nano::parse_address (std::string const & address_text_a, boost::asio::ip::address & address_a) -{ - auto address_text = address_text_a; - if (!address_text.empty () && address_text.front () == '[' && address_text.back () == ']') - { - // Chop the square brackets off as make_address doesn't always like them - address_text = address_text.substr (1, address_text.size () - 2); - } - - boost::system::error_code address_ec; - address_a = boost::asio::ip::make_address (address_text, address_ec); - return !!address_ec; -} - -bool nano::parse_address_port (std::string const & string, boost::asio::ip::address & address_a, uint16_t & port_a) -{ - auto result (false); - auto port_position (string.rfind (':')); - if (port_position != std::string::npos && port_position > 0) - { - std::string port_string (string.substr (port_position + 1)); - try - { - uint16_t port; - result = parse_port (port_string, port); - if (!result) - { - boost::system::error_code ec; - auto address (boost::asio::ip::make_address_v6 (string.substr (0, port_position), ec)); - if (!ec) - { - address_a = address; - port_a = port; - } - else - { - result = true; - } - } - else - { - result = true; - } - } - catch (...) - { - result = true; - } - } - else - { - result = true; - } - return result; -} - -bool nano::parse_endpoint (std::string const & string, nano::endpoint & endpoint_a) -{ - boost::asio::ip::address address; - uint16_t port; - auto result (parse_address_port (string, address, port)); - if (!result) - { - endpoint_a = nano::endpoint (address, port); - } - return result; -} - -std::optional nano::parse_endpoint (const std::string & str) -{ - nano::endpoint endpoint; - if (!parse_endpoint (str, endpoint)) - { - return endpoint; // Success - } - return {}; -} - -bool nano::parse_tcp_endpoint (std::string const & string, nano::tcp_endpoint & endpoint_a) -{ - boost::asio::ip::address address; - uint16_t port; - auto result (parse_address_port (string, address, port)); - if (!result) - { - endpoint_a = nano::tcp_endpoint (address, port); - } - return result; -} - nano::node_singleton_memory_pool_purge_guard::node_singleton_memory_pool_purge_guard () : cleanup_guard ({ nano::block_memory_pool_purge, nano::purge_shared_ptr_singleton_pool_memory, nano::purge_shared_ptr_singleton_pool_memory }) { diff --git a/nano/node/common.hpp b/nano/node/common.hpp index 9614826827..dfc12881ed 100644 --- a/nano/node/common.hpp +++ b/nano/node/common.hpp @@ -1,171 +1,14 @@ #pragma once -#include -#include #include #include +#include #include #include #include #include -namespace nano -{ -using endpoint = boost::asio::ip::udp::endpoint; -using tcp_endpoint = boost::asio::ip::tcp::endpoint; - -bool parse_port (std::string const &, uint16_t &); -bool parse_address (std::string const &, boost::asio::ip::address &); -bool parse_address_port (std::string const &, boost::asio::ip::address &, uint16_t &); -bool parse_endpoint (std::string const &, nano::endpoint &); -std::optional parse_endpoint (std::string const &); -bool parse_tcp_endpoint (std::string const &, nano::tcp_endpoint &); -uint64_t ip_address_hash_raw (boost::asio::ip::address const & ip_a, uint16_t port = 0); -} - -namespace -{ -uint64_t endpoint_hash_raw (nano::endpoint const & endpoint_a) -{ - uint64_t result (nano::ip_address_hash_raw (endpoint_a.address (), endpoint_a.port ())); - return result; -} -uint64_t endpoint_hash_raw (nano::tcp_endpoint const & endpoint_a) -{ - uint64_t result (nano::ip_address_hash_raw (endpoint_a.address (), endpoint_a.port ())); - return result; -} - -template -struct endpoint_hash -{ -}; - -template <> -struct endpoint_hash<8> -{ - std::size_t operator() (nano::endpoint const & endpoint_a) const - { - return endpoint_hash_raw (endpoint_a); - } - std::size_t operator() (nano::tcp_endpoint const & endpoint_a) const - { - return endpoint_hash_raw (endpoint_a); - } -}; - -template <> -struct endpoint_hash<4> -{ - std::size_t operator() (nano::endpoint const & endpoint_a) const - { - uint64_t big (endpoint_hash_raw (endpoint_a)); - uint32_t result (static_cast (big) ^ static_cast (big >> 32)); - return result; - } - std::size_t operator() (nano::tcp_endpoint const & endpoint_a) const - { - uint64_t big (endpoint_hash_raw (endpoint_a)); - uint32_t result (static_cast (big) ^ static_cast (big >> 32)); - return result; - } -}; - -template -struct ip_address_hash -{ -}; - -template <> -struct ip_address_hash<8> -{ - std::size_t operator() (boost::asio::ip::address const & ip_address_a) const - { - return nano::ip_address_hash_raw (ip_address_a); - } -}; - -template <> -struct ip_address_hash<4> -{ - std::size_t operator() (boost::asio::ip::address const & ip_address_a) const - { - uint64_t big (nano::ip_address_hash_raw (ip_address_a)); - uint32_t result (static_cast (big) ^ static_cast (big >> 32)); - return result; - } -}; -} - -namespace std -{ -template <> -struct hash<::nano::endpoint> -{ - std::size_t operator() (::nano::endpoint const & endpoint_a) const - { - endpoint_hash ehash; - return ehash (endpoint_a); - } -}; - -template <> -struct hash<::nano::tcp_endpoint> -{ - std::size_t operator() (::nano::tcp_endpoint const & endpoint_a) const - { - endpoint_hash ehash; - return ehash (endpoint_a); - } -}; - -#ifndef BOOST_ASIO_HAS_STD_HASH -template <> -struct hash -{ - std::size_t operator() (boost::asio::ip::address const & ip_a) const - { - ip_address_hash ihash; - return ihash (ip_a); - } -}; -#endif -} - -namespace boost -{ -template <> -struct hash<::nano::endpoint> -{ - std::size_t operator() (::nano::endpoint const & endpoint_a) const - { - std::hash<::nano::endpoint> hash; - return hash (endpoint_a); - } -}; - -template <> -struct hash<::nano::tcp_endpoint> -{ - std::size_t operator() (::nano::tcp_endpoint const & endpoint_a) const - { - std::hash<::nano::tcp_endpoint> hash; - return hash (endpoint_a); - } -}; - -template <> -struct hash -{ - std::size_t operator() (boost::asio::ip::address const & ip_a) const - { - std::hash hash; - return hash (ip_a); - } -}; -} - namespace nano { /** Helper guard which contains all the necessary purge (remove all memory even if used) functions */ diff --git a/nano/node/transport/common.cpp b/nano/node/transport/common.cpp new file mode 100644 index 0000000000..e711b8fa3f --- /dev/null +++ b/nano/node/transport/common.cpp @@ -0,0 +1,129 @@ +#include +#include +#include +#include +#include +#include + +uint64_t nano::ip_address_hash_raw (boost::asio::ip::address const & ip_a, uint16_t port) +{ + debug_assert (ip_a.is_v6 ()); + uint64_t result; + nano::uint128_union address; + address.bytes = ip_a.to_v6 ().to_bytes (); + blake2b_state state; + blake2b_init (&state, sizeof (result)); + blake2b_update (&state, nano::hardened_constants::get ().random_128.bytes.data (), nano::hardened_constants::get ().random_128.bytes.size ()); + if (port != 0) + { + blake2b_update (&state, &port, sizeof (port)); + } + blake2b_update (&state, address.bytes.data (), address.bytes.size ()); + blake2b_final (&state, &result, sizeof (result)); + return result; +} + +bool nano::parse_port (std::string const & string_a, uint16_t & port_a) +{ + bool result = false; + try + { + port_a = boost::lexical_cast (string_a); + } + catch (...) + { + result = true; + } + return result; +} + +// Can handle both ipv4 & ipv6 addresses (with and without square brackets) +bool nano::parse_address (std::string const & address_text_a, boost::asio::ip::address & address_a) +{ + auto address_text = address_text_a; + if (!address_text.empty () && address_text.front () == '[' && address_text.back () == ']') + { + // Chop the square brackets off as make_address doesn't always like them + address_text = address_text.substr (1, address_text.size () - 2); + } + + boost::system::error_code address_ec; + address_a = boost::asio::ip::make_address (address_text, address_ec); + return !!address_ec; +} + +bool nano::parse_address_port (std::string const & string, boost::asio::ip::address & address_a, uint16_t & port_a) +{ + auto result (false); + auto port_position (string.rfind (':')); + if (port_position != std::string::npos && port_position > 0) + { + std::string port_string (string.substr (port_position + 1)); + try + { + uint16_t port; + result = parse_port (port_string, port); + if (!result) + { + boost::system::error_code ec; + auto address (boost::asio::ip::make_address_v6 (string.substr (0, port_position), ec)); + if (!ec) + { + address_a = address; + port_a = port; + } + else + { + result = true; + } + } + else + { + result = true; + } + } + catch (...) + { + result = true; + } + } + else + { + result = true; + } + return result; +} + +bool nano::parse_endpoint (std::string const & string, nano::endpoint & endpoint_a) +{ + boost::asio::ip::address address; + uint16_t port; + auto result (parse_address_port (string, address, port)); + if (!result) + { + endpoint_a = nano::endpoint (address, port); + } + return result; +} + +std::optional nano::parse_endpoint (const std::string & str) +{ + nano::endpoint endpoint; + if (!parse_endpoint (str, endpoint)) + { + return endpoint; // Success + } + return {}; +} + +bool nano::parse_tcp_endpoint (std::string const & string, nano::tcp_endpoint & endpoint_a) +{ + boost::asio::ip::address address; + uint16_t port; + auto result (parse_address_port (string, address, port)); + if (!result) + { + endpoint_a = nano::tcp_endpoint (address, port); + } + return result; +} \ No newline at end of file diff --git a/nano/node/transport/common.hpp b/nano/node/transport/common.hpp new file mode 100644 index 0000000000..ed1640b445 --- /dev/null +++ b/nano/node/transport/common.hpp @@ -0,0 +1,167 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace nano +{ +using endpoint = boost::asio::ip::udp::endpoint; +using tcp_endpoint = boost::asio::ip::tcp::endpoint; + +bool parse_port (std::string const &, uint16_t &); +bool parse_address (std::string const &, boost::asio::ip::address &); +bool parse_address_port (std::string const &, boost::asio::ip::address &, uint16_t &); +bool parse_endpoint (std::string const &, nano::endpoint &); +std::optional parse_endpoint (std::string const &); +bool parse_tcp_endpoint (std::string const &, nano::tcp_endpoint &); +uint64_t ip_address_hash_raw (boost::asio::ip::address const & ip_a, uint16_t port = 0); +} + +namespace +{ +uint64_t endpoint_hash_raw (nano::endpoint const & endpoint_a) +{ + uint64_t result (nano::ip_address_hash_raw (endpoint_a.address (), endpoint_a.port ())); + return result; +} +uint64_t endpoint_hash_raw (nano::tcp_endpoint const & endpoint_a) +{ + uint64_t result (nano::ip_address_hash_raw (endpoint_a.address (), endpoint_a.port ())); + return result; +} + +template +struct endpoint_hash +{ +}; + +template <> +struct endpoint_hash<8> +{ + std::size_t operator() (nano::endpoint const & endpoint_a) const + { + return endpoint_hash_raw (endpoint_a); + } + std::size_t operator() (nano::tcp_endpoint const & endpoint_a) const + { + return endpoint_hash_raw (endpoint_a); + } +}; + +template <> +struct endpoint_hash<4> +{ + std::size_t operator() (nano::endpoint const & endpoint_a) const + { + uint64_t big (endpoint_hash_raw (endpoint_a)); + uint32_t result (static_cast (big) ^ static_cast (big >> 32)); + return result; + } + std::size_t operator() (nano::tcp_endpoint const & endpoint_a) const + { + uint64_t big (endpoint_hash_raw (endpoint_a)); + uint32_t result (static_cast (big) ^ static_cast (big >> 32)); + return result; + } +}; + +template +struct ip_address_hash +{ +}; + +template <> +struct ip_address_hash<8> +{ + std::size_t operator() (boost::asio::ip::address const & ip_address_a) const + { + return nano::ip_address_hash_raw (ip_address_a); + } +}; + +template <> +struct ip_address_hash<4> +{ + std::size_t operator() (boost::asio::ip::address const & ip_address_a) const + { + uint64_t big (nano::ip_address_hash_raw (ip_address_a)); + uint32_t result (static_cast (big) ^ static_cast (big >> 32)); + return result; + } +}; +} + +namespace std +{ +template <> +struct hash<::nano::endpoint> +{ + std::size_t operator() (::nano::endpoint const & endpoint_a) const + { + endpoint_hash ehash; + return ehash (endpoint_a); + } +}; + +template <> +struct hash<::nano::tcp_endpoint> +{ + std::size_t operator() (::nano::tcp_endpoint const & endpoint_a) const + { + endpoint_hash ehash; + return ehash (endpoint_a); + } +}; + +#ifndef BOOST_ASIO_HAS_STD_HASH +template <> +struct hash +{ + std::size_t operator() (boost::asio::ip::address const & ip_a) const + { + ip_address_hash ihash; + return ihash (ip_a); + } +}; +#endif +} + +namespace boost +{ +template <> +struct hash<::nano::endpoint> +{ + std::size_t operator() (::nano::endpoint const & endpoint_a) const + { + std::hash<::nano::endpoint> hash; + return hash (endpoint_a); + } +}; + +template <> +struct hash<::nano::tcp_endpoint> +{ + std::size_t operator() (::nano::tcp_endpoint const & endpoint_a) const + { + std::hash<::nano::tcp_endpoint> hash; + return hash (endpoint_a); + } +}; + +template <> +struct hash +{ + std::size_t operator() (boost::asio::ip::address const & ip_a) const + { + std::hash hash; + return hash (ip_a); + } +}; +} \ No newline at end of file