diff --git a/nano/core_test/network.cpp b/nano/core_test/network.cpp index 00e3593ed7..21d74fae43 100644 --- a/nano/core_test/network.cpp +++ b/nano/core_test/network.cpp @@ -118,7 +118,7 @@ TEST (network, last_contacted) ASSERT_EQ (0, node0->network.size ()); nano::node_config node1_config = system.default_config (); - node1_config.tcp_incoming_connections_max = 0; // Prevent ephemeral node1->node0 channel repacement with incoming connection + node1_config.tcp.max_inbound_connections = 0; // Prevent ephemeral node1->node0 channel repacement with incoming connection auto node1 (std::make_shared (system.io_ctx, nano::unique_path (), node1_config, system.work)); node1->start (); system.nodes.push_back (node1); diff --git a/nano/core_test/node.cpp b/nano/core_test/node.cpp index 7cbef18022..4df9c713da 100644 --- a/nano/core_test/node.cpp +++ b/nano/core_test/node.cpp @@ -2603,7 +2603,7 @@ TEST (node, bidirectional_tcp) node_config.backlog_scan.enable = false; auto node1 = system.add_node (node_config, node_flags); node_config.peering_port = system.get_available_port (); - node_config.tcp_incoming_connections_max = 0; // Disable incoming TCP connections for node 2 + node_config.tcp.max_inbound_connections = 0; // Disable incoming TCP connections for node 2 auto node2 = system.add_node (node_config, node_flags); // Check network connections ASSERT_EQ (1, node1->network.size ()); diff --git a/nano/core_test/toml.cpp b/nano/core_test/toml.cpp index cb635aecd1..a46408404f 100644 --- a/nano/core_test/toml.cpp +++ b/nano/core_test/toml.cpp @@ -250,6 +250,7 @@ TEST (toml_config, daemon_config_deserialize_defaults) [node.websocket] [node.lmdb] [node.rocksdb] + [node.tcp] [opencl] [rpc] [rpc.child_process] @@ -305,7 +306,6 @@ TEST (toml_config, daemon_config_deserialize_defaults) ASSERT_EQ (conf.node.preconfigured_representatives, defaults.node.preconfigured_representatives); ASSERT_EQ (conf.node.receive_minimum, defaults.node.receive_minimum); ASSERT_EQ (conf.node.signature_checker_threads, defaults.node.signature_checker_threads); - ASSERT_EQ (conf.node.tcp_incoming_connections_max, defaults.node.tcp_incoming_connections_max); ASSERT_EQ (conf.node.tcp_io_timeout, defaults.node.tcp_io_timeout); ASSERT_EQ (conf.node.unchecked_cutoff_time, defaults.node.unchecked_cutoff_time); ASSERT_EQ (conf.node.use_memory_pools, defaults.node.use_memory_pools); @@ -418,6 +418,14 @@ TEST (toml_config, daemon_config_deserialize_defaults) ASSERT_EQ (conf.node.message_processor.threads, defaults.node.message_processor.threads); ASSERT_EQ (conf.node.message_processor.max_queue, defaults.node.message_processor.max_queue); + + ASSERT_EQ (conf.node.tcp.max_inbound_connections, defaults.node.tcp.max_inbound_connections); + ASSERT_EQ (conf.node.tcp.max_outbound_connections, defaults.node.tcp.max_outbound_connections); + ASSERT_EQ (conf.node.tcp.max_attempts, defaults.node.tcp.max_attempts); + ASSERT_EQ (conf.node.tcp.max_attempts_per_ip, defaults.node.tcp.max_attempts_per_ip); + ASSERT_EQ (conf.node.tcp.connect_timeout, defaults.node.tcp.connect_timeout); + ASSERT_EQ (conf.node.tcp.handshake_timeout, defaults.node.tcp.handshake_timeout); + ASSERT_EQ (conf.node.tcp.io_timeout, defaults.node.tcp.io_timeout); } /** Deserialize a node config with non-default values */ @@ -458,7 +466,6 @@ TEST (toml_config, daemon_config_deserialize_no_defaults) preconfigured_representatives = ["nano_3arg3asgtigae3xckabaaewkx3bzsh7nwz7jkmjos79ihyaxwphhm6qgjps4"] receive_minimum = "999" signature_checker_threads = 999 - tcp_incoming_connections_max = 999 tcp_io_timeout = 999 unchecked_cutoff_time = 999 use_memory_pools = false @@ -641,6 +648,15 @@ TEST (toml_config, daemon_config_deserialize_no_defaults) threads = 999 max_queue = 999 + [node.tcp] + max_inbound_connections = 999 + max_outbound_connections = 999 + max_attempts = 999 + max_attempts_per_ip = 999 + connect_timeout = 999 + handshake_timeout = 999 + io_timeout = 999 + [opencl] device = 999 enable = true @@ -710,7 +726,6 @@ TEST (toml_config, daemon_config_deserialize_no_defaults) ASSERT_NE (conf.node.preconfigured_representatives, defaults.node.preconfigured_representatives); ASSERT_NE (conf.node.receive_minimum, defaults.node.receive_minimum); ASSERT_NE (conf.node.signature_checker_threads, defaults.node.signature_checker_threads); - ASSERT_NE (conf.node.tcp_incoming_connections_max, defaults.node.tcp_incoming_connections_max); ASSERT_NE (conf.node.tcp_io_timeout, defaults.node.tcp_io_timeout); ASSERT_NE (conf.node.unchecked_cutoff_time, defaults.node.unchecked_cutoff_time); ASSERT_NE (conf.node.use_memory_pools, defaults.node.use_memory_pools); @@ -823,6 +838,14 @@ TEST (toml_config, daemon_config_deserialize_no_defaults) ASSERT_NE (conf.node.message_processor.threads, defaults.node.message_processor.threads); ASSERT_NE (conf.node.message_processor.max_queue, defaults.node.message_processor.max_queue); + + ASSERT_NE (conf.node.tcp.max_inbound_connections, defaults.node.tcp.max_inbound_connections); + ASSERT_NE (conf.node.tcp.max_outbound_connections, defaults.node.tcp.max_outbound_connections); + ASSERT_NE (conf.node.tcp.max_attempts, defaults.node.tcp.max_attempts); + ASSERT_NE (conf.node.tcp.max_attempts_per_ip, defaults.node.tcp.max_attempts_per_ip); + ASSERT_NE (conf.node.tcp.connect_timeout, defaults.node.tcp.connect_timeout); + ASSERT_NE (conf.node.tcp.handshake_timeout, defaults.node.tcp.handshake_timeout); + ASSERT_NE (conf.node.tcp.io_timeout, defaults.node.tcp.io_timeout); } /** There should be no required values **/ diff --git a/nano/node/CMakeLists.txt b/nano/node/CMakeLists.txt index 13a182adff..e37da22bdb 100644 --- a/nano/node/CMakeLists.txt +++ b/nano/node/CMakeLists.txt @@ -164,6 +164,8 @@ add_library( transport/message_deserializer.cpp transport/tcp_channels.hpp transport/tcp_channels.cpp + transport/tcp_config.hpp + transport/tcp_config.cpp transport/tcp_listener.hpp transport/tcp_listener.cpp transport/tcp_server.hpp diff --git a/nano/node/node.cpp b/nano/node/node.cpp index b1693bc3bb..65c8fc1dc7 100644 --- a/nano/node/node.cpp +++ b/nano/node/node.cpp @@ -607,7 +607,7 @@ void nano::node::start () } bool tcp_enabled = false; - if (config.tcp_incoming_connections_max > 0 && !(flags.disable_bootstrap_listener && flags.disable_tcp_realtime)) + if (!(flags.disable_bootstrap_listener && flags.disable_tcp_realtime)) { tcp_listener.start (); tcp_enabled = true; diff --git a/nano/node/nodeconfig.cpp b/nano/node/nodeconfig.cpp index f6ccdf563f..a6314d9d76 100644 --- a/nano/node/nodeconfig.cpp +++ b/nano/node/nodeconfig.cpp @@ -125,7 +125,6 @@ nano::error nano::node_config::serialize_toml (nano::tomlconfig & toml) const toml.put ("pow_sleep_interval", pow_sleep_interval.count (), "Time to sleep between batch work generation attempts. Reduces max CPU usage at the expense of a longer generation time.\ntype:nanoseconds"); toml.put ("external_address", external_address, "The external address of this node (NAT). If not set, the node will request this information via UPnP.\ntype:string,ip"); toml.put ("external_port", external_port, "The external port number of this node (NAT). Only used if external_address is set.\ntype:uint16"); - toml.put ("tcp_incoming_connections_max", tcp_incoming_connections_max, "Maximum number of incoming TCP connections.\ntype:uint64"); toml.put ("use_memory_pools", use_memory_pools, "If true, allocate memory from memory pools. Enabling this may improve performance. Memory is never released to the OS.\ntype:bool"); toml.put ("bandwidth_limit", bandwidth_limit, "Outbound traffic limit in bytes/sec after which messages will be dropped.\nNote: changing to unlimited bandwidth (0) is not recommended for limited connections.\ntype:uint64"); @@ -247,6 +246,10 @@ nano::error nano::node_config::serialize_toml (nano::tomlconfig & toml) const peer_history.serialize (peer_history_l); toml.put_child ("peer_history", peer_history_l); + nano::tomlconfig tcp_l; + tcp.serialize (tcp_l); + toml.put_child ("tcp", tcp_l); + nano::tomlconfig request_aggregator_l; request_aggregator.serialize (request_aggregator_l); toml.put_child ("request_aggregator", request_aggregator_l); @@ -382,6 +385,12 @@ nano::error nano::node_config::deserialize_toml (nano::tomlconfig & toml) peer_history.deserialize (config_l); } + if (toml.has_key ("tcp")) + { + auto config_l = toml.get_required_child ("tcp"); + tcp.deserialize (config_l); + } + if (toml.has_key ("request_aggregator")) { auto config_l = toml.get_required_child ("request_aggregator"); @@ -538,7 +547,6 @@ nano::error nano::node_config::deserialize_toml (nano::tomlconfig & toml) toml.get ("external_address", external_address_l); external_address = external_address_l.to_string (); toml.get ("external_port", external_port); - toml.get ("tcp_incoming_connections_max", tcp_incoming_connections_max); auto pow_sleep_interval_l (pow_sleep_interval.count ()); toml.get (pow_sleep_interval_key, pow_sleep_interval_l); diff --git a/nano/node/nodeconfig.hpp b/nano/node/nodeconfig.hpp index 4871b98711..9a8d6bd41b 100644 --- a/nano/node/nodeconfig.hpp +++ b/nano/node/nodeconfig.hpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -109,8 +110,6 @@ class node_config std::chrono::seconds tcp_io_timeout{ (network_params.network.is_dev_network () && !is_sanitizer_build ()) ? std::chrono::seconds (5) : std::chrono::seconds (15) }; std::chrono::nanoseconds pow_sleep_interval{ 0 }; - /** Default maximum incoming TCP connections, including realtime network & bootstrap */ - unsigned tcp_incoming_connections_max{ 2048 }; bool use_memory_pools{ true }; static std::chrono::minutes constexpr wallet_backup_interval = std::chrono::minutes (5); /** Default outbound traffic shaping is 10MB/s */ diff --git a/nano/node/transport/tcp_config.cpp b/nano/node/transport/tcp_config.cpp new file mode 100644 index 0000000000..b85d0beb62 --- /dev/null +++ b/nano/node/transport/tcp_config.cpp @@ -0,0 +1,29 @@ +#include + +nano::error nano::transport::tcp_config::serialize (nano::tomlconfig & toml) const +{ + toml.put ("max_inbound_connections", max_inbound_connections, "Maximum number of incoming TCP connections. \ntype:uint64"); + toml.put ("max_outbound_connections", max_outbound_connections, "Maximum number of outgoing TCP connections. \ntype:uint64"); + toml.put ("max_attempts", max_attempts, "Maximum connection attempts. \ntype:uint64"); + toml.put ("max_attempts_per_ip", max_attempts_per_ip, "Maximum connection attempts per IP. \ntype:uint64"); + + toml.put ("connect_timeout", connect_timeout.count (), "Timeout for establishing TCP connection in seconds. \ntype:uint64"); + toml.put ("handshake_timeout", handshake_timeout.count (), "Timeout for completing handshake in seconds. \ntype:uint64"); + toml.put ("io_timeout", io_timeout.count (), "Timeout for TCP I/O operations in seconds. \ntype:uint64"); + + return toml.get_error (); +} + +nano::error nano::transport::tcp_config::deserialize (nano::tomlconfig & toml) +{ + toml.get ("max_inbound_connections", max_inbound_connections); + toml.get ("max_outbound_connections", max_outbound_connections); + toml.get ("max_attempts", max_attempts); + toml.get ("max_attempts_per_ip", max_attempts_per_ip); + + toml.get_duration ("connect_timeout", connect_timeout); + toml.get_duration ("handshake_timeout", handshake_timeout); + toml.get_duration ("io_timeout", io_timeout); + + return toml.get_error (); +} \ No newline at end of file diff --git a/nano/node/transport/tcp_config.hpp b/nano/node/transport/tcp_config.hpp new file mode 100644 index 0000000000..1a8a99d6bd --- /dev/null +++ b/nano/node/transport/tcp_config.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include +#include + +#include + +namespace nano::transport +{ +class tcp_config +{ +public: + explicit tcp_config (nano::network_constants const & network) + { + if (network.is_dev_network ()) + { + max_inbound_connections = 128; + max_outbound_connections = 128; + max_attempts = 128; + max_attempts_per_ip = 128; + connect_timeout = std::chrono::seconds{ 5 }; + } + } + +public: + nano::error deserialize (nano::tomlconfig &); + nano::error serialize (nano::tomlconfig &) const; + +public: + size_t max_inbound_connections{ 2048 }; + size_t max_outbound_connections{ 2048 }; + size_t max_attempts{ 60 }; + size_t max_attempts_per_ip{ 1 }; + std::chrono::seconds connect_timeout{ 60 }; + std::chrono::seconds handshake_timeout{ 30 }; + std::chrono::seconds io_timeout{ 30 }; +}; +} \ No newline at end of file diff --git a/nano/node/transport/tcp_listener.hpp b/nano/node/transport/tcp_listener.hpp index b5634b31e1..5503d47f70 100644 --- a/nano/node/transport/tcp_listener.hpp +++ b/nano/node/transport/tcp_listener.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -24,29 +25,6 @@ namespace asio = boost::asio; namespace nano::transport { -class tcp_config -{ -public: - explicit tcp_config (nano::network_constants const & network) - { - if (network.is_dev_network ()) - { - max_inbound_connections = 128; - max_outbound_connections = 128; - max_attempts = 128; - max_attempts_per_ip = 128; - connect_timeout = std::chrono::seconds{ 5 }; - } - } - -public: - size_t max_inbound_connections{ 2048 }; - size_t max_outbound_connections{ 2048 }; - size_t max_attempts{ 60 }; - size_t max_attempts_per_ip{ 1 }; - std::chrono::seconds connect_timeout{ 60 }; -}; - /** * Server side portion of tcp sessions. Listens for new socket connections and spawns tcp_server objects when connected. */