diff --git a/docs/BLE_PROTOCOL.md b/docs/BLE_PROTOCOL.md index a8edc89a..c17c3e7a 100644 --- a/docs/BLE_PROTOCOL.md +++ b/docs/BLE_PROTOCOL.md @@ -1287,105 +1287,6 @@ if (reactionInfo != null) { Reactions are parsed, processed to update target message's reaction counts, but never displayed as standalone messages. -## Routing Paths - -MeshCore supports variable-length multi-byte routing paths to scale mesh networks from 256 unique nodes (1-byte hashes) to millions (3-byte hashes). - -### Path Encoding Format - -**Single Byte Encodes Both Hop Count and Hash Mode**: -``` -Path Byte Format: -Bit 7-6: Hash mode (2 bits) → hash_bytes = 1 << mode -Bit 5-0: Hop count (6 bits) → max 63 hops -``` - -**Supported Modes**: - -| Mode | Hash Bytes | Max Hops | Max Unique Nodes | Firmware | -|------|-----------|----------|------------------|----------| -| 0 | 1 | 63 | 256 | v1.13+ | -| 1 | 2 | 63 | 65,536 | v1.14+ | -| 2 | 3 | 63 | 16.7M | v1.14+ | -| 3 | 4 | 63 | 4.3B | v1.14+ | - -**Special Values**: -- Path byte = **255** → Direct or flooded message (no path) -- Path byte = **0** → End of contact path data (padding byte) - -### Path Byte Calculation - -```dart -// Extract mode and hop count from wire byte -final pathLenRaw = frameData[index]; // Single byte -final hopCount = pathLenRaw & 0x3F; // Bits 5-0 -final hashMode = (pathLenRaw >> 6) & 0x03; // Bits 7-6 -final hashBytes = 1 << hashMode; // 1, 2, 4, or 8 - -// Total path bytes = hopCount * hashBytes -final pathByteLength = hopCount * hashBytes; -final pathData = frameData.sublist(index + 1, index + 1 + pathByteLength); -``` - -### Device Capability Detection - -The device firmware version determines multi-byte path support: - -**Firmware Byte 81** (from `RESP_CODE_SELF_INFO` and device initialization): -- Bits 3-0: Path hash mode capability (0-3) -- v1.13 and earlier: Hardcoded mode 0 (1-byte only) -- v1.14+: Firmware reports mode in byte 81; device generates paths in this mode - -**Detection in App**: -```dart -// After receiving RESP_CODE_SELF_INFO -if (firmwareBytes.length >= 82) { - final mode = (firmwareBytes[81] & 0xFF).clamp(0, 2); - pathHashByteWidth = mode + 1; // Sets to 1, 2, 3, or 4 bytes -} else { - pathHashByteWidth = 1; // Fallback for v1.13 -} -``` - -### Path Usage in Different Message Types - -**Direct Messages** (`RESP_CODE_CONTACT_MSG_RECV`/`RESP_CODE_CONTACT_MSG_RECV_V3`): -- Path extracted from payload after decryption -- Used to trace back to sender - -**Channel Messages** (`RESP_CODE_CHANNEL_MSG_RECV`/`RESP_CODE_CHANNEL_MSG_RECV_V3`): -- Group address + encrypted path in payload -- Decrypted to reveal hop-by-hop routing chain - -**Contact Storage** (from `RESP_CODE_CONTACT` frames): -- Byte 32: Path length encoding (hop_count | (mode << 6)) -- Bytes 33-96: Path data (max 64 bytes stored, variable interpretation) - -**Example Contact Path Parsing**: -```dart -// Mode 0 (1-byte): 3 hops = 3 bytes needed -// [0x83, 0xA1, 0xB2, 0xC3] → hopCount=3, mode=0, path=[A1,B2,C3] - -// Mode 1 (2-byte): 3 hops = 6 bytes needed -// [0xC3, 0xA1, 0xA2, 0xB1, 0xB2, 0xC1, 0xC2] -// → hopCount=3, mode=1, path=[A1A2, B1B2, C1C2] -``` - -### Path Validation During Input - -When user enters custom paths in the UI: - -1. **Parse comma-separated hex segments**: `"A1B2,C1C2,D1D2"` -2. **Validate segment length**: Each must be exactly `hashBytes * 2` hex characters -3. **Convert to bytes**: Group hex pairs into single bytes -4. **Check hop count**: Total bytes ÷ hashBytes must be ≤ 63 - -**Example with 2-byte mode**: -- Device reports: `pathHashByteWidth = 2` -- User enters: `"A1B2,C1C2"` (2 hops) -- Parse result: `[0xA1, 0xB2, 0xC1, 0xC2]` (4 bytes total) -- Validation: `4 bytes ÷ 2 bytes/hop = 2 hops` ✓ - ## References - **Firmware Repository**: https://github.com/nonik0/meshcore diff --git a/documentation/README.md b/documentation/README.md index 13670134..a3700fc6 100644 --- a/documentation/README.md +++ b/documentation/README.md @@ -14,7 +14,8 @@ MeshCore Open is an open-source Flutter client for MeshCore LoRa mesh networking 8. [Notifications](notifications.md) - System notifications, unread badges, and notification preferences 9. [Repeater Management](repeater-management.md) - Repeater hub, status, CLI, telemetry, and neighbors 10. [Additional Features](additional-features.md) - GIF picker, localization, debug logs, SMAZ compression, and more -11. [BLE Protocol & Data Layer](ble-protocol.md) - Technical reference for the communication protocol and data architecture +11. [Routing Paths](routing-paths.md) - Path encoding, validation, device capability detection, and storage +12. [BLE Protocol & Data Layer](ble-protocol.md) - Technical reference for the communication protocol and data architecture ## App Overview diff --git a/documentation/chat-and-messaging.md b/documentation/chat-and-messaging.md index baf2ab8d..19dc4f05 100644 --- a/documentation/chat-and-messaging.md +++ b/documentation/chat-and-messaging.md @@ -21,6 +21,7 @@ From the Contacts screen, tap any Chat-type contact to open the ChatScreen. - **Action buttons**: - **Routing mode** (waves icon): Switch between Auto, Direct, and Flood routing - **Path management** (timeline icon): View recent paths with hop count, round-trip time, age, and success count. Paths are color-coded by direct repeater (green/yellow/red/blue for ranked repeaters, grey for unknown). Tap a path to activate it (the device verifies and confirms via snackbar), long-press to view full path details, set custom paths, or force flood mode. A warning banner appears when history reaches 100 entries. + - Custom path entry follows the device's current hash width, so multibyte paths are entered as comma-separated hex prefixes such as `A1B2,C1C2` when that mode is enabled. - **Info** (info icon): Contact info dialog showing type, path, GPS coordinates, public key, and SMAZ compression toggle ### Message List diff --git a/documentation/routing-paths.md b/documentation/routing-paths.md new file mode 100644 index 00000000..2a25683e --- /dev/null +++ b/documentation/routing-paths.md @@ -0,0 +1,66 @@ +# Routing Paths + +This page covers how MeshCore Open represents, selects, validates, and stores routing paths in the UI and data layer. + +## Path Routing + +MeshCore supports variable-length multi-byte routing paths so the app can scale from small meshes to very large node sets. + +### Path Encoding Format + +Each path byte packs both the hop count and the hash width: + +``` +Bit 7-6: Hash mode (2 bits) → hash_bytes = 1 << mode +Bit 5-0: Hop count (6 bits) → max 63 hops +``` + +| Mode | Hash Bytes | Max Hops | Max Unique Nodes | Firmware | +|------|-----------|----------|------------------|----------| +| 0 | 1 | 63 | 256 | v1.13+ | +| 1 | 2 | 63 | 65,536 | v1.14+ | +| 2 | 3 | 63 | 16.7M | v1.14+ | +| 3 | 4 | 63 | 4.3B | v1.14+ | + +### Path Byte Calculation + +```dart +final pathLenRaw = frameData[index]; +final hopCount = pathLenRaw & 0x3F; +final hashMode = (pathLenRaw >> 6) & 0x03; +final hashBytes = 1 << hashMode; + +final pathByteLength = hopCount * hashBytes; +final pathData = frameData.sublist(index + 1, index + 1 + pathByteLength); +``` + +### Device Capability Detection + +The app reads the device's reported capability byte to determine whether multi-byte paths are available: + +```dart +if (firmwareBytes.length >= 82) { + final mode = (firmwareBytes[81] & 0xFF).clamp(0, 2); + pathHashByteWidth = mode + 1; +} else { + pathHashByteWidth = 1; +} +``` + +### Path Usage in Different Message Types + +- Direct messages extract the path from the decrypted payload to trace the sender route. +- Channel messages decrypt a hop-by-hop routing chain from the payload. +- Contact storage keeps the path length encoding in byte 32 and the raw path bytes in bytes 33-96. + +### Example Contact Path Parsing + +```dart +// Mode 0 (1-byte): 3 hops = 3 bytes needed +// [0x83, 0xA1, 0xB2, 0xC3] → hopCount=3, mode=0, path=[A1,B2,C3] + +// Mode 1 (2-byte): 3 hops = 6 bytes needed +// [0xC3, 0xA1, 0xA2, 0xB1, 0xB2, 0xC1, 0xC2] +// → hopCount=3, mode=1, path=[A1A2, B1B2, C1C2] +``` +