BLE Policies for Peer Discovery and Connection Management in BitChat

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 (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.

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 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.

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.

Security-critical operations occur in 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 (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 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.

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
BLELinkLayer.shared.send(command: .panicReset)

This policy is documented in 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 Design documentation for all policies and layer contracts
bitchat/BLELinkLayer.swift Scanning/advertising, connection scheduling, MTU, back-pressure buffers
bitchat/BLEPeerRegistryStore.swift Lock-backed peer state queries
bitchat/BLELinkAuthState.swift Atomic link authentication and binding
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, BLEPeerRegistryStore.swift, and BLELinkAuthState.swift under the architectural framework documented in 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →