mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-08-22 07:16:03 +00:00
* Fix the three follow-ups from the #1486 review Three defects shipped with the censorship-resilience merge, all confirmed against main: 1. Source-manifest verification silently accepted added files. shasum -c checks only the files the manifest lists, and the Xcode project compiles every source file present in the tree — so a hostile mirror could pass verification by adding a file rather than modifying one. The manifest header and VERIFYING-A-BUILD.md now require the completeness check (git status --porcelain, or a path diff for tarballs) alongside the hash check. 2. A relay removed while Tor was bootstrapping reconnected anyway. dropRelays never subtracted from pendingTorConnectionURLs, and a custom relay passes the allow-list filter, so draining the pending queue resurrected a relay someone had explicitly deleted. 3. Turning Tor off mid-bootstrap read as 'network may be blocking tor'. shutdownCompletely left the detached 75s poll loop running, which then stamped bootstrapDidStall over the clean shutdown state; and the stall handler guarded on torEnforced, which is compile-time true in release, instead of the runtime preference. The poll loop is now generation-fenced (shutdown, dormancy, and restart each invalidate it) and the handler consults persistedTorPreference(). Both app-side fixes carry regression tests proven to fail pre-fix. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Address Codex review: ignored files and manifest placement git status --porcelain omits ignored paths, and .gitignore covers build/ — a planted bitchat/build/Evil.swift would compile via the synchronized group while the documented check stayed silent. The checkout check now uses --ignored. The downloaded manifest also has to live outside the tree, or it trips the completeness checks itself; the doc now says so and references it at /tmp throughout. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: jack <jackjackbits@users.noreply.github.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
92 lines
3.7 KiB
Swift
92 lines
3.7 KiB
Swift
//
|
|
// ChatViewModel+Tor.swift
|
|
// bitchat
|
|
//
|
|
// Tor lifecycle handling for ChatViewModel
|
|
//
|
|
|
|
import Foundation
|
|
import Combine
|
|
import Tor
|
|
|
|
extension ChatViewModel {
|
|
|
|
// MARK: - Tor notifications
|
|
|
|
@objc func handleTorWillStart() {
|
|
Task { @MainActor in
|
|
// A fresh attempt can stall again, so let it be reported again.
|
|
self.torStallAnnounced = false
|
|
if !self.torStatusAnnounced && TorManager.shared.torEnforced {
|
|
self.torStatusAnnounced = true
|
|
// Post only in geohash channels (queue if not active)
|
|
self.addGeohashOnlySystemMessage(
|
|
String(localized: "system.tor.starting", comment: "System message when Tor is starting")
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
@objc func handleTorWillRestart() {
|
|
Task { @MainActor in
|
|
self.torRestartPending = true
|
|
// Post only in geohash channels (queue if not active)
|
|
self.addGeohashOnlySystemMessage(
|
|
String(localized: "system.tor.restarting", comment: "System message when Tor is restarting")
|
|
)
|
|
}
|
|
}
|
|
|
|
@objc func handleTorDidBecomeReady() {
|
|
Task { @MainActor in
|
|
self.torStallAnnounced = false
|
|
// Only announce "restarted" if we actually restarted this session
|
|
if self.torRestartPending {
|
|
// Post only in geohash channels (queue if not active)
|
|
self.addGeohashOnlySystemMessage(
|
|
String(localized: "system.tor.restarted", comment: "System message when Tor has restarted")
|
|
)
|
|
self.torRestartPending = false
|
|
} else if TorManager.shared.torEnforced && !self.torInitialReadyAnnounced {
|
|
// Initial start completed
|
|
self.addGeohashOnlySystemMessage(
|
|
String(localized: "system.tor.started", comment: "System message when Tor has started")
|
|
)
|
|
self.torInitialReadyAnnounced = true
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Bootstrap spent its whole deadline without connecting. Say so rather
|
|
/// than leaving "starting tor…" on screen indefinitely: on a network that
|
|
/// blocks Tor this is the terminal state, and someone needs to know that
|
|
/// internet features are stalled while the mesh still works.
|
|
@objc func handleTorBootstrapDidStall() {
|
|
Task { @MainActor in
|
|
guard TorManager.shared.torEnforced else { return }
|
|
// torEnforced is a compile-time constant in release builds; the
|
|
// runtime preference is what says whether anyone is waiting on
|
|
// Tor. Turning Tor off mid-bootstrap must not read as blocking.
|
|
guard NetworkActivationService.persistedTorPreference() else { return }
|
|
guard !self.torStallAnnounced else { return }
|
|
self.torStallAnnounced = true
|
|
self.addGeohashOnlySystemMessage(
|
|
String(
|
|
localized: "system.tor.blocked",
|
|
defaultValue: "tor could not connect — this network may be blocking it. mesh messaging still works; location channels and internet delivery are paused until tor gets through.",
|
|
comment: "System message shown when Tor bootstrap runs out its deadline without connecting, which is what a network that blocks Tor looks like"
|
|
)
|
|
)
|
|
}
|
|
}
|
|
|
|
@objc func handleTorPreferenceChanged(_: Notification) {
|
|
Task { @MainActor in
|
|
self.torStatusAnnounced = false
|
|
self.torInitialReadyAnnounced = false
|
|
self.torRestartPending = false
|
|
self.torStallAnnounced = false
|
|
}
|
|
}
|
|
}
|