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
;