]>
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
11 struct nw_path_monitor
;
12 type nw_path_monitor_t
= *mut nw_path_monitor
;
14 struct dispatch_queue
;
15 type dispatch_queue_t
= *mut dispatch_queue
;
16 const QOS_CLASS_BACKGROUND
: usize = 0x09;
18 unsafe impl objc2
::Encode
for nw_path
{
19 const ENCODING
: Encoding
= usize::ENCODING
;
22 #[link(name = "Network", kind = "framework")]
24 fn nw_path_monitor_create() -> nw_path_monitor_t
;
25 fn nw_path_monitor_set_update_handler(
26 monitor
: nw_path_monitor_t
,
27 update_handler
: &Block
<dyn
Fn(nw_path
)>,
29 fn nw_path_monitor_set_queue(monitor
: nw_path_monitor_t
, queue
: dispatch_queue_t
);
30 fn nw_path_monitor_start(monitor
: nw_path_monitor_t
);
31 fn nw_path_monitor_cancel(monitor
: nw_path_monitor_t
);
33 fn dispatch_get_global_queue(identifier
: usize, flag
: usize) -> dispatch_queue_t
;
36 pub(crate) struct WatchHandle
{
37 path_monitor
: nw_path_monitor_t
,
40 impl Drop
for WatchHandle
{
42 unsafe { nw_path_monitor_cancel(self.path_monitor
); }
46 struct CallbackState
{
48 callback
: Box
<dyn
FnMut(Update
) + Send
+ '
static>,
51 pub(crate) fn watch_interfaces
<F
: FnMut(Update
) + Send
+ '
static>(
53 ) -> Result
<WatchHandle
, Error
> {
54 let state
= CallbackState
{
55 prev_list
: List
::default(),
56 callback
: Box
::new(callback
),
58 // Blocks are Fn, not FnMut
59 let state
= Mutex
::new(state
);
60 let block
= RcBlock
::new(move |_
: nw_path
| {
61 let mut state
= state
.lock().unwrap
();
62 let Ok(new_list
) = crate::list
::list_interfaces() else {
65 if new_list
== state
.prev_list
{
69 interfaces
: new_list
.0.clone(),
70 diff
: new_list
.diff_from(&state
.prev_list
),
72 (state
.callback
)(update
);
73 state
.prev_list
= new_list
;
75 let path_monitor
: nw_path_monitor_t
;
77 let queue
= dispatch_get_global_queue(QOS_CLASS_BACKGROUND
, 0);
78 path_monitor
= nw_path_monitor_create();
79 nw_path_monitor_set_update_handler(path_monitor
, &block
);
80 nw_path_monitor_set_queue(path_monitor
, queue
);
81 nw_path_monitor_start(path_monitor
);