5 use windows
::Win32
::Foundation
::ERROR_INVALID_HANDLE
; 
   6 use windows
::Win32
::Foundation
::ERROR_INVALID_PARAMETER
; 
   7 use windows
::Win32
::Foundation
::ERROR_NOT_ENOUGH_MEMORY
; 
   8 use windows
::Win32
::Foundation
::NO_ERROR
; 
   9 use windows
::Win32
::NetworkManagement
::IpHelper
::CancelMibChangeNotify2
; 
  10 use windows
::Win32
::NetworkManagement
::IpHelper
::MIB_NOTIFICATION_TYPE
; 
  11 use windows
::Win32
::NetworkManagement
::IpHelper
::MIB_UNICASTIPADDRESS_ROW
; 
  13     Foundation
::{BOOLEAN
, HANDLE
}, 
  14     NetworkManagement
::IpHelper
::NotifyUnicastIpAddressChange
, 
  15     Networking
::WinSock
::AF_UNSPEC
, 
  22 pub struct WatchState 
{ 
  23     /// The last result that we captured, for diffing 
  26     cb
: Box
<dyn 
FnMut(Update
) + '
static>, 
  29 pub struct WatchHandle 
{ 
  31     _state
: Pin
<Box
<Mutex
<WatchState
>>>, 
  34 impl Drop 
for WatchHandle 
{ 
  37             let _ 
= CancelMibChangeNotify2(self.hnd
); 
  42 pub(crate) fn watch_interfaces
<F
: FnMut(Update
) + '
static>( 
  44 ) -> Result
<WatchHandle
, Error
> { 
  45     let null_list 
= List
::default(); 
  46     let prev_list 
= crate::list
::list_interfaces()?
; 
  48         interfaces
: prev_list
.0.clone(), 
  49         diff
: prev_list
.diff_from(&null_list
), 
  52     // TODO: Can wo do something about the race condition? 
  53     let state 
= Box
::pin(Mutex
::new(WatchState 
{ 
  55         cb
: Box
::new(callback
), 
  57     let state_ctx 
= &*state
.as_ref() as *const _ 
as *const c_void
; 
  59     let mut hnd 
= HANDLE
::default(); 
  61         NotifyUnicastIpAddressChange( 
  70         NO_ERROR 
=> Ok(WatchHandle 
{ hnd
, _state
: state 
}), 
  71         ERROR_INVALID_HANDLE 
=> Err(Error
::Internal
), 
  72         ERROR_INVALID_PARAMETER 
=> Err(Error
::Internal
), 
  73         ERROR_NOT_ENOUGH_MEMORY 
=> Err(Error
::Internal
), 
  74         _ 
=> Err(Error
::Internal
), // TODO: Use FormatMessage and get real error 
  78 unsafe extern "system" fn notif( 
  80     _row
: *const MIB_UNICASTIPADDRESS_ROW
, 
  81     _notification_type
: MIB_NOTIFICATION_TYPE
, 
  83     println
!("There was a change!"); 
  84     let Ok(new_list
) = crate::list
::list_interfaces() else { 
  85         println
!("Failed to get list of interfaces on change"); 
  88     let state_ptr 
= ctx 
as *const Mutex
<WatchState
>; 
  90         let state_guard 
= &mut *state_ptr
.as_ref().unwrap
().lock().unwrap
(); 
  91         if new_list 
== state_guard
.prev_list 
{ 
  92             // TODO: Hitting this a lot, is it true? 
  93             println
!("Interfaces seem to be the same, ignoring"); 
  97             interfaces
: new_list
.0.clone(), 
  98             diff
: new_list
.diff_from(&state_guard
.prev_list
), 
 100         (state_guard
.cb
)(update
); 
 101         state_guard
.prev_list 
= new_list
;