use std::io;
use std::net::{SocketAddr, UdpSocket};
use std::time::{Duration, Instant};
use bytes::Bytes;
use crate::protocol::DisconnectReason;
use crate::socket::{SocketConfig, SocketEvent, SoeMultiplexer, SoeSocket};
const RECV_BUFFER_SIZE: usize = 2048;
#[derive(Debug)]
pub struct SyncSoeSocket {
mux: SoeMultiplexer<SocketAddr>,
socket: UdpSocket,
buf: Box<[u8]>,
}
impl SyncSoeSocket {
pub fn bind(
local: SocketAddr,
config: SocketConfig,
tick_period: Duration,
) -> io::Result<Self> {
let socket = UdpSocket::bind(local)?;
socket.set_read_timeout(Some(tick_period))?;
Ok(Self {
mux: SoeMultiplexer::new(config),
socket,
buf: vec![0u8; RECV_BUFFER_SIZE].into_boxed_slice(),
})
}
pub fn step(&mut self) -> io::Result<Vec<SocketEvent<SocketAddr>>> {
match self.socket.recv_from(&mut self.buf) {
Ok((len, from)) => {
let datagram = Bytes::copy_from_slice(&self.buf[..len]);
self.mux.process_incoming(from, datagram, Instant::now());
}
Err(e)
if e.kind() == io::ErrorKind::WouldBlock || e.kind() == io::ErrorKind::TimedOut => {
}
Err(e) => return Err(e),
}
self.mux.run_tick(Instant::now());
for (addr, datagram) in self.mux.take_outgoing() {
self.socket.send_to(&datagram, addr)?;
}
Ok(self.mux.take_events())
}
}
impl SoeSocket for SyncSoeSocket {
fn local_addr(&self) -> io::Result<SocketAddr> {
self.socket.local_addr()
}
fn session_count(&self) -> usize {
self.mux.session_count()
}
fn connect(&mut self, remote: SocketAddr) {
self.mux.connect(remote, Instant::now());
}
fn enqueue_data(&mut self, remote: &SocketAddr, data: &[u8]) -> bool {
self.mux.enqueue_data(remote, data)
}
fn terminate(&mut self, remote: &SocketAddr, reason: DisconnectReason) {
self.mux.terminate(remote, reason, Instant::now());
}
}