use ax_errno::{AxResult, ax_bail};
use ax_sync::Mutex;
use smoltcp::wire::{IpAddress, Ipv4Address};
const EPHEMERAL_PORT_START: u16 = 0xc000;
const EPHEMERAL_PORT_END: u16 = 0xffff;
pub(crate) fn listen_addrs_conflict(a: Option<IpAddress>, b: Option<IpAddress>) -> bool {
a.is_none() || b.is_none() || a == b
}
pub(crate) fn allocate_ephemeral_port(check_available: impl Fn(u16) -> bool) -> AxResult<u16> {
static CURR: Mutex<u16> = Mutex::new(EPHEMERAL_PORT_START);
let mut curr = CURR.lock();
let mut tries = 0;
while tries <= EPHEMERAL_PORT_END - EPHEMERAL_PORT_START {
let port = *curr;
if *curr == EPHEMERAL_PORT_END {
*curr = EPHEMERAL_PORT_START;
} else {
*curr += 1;
}
if check_available(port) {
return Ok(port);
}
tries += 1;
}
ax_bail!(AddrInUse, "no available ports");
}
pub(crate) fn mask_from_prefix(prefix_len: u8) -> Ipv4Address {
let bits: u32 = if prefix_len == 0 {
0
} else {
u32::MAX << (32 - prefix_len.min(32) as u32)
};
Ipv4Address::from_bits(bits)
}