From 4abfa61b20e567fdd69ac3ca47a9c218971a30ff Mon Sep 17 00:00:00 2001 From: Thomas Karpiniec Date: Fri, 14 Jun 2024 22:08:38 +0100 Subject: [PATCH 1/1] Make watching work on Linux --- src/lib.rs | 2 +- src/watch_linux.rs | 34 +++++++++++++++++++++++++--------- src/watch_win.rs | 4 ++-- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 7a8298e..69de586 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -145,6 +145,6 @@ pub fn list_interfaces() -> Result, Error> { /// /// The callback will fire once immediately with an initial interface list, and a diff as if /// there were originally no interfaces present. -pub fn watch_interfaces(callback: F) -> Result { +pub fn watch_interfaces(callback: F) -> Result { watch::watch_interfaces(callback).map(|handle| WatchHandle { _inner: handle }) } diff --git a/src/watch_linux.rs b/src/watch_linux.rs index 4e4049b..efc3842 100644 --- a/src/watch_linux.rs +++ b/src/watch_linux.rs @@ -1,7 +1,6 @@ use std::os::fd::AsRawFd; use std::os::fd::OwnedFd; -use nix::libc::nlmsghdr; use nix::libc::RTMGRP_IPV4_IFADDR; use nix::libc::RTMGRP_IPV6_IFADDR; use nix::libc::RTMGRP_LINK; @@ -16,21 +15,23 @@ use nix::sys::socket::SockProtocol; use nix::sys::socket::SockType; use crate::Error; +use crate::List; use crate::Update; pub(crate) struct WatchHandle { // PROBLEM: close() doesn't cancel recv() for a netlink socket + // SOLUTION: open a pipe() and use poll() inside the thread to watch for cancellation too sockfd: OwnedFd, } -pub(crate) fn watch_interfaces( +pub(crate) fn watch_interfaces( callback: F, ) -> Result { let sockfd = start_watcher_thread(callback)?; Ok(WatchHandle { sockfd }) } -fn start_watcher_thread(callback: F) -> Result { +fn start_watcher_thread(mut callback: F) -> Result { let sockfd = socket(AddressFamily::Netlink, SockType::Raw, SockFlag::empty(), Some(SockProtocol::NetlinkRoute)) .map_err(|_| Error::Internal)?; // TODO: proper errors let sa_nl = NetlinkAddr::new(0, (RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR) as u32); @@ -40,15 +41,30 @@ fn start_watcher_thread(callback: F) -> Result, + cb: Box, } pub(crate) struct WatchHandle { @@ -39,7 +39,7 @@ impl Drop for WatchHandle { } } -pub(crate) fn watch_interfaces( +pub(crate) fn watch_interfaces( callback: F, ) -> Result { let state = Box::pin(Mutex::new(WatchState { -- 2.39.5