From 388a30e8d092a5e054c1b9078f03d50f3c2be2b1 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Fri, 31 Jan 2025 14:01:10 +0100 Subject: [PATCH 1/7] feat(portmapper): only use concrete errors --- Cargo.lock | 1 - portmapper/Cargo.toml | 1 - portmapper/src/lib.rs | 97 ++++++++++++++++++++++++--------------- portmapper/src/mapping.rs | 32 +++++++++---- portmapper/src/nat_pmp.rs | 43 +++++++++++++---- portmapper/src/pcp.rs | 57 +++++++++++++++++------ portmapper/src/upnp.rs | 35 +++++++++++--- 7 files changed, 187 insertions(+), 79 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 06ba50d..ef06499 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1137,7 +1137,6 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" name = "portmapper" version = "0.3.1" dependencies = [ - "anyhow", "base64", "bytes", "derive_more", diff --git a/portmapper/Cargo.toml b/portmapper/Cargo.toml index a7ae2c6..371b041 100644 --- a/portmapper/Cargo.toml +++ b/portmapper/Cargo.toml @@ -16,7 +16,6 @@ rust-version = "1.81" workspace = true [dependencies] -anyhow = { version = "1" } base64 = "0.22.1" bytes = "1.7" derive_more = { version = "1.0.0", features = ["debug", "display", "from", "try_into", "deref"] } diff --git a/portmapper/src/lib.rs b/portmapper/src/lib.rs index 708d572..767f2c3 100644 --- a/portmapper/src/lib.rs +++ b/portmapper/src/lib.rs @@ -6,7 +6,6 @@ use std::{ time::{Duration, Instant}, }; -use anyhow::{anyhow, Result}; use current_mapping::CurrentMapping; use futures_lite::StreamExt; use iroh_metrics::inc; @@ -67,6 +66,29 @@ impl ProbeOutput { } } +#[derive(Debug, thiserror::Error, Clone)] +pub enum ProbeError { + #[error("Mapping channel is full")] + ChannelFull, + #[error("Mapping channel is closed")] + ChannelClosed, + #[error("No gateway found for probe")] + NoGateway, + #[error("gateway found is ipv6, ignoring")] + Ipv6Gateway, + #[error("Join is_panic: {is_panic}, is_cancelled: {is_cancelled}")] + Join { is_panic: bool, is_cancelled: bool }, +} + +impl From for ProbeError { + fn from(value: tokio::task::JoinError) -> Self { + Self::Join { + is_panic: value.is_panic(), + is_cancelled: value.is_cancelled(), + } + } +} + #[derive(derive_more::Debug)] enum Message { /// Attempt to get a mapping if the local port is set but there is no mapping. @@ -84,7 +106,7 @@ enum Message { Probe { /// Sender side to communicate the result of the probe. #[debug("_")] - result_tx: oneshot::Sender>, + result_tx: oneshot::Sender>, }, } @@ -120,7 +142,7 @@ pub struct Client { /// Channel used to communicate with the port mapping service. service_tx: mpsc::Sender, /// A handle to the service that will cancel the spawned task once the client is dropped. - _service_handle: std::sync::Arc>>, + _service_handle: std::sync::Arc>, } impl Default for Client { @@ -150,7 +172,7 @@ impl Client { /// Request a probe to the port mapping protocols. /// /// Returns the [`oneshot::Receiver`] used to obtain the result of the probe. - pub fn probe(&self) -> oneshot::Receiver> { + pub fn probe(&self) -> oneshot::Receiver> { let (result_tx, result_rx) = oneshot::channel(); if let Err(e) = self.service_tx.try_send(Message::Probe { result_tx }) { @@ -158,15 +180,15 @@ impl Client { // recover the sender and return the error there let (result_tx, e) = match e { - Full(Message::Probe { result_tx }) => (result_tx, "Port mapping channel full"), - Closed(Message::Probe { result_tx }) => (result_tx, "Port mapping channel closed"), + Full(Message::Probe { result_tx }) => (result_tx, ProbeError::ChannelFull), + Closed(Message::Probe { result_tx }) => (result_tx, ProbeError::ChannelClosed), Full(_) | Closed(_) => unreachable!("Sent value is a probe."), }; // sender was just created. If it's dropped we have two send error and are likely // shutting down // NOTE: second Err is infallible match due to being the sent value - if let Err(Err(e)) = result_tx.send(Err(e.into())) { + if let Err(Err(e)) = result_tx.send(Err(e)) { trace!("Failed to request probe: {e}") } } @@ -382,7 +404,7 @@ impl Probe { } // mainly to make clippy happy -type ProbeResult = Result; +type ProbeResult = Result; /// A port mapping client. #[derive(Debug)] @@ -402,7 +424,7 @@ pub struct Service { /// /// This task will be cancelled if a request to set the local port arrives before it's /// finished. - mapping_task: Option>>, + mapping_task: Option>>, /// Task probing the necessary protocols. /// /// Requests for a probe that arrive while this task is still in progress will receive the same @@ -446,7 +468,7 @@ impl Service { } } - async fn run(mut self) -> Result<()> { + async fn run(mut self) { debug!("portmap starting"); loop { tokio::select! { @@ -468,17 +490,13 @@ impl Service { self.mapping_task = None; // there isn't really a way to react to a join error here. Flatten it to make // it easier to work with - let result = match mapping_result { - Ok(result) => result, - Err(join_err) => Err(anyhow!("Failed to obtain a result {join_err}")) - }; - self.on_mapping_result(result); + self.on_mapping_result(mapping_result); } probe_result = util::MaybeFuture{ inner: self.probing_task.as_mut().map(|(fut, _rec)| fut) } => { trace!("tick: probe ready"); // retrieve the receivers and clear the task let receivers = self.probing_task.take().expect("is some").1; - let probe_result = probe_result.map_err(|join_err| anyhow!("Failed to obtain a result {join_err}")); + let probe_result = probe_result.map_err(Into::into); self.on_probe_result(probe_result, receivers); } Some(event) = self.current_mapping.next() => { @@ -492,37 +510,40 @@ impl Service { } } } - Ok(()) } fn on_probe_result( &mut self, - result: Result, + result: Result, receivers: Vec>, ) { - let result = match result { - Err(e) => Err(e.to_string()), - Ok(probe) => { - self.full_probe.update(probe); - // TODO(@divma): the gateway of the current mapping could have changed. Tailscale - // still assumes the current mapping is valid/active and will return it even after - // this - let output = self.full_probe.output(); - trace!(?output, "probe output"); - Ok(output) - } - }; + let result = result.map(|probe| { + self.full_probe.update(probe); + // TODO(@divma): the gateway of the current mapping could have changed. Tailscale + // still assumes the current mapping is valid/active and will return it even after + // this + let output = self.full_probe.output(); + trace!(?output, "probe output"); + output + }); for tx in receivers { // ignore the error. If the receiver is no longer there we don't really care let _ = tx.send(result.clone()); } } - fn on_mapping_result(&mut self, result: Result) { + fn on_mapping_result( + &mut self, + result: Result, tokio::task::JoinError>, + ) { match result { - Ok(mapping) => { + Ok(Ok(mapping)) => { self.current_mapping.update(Some(mapping)); } + Ok(Err(e)) => { + debug!("failed to get a port mapping {e}"); + inc!(Metrics, mapping_failures); + } Err(e) => { debug!("failed to get a port mapping {e}"); inc!(Metrics, mapping_failures); @@ -622,6 +643,7 @@ impl Service { .as_ref() .map(|(gateway, _last_seen)| gateway.clone()); let task = mapping::Mapping::new_upnp(local_ip, local_port, gateway, external_port); + Some(AbortOnDropHandle::new(tokio::spawn( task.instrument(info_span!("upnp")), ))) @@ -629,6 +651,7 @@ impl Service { // if no service is available and the default fallback (upnp) is disabled, try pcp // first let task = mapping::Mapping::new_pcp(local_ip, local_port, gateway, external_addr); + Some(AbortOnDropHandle::new(tokio::spawn( task.instrument(info_span!("pcp")), ))) @@ -651,7 +674,7 @@ impl Service { /// If there is a task getting a probe, the receiver will be added with any other waiting for a /// result. If no probe is underway, a result can be returned immediately if it's still /// considered valid. Otherwise, a new probe task will be started. - fn probe_request(&mut self, result_tx: oneshot::Sender>) { + fn probe_request(&mut self, result_tx: oneshot::Sender>) { match self.probing_task.as_mut() { Some((_task_handle, receivers)) => receivers.push(result_tx), None => { @@ -667,7 +690,7 @@ impl Service { Err(e) => { // there is no guarantee this will be displayed, so log it anyway debug!("could not start probe: {e}"); - let _ = result_tx.send(Err(e.to_string())); + let _ = result_tx.send(Err(e)); return; } }; @@ -689,9 +712,9 @@ impl Service { } /// Gets the local ip and gateway address for port mapping. -fn ip_and_gateway() -> Result<(Ipv4Addr, Ipv4Addr)> { +fn ip_and_gateway() -> Result<(Ipv4Addr, Ipv4Addr), ProbeError> { let Some(HomeRouter { gateway, my_ip }) = HomeRouter::new() else { - anyhow::bail!("no gateway found for probe"); + return Err(ProbeError::NoGateway); }; let local_ip = match my_ip { @@ -707,7 +730,7 @@ fn ip_and_gateway() -> Result<(Ipv4Addr, Ipv4Addr)> { }; let std::net::IpAddr::V4(gateway) = gateway else { - anyhow::bail!("gateway found is ipv6, ignoring"); + return Err(ProbeError::Ipv6Gateway); }; Ok((local_ip, gateway)) diff --git a/portmapper/src/mapping.rs b/portmapper/src/mapping.rs index fc612a5..7ced912 100644 --- a/portmapper/src/mapping.rs +++ b/portmapper/src/mapping.rs @@ -2,8 +2,6 @@ use std::{net::Ipv4Addr, num::NonZeroU16, time::Duration}; -use anyhow::Result; - use super::{nat_pmp, pcp, upnp}; pub(super) trait PortMapped: std::fmt::Debug + Unpin { @@ -23,6 +21,18 @@ pub enum Mapping { NatPmp(nat_pmp::Mapping), } +/// Mapping error. +#[derive(Debug, thiserror::Error)] +#[non_exhaustive] +pub enum Error { + #[error("PCP mapping failed: {0}")] + Pcp(#[from] pcp::Error), + #[error("NAT-PMP mapping failed: {0}")] + NatPmp(#[from] nat_pmp::Error), + #[error("UPnP mapping failed: {0}")] + Upnp(#[from] upnp::Error), +} + impl Mapping { /// Create a new PCP mapping. pub(crate) async fn new_pcp( @@ -30,10 +40,11 @@ impl Mapping { local_port: NonZeroU16, gateway: Ipv4Addr, external_addr: Option<(Ipv4Addr, NonZeroU16)>, - ) -> Result { + ) -> Result { pcp::Mapping::new(local_ip, local_port, gateway, external_addr) .await .map(Self::Pcp) + .map_err(Into::into) } /// Create a new NAT-PMP mapping. @@ -42,7 +53,7 @@ impl Mapping { local_port: NonZeroU16, gateway: Ipv4Addr, external_addr: Option<(Ipv4Addr, NonZeroU16)>, - ) -> Result { + ) -> Result { nat_pmp::Mapping::new( local_ip, local_port, @@ -51,6 +62,7 @@ impl Mapping { ) .await .map(Self::NatPmp) + .map_err(Into::into) } /// Create a new UPnP mapping. @@ -59,19 +71,21 @@ impl Mapping { local_port: NonZeroU16, gateway: Option, external_port: Option, - ) -> Result { + ) -> Result { upnp::Mapping::new(local_ip, local_port, gateway, external_port) .await .map(Self::Upnp) + .map_err(Into::into) } /// Release the mapping. - pub(crate) async fn release(self) -> Result<()> { + pub(crate) async fn release(self) -> Result<(), Error> { match self { - Mapping::Upnp(m) => m.release().await, - Mapping::Pcp(m) => m.release().await, - Mapping::NatPmp(m) => m.release().await, + Mapping::Upnp(m) => m.release().await?, + Mapping::Pcp(m) => m.release().await?, + Mapping::NatPmp(m) => m.release().await?, } + Ok(()) } } diff --git a/portmapper/src/nat_pmp.rs b/portmapper/src/nat_pmp.rs index b859729..48813b5 100644 --- a/portmapper/src/nat_pmp.rs +++ b/portmapper/src/nat_pmp.rs @@ -31,6 +31,19 @@ pub struct Mapping { lifetime_seconds: u32, } +#[derive(Debug, thiserror::Error)] +#[non_exhaustive] +pub enum Error { + #[error("server returned unexpected response for mapping request")] + UnexpectedServerResponse, + #[error("received 0 port from server as external port")] + ZeroExternalPort, + #[error("IO: {0}")] + Io(#[from] std::io::Error), + #[error("Protocol: {0}")] + Protocol(#[from] protocol::Error), +} + impl super::mapping::PortMapped for Mapping { fn external(&self) -> (Ipv4Addr, NonZeroU16) { (self.external_addr, self.external_port) @@ -48,7 +61,7 @@ impl Mapping { local_port: NonZeroU16, gateway: Ipv4Addr, external_port: Option, - ) -> anyhow::Result { + ) -> Result { // create the socket and send the request let socket = UdpSocket::bind_full((local_ip, 0))?; socket.connect((gateway, protocol::SERVER_PORT).into())?; @@ -64,7 +77,11 @@ impl Mapping { // wait for the response and decode it let mut buffer = vec![0; Response::MAX_SIZE]; - let read = tokio::time::timeout(RECV_TIMEOUT, socket.recv(&mut buffer)).await??; + let read = tokio::time::timeout(RECV_TIMEOUT, socket.recv(&mut buffer)) + .await + .map_err(|_| { + std::io::Error::new(std::io::ErrorKind::TimedOut, "read timeout".to_string()) + })??; let response = Response::decode(&buffer[..read])?; let (external_port, lifetime_seconds) = match response { @@ -75,12 +92,12 @@ impl Mapping { external_port, lifetime_seconds, } if private_port == Into::::into(local_port) => (external_port, lifetime_seconds), - _ => anyhow::bail!("server returned unexpected response for mapping request"), + _ => return Err(Error::UnexpectedServerResponse), }; let external_port = external_port .try_into() - .map_err(|_| anyhow::anyhow!("received 0 port from server as external port"))?; + .map_err(|_| Error::ZeroExternalPort)?; // now send the second request to get the external address let req = Request::ExternalAddress; @@ -88,7 +105,11 @@ impl Mapping { // wait for the response and decode it let mut buffer = vec![0; Response::MAX_SIZE]; - let read = tokio::time::timeout(RECV_TIMEOUT, socket.recv(&mut buffer)).await??; + let read = tokio::time::timeout(RECV_TIMEOUT, socket.recv(&mut buffer)) + .await + .map_err(|_| { + std::io::Error::new(std::io::ErrorKind::TimedOut, "read timeout".to_string()) + })??; let response = Response::decode(&buffer[..read])?; let external_addr = match response { @@ -96,7 +117,7 @@ impl Mapping { epoch_time: _, public_ip, } => public_ip, - _ => anyhow::bail!("server returned unexpected response for mapping request"), + _ => return Err(Error::UnexpectedServerResponse), }; Ok(Mapping { @@ -110,7 +131,7 @@ impl Mapping { } /// Releases the mapping. - pub(crate) async fn release(self) -> anyhow::Result<()> { + pub(crate) async fn release(self) -> Result<(), Error> { // A client requests explicit deletion of a mapping by sending a message to the NAT gateway // requesting the mapping, with the Requested Lifetime in Seconds set to zero. The // Suggested External Port MUST be set to zero by the client on sending @@ -164,7 +185,7 @@ pub async fn probe_available(local_ip: Ipv4Addr, gateway: Ipv4Addr) -> bool { async fn probe_available_fallible( local_ip: Ipv4Addr, gateway: Ipv4Addr, -) -> anyhow::Result { +) -> Result { // create the socket and send the request let socket = UdpSocket::bind_full((local_ip, 0))?; socket.connect((gateway, protocol::SERVER_PORT).into())?; @@ -173,7 +194,11 @@ async fn probe_available_fallible( // wait for the response and decode it let mut buffer = vec![0; Response::MAX_SIZE]; - let read = tokio::time::timeout(RECV_TIMEOUT, socket.recv(&mut buffer)).await??; + let read = tokio::time::timeout(RECV_TIMEOUT, socket.recv(&mut buffer)) + .await + .map_err(|_| { + std::io::Error::new(std::io::ErrorKind::TimedOut, "read timeout".to_string()) + })??; let response = Response::decode(&buffer[..read])?; Ok(response) diff --git a/portmapper/src/pcp.rs b/portmapper/src/pcp.rs index 2019bc3..5fb9d05 100644 --- a/portmapper/src/pcp.rs +++ b/portmapper/src/pcp.rs @@ -34,6 +34,29 @@ pub struct Mapping { nonce: [u8; 12], } +#[derive(Debug, thiserror::Error)] +#[non_exhaustive] +pub enum Error { + #[error("received nonce does not match sent request")] + NonceMissmatch, + #[error("received mapping is not for UDP")] + ProtocolMissmatch, + #[error("received mapping is for a local port that does not match the requested one")] + PortMissmatch, + #[error("received 0 external port for mapping")] + ZeroExternalPort, + #[error("received external address is not ipv4")] + NotIpv4, + #[error("received an announce response for a map request")] + InvalidAnnounce, + #[error("IO: {0}")] + Io(#[from] std::io::Error), + #[error("Protocol: {0}")] + Protocol(#[from] protocol::Error), + #[error("Protocol Decode: {0}")] + ProtocolDecode(#[from] protocol::DecodeError), +} + impl super::mapping::PortMapped for Mapping { fn external(&self) -> (Ipv4Addr, NonZeroU16) { (self.external_address, self.external_port) @@ -51,7 +74,7 @@ impl Mapping { local_port: NonZeroU16, gateway: Ipv4Addr, preferred_external_address: Option<(Ipv4Addr, NonZeroU16)>, - ) -> anyhow::Result { + ) -> Result { // create the socket and send the request let socket = UdpSocket::bind_full((local_ip, 0))?; socket.connect((gateway, protocol::SERVER_PORT).into())?; @@ -77,7 +100,11 @@ impl Mapping { // wait for the response and decode it let mut buffer = vec![0; protocol::Response::MAX_SIZE]; - let read = tokio::time::timeout(RECV_TIMEOUT, socket.recv(&mut buffer)).await??; + let read = tokio::time::timeout(RECV_TIMEOUT, socket.recv(&mut buffer)) + .await + .map_err(|_| { + std::io::Error::new(std::io::ErrorKind::TimedOut, "read timeout".to_string()) + })??; let response = protocol::Response::decode(&buffer[..read])?; // verify that the response is correct and matches the request @@ -98,24 +125,22 @@ impl Mapping { } = map_data; if nonce != received_nonce { - anyhow::bail!("received nonce does not match sent request"); + return Err(Error::NonceMissmatch); } if protocol != protocol::MapProtocol::Udp { - anyhow::bail!("received mapping is not for UDP"); + return Err(Error::ProtocolMissmatch); } let sent_port: u16 = local_port.into(); if received_local_port != sent_port { - anyhow::bail!("received mapping is for a local port that does not match the requested one"); + return Err(Error::PortMissmatch); } let external_port = external_port .try_into() - .map_err(|_| anyhow::anyhow!("received 0 external port for mapping"))?; + .map_err(|_| Error::ZeroExternalPort)?; - let external_address = external_address - .to_ipv4_mapped() - .ok_or(anyhow::anyhow!("received external address is not ipv4"))?; + let external_address = external_address.to_ipv4_mapped().ok_or(Error::NotIpv4)?; Ok(Mapping { external_port, @@ -127,13 +152,11 @@ impl Mapping { gateway, }) } - protocol::OpcodeData::Announce => { - anyhow::bail!("received an announce response for a map request") - } + protocol::OpcodeData::Announce => Err(Error::InvalidAnnounce), } } - pub async fn release(self) -> anyhow::Result<()> { + pub async fn release(self) -> Result<(), Error> { let Mapping { nonce, local_ip, @@ -185,7 +208,7 @@ pub async fn probe_available(local_ip: Ipv4Addr, gateway: Ipv4Addr) -> bool { async fn probe_available_fallible( local_ip: Ipv4Addr, gateway: Ipv4Addr, -) -> anyhow::Result { +) -> Result { // create the socket and send the request let socket = UdpSocket::bind_full((local_ip, 0))?; socket.connect((gateway, protocol::SERVER_PORT).into())?; @@ -194,7 +217,11 @@ async fn probe_available_fallible( // wait for the response and decode it let mut buffer = vec![0; protocol::Response::MAX_SIZE]; - let read = tokio::time::timeout(RECV_TIMEOUT, socket.recv(&mut buffer)).await??; + let read = tokio::time::timeout(RECV_TIMEOUT, socket.recv(&mut buffer)) + .await + .map_err(|_| { + std::io::Error::new(std::io::ErrorKind::TimedOut, "read timeout".to_string()) + })??; let response = protocol::Response::decode(&buffer[..read])?; Ok(response) diff --git a/portmapper/src/upnp.rs b/portmapper/src/upnp.rs index 4960cea..9c6a87e 100644 --- a/portmapper/src/upnp.rs +++ b/portmapper/src/upnp.rs @@ -4,8 +4,7 @@ use std::{ time::Duration, }; -use anyhow::{anyhow, Result}; -use igd_next::aio as aigd; +use igd_next::{aio as aigd, AddAnyPortError, GetExternalIpError, RemovePortError, SearchError}; use iroh_metrics::inc; use tracing::debug; @@ -36,13 +35,32 @@ pub struct Mapping { external_port: NonZeroU16, } +#[derive(Debug, thiserror::Error)] +#[non_exhaustive] +pub enum Error { + #[error("Zero external port")] + ZeroExternalPort, + #[error("igd device's external ip is ipv6")] + NotIpv4, + #[error("Remove Port {0}")] + RemovePort(#[from] RemovePortError), + #[error("Search {0}")] + Search(#[from] SearchError), + #[error("Get external IP {0}")] + GetExternalIp(#[from] GetExternalIpError), + #[error("Add any port {0}")] + AddAnyPort(#[from] AddAnyPortError), + #[error("IO {0}")] + Io(#[from] std::io::Error), +} + impl Mapping { pub(crate) async fn new( local_addr: Ipv4Addr, port: NonZeroU16, gateway: Option, preferred_port: Option, - ) -> Result { + ) -> Result { let local_addr = SocketAddrV4::new(local_addr, port.into()); // search for a gateway if there is not one already @@ -57,11 +75,14 @@ impl Mapping { ..Default::default() }), ) - .await?? + .await + .map_err(|_| { + std::io::Error::new(std::io::ErrorKind::TimedOut, "read timeout".to_string()) + })?? }; let std::net::IpAddr::V4(external_ip) = gateway.get_external_ip().await? else { - return Err(anyhow!("igd device's external ip is ipv6")); + return Err(Error::NotIpv4); }; // if we are trying to get a specific external port, try this first. If this fails, default @@ -95,7 +116,7 @@ impl Mapping { ) .await? .try_into() - .map_err(|_| anyhow::anyhow!("upnp mapping got zero external port"))?; + .map_err(|_| Error::ZeroExternalPort)?; Ok(Mapping { gateway, @@ -109,7 +130,7 @@ impl Mapping { } /// Releases the mapping. - pub(crate) async fn release(self) -> Result<()> { + pub(crate) async fn release(self) -> Result<(), Error> { let Mapping { gateway, external_port, From 30773fc204bd51cbbeb54434f3b9373dd6431d31 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Fri, 31 Jan 2025 14:31:34 +0100 Subject: [PATCH 2/7] feat(netwatch): use concrete errors --- Cargo.lock | 485 +++++++++++++++++++---------- netwatch/Cargo.toml | 2 +- netwatch/src/interfaces/linux.rs | 40 ++- netwatch/src/interfaces/windows.rs | 12 +- netwatch/src/netmon.rs | 29 +- netwatch/src/netmon/actor.rs | 17 +- netwatch/src/netmon/android.rs | 7 +- netwatch/src/netmon/bsd.rs | 11 +- netwatch/src/netmon/linux.rs | 9 +- netwatch/src/netmon/windows.rs | 53 ++-- netwatch/src/udp.rs | 14 +- 11 files changed, 444 insertions(+), 235 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ef06499..406be6e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -34,19 +34,19 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.94" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" [[package]] name = "async-trait" -version = "0.1.83" +version = "0.1.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -84,7 +84,7 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -101,15 +101,15 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.6.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" [[package]] name = "bumpalo" -version = "3.16.0" +version = "3.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" [[package]] name = "byteorder" @@ -125,9 +125,9 @@ checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "cc" -version = "1.2.4" +version = "1.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9157bbaa6b165880c27a4293a474c91cdcf265cc68cc829bf10be0964a391caf" +checksum = "13208fcbb66eaeffe09b99fffbe1af420f00a7b35aa99ad683dfc1aa76145229" dependencies = [ "shlex", ] @@ -154,7 +154,7 @@ dependencies = [ "iana-time-zone", "num-traits", "serde", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -199,7 +199,7 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", "unicode-xid", ] @@ -211,7 +211,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -323,9 +323,9 @@ checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cef40d21ae2c515b51041df9ed313ed21e572df340ea58a922a0aefe7e8891a1" +checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532" dependencies = [ "fastrand", "futures-core", @@ -342,7 +342,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -472,9 +472,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.9.5" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" +checksum = "f2d708df4e7140240a16cd6ab0ab65c972d7433ab77819ea693fde9c43811e2a" [[package]] name = "httpdate" @@ -484,9 +484,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "1.5.2" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "256fb8d4bd6413123cc9d91832d78325c48ff41677595be797d90f42969beae0" +checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" dependencies = [ "bytes", "futures-channel", @@ -505,9 +505,9 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.3" +version = "0.27.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" dependencies = [ "futures-util", "http 1.2.0", @@ -678,7 +678,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -725,9 +725,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.7.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" dependencies = [ "equivalent", "hashbrown 0.15.2", @@ -735,9 +735,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.10.1" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] name = "iroh-metrics" @@ -753,17 +753,18 @@ dependencies = [ "reqwest", "serde", "struct_iterable", - "thiserror 2.0.7", + "thiserror 2.0.11", "tokio", "tracing", ] [[package]] name = "iroh-quinn-udp" -version = "0.5.5" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfcfc0abc2fdf8cf18a6c72893b7cbebeac2274a3b1306c1760c48c0e10ac5e0" +checksum = "c53afaa1049f7c83ea1331f5ebb9e6ebc5fdd69c468b7a22dd598b02c9bcc973" dependencies = [ + "cfg_aliases", "libc", "once_cell", "socket2", @@ -779,9 +780,9 @@ checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "js-sys" -version = "0.3.76" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ "once_cell", "wasm-bindgen", @@ -789,9 +790,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.168" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "litemap" @@ -811,9 +812,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.22" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" [[package]] name = "memchr" @@ -829,9 +830,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "miniz_oxide" -version = "0.8.0" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924" dependencies = [ "adler2", ] @@ -917,17 +918,16 @@ dependencies = [ [[package]] name = "netlink-proto" -version = "0.11.3" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b33524dc0968bfad349684447bfce6db937a9ac3332a1fe60c0c5a5ce63f21" +checksum = "72452e012c2f8d612410d89eea01e2d9b56205274abb35d53f60200b2ec41d60" dependencies = [ "bytes", "futures", "log", "netlink-packet-core", "netlink-sys", - "thiserror 1.0.69", - "tokio", + "thiserror 2.0.11", ] [[package]] @@ -947,7 +947,6 @@ dependencies = [ name = "netwatch" version = "0.3.0" dependencies = [ - "anyhow", "atomic-waker", "bytes", "derive_more", @@ -965,12 +964,13 @@ dependencies = [ "rtnetlink 0.14.1", "serde", "socket2", - "thiserror 2.0.7", + "testresult", + "thiserror 2.0.11", "time", "tokio", "tokio-util", "tracing", - "windows", + "windows 0.58.0", "wmi", ] @@ -991,7 +991,7 @@ version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.8.0", "cfg-if", "libc", ] @@ -1062,14 +1062,14 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] name = "object" -version = "0.36.5" +version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "memchr", ] @@ -1106,7 +1106,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -1123,9 +1123,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project-lite" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" @@ -1153,7 +1153,7 @@ dependencies = [ "serde", "smallvec", "socket2", - "thiserror 2.0.7", + "thiserror 2.0.11", "time", "tokio", "tokio-util", @@ -1187,9 +1187,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.92" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] @@ -1214,7 +1214,7 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -1230,7 +1230,7 @@ dependencies = [ "rustc-hash", "rustls", "socket2", - "thiserror 2.0.7", + "thiserror 2.0.11", "tokio", "tracing", ] @@ -1249,7 +1249,7 @@ dependencies = [ "rustls", "rustls-pki-types", "slab", - "thiserror 2.0.7", + "thiserror 2.0.11", "tinyvec", "tracing", "web-time", @@ -1257,9 +1257,9 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.8" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52cd4b1eff68bf27940dd39811292c49e007f4d0b4c357358dc9b0197be6b527" +checksum = "1c40286217b4ba3a71d644d752e6a0b71f13f1b6a2c5311acfcbe0c2418ed904" dependencies = [ "cfg_aliases", "libc", @@ -1271,9 +1271,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] @@ -1314,14 +1314,14 @@ version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.8.0", ] [[package]] name = "reqwest" -version = "0.12.9" +version = "0.12.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" +checksum = "43e734407157c3c2034e0258f5e4473ddb361b1e85f95a66690d67264d7cd1da" dependencies = [ "base64", "bytes", @@ -1350,6 +1350,7 @@ dependencies = [ "sync_wrapper", "tokio", "tokio-rustls", + "tower", "tower-service", "url", "wasm-bindgen", @@ -1424,9 +1425,9 @@ checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497" [[package]] name = "rustls" -version = "0.23.20" +version = "0.23.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5065c3f250cbd332cd894be57c40fa52387247659b14a2d6041d121547903b1b" +checksum = "9fb9263ab4eb695e42321db096e3b8fbd715a59b154d5c88d82db2175b681ba7" dependencies = [ "once_cell", "ring", @@ -1447,9 +1448,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" +checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" dependencies = [ "web-time", ] @@ -1465,11 +1466,17 @@ dependencies = [ "untrusted", ] +[[package]] +name = "rustversion" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" + [[package]] name = "ryu" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" [[package]] name = "scopeguard" @@ -1479,29 +1486,29 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.216" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.216" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] name = "serde_json" -version = "1.0.133" +version = "1.0.138" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" +checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" dependencies = [ "itoa", "memchr", @@ -1593,7 +1600,7 @@ dependencies = [ "proc-macro2", "quote", "struct_iterable_internal", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -1621,9 +1628,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.90" +version = "2.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" dependencies = [ "proc-macro2", "quote", @@ -1647,7 +1654,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -1656,7 +1663,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.8.0", "core-foundation", "system-configuration-sys", ] @@ -1671,6 +1678,12 @@ dependencies = [ "libc", ] +[[package]] +name = "testresult" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614b328ff036a4ef882c61570f72918f7e9c5bee1da33f8e7f91e01daee7e56c" + [[package]] name = "thiserror" version = "1.0.69" @@ -1682,11 +1695,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.7" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93605438cbd668185516ab499d589afb7ee1859ea3d5fc8f6b0755e1c7443767" +checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" dependencies = [ - "thiserror-impl 2.0.7", + "thiserror-impl 2.0.11", ] [[package]] @@ -1697,18 +1710,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] name = "thiserror-impl" -version = "2.0.7" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d8749b4531af2117677a5fcd12b1348a3fe2b81e36e61ffeac5c4aa3273e36" +checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -1742,9 +1755,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8" dependencies = [ "tinyvec_macros", ] @@ -1757,9 +1770,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.42.0" +version = "1.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" +checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" dependencies = [ "backtrace", "bytes", @@ -1774,13 +1787,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -1816,15 +1829,36 @@ checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" [[package]] name = "toml_edit" -version = "0.22.22" +version = "0.22.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +checksum = "02a8b472d1a3d7c18e2d61a489aee3453fd9031c33e4f55bd533f4a7adca1bee" dependencies = [ "indexmap", "toml_datetime", "winnow", ] +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + [[package]] name = "tower-service" version = "0.3.3" @@ -1851,7 +1885,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -1871,9 +1905,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "unicode-ident" -version = "1.0.14" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" +checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" [[package]] name = "unicode-xid" @@ -1928,34 +1962,35 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", "once_cell", + "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.49" +version = "0.4.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38176d9b44ea84e9184eff0bc34cc167ed044f816accfe5922e54d84cf48eca2" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" dependencies = [ "cfg-if", "js-sys", @@ -1966,9 +2001,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1976,28 +2011,31 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] name = "web-sys" -version = "0.3.76" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" dependencies = [ "js-sys", "wasm-bindgen", @@ -2015,9 +2053,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.26.7" +version = "0.26.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e" +checksum = "2210b291f7ea53617fbafcc4939f10914214ec15aace5ba62293a668f322c5c9" dependencies = [ "rustls-pki-types", ] @@ -2051,7 +2089,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" dependencies = [ "windows-core 0.58.0", - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f919aee0a93304be7f62e8e5027811bbba96bcb1de84d6618be56e43f8a32a1" +dependencies = [ + "windows-core 0.59.0", + "windows-targets 0.53.0", ] [[package]] @@ -2060,7 +2108,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -2069,11 +2117,24 @@ version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" dependencies = [ - "windows-implement", - "windows-interface", - "windows-result", - "windows-strings", - "windows-targets", + "windows-implement 0.58.0", + "windows-interface 0.58.0", + "windows-result 0.2.0", + "windows-strings 0.1.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "810ce18ed2112484b0d4e15d022e5f598113e220c53e373fb31e67e21670c1ce" +dependencies = [ + "windows-implement 0.59.0", + "windows-interface 0.59.0", + "windows-result 0.3.0", + "windows-strings 0.3.0", + "windows-targets 0.53.0", ] [[package]] @@ -2084,7 +2145,18 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", +] + +[[package]] +name = "windows-implement" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", ] [[package]] @@ -2095,7 +2167,18 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", +] + +[[package]] +name = "windows-interface" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb26fd936d991781ea39e87c3a27285081e3c0da5ca0fcbc02d368cc6f52ff01" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", ] [[package]] @@ -2104,9 +2187,9 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" dependencies = [ - "windows-result", - "windows-strings", - "windows-targets", + "windows-result 0.2.0", + "windows-strings 0.1.0", + "windows-targets 0.52.6", ] [[package]] @@ -2115,7 +2198,16 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d08106ce80268c4067c0571ca55a9b4e9516518eaa1a1fe9b37ca403ae1d1a34" +dependencies = [ + "windows-targets 0.53.0", ] [[package]] @@ -2124,8 +2216,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" dependencies = [ - "windows-result", - "windows-targets", + "windows-result 0.2.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b888f919960b42ea4e11c2f408fadb55f78a9f236d5eef084103c8ce52893491" +dependencies = [ + "windows-targets 0.53.0", ] [[package]] @@ -2134,7 +2235,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -2143,7 +2244,7 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -2152,14 +2253,30 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", ] [[package]] @@ -2168,70 +2285,118 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + [[package]] name = "winnow" -version = "0.6.20" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +checksum = "7e49d2d35d3fad69b39b94139037ecfb4f359f08958b9c11e7315ce770462419" dependencies = [ "memchr", ] [[package]] name = "wmi" -version = "0.14.2" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc47c0776cc6c00d2f7a874a0c846d94d45535936e5a1187693a24f23b4dd701" +checksum = "7787dacdd8e71cbc104658aade4009300777f9b5fda6a75f19145fedb8a18e71" dependencies = [ "chrono", "futures", "log", "serde", - "thiserror 2.0.7", - "windows", - "windows-core 0.58.0", + "thiserror 2.0.11", + "windows 0.59.0", + "windows-core 0.59.0", ] [[package]] @@ -2248,9 +2413,9 @@ checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" [[package]] name = "xml-rs" -version = "0.8.24" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea8b391c9a790b496184c29f7f93b9ed5b16abb306c05415b68bcc16e4d06432" +checksum = "c5b940ebc25896e71dd073bad2dbaa2abfe97b0a391415e22ad1326d9c54e3c4" [[package]] name = "xmltree" @@ -2281,7 +2446,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", "synstructure", ] @@ -2303,7 +2468,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -2323,7 +2488,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", "synstructure", ] @@ -2352,5 +2517,5 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] diff --git a/netwatch/Cargo.toml b/netwatch/Cargo.toml index 3ac2605..3dd98ab 100644 --- a/netwatch/Cargo.toml +++ b/netwatch/Cargo.toml @@ -16,7 +16,6 @@ rust-version = "1.81" workspace = true [dependencies] -anyhow = { version = "1" } atomic-waker = "1.1.2" bytes = "1.7" futures-lite = "2.5" @@ -63,6 +62,7 @@ serde = { version = "1", features = ["derive"] } derive_more = { version = "1.0.0", features = ["debug"] } [dev-dependencies] +testresult = "0.4.1" tokio = { version = "1", features = [ "io-util", "sync", diff --git a/netwatch/src/interfaces/linux.rs b/netwatch/src/interfaces/linux.rs index b7bc16f..3396108 100644 --- a/netwatch/src/interfaces/linux.rs +++ b/netwatch/src/interfaces/linux.rs @@ -1,6 +1,5 @@ //! Linux-specific network interfaces implementations. -use anyhow::{anyhow, Result}; #[cfg(not(target_os = "android"))] use futures_util::TryStreamExt; use tokio::{ @@ -10,6 +9,22 @@ use tokio::{ use super::DefaultRouteDetails; +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("IO {0}")] + Io(#[from] std::io::Error), + #[error("no netlink response")] + NoResponse, + #[error("interface not found")] + InterfaceNotFound, + #[error("iface field is missing")] + MissingIfaceField, + #[error("destination field is missing")] + MissingDestinationField, + #[error("mask field is missing")] + MissingMaskField, +} + pub async fn default_route() -> Option { let route = default_route_proc().await; if let Ok(route) = route { @@ -27,7 +42,7 @@ pub async fn default_route() -> Option { const PROC_NET_ROUTE_PATH: &str = "/proc/net/route"; -async fn default_route_proc() -> Result> { +async fn default_route_proc() -> Result, Error> { const ZERO_ADDR: &str = "00000000"; let file = File::open(PROC_NET_ROUTE_PATH).await?; @@ -50,9 +65,9 @@ async fn default_route_proc() -> Result> { continue; } let mut fields = line.split_ascii_whitespace(); - let iface = fields.next().ok_or(anyhow!("iface field missing"))?; - let destination = fields.next().ok_or(anyhow!("destination field missing"))?; - let mask = fields.nth(5).ok_or(anyhow!("mask field missing"))?; + let iface = fields.next().ok_or(Error::MissingIfaceField)?; + let destination = fields.next().ok_or(Error::MissingDestinationField)?; + let mask = fields.nth(5).ok_or(Error::MissingMaskField)?; // if iface.starts_with("tailscale") || iface.starts_with("wg") { // continue; // } @@ -70,7 +85,7 @@ async fn default_route_proc() -> Result> { /// We use this on Android where /proc/net/route can be missing entries or have locked-down /// permissions. See also comments in . #[cfg(target_os = "android")] -pub async fn default_route_android_ip_route() -> Result> { +pub async fn default_route_android_ip_route() -> Result, Error> { use tokio::process::Command; let output = Command::new("/system/bin/ip") @@ -104,7 +119,7 @@ fn parse_android_ip_route(stdout: &str) -> Option<&str> { } #[cfg(not(target_os = "android"))] -async fn default_route_netlink() -> Result> { +async fn default_route_netlink() -> Result, Error> { use tracing::{info_span, Instrument}; let (connection, handle, _receiver) = rtnetlink::new_connection()?; @@ -127,7 +142,7 @@ async fn default_route_netlink() -> Result> { async fn default_route_netlink_family( handle: &rtnetlink::Handle, family: rtnetlink::IpVersion, -) -> Result> { +) -> Result, Error> { use netlink_packet_route::route::RouteAttribute; let mut routes = handle.route().get(family).execute(); @@ -165,21 +180,18 @@ async fn default_route_netlink_family( } #[cfg(not(target_os = "android"))] -async fn iface_by_index(handle: &rtnetlink::Handle, index: u32) -> Result { +async fn iface_by_index(handle: &rtnetlink::Handle, index: u32) -> Result { use netlink_packet_route::link::LinkAttribute; let mut links = handle.link().get().match_index(index).execute(); - let msg = links - .try_next() - .await? - .ok_or_else(|| anyhow!("No netlink response"))?; + let msg = links.try_next().await?.ok_or_else(|| Error::NoResponse)?; for nla in msg.attributes { if let LinkAttribute::IfName(name) = nla { return Ok(name); } } - Err(anyhow!("Interface name not found")) + Err(Error::InterfaceNotFound) } #[cfg(test)] diff --git a/netwatch/src/interfaces/windows.rs b/netwatch/src/interfaces/windows.rs index 3b5480b..5215a88 100644 --- a/netwatch/src/interfaces/windows.rs +++ b/netwatch/src/interfaces/windows.rs @@ -13,7 +13,15 @@ struct Win32_IP4RouteTable { Name: String, } -fn get_default_route() -> anyhow::Result { +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("IO {0}")] + Io(#[from] std::io::Error), + #[error("not route found")] + NoRoute, +} + +fn get_default_route() -> Result { let com_con = COMLibrary::new()?; let wmi_con = WMIConnection::new(com_con)?; @@ -22,7 +30,7 @@ fn get_default_route() -> anyhow::Result { .filtered_query(&query)? .drain(..) .next() - .ok_or_else(|| anyhow::anyhow!("no route found"))?; + .ok_or(Error::NoRoute)?; Ok(DefaultRouteDetails { interface_name: route.Name, diff --git a/netwatch/src/netmon.rs b/netwatch/src/netmon.rs index 4901bec..12edeb1 100644 --- a/netwatch/src/netmon.rs +++ b/netwatch/src/netmon.rs @@ -1,6 +1,5 @@ //! Monitoring of networking interfaces and route changes. -use anyhow::Result; use futures_lite::future::Boxed as BoxFuture; use tokio::sync::{mpsc, oneshot}; use tokio_util::task::AbortOnDropHandle; @@ -32,9 +31,29 @@ pub struct Monitor { actor_tx: mpsc::Sender, } +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("channel closed")] + ChannelClosed, + #[error("actor {0}")] + Actor(#[from] actor::Error), +} + +impl From> for Error { + fn from(_value: mpsc::error::SendError) -> Self { + Self::ChannelClosed + } +} + +impl From for Error { + fn from(_value: oneshot::error::RecvError) -> Self { + Self::ChannelClosed + } +} + impl Monitor { /// Create a new monitor. - pub async fn new() -> Result { + pub async fn new() -> Result { let actor = Actor::new().await?; let actor_tx = actor.subscribe(); @@ -49,7 +68,7 @@ impl Monitor { } /// Subscribe to network changes. - pub async fn subscribe(&self, callback: F) -> Result + pub async fn subscribe(&self, callback: F) -> Result where F: Fn(bool) -> BoxFuture<()> + 'static + Sync + Send, { @@ -62,7 +81,7 @@ impl Monitor { } /// Unsubscribe a callback from network changes, using the provided token. - pub async fn unsubscribe(&self, token: CallbackToken) -> Result<()> { + pub async fn unsubscribe(&self, token: CallbackToken) -> Result<(), Error> { let (s, r) = oneshot::channel(); self.actor_tx .send(ActorMessage::Unsubscribe(token, s)) @@ -72,7 +91,7 @@ impl Monitor { } /// Potential change detected outside - pub async fn network_change(&self) -> Result<()> { + pub async fn network_change(&self) -> Result<(), Error> { self.actor_tx.send(ActorMessage::NetworkChange).await?; Ok(()) } diff --git a/netwatch/src/netmon/actor.rs b/netwatch/src/netmon/actor.rs index d18c9bd..8ddf748 100644 --- a/netwatch/src/netmon/actor.rs +++ b/netwatch/src/netmon/actor.rs @@ -4,11 +4,10 @@ use std::{ time::{Duration, Instant}, }; -use anyhow::Result; use futures_lite::future::Boxed as BoxFuture; use os::{is_interesting_interface, RouteMonitor}; use tokio::sync::{mpsc, oneshot}; -use tracing::{debug, trace, warn}; +use tracing::{debug, trace}; #[cfg(target_os = "android")] use super::android as os; @@ -29,6 +28,8 @@ use crate::{ ip::is_link_local, }; +pub(super) use os::Error; + /// The message sent by the OS specific monitors. #[derive(Debug, Copy, Clone)] pub(super) enum NetworkMessage { @@ -77,7 +78,7 @@ pub(super) enum ActorMessage { } impl Actor { - pub(super) async fn new() -> Result { + pub(super) async fn new() -> Result { let interface_state = State::new().await; let wall_time = Instant::now(); @@ -114,9 +115,7 @@ impl Actor { _ = debounce_interval.tick() => { if let Some(time_jumped) = last_event.take() { - if let Err(err) = self.handle_potential_change(time_jumped).await { - warn!("failed to handle network changes: {:?}", err); - }; + self.handle_potential_change(time_jumped).await; } } _ = wall_time_interval.tick() => { @@ -172,7 +171,7 @@ impl Actor { token } - async fn handle_potential_change(&mut self, time_jumped: bool) -> Result<()> { + async fn handle_potential_change(&mut self, time_jumped: bool) { trace!("potential change"); let new_state = State::new().await; @@ -181,7 +180,7 @@ impl Actor { // No major changes, continue on if !time_jumped && old_state == &new_state { debug!("no changes detected"); - return Ok(()); + return; } let is_major = is_major_change(old_state, &new_state) || time_jumped; @@ -197,8 +196,6 @@ impl Actor { cb(is_major).await; }); } - - Ok(()) } /// Reports whether wall time jumped more than 150% diff --git a/netwatch/src/netmon/android.rs b/netwatch/src/netmon/android.rs index 29c1da0..c9b48b3 100644 --- a/netwatch/src/netmon/android.rs +++ b/netwatch/src/netmon/android.rs @@ -1,15 +1,18 @@ -use anyhow::Result; use tokio::sync::mpsc; use super::actor::NetworkMessage; +#[derive(Debug, thiserror::Error)] +#[error("error")] +pub struct Error; + #[derive(Debug)] pub(super) struct RouteMonitor { _sender: mpsc::Sender, } impl RouteMonitor { - pub(super) fn new(_sender: mpsc::Sender) -> Result { + pub(super) fn new(_sender: mpsc::Sender) -> Result { // Very sad monitor. Android doesn't allow us to do this Ok(RouteMonitor { _sender }) diff --git a/netwatch/src/netmon/bsd.rs b/netwatch/src/netmon/bsd.rs index 61ebb34..21b9676 100644 --- a/netwatch/src/netmon/bsd.rs +++ b/netwatch/src/netmon/bsd.rs @@ -1,4 +1,3 @@ -use anyhow::Result; #[cfg(any(target_os = "macos", target_os = "ios"))] use libc::{RTAX_DST, RTAX_IFP}; use tokio::{io::AsyncReadExt, sync::mpsc}; @@ -15,7 +14,13 @@ pub(super) struct RouteMonitor { _handle: AbortOnDropHandle<()>, } -fn create_socket() -> Result { +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("IO {0}")] + Io(#[from] std::io::Error), +} + +fn create_socket() -> std::io::Result { let socket = socket2::Socket::new(libc::AF_ROUTE.into(), socket2::Type::RAW, None)?; socket.set_nonblocking(true)?; let socket_std: std::os::unix::net::UnixStream = socket.into(); @@ -27,7 +32,7 @@ fn create_socket() -> Result { } impl RouteMonitor { - pub(super) fn new(sender: mpsc::Sender) -> Result { + pub(super) fn new(sender: mpsc::Sender) -> Result { let mut socket = create_socket()?; let handle = tokio::task::spawn(async move { trace!("AF_ROUTE monitor started"); diff --git a/netwatch/src/netmon/linux.rs b/netwatch/src/netmon/linux.rs index 8aad4f6..2330249 100644 --- a/netwatch/src/netmon/linux.rs +++ b/netwatch/src/netmon/linux.rs @@ -3,7 +3,6 @@ use std::{ net::IpAddr, }; -use anyhow::Result; use futures_lite::StreamExt; use libc::{ RTNLGRP_IPV4_IFADDR, RTNLGRP_IPV4_ROUTE, RTNLGRP_IPV4_RULE, RTNLGRP_IPV6_IFADDR, @@ -32,6 +31,12 @@ impl Drop for RouteMonitor { } } +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("IO {0}")] + Io(#[from] std::io::Error), +} + const fn nl_mgrp(group: u32) -> u32 { if group > 31 { panic!("use netlink_sys::Socket::add_membership() for this group"); @@ -52,7 +57,7 @@ macro_rules! get_nla { } impl RouteMonitor { - pub(super) fn new(sender: mpsc::Sender) -> Result { + pub(super) fn new(sender: mpsc::Sender) -> Result { let (mut conn, mut _handle, mut messages) = new_connection()?; // Specify flags to listen on. diff --git a/netwatch/src/netmon/windows.rs b/netwatch/src/netmon/windows.rs index 95038a6..b61b593 100644 --- a/netwatch/src/netmon/windows.rs +++ b/netwatch/src/netmon/windows.rs @@ -1,11 +1,10 @@ use std::{collections::HashMap, sync::Arc}; -use anyhow::Result; use libc::c_void; use tokio::sync::mpsc; use tracing::{trace, warn}; use windows::Win32::{ - Foundation::{BOOLEAN, HANDLE as Handle}, + Foundation::{BOOLEAN, HANDLE as Handle, WIN32_ERROR}, NetworkManagement::IpHelper::{ MIB_IPFORWARD_ROW2, MIB_NOTIFICATION_TYPE, MIB_UNICASTIPADDRESS_ROW, }, @@ -19,8 +18,15 @@ pub(super) struct RouteMonitor { cb_handler: CallbackHandler, } +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("IO {0}")] + Io(#[from] std::io::Error), + NotifyUnicastIpAddressChange(#[from] WIN32_ERROR), +} + impl RouteMonitor { - pub(super) fn new(sender: mpsc::Sender) -> Result { + pub(super) fn new(sender: mpsc::Sender) -> Result { // Register two callbacks with the windows api let mut cb_handler = CallbackHandler::default(); @@ -100,19 +106,13 @@ impl CallbackHandler { let mut handle = Handle::default(); let cb = Arc::new(cb); unsafe { - let r = windows::Win32::NetworkManagement::IpHelper::NotifyUnicastIpAddressChange( + windows::Win32::NetworkManagement::IpHelper::NotifyUnicastIpAddressChange( windows::Win32::Networking::WinSock::AF_UNSPEC, Some(unicast_change_callback), Some(Arc::as_ptr(&cb) as *const c_void), // context BOOLEAN::from(false), // initial notification, &mut handle, - ); - if r.is_err() { - return Err(anyhow::anyhow!( - "NotifyUnicastIpAddressChange failed: {:?}", - r - )); - } + )?; } self.unicast_callbacks.insert(handle.0 as isize, cb); @@ -123,7 +123,7 @@ impl CallbackHandler { fn unregister_unicast_address_change_callback( &mut self, handle: UnicastCallbackHandle, - ) -> Result<()> { + ) -> Result<(), Error> { trace!("unregistering unicast callback"); if self .unicast_callbacks @@ -131,32 +131,28 @@ impl CallbackHandler { .is_some() { unsafe { - let r = - windows::Win32::NetworkManagement::IpHelper::CancelMibChangeNotify2(handle.0); - if r.is_err() { - return Err(anyhow::anyhow!("CancelMibChangeNotify2 failed: {:?}", r)); - } + windows::Win32::NetworkManagement::IpHelper::CancelMibChangeNotify2(handle.0)?; } } Ok(()) } - fn register_route_change_callback(&mut self, cb: RouteCallback) -> Result { + fn register_route_change_callback( + &mut self, + cb: RouteCallback, + ) -> Result { trace!("registering route change callback"); let mut handle = Handle::default(); let cb = Arc::new(cb); unsafe { - let r = windows::Win32::NetworkManagement::IpHelper::NotifyRouteChange2( + windows::Win32::NetworkManagement::IpHelper::NotifyRouteChange2( windows::Win32::Networking::WinSock::AF_UNSPEC, Some(route_change_callback), Arc::as_ptr(&cb) as *const c_void, // context BOOLEAN::from(false), // initial notification, &mut handle, - ); - if r.is_err() { - return Err(anyhow::anyhow!("NotifyRouteChange2 failed: {:?}", r)); - } + )?; } self.route_callbacks.insert(handle.0 as isize, cb); @@ -164,7 +160,10 @@ impl CallbackHandler { Ok(RouteCallbackHandle(handle)) } - fn unregister_route_change_callback(&mut self, handle: RouteCallbackHandle) -> Result<()> { + fn unregister_route_change_callback( + &mut self, + handle: RouteCallbackHandle, + ) -> Result<(), Error> { trace!("unregistering route callback"); if self .route_callbacks @@ -172,11 +171,7 @@ impl CallbackHandler { .is_some() { unsafe { - let r = - windows::Win32::NetworkManagement::IpHelper::CancelMibChangeNotify2(handle.0); - if r.is_err() { - return Err(anyhow::anyhow!("CancelMibChangeNotify2 failed: {:?}", r)); - } + windows::Win32::NetworkManagement::IpHelper::CancelMibChangeNotify2(handle.0)?; } } diff --git a/netwatch/src/udp.rs b/netwatch/src/udp.rs index 09fc0cf..4d1e8e4 100644 --- a/netwatch/src/udp.rs +++ b/netwatch/src/udp.rs @@ -814,12 +814,12 @@ impl Drop for UdpSocket { #[cfg(test)] mod tests { - use anyhow::Context; - use super::*; + use testresult::TestResult; + #[tokio::test] - async fn test_reconnect() -> anyhow::Result<()> { + async fn test_reconnect() -> TestResult { let (s_b, mut r_b) = tokio::sync::mpsc::channel(16); let handle_a = tokio::task::spawn(async move { let socket = UdpSocket::bind_local(IpFamily::V4, 0)?; @@ -843,7 +843,7 @@ mod tests { } } socket.close().await; - anyhow::Ok(()) + Ok::<_, testresult::TestError>(()) }); let socket = UdpSocket::bind_local(IpFamily::V4, 0)?; @@ -854,8 +854,8 @@ mod tests { let mut buffer = [0u8; 16]; for i in 0u8..100 { println!("round one - {}", i); - socket.send_to(&[i][..], addr).await.context("send")?; - let (count, from) = socket.recv_from(&mut buffer).await.context("recv")?; + socket.send_to(&[i][..], addr).await?; + let (count, from) = socket.recv_from(&mut buffer).await?; assert_eq!(addr, from); assert_eq!(count, 1); assert_eq!(buffer[0], i); @@ -876,7 +876,7 @@ mod tests { } #[tokio::test] - async fn test_udp_mark_broken() -> anyhow::Result<()> { + async fn test_udp_mark_broken() -> TestResult { let socket_a = UdpSocket::bind_local(IpFamily::V4, 0)?; let addr_a = socket_a.local_addr()?; println!("socket bound to {:?}", addr_a); From 5ce7a89d6608ad2e6f2c17e7b1f0f16ad8585b26 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Fri, 31 Jan 2025 14:38:09 +0100 Subject: [PATCH 3/7] fixups --- netwatch/src/interfaces/linux.rs | 2 ++ netwatch/src/netmon/actor.rs | 3 +-- netwatch/src/netmon/windows.rs | 15 ++++++++++----- netwatch/src/udp.rs | 4 ++-- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/netwatch/src/interfaces/linux.rs b/netwatch/src/interfaces/linux.rs index 3396108..b0d80ae 100644 --- a/netwatch/src/interfaces/linux.rs +++ b/netwatch/src/interfaces/linux.rs @@ -23,6 +23,8 @@ pub enum Error { MissingDestinationField, #[error("mask field is missing")] MissingMaskField, + #[error("netlink")] + Netlink(#[from] rtnetlink::Error), } pub async fn default_route() -> Option { diff --git a/netwatch/src/netmon/actor.rs b/netwatch/src/netmon/actor.rs index 8ddf748..58b1ed0 100644 --- a/netwatch/src/netmon/actor.rs +++ b/netwatch/src/netmon/actor.rs @@ -5,6 +5,7 @@ use std::{ }; use futures_lite::future::Boxed as BoxFuture; +pub(super) use os::Error; use os::{is_interesting_interface, RouteMonitor}; use tokio::sync::{mpsc, oneshot}; use tracing::{debug, trace}; @@ -28,8 +29,6 @@ use crate::{ ip::is_link_local, }; -pub(super) use os::Error; - /// The message sent by the OS specific monitors. #[derive(Debug, Copy, Clone)] pub(super) enum NetworkMessage { diff --git a/netwatch/src/netmon/windows.rs b/netwatch/src/netmon/windows.rs index b61b593..30cda5b 100644 --- a/netwatch/src/netmon/windows.rs +++ b/netwatch/src/netmon/windows.rs @@ -22,7 +22,8 @@ pub(super) struct RouteMonitor { pub enum Error { #[error("IO {0}")] Io(#[from] std::io::Error), - NotifyUnicastIpAddressChange(#[from] WIN32_ERROR), + #[error("win32: {0}")] + Win32(#[from] windows::Win32::Foundation::Error), } impl RouteMonitor { @@ -112,7 +113,8 @@ impl CallbackHandler { Some(Arc::as_ptr(&cb) as *const c_void), // context BOOLEAN::from(false), // initial notification, &mut handle, - )?; + ) + .ok()?; } self.unicast_callbacks.insert(handle.0 as isize, cb); @@ -131,7 +133,8 @@ impl CallbackHandler { .is_some() { unsafe { - windows::Win32::NetworkManagement::IpHelper::CancelMibChangeNotify2(handle.0)?; + windows::Win32::NetworkManagement::IpHelper::CancelMibChangeNotify2(handle.0) + .ok()?; } } @@ -152,7 +155,8 @@ impl CallbackHandler { Arc::as_ptr(&cb) as *const c_void, // context BOOLEAN::from(false), // initial notification, &mut handle, - )?; + ) + .ok()?; } self.route_callbacks.insert(handle.0 as isize, cb); @@ -171,7 +175,8 @@ impl CallbackHandler { .is_some() { unsafe { - windows::Win32::NetworkManagement::IpHelper::CancelMibChangeNotify2(handle.0)?; + windows::Win32::NetworkManagement::IpHelper::CancelMibChangeNotify2(handle.0) + .ok()?; } } diff --git a/netwatch/src/udp.rs b/netwatch/src/udp.rs index 4d1e8e4..b667389 100644 --- a/netwatch/src/udp.rs +++ b/netwatch/src/udp.rs @@ -814,10 +814,10 @@ impl Drop for UdpSocket { #[cfg(test)] mod tests { - use super::*; - use testresult::TestResult; + use super::*; + #[tokio::test] async fn test_reconnect() -> TestResult { let (s_b, mut r_b) = tokio::sync::mpsc::channel(16); From 8dd2cb9267aa0c8f358a7732102ddc92f6323118 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Fri, 31 Jan 2025 14:59:23 +0100 Subject: [PATCH 4/7] more fixes --- Cargo.lock | 1 + netwatch/Cargo.toml | 1 + netwatch/src/interfaces/linux.rs | 4 ++-- netwatch/src/netmon/windows.rs | 4 ++-- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 406be6e..091b7be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -971,6 +971,7 @@ dependencies = [ "tokio-util", "tracing", "windows 0.58.0", + "windows-result 0.3.0", "wmi", ] diff --git a/netwatch/Cargo.toml b/netwatch/Cargo.toml index 3dd98ab..5f2521c 100644 --- a/netwatch/Cargo.toml +++ b/netwatch/Cargo.toml @@ -58,6 +58,7 @@ rtnetlink = "=0.13.1" # pinned because of https://github.com/rust-netlink/rtnetl [target.'cfg(target_os = "windows")'.dependencies] wmi = "0.14" windows = { version = "0.58", features = ["Win32_NetworkManagement_IpHelper", "Win32_Foundation", "Win32_NetworkManagement_Ndis", "Win32_Networking_WinSock"] } +windows-result = "0.3" serde = { version = "1", features = ["derive"] } derive_more = { version = "1.0.0", features = ["debug"] } diff --git a/netwatch/src/interfaces/linux.rs b/netwatch/src/interfaces/linux.rs index b0d80ae..3483e69 100644 --- a/netwatch/src/interfaces/linux.rs +++ b/netwatch/src/interfaces/linux.rs @@ -95,7 +95,7 @@ pub async fn default_route_android_ip_route() -> Result Result Date: Fri, 31 Jan 2025 15:00:21 +0100 Subject: [PATCH 5/7] update windows dep --- Cargo.lock | 53 ++++----------------------------------------- netwatch/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 50 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 091b7be..eb79fd5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -970,7 +970,7 @@ dependencies = [ "tokio", "tokio-util", "tracing", - "windows 0.58.0", + "windows", "windows-result 0.3.0", "wmi", ] @@ -2083,16 +2083,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" -dependencies = [ - "windows-core 0.58.0", - "windows-targets 0.52.6", -] - [[package]] name = "windows" version = "0.59.0" @@ -2112,43 +2102,19 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-core" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" -dependencies = [ - "windows-implement 0.58.0", - "windows-interface 0.58.0", - "windows-result 0.2.0", - "windows-strings 0.1.0", - "windows-targets 0.52.6", -] - [[package]] name = "windows-core" version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "810ce18ed2112484b0d4e15d022e5f598113e220c53e373fb31e67e21670c1ce" dependencies = [ - "windows-implement 0.59.0", - "windows-interface 0.59.0", + "windows-implement", + "windows-interface", "windows-result 0.3.0", "windows-strings 0.3.0", "windows-targets 0.53.0", ] -[[package]] -name = "windows-implement" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.96", -] - [[package]] name = "windows-implement" version = "0.59.0" @@ -2160,17 +2126,6 @@ dependencies = [ "syn 2.0.96", ] -[[package]] -name = "windows-interface" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.96", -] - [[package]] name = "windows-interface" version = "0.59.0" @@ -2396,7 +2351,7 @@ dependencies = [ "log", "serde", "thiserror 2.0.11", - "windows 0.59.0", + "windows", "windows-core 0.59.0", ] diff --git a/netwatch/Cargo.toml b/netwatch/Cargo.toml index 5f2521c..f71208a 100644 --- a/netwatch/Cargo.toml +++ b/netwatch/Cargo.toml @@ -57,7 +57,7 @@ rtnetlink = "=0.13.1" # pinned because of https://github.com/rust-netlink/rtnetl [target.'cfg(target_os = "windows")'.dependencies] wmi = "0.14" -windows = { version = "0.58", features = ["Win32_NetworkManagement_IpHelper", "Win32_Foundation", "Win32_NetworkManagement_Ndis", "Win32_Networking_WinSock"] } +windows = { version = "0.59", features = ["Win32_NetworkManagement_IpHelper", "Win32_Foundation", "Win32_NetworkManagement_Ndis", "Win32_Networking_WinSock"] } windows-result = "0.3" serde = { version = "1", features = ["derive"] } derive_more = { version = "1.0.0", features = ["debug"] } From 5171e711f68221a58ba31f9d388916f646b632b3 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Fri, 31 Jan 2025 15:04:56 +0100 Subject: [PATCH 6/7] more fixes --- netwatch/src/interfaces/linux.rs | 2 ++ netwatch/src/interfaces/windows.rs | 2 ++ netwatch/src/netmon/windows.rs | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/netwatch/src/interfaces/linux.rs b/netwatch/src/interfaces/linux.rs index 3483e69..23296f7 100644 --- a/netwatch/src/interfaces/linux.rs +++ b/netwatch/src/interfaces/linux.rs @@ -13,8 +13,10 @@ use super::DefaultRouteDetails; pub enum Error { #[error("IO {0}")] Io(#[from] std::io::Error), + #[cfg(not(target_os = "android"))] #[error("no netlink response")] NoResponse, + #[cfg(not(target_os = "android"))] #[error("interface not found")] InterfaceNotFound, #[error("iface field is missing")] diff --git a/netwatch/src/interfaces/windows.rs b/netwatch/src/interfaces/windows.rs index 5215a88..e796824 100644 --- a/netwatch/src/interfaces/windows.rs +++ b/netwatch/src/interfaces/windows.rs @@ -19,6 +19,8 @@ pub enum Error { Io(#[from] std::io::Error), #[error("not route found")] NoRoute, + #[error("WMI {0}")] + Wmi(#[from] wmi::WMIError), } fn get_default_route() -> Result { diff --git a/netwatch/src/netmon/windows.rs b/netwatch/src/netmon/windows.rs index 19e88ef..050dcd0 100644 --- a/netwatch/src/netmon/windows.rs +++ b/netwatch/src/netmon/windows.rs @@ -102,7 +102,7 @@ impl CallbackHandler { fn register_unicast_address_change_callback( &mut self, cb: UnicastCallback, - ) -> Result { + ) -> Result { trace!("registering unicast callback"); let mut handle = Handle::default(); let cb = Arc::new(cb); From 7ee0b70163a20a4e8514d0fc80778c6edb319537 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Fri, 31 Jan 2025 17:15:25 +0100 Subject: [PATCH 7/7] no more BOOLEAN --- netwatch/src/netmon/windows.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/netwatch/src/netmon/windows.rs b/netwatch/src/netmon/windows.rs index 050dcd0..b2d06c1 100644 --- a/netwatch/src/netmon/windows.rs +++ b/netwatch/src/netmon/windows.rs @@ -4,7 +4,7 @@ use libc::c_void; use tokio::sync::mpsc; use tracing::{trace, warn}; use windows::Win32::{ - Foundation::{BOOLEAN, HANDLE as Handle}, + Foundation::HANDLE as Handle, NetworkManagement::IpHelper::{ MIB_IPFORWARD_ROW2, MIB_NOTIFICATION_TYPE, MIB_UNICASTIPADDRESS_ROW, }, @@ -111,7 +111,7 @@ impl CallbackHandler { windows::Win32::Networking::WinSock::AF_UNSPEC, Some(unicast_change_callback), Some(Arc::as_ptr(&cb) as *const c_void), // context - BOOLEAN::from(false), // initial notification, + false, // initial notification, &mut handle, ) .ok()?; @@ -153,7 +153,7 @@ impl CallbackHandler { windows::Win32::Networking::WinSock::AF_UNSPEC, Some(route_change_callback), Arc::as_ptr(&cb) as *const c_void, // context - BOOLEAN::from(false), // initial notification, + false, // initial notification, &mut handle, ) .ok()?;