veilid/veilid-core/src/xx/bump_port.rs

108 lines
2.7 KiB
Rust
Raw Normal View History

2021-11-22 16:28:30 +00:00
use super::*;
cfg_if! {
if #[cfg(target_arch = "wasm32")] {
} else {
use std::net::{TcpListener, UdpSocket};
}
}
2022-07-12 16:45:54 +00:00
#[derive(ThisError, Debug, Clone, PartialEq, Eq)]
pub enum BumpPortError {
#[error("Unsupported architecture")]
Unsupported,
#[error("Failure: {0}")]
Failed(String),
}
2021-11-22 16:28:30 +00:00
pub enum BumpPortType {
UDP,
TCP,
}
pub fn tcp_port_available(addr: &SocketAddr) -> bool {
cfg_if! {
if #[cfg(target_arch = "wasm32")] {
true
2021-11-22 16:28:30 +00:00
} else {
match TcpListener::bind(addr) {
Ok(_) => true,
Err(_) => false,
}
}
}
}
pub fn udp_port_available(addr: &SocketAddr) -> bool {
cfg_if! {
if #[cfg(target_arch = "wasm32")] {
true
2021-11-22 16:28:30 +00:00
} else {
match UdpSocket::bind(addr) {
Ok(_) => true,
Err(_) => false,
}
}
}
}
2022-07-12 16:45:54 +00:00
pub fn bump_port(addr: &mut SocketAddr, bpt: BumpPortType) -> Result<bool, BumpPortError> {
2021-11-22 16:28:30 +00:00
cfg_if! {
if #[cfg(target_arch = "wasm32")] {
2022-07-12 16:45:54 +00:00
Err(BumpPortError::Unsupported)
2021-11-22 16:28:30 +00:00
}
else
{
let mut bumped = false;
let mut port = addr.port();
let mut addr_bump = addr.clone();
loop {
if match bpt {
BumpPortType::TCP => tcp_port_available(&addr_bump),
BumpPortType::UDP => udp_port_available(&addr_bump),
} {
*addr = addr_bump;
return Ok(bumped);
}
if port == u16::MAX {
break;
}
port += 1;
addr_bump.set_port(port);
bumped = true;
}
2022-07-12 16:45:54 +00:00
Err(BumpPortError::Failure("no ports remaining".to_owned()))
2021-11-22 16:28:30 +00:00
}
}
}
2022-07-12 16:45:54 +00:00
pub fn bump_port_string(addr: &mut String, bpt: BumpPortType) -> Result<bool, BumpPortError> {
2021-11-22 16:28:30 +00:00
cfg_if! {
if #[cfg(target_arch = "wasm32")] {
2022-07-12 16:45:54 +00:00
return Err(BumpPortError::Unsupported);
2021-11-22 16:28:30 +00:00
}
else
{
let savec: Vec<SocketAddr> = addr
.to_socket_addrs()
2022-07-12 16:45:54 +00:00
.map_err(|x| BumpPortError::Failure(format!("failed to resolve socket address: {}", x)))?
2021-11-22 16:28:30 +00:00
.collect();
if savec.len() == 0 {
2022-07-12 16:45:54 +00:00
return Err(BumpPortError::Failure("No socket addresses resolved".to_owned()));
2021-11-22 16:28:30 +00:00
}
let mut sa = savec.first().unwrap().clone();
if !bump_port(&mut sa, bpt)? {
return Ok(false);
}
*addr = sa.to_string();
Ok(true)
}
}
}