sui_config/
local_ip_utils.rs1use std::net::SocketAddr;
5#[cfg(msim)]
6use std::sync::{Arc, atomic::AtomicI16};
7use sui_types::multiaddr::Multiaddr;
8
9#[cfg(msim)]
12pub struct SimAddressManager {
13 next_ip_offset: AtomicI16,
14 next_port: AtomicI16,
15}
16
17#[cfg(msim)]
18impl SimAddressManager {
19 pub fn new() -> Self {
20 Self {
21 next_ip_offset: AtomicI16::new(1),
22 next_port: AtomicI16::new(9000),
23 }
24 }
25
26 pub fn get_next_ip(&self) -> String {
27 let offset = self
28 .next_ip_offset
29 .fetch_add(1, std::sync::atomic::Ordering::SeqCst);
30 assert!(offset <= 255);
32 format!("10.10.0.{}", offset)
33 }
34
35 pub fn get_next_available_port(&self) -> u16 {
36 self.next_port
37 .fetch_add(1, std::sync::atomic::Ordering::SeqCst) as u16
38 }
39}
40
41#[cfg(msim)]
42fn get_sim_address_manager() -> Arc<SimAddressManager> {
43 static SIM_ADDRESS_MANAGER: std::sync::OnceLock<Arc<SimAddressManager>> =
45 std::sync::OnceLock::new();
46 SIM_ADDRESS_MANAGER
47 .get_or_init(|| Arc::new(SimAddressManager::new()))
48 .clone()
49}
50
51#[cfg(msim)]
53pub fn get_new_ip() -> String {
54 get_sim_address_manager().get_next_ip()
55}
56
57#[cfg(not(msim))]
59pub fn get_new_ip() -> String {
60 localhost_for_testing()
61}
62
63pub fn localhost_for_testing() -> String {
65 "127.0.0.1".to_string()
66}
67
68#[cfg(msim)]
71pub fn get_available_port(_host: &str) -> u16 {
72 get_sim_address_manager().get_next_available_port()
73}
74
75#[cfg(not(msim))]
79pub fn get_available_port(host: &str) -> u16 {
80 const MAX_PORT_RETRIES: u32 = 1000;
81
82 for _ in 0..MAX_PORT_RETRIES {
83 if let Ok(port) = get_ephemeral_port(host) {
84 return port;
85 }
86 }
87
88 panic!(
89 "Error: could not find an available port on {}: {:?}",
90 host,
91 get_ephemeral_port(host)
92 );
93}
94
95#[cfg(not(msim))]
96fn get_ephemeral_port(host: &str) -> std::io::Result<u16> {
97 use std::net::{TcpListener, TcpStream, UdpSocket};
98
99 let listener = TcpListener::bind((host, 0))?;
101 let addr = listener.local_addr()?;
102 let _udp_socket = UdpSocket::bind(addr)?;
103
104 let _sender = TcpStream::connect(addr)?;
108 let _incoming = listener.accept()?;
109
110 Ok(addr.port())
111}
112
113pub fn new_tcp_address_for_testing(host: &str) -> Multiaddr {
115 format!("/ip4/{}/tcp/{}/https", host, get_available_port(host))
116 .parse()
117 .unwrap()
118}
119
120pub fn new_udp_address_for_testing(host: &str) -> Multiaddr {
122 format!("/ip4/{}/udp/{}", host, get_available_port(host))
123 .parse()
124 .unwrap()
125}
126
127pub fn new_local_tcp_socket_for_testing_string() -> String {
129 format!(
130 "{}:{}",
131 localhost_for_testing(),
132 get_available_port(&localhost_for_testing())
133 )
134}
135
136pub fn new_local_tcp_socket_for_testing() -> SocketAddr {
138 new_local_tcp_socket_for_testing_string().parse().unwrap()
139}
140
141pub fn new_local_tcp_address_for_testing() -> Multiaddr {
143 new_tcp_address_for_testing(&localhost_for_testing())
144}
145
146pub fn new_local_udp_address_for_testing() -> Multiaddr {
148 new_udp_address_for_testing(&localhost_for_testing())
149}
150
151pub fn new_deterministic_tcp_address_for_testing(host: &str, port: u16) -> Multiaddr {
152 format!("/ip4/{host}/tcp/{port}/https").parse().unwrap()
153}
154
155pub fn new_deterministic_udp_address_for_testing(host: &str, port: u16) -> Multiaddr {
156 format!("/ip4/{host}/udp/{port}/https").parse().unwrap()
157}