Mesh robustness optimizations (#463)

* Mesh robustness: link-aware fragmentation, relay jitter, connection budget, adaptive scanning; fix BLE queue deadlock

- Link-aware fragmentation using per-link write/notify limits
- Directed fragments for one-to-one; exclude from relays
- Add relay jitter with cancel-on-duplicate to reduce floods
- Cap central links and rate-limit connect attempts with queue
- Foreground duty-cycled scanning when connected; continuous when isolated
- Fix deadlock by avoiding sync on BLE queue when already on it
- Silence Keychain var->let warnings

* Mesh: add relay jitter; dynamic RSSI threshold; candidate scoring/backoff; fix misplaced lines in BLEService extension

* macOS UI: restore mesh peer list when geohash feature is iOS-only by moving mesh list outside iOS switch (ContentView)

* ContentView: add macOS mesh peer list under #else to fix missing People section on macOS

* Refactor People section: extract MeshPeerList and GeohashPeopleList into separate views to reduce SwiftUI type-checking complexity; integrate in ContentView

* BLE: prevent re-fragmentation loops; UI: darker mesh blue + first-row spacing in peer list

* Mesh flood/battery: probabilistic relays, adaptive TTL caps, fragment pacing + scan pause, assembly cap; enable relayed DMs with direct-first then flood fallback.

* Refactor BLEService broadcast: split pad policy, encrypted/direct-first handler, and link-aware sender; simplify broadcastPacket to delegate by type.

* Extract relay decision into RelayController with RelayDecision; simplify handleReceivedPacket to use it.

* Move RelayController and RelayDecision into their own file under Services; keep BLEService leaner.

* UI: adjust mesh blue to a darker, less purple tone; apply consistently for count and #mesh badge.

* Project: include RelayController.swift in target and sync project file changes.

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
This commit is contained in:
jack
2025-08-20 16:27:49 +02:00
committed by GitHub
co-authored by jack
parent 3074fa0fcb
commit 496972dcc9
8 changed files with 755 additions and 398 deletions
+18
View File
@@ -23,6 +23,12 @@
047502AD2E55E8360083520F /* BinaryProtocolPaddingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 047502AB2E55E8360083520F /* BinaryProtocolPaddingTests.swift */; };
047502B02E55E8450083520F /* InputValidatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 047502AE2E55E8450083520F /* InputValidatorTests.swift */; };
047502B12E55E8450083520F /* InputValidatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 047502AE2E55E8450083520F /* InputValidatorTests.swift */; };
047502B42E55FED60083520F /* MeshPeerList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 047502B32E55FED60083520F /* MeshPeerList.swift */; };
047502B52E55FED60083520F /* GeohashPeopleList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 047502B22E55FED60083520F /* GeohashPeopleList.swift */; };
047502B62E55FED60083520F /* MeshPeerList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 047502B32E55FED60083520F /* MeshPeerList.swift */; };
047502B72E55FED60083520F /* GeohashPeopleList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 047502B22E55FED60083520F /* GeohashPeopleList.swift */; };
047502B92E560F690083520F /* RelayController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 047502B82E560F690083520F /* RelayController.swift */; };
047502BA2E560F690083520F /* RelayController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 047502B82E560F690083520F /* RelayController.swift */; };
049BD3902E4EC4F0001A566B /* PrivateChatManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 049BD38F2E4EC4F0001A566B /* PrivateChatManager.swift */; };
049BD3912E4EC4F0001A566B /* AutocompleteService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 049BD38C2E4EC4F0001A566B /* AutocompleteService.swift */; };
049BD3922E4EC4F0001A566B /* CommandProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 049BD38D2E4EC4F0001A566B /* CommandProcessor.swift */; };
@@ -180,6 +186,9 @@
047502912E547ACC0083520F /* LocationChannelsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationChannelsTests.swift; sourceTree = "<group>"; };
047502AB2E55E8360083520F /* BinaryProtocolPaddingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BinaryProtocolPaddingTests.swift; sourceTree = "<group>"; };
047502AE2E55E8450083520F /* InputValidatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputValidatorTests.swift; sourceTree = "<group>"; };
047502B22E55FED60083520F /* GeohashPeopleList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeohashPeopleList.swift; sourceTree = "<group>"; };
047502B32E55FED60083520F /* MeshPeerList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeshPeerList.swift; sourceTree = "<group>"; };
047502B82E560F690083520F /* RelayController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayController.swift; sourceTree = "<group>"; };
049BD38C2E4EC4F0001A566B /* AutocompleteService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutocompleteService.swift; sourceTree = "<group>"; };
049BD38D2E4EC4F0001A566B /* CommandProcessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommandProcessor.swift; sourceTree = "<group>"; };
049BD38F2E4EC4F0001A566B /* PrivateChatManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivateChatManager.swift; sourceTree = "<group>"; };
@@ -412,6 +421,8 @@
A55126E93155456CAA8D6656 /* Views */ = {
isa = PBXGroup;
children = (
047502B22E55FED60083520F /* GeohashPeopleList.swift */,
047502B32E55FED60083520F /* MeshPeerList.swift */,
0475028E2E5417660083520F /* LocationChannelsSheet.swift */,
763E0DBA9492A654FC0CDCB9 /* AppInfoView.swift */,
A08E03AA0C63E97C91749AEC /* ContentView.swift */,
@@ -483,6 +494,7 @@
D98A3186D7E4C72E35BDF7FE /* Services */ = {
isa = PBXGroup;
children = (
047502B82E560F690083520F /* RelayController.swift */,
0475028B2E54171C0083520F /* LocationChannelManager.swift */,
049BD3B02E51F319001A566B /* MessageRouter.swift */,
049BD3B12E51F319001A566B /* NostrTransport.swift */,
@@ -703,6 +715,7 @@
049BD3B42E51F319001A566B /* NostrTransport.swift in Sources */,
049BD3B52E51F319001A566B /* MessageRouter.swift in Sources */,
4B747085D07A1BCE0F5BA612 /* BinaryProtocol.swift in Sources */,
047502B92E560F690083520F /* RelayController.swift in Sources */,
6E7761E21C99F28AE2F9BE5F /* BitchatApp.swift in Sources */,
84E3F9B64FB7FB4A140BD0A8 /* BitchatPeer.swift in Sources */,
923027D6F2F417AFA2488127 /* BitchatProtocol.swift in Sources */,
@@ -710,6 +723,8 @@
B0CA7796B2B2AC2B33F84548 /* CompressionUtil.swift in Sources */,
92D34E7A07C990C8A815B0CE /* ContentView.swift in Sources */,
5C93B4FDD0C448C3EDDBF8AE /* FavoritesPersistenceService.swift in Sources */,
047502B42E55FED60083520F /* MeshPeerList.swift in Sources */,
047502B52E55FED60083520F /* GeohashPeopleList.swift in Sources */,
6C63FA98D59854C15C57B3D6 /* FingerprintView.swift in Sources */,
38EDDC049FD56B1BB1F14C91 /* IdentityModels.swift in Sources */,
7241FFD6CFFB875B864FA223 /* InputValidator.swift in Sources */,
@@ -753,6 +768,7 @@
049BD3B22E51F319001A566B /* NostrTransport.swift in Sources */,
049BD3B32E51F319001A566B /* MessageRouter.swift in Sources */,
F455F011B3B648ADA233F998 /* BinaryProtocol.swift in Sources */,
047502BA2E560F690083520F /* RelayController.swift in Sources */,
10E68BB889356219189E38EC /* BitchatApp.swift in Sources */,
84D13329AB7EE1D65A37438A /* BitchatPeer.swift in Sources */,
6DE056E1EE9850E9FBF50157 /* BitchatProtocol.swift in Sources */,
@@ -760,6 +776,8 @@
7DCA0DBCB8884E3B31C7BCE3 /* CompressionUtil.swift in Sources */,
1D9674FA5F998503831DC281 /* ContentView.swift in Sources */,
ACE2ED172C37F01561E50B71 /* FavoritesPersistenceService.swift in Sources */,
047502B62E55FED60083520F /* MeshPeerList.swift in Sources */,
047502B72E55FED60083520F /* GeohashPeopleList.swift in Sources */,
132DF1E24B4E9C7DCDAD4376 /* FingerprintView.swift in Sources */,
B909706CD38FC56C0C8EB7BF /* IdentityModels.swift in Sources */,
EF49C600C1E464710DD6CA29 /* InputValidator.swift in Sources */,