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.
Link Authentication and Binding Policy
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:
- Immediate termination of all active connections
- Complete reset of connection state
- 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
BLEScanPolicyobjects executed as serialLinkCommandoperations - 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
bleQueueand engine queue eliminates deadlocks while maintaining deterministic behavior - All policies are implemented in
BLELinkLayer.swift,BLEPeerRegistryStore.swift, andBLELinkAuthState.swiftunder the architectural framework documented inBLE-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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →