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};
98
99 let listener = TcpListener::bind((host, 0))?;
101 let addr = listener.local_addr()?;
102
103 let _sender = TcpStream::connect(addr)?;
107 let _incoming = listener.accept()?;
108
109 Ok(addr.port())
110}
111
112pub fn new_tcp_address_for_testing(host: &str) -> Multiaddr {
114 format!("/ip4/{}/tcp/{}/https", host, get_available_port(host))
115 .parse()
116 .unwrap()
117}
118
119pub fn new_udp_address_for_testing(host: &str) -> Multiaddr {
121 format!("/ip4/{}/udp/{}", host, get_available_port(host))
122 .parse()
123 .unwrap()
124}
125
126pub fn new_local_tcp_socket_for_testing_string() -> String {
128 format!(
129 "{}:{}",
130 localhost_for_testing(),
131 get_available_port(&localhost_for_testing())
132 )
133}
134
135pub fn new_local_tcp_socket_for_testing() -> SocketAddr {
137 new_local_tcp_socket_for_testing_string().parse().unwrap()
138}
139
140pub fn new_local_tcp_address_for_testing() -> Multiaddr {
142 new_tcp_address_for_testing(&localhost_for_testing())
143}
144
145pub fn new_local_udp_address_for_testing() -> Multiaddr {
147 new_udp_address_for_testing(&localhost_for_testing())
148}
149
150pub fn new_deterministic_tcp_address_for_testing(host: &str, port: u16) -> Multiaddr {
151 format!("/ip4/{host}/tcp/{port}/https").parse().unwrap()
152}
153
154pub fn new_deterministic_udp_address_for_testing(host: &str, port: u16) -> Multiaddr {
155 format!("/ip4/{host}/udp/{port}/https").parse().unwrap()
156}