Skip to content

Commit

Permalink
Hide implementation details of ApplyTcpOptionsError
Browse files Browse the repository at this point in the history
  • Loading branch information
faern committed Apr 11, 2024
1 parent ccad8d9 commit f1f1225
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 18 deletions.
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ mod forward_traffic;
mod logging;
mod tcp_options;

pub use tcp_options::{ApplyTcpOptionsError, TcpOptions};
pub use tcp_options::{ApplyTcpOptionsError, ApplyTcpOptionsErrorKind, TcpOptions};

/// Helper trait for `Result<Infallible, E>` types. Allows getting the `E` value
/// in a way that is guaranteed to not panic.
Expand Down
69 changes: 52 additions & 17 deletions src/tcp_options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,27 +35,61 @@ pub struct TcpOptions {
pub nodelay: bool,
}

/// Represents a failure to apply socket options to the TCP socket.
#[derive(Debug)]
pub struct ApplyTcpOptionsError(ApplyTcpOptionsErrorInternal);

#[derive(Debug)]
enum ApplyTcpOptionsErrorInternal {
RecvBuffer(io::Error),
SendBuffer(io::Error),
#[cfg(target_os = "linux")]
Mark(nix::Error),
TcpNoDelay(io::Error),
}

/// A list specifying what failed when applying the TCP options.
#[derive(Debug, Copy, Clone)]
#[non_exhaustive]
pub enum ApplyTcpOptionsError {
pub enum ApplyTcpOptionsErrorKind {
/// Failed to get/set TCP_RCVBUF
RecvBuffer(io::Error),
RecvBuffer,

/// Failed to get/set TCP_SNDBUF
SendBuffer(io::Error),
SendBuffer,

/// Failed to get/set SO_MARK
#[cfg(target_os = "linux")]
Mark(nix::Error),
Mark,

/// Failed to get/set TCP_NODELAY
TcpNoDelay(io::Error),
TcpNoDelay,
}

impl ApplyTcpOptionsError {
/// Returns the kind of error that happened as an enum
pub fn kind(&self) -> ApplyTcpOptionsErrorKind {
use ApplyTcpOptionsErrorInternal::*;
match self.0 {
RecvBuffer(_) => ApplyTcpOptionsErrorKind::RecvBuffer,
SendBuffer(_) => ApplyTcpOptionsErrorKind::SendBuffer,
#[cfg(target_os = "linux")]
Mark(_) => ApplyTcpOptionsErrorKind::Mark,
TcpNoDelay(_) => ApplyTcpOptionsErrorKind::TcpNoDelay,
}
}
}

impl From<ApplyTcpOptionsErrorInternal> for ApplyTcpOptionsError {
fn from(value: ApplyTcpOptionsErrorInternal) -> Self {
Self(value)
}
}

impl fmt::Display for ApplyTcpOptionsError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use ApplyTcpOptionsError::*;
match self {
use ApplyTcpOptionsErrorInternal::*;
match self.0 {
RecvBuffer(_) => "Failed to get/set TCP_RCVBUF",
SendBuffer(_) => "Failed to get/set TCP_SNDBUF",
#[cfg(target_os = "linux")]
Expand All @@ -68,8 +102,8 @@ impl fmt::Display for ApplyTcpOptionsError {

impl std::error::Error for ApplyTcpOptionsError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
use ApplyTcpOptionsError::*;
match self {
use ApplyTcpOptionsErrorInternal::*;
match &self.0 {
RecvBuffer(e) => Some(e),
SendBuffer(e) => Some(e),
#[cfg(target_os = "linux")]
Expand All @@ -90,33 +124,34 @@ pub fn apply(socket: &TcpSocket, options: &TcpOptions) -> Result<(), ApplyTcpOpt
if let Some(recv_buffer_size) = options.recv_buffer_size {
socket
.set_recv_buffer_size(recv_buffer_size)
.map_err(ApplyTcpOptionsError::RecvBuffer)?;
.map_err(ApplyTcpOptionsErrorInternal::RecvBuffer)?;
}
log::debug!(
"SO_RCVBUF: {}",
socket
.recv_buffer_size()
.map_err(ApplyTcpOptionsError::RecvBuffer)?
.map_err(ApplyTcpOptionsErrorInternal::RecvBuffer)?
);
if let Some(send_buffer_size) = options.send_buffer_size {
socket
.set_send_buffer_size(send_buffer_size)
.map_err(ApplyTcpOptionsError::SendBuffer)?;
.map_err(ApplyTcpOptionsErrorInternal::SendBuffer)?;
}
log::debug!(
"SO_SNDBUF: {}",
socket
.send_buffer_size()
.map_err(ApplyTcpOptionsError::SendBuffer)?
.map_err(ApplyTcpOptionsErrorInternal::SendBuffer)?
);
#[cfg(target_os = "linux")]
{
if let Some(fwmark) = options.fwmark {
setsockopt(&socket, sockopt::Mark, &fwmark).map_err(ApplyTcpOptionsError::Mark)?;
setsockopt(&socket, sockopt::Mark, &fwmark)
.map_err(ApplyTcpOptionsErrorInternal::Mark)?;
}
log::debug!(
"SO_MARK: {}",
getsockopt(&socket, sockopt::Mark).map_err(ApplyTcpOptionsError::Mark)?
getsockopt(&socket, sockopt::Mark).map_err(ApplyTcpOptionsErrorInternal::Mark)?
);
}
Ok(())
Expand All @@ -128,12 +163,12 @@ pub fn set_nodelay(tcp_stream: &TcpStream, nodelay: bool) -> Result<(), ApplyTcp
// Configure TCP_NODELAY on the TCP stream
tcp_stream
.set_nodelay(nodelay)
.map_err(ApplyTcpOptionsError::TcpNoDelay)?;
.map_err(ApplyTcpOptionsErrorInternal::TcpNoDelay)?;
log::debug!(
"TCP_NODELAY: {}",
tcp_stream
.nodelay()
.map_err(ApplyTcpOptionsError::TcpNoDelay)?
.map_err(ApplyTcpOptionsErrorInternal::TcpNoDelay)?
);
Ok(())
}

0 comments on commit f1f1225

Please sign in to comment.