# How BLEService Manages Concurrent Connections and Authentication States in Bitchat

> Discover how BLEService manages concurrent connections and authentication in Bitchat. Learn about its dual-queue architecture for thread-safe operations and strict queue isolation.

- Repository: [permissionlesstech/bitchat](https://github.com/permissionlesstech/bitchat)
- Tags: internals
- Published: 2026-08-09

---

**BLEService uses a dual-queue architecture where a serial `bleQueue` handles all mutable BLE link state while a separate `messageQueue` (engine queue) manages authentication maps, ensuring thread-safe concurrent connections through strict queue isolation.**

BLEService serves as the core Bluetooth Low Energy transport layer in the open-source **bitchat** messaging application. This Swift class orchestrates multiple simultaneous BLE links across both central and peripheral roles while maintaining consistent authentication state. Understanding how BLEService manages concurrent connections and authentication states reveals a sophisticated concurrency model built on serial dispatch queues and strict ownership boundaries.

## Serial Queue Architecture for Thread Safety

### The bleQueue Isolation Pattern

All mutable Bluetooth state in `BLEService` is owned by a dedicated serial dispatch queue called `bleQueue`. Initialized as `DispatchQueue(label: "mesh.bluetooth", …)` in [`BLEService.swift`](https://github.com/permissionlesstech/bitchat/blob/main/BLEService.swift) (lines 71-82), this queue guarantees that no two callbacks race when accessing the physical link store.

The `linkStateStore` (an instance of `BLELinkStateStore`) holds all per-link information and is only accessed from `bleQueue`. When BLE callbacks arrive from the operating system—whether from central or peripheral role events—they immediately target this queue before modifying any connection state.

## Engine Queue and Authentication State Management

### The onEngine Synchronization Contract

High-level authentication logic runs on a separate `messageQueue` (referred to as the engine queue). The `onEngine<T>(_:)` method enforces strict queue discipline: if already executing on the engine queue, it runs the closure directly; otherwise, it synchronously dispatches to the queue.

According to [`BLEService.swift`](https://github.com/permissionlesstech/bitchat/blob/main/BLEService.swift) (lines 96-106), this contract ensures that `BLELinkAuthState` and `BLELinkBindings` are mutated exclusively on the engine queue, preventing accidental cross-queue reads of authentication-sensitive data.

## Authentication State Tracking

### BLELinkAuthState and Session Ownership

The `BLELinkAuthState` class records which Noise session was established on which physical link through the `authenticatedOwners` dictionary. It also manages revalidation cooldowns to prevent thrashing during authentication retries.

As implemented in [`BLELinkAuthState.swift`](https://github.com/permissionlesstech/bitchat/blob/main/BLELinkAuthState.swift) (lines 17-30 and 37-47), this structure tracks the cryptographic identity associated with each live link. The `permitRebind` and `permitRedundantRetirement` methods (lines 90-114) enforce rate-limiting by checking cooldown windows before allowing link state changes.

### BLELinkBindings for Peer Mapping

`BLELinkBindings` maintains the mapping between link UUIDs and their owning peer identities. This class also tracks the "preferred peripheral" for fan-out collapse optimization. Source code in [`BLELinkBindings.swift`](https://github.com/permissionlesstech/bitchat/blob/main/BLELinkBindings.swift) (lines 4-15 and 81-97) shows how the system maps physical transport identifiers to logical peer IDs while managing preferred connection paths.

## Noise Handshake Integration

BLEService owns a `NoiseEncryptionService` instance (`noiseService`) that creates and validates Noise protocol sessions. When a link completes authentication, the `markAuthenticated` method records the owner in `BLELinkAuthState`.

Before transmitting sensitive data, `BLEService` verifies security through `canDeliverSecurely(to:)`. This method checks `noiseService.hasEstablishedSession(with:)` to ensure only links with verified Noise sessions handle secure private-media transfers. The implementation in [`BLEService.swift`](https://github.com/permissionlesstech/bitchat/blob/main/BLEService.swift) (lines 119-131) enforces this security boundary for every packet delivery decision.

## Panic-Safe Lifecycle Management

To handle catastrophic reset scenarios, BLEService implements a generation-bounded lifecycle through `panicLifecycleGeneration`. The methods `capturePanicLifecycleGeneration` and `isCurrentPanicLifecycleGeneration` (lines 140-158 in [`BLEService.swift`](https://github.com/permissionlesstech/bitchat/blob/main/BLEService.swift)) ensure that in-flight work from previous panic resets is discarded.

When resetting state, `removeAll` and `clearAll` operations execute exclusively on the engine queue before radio restart. This guarantees that stale authentication data cannot persist across service panic recoveries.

## Rate Limiting and Cooldowns

Authentication state mutations incorporate defensive rate-limiting. The `BLELinkAuthState` class stores per-link cooldown windows that govern how frequently links can rebind or retire. 

The `permitRebind` method prunes outdated entries and returns a boolean indicating whether the operation is allowed, while `permitRedundantRetirement` prevents excessive link teardown events. These mechanisms protect against denial-of-service through rapid connection cycling.

## Practical Implementation Flow

The concurrent connection management follows a strict four-step pipeline:

1. **BLE callbacks** arrive on `bleQueue` from Core Bluetooth delegates
2. **Physical state updates** modify `linkStateStore` (e.g., adding new peripheral links)
3. **Engine hop** transitions to `messageQueue` via `onEngine` to update authentication maps
4. **Transmission verification** checks `canDeliverSecurely` using the Noise service before selecting links via `linkStateStore` and `linkBindings`

This architecture serializes physical link operations on `bleQueue` while isolating authentication state on `messageQueue`, eliminating race conditions between link discovery, teardown, and cryptographic updates.

## Code Examples

```swift
// Initialize BLEService (normally injected by the app container)
let bleService = BLEService(
    keychain: KeychainManager.shared,
    idBridge: NostrIdentityBridge(),
    identityManager: SecureIdentityStateManager.shared
)

// Verify secure delivery capability before transmission
let peerID = PeerID(hexString: "a1b2c3…")!
let isSecure = bleService.canDeliverSecurely(to: peerID)

// Send message - automatically selects authenticated link
bleService.sendMessage("Hello mesh!", mentions: [], to: nil)

// Manual link retirement with proper queue handling
let linkID = BLEIngressLinkID.peripheral(uuidString)
bleService.onEngine {
    // Remove authentication proof and binding atomically
    bleService.linkAuth.retireLink(linkID)
    bleService.linkBindings.peripheralRemoved(linkID.uuidString) { _ in nil }
}

```

## Summary

- **Dual-queue isolation**: `bleQueue` owns physical link state while `messageQueue` owns authentication maps, preventing cross-thread data races
- **Strict synchronization**: The `onEngine` method guarantees all access to `BLELinkAuthState` and `BLELinkBindings` occurs on the engine queue
- **Noise protocol integration**: `BLEService` coordinates with `NoiseEncryptionService` to verify sessions via `canDeliverSecurely` before transmitting sensitive data
- **Defensive rate limiting**: Per-link cooldowns in `BLELinkAuthState` prevent rebind and retirement thrashing through `permitRebind` and `permitRedundantRetirement`
- **Panic resilience**: Generation-bounded lifecycle tracking ensures stale operations from previous resets cannot corrupt current authentication state

## Frequently Asked Questions

### What prevents race conditions between BLE connection callbacks and authentication updates?

The `bleQueue` serializes all Core Bluetooth callbacks and physical link store modifications. When authentication state needs updating, the code explicitly transitions to the `messageQueue` (engine queue) using `onEngine`. This queue isolation ensures that `BLELinkAuthState` mutations never occur concurrently with physical link teardowns.

### How does BLEService verify that a connection is secure before sending private messages?

Before transmission, `BLEService` calls `canDeliverSecurely(to:)` which queries `noiseService.hasEstablishedSession(with:)`. This verifies that a complete Noise protocol handshake has finished and the cryptographic session is active. Only links with established Noise sessions are eligible for private-media transfers.

### What happens to authentication state when the BLE service panics or resets?

BLEService implements a generation counter (`panicLifecycleGeneration`) captured via `capturePanicLifecycleGeneration`. All async operations check `isCurrentPanicLifecycleGeneration` before executing. During reset, `removeAll` and `clearAll` execute on the engine queue to atomically clear `BLELinkAuthState` and `BLELinkBindings` before the radio restarts, ensuring no stale authentication data persists.

### Where are the physical link objects stored versus the authentication metadata?

Physical link objects (CBPeripheral, CBCentral, characteristics) live in `BLELinkStateStore`, accessed exclusively from `bleQueue`. Authentication metadata—including Noise session ownership and peer bindings—resides in `BLELinkAuthState` and `BLELinkBindings`, accessed exclusively from the engine queue (`messageQueue`). This separation of concerns prevents low-level transport errors from corrupting high-level security state.