use std::{io::ErrorKind, net::SocketAddr};
use crate::{NetcodeTransportError, ServerSocket};
use super::*;
#[derive(Debug)]
pub struct MemorySocketServer {
clients: Vec<(u16, MemorySocketChannels)>,
encrypted: bool,
reliable: bool,
drain_index: usize,
}
impl MemorySocketServer {
pub fn new(clients: Vec<(u16, MemorySocketChannels)>) -> Self {
Self::new_with(clients, true, true)
}
pub fn new_with(clients: Vec<(u16, MemorySocketChannels)>, encrypted: bool, reliable: bool) -> Self {
Self {
clients,
encrypted,
reliable,
drain_index: 0,
}
}
}
impl ServerSocket for MemorySocketServer {
fn is_encrypted(&self) -> bool {
self.encrypted
}
fn is_reliable(&self) -> bool {
self.reliable
}
fn addr(&self) -> std::io::Result<SocketAddr> {
Ok(in_memory_server_addr())
}
fn is_closed(&mut self) -> bool {
false
}
fn close(&mut self) {}
fn connection_denied(&mut self, _: SocketAddr) {}
fn connection_accepted(&mut self, _: u64, _: SocketAddr) {}
fn disconnect(&mut self, _: SocketAddr) {}
fn preupdate(&mut self) {
self.drain_index = 0;
}
fn try_recv(&mut self, buffer: &mut [u8]) -> std::io::Result<(usize, SocketAddr)> {
loop {
if self.drain_index >= self.clients.len() {
return Err(std::io::Error::from(ErrorKind::WouldBlock));
}
let client = &mut self.clients[self.drain_index];
if let Ok(packet) = client.1.receiver.try_recv() {
buffer[..packet.len].copy_from_slice(&packet.bytes[..packet.len]);
return Ok((packet.len, in_memory_client_addr(client.0)));
};
self.drain_index += 1;
}
}
fn postupdate(&mut self) {}
fn send(&mut self, addr: SocketAddr, packet: &[u8]) -> Result<(), NetcodeTransportError> {
assert!(packet.len() <= NETCODE_MAX_PACKET_BYTES);
let client_id = addr.port();
let mut mem_packet = InMemoryPacket {
len: packet.len(),
..Default::default()
};
mem_packet.bytes[..packet.len()].copy_from_slice(packet);
let idx = self
.clients
.iter()
.position(|(id, _)| *id == client_id)
.ok_or_else(|| std::io::Error::from(ErrorKind::AddrNotAvailable))?;
self.clients[idx]
.1
.sender
.send(mem_packet)
.map_err(|_| std::io::Error::from(ErrorKind::ConnectionAborted))?;
Ok(())
}
}