engine/Networking/src/client.rs

100 lines
2.5 KiB
Rust
Raw Normal View History

2024-08-23 11:22:09 +00:00
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<Instant>,
}
impl Client {
pub fn new(create_info: SocketCreateInfo, server: impl Into<SocketAddr>) -> Result<Self> {
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<Vec<SocketContent>> {
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
}
}