Skip to content

Commit

Permalink
Merge pull request #12 from quackitsquinn/socket-config
Browse files Browse the repository at this point in the history
Add Socket config
  • Loading branch information
quackitsquinn authored May 19, 2024
2 parents 857cc0b + f99697e commit edd807c
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 10 deletions.
11 changes: 10 additions & 1 deletion lazuli_core/src/client/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ use log::trace;

use crate::{hash_type_id, stream::Stream, ArcMutex, Result, Sendable};

use super::{connector::StreamConnector, input, listener::SocketListener, StreamCollection};
use super::{
config::SocketConfig, connector::StreamConnector, input, listener::SocketListener,
StreamCollection,
};
/// A client for sending and receiving data.
pub struct Client {
socket: ArcMutex<TcpStream>,
Expand Down Expand Up @@ -55,6 +58,12 @@ impl Client {
))
}

/// Applies the configuration to the socket.
pub fn with_config(self, config: &SocketConfig) -> Result<Self> {
config.apply_stream(&mut self.socket.lock().unwrap())?;
Ok(self)
}

/// Sends data to the socket.
#[inline]
pub fn send<T>(&mut self, data: &T) -> Result<()>
Expand Down
94 changes: 94 additions & 0 deletions lazuli_core/src/client/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/// Config flags for the underlying socket of a client.
pub struct SocketConfig {
/// Whether the socket should be blocking.
pub blocking: Option<bool>,
/// The read timeout for the socket.
pub read_timeout: Option<std::time::Duration>,
/// The write timeout for the socket.
pub write_timeout: Option<std::time::Duration>,
/// The time-to-live for the socket.
pub ttl: Option<u32>,
/// Whether the socket should have the Nagle algorithm disabled
pub nodelay: Option<bool>,
}

impl Default for SocketConfig {
fn default() -> Self {
Self {
blocking: None,
read_timeout: None,
write_timeout: None,
ttl: None,
nodelay: None,
}
}
}

impl SocketConfig {
/// Creates a new `SocketConfig` with all fields set to `None`.
/// This is equivalent to `SocketConfig::default()`.
pub fn new() -> Self {
Self::default()
}

/// Applies the configuration to the given socket. Any fields that are `None` are ignored.
pub fn apply_stream(&self, socket: &std::net::TcpStream) -> std::io::Result<()> {
if let Some(blocking) = self.blocking {
socket.set_nonblocking(!blocking)?;
}
if let Some(read_timeout) = self.read_timeout {
socket.set_read_timeout(Some(read_timeout))?;
}
if let Some(write_timeout) = self.write_timeout {
socket.set_write_timeout(Some(write_timeout))?;
}
if let Some(ttl) = self.ttl {
socket.set_ttl(ttl)?;
}
if let Some(nodelay) = self.nodelay {
socket.set_nodelay(nodelay)?;
}
Ok(())
}

/// Applies the configuration to the given listener. Any fields that are `None` are ignored.
pub fn apply_listener(&self, listener: &std::net::TcpListener) -> std::io::Result<()> {
if let Some(blocking) = self.blocking {
listener.set_nonblocking(!blocking)?;
}
if let Some(ttl) = self.ttl {
listener.set_ttl(ttl)?;
}
Ok(())
}

/// Sets the blocking flag for the socket.
pub fn blocking(mut self, blocking: bool) -> Self {
self.blocking = Some(blocking);
self
}

/// Sets the read timeout for the socket.
pub fn read_timeout(mut self, read_timeout: std::time::Duration) -> Self {
self.read_timeout = Some(read_timeout);
self
}

/// Sets the write timeout for the socket.
pub fn write_timeout(mut self, write_timeout: std::time::Duration) -> Self {
self.write_timeout = Some(write_timeout);
self
}

/// Sets the time-to-live for the socket.
pub fn ttl(mut self, ttl: u32) -> Self {
self.ttl = Some(ttl);
self
}

/// Sets the nodelay flag for the socket.
pub fn nodelay(mut self, nodelay: bool) -> Self {
self.nodelay = Some(nodelay);
self
}
}
1 change: 1 addition & 0 deletions lazuli_core/src/client/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod client;
mod config;
mod connector;
mod input;
mod listener;
Expand Down
17 changes: 8 additions & 9 deletions lazuli_core/src/client/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ use std::{

use crate::{ArcMutex, Client, Result, Sendable};

use super::config::{self, SocketConfig};

pub struct Server {
listener: TcpListener,
streams: Vec<ArcMutex<Client>>,
Expand All @@ -19,14 +21,10 @@ impl Server {
streams: vec![],
})
}
/// Creates a new non-blocking server.
pub fn new_nonblocking<T: ToSocketAddrs>(addrs: T) -> Result<Self> {
let listener = TcpListener::bind(addrs)?;
listener.set_nonblocking(true)?;
Ok(Server {
listener,
streams: vec![],
})
/// Adds a configuration to the server.
pub fn with_config(self, config: SocketConfig) -> Result<Self> {
config.apply_listener(&self.listener)?;
Ok(self)
}
/// Accepts a connection.
pub fn accept(&mut self) -> Result<ArcMutex<Client>> {
Expand Down Expand Up @@ -116,7 +114,8 @@ mod test {
}
#[test]
fn test_nonblocking_server() -> Result<()> {
let mut server = Server::new_nonblocking((Ipv4Addr::LOCALHOST, 0))?;
let mut server = Server::new((Ipv4Addr::LOCALHOST, 0))?
.with_config(SocketConfig::new().blocking(false))?;
assert!(server.accept().is_err());
if let Err(e) = server.accept() {
assert_eq!(e.kind(), std::io::ErrorKind::WouldBlock);
Expand Down

0 comments on commit edd807c

Please sign in to comment.