From 73b71a1fb056ed1059e6f4832791d1c46e76b7dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konrad=20Gr=C3=A4fe?= Date: Wed, 3 May 2023 12:21:48 +0200 Subject: [PATCH] [refactor] config: Use dedicated functions to set options (#153) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [refactor] config: Use dedicated functions to set options With public members in the config structs the public API breaks each time we're adding new options as the users MUST or MUST NOT add ".. Default::default()" depending on whether they're setting all options or not. So adding new options breaks for those users who use all options. This change hides the members from the users and replaces access by dedicated setter functions for each option so adding new options does not break API in the future. (This change obviously is an API break in itself.) Signed-off-by: Konrad Gräfe * adapters::{framed_,}tcp: Re-export TcpKeepalive Signed-off-by: Konrad Gräfe --------- Signed-off-by: Konrad Gräfe --- src/adapters/framed_tcp.rs | 22 +++++++++++++--- src/adapters/tcp.rs | 22 +++++++++++++--- src/adapters/udp.rs | 54 ++++++++++++++++++++++++++++++++------ src/network.rs | 4 +-- 4 files changed, 86 insertions(+), 16 deletions(-) diff --git a/src/adapters/framed_tcp.rs b/src/adapters/framed_tcp.rs index fff93b3..b063710 100644 --- a/src/adapters/framed_tcp.rs +++ b/src/adapters/framed_tcp.rs @@ -1,3 +1,5 @@ +pub use socket2::{TcpKeepalive}; + use crate::network::adapter::{ Resource, Remote, Local, Adapter, SendStatus, AcceptedType, ReadStatus, ConnectionInfo, ListeningInfo, PendingStatus, @@ -8,7 +10,7 @@ use crate::util::encoding::{self, Decoder, MAX_ENCODED_SIZE}; use mio::net::{TcpListener, TcpStream}; use mio::event::{Source}; -use socket2::{Socket, TcpKeepalive}; +use socket2::{Socket}; use std::net::{SocketAddr}; use std::io::{self, ErrorKind, Read, Write}; @@ -24,14 +26,28 @@ const INPUT_BUFFER_SIZE: usize = u16::MAX as usize; // 2^16 - 1 #[derive(Clone, Debug, Default)] pub struct FramedTcpConnectConfig { + keepalive: Option, +} + +impl FramedTcpConnectConfig { /// Enables TCP keepalive settings on the socket. - pub keepalive: Option, + pub fn with_keepalive(mut self, keepalive: TcpKeepalive) -> Self { + self.keepalive = Some(keepalive); + self + } } #[derive(Clone, Debug, Default)] pub struct FramedTcpListenConfig { + keepalive: Option, +} + +impl FramedTcpListenConfig { /// Enables TCP keepalive settings on client connection sockets. - pub keepalive: Option, + pub fn with_keepalive(mut self, keepalive: TcpKeepalive) -> Self { + self.keepalive = Some(keepalive); + self + } } pub(crate) struct FramedTcpAdapter; diff --git a/src/adapters/tcp.rs b/src/adapters/tcp.rs index a781d0d..2934872 100644 --- a/src/adapters/tcp.rs +++ b/src/adapters/tcp.rs @@ -1,3 +1,5 @@ +pub use socket2::{TcpKeepalive}; + use crate::network::adapter::{ Resource, Remote, Local, Adapter, SendStatus, AcceptedType, ReadStatus, ConnectionInfo, ListeningInfo, PendingStatus, @@ -7,7 +9,7 @@ use crate::network::{RemoteAddr, Readiness, TransportConnect, TransportListen}; use mio::net::{TcpListener, TcpStream}; use mio::event::{Source}; -use socket2::{Socket, TcpKeepalive}; +use socket2::{Socket}; use std::net::{SocketAddr}; use std::io::{self, ErrorKind, Read, Write}; @@ -25,14 +27,28 @@ pub const INPUT_BUFFER_SIZE: usize = u16::MAX as usize; // 2^16 - 1 #[derive(Clone, Debug, Default)] pub struct TcpConnectConfig { + keepalive: Option, +} + +impl TcpConnectConfig { /// Enables TCP keepalive settings on the socket. - pub keepalive: Option, + pub fn with_keepalive(mut self, keepalive: TcpKeepalive) -> Self { + self.keepalive = Some(keepalive); + self + } } #[derive(Clone, Debug, Default)] pub struct TcpListenConfig { + keepalive: Option, +} + +impl TcpListenConfig { /// Enables TCP keepalive settings on client connection sockets. - pub keepalive: Option, + pub fn with_keepalive(mut self, keepalive: TcpKeepalive) -> Self { + self.keepalive = Some(keepalive); + self + } } pub(crate) struct TcpAdapter; diff --git a/src/adapters/udp.rs b/src/adapters/udp.rs index d1bbe15..35b4695 100644 --- a/src/adapters/udp.rs +++ b/src/adapters/udp.rs @@ -39,22 +39,41 @@ pub const MAX_LOCAL_PAYLOAD_LEN: usize = 9216 - 20 - 8; #[derive(Clone, PartialEq, Eq, Hash, Debug)] pub struct UdpConnectConfig { + source_address: SocketAddr, + broadcast: bool, + reuse_address: bool, + reuse_port: bool, +} + +impl UdpConnectConfig { /// Specify the source address and port. - pub source_address: SocketAddr, + pub fn with_source_address(mut self, addr: SocketAddr) -> Self { + self.source_address = addr; + self + } /// Enables the socket capabilities to send broadcast messages. - pub broadcast: bool, + pub fn with_broadcast(mut self) -> Self { + self.broadcast = true; + self + } /// Set value for the `SO_REUSEADDR` option on this socket. This indicates that futher calls to /// `bind` may allow reuse of local addresses. For IPv4 sockets this means that a socket may /// bind even when there’s a socket already listening on this port. - pub reuse_address: bool, + pub fn with_reuse_address(mut self) -> Self { + self.reuse_address = true; + self + } /// Set value for the `SO_REUSEPORT` option on this socket. This indicates that further calls /// to `bind` may allow reuse of local addresses. For IPv4 sockets this means that a socket may /// bind even when there’s a socket already listening on this port. This option is always-on on /// Windows and cannot be configured. - pub reuse_port: bool, + pub fn with_reuse_port(mut self) -> Self { + self.reuse_port = true; + self + } } impl Default for UdpConnectConfig { @@ -70,26 +89,45 @@ impl Default for UdpConnectConfig { #[derive(Clone, PartialEq, Eq, Hash, Debug, Default)] pub struct UdpListenConfig { + send_broadcasts: bool, + receive_broadcasts: bool, + reuse_address: bool, + reuse_port: bool, +} + +impl UdpListenConfig { /// Enables the socket capabilities to send broadcast messages when the listening socket is /// also used for sending with /// [`Endpoint::from_listener`](crate::network::Endpoint::from_listener). - pub send_broadcasts: bool, + pub fn with_send_broadcasts(mut self) -> Self { + self.send_broadcasts = true; + self + } /// On Windows, when listening on a specific IP address, the sockets also receives /// corresponding subnet broadcasts and global broadcasts ([`std::net::Ipv4Addr::BROADCAST`]) /// received on the interface matching the IP. When this option is set, message-io mimics this /// behavior on Linux. - pub receive_broadcasts: bool, + pub fn with_receive_broadcasts(mut self) -> Self { + self.receive_broadcasts = true; + self + } /// Set value for the `SO_REUSEADDR` option on this socket. This indicates that futher calls to /// `bind` may allow reuse of local addresses. - pub reuse_address: bool, + pub fn with_reuse_address(mut self) -> Self { + self.reuse_address = true; + self + } /// Set value for the `SO_REUSEPORT` option on this socket. This indicates that further calls /// to `bind` may allow reuse of local addresses. For IPv4 sockets this means that a socket may /// bind even when there’s a socket already listening on this port. This option is always-on /// on Windows and cannot be configured. - pub reuse_port: bool, + pub fn with_reuse_port(mut self) -> Self { + self.reuse_port = true; + self + } } pub(crate) struct UdpAdapter; diff --git a/src/network.rs b/src/network.rs index 78326ba..1b5eafd 100644 --- a/src/network.rs +++ b/src/network.rs @@ -126,7 +126,7 @@ impl NetworkController { /// let (handler, listener) = node::split(); /// handler.signals().send_with_timer((), std::time::Duration::from_secs(1)); /// - /// let config = UdpConnectConfig { broadcast: true, ..Default::default() }; + /// let config = UdpConnectConfig::default().with_broadcast(); /// let addr = "255.255.255.255:7777"; /// let (conn_endpoint, _) = handler.network().connect_with(TransportConnect::Udp(config), addr).unwrap(); /// // The socket could not be able to send yet. @@ -226,7 +226,7 @@ impl NetworkController { /// let (handler, listener) = node::split(); /// handler.signals().send_with_timer((), std::time::Duration::from_secs(1)); /// - /// let config = UdpConnectConfig { broadcast: true, ..Default::default() }; + /// let config = UdpConnectConfig::default().with_broadcast(); /// let addr = "255.255.255.255:7777"; /// match handler.network().connect_sync_with(TransportConnect::Udp(config), addr) { /// Ok((endpoint, _)) => {