use crate::utils::local_context::detect_container_environment;
use rand::Rng;
use tokio::net::TcpListener;
const MIN_EPHEMERAL_PORT: u16 = 49152;
const MAX_EPHEMERAL_PORT: u16 = 65535;
const MAX_ATTEMPTS: u32 = 100;
async fn find_available_port_with_listener(host: &str) -> Result<(TcpListener, u16), String> {
for _attempt in 0..MAX_ATTEMPTS {
let port = {
let mut rng = rand::rng();
rng.random_range(MIN_EPHEMERAL_PORT..=MAX_EPHEMERAL_PORT)
}; let addr = format!("{}:{}", host, port);
match TcpListener::bind(&addr).await {
Ok(listener) => {
return Ok((listener, port));
}
Err(_) => {
continue;
}
}
}
Err(format!(
"Failed to find available port after {} attempts in range {}-{}",
MAX_ATTEMPTS, MIN_EPHEMERAL_PORT, MAX_EPHEMERAL_PORT
))
}
pub async fn find_available_bind_address_with_listener() -> Result<(String, TcpListener), String> {
let host = match detect_container_environment() {
true => "0.0.0.0",
false => "127.0.0.1", };
let (listener, port) = find_available_port_with_listener(host).await?;
let bind_address = format!("{}:{}", host, port);
Ok((bind_address, listener))
}