mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-24 23:45:18 +00:00
Fix connect/disconnect/connect pattern on initial connection
- Added duplicate connection detection in key exchange handler - When same peer connects through multiple peripherals, keep only one - Track intentional disconnects to suppress disconnect messages - Don't show disconnect message when dropping duplicate connections - This prevents the confusing connect/disconnect/connect pattern The issue was that both devices try to connect to each other simultaneously, creating duplicate connections. One gets dropped, but now it's handled gracefully.
This commit is contained in:
@@ -255,6 +255,8 @@
|
||||
DEVELOPMENT_TEAM = L3N5LHJD5Y;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
INFOPLIST_FILE = bitchat/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = bitchat;
|
||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
@@ -264,9 +266,12 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = chat.bitchat;
|
||||
PRODUCT_NAME = bitchat;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
TARGETED_DEVICE_FAMILY = 1;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -282,6 +287,8 @@
|
||||
DEVELOPMENT_TEAM = L3N5LHJD5Y;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
INFOPLIST_FILE = bitchat/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = bitchat;
|
||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
@@ -291,9 +298,12 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = chat.bitchat;
|
||||
PRODUCT_NAME = bitchat;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
TARGETED_DEVICE_FAMILY = 1;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
||||
+5
-1
@@ -39,9 +39,13 @@
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -54,6 +54,7 @@ class BluetoothMeshService: NSObject {
|
||||
private var announcedToPeers = Set<String>() // Track which peers we've announced to
|
||||
private var announcedPeers = Set<String>() // Track peers who have already been announced
|
||||
private var processedKeyExchanges = Set<String>() // Track processed key exchanges to prevent duplicates
|
||||
private var intentionalDisconnects = Set<String>() // Track peripherals we're disconnecting intentionally
|
||||
|
||||
// Store-and-forward message cache
|
||||
private struct StoredMessage {
|
||||
@@ -1322,6 +1323,16 @@ class BluetoothMeshService: NSObject {
|
||||
if senderID != "unknown" && senderID != myPeerID {
|
||||
// Check if we need to update peripheral mapping from the specific peripheral that sent this
|
||||
if let peripheral = peripheral {
|
||||
// Check if we already have a different peripheral connected for this peer
|
||||
if let existingPeripheral = self.connectedPeripherals[senderID],
|
||||
existingPeripheral != peripheral {
|
||||
// We have a duplicate connection - disconnect the newer one
|
||||
// print("[DEBUG] Duplicate connection detected for \(senderID), keeping existing")
|
||||
intentionalDisconnects.insert(peripheral.identifier.uuidString)
|
||||
centralManager.cancelPeripheralConnection(peripheral)
|
||||
return
|
||||
}
|
||||
|
||||
// Find if this peripheral is currently mapped with a temp ID
|
||||
if let tempID = self.connectedPeripherals.first(where: { $0.value == peripheral })?.key,
|
||||
tempID.count > 8 { // It's a temp ID
|
||||
@@ -1748,6 +1759,8 @@ extension BluetoothMeshService: CBCentralManagerDelegate {
|
||||
let tempID = peripheral.identifier.uuidString
|
||||
connectedPeripherals[tempID] = peripheral
|
||||
|
||||
// Don't show connected message yet - wait for key exchange
|
||||
// This prevents the connect/disconnect/connect pattern
|
||||
|
||||
// Request RSSI reading
|
||||
peripheral.readRSSI()
|
||||
@@ -1762,6 +1775,13 @@ extension BluetoothMeshService: CBCentralManagerDelegate {
|
||||
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
|
||||
let peripheralID = peripheral.identifier.uuidString
|
||||
|
||||
// Check if this was an intentional disconnect
|
||||
if intentionalDisconnects.contains(peripheralID) {
|
||||
intentionalDisconnects.remove(peripheralID)
|
||||
// Don't process this disconnect further
|
||||
return
|
||||
}
|
||||
|
||||
// Implement exponential backoff for failed connections
|
||||
if error != nil {
|
||||
let attempts = connectionAttempts[peripheralID] ?? 0
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
# Connection Stability Fixes for BluetoothMeshService
|
||||
|
||||
## Issues Causing Disconnect/Reconnect
|
||||
|
||||
1. **Simultaneous Connection Attempts**: Both devices acting as central and peripheral can create duplicate connections
|
||||
2. **Temporary ID Management**: Using peripheral UUIDs as temporary IDs causes confusion
|
||||
3. **Premature State Updates**: Peer list updates happen before connections are fully established
|
||||
4. **Aggressive Disconnect Handling**: Peers are removed immediately on disconnect without grace period
|
||||
|
||||
## Recommended Fixes
|
||||
|
||||
### 1. Implement Connection Deduplication
|
||||
- Track ongoing connection attempts by peer ID
|
||||
- Reject duplicate connections from same peer
|
||||
- Use deterministic logic to decide which side maintains connection (e.g., compare peer IDs)
|
||||
|
||||
### 2. Improve Peer State Management
|
||||
- Add connection states: CONNECTING, CONNECTED, DISCONNECTING
|
||||
- Only show "joined" after key exchange AND announce received
|
||||
- Add grace period before showing "left" messages (e.g., 5 seconds)
|
||||
|
||||
### 3. Fix Temporary ID Handling
|
||||
- Don't add temp IDs to activePeers
|
||||
- Only update peer lists after receiving real peer ID
|
||||
- Use a separate pendingPeripherals dictionary
|
||||
|
||||
### 4. Consolidate Key Exchange and Announce
|
||||
- Send key exchange and announce as atomic operation
|
||||
- Wait for both before considering peer "connected"
|
||||
- Add sequence numbers to prevent duplicate processing
|
||||
|
||||
### 5. Add Connection Stability Timer
|
||||
- Don't show "joined" until connection stable for 1 second
|
||||
- Buffer rapid connect/disconnect cycles
|
||||
- Implement exponential backoff for reconnection attempts
|
||||
|
||||
## Implementation Priority
|
||||
1. Fix duplicate connection handling (highest impact)
|
||||
2. Add connection grace period
|
||||
3. Improve state management
|
||||
4. Consolidate initialization messages
|
||||
+2
-5
@@ -34,11 +34,8 @@ targets:
|
||||
UIColorName: Black
|
||||
UISupportedInterfaceOrientations:
|
||||
- UIInterfaceOrientationPortrait
|
||||
- UIInterfaceOrientationPortraitUpsideDown
|
||||
- UIInterfaceOrientationLandscapeLeft
|
||||
- UIInterfaceOrientationLandscapeRight
|
||||
settings:
|
||||
PRODUCT_BUNDLE_IDENTIFIER: com.bitchat.app
|
||||
PRODUCT_BUNDLE_IDENTIFIER: chat.bitchat
|
||||
INFOPLIST_FILE: bitchat/Info.plist
|
||||
ENABLE_PREVIEWS: YES
|
||||
SWIFT_VERSION: 5.0
|
||||
@@ -49,4 +46,4 @@ targets:
|
||||
CODE_SIGNING_REQUIRED: YES
|
||||
CODE_SIGNING_ALLOWED: YES
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon
|
||||
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS: YES
|
||||
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS: YES
|
||||
|
||||
Reference in New Issue
Block a user