]>
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
{
46 nw_path_monitor_cancel(self.path_monitor
);
51 struct CallbackState
{
53 callback
: Box
<dyn
FnMut(Update
) + Send
+ '
static>,
56 pub(crate) fn watch_interfaces
<F
: FnMut(Update
) + Send
+ '
static>(
58 ) -> Result
<WatchHandle
, Error
> {
59 let state
= CallbackState
{
60 prev_list
: List
::default(),
61 callback
: Box
::new(callback
),
63 // Blocks are Fn, not FnMut
64 let state
= Mutex
::new(state
);
65 let block
= RcBlock
::new(move |_
: NwPath
| {
66 let mut state
= state
.lock().unwrap
();
67 let Ok(new_list
) = crate::list
::list_interfaces() else {
70 if new_list
== state
.prev_list
{
74 interfaces
: new_list
.0.clone(),
75 diff
: new_list
.diff_from(&state
.prev_list
),
77 (state
.callback
)(update
);
78 state
.prev_list
= new_list
;
80 let path_monitor
: NwPathMonitorT
;
82 let queue
= dispatch_get_global_queue(QOS_CLASS_BACKGROUND
, 0);
83 path_monitor
= nw_path_monitor_create();
84 nw_path_monitor_set_update_handler(path_monitor
, &block
);
85 nw_path_monitor_set_queue(path_monitor
, queue
);
86 nw_path_monitor_start(path_monitor
);
88 Ok(WatchHandle
{ path_monitor
})