]>
code.octet-stream.net Git - netwatcher/blob - src/watch_mac.rs
3 use block2
::{Block
, RcBlock
};
6 use crate::{Error
, List
, Update
};
8 // The "objc2" project aims to provide bindings for all frameworks but Network.framework
9 // isn't ready yet so let's kick it old-school
12 struct NwPathMonitor([u8; 0]);
13 type NwPathMonitorT
= *mut NwPathMonitor
;
15 struct NwPath([u8; 0]);
17 struct DispatchQueue([u8; 0]);
18 type DispatchQueueT
= *mut DispatchQueue
;
19 const QOS_CLASS_BACKGROUND
: usize = 0x09;
21 unsafe impl objc2
::Encode
for NwPath
{
22 const ENCODING
: Encoding
= usize::ENCODING
;
25 #[link(name = "Network", kind = "framework")]
27 fn nw_path_monitor_create() -> NwPathMonitorT
;
28 fn nw_path_monitor_set_update_handler(
29 monitor
: NwPathMonitorT
,
30 update_handler
: &Block
<dyn
Fn(NwPath
)>,
32 fn nw_path_monitor_set_queue(monitor
: NwPathMonitorT
, queue
: DispatchQueueT
);
33 fn nw_path_monitor_start(monitor
: NwPathMonitorT
);
34 fn nw_path_monitor_cancel(monitor
: NwPathMonitorT
);
36 fn dispatch_get_global_queue(identifier
: usize, flag
: usize) -> DispatchQueueT
;
39 pub(crate) struct WatchHandle
{
40 path_monitor
: NwPathMonitorT
,
43 impl Drop
for WatchHandle
{
45 unsafe { nw_path_monitor_cancel(self.path_monitor
); }
49 struct CallbackState
{
51 callback
: Box
<dyn
FnMut(Update
) + Send
+ '
static>,
54 pub(crate) fn watch_interfaces
<F
: FnMut(Update
) + Send
+ '
static>(
56 ) -> Result
<WatchHandle
, Error
> {
57 let state
= CallbackState
{
58 prev_list
: List
::default(),
59 callback
: Box
::new(callback
),
61 // Blocks are Fn, not FnMut
62 let state
= Mutex
::new(state
);
63 let block
= RcBlock
::new(move |_
: NwPath
| {
64 let mut state
= state
.lock().unwrap
();
65 let Ok(new_list
) = crate::list
::list_interfaces() else {
68 if new_list
== state
.prev_list
{
72 interfaces
: new_list
.0.clone(),
73 diff
: new_list
.diff_from(&state
.prev_list
),
75 (state
.callback
)(update
);
76 state
.prev_list
= new_list
;
78 let path_monitor
: NwPathMonitorT
;
80 let queue
= dispatch_get_global_queue(QOS_CLASS_BACKGROUND
, 0);
81 path_monitor
= nw_path_monitor_create();
82 nw_path_monitor_set_update_handler(path_monitor
, &block
);
83 nw_path_monitor_set_queue(path_monitor
, queue
);
84 nw_path_monitor_start(path_monitor
);