Don't bind to UDP socket with --disable_udp flag (#2464)
* don't bind to UDP socket with --disable_udp flag * don't start port mapping with both UDP & TCP sockets disabled * use predefined port in `nano::network::endpoint ()` function rather than call to UDP socket * update TCP (bootstrap) server `endpoint ()` function to return empty endpoint if server is not started * update several tests to run twice: with UDP only and with TCP only * attepmt to start realtime TCP connection to RPC bootstrap peer if UDP is disabled * make UDP socket unique_ptr
This commit is contained in:
		
					parent
					
						
							
								110b9540f9
							
						
					
				
			
			
				commit
				
					
						e9aae5cb6e
					
				
			
		
					 13 changed files with 273 additions and 128 deletions
				
			
		| 
						 | 
					@ -275,7 +275,17 @@ TEST (network, send_valid_confirm_ack)
 | 
				
			||||||
	std::vector<nano::transport::transport_type> types{ nano::transport::transport_type::tcp, nano::transport::transport_type::udp };
 | 
						std::vector<nano::transport::transport_type> types{ nano::transport::transport_type::tcp, nano::transport::transport_type::udp };
 | 
				
			||||||
	for (auto & type : types)
 | 
						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 & node1 (*system.nodes[0]);
 | 
							auto & node1 (*system.nodes[0]);
 | 
				
			||||||
		auto & node2 (*system.nodes[1]);
 | 
							auto & node2 (*system.nodes[1]);
 | 
				
			||||||
		nano::keypair key2;
 | 
							nano::keypair key2;
 | 
				
			||||||
| 
						 | 
					@ -301,7 +311,17 @@ TEST (network, send_valid_publish)
 | 
				
			||||||
	std::vector<nano::transport::transport_type> types{ nano::transport::transport_type::tcp, nano::transport::transport_type::udp };
 | 
						std::vector<nano::transport::transport_type> types{ nano::transport::transport_type::tcp, nano::transport::transport_type::udp };
 | 
				
			||||||
	for (auto & type : types)
 | 
						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 & node1 (*system.nodes[0]);
 | 
							auto & node1 (*system.nodes[0]);
 | 
				
			||||||
		auto & node2 (*system.nodes[1]);
 | 
							auto & node2 (*system.nodes[1]);
 | 
				
			||||||
		node1.bootstrap_initiator.stop ();
 | 
							node1.bootstrap_initiator.stop ();
 | 
				
			||||||
| 
						 | 
					@ -381,7 +401,17 @@ TEST (receivable_processor, send_with_receive)
 | 
				
			||||||
	std::vector<nano::transport::transport_type> types{ nano::transport::transport_type::tcp, nano::transport::transport_type::udp };
 | 
						std::vector<nano::transport::transport_type> types{ nano::transport::transport_type::tcp, nano::transport::transport_type::udp };
 | 
				
			||||||
	for (auto & type : types)
 | 
						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 & node1 (*system.nodes[0]);
 | 
							auto & node1 (*system.nodes[0]);
 | 
				
			||||||
		auto & node2 (*system.nodes[1]);
 | 
							auto & node2 (*system.nodes[1]);
 | 
				
			||||||
		auto amount (std::numeric_limits<nano::uint128_t>::max ());
 | 
							auto amount (std::numeric_limits<nano::uint128_t>::max ());
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1109,6 +1109,26 @@ TEST (node_flags, disable_tcp_realtime)
 | 
				
			||||||
	ASSERT_EQ (nano::transport::transport_type::udp, list2[0]->get_type ());
 | 
						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)
 | 
					TEST (node_flags, disable_udp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	nano::system system (1);
 | 
						nano::system system (1);
 | 
				
			||||||
| 
						 | 
					@ -1118,6 +1138,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));
 | 
						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);
 | 
						system.nodes.push_back (node2);
 | 
				
			||||||
	node2->start ();
 | 
						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
 | 
						// 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));
 | 
						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);
 | 
						node1->network.send_keepalive (channel);
 | 
				
			||||||
