-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Open
Description
Hello,
I tried to build an application with the latest libp2p version 0.56
including quic
features on iOS, however, I have the below compiler errors, which seem to be related to the issue #5628 and #5679. I see that if-watch v3.2.1 was used in the compilation.
Undefined symbols for architecture arm64:
"_SCDynamicStoreCreateRunLoopSource", referenced from:
system_configuration::dynamic_store::SCDynamicStore::create_run_loop_source::hc606d8191d1eee96 in libapp.a[1330](system_configuration-ef8f09e6c16c7e34.system_configuration.a183a244f0552131-cgu.0.rcgu.o)
"_SCDynamicStoreCreateWithOptions", referenced from:
system_configuration::dynamic_store::SCDynamicStore::create::h7b8d644247fa5cbe in libapp.a[1330](system_configuration-ef8f09e6c16c7e34.system_configuration.a183a244f0552131-cgu.0.rcgu.o)
"_SCDynamicStoreSetNotificationKeys", referenced from:
std::sys::backtrace::__rust_begin_short_backtrace::h50d2f1a25ee701a8 in libapp.a[1329](if_watch-7a230dd48f870c3b.if_watch.56977769d1be1092-cgu.0.rcgu.o)
"_kSCDynamicStoreUseSessionKeys", referenced from:
system_configuration::dynamic_store::SCDynamicStoreBuilder$LT$T$GT$::create_store_options::h88a4075b4fa8049f in libapp.a[1329](if_watch-7a230dd48f870c3b.if_watch.56977769d1be1092-cgu.0.rcgu.o)
I am not experienced with iOS internals, but from the errors above I suspect that i.e. SCDynamicStore
does not exist in the iOS world.
I checked with Claude LLM the apple.rs
module in if-watch and it suggested to patch it this way (if it makes sense), practically using the fallback polling on iOS which is also described in the if-watch README.md file.
--- a/src/apple.rs
+++ b/src/apple.rs
@@ -1,11 +1,17 @@
use crate::{IfEvent, IpNet, Ipv4Net, Ipv6Net};
+#[cfg(target_os = "macos")]
use core_foundation::array::CFArray;
+#[cfg(target_os = "macos")]
use core_foundation::runloop::{kCFRunLoopCommonModes, CFRunLoop};
+#[cfg(target_os = "macos")]
use core_foundation::string::CFString;
use fnv::FnvHashSet;
use futures::channel::mpsc;
use futures::stream::{FusedStream, Stream};
use if_addrs::IfAddr;
use std::collections::VecDeque;
use std::io::Result;
use std::pin::Pin;
use std::task::{Context, Poll};
+#[cfg(target_os = "macos")]
use system_configuration::dynamic_store::{
SCDynamicStore, SCDynamicStoreBuilder, SCDynamicStoreCallBackContext,
};
@@ -40,7 +46,12 @@ pub struct IfWatcher {
impl IfWatcher {
pub fn new() -> Result<Self> {
let (tx, rx) = mpsc::channel(1);
- std::thread::spawn(|| background_task(tx));
+
+ #[cfg(target_os = "macos")]
+ std::thread::spawn(move || background_task_macos(tx));
+
+ #[cfg(not(target_os = "macos"))]
+ std::thread::spawn(move || background_task_ios(tx));
+
let mut watcher = Self {
addrs: Default::default(),
queue: Default::default(),
@@ -119,6 +130,7 @@ fn ifaddr_to_ipnet(addr: IfAddr) -> IpNet {
}
}
+#[cfg(target_os = "macos")]
fn callback(_store: SCDynamicStore, _changed_keys: CFArray<CFString>, info: &mut mpsc::Sender<()>) {
match info.try_send(()) {
Err(err) if err.is_disconnected() => CFRunLoop::get_current().stop(),
@@ -126,7 +138,8 @@ fn callback(_store: SCDynamicStore, _changed_keys: CFArray<CFString>, info: &mu
}
}
-fn background_task(tx: mpsc::Sender<()>) {
+#[cfg(target_os = "macos")]
+fn background_task_macos(tx: mpsc::Sender<()>) {
let store = SCDynamicStoreBuilder::new("global-network-watcher")
.callback_context(SCDynamicStoreCallBackContext {
callout: callback,
@@ -140,4 +153,24 @@ fn background_task(tx: mpsc::Sender<()>) {
let source = store.create_run_loop_source();
let run_loop = CFRunLoop::get_current();
run_loop.add_source(&source, unsafe { kCFRunLoopCommonModes });
CFRunLoop::run_current();
-}
\ No newline at end of file
+}
+
+#[cfg(not(target_os = "macos"))]
+fn background_task_ios(mut tx: mpsc::Sender<()>) {
+ // On iOS, tvOS, and watchOS, we use a polling approach
+ // Poll every 2 seconds for network interface changes
+ loop {
+ std::thread::sleep(std::time::Duration::from_secs(2));
+
+ // Send a notification to trigger a resync
+ match tx.try_send(()) {
+ Ok(_) => {},
+ Err(err) => {
+ if err.is_disconnected() {
+ // Receiver has been dropped, exit the thread
+ break;
+ }
+ // If the channel is full, skip this notification
+ }
+ }
+ }
+}
Any feedback appreciated! Thanks
Metadata
Metadata
Assignees
Labels
No labels