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 thread_local! {
44 static SIM_ADDRESS_MANAGER: Arc<SimAddressManager> = Arc::new(SimAddressManager::new());
46 }
47 SIM_ADDRESS_MANAGER.with(|s| s.clone())
48}
49
50#[cfg(msim)]
52pub fn get_new_ip() -> String {
53 get_sim_address_manager().get_next_ip()
54}
55
56#[cfg(not(msim))]
58pub fn get_new_ip() -> String {
59 localhost_for_testing()
60}
61
62pub fn localhost_for_testing() -> String {
64 "127.0.0.1".to_string()
65}
66
67#[cfg(msim)]
70pub fn get_available_port(_host: &str) -> u16 {
71 get_sim_address_manager().get_next_available_port()
72}
73
74#[cfg(not(msim))]
78pub fn get_available_port(host: &str) -> u16 {
79 const MAX_PORT_RETRIES: u32 = 1000;
80
81 for _ in 0..MAX_PORT_RETRIES {
82 if let Ok(port) = get_ephemeral_port(host) {
83 return port;
84 }
85 }
86
87 panic!(
88 "Error: could not find an available port on {}: {:?}",
89 host,
90 get_ephemeral_port(host)
91 );
92}
93
94#[cfg(not(msim))]
95fn get_ephemeral_port(host: &str) -> std::io::Result<u16> {
96 use std::net::{TcpListener, TcpStream};
97
98 let listener = TcpListener::bind((host, 0))?;
100 let addr = listener.local_addr()?;
101
102 let _sender = TcpStream::connect(addr)?;
106 let _incoming = listener.accept()?;
107
108 Ok(addr.port())
109}
110
111pub fn new_tcp_address_for_testing(host: &str) -> Multiaddr {
113 format!("/ip4/{}/tcp/{}/http", host, get_available_port(host))
114 .parse()
115 .unwrap()
116}
117
118pub fn new_udp_address_for_testing(host: &str) -> Multiaddr {
120 format!("/ip4/{}/udp/{}", host, get_available_port(host))
121 .parse()
122 .unwrap()
123}
124
125pub fn new_local_tcp_socket_for_testing_string() -> String {
127 format!(
128 "{}:{}",
129 localhost_for_testing(),
130 get_available_port(&localhost_for_testing())
131 )
132}
133
134pub fn new_local_tcp_socket_for_testing() -> SocketAddr {
136 new_local_tcp_socket_for_testing_string().parse().unwrap()
137}
138
139pub fn new_local_tcp_address_for_testing() -> Multiaddr {
141 new_tcp_address_for_testing(&localhost_for_testing())
142}
143
144pub fn new_local_udp_address_for_testing() -> Multiaddr {
146 new_udp_address_for_testing(&localhost_for_testing())
147}
148
149pub fn new_deterministic_tcp_address_for_testing(host: &str, port: u16) -> Multiaddr {
150 format!("/ip4/{host}/tcp/{port}/http").parse().unwrap()
151}
152
153pub fn new_deterministic_udp_address_for_testing(host: &str, port: u16) -> Multiaddr {
154 format!("/ip4/{host}/udp/{port}/http").parse().unwrap()
155}