From 58bacfab0985e40f8f5ea338723e6c60560c356f Mon Sep 17 00:00:00 2001 From: Trent Nelson Date: Fri, 5 Apr 2024 22:39:22 -0600 Subject: [PATCH 1/3] net-utils: remove dubious `find_available_port_in_range()` utility --- gossip/src/cluster_info.rs | 10 +++++----- gossip/src/main.rs | 9 ++++----- net-utils/src/lib.rs | 38 -------------------------------------- rpc/src/rpc_service.rs | 7 +++---- validator/src/main.rs | 8 ++++---- 5 files changed, 16 insertions(+), 56 deletions(-) diff --git a/gossip/src/cluster_info.rs b/gossip/src/cluster_info.rs index 7d737d313eeae7..06f2876ef5e3b6 100644 --- a/gossip/src/cluster_info.rs +++ b/gossip/src/cluster_info.rs @@ -55,7 +55,7 @@ use { solana_measure::measure::Measure, solana_net_utils::{ bind_common, bind_common_in_range, bind_in_range, bind_two_in_range_with_offset, - find_available_port_in_range, multi_bind_in_range, PortRange, + multi_bind_in_range, PortRange, }, solana_perf::{ data_budget::DataBudget, @@ -2822,9 +2822,9 @@ impl Node { bind_two_in_range_with_offset(localhost_ip_addr, port_range, QUIC_PORT_OFFSET).unwrap(); let tpu_vote = UdpSocket::bind(&localhost_bind_addr).unwrap(); let repair = UdpSocket::bind(&localhost_bind_addr).unwrap(); - let rpc_port = find_available_port_in_range(localhost_ip_addr, port_range).unwrap(); + let (rpc_port, _) = bind_common_in_range(localhost_ip_addr, port_range).unwrap(); let rpc_addr = SocketAddr::new(localhost_ip_addr, rpc_port); - let rpc_pubsub_port = find_available_port_in_range(localhost_ip_addr, port_range).unwrap(); + let (rpc_pubsub_port, _) = bind_common_in_range(localhost_ip_addr, port_range).unwrap(); let rpc_pubsub_addr = SocketAddr::new(localhost_ip_addr, rpc_pubsub_port); let broadcast = vec![UdpSocket::bind(&unspecified_bind_addr).unwrap()]; let retransmit_socket = UdpSocket::bind(&unspecified_bind_addr).unwrap(); @@ -2931,8 +2931,8 @@ impl Node { let (_, broadcast) = Self::bind(bind_ip_addr, port_range); let (_, ancestor_hashes_requests) = Self::bind(bind_ip_addr, port_range); - let rpc_port = find_available_port_in_range(bind_ip_addr, port_range).unwrap(); - let rpc_pubsub_port = find_available_port_in_range(bind_ip_addr, port_range).unwrap(); + let (rpc_port, _) = bind_common_in_range(bind_ip_addr, port_range).unwrap(); + let (rpc_pubsub_port, _) = bind_common_in_range(bind_ip_addr, port_range).unwrap(); let addr = gossip_addr.ip(); let mut info = ContactInfo::new( diff --git a/gossip/src/main.rs b/gossip/src/main.rs index 1f31195f431d36..05d46bfae865d7 100644 --- a/gossip/src/main.rs +++ b/gossip/src/main.rs @@ -236,11 +236,10 @@ fn process_spy(matches: &ArgMatches, socket_addr_space: SocketAddrSpace) -> std: let gossip_addr = SocketAddr::new( gossip_host, value_t!(matches, "gossip_port", u16).unwrap_or_else(|_| { - solana_net_utils::find_available_port_in_range( - IpAddr::V4(Ipv4Addr::UNSPECIFIED), - (0, 1), - ) - .expect("unable to find an available gossip port") + let (gossip_port, _) = + solana_net_utils::bind_common_in_range(IpAddr::V4(Ipv4Addr::UNSPECIFIED), (0, 1)) + .expect("unable to find an available gossip port"); + gossip_port }), ); let discover_timeout = Duration::from_secs(timeout.unwrap_or(u64::MAX)); diff --git a/net-utils/src/lib.rs b/net-utils/src/lib.rs index 2d1b6249f3fcb1..1154246f2fd6d5 100644 --- a/net-utils/src/lib.rs +++ b/net-utils/src/lib.rs @@ -3,7 +3,6 @@ use { crossbeam_channel::unbounded, log::*, - rand::{thread_rng, Rng}, socket2::{Domain, SockAddr, Socket, Type}, std::{ collections::{BTreeMap, HashSet}, @@ -558,29 +557,6 @@ pub fn bind_two_in_range_with_offset( )) } -pub fn find_available_port_in_range(ip_addr: IpAddr, range: PortRange) -> io::Result { - let (start, end) = range; - let mut tries_left = end - start; - let mut rand_port = thread_rng().gen_range(start..end); - loop { - match bind_common(ip_addr, rand_port, false) { - Ok(_) => { - break Ok(rand_port); - } - Err(err) => { - if tries_left == 0 { - return Err(err); - } - } - } - rand_port += 1; - if rand_port == end { - rand_port = start; - } - tries_left -= 1; - } -} - #[cfg(test)] mod tests { use {super::*, std::net::Ipv4Addr}; @@ -717,20 +693,6 @@ mod tests { bind_in_range(ip_addr, (2000, 1999)).unwrap_err(); } - #[test] - fn test_find_available_port_in_range() { - let ip_addr = IpAddr::V4(Ipv4Addr::UNSPECIFIED); - assert_eq!( - find_available_port_in_range(ip_addr, (3000, 3001)).unwrap(), - 3000 - ); - let port = find_available_port_in_range(ip_addr, (3000, 3050)).unwrap(); - assert!((3000..3050).contains(&port)); - - let _socket = bind_to(ip_addr, port, false).unwrap(); - find_available_port_in_range(ip_addr, (port, port + 1)).unwrap_err(); - } - #[test] fn test_bind_common_in_range() { let ip_addr = IpAddr::V4(Ipv4Addr::UNSPECIFIED); diff --git a/rpc/src/rpc_service.rs b/rpc/src/rpc_service.rs index 10580b4711c054..74b935937d93aa 100644 --- a/rpc/src/rpc_service.rs +++ b/rpc/src/rpc_service.rs @@ -624,10 +624,9 @@ mod tests { let bank = Bank::new_for_tests(&genesis_config); let cluster_info = Arc::new(new_test_cluster_info()); let ip_addr = IpAddr::V4(Ipv4Addr::UNSPECIFIED); - let rpc_addr = SocketAddr::new( - ip_addr, - solana_net_utils::find_available_port_in_range(ip_addr, (10000, 65535)).unwrap(), - ); + let (rpc_port, _) = + solana_net_utils::bind_common_in_range(ip_addr, (10000, 65535)).unwrap(); + let rpc_addr = SocketAddr::new(ip_addr, rpc_port); let bank_forks = BankForks::new_rw_arc(bank); let ledger_path = get_tmp_ledger_path_auto_delete!(); let blockstore = Arc::new(Blockstore::open(ledger_path.path()).unwrap()); diff --git a/validator/src/main.rs b/validator/src/main.rs index c8494221d614b0..0e5cbeafd3f84a 100644 --- a/validator/src/main.rs +++ b/validator/src/main.rs @@ -1821,12 +1821,12 @@ pub fn main() { let gossip_addr = SocketAddr::new( gossip_host, value_t!(matches, "gossip_port", u16).unwrap_or_else(|_| { - solana_net_utils::find_available_port_in_range(bind_address, (0, 1)).unwrap_or_else( - |err| { + let (gossip_port, _) = solana_net_utils::bind_common_in_range(bind_address, (0, 1)) + .unwrap_or_else(|err| { eprintln!("Unable to find an available gossip port: {err}"); exit(1); - }, - ) + }); + gossip_port }), ); From a96a9c81862e20a83e0c73ba79ecbca25a9bdff5 Mon Sep 17 00:00:00 2001 From: Trent Nelson Date: Sat, 6 Apr 2024 00:03:37 -0600 Subject: [PATCH 2/3] net-utils: make `PortRange` a `Range` --- bench-streamer/src/main.rs | 2 +- gossip/src/cluster_info.rs | 123 +++++++++++++++++++------------------ gossip/src/main.rs | 2 +- net-utils/src/lib.rs | 53 ++++++++-------- rpc/src/rpc_service.rs | 3 +- test-validator/src/lib.rs | 4 +- validator/src/cli.rs | 15 +++-- validator/src/main.rs | 2 +- 8 files changed, 103 insertions(+), 101 deletions(-) diff --git a/bench-streamer/src/main.rs b/bench-streamer/src/main.rs index de300345ebad42..a0b0747b0ea774 100644 --- a/bench-streamer/src/main.rs +++ b/bench-streamer/src/main.rs @@ -96,7 +96,7 @@ fn main() -> Result<()> { let recycler = PacketBatchRecycler::default(); let (_port, read_sockets) = solana_net_utils::multi_bind_in_range( ip_addr, - (port, port + num_sockets as u16), + port..port + num_sockets as u16, num_sockets, ) .unwrap(); diff --git a/gossip/src/cluster_info.rs b/gossip/src/cluster_info.rs index 06f2876ef5e3b6..762b2e59e5f4a8 100644 --- a/gossip/src/cluster_info.rs +++ b/gossip/src/cluster_info.rs @@ -2809,22 +2809,25 @@ impl Node { let localhost_ip_addr = IpAddr::V4(Ipv4Addr::LOCALHOST); let localhost_bind_addr = format!("{localhost_ip_addr:?}:0"); let unspecified_bind_addr = format!("{:?}:0", IpAddr::V4(Ipv4Addr::UNSPECIFIED)); - let port_range = (1024, 65535); + let port_range = 1024..65535; let ((_tpu_port, tpu), (_tpu_quic_port, tpu_quic)) = - bind_two_in_range_with_offset(localhost_ip_addr, port_range, QUIC_PORT_OFFSET).unwrap(); + bind_two_in_range_with_offset(localhost_ip_addr, port_range.clone(), QUIC_PORT_OFFSET) + .unwrap(); let (gossip_port, (gossip, ip_echo)) = - bind_common_in_range(localhost_ip_addr, port_range).unwrap(); + bind_common_in_range(localhost_ip_addr, port_range.clone()).unwrap(); let gossip_addr = SocketAddr::new(localhost_ip_addr, gossip_port); let tvu = UdpSocket::bind(&localhost_bind_addr).unwrap(); let tvu_quic = UdpSocket::bind(&localhost_bind_addr).unwrap(); let ((_tpu_forwards_port, tpu_forwards), (_tpu_forwards_quic_port, tpu_forwards_quic)) = - bind_two_in_range_with_offset(localhost_ip_addr, port_range, QUIC_PORT_OFFSET).unwrap(); + bind_two_in_range_with_offset(localhost_ip_addr, port_range.clone(), QUIC_PORT_OFFSET) + .unwrap(); let tpu_vote = UdpSocket::bind(&localhost_bind_addr).unwrap(); let repair = UdpSocket::bind(&localhost_bind_addr).unwrap(); - let (rpc_port, _) = bind_common_in_range(localhost_ip_addr, port_range).unwrap(); + let (rpc_port, _) = bind_common_in_range(localhost_ip_addr, port_range.clone()).unwrap(); let rpc_addr = SocketAddr::new(localhost_ip_addr, rpc_port); - let (rpc_pubsub_port, _) = bind_common_in_range(localhost_ip_addr, port_range).unwrap(); + let (rpc_pubsub_port, _) = + bind_common_in_range(localhost_ip_addr, port_range.clone()).unwrap(); let rpc_pubsub_addr = SocketAddr::new(localhost_ip_addr, rpc_pubsub_port); let broadcast = vec![UdpSocket::bind(&unspecified_bind_addr).unwrap()]; let retransmit_socket = UdpSocket::bind(&unspecified_bind_addr).unwrap(); @@ -2916,23 +2919,26 @@ impl Node { bind_ip_addr: IpAddr, ) -> Self { let (gossip_port, (gossip, ip_echo)) = - Self::get_gossip_port(gossip_addr, port_range, bind_ip_addr); - let (tvu_port, tvu) = Self::bind(bind_ip_addr, port_range); - let (tvu_quic_port, tvu_quic) = Self::bind(bind_ip_addr, port_range); + Self::get_gossip_port(gossip_addr, port_range.clone(), bind_ip_addr); + let (tvu_port, tvu) = Self::bind(bind_ip_addr, port_range.clone()); + let (tvu_quic_port, tvu_quic) = Self::bind(bind_ip_addr, port_range.clone()); let ((tpu_port, tpu), (_tpu_quic_port, tpu_quic)) = - bind_two_in_range_with_offset(bind_ip_addr, port_range, QUIC_PORT_OFFSET).unwrap(); + bind_two_in_range_with_offset(bind_ip_addr, port_range.clone(), QUIC_PORT_OFFSET) + .unwrap(); let ((tpu_forwards_port, tpu_forwards), (_tpu_forwards_quic_port, tpu_forwards_quic)) = - bind_two_in_range_with_offset(bind_ip_addr, port_range, QUIC_PORT_OFFSET).unwrap(); - let (tpu_vote_port, tpu_vote) = Self::bind(bind_ip_addr, port_range); - let (_, retransmit_socket) = Self::bind(bind_ip_addr, port_range); - let (_, repair) = Self::bind(bind_ip_addr, port_range); - let (serve_repair_port, serve_repair) = Self::bind(bind_ip_addr, port_range); - let (serve_repair_quic_port, serve_repair_quic) = Self::bind(bind_ip_addr, port_range); - let (_, broadcast) = Self::bind(bind_ip_addr, port_range); - let (_, ancestor_hashes_requests) = Self::bind(bind_ip_addr, port_range); - - let (rpc_port, _) = bind_common_in_range(bind_ip_addr, port_range).unwrap(); - let (rpc_pubsub_port, _) = bind_common_in_range(bind_ip_addr, port_range).unwrap(); + bind_two_in_range_with_offset(bind_ip_addr, port_range.clone(), QUIC_PORT_OFFSET) + .unwrap(); + let (tpu_vote_port, tpu_vote) = Self::bind(bind_ip_addr, port_range.clone()); + let (_, retransmit_socket) = Self::bind(bind_ip_addr, port_range.clone()); + let (_, repair) = Self::bind(bind_ip_addr, port_range.clone()); + let (serve_repair_port, serve_repair) = Self::bind(bind_ip_addr, port_range.clone()); + let (serve_repair_quic_port, serve_repair_quic) = + Self::bind(bind_ip_addr, port_range.clone()); + let (_, broadcast) = Self::bind(bind_ip_addr, port_range.clone()); + let (_, ancestor_hashes_requests) = Self::bind(bind_ip_addr, port_range.clone()); + + let (rpc_port, _) = bind_common_in_range(bind_ip_addr, port_range.clone()).unwrap(); + let (rpc_pubsub_port, _) = bind_common_in_range(bind_ip_addr, port_range.clone()).unwrap(); let addr = gossip_addr.ip(); let mut info = ContactInfo::new( @@ -2996,44 +3002,43 @@ impl Node { } = config; let (gossip_port, (gossip, ip_echo)) = - Self::get_gossip_port(&gossip_addr, port_range, bind_ip_addr); + Self::get_gossip_port(&gossip_addr, port_range.clone(), bind_ip_addr); let (tvu_port, tvu_sockets) = - multi_bind_in_range(bind_ip_addr, port_range, 8).expect("tvu multi_bind"); - let (tvu_quic_port, tvu_quic) = Self::bind(bind_ip_addr, port_range); + multi_bind_in_range(bind_ip_addr, port_range.clone(), 8).expect("tvu multi_bind"); + let (tvu_quic_port, tvu_quic) = Self::bind(bind_ip_addr, port_range.clone()); let (tpu_port, tpu_sockets) = - multi_bind_in_range(bind_ip_addr, port_range, 32).expect("tpu multi_bind"); + multi_bind_in_range(bind_ip_addr, port_range.clone(), 32).expect("tpu multi_bind"); let (_tpu_port_quic, tpu_quic) = Self::bind( bind_ip_addr, - (tpu_port + QUIC_PORT_OFFSET, tpu_port + QUIC_PORT_OFFSET + 1), + tpu_port + QUIC_PORT_OFFSET..tpu_port + QUIC_PORT_OFFSET + 1, ); let (tpu_forwards_port, tpu_forwards_sockets) = - multi_bind_in_range(bind_ip_addr, port_range, 8).expect("tpu_forwards multi_bind"); + multi_bind_in_range(bind_ip_addr, port_range.clone(), 8) + .expect("tpu_forwards multi_bind"); let (_tpu_forwards_port_quic, tpu_forwards_quic) = Self::bind( bind_ip_addr, - ( - tpu_forwards_port + QUIC_PORT_OFFSET, - tpu_forwards_port + QUIC_PORT_OFFSET + 1, - ), + tpu_forwards_port + QUIC_PORT_OFFSET..tpu_forwards_port + QUIC_PORT_OFFSET + 1, ); let (tpu_vote_port, tpu_vote_sockets) = - multi_bind_in_range(bind_ip_addr, port_range, 1).expect("tpu_vote multi_bind"); + multi_bind_in_range(bind_ip_addr, port_range.clone(), 1).expect("tpu_vote multi_bind"); - let (_, retransmit_sockets) = - multi_bind_in_range(bind_ip_addr, port_range, 8).expect("retransmit multi_bind"); + let (_, retransmit_sockets) = multi_bind_in_range(bind_ip_addr, port_range.clone(), 8) + .expect("retransmit multi_bind"); - let (_, repair) = Self::bind(bind_ip_addr, port_range); - let (serve_repair_port, serve_repair) = Self::bind(bind_ip_addr, port_range); - let (serve_repair_quic_port, serve_repair_quic) = Self::bind(bind_ip_addr, port_range); + let (_, repair) = Self::bind(bind_ip_addr, port_range.clone()); + let (serve_repair_port, serve_repair) = Self::bind(bind_ip_addr, port_range.clone()); + let (serve_repair_quic_port, serve_repair_quic) = + Self::bind(bind_ip_addr, port_range.clone()); let (_, broadcast) = - multi_bind_in_range(bind_ip_addr, port_range, 4).expect("broadcast multi_bind"); + multi_bind_in_range(bind_ip_addr, port_range.clone(), 4).expect("broadcast multi_bind"); - let (_, ancestor_hashes_requests) = Self::bind(bind_ip_addr, port_range); + let (_, ancestor_hashes_requests) = Self::bind(bind_ip_addr, port_range.clone()); let mut info = ContactInfo::new( *pubkey, @@ -3570,33 +3575,27 @@ mod tests { assert!(gossip_crds.get::<&CrdsValue>(&label).is_some()); } - fn assert_in_range(x: u16, range: (u16, u16)) { - assert!(x >= range.0); - assert!(x < range.1); - } - - fn check_sockets(sockets: &[UdpSocket], ip: IpAddr, range: (u16, u16)) { + fn check_sockets(sockets: &[UdpSocket], ip: IpAddr) { assert!(sockets.len() > 1); let port = sockets[0].local_addr().unwrap().port(); for socket in sockets.iter() { - check_socket(socket, ip, range); + check_socket(socket, ip); assert_eq!(socket.local_addr().unwrap().port(), port); } } - fn check_socket(socket: &UdpSocket, ip: IpAddr, range: (u16, u16)) { + fn check_socket(socket: &UdpSocket, ip: IpAddr) { let local_addr = socket.local_addr().unwrap(); assert_eq!(local_addr.ip(), ip); - assert_in_range(local_addr.port(), range); } - fn check_node_sockets(node: &Node, ip: IpAddr, range: (u16, u16)) { - check_socket(&node.sockets.gossip, ip, range); - check_socket(&node.sockets.repair, ip, range); - check_socket(&node.sockets.tvu_quic, ip, range); + fn check_node_sockets(node: &Node, ip: IpAddr) { + check_socket(&node.sockets.gossip, ip); + check_socket(&node.sockets.repair, ip); + check_socket(&node.sockets.tvu_quic, ip); - check_sockets(&node.sockets.tvu, ip, range); - check_sockets(&node.sockets.tpu, ip, range); + check_sockets(&node.sockets.tvu, ip); + check_sockets(&node.sockets.tpu, ip); } #[test] @@ -3612,19 +3611,21 @@ mod tests { let node = Node::new_with_external_ip(&solana_sdk::pubkey::new_rand(), config); - check_node_sockets(&node, IpAddr::V4(ip), VALIDATOR_PORT_RANGE); + check_node_sockets(&node, IpAddr::V4(ip)); } #[test] fn new_with_external_ip_test_gossip() { // Can't use VALIDATOR_PORT_RANGE because if this test runs in parallel with others, the // port returned by `bind_in_range()` might be snatched up before `Node::new_with_external_ip()` runs - let port_range = ( - VALIDATOR_PORT_RANGE.1 + MINIMUM_VALIDATOR_PORT_RANGE_WIDTH, - VALIDATOR_PORT_RANGE.1 + (2 * MINIMUM_VALIDATOR_PORT_RANGE_WIDTH), - ); + let new_start = VALIDATOR_PORT_RANGE.end + MINIMUM_VALIDATOR_PORT_RANGE_WIDTH; + let new_end = VALIDATOR_PORT_RANGE.end + (2 * MINIMUM_VALIDATOR_PORT_RANGE_WIDTH); + let port_range = new_start..new_end; + let ip = IpAddr::V4(Ipv4Addr::LOCALHOST); - let port = bind_in_range(ip, port_range).expect("Failed to bind").0; + let port = bind_in_range(ip, port_range.clone()) + .expect("Failed to bind") + .0; let config = NodeConfig { gossip_addr: socketaddr!(Ipv4Addr::LOCALHOST, port), port_range, @@ -3635,7 +3636,7 @@ mod tests { let node = Node::new_with_external_ip(&solana_sdk::pubkey::new_rand(), config); - check_node_sockets(&node, ip, port_range); + check_node_sockets(&node, ip); assert_eq!(node.sockets.gossip.local_addr().unwrap().port(), port); } diff --git a/gossip/src/main.rs b/gossip/src/main.rs index 05d46bfae865d7..acc142338204b1 100644 --- a/gossip/src/main.rs +++ b/gossip/src/main.rs @@ -237,7 +237,7 @@ fn process_spy(matches: &ArgMatches, socket_addr_space: SocketAddrSpace) -> std: gossip_host, value_t!(matches, "gossip_port", u16).unwrap_or_else(|_| { let (gossip_port, _) = - solana_net_utils::bind_common_in_range(IpAddr::V4(Ipv4Addr::UNSPECIFIED), (0, 1)) + solana_net_utils::bind_common_in_range(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0..1) .expect("unable to find an available gossip port"); gossip_port }), diff --git a/net-utils/src/lib.rs b/net-utils/src/lib.rs index 1154246f2fd6d5..9f81c66773aebf 100644 --- a/net-utils/src/lib.rs +++ b/net-utils/src/lib.rs @@ -28,9 +28,9 @@ pub struct UdpSocketPair { pub sender: UdpSocket, // Locally bound socket to send via public address } -pub type PortRange = (u16, u16); +pub type PortRange = std::ops::Range; -pub const VALIDATOR_PORT_RANGE: PortRange = (8000, 10_000); +pub const VALIDATOR_PORT_RANGE: PortRange = 8000..10000; pub const MINIMUM_VALIDATOR_PORT_RANGE_WIDTH: u16 = 14; // VALIDATOR_PORT_RANGE must be at least this wide pub(crate) const HEADER_LENGTH: usize = 4; @@ -339,7 +339,7 @@ pub fn parse_port_range(port_range: &str) -> Option { if end_port < start_port { return None; } - Some((start_port, end_port)) + Some(start_port..end_port) } pub fn parse_host(host: &str) -> Result { @@ -416,7 +416,7 @@ pub fn bind_common_in_range( ip_addr: IpAddr, range: PortRange, ) -> io::Result<(u16, (UdpSocket, TcpListener))> { - for port in range.0..range.1 { + for port in range.clone() { if let Ok((sock, listener)) = bind_common(ip_addr, port, false) { return Result::Ok((sock.local_addr().unwrap().port(), (sock, listener))); } @@ -431,7 +431,7 @@ pub fn bind_common_in_range( pub fn bind_in_range(ip_addr: IpAddr, range: PortRange) -> io::Result<(u16, UdpSocket)> { let sock = udp_socket(false)?; - for port in range.0..range.1 { + for port in range.clone() { let addr = SocketAddr::new(ip_addr, port); if sock.bind(&SockAddr::from(addr)).is_ok() { @@ -479,7 +479,7 @@ pub fn multi_bind_in_range( let mut error = None; for _ in 0..NUM_TRIES { port = { - let (port, _) = bind_in_range(ip_addr, range)?; + let (port, _) = bind_in_range(ip_addr, range.clone())?; port }; // drop the probe, port should be available... briefly. @@ -531,15 +531,15 @@ pub fn bind_two_in_range_with_offset( range: PortRange, offset: u16, ) -> io::Result<((u16, UdpSocket), (u16, UdpSocket))> { - if range.1.saturating_sub(range.0) < offset { + if range.len() < usize::from(offset) { return Err(io::Error::new( io::ErrorKind::Other, "range too small to find two ports with the correct offset".to_string(), )); } - for port in range.0..range.1 { + for port in range.clone() { if let Ok(first_bind) = bind_to(ip_addr, port, false) { - if range.1.saturating_sub(port) >= offset { + if range.len() >= usize::from(offset) { if let Ok(second_bind) = bind_to(ip_addr, port + offset, false) { return Ok(( (first_bind.local_addr().unwrap().port(), first_bind), @@ -628,7 +628,7 @@ mod tests { fn test_parse_port_range() { assert_eq!(parse_port_range("garbage"), None); assert_eq!(parse_port_range("1-"), None); - assert_eq!(parse_port_range("1-2"), Some((1, 2))); + assert_eq!(parse_port_range("1-2"), Some(1..2)); assert_eq!(parse_port_range("1-2-3"), None); assert_eq!(parse_port_range("2-1"), None); } @@ -658,7 +658,7 @@ mod tests { #[test] fn test_bind() { let ip_addr = IpAddr::V4(Ipv4Addr::UNSPECIFIED); - assert_eq!(bind_in_range(ip_addr, (2000, 2001)).unwrap().0, 2000); + assert_eq!(bind_in_range(ip_addr, 2000..2001).unwrap().0, 2000); let ip_addr = IpAddr::V4(Ipv4Addr::UNSPECIFIED); let x = bind_to(ip_addr, 2002, true).unwrap(); let y = bind_to(ip_addr, 2002, true).unwrap(); @@ -667,9 +667,9 @@ mod tests { y.local_addr().unwrap().port() ); bind_to(ip_addr, 2002, false).unwrap_err(); - bind_in_range(ip_addr, (2002, 2003)).unwrap_err(); + bind_in_range(ip_addr, 2002..2003).unwrap_err(); - let (port, v) = multi_bind_in_range(ip_addr, (2010, 2110), 10).unwrap(); + let (port, v) = multi_bind_in_range(ip_addr, 2010..2110, 10).unwrap(); for sock in &v { assert_eq!(port, sock.local_addr().unwrap().port()); } @@ -689,17 +689,16 @@ mod tests { #[test] fn test_bind_in_range_nil() { let ip_addr = IpAddr::V4(Ipv4Addr::UNSPECIFIED); - bind_in_range(ip_addr, (2000, 2000)).unwrap_err(); - bind_in_range(ip_addr, (2000, 1999)).unwrap_err(); + bind_in_range(ip_addr, 2000..2000).unwrap_err(); } #[test] fn test_bind_common_in_range() { let ip_addr = IpAddr::V4(Ipv4Addr::UNSPECIFIED); - let (port, _sockets) = bind_common_in_range(ip_addr, (3100, 3150)).unwrap(); + let (port, _sockets) = bind_common_in_range(ip_addr, 3100..3150).unwrap(); assert!((3100..3150).contains(&port)); - bind_common_in_range(ip_addr, (port, port + 1)).unwrap_err(); + bind_common_in_range(ip_addr, port..port + 1).unwrap_err(); } #[test] @@ -707,7 +706,7 @@ mod tests { solana_logger::setup(); let ip_addr = IpAddr::V4(Ipv4Addr::UNSPECIFIED); let (_server_port, (server_udp_socket, server_tcp_listener)) = - bind_common_in_range(ip_addr, (3200, 3250)).unwrap(); + bind_common_in_range(ip_addr, 3200..3250).unwrap(); let _runtime = ip_echo_server( server_tcp_listener, @@ -729,9 +728,9 @@ mod tests { solana_logger::setup(); let ip_addr = IpAddr::V4(Ipv4Addr::UNSPECIFIED); let (_server_port, (server_udp_socket, server_tcp_listener)) = - bind_common_in_range(ip_addr, (3200, 3250)).unwrap(); + bind_common_in_range(ip_addr, 3200..3250).unwrap(); let (client_port, (client_udp_socket, client_tcp_listener)) = - bind_common_in_range(ip_addr, (3200, 3250)).unwrap(); + bind_common_in_range(ip_addr, 3200..3250).unwrap(); let _runtime = ip_echo_server( server_tcp_listener, @@ -757,14 +756,14 @@ mod tests { solana_logger::setup(); let ip_addr = IpAddr::V4(Ipv4Addr::UNSPECIFIED); let (_server_port, (server_udp_socket, _server_tcp_listener)) = - bind_common_in_range(ip_addr, (3200, 3250)).unwrap(); + bind_common_in_range(ip_addr, 3200..3250).unwrap(); // make the socket unreachable by not running the ip echo server! let server_ip_echo_addr = server_udp_socket.local_addr().unwrap(); let (correct_client_port, (_client_udp_socket, client_tcp_listener)) = - bind_common_in_range(ip_addr, (3200, 3250)).unwrap(); + bind_common_in_range(ip_addr, 3200..3250).unwrap(); assert!(!do_verify_reachable_ports( &server_ip_echo_addr, @@ -780,14 +779,14 @@ mod tests { solana_logger::setup(); let ip_addr = IpAddr::V4(Ipv4Addr::UNSPECIFIED); let (_server_port, (server_udp_socket, _server_tcp_listener)) = - bind_common_in_range(ip_addr, (3200, 3250)).unwrap(); + bind_common_in_range(ip_addr, 3200..3250).unwrap(); // make the socket unreachable by not running the ip echo server! let server_ip_echo_addr = server_udp_socket.local_addr().unwrap(); let (_correct_client_port, (client_udp_socket, _client_tcp_listener)) = - bind_common_in_range(ip_addr, (3200, 3250)).unwrap(); + bind_common_in_range(ip_addr, 3200..3250).unwrap(); assert!(!do_verify_reachable_ports( &server_ip_echo_addr, @@ -804,16 +803,16 @@ mod tests { let ip_addr = IpAddr::V4(Ipv4Addr::UNSPECIFIED); let offset = 6; if let Ok(((port1, _), (port2, _))) = - bind_two_in_range_with_offset(ip_addr, (1024, 65535), offset) + bind_two_in_range_with_offset(ip_addr, 1024..65535, offset) { assert!(port2 == port1 + offset); } let offset = 42; if let Ok(((port1, _), (port2, _))) = - bind_two_in_range_with_offset(ip_addr, (1024, 65535), offset) + bind_two_in_range_with_offset(ip_addr, 1024..65535, offset) { assert!(port2 == port1 + offset); } - assert!(bind_two_in_range_with_offset(ip_addr, (1024, 1044), offset).is_err()); + assert!(bind_two_in_range_with_offset(ip_addr, 1024..1044, offset).is_err()); } } diff --git a/rpc/src/rpc_service.rs b/rpc/src/rpc_service.rs index 74b935937d93aa..d0e440a8f9135d 100644 --- a/rpc/src/rpc_service.rs +++ b/rpc/src/rpc_service.rs @@ -624,8 +624,7 @@ mod tests { let bank = Bank::new_for_tests(&genesis_config); let cluster_info = Arc::new(new_test_cluster_info()); let ip_addr = IpAddr::V4(Ipv4Addr::UNSPECIFIED); - let (rpc_port, _) = - solana_net_utils::bind_common_in_range(ip_addr, (10000, 65535)).unwrap(); + let (rpc_port, _) = solana_net_utils::bind_common_in_range(ip_addr, 10000..65535).unwrap(); let rpc_addr = SocketAddr::new(ip_addr, rpc_port); let bank_forks = BankForks::new_rw_arc(bank); let ledger_path = get_tmp_ledger_path_auto_delete!(); diff --git a/test-validator/src/lib.rs b/test-validator/src/lib.rs index 8b32762a203d02..860b96db90b52a 100644 --- a/test-validator/src/lib.rs +++ b/test-validator/src/lib.rs @@ -107,7 +107,7 @@ impl Default for TestValidatorNodeConfig { const MAX_PORT_RANGE: u16 = 65535; let bind_ip_addr = IpAddr::V4(Ipv4Addr::UNSPECIFIED); - let port_range = (MIN_PORT_RANGE, MAX_PORT_RANGE); + let port_range = MIN_PORT_RANGE..MAX_PORT_RANGE; Self { gossip_addr: socketaddr!(Ipv4Addr::LOCALHOST, 0), @@ -950,7 +950,7 @@ impl TestValidator { let mut node = Node::new_single_bind( &validator_identity.pubkey(), &config.node_config.gossip_addr, - config.node_config.port_range, + config.node_config.port_range.clone(), config.node_config.bind_ip_addr, ); if let Some((rpc, rpc_pubsub)) = config.rpc_ports { diff --git a/validator/src/cli.rs b/validator/src/cli.rs index 7fc525477ef41e..eb7c3d6ddfa66c 100644 --- a/validator/src/cli.rs +++ b/validator/src/cli.rs @@ -2211,7 +2211,10 @@ impl DefaultArgs { DefaultArgs { bind_address: "0.0.0.0".to_string(), ledger_path: "ledger".to_string(), - dynamic_port_range: format!("{}-{}", VALIDATOR_PORT_RANGE.0, VALIDATOR_PORT_RANGE.1), + dynamic_port_range: format!( + "{}-{}", + VALIDATOR_PORT_RANGE.start, VALIDATOR_PORT_RANGE.end + ), maximum_local_snapshot_age: "2500".to_string(), genesis_archive_unpacked_size: MAX_GENESIS_ARCHIVE_UNPACKED_SIZE.to_string(), rpc_max_multiple_accounts: MAX_MULTIPLE_ACCOUNTS.to_string(), @@ -2302,14 +2305,14 @@ pub fn port_validator(port: String) -> Result<(), String> { } pub fn port_range_validator(port_range: String) -> Result<(), String> { - if let Some((start, end)) = solana_net_utils::parse_port_range(&port_range) { - if end - start < MINIMUM_VALIDATOR_PORT_RANGE_WIDTH { + if let Some(port_range) = solana_net_utils::parse_port_range(&port_range) { + if port_range.len() < usize::from(MINIMUM_VALIDATOR_PORT_RANGE_WIDTH) { Err(format!( "Port range is too small. Try --dynamic-port-range {}-{}", - start, - start + MINIMUM_VALIDATOR_PORT_RANGE_WIDTH + port_range.start, + port_range.start + MINIMUM_VALIDATOR_PORT_RANGE_WIDTH )) - } else if end.checked_add(QUIC_PORT_OFFSET).is_none() { + } else if port_range.end.checked_add(QUIC_PORT_OFFSET).is_none() { Err("Invalid dynamic_port_range.".to_string()) } else { Ok(()) diff --git a/validator/src/main.rs b/validator/src/main.rs index 0e5cbeafd3f84a..cd9c4151225d28 100644 --- a/validator/src/main.rs +++ b/validator/src/main.rs @@ -1821,7 +1821,7 @@ pub fn main() { let gossip_addr = SocketAddr::new( gossip_host, value_t!(matches, "gossip_port", u16).unwrap_or_else(|_| { - let (gossip_port, _) = solana_net_utils::bind_common_in_range(bind_address, (0, 1)) + let (gossip_port, _) = solana_net_utils::bind_common_in_range(bind_address, 0..1) .unwrap_or_else(|err| { eprintln!("Unable to find an available gossip port: {err}"); exit(1); From 359caf3b2727ea69a719d16c58af3d7d38476353 Mon Sep 17 00:00:00 2001 From: Trent Nelson Date: Sat, 6 Apr 2024 02:58:23 -0600 Subject: [PATCH 3/3] net-utils: consume ports from `port_range` as they're allocated --- bench-streamer/src/main.rs | 9 +- gossip/src/cluster_info.rs | 105 ++++++++++----------- gossip/src/main.rs | 8 +- net-utils/src/lib.rs | 55 ++++++----- quic-client/src/nonblocking/quic_client.rs | 2 +- rpc/src/rpc_service.rs | 3 +- validator/src/main.rs | 12 ++- 7 files changed, 97 insertions(+), 97 deletions(-) diff --git a/bench-streamer/src/main.rs b/bench-streamer/src/main.rs index a0b0747b0ea774..ed0cb9a88187ad 100644 --- a/bench-streamer/src/main.rs +++ b/bench-streamer/src/main.rs @@ -94,12 +94,9 @@ fn main() -> Result<()> { let mut read_channels = Vec::new(); let mut read_threads = Vec::new(); let recycler = PacketBatchRecycler::default(); - let (_port, read_sockets) = solana_net_utils::multi_bind_in_range( - ip_addr, - port..port + num_sockets as u16, - num_sockets, - ) - .unwrap(); + let mut port_range = port..port + num_sockets as u16; + let (_port, read_sockets) = + solana_net_utils::multi_bind_in_range(ip_addr, &mut port_range, num_sockets).unwrap(); let stats = Arc::new(StreamerReceiveStats::new("bench-streamer-test")); for read in read_sockets { read.set_read_timeout(Some(Duration::new(1, 0))).unwrap(); diff --git a/gossip/src/cluster_info.rs b/gossip/src/cluster_info.rs index 762b2e59e5f4a8..f21742cd928b1b 100644 --- a/gossip/src/cluster_info.rs +++ b/gossip/src/cluster_info.rs @@ -2729,8 +2729,9 @@ impl ClusterInfo { shred_version: u16, ) -> (ContactInfo, UdpSocket, Option) { let bind_ip_addr = IpAddr::V4(Ipv4Addr::UNSPECIFIED); + let mut port_range = VALIDATOR_PORT_RANGE.clone(); let (port, (gossip_socket, ip_echo)) = - Node::get_gossip_port(gossip_addr, VALIDATOR_PORT_RANGE, bind_ip_addr); + Node::get_gossip_port(gossip_addr, &mut port_range, bind_ip_addr); let contact_info = Self::gossip_contact_info(id, SocketAddr::new(gossip_addr.ip(), port), shred_version); @@ -2743,7 +2744,8 @@ impl ClusterInfo { shred_version: u16, ) -> (ContactInfo, UdpSocket, Option) { let bind_ip_addr = IpAddr::V4(Ipv4Addr::UNSPECIFIED); - let (_, gossip_socket) = bind_in_range(bind_ip_addr, VALIDATOR_PORT_RANGE).unwrap(); + let mut port_range = VALIDATOR_PORT_RANGE.clone(); + let (_, gossip_socket) = bind_in_range(bind_ip_addr, &mut port_range).unwrap(); let contact_info = Self::gossip_contact_info(id, socketaddr_any!(), shred_version); (contact_info, gossip_socket, None) @@ -2809,25 +2811,25 @@ impl Node { let localhost_ip_addr = IpAddr::V4(Ipv4Addr::LOCALHOST); let localhost_bind_addr = format!("{localhost_ip_addr:?}:0"); let unspecified_bind_addr = format!("{:?}:0", IpAddr::V4(Ipv4Addr::UNSPECIFIED)); - let port_range = 1024..65535; + let mut port_range = 1024..65535; let ((_tpu_port, tpu), (_tpu_quic_port, tpu_quic)) = - bind_two_in_range_with_offset(localhost_ip_addr, port_range.clone(), QUIC_PORT_OFFSET) + bind_two_in_range_with_offset(localhost_ip_addr, &mut port_range, QUIC_PORT_OFFSET) .unwrap(); let (gossip_port, (gossip, ip_echo)) = - bind_common_in_range(localhost_ip_addr, port_range.clone()).unwrap(); + bind_common_in_range(localhost_ip_addr, &mut port_range).unwrap(); let gossip_addr = SocketAddr::new(localhost_ip_addr, gossip_port); let tvu = UdpSocket::bind(&localhost_bind_addr).unwrap(); let tvu_quic = UdpSocket::bind(&localhost_bind_addr).unwrap(); let ((_tpu_forwards_port, tpu_forwards), (_tpu_forwards_quic_port, tpu_forwards_quic)) = - bind_two_in_range_with_offset(localhost_ip_addr, port_range.clone(), QUIC_PORT_OFFSET) + bind_two_in_range_with_offset(localhost_ip_addr, &mut port_range, QUIC_PORT_OFFSET) .unwrap(); let tpu_vote = UdpSocket::bind(&localhost_bind_addr).unwrap(); let repair = UdpSocket::bind(&localhost_bind_addr).unwrap(); - let (rpc_port, _) = bind_common_in_range(localhost_ip_addr, port_range.clone()).unwrap(); + let (rpc_port, _) = bind_common_in_range(localhost_ip_addr, &mut port_range).unwrap(); let rpc_addr = SocketAddr::new(localhost_ip_addr, rpc_port); let (rpc_pubsub_port, _) = - bind_common_in_range(localhost_ip_addr, port_range.clone()).unwrap(); + bind_common_in_range(localhost_ip_addr, &mut port_range).unwrap(); let rpc_pubsub_addr = SocketAddr::new(localhost_ip_addr, rpc_pubsub_port); let broadcast = vec![UdpSocket::bind(&unspecified_bind_addr).unwrap()]; let retransmit_socket = UdpSocket::bind(&unspecified_bind_addr).unwrap(); @@ -2894,7 +2896,7 @@ impl Node { fn get_gossip_port( gossip_addr: &SocketAddr, - port_range: PortRange, + port_range: &mut impl ExactSizeIterator, bind_ip_addr: IpAddr, ) -> (u16, (UdpSocket, TcpListener)) { if gossip_addr.port() != 0 { @@ -2908,37 +2910,37 @@ impl Node { bind_common_in_range(bind_ip_addr, port_range).expect("Failed to bind") } } - fn bind(bind_ip_addr: IpAddr, port_range: PortRange) -> (u16, UdpSocket) { + fn bind( + bind_ip_addr: IpAddr, + port_range: &mut impl ExactSizeIterator, + ) -> (u16, UdpSocket) { bind_in_range(bind_ip_addr, port_range).expect("Failed to bind") } pub fn new_single_bind( pubkey: &Pubkey, gossip_addr: &SocketAddr, - port_range: PortRange, + mut port_range: PortRange, bind_ip_addr: IpAddr, ) -> Self { let (gossip_port, (gossip, ip_echo)) = - Self::get_gossip_port(gossip_addr, port_range.clone(), bind_ip_addr); - let (tvu_port, tvu) = Self::bind(bind_ip_addr, port_range.clone()); - let (tvu_quic_port, tvu_quic) = Self::bind(bind_ip_addr, port_range.clone()); + Self::get_gossip_port(gossip_addr, &mut port_range, bind_ip_addr); + let (tvu_port, tvu) = Self::bind(bind_ip_addr, &mut port_range); + let (tvu_quic_port, tvu_quic) = Self::bind(bind_ip_addr, &mut port_range); let ((tpu_port, tpu), (_tpu_quic_port, tpu_quic)) = - bind_two_in_range_with_offset(bind_ip_addr, port_range.clone(), QUIC_PORT_OFFSET) - .unwrap(); + bind_two_in_range_with_offset(bind_ip_addr, &mut port_range, QUIC_PORT_OFFSET).unwrap(); let ((tpu_forwards_port, tpu_forwards), (_tpu_forwards_quic_port, tpu_forwards_quic)) = - bind_two_in_range_with_offset(bind_ip_addr, port_range.clone(), QUIC_PORT_OFFSET) - .unwrap(); - let (tpu_vote_port, tpu_vote) = Self::bind(bind_ip_addr, port_range.clone()); - let (_, retransmit_socket) = Self::bind(bind_ip_addr, port_range.clone()); - let (_, repair) = Self::bind(bind_ip_addr, port_range.clone()); - let (serve_repair_port, serve_repair) = Self::bind(bind_ip_addr, port_range.clone()); - let (serve_repair_quic_port, serve_repair_quic) = - Self::bind(bind_ip_addr, port_range.clone()); - let (_, broadcast) = Self::bind(bind_ip_addr, port_range.clone()); - let (_, ancestor_hashes_requests) = Self::bind(bind_ip_addr, port_range.clone()); - - let (rpc_port, _) = bind_common_in_range(bind_ip_addr, port_range.clone()).unwrap(); - let (rpc_pubsub_port, _) = bind_common_in_range(bind_ip_addr, port_range.clone()).unwrap(); + bind_two_in_range_with_offset(bind_ip_addr, &mut port_range, QUIC_PORT_OFFSET).unwrap(); + let (tpu_vote_port, tpu_vote) = Self::bind(bind_ip_addr, &mut port_range); + let (_, retransmit_socket) = Self::bind(bind_ip_addr, &mut port_range); + let (_, repair) = Self::bind(bind_ip_addr, &mut port_range); + let (serve_repair_port, serve_repair) = Self::bind(bind_ip_addr, &mut port_range); + let (serve_repair_quic_port, serve_repair_quic) = Self::bind(bind_ip_addr, &mut port_range); + let (_, broadcast) = Self::bind(bind_ip_addr, &mut port_range); + let (_, ancestor_hashes_requests) = Self::bind(bind_ip_addr, &mut port_range); + + let (rpc_port, _) = bind_common_in_range(bind_ip_addr, &mut port_range).unwrap(); + let (rpc_pubsub_port, _) = bind_common_in_range(bind_ip_addr, &mut port_range).unwrap(); let addr = gossip_addr.ip(); let mut info = ContactInfo::new( @@ -2995,50 +2997,43 @@ impl Node { pub fn new_with_external_ip(pubkey: &Pubkey, config: NodeConfig) -> Node { let NodeConfig { gossip_addr, - port_range, + mut port_range, bind_ip_addr, public_tpu_addr, public_tpu_forwards_addr, } = config; let (gossip_port, (gossip, ip_echo)) = - Self::get_gossip_port(&gossip_addr, port_range.clone(), bind_ip_addr); + Self::get_gossip_port(&gossip_addr, &mut port_range, bind_ip_addr); let (tvu_port, tvu_sockets) = - multi_bind_in_range(bind_ip_addr, port_range.clone(), 8).expect("tvu multi_bind"); - let (tvu_quic_port, tvu_quic) = Self::bind(bind_ip_addr, port_range.clone()); + multi_bind_in_range(bind_ip_addr, &mut port_range, 8).expect("tvu multi_bind"); + let (tvu_quic_port, tvu_quic) = Self::bind(bind_ip_addr, &mut port_range); let (tpu_port, tpu_sockets) = - multi_bind_in_range(bind_ip_addr, port_range.clone(), 32).expect("tpu multi_bind"); + multi_bind_in_range(bind_ip_addr, &mut port_range, 32).expect("tpu multi_bind"); - let (_tpu_port_quic, tpu_quic) = Self::bind( - bind_ip_addr, - tpu_port + QUIC_PORT_OFFSET..tpu_port + QUIC_PORT_OFFSET + 1, - ); + let (_tpu_port_quic, tpu_quic) = Self::bind(bind_ip_addr, &mut port_range); let (tpu_forwards_port, tpu_forwards_sockets) = - multi_bind_in_range(bind_ip_addr, port_range.clone(), 8) - .expect("tpu_forwards multi_bind"); + multi_bind_in_range(bind_ip_addr, &mut port_range, 8).expect("tpu_forwards multi_bind"); - let (_tpu_forwards_port_quic, tpu_forwards_quic) = Self::bind( - bind_ip_addr, - tpu_forwards_port + QUIC_PORT_OFFSET..tpu_forwards_port + QUIC_PORT_OFFSET + 1, - ); + let (_tpu_forwards_port_quic, tpu_forwards_quic) = + Self::bind(bind_ip_addr, &mut port_range); let (tpu_vote_port, tpu_vote_sockets) = - multi_bind_in_range(bind_ip_addr, port_range.clone(), 1).expect("tpu_vote multi_bind"); + multi_bind_in_range(bind_ip_addr, &mut port_range, 1).expect("tpu_vote multi_bind"); - let (_, retransmit_sockets) = multi_bind_in_range(bind_ip_addr, port_range.clone(), 8) - .expect("retransmit multi_bind"); + let (_, retransmit_sockets) = + multi_bind_in_range(bind_ip_addr, &mut port_range, 8).expect("retransmit multi_bind"); - let (_, repair) = Self::bind(bind_ip_addr, port_range.clone()); - let (serve_repair_port, serve_repair) = Self::bind(bind_ip_addr, port_range.clone()); - let (serve_repair_quic_port, serve_repair_quic) = - Self::bind(bind_ip_addr, port_range.clone()); + let (_, repair) = Self::bind(bind_ip_addr, &mut port_range); + let (serve_repair_port, serve_repair) = Self::bind(bind_ip_addr, &mut port_range); + let (serve_repair_quic_port, serve_repair_quic) = Self::bind(bind_ip_addr, &mut port_range); let (_, broadcast) = - multi_bind_in_range(bind_ip_addr, port_range.clone(), 4).expect("broadcast multi_bind"); + multi_bind_in_range(bind_ip_addr, &mut port_range, 4).expect("broadcast multi_bind"); - let (_, ancestor_hashes_requests) = Self::bind(bind_ip_addr, port_range.clone()); + let (_, ancestor_hashes_requests) = Self::bind(bind_ip_addr, &mut port_range); let mut info = ContactInfo::new( *pubkey, @@ -3620,10 +3615,10 @@ mod tests { // port returned by `bind_in_range()` might be snatched up before `Node::new_with_external_ip()` runs let new_start = VALIDATOR_PORT_RANGE.end + MINIMUM_VALIDATOR_PORT_RANGE_WIDTH; let new_end = VALIDATOR_PORT_RANGE.end + (2 * MINIMUM_VALIDATOR_PORT_RANGE_WIDTH); - let port_range = new_start..new_end; + let mut port_range = new_start..new_end; let ip = IpAddr::V4(Ipv4Addr::LOCALHOST); - let port = bind_in_range(ip, port_range.clone()) + let port = bind_in_range(ip, &mut port_range) .expect("Failed to bind") .0; let config = NodeConfig { diff --git a/gossip/src/main.rs b/gossip/src/main.rs index acc142338204b1..cd20a79f059884 100644 --- a/gossip/src/main.rs +++ b/gossip/src/main.rs @@ -236,9 +236,11 @@ fn process_spy(matches: &ArgMatches, socket_addr_space: SocketAddrSpace) -> std: let gossip_addr = SocketAddr::new( gossip_host, value_t!(matches, "gossip_port", u16).unwrap_or_else(|_| { - let (gossip_port, _) = - solana_net_utils::bind_common_in_range(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0..1) - .expect("unable to find an available gossip port"); + let (gossip_port, _) = solana_net_utils::bind_common_in_range( + IpAddr::V4(Ipv4Addr::UNSPECIFIED), + &mut (0..1), + ) + .expect("unable to find an available gossip port"); gossip_port }), ); diff --git a/net-utils/src/lib.rs b/net-utils/src/lib.rs index 9f81c66773aebf..770b9180272a92 100644 --- a/net-utils/src/lib.rs +++ b/net-utils/src/lib.rs @@ -414,9 +414,9 @@ fn udp_socket(reuseaddr: bool) -> io::Result { // Find a port in the given range that is available for both TCP and UDP pub fn bind_common_in_range( ip_addr: IpAddr, - range: PortRange, + range: &mut impl ExactSizeIterator, ) -> io::Result<(u16, (UdpSocket, TcpListener))> { - for port in range.clone() { + for port in range.by_ref() { if let Ok((sock, listener)) = bind_common(ip_addr, port, false) { return Result::Ok((sock.local_addr().unwrap().port(), (sock, listener))); } @@ -424,14 +424,17 @@ pub fn bind_common_in_range( Err(io::Error::new( io::ErrorKind::Other, - format!("No available TCP/UDP ports in {range:?}"), + "No available TCP/UDP ports in range".to_string(), )) } -pub fn bind_in_range(ip_addr: IpAddr, range: PortRange) -> io::Result<(u16, UdpSocket)> { +pub fn bind_in_range( + ip_addr: IpAddr, + range: &mut impl ExactSizeIterator, +) -> io::Result<(u16, UdpSocket)> { let sock = udp_socket(false)?; - for port in range.clone() { + for port in range.by_ref() { let addr = SocketAddr::new(ip_addr, port); if sock.bind(&SockAddr::from(addr)).is_ok() { @@ -442,7 +445,7 @@ pub fn bind_in_range(ip_addr: IpAddr, range: PortRange) -> io::Result<(u16, UdpS Err(io::Error::new( io::ErrorKind::Other, - format!("No available UDP ports in {range:?}"), + "No available UDP ports in range".to_string(), )) } @@ -461,7 +464,7 @@ pub fn bind_with_any_port(ip_addr: IpAddr) -> io::Result { // binds many sockets to the same port in a range pub fn multi_bind_in_range( ip_addr: IpAddr, - range: PortRange, + range: &mut impl ExactSizeIterator, mut num: usize, ) -> io::Result<(u16, Vec)> { if cfg!(windows) && num != 1 { @@ -479,7 +482,7 @@ pub fn multi_bind_in_range( let mut error = None; for _ in 0..NUM_TRIES { port = { - let (port, _) = bind_in_range(ip_addr, range.clone())?; + let (port, _) = bind_in_range(ip_addr, range)?; port }; // drop the probe, port should be available... briefly. @@ -528,7 +531,7 @@ pub fn bind_common( pub fn bind_two_in_range_with_offset( ip_addr: IpAddr, - range: PortRange, + range: &mut impl ExactSizeIterator, offset: u16, ) -> io::Result<((u16, UdpSocket), (u16, UdpSocket))> { if range.len() < usize::from(offset) { @@ -537,7 +540,7 @@ pub fn bind_two_in_range_with_offset( "range too small to find two ports with the correct offset".to_string(), )); } - for port in range.clone() { + while let Some(port) = range.next() { if let Ok(first_bind) = bind_to(ip_addr, port, false) { if range.len() >= usize::from(offset) { if let Ok(second_bind) = bind_to(ip_addr, port + offset, false) { @@ -658,7 +661,7 @@ mod tests { #[test] fn test_bind() { let ip_addr = IpAddr::V4(Ipv4Addr::UNSPECIFIED); - assert_eq!(bind_in_range(ip_addr, 2000..2001).unwrap().0, 2000); + assert_eq!(bind_in_range(ip_addr, &mut (2000..2001)).unwrap().0, 2000); let ip_addr = IpAddr::V4(Ipv4Addr::UNSPECIFIED); let x = bind_to(ip_addr, 2002, true).unwrap(); let y = bind_to(ip_addr, 2002, true).unwrap(); @@ -667,9 +670,9 @@ mod tests { y.local_addr().unwrap().port() ); bind_to(ip_addr, 2002, false).unwrap_err(); - bind_in_range(ip_addr, 2002..2003).unwrap_err(); + bind_in_range(ip_addr, &mut (2002..2003)).unwrap_err(); - let (port, v) = multi_bind_in_range(ip_addr, 2010..2110, 10).unwrap(); + let (port, v) = multi_bind_in_range(ip_addr, &mut (2010..2110), 10).unwrap(); for sock in &v { assert_eq!(port, sock.local_addr().unwrap().port()); } @@ -689,16 +692,16 @@ mod tests { #[test] fn test_bind_in_range_nil() { let ip_addr = IpAddr::V4(Ipv4Addr::UNSPECIFIED); - bind_in_range(ip_addr, 2000..2000).unwrap_err(); + bind_in_range(ip_addr, &mut (2000..2000)).unwrap_err(); } #[test] fn test_bind_common_in_range() { let ip_addr = IpAddr::V4(Ipv4Addr::UNSPECIFIED); - let (port, _sockets) = bind_common_in_range(ip_addr, 3100..3150).unwrap(); + let (port, _sockets) = bind_common_in_range(ip_addr, &mut (3100..3150)).unwrap(); assert!((3100..3150).contains(&port)); - bind_common_in_range(ip_addr, port..port + 1).unwrap_err(); + bind_common_in_range(ip_addr, &mut (port..port + 1)).unwrap_err(); } #[test] @@ -706,7 +709,7 @@ mod tests { solana_logger::setup(); let ip_addr = IpAddr::V4(Ipv4Addr::UNSPECIFIED); let (_server_port, (server_udp_socket, server_tcp_listener)) = - bind_common_in_range(ip_addr, 3200..3250).unwrap(); + bind_common_in_range(ip_addr, &mut (3200..3250)).unwrap(); let _runtime = ip_echo_server( server_tcp_listener, @@ -728,9 +731,9 @@ mod tests { solana_logger::setup(); let ip_addr = IpAddr::V4(Ipv4Addr::UNSPECIFIED); let (_server_port, (server_udp_socket, server_tcp_listener)) = - bind_common_in_range(ip_addr, 3200..3250).unwrap(); + bind_common_in_range(ip_addr, &mut (3200..3250)).unwrap(); let (client_port, (client_udp_socket, client_tcp_listener)) = - bind_common_in_range(ip_addr, 3200..3250).unwrap(); + bind_common_in_range(ip_addr, &mut (3200..3250)).unwrap(); let _runtime = ip_echo_server( server_tcp_listener, @@ -756,14 +759,14 @@ mod tests { solana_logger::setup(); let ip_addr = IpAddr::V4(Ipv4Addr::UNSPECIFIED); let (_server_port, (server_udp_socket, _server_tcp_listener)) = - bind_common_in_range(ip_addr, 3200..3250).unwrap(); + bind_common_in_range(ip_addr, &mut (3200..3250)).unwrap(); // make the socket unreachable by not running the ip echo server! let server_ip_echo_addr = server_udp_socket.local_addr().unwrap(); let (correct_client_port, (_client_udp_socket, client_tcp_listener)) = - bind_common_in_range(ip_addr, 3200..3250).unwrap(); + bind_common_in_range(ip_addr, &mut (3200..3250)).unwrap(); assert!(!do_verify_reachable_ports( &server_ip_echo_addr, @@ -779,14 +782,14 @@ mod tests { solana_logger::setup(); let ip_addr = IpAddr::V4(Ipv4Addr::UNSPECIFIED); let (_server_port, (server_udp_socket, _server_tcp_listener)) = - bind_common_in_range(ip_addr, 3200..3250).unwrap(); + bind_common_in_range(ip_addr, &mut (3200..3250)).unwrap(); // make the socket unreachable by not running the ip echo server! let server_ip_echo_addr = server_udp_socket.local_addr().unwrap(); let (_correct_client_port, (client_udp_socket, _client_tcp_listener)) = - bind_common_in_range(ip_addr, 3200..3250).unwrap(); + bind_common_in_range(ip_addr, &mut (3200..3250)).unwrap(); assert!(!do_verify_reachable_ports( &server_ip_echo_addr, @@ -803,16 +806,16 @@ mod tests { let ip_addr = IpAddr::V4(Ipv4Addr::UNSPECIFIED); let offset = 6; if let Ok(((port1, _), (port2, _))) = - bind_two_in_range_with_offset(ip_addr, 1024..65535, offset) + bind_two_in_range_with_offset(ip_addr, &mut (1024..65535), offset) { assert!(port2 == port1 + offset); } let offset = 42; if let Ok(((port1, _), (port2, _))) = - bind_two_in_range_with_offset(ip_addr, 1024..65535, offset) + bind_two_in_range_with_offset(ip_addr, &mut (1024..65535), offset) { assert!(port2 == port1 + offset); } - assert!(bind_two_in_range_with_offset(ip_addr, 1024..1044, offset).is_err()); + assert!(bind_two_in_range_with_offset(ip_addr, &mut (1024..1044), offset).is_err()); } } diff --git a/quic-client/src/nonblocking/quic_client.rs b/quic-client/src/nonblocking/quic_client.rs index 5817a676f3b760..a0916cea080ded 100644 --- a/quic-client/src/nonblocking/quic_client.rs +++ b/quic-client/src/nonblocking/quic_client.rs @@ -106,7 +106,7 @@ impl QuicLazyInitializedEndpoint { } else { let client_socket = solana_net_utils::bind_in_range( IpAddr::V4(Ipv4Addr::UNSPECIFIED), - VALIDATOR_PORT_RANGE, + &mut VALIDATOR_PORT_RANGE.clone(), ) .expect("QuicLazyInitializedEndpoint::create_endpoint bind_in_range") .1; diff --git a/rpc/src/rpc_service.rs b/rpc/src/rpc_service.rs index d0e440a8f9135d..6240865517f54e 100644 --- a/rpc/src/rpc_service.rs +++ b/rpc/src/rpc_service.rs @@ -624,7 +624,8 @@ mod tests { let bank = Bank::new_for_tests(&genesis_config); let cluster_info = Arc::new(new_test_cluster_info()); let ip_addr = IpAddr::V4(Ipv4Addr::UNSPECIFIED); - let (rpc_port, _) = solana_net_utils::bind_common_in_range(ip_addr, 10000..65535).unwrap(); + let (rpc_port, _) = + solana_net_utils::bind_common_in_range(ip_addr, &mut (10000..65535)).unwrap(); let rpc_addr = SocketAddr::new(ip_addr, rpc_port); let bank_forks = BankForks::new_rw_arc(bank); let ledger_path = get_tmp_ledger_path_auto_delete!(); diff --git a/validator/src/main.rs b/validator/src/main.rs index cd9c4151225d28..2af1daf319baa8 100644 --- a/validator/src/main.rs +++ b/validator/src/main.rs @@ -1821,11 +1821,13 @@ pub fn main() { let gossip_addr = SocketAddr::new( gossip_host, value_t!(matches, "gossip_port", u16).unwrap_or_else(|_| { - let (gossip_port, _) = solana_net_utils::bind_common_in_range(bind_address, 0..1) - .unwrap_or_else(|err| { - eprintln!("Unable to find an available gossip port: {err}"); - exit(1); - }); + let (gossip_port, _) = + solana_net_utils::bind_common_in_range(bind_address, &mut (0..1)).unwrap_or_else( + |err| { + eprintln!("Unable to find an available gossip port: {err}"); + exit(1); + }, + ); gossip_port }), );