]>
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 unsafe impl Send
for WatchHandle
{}
27 #[link(name = "Network", kind = "framework")]
29 fn nw_path_monitor_create() -> NwPathMonitorT
;
30 fn nw_path_monitor_set_update_handler(
31 monitor
: NwPathMonitorT
,
32 update_handler
: &Block
<dyn
Fn(NwPath
)>,
34 fn nw_path_monitor_set_queue(monitor
: NwPathMonitorT
, queue
: DispatchQueueT
);
35 fn nw_path_monitor_start(monitor
: NwPathMonitorT
);
36 fn nw_path_monitor_cancel(monitor
: NwPathMonitorT
);
38 fn dispatch_get_global_queue(identifier
: usize, flag
: usize) -> DispatchQueueT
;
41 pub(crate) struct WatchHandle
{
42 path_monitor
: NwPathMonitorT
,
45 impl Drop
for WatchHandle
{
48 nw_path_monitor_cancel(self.path_monitor
);
53 struct CallbackState
{
55 callback
: Box
<dyn
FnMut(Update
) + Send
+ '
static>,
58 pub(crate) fn watch_interfaces
<F
: FnMut(Update
) + Send
+ '
static>(
60 ) -> Result
<WatchHandle
, Error
> {
61 let state
= CallbackState
{
62 prev_list
: List
::default(),
63 callback
: Box
::new(callback
),
65 // Blocks are Fn, not FnMut
66 let state
= Mutex
::new(state
);
67 let block
= RcBlock
::new(move |_
: NwPath
| {
68 let mut state
= state
.lock().unwrap
();
69 let Ok(new_list
) = crate::list
::list_interfaces() else {
72 if new_list
== state
.prev_list
{
76 interfaces
: new_list
.0.clone(),
77 diff
: new_list
.diff_from(&state
.prev_list
),
79 (state
.callback
)(update
);
80 state
.prev_list
= new_list
;
82 let path_monitor
: NwPathMonitorT
;
84 let queue
= dispatch_get_global_queue(QOS_CLASS_BACKGROUND
, 0);
85 path_monitor
= nw_path_monitor_create();
86 nw_path_monitor_set_update_handler(path_monitor
, &block
);
87 nw_path_monitor_set_queue(path_monitor
, queue
);
88 nw_path_monitor_start(path_monitor
);
90 Ok(WatchHandle
{ path_monitor
})