use std::net::{Ipv4Addr, SocketAddrV4}; use std::sync::Arc; use tokio::net::UdpSocket; use crate::types::{Message, Sockets}; pub struct IpcFrame { pub message: Message, pub remote_addr: SocketAddrV4, } impl IpcFrame { pub fn to_bytes(&self, socket: Arc) -> [u8; 22] { let message_bytes = self.message.to_response_bytes(socket, self.remote_addr); let mut buf = [0u8; 22]; buf[0..2].copy_from_slice(&self.remote_addr.port().to_be_bytes()); buf[2..6].copy_from_slice(&u32::from(*self.remote_addr.ip()).to_be_bytes()); buf[6..].copy_from_slice(&message_bytes.unwrap()); buf } pub fn from_bytes(slice: &[u8]) -> Result { if slice.len() < 6 { return Err("Frame too small to extract client metadata".into()) } let remote_port = u16::from_be_bytes(slice[0..2].try_into().unwrap()); let remote_ip = Ipv4Addr::from(u32::from_be_bytes(slice[2..6].try_into().unwrap())); let remote_addr = SocketAddrV4::new(remote_ip, remote_port); let message = Message::from_bytes(&slice[6..])?; Ok(IpcFrame{message, remote_addr}) } } pub async fn run(host: String, port: u16, sockets: Arc) -> Result<(), Box> { let ipc_socket = UdpSocket::bind(format!("{host}:{port}")).await?; let mut buf = [0u8; 2048]; tokio::spawn(async move { loop { match ipc_socket.recv_from(&mut buf).await { Ok((len, _sender_addr)) => { match IpcFrame::from_bytes(&buf[..len]) { Ok(ipc_frame) => { let socket = &sockets.alt; let _ = socket.send_to( &ipc_frame.message.to_response_bytes(socket.clone(), ipc_frame.remote_addr).unwrap(), format!("{}:{}", ipc_frame.remote_addr.ip(), ipc_frame.remote_addr.port()), ).await; }, Err(e) => { eprintln!("Failed to decode IPC Frame: {e}") } } }, Err(e) => { eprintln!("IPC Socket Error: {e}"); break; } } } }); Ok(()) }