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

Don't bind to UDP socket with --disable_udp flag #2464

Merged
merged 11 commits into from
Jan 20, 2020
36 changes: 33 additions & 3 deletions nano/core_test/network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,17 @@ TEST (network, send_valid_confirm_ack)
std::vector<nano::transport::transport_type> types{ nano::transport::transport_type::tcp, nano::transport::transport_type::udp };
for (auto & type : types)
{
nano::system system (2, type);
nano::node_flags node_flags;
if (type == nano::transport::transport_type::tcp)
{
node_flags.disable_udp = true;
}
else
{
node_flags.disable_tcp_realtime = true;
node_flags.disable_bootstrap_listener = true;
}
nano::system system (2, type, node_flags);
nano::keypair key2;
system.wallet (0)->insert_adhoc (nano::test_genesis_key.prv);
system.wallet (1)->insert_adhoc (key2.prv);
Expand All @@ -291,7 +301,17 @@ TEST (network, send_valid_publish)
std::vector<nano::transport::transport_type> types{ nano::transport::transport_type::tcp, nano::transport::transport_type::udp };
for (auto & type : types)
{
nano::system system (2, type);
nano::node_flags node_flags;
if (type == nano::transport::transport_type::tcp)
{
node_flags.disable_udp = true;
}
else
{
node_flags.disable_tcp_realtime = true;
node_flags.disable_bootstrap_listener = true;
}
nano::system system (2, type, node_flags);
system.nodes[0]->bootstrap_initiator.stop ();
system.nodes[1]->bootstrap_initiator.stop ();
system.wallet (0)->insert_adhoc (nano::test_genesis_key.prv);
Expand Down Expand Up @@ -370,7 +390,17 @@ TEST (receivable_processor, send_with_receive)
std::vector<nano::transport::transport_type> types{ nano::transport::transport_type::tcp, nano::transport::transport_type::udp };
for (auto & type : types)
{
nano::system system (2, type);
nano::node_flags node_flags;
if (type == nano::transport::transport_type::tcp)
{
node_flags.disable_udp = true;
}
else
{
node_flags.disable_tcp_realtime = true;
node_flags.disable_bootstrap_listener = true;
}
nano::system system (2, type, node_flags);
auto amount (std::numeric_limits<nano::uint128_t>::max ());
nano::keypair key2;
system.wallet (0)->insert_adhoc (nano::test_genesis_key.prv);
Expand Down
186 changes: 126 additions & 60 deletions nano/core_test/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1102,6 +1102,26 @@ TEST (node_flags, disable_tcp_realtime)
ASSERT_EQ (nano::transport::transport_type::udp, list2[0]->get_type ());
}

TEST (node_flags, disable_tcp_realtime_and_bootstrap_listener)
{
nano::system system (1);
auto node1 = system.nodes[0];
nano::node_flags node_flags;
node_flags.disable_tcp_realtime = true;
node_flags.disable_bootstrap_listener = true;
auto node2 = system.add_node (nano::node_config (nano::get_available_port (), system.logging), node_flags);
ASSERT_EQ (nano::tcp_endpoint (boost::asio::ip::address_v6::loopback (), 0), node2->bootstrap.endpoint ());
ASSERT_NE (nano::endpoint (boost::asio::ip::address_v6::loopback (), 0), node2->network.endpoint ());
ASSERT_EQ (1, node1->network.size ());
auto list1 (node1->network.list (2));
ASSERT_EQ (node2->network.endpoint (), list1[0]->get_endpoint ());
ASSERT_EQ (nano::transport::transport_type::udp, list1[0]->get_type ());
ASSERT_EQ (1, node2->network.size ());
auto list2 (node2->network.list (2));
ASSERT_EQ (node1->network.endpoint (), list2[0]->get_endpoint ());
ASSERT_EQ (nano::transport::transport_type::udp, list2[0]->get_type ());
}

TEST (node_flags, disable_udp)
{
nano::system system (1);
Expand All @@ -1111,6 +1131,8 @@ TEST (node_flags, disable_udp)
auto node2 (std::make_shared<nano::node> (system.io_ctx, nano::unique_path (), system.alarm, nano::node_config (nano::get_available_port (), system.logging), system.work, node_flags));
system.nodes.push_back (node2);
node2->start ();
ASSERT_EQ (nano::endpoint (boost::asio::ip::address_v6::loopback (), 0), node2->network.udp_channels.get_local_endpoint ());
ASSERT_NE (nano::endpoint (boost::asio::ip::address_v6::loopback (), 0), node2->network.endpoint ());
// Send UDP message
auto channel (std::make_shared<nano::transport::channel_udp> (node1->network.udp_channels, node2->network.endpoint (), node2->network_params.protocol.protocol_version));
node1->network.send_keepalive (channel);
Expand Down Expand Up @@ -1295,65 +1317,79 @@ TEST (node, fork_flip)

TEST (node, fork_multi_flip)
{
nano::system system (2);
auto & node1 (*system.nodes[0]);
auto & node2 (*system.nodes[1]);
ASSERT_EQ (1, node1.network.size ());
nano::keypair key1;
nano::genesis genesis;
auto send1 (std::make_shared<nano::send_block> (genesis.hash (), key1.pub, nano::genesis_amount - 100, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *system.work.generate (genesis.hash ())));
nano::publish publish1 (send1);
nano::keypair key2;
auto send2 (std::make_shared<nano::send_block> (genesis.hash (), key2.pub, nano::genesis_amount - 100, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *system.work.generate (genesis.hash ())));
nano::publish publish2 (send2);
auto send3 (std::make_shared<nano::send_block> (publish2.block->hash (), key2.pub, nano::genesis_amount - 100, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *system.work.generate (publish2.block->hash ())));
nano::publish publish3 (send3);
node1.network.process_message (publish1, node1.network.udp_channels.create (node1.network.endpoint ()));
node1.block_processor.flush ();
node2.network.process_message (publish2, node2.network.udp_channels.create (node2.network.endpoint ()));
node2.network.process_message (publish3, node2.network.udp_channels.create (node2.network.endpoint ()));
node2.block_processor.flush ();
ASSERT_EQ (1, node1.active.size ());
ASSERT_EQ (2, node2.active.size ());
system.wallet (0)->insert_adhoc (nano::test_genesis_key.prv);
node1.network.process_message (publish2, node1.network.udp_channels.create (node1.network.endpoint ()));
node1.network.process_message (publish3, node1.network.udp_channels.create (node1.network.endpoint ()));
node1.block_processor.flush ();
node2.network.process_message (publish1, node2.network.udp_channels.create (node2.network.endpoint ()));
node2.block_processor.flush ();
nano::unique_lock<std::mutex> lock (node2.active.mutex);
auto conflict (node2.active.roots.find (nano::qualified_root (genesis.hash (), genesis.hash ())));
ASSERT_NE (node2.active.roots.end (), conflict);
auto votes1 (conflict->election);
ASSERT_NE (nullptr, votes1);
ASSERT_EQ (1, votes1->last_votes.size ());
lock.unlock ();
{
auto transaction (system.nodes[0]->store.tx_begin_read ());
ASSERT_TRUE (node1.store.block_exists (transaction, publish1.block->hash ()));
}
{
auto transaction (system.nodes[1]->store.tx_begin_read ());
ASSERT_TRUE (node2.store.block_exists (transaction, publish2.block->hash ()));
ASSERT_TRUE (node2.store.block_exists (transaction, publish3.block->hash ()));
}
system.deadline_set (10s);
auto done (false);
while (!done)
std::vector<nano::transport::transport_type> types{ nano::transport::transport_type::tcp, nano::transport::transport_type::udp };
for (auto & type : types)
{
ASSERT_NO_ERROR (system.poll ());
done = node2.ledger.block_exists (publish1.block->hash ());
nano::node_flags node_flags;
if (type == nano::transport::transport_type::tcp)
{
node_flags.disable_udp = true;
}
else
{
node_flags.disable_tcp_realtime = true;
node_flags.disable_bootstrap_listener = true;
}
nano::system system (2, type, node_flags);
auto & node1 (*system.nodes[0]);
auto & node2 (*system.nodes[1]);
ASSERT_EQ (1, node1.network.size ());
nano::keypair key1;
nano::genesis genesis;
auto send1 (std::make_shared<nano::send_block> (genesis.hash (), key1.pub, nano::genesis_amount - 100, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *system.work.generate (genesis.hash ())));
nano::publish publish1 (send1);
nano::keypair key2;
auto send2 (std::make_shared<nano::send_block> (genesis.hash (), key2.pub, nano::genesis_amount - 100, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *system.work.generate (genesis.hash ())));
nano::publish publish2 (send2);
auto send3 (std::make_shared<nano::send_block> (publish2.block->hash (), key2.pub, nano::genesis_amount - 100, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *system.work.generate (publish2.block->hash ())));
nano::publish publish3 (send3);
node1.network.process_message (publish1, node1.network.udp_channels.create (node1.network.endpoint ()));
node1.block_processor.flush ();
node2.network.process_message (publish2, node2.network.udp_channels.create (node2.network.endpoint ()));
node2.network.process_message (publish3, node2.network.udp_channels.create (node2.network.endpoint ()));
node2.block_processor.flush ();
ASSERT_EQ (1, node1.active.size ());
ASSERT_EQ (2, node2.active.size ());
system.wallet (0)->insert_adhoc (nano::test_genesis_key.prv);
node1.network.process_message (publish2, node1.network.udp_channels.create (node1.network.endpoint ()));
node1.network.process_message (publish3, node1.network.udp_channels.create (node1.network.endpoint ()));
node1.block_processor.flush ();
node2.network.process_message (publish1, node2.network.udp_channels.create (node2.network.endpoint ()));
node2.block_processor.flush ();
nano::unique_lock<std::mutex> lock (node2.active.mutex);
auto conflict (node2.active.roots.find (nano::qualified_root (genesis.hash (), genesis.hash ())));
ASSERT_NE (node2.active.roots.end (), conflict);
auto votes1 (conflict->election);
ASSERT_NE (nullptr, votes1);
ASSERT_EQ (1, votes1->last_votes.size ());
lock.unlock ();
{
auto transaction (system.nodes[0]->store.tx_begin_read ());
ASSERT_TRUE (node1.store.block_exists (transaction, publish1.block->hash ()));
}
{
auto transaction (system.nodes[1]->store.tx_begin_read ());
ASSERT_TRUE (node2.store.block_exists (transaction, publish2.block->hash ()));
ASSERT_TRUE (node2.store.block_exists (transaction, publish3.block->hash ()));
}
system.deadline_set (10s);
auto done (false);
while (!done)
{
ASSERT_NO_ERROR (system.poll ());
done = node2.ledger.block_exists (publish1.block->hash ());
}
auto transaction1 (system.nodes[0]->store.tx_begin_read ());
auto transaction2 (system.nodes[1]->store.tx_begin_read ());
lock.lock ();
auto winner (*votes1->tally ().begin ());
ASSERT_EQ (*publish1.block, *winner.second);
ASSERT_EQ (nano::genesis_amount - 100, winner.first);
ASSERT_TRUE (node1.store.block_exists (transaction1, publish1.block->hash ()));
ASSERT_TRUE (node2.store.block_exists (transaction2, publish1.block->hash ()));
ASSERT_FALSE (node2.store.block_exists (transaction2, publish2.block->hash ()));
ASSERT_FALSE (node2.store.block_exists (transaction2, publish3.block->hash ()));
}
auto transaction1 (system.nodes[0]->store.tx_begin_read ());
auto transaction2 (system.nodes[1]->store.tx_begin_read ());
lock.lock ();
auto winner (*votes1->tally ().begin ());
ASSERT_EQ (*publish1.block, *winner.second);
ASSERT_EQ (nano::genesis_amount - 100, winner.first);
ASSERT_TRUE (node1.store.block_exists (transaction1, publish1.block->hash ()));
ASSERT_TRUE (node2.store.block_exists (transaction2, publish1.block->hash ()));
ASSERT_FALSE (node2.store.block_exists (transaction2, publish2.block->hash ()));
ASSERT_FALSE (node2.store.block_exists (transaction2, publish3.block->hash ()));
}

// Blocks that are no longer actively being voted on should be able to be evicted through bootstrapping.
Expand Down Expand Up @@ -1649,7 +1685,17 @@ TEST (node, broadcast_elected)
std::vector<nano::transport::transport_type> types{ nano::transport::transport_type::tcp, nano::transport::transport_type::udp };
for (auto & type : types)
{
nano::system system (3, type);
nano::node_flags node_flags;
if (type == nano::transport::transport_type::tcp)
{
node_flags.disable_udp = true;
}
else
{
node_flags.disable_tcp_realtime = true;
node_flags.disable_bootstrap_listener = true;
}
nano::system system (3, type, node_flags);
auto node0 (system.nodes[0]);
auto node1 (system.nodes[1]);
auto node2 (system.nodes[2]);
Expand Down Expand Up @@ -2232,7 +2278,17 @@ TEST (node, block_confirm)
std::vector<nano::transport::transport_type> types{ nano::transport::transport_type::tcp, nano::transport::transport_type::udp };
for (auto & type : types)
{
nano::system system (2, type);
nano::node_flags node_flags;
if (type == nano::transport::transport_type::tcp)
{
node_flags.disable_udp = true;
}
else
{
node_flags.disable_tcp_realtime = true;
node_flags.disable_bootstrap_listener = true;
}
nano::system system (2, type, node_flags);
nano::genesis genesis;
nano::keypair key;
system.wallet (1)->insert_adhoc (nano::test_genesis_key.prv);
Expand Down Expand Up @@ -2563,7 +2619,17 @@ TEST (node, vote_by_hash_republish)
std::vector<nano::transport::transport_type> types{ nano::transport::transport_type::tcp, nano::transport::transport_type::udp };
for (auto & type : types)
{
nano::system system (2, type);
nano::node_flags node_flags;
if (type == nano::transport::transport_type::tcp)
{
node_flags.disable_udp = true;
}
else
{
node_flags.disable_tcp_realtime = true;
node_flags.disable_bootstrap_listener = true;
}
nano::system system (2, type, node_flags);
nano::keypair key2;
system.wallet (1)->insert_adhoc (key2.prv);
nano::genesis genesis;
Expand Down
9 changes: 8 additions & 1 deletion nano/node/bootstrap/bootstrap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1361,7 +1361,14 @@ void nano::bootstrap_initiator::bootstrap (nano::endpoint const & endpoint_a, bo
{
if (add_to_peers)
{
node.network.udp_channels.insert (nano::transport::map_endpoint_to_v6 (endpoint_a), node.network_params.protocol.protocol_version);
if (!node.flags.disable_udp)
{
node.network.udp_channels.insert (nano::transport::map_endpoint_to_v6 (endpoint_a), node.network_params.protocol.protocol_version);
}
else if (!node.flags.disable_tcp_realtime)
{
node.network.merge_peer (nano::transport::map_endpoint_to_v6 (endpoint_a));
}
}
nano::unique_lock<std::mutex> lock (mutex);
if (!stopped)
Expand Down
14 changes: 13 additions & 1 deletion nano/node/bootstrap/bootstrap_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ port (port_a)

void nano::bootstrap_listener::start ()
{
nano::lock_guard<std::mutex> lock (mutex);
on = true;
listening_socket = std::make_shared<nano::server_socket> (node.shared (), boost::asio::ip::tcp::endpoint (boost::asio::ip::address_v6::any (), port), node.config.tcp_incoming_connections_max);
boost::system::error_code ec;
listening_socket->start (ec);
Expand All @@ -22,6 +24,7 @@ void nano::bootstrap_listener::start ()
node.logger.try_log (boost::str (boost::format ("Error while binding for incoming TCP/bootstrap on port %1%: %2%") % listening_socket->listening_port () % ec.message ()));
throw std::runtime_error (ec.message ());
}
assert (node.network.endpoint ().port () == listening_socket->listening_port ());
listening_socket->on_connection ([this](std::shared_ptr<nano::socket> new_connection, boost::system::error_code const & ec_a) {
bool keep_accepting = true;
if (ec_a)
Expand All @@ -47,6 +50,7 @@ void nano::bootstrap_listener::stop ()
}
if (listening_socket)
{
nano::lock_guard<std::mutex> lock (mutex);
listening_socket->close ();
listening_socket = nullptr;
}
Expand All @@ -70,7 +74,15 @@ void nano::bootstrap_listener::accept_action (boost::system::error_code const &

boost::asio::ip::tcp::endpoint nano::bootstrap_listener::endpoint ()
{
return boost::asio::ip::tcp::endpoint (boost::asio::ip::address_v6::loopback (), listening_socket->listening_port ());
nano::lock_guard<std::mutex> lock (mutex);
if (on && listening_socket)
{
return boost::asio::ip::tcp::endpoint (boost::asio::ip::address_v6::loopback (), listening_socket->listening_port ());
}
else
{
return boost::asio::ip::tcp::endpoint (boost::asio::ip::address_v6::loopback (), 0);
}
}

std::unique_ptr<nano::container_info_component> nano::collect_container_info (bootstrap_listener & bootstrap_listener, const std::string & name)
Expand Down
2 changes: 1 addition & 1 deletion nano/node/bootstrap/bootstrap_server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class bootstrap_listener final
nano::tcp_endpoint endpoint ();
nano::node & node;
std::shared_ptr<nano::server_socket> listening_socket;
bool on;
bool on{ false };
std::atomic<size_t> bootstrap_count{ 0 };
std::atomic<size_t> realtime_count{ 0 };

Expand Down
7 changes: 5 additions & 2 deletions nano/node/network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ limiter (node_a.config.bandwidth_limit),
node (node_a),
udp_channels (node_a, port_a),
tcp_channels (node_a),
port (port_a),
disconnect_observer ([]() {})
{
boost::thread::attributes attrs;
nano::thread_attributes::set (attrs);
for (size_t i = 0; i < node.config.network_threads; ++i)
for (size_t i = 0; i < node.config.network_threads && !node.flags.disable_udp; ++i)
{
packet_processing_threads.push_back (boost::thread (attrs, [this]() {
nano::thread_role::set (nano::thread_role::name::packet_processing);
Expand Down Expand Up @@ -68,6 +69,7 @@ void nano::network::start ()
if (!node.flags.disable_udp)
{
udp_channels.start ();
assert (udp_channels.get_local_endpoint ().port () == port);
}
if (!node.flags.disable_tcp_realtime)
{
Expand All @@ -84,6 +86,7 @@ void nano::network::stop ()
tcp_channels.stop ();
resolver.cancel ();
buffer_container.stop ();
port = 0;
for (auto & thread : packet_processing_threads)
{
thread.join ();
Expand Down Expand Up @@ -753,7 +756,7 @@ std::shared_ptr<nano::transport::channel> nano::network::find_node_id (nano::acc

nano::endpoint nano::network::endpoint ()
{
return udp_channels.get_local_endpoint ();
return nano::endpoint (boost::asio::ip::address_v6::loopback (), port);
}

void nano::network::cleanup (std::chrono::steady_clock::time_point const & cutoff_a)
Expand Down
Loading