diff --git a/bench-streamer/src/main.rs b/bench-streamer/src/main.rs index de300345ebad42..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 7d737d313eeae7..f21742cd928b1b 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, @@ -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,22 +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, QUIC_PORT_OFFSET).unwrap(); + 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).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, QUIC_PORT_OFFSET).unwrap(); + 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 = find_available_port_in_range(localhost_ip_addr, port_range).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 = find_available_port_in_range(localhost_ip_addr, port_range).unwrap(); + let (rpc_pubsub_port, _) = + 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(); @@ -2891,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 { @@ -2905,34 +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, 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, &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, 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, 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 = 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(); + 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( @@ -2989,51 +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, 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, 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, &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, 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, 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, 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, 8).expect("retransmit multi_bind"); + multi_bind_in_range(bind_ip_addr, &mut port_range, 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, &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, 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); + let (_, ancestor_hashes_requests) = Self::bind(bind_ip_addr, &mut port_range); let mut info = ContactInfo::new( *pubkey, @@ -3570,33 +3570,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 +3606,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 mut 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, &mut port_range) + .expect("Failed to bind") + .0; let config = NodeConfig { gossip_addr: socketaddr!(Ipv4Addr::LOCALHOST, port), port_range, @@ -3635,7 +3631,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 1f31195f431d36..cd20a79f059884 100644 --- a/gossip/src/main.rs +++ b/gossip/src/main.rs @@ -236,11 +236,12 @@ 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( + let (gossip_port, _) = solana_net_utils::bind_common_in_range( IpAddr::V4(Ipv4Addr::UNSPECIFIED), - (0, 1), + &mut (0..1), ) - .expect("unable to find an available gossip port") + .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..770b9180272a92 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}, @@ -29,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; @@ -340,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 { @@ -415,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.0..range.1 { + 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))); } @@ -425,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.0..range.1 { + for port in range.by_ref() { let addr = SocketAddr::new(ip_addr, port); if sock.bind(&SockAddr::from(addr)).is_ok() { @@ -443,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(), )) } @@ -462,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 { @@ -529,18 +531,18 @@ 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.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 { + while let Some(port) = range.next() { 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), @@ -558,29 +560,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}; @@ -652,7 +631,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); } @@ -682,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(); @@ -691,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()); } @@ -713,31 +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, (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(); + 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] @@ -745,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, @@ -767,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, @@ -795,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, @@ -818,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, @@ -842,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 10580b4711c054..6240865517f54e 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, &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!(); let blockstore = Arc::new(Blockstore::open(ledger_path.path()).unwrap()); 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 c8494221d614b0..2af1daf319baa8 100644 --- a/validator/src/main.rs +++ b/validator/src/main.rs @@ -1821,12 +1821,14 @@ 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| { - 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 }), );