use std::{net::SocketAddr, time::Instant}; use crate::Sender; use super::socket::{Socket, SocketContent, SocketCreateInfo}; use anyhow::Result; pub struct Client { socket: Socket, server: SocketAddr, last_message: Option, } impl Client { pub fn new(create_info: SocketCreateInfo, server: impl Into) -> Result { Ok(Self { socket: Socket::new(create_info)?, server: server.into(), last_message: None, }) } pub fn server_address(&self) -> SocketAddr { self.server } pub fn check_heartbeat(&mut self) -> Result<()> { let now = Instant::now(); if (now - self.socket.start) > self.socket.heartbeat_interval { self.socket.start += self.socket.heartbeat_interval; Client::send(self, "")?; } Ok(()) } pub fn send(&self, msg: &str) -> Result<()> { self.socket.send(self.server, msg) } pub fn receive(&mut self) -> Result> { let now = Instant::now(); let mut content = Vec::new(); while let Some((addr, msg)) = match self.socket.receive() { Ok(r) => r, Err(err) => { // if content is empty return the error // if not, ignore the error and break the loop if content.is_empty() { return Err(err); } else { None } } } { if addr != self.server { // discard message if thats from another source continue; } match &mut self.last_message { Some(last_message) => *last_message = now, None => { self.last_message = Some(now); content.push(SocketContent::NewConnection(addr)); } } if !msg.is_empty() { content.push(SocketContent::Message(addr, msg)); } } if let Some(last_message) = self.last_message { if (now - last_message) > self.socket.connection_time_out() { self.last_message = None; content.push(SocketContent::TimeOut(self.server)); } } Ok(content) } } impl Sender for Client { fn send(&mut self, _: SocketAddr, msg: &str) -> Result<()> { Client::send(self, msg) } fn is_server(&self) -> bool { false } }