use std::{
io::{Read, Write},
net::{Ipv4Addr, SocketAddr, TcpListener, TcpStream},
thread,
time::Duration,
};
pub fn find_all_instances(
base_port: u16,
max_search: u16,
timeout: Duration,
request_message: &[u8],
) -> Vec<(u16, String)> {
let mut instances = Vec::new();
for port in base_port..(base_port + max_search) {
if let Ok(response) = send_handshake_request(port, timeout, request_message) {
instances.push((port, response));
}
}
instances
}
pub fn find_next_available_port(base_port: u16, max_search: u16) -> u16 {
for port in base_port..(base_port + max_search) {
if !is_port_in_use(port) {
return port;
}
}
base_port
}
pub fn start_handshake_server<F>(port: u16, response_generator: F)
where
F: Fn() -> String + Send + Sync + 'static + Clone,
{
thread::spawn(move || {
let listener = match TcpListener::bind((Ipv4Addr::LOCALHOST, port)) {
Ok(listener) => listener,
Err(e) => {
eprintln!("[!] Failed to bind handshake server on port {}: {}", port, e);
return;
}
};
eprintln!("[+] Handshake server listening on port {}", port);
for stream in listener.incoming() {
match stream {
Ok(mut stream) => {
let local_generator = response_generator.clone();
thread::spawn(move || {
let mut buffer = [0u8; 1024];
let peer_addr = stream.peer_addr()
.map(|a| a.to_string())
.unwrap_or_else(|_| "unknown".to_string());
match stream.read(&mut buffer) {
Ok(_) => {
let response_str = local_generator();
if let Err(e) = stream.write_all(response_str.as_bytes()) {
eprintln!("[!] Error sending handshake response to {}: {}", peer_addr, e);
}
}
Err(e) => {
eprintln!("[!] Error reading handshake request from {}: {}", peer_addr, e);
}
}
});
}
Err(e) => {
eprintln!("[!] Handshake server connection error on port {}: {}", port, e);
}
}
}
eprintln!("[-] Handshake server on port {} stopped.", port);
});
}
pub fn is_port_in_use(port: u16) -> bool {
let addr = SocketAddr::new(Ipv4Addr::LOCALHOST.into(), port);
TcpStream::connect_timeout(&addr, Duration::from_millis(100)).is_ok()
}
pub fn send_handshake_request(
port: u16,
timeout: Duration,
request_message: &[u8],
) -> anyhow::Result<String> {
let addr = SocketAddr::new(Ipv4Addr::LOCALHOST.into(), port);
let mut stream = TcpStream::connect_timeout(&addr, timeout)?;
stream.set_read_timeout(Some(timeout))?;
stream.write_all(request_message)?;
let mut buffer = [0u8; 1024];
let n = stream.read(&mut buffer)?;
let response = String::from_utf8_lossy(&buffer[..n]).to_string();
Ok(response)
}