build(ios): error on iOS with libp2p 0.56 using quic feature and if-watch 3.2.1
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 5.6k
- Forks
- 1.3k
- Avg merge
- 8h 47m
- Merged PRs (30d)
- 19
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
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with if-watch's src/apple.rs and README.md, then compare the iOS linker errors against the macOS-specific system_configuration code and the fallback behavior described in the issue. Verify the chosen change by building libp2p 0.56 with quic for iOS and confirming the unresolved SCDynamicStore symbols no longer occur.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- ios, rust
- Domain
- build-system, mobile-dev, networking
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100