Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hide details of error implementation, to not make changes into breaking changes #57

Merged
merged 2 commits into from
Apr 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ Line wrap the file at 100 chars. Th


## [Unreleased]
### Changed
- Change the public API of `ApplyTcpOptionsError`. So this is a breaking change. This stops
exposing the internal details of the type which allows future changes to not be breaking.


## [0.4.0] - 2024-01-02
Expand Down
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(())
}
Loading