]> code.octet-stream.net Git - netwatcher/blobdiff - src/watch_win.rs
Fix typo in README
[netwatcher] / src / watch_win.rs
index c88cd7c1263b32bbfa87f8b9b06b702b4f7ed5bc..a247916b7aac1cf586f54d54a1526e1ad11cccdb 100644 (file)
@@ -19,14 +19,14 @@ use crate::Error;
 use crate::List;
 use crate::Update;
 
 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
     /// The last result that we captured, for diffing
     prev_list: List,
     /// User's callback
-    cb: Box<dyn FnMut(Update) + 'static>,
+    cb: Box<dyn FnMut(Update) + Send + 'static>,
 }
 
 }
 
-pub struct WatchHandle {
+pub(crate) struct WatchHandle {
     hnd: HANDLE,
     _state: Pin<Box<Mutex<WatchState>>>,
 }
     hnd: HANDLE,
     _state: Pin<Box<Mutex<WatchState>>>,
 }
@@ -39,19 +39,11 @@ impl Drop for WatchHandle {
     }
 }
 
     }
 }
 
-pub(crate) fn watch_interfaces<F: FnMut(Update) + 'static>(
-    mut callback: F,
+pub(crate) fn watch_interfaces<F: FnMut(Update) + Send + 'static>(
+    callback: F,
 ) -> Result<WatchHandle, Error> {
 ) -> Result<WatchHandle, Error> {
-    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 {
     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;
         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<F: FnMut(Update) + 'static>(
         )
     };
     match res {
         )
     };
     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,
 ) {
     _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<WatchState>;
     unsafe {
     let state_ptr = ctx as *const Mutex<WatchState>;
     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;
             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;
+}