diff --git a/Cargo.lock b/Cargo.lock index 572d9a1..3bd24c3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -464,18 +464,18 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "proc-macro2" -version = "1.0.67" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -528,6 +528,12 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + [[package]] name = "slab" version = "0.4.9" @@ -553,11 +559,33 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "strum" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a3417fc93d76740d974a01654a09777cb500428cc874ca9f45edfe0c4d4cd18" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn", +] + [[package]] name = "syn" -version = "2.0.37" +version = "2.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" +checksum = "11a6ae1e52eb25aab8f3fb9fca13be982a373b8f1157ca14b897a825ba4a2d35" dependencies = [ "proc-macro2", "quote", @@ -573,6 +601,26 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "thiserror" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tokio" version = "1.32.0" @@ -613,6 +661,8 @@ dependencies = [ "lazy_static", "log", "nix", + "strum", + "thiserror", "tokio", ] diff --git a/Cargo.toml b/Cargo.toml index c639698..963e81f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,6 +37,8 @@ lazy_static = "1.4.0" # pulled in when built as a library. env_logger = { version = "0.10.0", optional = true } cadence = { version = "1.0.0", optional = true } +thiserror = "1.0.58" +strum = { version = "0.26.2", features = ["derive"] } [target.'cfg(target_os = "linux")'.dependencies] nix = { version = "0.27.1", features = ["socket"] } diff --git a/src/lib.rs b/src/lib.rs index 6e95d3d..ab11191 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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` types. Allows getting the `E` value /// in a way that is guaranteed to not panic. diff --git a/src/tcp_options.rs b/src/tcp_options.rs index f58205c..3b3727a 100644 --- a/src/tcp_options.rs +++ b/src/tcp_options.rs @@ -1,6 +1,5 @@ #[cfg(target_os = "linux")] use nix::sys::socket::{getsockopt, setsockopt, sockopt}; -use std::fmt; use std::io; use std::time::Duration; use tokio::net::{TcpSocket, TcpStream}; @@ -36,80 +35,37 @@ pub struct TcpOptions { } /// Represents a failure to apply socket options to the TCP socket. -#[derive(Debug)] -pub struct ApplyTcpOptionsError(ApplyTcpOptionsErrorInternal); - -#[derive(Debug)] +#[derive(Debug, thiserror::Error)] +#[error(transparent)] +pub struct ApplyTcpOptionsError(#[from] ApplyTcpOptionsErrorInternal); + +#[derive(Debug, thiserror::Error, strum::EnumDiscriminants)] +#[strum_discriminants(vis(pub))] +#[strum_discriminants(name(ApplyTcpOptionsErrorKind))] +#[strum_discriminants(cfg_attr(all(), non_exhaustive))] // hacky way of bypassing strum limitations 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 ApplyTcpOptionsErrorKind { - /// Failed to get/set TCP_RCVBUF - RecvBuffer, + /// "Failed to get/set TCP_RCVBUF")] + #[error("Failed to get/set TCP_RCVBUF")] + RecvBuffer(#[source] io::Error), - /// Failed to get/set TCP_SNDBUF - SendBuffer, + /// "Failed to get/set TCP_SNDBUF")] + #[error("Failed to get/set TCP_SNDBUF")] + SendBuffer(#[source] io::Error), - /// Failed to get/set SO_MARK + /// "Failed to get/set SO_MARK")] #[cfg(target_os = "linux")] - Mark, + #[error("Failed to get/set SO_MARK")] + Mark(#[source] nix::Error), - /// Failed to get/set TCP_NODELAY - TcpNoDelay, + /// "Failed to get/set TCP_NODELAY")] + #[error("Failed to get/set TCP_NODELAY")] + TcpNoDelay(#[source] io::Error), } 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 for ApplyTcpOptionsError { - fn from(value: ApplyTcpOptionsErrorInternal) -> Self { - Self(value) - } -} - -impl fmt::Display for ApplyTcpOptionsError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - use ApplyTcpOptionsErrorInternal::*; - match self.0 { - RecvBuffer(_) => "Failed to get/set TCP_RCVBUF", - SendBuffer(_) => "Failed to get/set TCP_SNDBUF", - #[cfg(target_os = "linux")] - Mark(_) => "Failed to get/set SO_MARK", - TcpNoDelay(_) => "Failed to get/set TCP_NODELAY", - } - .fmt(f) - } -} - -impl std::error::Error for ApplyTcpOptionsError { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - use ApplyTcpOptionsErrorInternal::*; - match &self.0 { - RecvBuffer(e) => Some(e), - SendBuffer(e) => Some(e), - #[cfg(target_os = "linux")] - Mark(e) => Some(e), - TcpNoDelay(e) => Some(e), - } + ApplyTcpOptionsErrorKind::from(&self.0) } }