mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-26 05:45:20 +00:00
tor by default, small (#564)
* feat(tor): Tor-by-default scaffold and integration - Add TorManager with static/dlopen start, torrc generation, SOCKS probe - Add TorURLSession; route Nostr/Web fetches via SOCKS proxy - Add chat system messages for Tor status; show progress (macOS) and ready - Disable ControlPort bootstrap monitor on iOS; keep it on macOS - Make Tor waits non-blocking; avoid main-actor stalls on startup - Queue & flush Nostr subscriptions on relay connect; skip duplicates - Always rewrite torrc at launch to fix iOS container path mismatches - Link libz; add project wiring for tor-nolzma.xcframework - Minor fixes: SOCKS probe resumeOnce guard, entitlement for network.server (macOS) * iOS: deterministic Tor recovery + 100% gating; BLE-first; session rebuild - Restart/wake Tor on foreground via ControlPort (ACTIVE/SHUTDOWN), avoid restarts during bootstrap; add NWPathMonitor to trigger checks - Use NWConnection control polling for GETINFO; remove blocking CFStream readers to avoid QoS inversions; compute readiness from SOCKS + 100% - Rebuild TorURLSession on resume; reset Nostr connections to rebind - Gate all internet after full bootstrap; keep BLE mesh startup fast - Fix Swift 6 capture issues; hop UI updates to @MainActor - Remove Tor progress spam; persist initial "starting tor..." system message * UI: show Tor system messages only in geohash channels (not mesh) - Gate "starting tor..." and readiness/timeout messages to geohash view - Add helper addGeohashOnlySystemMessage() to avoid posting to mesh timeline - Persist system messages in geohash backing store via addPublicSystemMessage() * Relays: treat repeated -1011 handshake failures as permanent; skip reconnects - Classify NSURLErrorBadServerResponse as permanent and stop retrying - Filter permanently-failed relays from subscribe/connect attempts - Avoid reconnect scheduling for permanently failed relays * Embed Tor via tor_api; deterministic restart + Nostr gating; add Tor notifications - Run Tor via tor_api in a dedicated thread with OwningControllerFD - Cleanly stop Tor on background; restart on .active (single instance) - Avoid fallback to tor_main/dlopen; add is-running check to prevent duplicates - Fix argv lifetime in C glue to avoid strcmp crash on start - Gate Nostr connect/subscribe/send until Tor is fully ready - Rebuild URLSession + reset relays after Tor readiness (scene-based) - Remove TorDidBecomeReady double-reset and appDidBecomeActive resubscribe - Add TorWillRestart/TorDidBecomeReady notifications and chat system messages - Debounce path-change restarts; ACTIVE poke first; coalesce subs; cancel stale reconnect timers - Project: add CTorHost.c and TorNotifications.swift to targets; fix libz.tbd path * Defer Nostr setup logs until Tor is ready; fix subscribe coalescing and reconnect generation - Move "Connecting to Nostr relays" log after awaitReady() - Log "Queuing subscription" when Tor not ready; only coalesce when handler exists - Clear coalescer on unsubscribe - Cancel stale reconnect timers using connectionGeneration - Remove app-level TorDidBecomeReady reset to avoid duplicate reconnects - Debounce path-change restarts * Gate Nostr init/subscription logs until Tor is ready - ChatViewModel: await Tor readiness before initializing Nostr and logging - Only log GeoDM subscription when Tor is ready to avoid early noise * Make Nostr connect single-sourced; defer DM subscription until connected - Remove duplicate connect call from ChatViewModel; let scene-based flow connect - Setup DM subscription once on first connection via sink - Reduce early subscription send/cancel noise after Tor restarts * On launch, queue Nostr subscriptions without initiating connects; let centralized connect handle it - In subscribe(), if no connections exist, just list relays and queue subs - Avoids early send/cancel churn before connect() runs post-Tor-ready * Always queue subscriptions and flush on connection; avoid immediate sends - Prevents early send/cancel churn at launch and during reconnects - If relays are already connected, flush immediately; otherwise pending until connected * UI: scope Tor restart messages to geohash channels; skip initial foreground restart on cold launch to avoid confusing system message in #mesh * geo: disable background sampling + notifications\n- Gate sampling to foreground only (beginGeohashSampling, watchers)\n- Suppress geohash activity notifications unless app is active\n- Stop sampling explicitly on background scene phase * Update BitchatApp.swift Co-authored-by: asmo <asmogo@protonmail.com> * Update BitchatApp.swift Co-authored-by: asmo <asmogo@protonmail.com> * Update BitchatApp.swift Co-authored-by: asmo <asmogo@protonmail.com> * Update bitchat/BitchatApp.swift Co-authored-by: asmo <asmogo@protonmail.com> * Update bitchat/BitchatApp.swift Co-authored-by: asmo <asmogo@protonmail.com> * fix(iOS App): resolve merge artifacts in scenePhase handler\n- Remove duplicate didEnterBackground state\n- Fix switch/if braces and logic for foreground restart gating --------- Co-authored-by: jack <jackjackbits@users.noreply.github.com> Co-authored-by: asmo <asmogo@protonmail.com>
This commit is contained in:
@@ -15,6 +15,9 @@ struct BitchatApp: App {
|
||||
#if os(iOS)
|
||||
@Environment(\.scenePhase) var scenePhase
|
||||
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
|
||||
// Skip the very first .active-triggered Tor restart on cold launch
|
||||
@State private var didHandleInitialActive: Bool = false
|
||||
@State private var didEnterBackground: Bool = false
|
||||
#elseif os(macOS)
|
||||
@NSApplicationDelegateAdaptor(MacAppDelegate.self) var appDelegate
|
||||
#endif
|
||||
@@ -43,6 +46,8 @@ struct BitchatApp: App {
|
||||
#elseif os(macOS)
|
||||
appDelegate.chatViewModel = chatViewModel
|
||||
#endif
|
||||
// Spin up Tor early; all internet will gate on Tor 100%
|
||||
TorManager.shared.startIfNeeded()
|
||||
// Check for shared content
|
||||
checkForSharedContent()
|
||||
}
|
||||
@@ -54,10 +59,37 @@ struct BitchatApp: App {
|
||||
switch newPhase {
|
||||
case .background:
|
||||
// Keep BLE mesh running in background; BLEService adapts scanning automatically
|
||||
break
|
||||
// Optionally nudge Tor to dormant to save power
|
||||
TorManager.shared.setAppForeground(false)
|
||||
TorManager.shared.goDormantOnBackground()
|
||||
// Stop geohash sampling while backgrounded
|
||||
Task { @MainActor in
|
||||
chatViewModel.endGeohashSampling()
|
||||
}
|
||||
// Proactively disconnect Nostr to avoid spurious socket errors while Tor is down
|
||||
NostrRelayManager.shared.disconnect()
|
||||
didEnterBackground = true
|
||||
case .active:
|
||||
// Restart services when becoming active
|
||||
chatViewModel.meshService.startServices()
|
||||
TorManager.shared.setAppForeground(true)
|
||||
// On initial cold launch, Tor was just started in onAppear.
|
||||
// Skip the deterministic restart the first time we become active.
|
||||
if didHandleInitialActive && didEnterBackground {
|
||||
TorManager.shared.ensureRunningOnForeground()
|
||||
} else {
|
||||
didHandleInitialActive = true
|
||||
}
|
||||
didEnterBackground = false
|
||||
Task.detached {
|
||||
let _ = await TorManager.shared.awaitReady(timeout: 60)
|
||||
await MainActor.run {
|
||||
// Rebuild proxied sessions to bind to the live Tor after readiness
|
||||
TorURLSession.shared.rebuild()
|
||||
// Reconnect Nostr via fresh sessions; will gate until Tor 100%
|
||||
NostrRelayManager.shared.resetAllConnections()
|
||||
}
|
||||
}
|
||||
checkForSharedContent()
|
||||
case .inactive:
|
||||
break
|
||||
|
||||
Reference in New Issue
Block a user