easy_sockets/
lib.rs

1//! Easy Sockets Rust
2//! -----------------
3//! Quick and easy way of building up complex socket protocols.
4//!
5
6use anyhow::{Context, Result};
7use lazy_static::lazy_static;
8pub use serde::{Deserialize, Serialize};
9
10use std::net::TcpStream;
11use std::sync::Mutex;
12
13pub use std::{thread::sleep, time::Duration};
14pub use tokio;
15
16use tokio::io::{AsyncReadExt, AsyncWriteExt};
17use tokio::net;
18
19pub mod error;
20pub mod logger;
21pub mod prelude;
22pub mod sendable;
23pub mod sockets;
24
25use sendable::Sendable;
26
27lazy_static! {
28    static ref CLIENT: Mutex<Option<TcpStream>> = Mutex::new(None);
29}
30
31/// The default buffer size expected from a socket message.
32const BUFFER_SIZE: usize = 1024;
33pub type Bytes = Vec<u8>;
34
35/// Trait that simplifies the creation of the server side of a socket protocol.
36pub trait ServerConn {
37    type ClientMsg: Serialize + for<'de> Deserialize<'de> + Send + 'static;
38    type ServerMsg: Serialize + for<'de> Deserialize<'de> + Send + 'static;
39
40    /// Handle Message
41    /// --------------
42    /// This function runs every time the server-conn receives a client message. You need to decide what message tp respond with.
43    ///
44    fn handle_message(&mut self, message: Self::ClientMsg) -> Self::ServerMsg;
45
46    /// Opens a new server connection.
47    fn new() -> Self;
48}
49
50pub async fn start_server<T: ServerConn + Send + 'static>(
51    address: impl net::ToSocketAddrs,
52) -> Result<()> {
53    // Initialize and bind the server
54    let listener = net::TcpListener::bind(address)
55        .await
56        .context("Failed to bind to address")?;
57
58    // Accept and handle connections
59    while let Ok((socket, _)) = listener.accept().await {
60        tokio::spawn(async move {
61            let res = handle_connection(socket, &mut T::new()).await;
62            eprintln!("{:?}", res);
63        });
64    }
65
66    Ok(())
67}
68
69async fn handle_connection<T: ServerConn + Send + 'static>(
70    mut socket: tokio::net::TcpStream,
71    instance: &mut T,
72) -> Result<()> {
73    let (reader, writer) = socket.split();
74    let mut reader = tokio::io::BufReader::new(reader);
75    let mut writer = tokio::io::BufWriter::new(writer);
76
77    let mut buf = vec![0; BUFFER_SIZE];
78    loop {
79        let n = reader
80            .read(&mut buf)
81            .await
82            .context("Failed to read from socket")?;
83        if n == 0 {
84            break; // Connection closed
85        }
86
87        // Ensure buf contains only the data read
88        let message = T::ClientMsg::from_bytes(&buf).context("Failed to parse message")?;
89        let response = instance.handle_message(message);
90
91        let response_bytes = response
92            .to_bytes()
93            .context("Failed to serialize response")?;
94        writer
95            .write_all(&response_bytes)
96            .await
97            .context("Failed to write to socket")?;
98        writer.flush().await.context("Failed to flush writer")?;
99    }
100
101    Ok(())
102}