| 
						 | 
					@ -1302,65 +1324,79 @@ TEST (node, fork_flip)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST (node, fork_multi_flip)
 | 
					TEST (node, fork_multi_flip)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	nano::system system (2);
 | 
						std::vector<nano::transport::transport_type> types{ nano::transport::transport_type::tcp, nano::transport::transport_type::udp };
 | 
				
			||||||
	auto & node1 (*system.nodes[0]);
 | 
						for (auto & type : types)
 | 
				
			||||||
	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 (node1.store.tx_begin_read ());
 | 
							nano::node_flags node_flags;
 | 
				
			||||||
		ASSERT_TRUE (node1.store.block_exists (transaction, publish1.block->hash ()));
 | 
							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 (node1.store.tx_begin_read ());
 | 
				
			||||||
 | 
								ASSERT_TRUE (node1.store.block_exists (transaction, publish1.block->hash ()));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								auto transaction (node2.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 (node1.store.tx_begin_read ());
 | 
				
			||||||
 | 
							auto transaction2 (node2.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 transaction (node2.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 (node1.store.tx_begin_read ());
 | 
					 | 
				
			||||||
	auto transaction2 (node2.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.
 | 
					// Blocks that are no longer actively being voted on should be able to be evicted through bootstrapping.
 | 
				
			||||||
| 
						 | 
					@ -1657,7 +1693,17 @@ TEST (node, broadcast_elected)
 | 
				
			||||||
	std::vector<nano::transport::transport_type> types{ nano::transport::transport_type::tcp, nano::transport::transport_type::udp };
 | 
						std::vector<nano::transport::transport_type> types{ nano::transport::transport_type::tcp, nano::transport::transport_type::udp };
 | 
				
			||||||
	for (auto & type : types)
 | 
						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 node0 (system.nodes[0]);
 | 
				
			||||||
		auto node1 (system.nodes[1]);
 | 
							auto node1 (system.nodes[1]);
 | 
				
			||||||
		auto node2 (system.nodes[2]);
 | 
							auto node2 (system.nodes[2]);
 | 
				
			||||||
| 
						 | 
					@ -2340,7 +2386,17 @@ TEST (node, block_confirm)
 | 
				
			||||||
	std::vector<nano::transport::transport_type> types{ nano::transport::transport_type::tcp, nano::transport::transport_type::udp };
 | 
						std::vector<nano::transport::transport_type> types{ nano::transport::transport_type::tcp, nano::transport::transport_type::udp };
 | 
				
			||||||
	for (auto & type : types)
 | 
						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 & node1 (*system.nodes[0]);
 | 
							auto & node1 (*system.nodes[0]);
 | 
				
			||||||
		auto & node2 (*system.nodes[1]);
 | 
							auto & node2 (*system.nodes[1]);
 | 
				
			||||||
		nano::genesis genesis;
 | 
							nano::genesis genesis;
 | 
				
			||||||
| 
						 | 
					@ -2734,7 +2790,17 @@ TEST (node, vote_by_hash_republish)
 | 
				
			||||||
	std::vector<nano::transport::transport_type> types{ nano::transport::transport_type::tcp, nano::transport::transport_type::udp };
 | 
						std::vector<nano::transport::transport_type> types{ nano::transport::transport_type::tcp, nano::transport::transport_type::udp };
 | 
				
			||||||
	for (auto & type : types)
 | 
						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 & node1 (*system.nodes[0]);
 | 
							auto & node1 (*system.nodes[0]);
 | 
				
			||||||
		auto & node2 (*system.nodes[1]);
 | 
							auto & node2 (*system.nodes[1]);
 | 
				
			||||||
		nano::keypair key2;
 | 
							nano::keypair key2;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1391,7 +1391,14 @@ void nano::bootstrap_initiator::bootstrap (nano::endpoint const & endpoint_a, bo
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (add_to_peers)
 | 
						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);
 | 
						nano::unique_lock<std::mutex> lock (mutex);
 | 
				
			||||||
	if (!stopped)
 | 
						if (!stopped)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,6 +14,8 @@ port (port_a)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void nano::bootstrap_listener::start ()
 | 
					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);
 | 
						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;
 | 
						boost::system::error_code ec;
 | 
				
			||||||
	listening_socket->start (ec);
 | 
						listening_socket->start (ec);
 | 
				
			||||||
| 
						 | 
					@ -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 ()));
 | 
							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 ());
 | 
							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) {
 | 
						listening_socket->on_connection ([this](std::shared_ptr<nano::socket> new_connection, boost::system::error_code const & ec_a) {
 | 
				
			||||||
		bool keep_accepting = true;
 | 
							bool keep_accepting = true;
 | 
				
			||||||
		if (ec_a)
 | 
							if (ec_a)
 | 
				
			||||||
| 
						 | 
					@ -47,6 +50,7 @@ void nano::bootstrap_listener::stop ()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (listening_socket)
 | 
						if (listening_socket)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 | 
							nano::lock_guard<std::mutex> lock (mutex);
 | 
				
			||||||
		listening_socket->close ();
 | 
							listening_socket->close ();
 | 
				
			||||||
		listening_socket = nullptr;
 | 
							listening_socket = nullptr;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -70,7 +74,15 @@ void nano::bootstrap_listener::accept_action (boost::system::error_code const &
 | 
				
			||||||
 | 
					
 | 
				
			||||||
boost::asio::ip::tcp::endpoint nano::bootstrap_listener::endpoint ()
 | 
					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)
 | 
					std::unique_ptr<nano::container_info_component> nano::collect_container_info (bootstrap_listener & bootstrap_listener, const std::string & name)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,7 +23,7 @@ public:
 | 
				
			||||||
	nano::tcp_endpoint endpoint ();
 | 
						nano::tcp_endpoint endpoint ();
 | 
				
			||||||
	nano::node & node;
 | 
						nano::node & node;
 | 
				
			||||||
	std::shared_ptr<nano::server_socket> listening_socket;
 | 
						std::shared_ptr<nano::server_socket> listening_socket;
 | 
				
			||||||
	bool on;
 | 
						bool on{ false };
 | 
				
			||||||
	std::atomic<size_t> bootstrap_count{ 0 };
 | 
						std::atomic<size_t> bootstrap_count{ 0 };
 | 
				
			||||||
	std::atomic<size_t> realtime_count{ 0 };
 | 
						std::atomic<size_t> realtime_count{ 0 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,11 +16,12 @@ limiter (node_a.config.bandwidth_limit),
 | 
				
			||||||
node (node_a),
 | 
					node (node_a),
 | 
				
			||||||
udp_channels (node_a, port_a),
 | 
					udp_channels (node_a, port_a),
 | 
				
			||||||
tcp_channels (node_a),
 | 
					tcp_channels (node_a),
 | 
				
			||||||
 | 
					port (port_a),
 | 
				
			||||||
disconnect_observer ([]() {})
 | 
					disconnect_observer ([]() {})
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	boost::thread::attributes attrs;
 | 
						boost::thread::attributes attrs;
 | 
				
			||||||
	nano::thread_attributes::set (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.emplace_back (attrs, [this]() {
 | 
							packet_processing_threads.emplace_back (attrs, [this]() {
 | 
				
			||||||
			nano::thread_role::set (nano::thread_role::name::packet_processing);
 | 
								nano::thread_role::set (nano::thread_role::name::packet_processing);
 | 
				
			||||||
| 
						 | 
					@ -68,6 +69,7 @@ void nano::network::start ()
 | 
				
			||||||
	if (!node.flags.disable_udp)
 | 
						if (!node.flags.disable_udp)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		udp_channels.start ();
 | 
							udp_channels.start ();
 | 
				
			||||||
 | 
							assert (udp_channels.get_local_endpoint ().port () == port);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (!node.flags.disable_tcp_realtime)
 | 
						if (!node.flags.disable_tcp_realtime)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
| 
						 | 
					@ -84,6 +86,7 @@ void nano::network::stop ()
 | 
				
			||||||
		tcp_channels.stop ();
 | 
							tcp_channels.stop ();
 | 
				
			||||||
		resolver.cancel ();
 | 
							resolver.cancel ();
 | 
				
			||||||
		buffer_container.stop ();
 | 
							buffer_container.stop ();
 | 
				
			||||||
 | 
							port = 0;
 | 
				
			||||||
		for (auto & thread : packet_processing_threads)
 | 
							for (auto & thread : packet_processing_threads)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			thread.join ();
 | 
								thread.join ();
 | 
				
			||||||
| 
						 | 
					@ -656,7 +659,7 @@ std::shared_ptr<nano::transport::channel> nano::network::find_node_id (nano::acc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nano::endpoint nano::network::endpoint ()
 | 
					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)
 | 
					void nano::network::cleanup (std::chrono::steady_clock::time_point const & cutoff_a)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -159,6 +159,7 @@ public:
 | 
				
			||||||
	nano::node & node;
 | 
						nano::node & node;
 | 
				
			||||||
	nano::transport::udp_channels udp_channels;
 | 
						nano::transport::udp_channels udp_channels;
 | 
				
			||||||
	nano::transport::tcp_channels tcp_channels;
 | 
						nano::transport::tcp_channels tcp_channels;
 | 
				
			||||||
 | 
						std::atomic<uint16_t> port{ 0 };
 | 
				
			||||||
	std::function<void()> disconnect_observer;
 | 
						std::function<void()> disconnect_observer;
 | 
				
			||||||
	// Called when a new channel is observed
 | 
						// Called when a new channel is observed
 | 
				
			||||||
	std::function<void(std::shared_ptr<nano::transport::channel>)> channel_observer;
 | 
						std::function<void(std::shared_ptr<nano::transport::channel>)> channel_observer;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -646,9 +646,11 @@ void nano::node::start ()
 | 
				
			||||||
	ongoing_rep_calculation ();
 | 
						ongoing_rep_calculation ();
 | 
				
			||||||
	ongoing_peer_store ();
 | 
						ongoing_peer_store ();
 | 
				
			||||||
	ongoing_online_weight_calculation_queue ();
 | 
						ongoing_online_weight_calculation_queue ();
 | 
				
			||||||
	if (config.tcp_incoming_connections_max > 0)
 | 
						bool tcp_enabled (false);
 | 
				
			||||||
 | 
						if (config.tcp_incoming_connections_max > 0 && !(flags.disable_bootstrap_listener && flags.disable_tcp_realtime))
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		bootstrap.start ();
 | 
							bootstrap.start ();
 | 
				
			||||||
 | 
							tcp_enabled = true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (!flags.disable_backup)
 | 
						if (!flags.disable_backup)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
| 
						 | 
					@ -663,7 +665,8 @@ void nano::node::start ()
 | 
				
			||||||
			this_l->bootstrap_wallet ();
 | 
								this_l->bootstrap_wallet ();
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (config.external_address == boost::asio::ip::address_v6{}.any ().to_string ())
 | 
						// 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))
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		port_mapping.start ();
 | 
							port_mapping.start ();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -1352,6 +1355,9 @@ nano::node_flags const & nano::inactive_node_flag_defaults ()
 | 
				
			||||||
	node_flags.generate_cache.reps = false;
 | 
						node_flags.generate_cache.reps = false;
 | 
				
			||||||
	node_flags.generate_cache.cemented_count = false;
 | 
						node_flags.generate_cache.cemented_count = false;
 | 
				
			||||||
	node_flags.generate_cache.unchecked_count = false;
 | 
						node_flags.generate_cache.unchecked_count = false;
 | 
				
			||||||
 | 
						node_flags.disable_udp = true;
 | 
				
			||||||
 | 
						node_flags.disable_bootstrap_listener = true;
 | 
				
			||||||
 | 
						node_flags.disable_tcp_realtime = true;
 | 
				
			||||||
	return node_flags;
 | 
						return node_flags;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -109,14 +109,14 @@ nano::system::system ()
 | 
				
			||||||
	logging.init (nano::unique_path ());
 | 
						logging.init (nano::unique_path ());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nano::system::system (uint16_t count_a, nano::transport::transport_type type_a) :
 | 
					nano::system::system (uint16_t count_a, nano::transport::transport_type type_a, nano::node_flags flags_a) :
 | 
				
			||||||
system ()
 | 
					system ()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	nodes.reserve (count_a);
 | 
						nodes.reserve (count_a);
 | 
				
			||||||
	for (uint16_t i (0); i < count_a; ++i)
 | 
						for (uint16_t i (0); i < count_a; ++i)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		nano::node_config config (nano::get_available_port (), logging);
 | 
							nano::node_config config (nano::get_available_port (), logging);
 | 
				
			||||||
		add_node (config, nano::node_flags (), type_a);
 | 
							add_node (config, flags_a, type_a);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,7 +17,7 @@ class system final
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	system ();
 | 
						system ();
 | 
				
			||||||
	system (uint16_t, nano::transport::transport_type = nano::transport::transport_type::tcp);
 | 
						system (uint16_t, nano::transport::transport_type = nano::transport::transport_type::tcp, nano::node_flags = nano::node_flags ());
 | 
				
			||||||
	~system ();
 | 
						~system ();
 | 
				
			||||||
	void generate_activity (nano::node &, std::vector<nano::account> &);
 | 
						void generate_activity (nano::node &, std::vector<nano::account> &);
 | 
				
			||||||
	void generate_mass_activity (uint32_t, nano::node &);
 | 
						void generate_mass_activity (uint32_t, nano::node &);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -310,6 +310,7 @@ void nano::transport::tcp_channels::process_keepalive (nano::keepalive const & m
 | 
				
			||||||
			nano::endpoint new_endpoint (endpoint_a.address (), peer0.port ());
 | 
								nano::endpoint new_endpoint (endpoint_a.address (), peer0.port ());
 | 
				
			||||||
			node.network.merge_peer (new_endpoint);
 | 
								node.network.merge_peer (new_endpoint);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							// Used to store sender endpoint information only
 | 
				
			||||||
		auto udp_channel (std::make_shared<nano::transport::channel_udp> (node.network.udp_channels, nano::transport::map_tcp_to_endpoint (endpoint_a), node.network_params.protocol.protocol_version));
 | 
							auto udp_channel (std::make_shared<nano::transport::channel_udp> (node.network.udp_channels, nano::transport::map_tcp_to_endpoint (endpoint_a), node.network_params.protocol.protocol_version));
 | 
				
			||||||
		node.network.process_message (message_a, udp_channel);
 | 
							node.network.process_message (message_a, udp_channel);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -353,7 +354,7 @@ bool nano::transport::tcp_channels::reachout (nano::endpoint const & endpoint_a)
 | 
				
			||||||
	auto tcp_endpoint (nano::transport::map_endpoint_to_tcp (endpoint_a));
 | 
						auto tcp_endpoint (nano::transport::map_endpoint_to_tcp (endpoint_a));
 | 
				
			||||||
	// Don't overload single IP
 | 
						// Don't overload single IP
 | 
				
			||||||
	bool error = max_ip_connections (tcp_endpoint);
 | 
						bool error = max_ip_connections (tcp_endpoint);
 | 
				
			||||||
	if (!error)
 | 
						if (!error && !node.flags.disable_tcp_realtime)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		// Don't keepalive to nodes that already sent us something
 | 
							// Don't keepalive to nodes that already sent us something
 | 
				
			||||||
		error |= find_channel (tcp_endpoint) != nullptr;
 | 
							error |= find_channel (tcp_endpoint) != nullptr;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -68,25 +68,35 @@ std::string nano::transport::channel_udp::to_string () const
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nano::transport::udp_channels::udp_channels (nano::node & node_a, uint16_t port_a) :
 | 
					nano::transport::udp_channels::udp_channels (nano::node & node_a, uint16_t port_a) :
 | 
				
			||||||
node (node_a),
 | 
					node (node_a),
 | 
				
			||||||
strand (node_a.io_ctx.get_executor ()),
 | 
					strand (node_a.io_ctx.get_executor ())
 | 
				
			||||||
socket (node_a.io_ctx, nano::endpoint (boost::asio::ip::address_v6::any (), port_a))
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	boost::system::error_code ec;
 | 
						if (!node.flags.disable_udp)
 | 
				
			||||||
	auto port (socket.local_endpoint (ec).port ());
 | 
					 | 
				
			||||||
	if (ec)
 | 
					 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		node.logger.try_log ("Unable to retrieve port: ", ec.message ());
 | 
							socket = std::make_unique<boost::asio::ip::udp::socket> (node_a.io_ctx, nano::endpoint (boost::asio::ip::address_v6::any (), port_a));
 | 
				
			||||||
 | 
							boost::system::error_code ec;
 | 
				
			||||||
 | 
							auto port (socket->local_endpoint (ec).port ());
 | 
				
			||||||
 | 
							if (ec)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								node.logger.try_log ("Unable to retrieve port: ", ec.message ());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							local_endpoint = nano::endpoint (boost::asio::ip::address_v6::loopback (), port);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							local_endpoint = nano::endpoint (boost::asio::ip::address_v6::loopback (), 0);
 | 
				
			||||||
 | 
							stopped = true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	local_endpoint = nano::endpoint (boost::asio::ip::address_v6::loopback (), port);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void nano::transport::udp_channels::send (nano::shared_const_buffer const & buffer_a, nano::endpoint endpoint_a, std::function<void(boost::system::error_code const &, size_t)> const & callback_a)
 | 
					void nano::transport::udp_channels::send (nano::shared_const_buffer const & buffer_a, nano::endpoint endpoint_a, std::function<void(boost::system::error_code const &, size_t)> const & callback_a)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	boost::asio::post (strand,
 | 
						boost::asio::post (strand,
 | 
				
			||||||
	[this, buffer_a, endpoint_a, callback_a]() {
 | 
						[this, buffer_a, endpoint_a, callback_a]() {
 | 
				
			||||||
		this->socket.async_send_to (buffer_a, endpoint_a,
 | 
							if (!this->stopped)
 | 
				
			||||||
		boost::asio::bind_executor (strand, callback_a));
 | 
							{
 | 
				
			||||||
 | 
								this->socket->async_send_to (buffer_a, endpoint_a,
 | 
				
			||||||
 | 
								boost::asio::bind_executor (strand, callback_a));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -261,43 +271,48 @@ nano::tcp_endpoint nano::transport::udp_channels::bootstrap_peer (uint8_t connec
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void nano::transport::udp_channels::receive ()
 | 
					void nano::transport::udp_channels::receive ()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (node.config.logging.network_packet_logging ())
 | 
						if (!stopped)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		node.logger.try_log ("Receiving packet");
 | 
							release_assert (socket != nullptr);
 | 
				
			||||||
	}
 | 
							if (node.config.logging.network_packet_logging ())
 | 
				
			||||||
 | 
					 | 
				
			||||||
	auto data (node.network.buffer_container.allocate ());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	socket.async_receive_from (boost::asio::buffer (data->buffer, nano::network::buffer_size), data->endpoint,
 | 
					 | 
				
			||||||
	boost::asio::bind_executor (strand,
 | 
					 | 
				
			||||||
	[this, data](boost::system::error_code const & error, std::size_t size_a) {
 | 
					 | 
				
			||||||
		if (!error && !stopped)
 | 
					 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			data->size = size_a;
 | 
								node.logger.try_log ("Receiving packet");
 | 
				
			||||||
			this->node.network.buffer_container.enqueue (data);
 | 
					 | 
				
			||||||
			this->receive ();
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else
 | 
					
 | 
				
			||||||
		{
 | 
							auto data (node.network.buffer_container.allocate ());
 | 
				
			||||||
			this->node.network.buffer_container.release (data);
 | 
					
 | 
				
			||||||
			if (error)
 | 
							socket->async_receive_from (boost::asio::buffer (data->buffer, nano::network::buffer_size), data->endpoint,
 | 
				
			||||||
 | 
							boost::asio::bind_executor (strand,
 | 
				
			||||||
 | 
							[this, data](boost::system::error_code const & error, std::size_t size_a) {
 | 
				
			||||||
 | 
								if (!error && !this->stopped)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				if (this->node.config.logging.network_logging ())
 | 
									data->size = size_a;
 | 
				
			||||||
 | 
									this->node.network.buffer_container.enqueue (data);
 | 
				
			||||||
 | 
									this->receive ();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									this->node.network.buffer_container.release (data);
 | 
				
			||||||
 | 
									if (error)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					this->node.logger.try_log (boost::str (boost::format ("UDP Receive error: %1%") % error.message ()));
 | 
										if (this->node.config.logging.network_logging ())
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											this->node.logger.try_log (boost::str (boost::format ("UDP Receive error: %1%") % error.message ()));
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if (!this->stopped)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										this->node.alarm.add (std::chrono::steady_clock::now () + std::chrono::seconds (5), [this]() { this->receive (); });
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if (!stopped)
 | 
							}));
 | 
				
			||||||
			{
 | 
						}
 | 
				
			||||||
				this->node.alarm.add (std::chrono::steady_clock::now () + std::chrono::seconds (5), [this]() { this->receive (); });
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}));
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void nano::transport::udp_channels::start ()
 | 
					void nano::transport::udp_channels::start ()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	for (size_t i = 0; i < node.config.io_threads; ++i)
 | 
						assert (!node.flags.disable_udp);
 | 
				
			||||||
 | 
						for (size_t i = 0; i < node.config.io_threads && !stopped; ++i)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		boost::asio::post (strand, [this]() {
 | 
							boost::asio::post (strand, [this]() {
 | 
				
			||||||
			receive ();
 | 
								receive ();
 | 
				
			||||||
| 
						 | 
					@ -309,29 +324,33 @@ void nano::transport::udp_channels::start ()
 | 
				
			||||||
void nano::transport::udp_channels::stop ()
 | 
					void nano::transport::udp_channels::stop ()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	// Stop and invalidate local endpoint
 | 
						// Stop and invalidate local endpoint
 | 
				
			||||||
	stopped = true;
 | 
						if (!stopped.exchange (true))
 | 
				
			||||||
	nano::lock_guard<std::mutex> lock (mutex);
 | 
						{
 | 
				
			||||||
	local_endpoint = nano::endpoint (boost::asio::ip::address_v6::loopback (), 0);
 | 
							nano::lock_guard<std::mutex> lock (mutex);
 | 
				
			||||||
 | 
							local_endpoint = nano::endpoint (boost::asio::ip::address_v6::loopback (), 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// On test-net, close directly to avoid address-reuse issues. On livenet, close
 | 
							// On test-net, close directly to avoid address-reuse issues. On livenet, close
 | 
				
			||||||
	// through the strand as multiple IO threads may access the socket.
 | 
							// through the strand as multiple IO threads may access the socket.
 | 
				
			||||||
	if (node.network_params.network.is_test_network ())
 | 
							if (node.network_params.network.is_test_network ())
 | 
				
			||||||
	{
 | 
							{
 | 
				
			||||||
		this->close_socket ();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		boost::asio::dispatch (strand, [this] {
 | 
					 | 
				
			||||||
			this->close_socket ();
 | 
								this->close_socket ();
 | 
				
			||||||
		});
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								boost::asio::dispatch (strand, [this] {
 | 
				
			||||||
 | 
									this->close_socket ();
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void nano::transport::udp_channels::close_socket ()
 | 
					void nano::transport::udp_channels::close_socket ()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	boost::system::error_code ignored;
 | 
						if (this->socket != nullptr)
 | 
				
			||||||
	this->socket.close (ignored);
 | 
						{
 | 
				
			||||||
	this->local_endpoint = nano::endpoint (boost::asio::ip::address_v6::loopback (), 0);
 | 
							boost::system::error_code ignored;
 | 
				
			||||||
 | 
							this->socket->close (ignored);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nano::endpoint nano::transport::udp_channels::get_local_endpoint () const
 | 
					nano::endpoint nano::transport::udp_channels::get_local_endpoint () const
 | 
				
			||||||
| 
						 | 
					@ -587,7 +606,7 @@ bool nano::transport::udp_channels::reachout (nano::endpoint const & endpoint_a)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	// Don't overload single IP
 | 
						// Don't overload single IP
 | 
				
			||||||
	bool error = max_ip_connections (endpoint_a);
 | 
						bool error = max_ip_connections (endpoint_a);
 | 
				
			||||||
	if (!error)
 | 
						if (!error && !node.flags.disable_udp)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		auto endpoint_l (nano::transport::map_endpoint_to_v6 (endpoint_a));
 | 
							auto endpoint_l (nano::transport::map_endpoint_to_v6 (endpoint_a));
 | 
				
			||||||
		// Don't keepalive to nodes that already sent us something
 | 
							// Don't keepalive to nodes that already sent us something
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -181,7 +181,7 @@ namespace transport
 | 
				
			||||||
		attempts;
 | 
							attempts;
 | 
				
			||||||
		// clang-format on
 | 
							// clang-format on
 | 
				
			||||||
		boost::asio::strand<boost::asio::io_context::executor_type> strand;
 | 
							boost::asio::strand<boost::asio::io_context::executor_type> strand;
 | 
				
			||||||
		boost::asio::ip::udp::socket socket;
 | 
							std::unique_ptr<boost::asio::ip::udp::socket> socket;
 | 
				
			||||||
		nano::endpoint local_endpoint;
 | 
							nano::endpoint local_endpoint;
 | 
				
			||||||
		std::atomic<bool> stopped{ false };
 | 
							std::atomic<bool> stopped{ false };
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue