Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove the UDP channel implementation from the network #4105

Merged
merged 13 commits into from Feb 15, 2023
2 changes: 0 additions & 2 deletions nano/node/CMakeLists.txt
Expand Up @@ -200,8 +200,6 @@ add_library(
transport/tcp_server.cpp
transport/transport.hpp
transport/transport.cpp
transport/udp.hpp
transport/udp.cpp
unchecked_map.cpp
unchecked_map.hpp
vote_cache.hpp
Expand Down
6 changes: 1 addition & 5 deletions nano/node/bootstrap/bootstrap.cpp
Expand Up @@ -52,11 +52,7 @@ void nano::bootstrap_initiator::bootstrap (nano::endpoint const & endpoint_a, bo
{
if (add_to_peers)
{
if (!node.flags.disable_udp)
{
node.network.udp_channels.insert (nano::transport::map_endpoint_to_v6 (endpoint_a), node.network_params.network.protocol_version);
}
else if (!node.flags.disable_tcp_realtime)
if (!node.flags.disable_tcp_realtime)
{
node.network.merge_peer (nano::transport::map_endpoint_to_v6 (endpoint_a));
}
Expand Down
4 changes: 1 addition & 3 deletions nano/node/cli.cpp
Expand Up @@ -102,7 +102,6 @@ void nano::add_node_flag_options (boost::program_options::options_description &
("disable_request_loop", "Disable request loop")
("disable_bootstrap_listener", "Disables bootstrap processing for TCP listener (not including realtime network TCP connections)")
("disable_tcp_realtime", "Disables TCP realtime network")
("disable_udp", "(Deprecated) UDP is disabled by default")
("enable_udp", "Enables UDP realtime network")
("disable_unchecked_cleanup", "Disables periodic cleanup of old records from unchecked table")
("disable_unchecked_drop", "Disables drop of unchecked table at startup")
Expand Down Expand Up @@ -141,8 +140,7 @@ std::error_code nano::update_flags (nano::node_flags & flags_a, boost::program_o
{
ec = nano::error_cli::ambiguous_udp_options;
}
flags_a.disable_udp = (vm.count ("enable_udp") == 0);
if (flags_a.disable_tcp_realtime && flags_a.disable_udp)
if (flags_a.disable_tcp_realtime)
{
ec = nano::error_cli::disable_all_network;
}
Expand Down
99 changes: 6 additions & 93 deletions nano/node/network.cpp
Expand Up @@ -24,53 +24,12 @@ nano::network::network (nano::node & node_a, uint16_t port_a) :
tcp_message_manager (node_a.config.tcp_incoming_connections_max),
node (node_a),
publish_filter (256 * 1024),
udp_channels (node_a, port_a, inbound),
tcp_channels (node_a, inbound),
port (port_a),
disconnect_observer ([] () {})
{
if (!node.flags.disable_udp)
{
port = udp_channels.get_local_endpoint ().port ();
}

boost::thread::attributes attrs;
nano::thread_attributes::set (attrs);
// UDP
for (std::size_t i = 0; i < node.config.network_threads && !node.flags.disable_udp; ++i)
{
packet_processing_threads.emplace_back (attrs, [this] () {
nano::thread_role::set (nano::thread_role::name::packet_processing);
try
{
udp_channels.process_packets ();
}
catch (boost::system::error_code & ec)
{
this->node.logger.always_log (FATAL_LOG_PREFIX, ec.message ());
release_assert (false);
}
catch (std::error_code & ec)
{
this->node.logger.always_log (FATAL_LOG_PREFIX, ec.message ());
release_assert (false);
}
catch (std::runtime_error & err)
{
this->node.logger.always_log (FATAL_LOG_PREFIX, err.what ());
release_assert (false);
}
catch (...)
{
this->node.logger.always_log (FATAL_LOG_PREFIX, "Unknown exception");
release_assert (false);
}
if (this->node.config.logging.network_packet_logging ())
{
this->node.logger.try_log ("Exiting UDP packet processing thread");
}
});
}
// TCP
for (std::size_t i = 0; i < node.config.network_threads && !node.flags.disable_tcp_realtime; ++i)
{
Expand Down Expand Up @@ -120,11 +79,6 @@ void nano::network::start ()
ongoing_cleanup ();
}
ongoing_syn_cookie_cleanup ();
if (!node.flags.disable_udp)
{
udp_channels.start ();
debug_assert (udp_channels.get_local_endpoint ().port () == port);
}
if (!node.flags.disable_tcp_realtime)
{
tcp_channels.start ();
Expand All @@ -136,7 +90,6 @@ void nano::network::stop ()
{
if (!stopped.exchange (true))
{
udp_channels.stop ();
tcp_channels.stop ();
resolver.cancel ();
buffer_container.stop ();
Expand Down Expand Up @@ -609,8 +562,7 @@ bool nano::network::reachout (nano::endpoint const & endpoint_a, bool allow_loca
bool error = not_a_peer (endpoint_a, allow_local_peers);
if (!error)
{
error |= udp_channels.reachout (endpoint_a);
error |= tcp_channels.reachout (endpoint_a);
error = tcp_channels.reachout (endpoint_a);
}
return error;
}
Expand All @@ -619,7 +571,6 @@ std::deque<std::shared_ptr<nano::transport::channel>> nano::network::list (std::
{
std::deque<std::shared_ptr<nano::transport::channel>> result;
tcp_channels.list (result, minimum_version_a, include_tcp_temporary_channels_a);
udp_channels.list (result, minimum_version_a);
nano::random_pool_shuffle (result.begin (), result.end ());
if (count_a > 0 && result.size () > count_a)
{
Expand All @@ -632,7 +583,6 @@ std::deque<std::shared_ptr<nano::transport::channel>> nano::network::list_non_pr
{
std::deque<std::shared_ptr<nano::transport::channel>> result;
tcp_channels.list (result);
udp_channels.list (result);
nano::random_pool_shuffle (result.begin (), result.end ());
result.erase (std::remove_if (result.begin (), result.end (), [this] (std::shared_ptr<nano::transport::channel> const & channel) {
return this->node.rep_crawler.is_pr (*channel);
Expand All @@ -653,17 +603,7 @@ std::size_t nano::network::fanout (float scale) const

std::unordered_set<std::shared_ptr<nano::transport::channel>> nano::network::random_set (std::size_t count_a, uint8_t min_version_a, bool include_temporary_channels_a) const
{
std::unordered_set<std::shared_ptr<nano::transport::channel>> result (tcp_channels.random_set (count_a, min_version_a, include_temporary_channels_a));
std::unordered_set<std::shared_ptr<nano::transport::channel>> udp_random (udp_channels.random_set (count_a, min_version_a));
for (auto i (udp_random.begin ()), n (udp_random.end ()); i != n && result.size () < count_a * 1.5; ++i)
{
result.insert (*i);
}
while (result.size () > count_a)
{
result.erase (result.begin ());
}
return result;
return tcp_channels.random_set (count_a, min_version_a, include_temporary_channels_a);
}

void nano::network::random_fill (std::array<nano::endpoint, 8> & target_a) const
Expand Down Expand Up @@ -714,37 +654,17 @@ void nano::network::fill_keepalive_self (std::array<nano::endpoint, 8> & target_

nano::tcp_endpoint nano::network::bootstrap_peer ()
{
nano::tcp_endpoint result (boost::asio::ip::address_v6::any (), 0);
bool use_udp_peer (nano::random_pool::generate_word32 (0, 1));
if (use_udp_peer || tcp_channels.size () == 0)
{
result = udp_channels.bootstrap_peer (node.network_params.network.protocol_version_min);
}
if (result == nano::tcp_endpoint (boost::asio::ip::address_v6::any (), 0))
{
result = tcp_channels.bootstrap_peer (node.network_params.network.protocol_version_min);
}
return result;
return tcp_channels.bootstrap_peer (node.network_params.network.protocol_version_min);
}

std::shared_ptr<nano::transport::channel> nano::network::find_channel (nano::endpoint const & endpoint_a)
{
std::shared_ptr<nano::transport::channel> result (tcp_channels.find_channel (nano::transport::map_endpoint_to_tcp (endpoint_a)));
if (!result)
{
result = udp_channels.channel (endpoint_a);
}
return result;
return tcp_channels.find_channel (nano::transport::map_endpoint_to_tcp (endpoint_a));
}

std::shared_ptr<nano::transport::channel> nano::network::find_node_id (nano::account const & node_id_a)
{
std::shared_ptr<nano::transport::channel> result (tcp_channels.find_node_id (node_id_a));
if (!result)
{
result = udp_channels.find_node_id (node_id_a);
}
return result;
return tcp_channels.find_node_id (node_id_a);
}

nano::endpoint nano::network::endpoint () const
Expand All @@ -755,7 +675,6 @@ nano::endpoint nano::network::endpoint () const
void nano::network::cleanup (std::chrono::steady_clock::time_point const & cutoff_a)
{
tcp_channels.purge (cutoff_a);
udp_channels.purge (cutoff_a);
if (node.network.empty ())
{
disconnect_observer ();
Expand Down Expand Up @@ -801,7 +720,7 @@ void nano::network::ongoing_keepalive ()

std::size_t nano::network::size () const
{
return tcp_channels.size () + udp_channels.size ();
return tcp_channels.size ();
}

float nano::network::size_sqrt () const
Expand All @@ -821,11 +740,6 @@ void nano::network::erase (nano::transport::channel const & channel_a)
{
tcp_channels.erase (channel_a.get_tcp_endpoint ());
}
else if (channel_type != nano::transport::transport_type::loopback)
{
udp_channels.erase (channel_a.get_endpoint ());
udp_channels.clean_node_id (channel_a.get_node_id ());
}
}

void nano::network::exclude (std::shared_ptr<nano::transport::channel> const & channel)
Expand Down Expand Up @@ -1068,7 +982,6 @@ std::unique_ptr<nano::container_info_component> nano::collect_container_info (ne
{
auto composite = std::make_unique<container_info_composite> (name);
composite->add_component (network.tcp_channels.collect_container_info ("tcp_channels"));
composite->add_component (network.udp_channels.collect_container_info ("udp_channels"));
composite->add_component (network.syn_cookies.collect_container_info ("syn_cookies"));
composite->add_component (network.excluded_peers.collect_container_info ("excluded_peers"));
return composite;
Expand Down
2 changes: 0 additions & 2 deletions nano/node/network.hpp
Expand Up @@ -3,7 +3,6 @@
#include <nano/node/common.hpp>
#include <nano/node/peer_exclusion.hpp>
#include <nano/node/transport/tcp.hpp>
#include <nano/node/transport/udp.hpp>
#include <nano/secure/network_filter.hpp>

#include <boost/thread/thread.hpp>
Expand Down Expand Up @@ -189,7 +188,6 @@ class network final
nano::tcp_message_manager tcp_message_manager;
nano::node & node;
nano::network_filter publish_filter;
nano::transport::udp_channels udp_channels;
nano::transport::tcp_channels tcp_channels;
std::atomic<uint16_t> port{ 0 };
std::function<void ()> disconnect_observer;
Expand Down
9 changes: 4 additions & 5 deletions nano/node/node.cpp
Expand Up @@ -658,7 +658,7 @@ void nano::node::start ()
tcp_listener.start ();
tcp_enabled = true;

if (flags.disable_udp && network.port != tcp_listener.port)
if (network.port != tcp_listener.port)
{
network.port = tcp_listener.port;
}
Expand All @@ -682,8 +682,8 @@ void nano::node::start ()
this_l->bootstrap_wallet ();
});
}
// Start port mapping if external address is not defined and TCP or UDP ports are enabled
if (config.external_address == boost::asio::ip::address_v6{}.any ().to_string () && (tcp_enabled || !flags.disable_udp))
// Start port mapping if external address is not defined and TCP ports are enabled
if (config.external_address == boost::asio::ip::address_v6{}.any ().to_string () && tcp_enabled)
thsfs marked this conversation as resolved.
Show resolved Hide resolved
{
port_mapping.start ();
}
Expand Down Expand Up @@ -893,8 +893,7 @@ void nano::node::ongoing_bootstrap ()

void nano::node::ongoing_peer_store ()
{
const bool stored (network.tcp_channels.store_all (true));
network.udp_channels.store_all (!stored);
const bool stored{ network.tcp_channels.store_all (true) };
std::weak_ptr<nano::node> node_w (shared_from_this ());
workers.add_timed_task (std::chrono::steady_clock::now () + network_params.network.peer_dump_interval, [node_w] () {
if (auto node_l = node_w.lock ())
Expand Down
1 change: 0 additions & 1 deletion nano/node/nodeconfig.hpp
Expand Up @@ -137,7 +137,6 @@ class node_flags final
bool disable_rep_crawler{ false };
bool disable_request_loop{ false }; // For testing only
bool disable_tcp_realtime{ false };
bool disable_udp{ true };
bool disable_unchecked_cleanup{ false };
bool disable_unchecked_drop{ true };
bool disable_providing_telemetry_metrics{ false };
Expand Down
4 changes: 3 additions & 1 deletion nano/node/portmapping.cpp
Expand Up @@ -17,7 +17,9 @@ std::string nano::mapping_protocol::to_string ()

nano::port_mapping::port_mapping (nano::node & node_a) :
node (node_a),
protocols ({ { { "TCP", boost::asio::ip::address_v4::any (), 0, true }, { "UDP", boost::asio::ip::address_v4::any (), 0, !node_a.flags.disable_udp } } })
// Kept UDP in the array (set disabled) so the port mapping is still
// implemented in case other transport protocols that rely on it is added.
protocols ({ { { "TCP", boost::asio::ip::address_v4::any (), 0, true }, { "UDP", boost::asio::ip::address_v4::any (), 0, false } } })
thsfs marked this conversation as resolved.
Show resolved Hide resolved
{
}

Expand Down
8 changes: 0 additions & 8 deletions nano/node/repcrawler.cpp
Expand Up @@ -319,14 +319,6 @@ void nano::rep_crawler::cleanup_reps ()
equal = true;
}
}
else if (i->get_type () == nano::transport::transport_type::udp)
{
auto find_channel (node.network.udp_channels.channel (i->get_endpoint ()));
if (find_channel != nullptr && *find_channel == *static_cast<nano::transport::channel_udp *> (i.get ()))
{
equal = true;
}
}
else if (i->get_type () == nano::transport::transport_type::fake)
{
equal = true;
Expand Down
18 changes: 0 additions & 18 deletions nano/node/transport/tcp.cpp
Expand Up @@ -141,10 +141,6 @@ bool nano::transport::tcp_channels::insert (std::shared_ptr<nano::transport::cha
error = false;
lock.unlock ();
node.network.channel_observer (channel_a);
// Remove UDP channel to same IP:port if exists
node.network.udp_channels.erase (udp_endpoint);
// Remove UDP channels with same node ID
node.network.udp_channels.clean_node_id (node_id);
}
}
return error;
Expand Down Expand Up @@ -490,20 +486,6 @@ void nano::transport::tcp_channels::ongoing_keepalive ()
{
channel->send (message);
}
// Attempt to start TCP connections to known UDP peers
nano::tcp_endpoint invalid_endpoint (boost::asio::ip::address_v6::any (), 0);
if (!node.network_params.network.is_dev_network () && !node.flags.disable_udp)
{
std::size_t random_count (std::min (static_cast<std::size_t> (6), static_cast<std::size_t> (std::ceil (std::sqrt (node.network.udp_channels.size ())))));
for (auto i (0); i <= random_count; ++i)
{
auto tcp_endpoint (node.network.udp_channels.bootstrap_peer (node.network_params.network.protocol_version_min));
if (tcp_endpoint != invalid_endpoint && find_channel (tcp_endpoint) == nullptr && !node.network.excluded_peers.check (tcp_endpoint))
{
start_tcp (nano::transport::map_tcp_to_endpoint (tcp_endpoint));
}
}
}
std::weak_ptr<nano::node> node_w (node.shared ());
node.workers.add_timed_task (std::chrono::steady_clock::now () + node.network_params.network.keepalive_period, [node_w] () {
if (auto node_l = node_w.lock ())
Expand Down
23 changes: 5 additions & 18 deletions nano/node/transport/tcp_server.cpp
Expand Up @@ -27,33 +27,20 @@ void nano::transport::tcp_listener::start ()
throw std::runtime_error (ec.message ());
}

// the user can either specify a port value in the config or it can leave the choice up to the OS;
// independently of user's port choice, he may have also opted to disable UDP or not; this gives us 4 possibilities:
// (1): UDP enabled, port specified
// (2): UDP enabled, port not specified
// (3): UDP disabled, port specified
// (4): UDP disabled, port not specified
// the user can either specify a port value in the config or it can leave the choice up to the OS:
// (1): port specified
// (2): port not specified
//
const auto listening_port = listening_socket->listening_port ();
if (!node.flags.disable_udp)
{
// (1) and (2) -- no matter if (1) or (2), since UDP socket binding happens before this TCP socket binding,
// we must have already been constructed with a valid port value, so check that it really is the same everywhere
//
debug_assert (port == listening_port);
debug_assert (port == node.network.port);
debug_assert (port == node.network.endpoint ().port ());
}
else
{
// (3) -- nothing to do, just check that port values match everywhere
// (1) -- nothing to do, just check that port values match everywhere
//
if (port == listening_port)
{
debug_assert (port == node.network.port);
debug_assert (port == node.network.endpoint ().port ());
}
// (4) -- OS port choice happened at TCP socket bind time, so propagate this port value back;
// (2) -- OS port choice happened at TCP socket bind time, so propagate this port value back;
// the propagation is done here for the `tcp_listener` itself, whereas for `network`, the node does it
// after calling `tcp_listener.start ()`
//
Expand Down