X-Git-Url: https://code.octet-stream.net/netwatcher/blobdiff_plain/cc3e849e9ff8568609f160d4bcdb83966ffdb6c5..HEAD:/src/watch_win.rs diff --git a/src/watch_win.rs b/src/watch_win.rs index c88cd7c..a247916 100644 --- a/src/watch_win.rs +++ b/src/watch_win.rs @@ -19,14 +19,14 @@ use crate::Error; use crate::List; use crate::Update; -pub struct WatchState { +struct WatchState { /// The last result that we captured, for diffing prev_list: List, /// User's callback - cb: Box, + cb: Box, } -pub struct WatchHandle { +pub(crate) struct WatchHandle { hnd: HANDLE, _state: Pin>>, } @@ -39,19 +39,11 @@ impl Drop for WatchHandle { } } -pub(crate) fn watch_interfaces( - mut callback: F, +pub(crate) fn watch_interfaces( + callback: F, ) -> Result { - let null_list = List::default(); - let prev_list = crate::list::list_interfaces()?; - callback(Update { - interfaces: prev_list.0.clone(), - diff: prev_list.diff_from(&null_list), - }); - - // TODO: Can wo do something about the race condition? let state = Box::pin(Mutex::new(WatchState { - prev_list, + prev_list: List::default(), cb: Box::new(callback), })); let state_ctx = &*state.as_ref() as *const _ as *const c_void; @@ -67,11 +59,16 @@ pub(crate) fn watch_interfaces( ) }; match res { - NO_ERROR => Ok(WatchHandle { hnd, _state: state }), - ERROR_INVALID_HANDLE => Err(Error::Internal), - ERROR_INVALID_PARAMETER => Err(Error::Internal), - ERROR_NOT_ENOUGH_MEMORY => Err(Error::Internal), - _ => Err(Error::Internal), // TODO: Use FormatMessage and get real error + NO_ERROR => { + // Trigger an initial update + handle_notif(&mut state.lock().unwrap(), crate::list::list_interfaces()?); + // Then return the handle + Ok(WatchHandle { hnd, _state: state }) + } + ERROR_INVALID_HANDLE => Err(Error::InvalidHandle), + ERROR_INVALID_PARAMETER => Err(Error::InvalidParameter), + ERROR_NOT_ENOUGH_MEMORY => Err(Error::NotEnoughMemory), + _ => Err(Error::UnexpectedWindowsResult(res.0)), } } @@ -80,24 +77,28 @@ unsafe extern "system" fn notif( _row: *const MIB_UNICASTIPADDRESS_ROW, _notification_type: MIB_NOTIFICATION_TYPE, ) { - println!("There was a change!"); - let Ok(new_list) = crate::list::list_interfaces() else { - println!("Failed to get list of interfaces on change"); - return; - }; let state_ptr = ctx as *const Mutex; unsafe { - let state_guard = &mut *state_ptr.as_ref().unwrap().lock().unwrap(); - if new_list == state_guard.prev_list { - // TODO: Hitting this a lot, is it true? - println!("Interfaces seem to be the same, ignoring"); + let state_guard = &mut *state_ptr + .as_ref() + .expect("callback ctx should never be null") + .lock() + .unwrap(); + let Ok(new_list) = crate::list::list_interfaces() else { return; - } - let update = Update { - interfaces: new_list.0.clone(), - diff: new_list.diff_from(&state_guard.prev_list), }; - (state_guard.cb)(update); - state_guard.prev_list = new_list; + handle_notif(state_guard, new_list); } } + +fn handle_notif(state: &mut WatchState, new_list: List) { + if new_list == state.prev_list { + return; + } + let update = Update { + interfaces: new_list.0.clone(), + diff: new_list.diff_from(&state.prev_list), + }; + (state.cb)(update); + state.prev_list = new_list; +}