use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; use std::sync::Arc; use tokio::net::UdpSocket; pub struct Sockets { pub primary: Arc, pub secondary: Arc, pub alt: Arc, pub p33334: Arc, pub p33335: Arc, } #[derive(Debug)] pub struct Message { pub r#type: u32, pub external_port: u32, pub external_address: Ipv4Addr, pub local_address: u32, } impl Message { pub fn from_bytes(bytes: &[u8]) -> Result { if bytes.len() < 16 { return Err(format!("Buffer too short, expected 16 bytes but found {} bytes", bytes.len())) }; let r#type = u32::from_be_bytes(bytes[0..4].try_into().unwrap()); let external_port = u32::from_be_bytes(bytes[4..8].try_into().unwrap()); let external_address = Ipv4Addr::from(u32::from_be_bytes(bytes[8..12].try_into().unwrap())); let local_address = u32::from_be_bytes(bytes[12..16].try_into().unwrap()); Ok(Message{ r#type, external_port, external_address, local_address, }) } pub fn to_response_bytes(&self, socket: Arc, remote_addr: SocketAddrV4) -> Result<[u8; 16], String> { let mut bytes = [0u8; 16]; bytes[0..4].copy_from_slice(&self.r#type.to_be_bytes()); bytes[4..8].copy_from_slice(&remote_addr.port().to_be_bytes()); bytes[8..12].copy_from_slice(&u32::from(*remote_addr.ip()).to_be_bytes()); let local_ip = match socket.local_addr().unwrap() { SocketAddr::V4(addr) => *addr.ip(), SocketAddr::V6(_) => { return Err("Ipv6 not supported".into()); }, }; bytes[12..16].copy_from_slice(&u32::from(local_ip).to_be_bytes()); Ok(bytes) } }