iota_config/
local_ip_utils.rs1use std::net::SocketAddr;
6#[cfg(msim)]
7use std::sync::{Arc, atomic::AtomicI16};
8
9use iota_types::multiaddr::Multiaddr;
10
11#[cfg(msim)]
15pub struct SimAddressManager {
16 next_ip_offset: AtomicI16,
17 next_port: AtomicI16,
18}
19
20#[cfg(msim)]
21impl Default for SimAddressManager {
22 fn default() -> Self {
23 Self {
24 next_ip_offset: AtomicI16::new(1),
25 next_port: AtomicI16::new(9000),
26 }
27 }
28}
29
30#[cfg(msim)]
31impl SimAddressManager {
32 pub fn new() -> Self {
33 Self::default()
34 }
35
36 pub fn get_next_ip(&self) -> String {
37 let offset = self
38 .next_ip_offset
39 .fetch_add(1, std::sync::atomic::Ordering::SeqCst);
40 assert!(offset <= 255);
42 format!("10.10.0.{}", offset)
43 }
44
45 pub fn get_next_available_port(&self) -> u16 {
46 self.next_port
47 .fetch_add(1, std::sync::atomic::Ordering::SeqCst) as u16
48 }
49}
50
51#[cfg(msim)]
52fn get_sim_address_manager() -> Arc<SimAddressManager> {
53 thread_local! {
54 static SIM_ADDRESS_MANAGER: Arc<SimAddressManager> = Arc::new(SimAddressManager::new());
56 }
57 SIM_ADDRESS_MANAGER.with(|s| s.clone())
58}
59
60#[cfg(msim)]
62pub fn get_new_ip() -> String {
63 get_sim_address_manager().get_next_ip()
64}
65
66#[cfg(not(msim))]
68pub fn get_new_ip() -> String {
69 localhost_for_testing()
70}
71
72pub fn localhost_for_testing() -> String {
74 "127.0.0.1".to_string()
75}
76
77#[cfg(msim)]
81pub fn get_available_port(_host: &str) -> u16 {
82 get_sim_address_manager().get_next_available_port()
83}
84
85#[cfg(not(msim))]
90pub fn get_available_port(host: &str) -> u16 {
91 const MAX_PORT_RETRIES: u32 = 1000;
92
93 for _ in 0..MAX_PORT_RETRIES {
94 if let Ok(port) = get_ephemeral_port(host) {
95 return port;
96 }
97 }
98
99 panic!(
100 "error: could not find an available port on {}: {:?}",
101 host,
102 get_ephemeral_port(host)
103 );
104}
105
106#[cfg(not(msim))]
107fn get_ephemeral_port(host: &str) -> std::io::Result<u16> {
108 use std::net::{TcpListener, TcpStream};
109
110 let listener = TcpListener::bind((host, 0))?;
112 let addr = listener.local_addr()?;
113
114 let _sender = TcpStream::connect(addr)?;
119 let _incoming = listener.accept()?;
120
121 Ok(addr.port())
122}
123
124pub fn new_tcp_address_for_testing(host: &str) -> Multiaddr {
127 format!("/ip4/{}/tcp/{}/http", host, get_available_port(host))
128 .parse()
129 .unwrap()
130}
131
132pub fn new_udp_address_for_testing(host: &str) -> Multiaddr {
135 format!("/ip4/{}/udp/{}", host, get_available_port(host))
136 .parse()
137 .unwrap()
138}
139
140pub fn new_local_tcp_socket_for_testing() -> SocketAddr {
143 format!(
144 "{}:{}",
145 localhost_for_testing(),
146 get_available_port(&localhost_for_testing())
147 )
148 .parse()
149 .unwrap()
150}
151
152pub fn new_local_tcp_address_for_testing() -> Multiaddr {
155 new_tcp_address_for_testing(&localhost_for_testing())
156}
157
158pub fn new_local_udp_address_for_testing() -> Multiaddr {
161 new_udp_address_for_testing(&localhost_for_testing())
162}
163
164pub fn new_deterministic_tcp_address_for_testing(host: &str, port: u16) -> Multiaddr {
165 format!("/ip4/{host}/tcp/{port}/http").parse().unwrap()
166}
167
168pub fn new_deterministic_udp_address_for_testing(host: &str, port: u16) -> Multiaddr {
169 format!("/ip4/{host}/udp/{port}/http").parse().unwrap()
170}