BLEChat is a constraint-driven, protocol-first Bluetooth Low Energy (BLE) messaging system that implements secure handshakes, reliable delivery, flow control, and session hardening — entirely without servers.
This repository demonstrates how to build a real protocol, not just a BLE app.
- 🔗 Direct peer-to-peer communication (no backend, no internet)
- 🤝 Mutual handshake protocol with explicit role enforcement
- 📦 Reliable message delivery over unreliable BLE transport
- 🔁 Chunking, reassembly, ACK/NACK
- ⏱️ TTL-based expiration & replay protection
- 🔐 Session-based security hardening
- 🧠 Protocol-level state machines
- 🧪 Extensive debug & audit logs
BLEChat was built with constraint-first engineering:
- BLE is unreliable → reliability was implemented
- BLE drops packets → flow control was added
- BLE callbacks are strict → writes were serialized
- Security is fragile → sessions were hardened explicitly
Every feature exists because something broke.
BLEChat is a constraint-driven, protocol-first Bluetooth Low Energy (BLE) messaging system that implements secure handshakes, reliable delivery, flow control, and session hardening — entirely without servers.
This repository demonstrates how to build a real protocol, not just a BLE app.
- 🔗 Direct peer-to-peer communication (no backend, no internet)
- 🤝 Mutual handshake protocol with explicit role enforcement
- 📦 Reliable message delivery over unreliable BLE transport
- 🔁 Chunking, reassembly, ACK/NACK
- ⏱️ TTL-based expiration & replay protection
- 🔐 Session-based security hardening
- 🧠 Protocol-level state machines
- 🧪 Extensive debug & audit logs
BLEChat was built with constraint-first engineering:
- BLE is unreliable → reliability was implemented
- BLE drops packets → flow control was added
- BLE callbacks are strict → writes were serialized
- Security is fragile → sessions were hardened explicitly
Every feature exists because something broke.
┌──────────────┐ │ UI Layer │ └──────┬───────┘ │ ┌──────▼────────────────────────────┐ │ Reliable Transfer │ ← Phase 4–5 | │ (Chunking, ACKs) │ | └──────┬────────────────────────────┘ │ ┌──────▼────────────────────────────┐ │ Session Layer │ ← Phase 3 & 7 | │ (Handshake, Roles) | └──────┬────────────────────────────┘ │ ┌──────▼──────────────┐ │ BLE Transport │ │ (GATT, MTU, CCCD) │ └─────────────────────┘
| Phase | Description |
|---|---|
| Phase 1 | BLE Discovery & Connection |
| Phase 2 | Deterministic Peer Selection |
| Phase 3 | Mutual Handshake Protocol |
| Phase 4 | Reliable Message Transfer |
| Phase 5 | Dynamic MTU & Integrity |
| Phase 6 | Encryption (experimental) |
| Phase 7 | Session Hardening |
| Phase 8C | Formal Protocol Specification |
BLEChat uses a strict 4-step mutual handshake:
CLIENT → SERVER : HANDSHAKE_INIT SERVER → CLIENT : HANDSHAKE_ACK CLIENT → SERVER : HANDSHAKE_CONFIRM SERVER → CLIENT : HANDSHAKE_CONFIRM_ACK
✔ Both peers must reach SUCCESS
❌ No messaging before handshake
🔒 Session state is enforced
[TYPE][FLAGS][MSG_ID][CHUNK_IDX][TOTAL][TTL][PAYLOAD]
- Chunking adapts dynamically to negotiated MTU
- Messages are reassembled atomically
- ACK is sent only after full reassembly
- Sender advances one chunk per BLE callback
BLEChat explicitly handles:
- ❌ Packet loss
- ❌ Duplicate messages
- ❌ Replay attempts
- ❌ TTL expiration
- ❌ Link drops
- ❌ Invalid ACK/NACK
- ❌ Out-of-order events
Each failure:
- Transitions state
- Emits logs
- Cleans up memory
No silent failures.
Logs are part of the protocol — not debugging noise.
Examples:
- Chunking adapts dynamically to negotiated MTU
- Messages are reassembled atomically
- ACK is sent only after full reassembly
- Sender advances one chunk per BLE callback
BLEChat explicitly handles:
- ❌ Packet loss
- ❌ Duplicate messages
- ❌ Replay attempts
- ❌ TTL expiration
- ❌ Link drops
- ❌ Invalid ACK/NACK
- ❌ Out-of-order events
Each failure:
- Transitions state
- Emits logs
- Cleans up memory
No silent failures.
Logs are part of the protocol — not debugging noise.
Examples: SESSION_ESTABLISHED MSG_CREATED TX_CHUNK(0) RX_CHUNK(0) MSG_REASSEMBLED(msgId) ACK_SENT(msgId) ACK_RX(msgId) MSG_SENT_CONFIRMED(msgId) SESSION_INVALIDATED(reason)
If logs stop making sense → the protocol is broken.
- ❌ Single active peer only
- ❌ No MITM protection during initial pairing
- ❌ No group messaging
- ❌ No persistence across app restarts (session-based)
These are documented constraints, not bugs.
- Protocol engineers
- BLE developers
- Systems programmers
- Security-minded mobile developers
- Anyone interested in building systems under hostile constraints
A complete, frozen specification is available:
📘 BLEChat Protocol v1.0
(see /docs/protocol.md)
This document defines:
- State machines
- Wire formats
- Invariants
- Failure semantics
- Security boundaries
STABLE / FROZEN
The protocol is complete and verified across Android 13–16.
This project exists to prove one thing:
You can build real systems on top of hostile constraints —
if you respect the constraints instead of fighting them.