# BLE Policies for Peer Discovery and Connection Management in BitChat

> Explore BitChat's six layered BLE policies for peer discovery and connection management. Discover how BitChat ensures deadlock-free concurrency, atomic security checks, and deterministic peer discovery.

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

---

**BitChat employs six layered BLE policies—spanning scanning/advertising, connection scheduling, back-pressure buffering, link authentication, peer-registry locking, and panic-reset handling—to enforce dead-lock-free concurrency, atomic security checks, and deterministic peer discovery.**

The permissionlesstech/bitchat repository implements a rigorously structured Bluetooth Low-Energy (BLE) stack where **peer discovery** and **connection management** are governed by explicit policies rather than ad-hoc logic. Each policy resides at a specific architectural layer, with strict concurrency boundaries preventing race conditions and security vulnerabilities.

## Scanning and Advertising Policy

The **BLELinkLayer** controls when and how devices discover each other through a configurable scanning and advertising policy.

This policy determines:
- Scan intervals and maximum durations
- Whether duplicate advertisements are filtered (`allowDuplicates`)
- Duty-cycle limits to prevent excessive radio usage

In [`docs/BLE-ARCHITECTURE-V3.md`](https://github.com/permissionlesstech/bitchat/blob/main/docs/BLE-ARCHITECTURE-V3.md) (lines 31-38), the architecture specifies that scanning/advertising decisions are expressed as `LinkCommand` values that the link layer executes serially. This makes the discovery policy fully deterministic and testable in simulator environments.

```swift
let scanPolicy = BLEScanPolicy(
    interval: .seconds(5),          // Scan every 5 s
    maxDuration: .seconds(2),      // Scan for 2 s each interval
    allowDuplicates: false
)
let linkCmd = LinkCommand.startScanning(policy: scanPolicy)
BLELinkLayer.shared.send(command: linkCmd)

```

The `BLELinkLayer` implementation in [`bitchat/BLELinkLayer.swift`](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/BLELinkLayer.swift) enforces these policies on a dedicated `bleQueue`, isolating radio operations from higher-level mesh logic.

## Connection Scheduling and MTU Negotiation

Outbound connections are not initiated arbitrarily. The **connection scheduling policy** throttles connection attempts to respect BLE duty-cycle constraints and negotiates **maximum transmission unit (MTU)** sizes before data transfer begins.

This policy prevents:
- Connection storms that violate regulatory duty cycles
- MTU mismatches that fragment packets inefficiently

The same `LinkCommand` infrastructure handles connection requests, queuing them behind scanning operations when the radio is busy.

## Write and Notification Back-Pressure Policy

To prevent memory exhaustion during high-throughput scenarios, BitChat implements **bounded buffers** for both outgoing writes and incoming notifications.

When these buffers reach capacity, the transport layer automatically backs off rather than dropping data or consuming unbounded memory. This back-pressure policy is critical for mesh stability when multiple peers send simultaneous broadcasts.

```swift
let payload = Data("Hello".utf8)
BLELinkLayer.shared.send(
    command: .write(payload, to: peerID, expectAck: true)
)   // Internally checks pendingWriteBuffers limits

```

The `write` command in the example above silently enforces buffer limits defined in the link layer's policy configuration.

## Link Authentication and Binding Policy

Security-critical operations occur in [`bitchat/BLELinkAuthState.swift`](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/BLELinkAuthState.swift) under a strict **link-auth boundary policy**. This guarantees atomic "check-then-act" semantics for:

- Link authentication state transitions
- Peer-to-link binding operations

The **Engine (Mesh)** owns the binding maps, ensuring a peer cannot be re-bound after a security check has passed. This eliminates **time-of-check-to-time-of-use (TOCTOU)** attacks where an adversary might swap identities between verification and binding.

As documented in [`docs/BLE-ARCHITECTURE-V3.md`](https://github.com/permissionlesstech/bitchat/blob/main/docs/BLE-ARCHITECTURE-V3.md) (lines 135-144), this policy requires that all binding mutations occur on the serial engine queue with exclusive access.

## Peer Registry Connection Policy

The **Engine** exposes read-only, lock-backed queries through [`bitchat/BLEPeerRegistryStore.swift`](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/BLEPeerRegistryStore.swift) for connection state inspection.

Available operations include:
- `isPeerConnected(peerID:)` — immediate reachability check
- Nickname and capability queries

All mutations happen on the serial engine queue, eliminating race conditions between the mesh layer and UI components. External callers receive immutable snapshots, preventing accidental state corruption.

```swift
if BLEPeerRegistryStore.shared.isPeerConnected(peerID) {
    print("✅ Peer is reachable")
}

```

## Back-Off and Panic-Reset Policy

When fatal errors occur in the mesh—such as cryptographic validation failures or state machine violations—the **Engine** triggers a **panic-reset policy**. This forces:

1. Immediate termination of all active connections
2. Complete reset of connection state
3. Fresh discovery and advertising cycle

```swift
BLELinkLayer.shared.send(command: .panicReset)

```

This policy is documented in [`docs/BLE-ARCHITECTURE-V3.md`](https://github.com/permissionlesstech/bitchat/blob/main/docs/BLE-ARCHITECTURE-V3.md) (lines 166-176) and prevents cascading failures from corrupting the peer registry or link authentication state.

## Concurrency Architecture

These six policies achieve three architectural guarantees through strict queue confinement:

| Guarantee | Mechanism |
|-----------|-----------|
| **Dead-lock-free concurrency** | `bleQueue` (link layer) and engine queue (mesh) never wait on each other; only `onEngine` → `bleQueue` calls are permitted |
| **Atomic security checks** | Link-auth and binding updates execute in single critical sections on the engine queue |
| **Deterministic discovery** | All radio operations are `LinkCommand` objects, enabling reproducible simulation |

## Key Source Files

| File | Policy Responsibility |
|------|----------------------|
| [`docs/BLE-ARCHITECTURE-V3.md`](https://github.com/permissionlesstech/bitchat/blob/main/docs/BLE-ARCHITECTURE-V3.md) | Design documentation for all policies and layer contracts |
| [`bitchat/BLELinkLayer.swift`](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/BLELinkLayer.swift) | Scanning/advertising, connection scheduling, MTU, back-pressure buffers |
| [`bitchat/BLEPeerRegistryStore.swift`](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/BLEPeerRegistryStore.swift) | Lock-backed peer state queries |
| [`bitchat/BLELinkAuthState.swift`](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/BLELinkAuthState.swift) | Atomic link authentication and binding |
| [`bitchatTests/BLEServiceTests.swift`](https://github.com/permissionlesstech/bitchat/blob/main/bitchatTests/BLEServiceTests.swift) | Unit tests for discovery timing, back-pressure, panic-reset behavior |

## Summary

- **Peer discovery** in BitChat is governed by configurable `BLEScanPolicy` objects executed as serial `LinkCommand` operations
- **Connection management** spans scheduling, MTU negotiation, back-pressure buffering, and panic-reset handling across separate architectural layers
- **Security policies** enforce atomic link authentication through engine-queue exclusivity, preventing TOCTOU vulnerabilities
- **Concurrency isolation** between `bleQueue` and engine queue eliminates deadlocks while maintaining deterministic behavior
- All policies are implemented in [`BLELinkLayer.swift`](https://github.com/permissionlesstech/bitchat/blob/main/BLELinkLayer.swift), [`BLEPeerRegistryStore.swift`](https://github.com/permissionlesstech/bitchat/blob/main/BLEPeerRegistryStore.swift), and [`BLELinkAuthState.swift`](https://github.com/permissionlesstech/bitchat/blob/main/BLELinkAuthState.swift) under the architectural framework documented in [`BLE-ARCHITECTURE-V3.md`](https://github.com/permissionlesstech/bitchat/blob/main/BLE-ARCHITECTURE-V3.md)

## Frequently Asked Questions

### How does BitChat prevent BLE connection storms?

The **connection scheduling policy** in `BLELinkLayer` throttles outbound connection attempts to respect BLE duty-cycle constraints. Connections are queued as `LinkCommand` objects and executed when radio resources are available, preventing regulatory violations and hardware overload.

### What happens when BitChat's BLE buffers are full?

The **back-pressure policy** causes the transport layer to automatically back off when `pendingWriteBuffers` or notification buffers reach capacity. The `write` command checks these limits internally before accepting new data, ensuring memory usage remains bounded regardless of peer behavior.

### Can race conditions corrupt peer connection state?

No. The **peer-registry policy** mandates that all state mutations occur on the serial engine queue, while `BLEPeerRegistryStore` exposes only read-only, lock-backed queries to external callers. This design eliminates race conditions without requiring complex locking strategies throughout the codebase.

### How does BitChat recover from critical BLE mesh failures?

The **panic-reset policy** triggers a complete connection state reset and fresh discovery cycle. Implemented in the Engine and executed via `LinkCommand.panicReset`, this prevents cascading failures by isolating corrupt state and reinitializing radio operations from a known-good configuration.