-
Notifications
You must be signed in to change notification settings - Fork 0
Constants and Limits
Every numeric ceiling in the protocol, with rationale. The
consts module is
the source of truth for these values.
| Constant | Value | Why |
|---|---|---|
PROTOCOL_VERSION |
0x03 |
Drop frames with any other first byte. |
HEADER_SIZE |
16 B | 12 B logical header + 4 B trailing integrity tag. |
HEADER_MAC_LEN |
4 B | Truncated unkeyed SHA-256 over header[0..12]. |
MAX_PACKET_SIZE |
231 B | Meshtastic LoRa MTU. All frames MUST fit. |
MAX_BODY_SIZE |
215 B |
MAX_PACKET_SIZE − HEADER_SIZE. |
MIN_CHUNK_SIZE |
16 B | Per-frame overhead floor; below this, FEC + pacing waste airtime. |
| Constant | Value | Why |
|---|---|---|
MAX_CHUNKS_PER_MESSAGE |
255 |
total_data is u8; index 0..=254. |
MAX_PARITY_PER_MESSAGE |
128 |
reed-solomon-erasure GF(2⁸) coder limit. |
MAX_MESSAGE_BYTES |
54 825 |
MAX_CHUNKS_PER_MESSAGE × MAX_BODY_SIZE. |
V3 has no protocol-layer encryption. Confidentiality is delegated to Meshtastic's channel encryption (AES-256-CTR with the channel PSK). See Encryption.
| Constant | Value | Why |
|---|---|---|
MAX_IN_PROGRESS_GLOBAL |
64 | Bounds total reassembler memory. |
MAX_IN_PROGRESS_PER_SENDER |
4 | Stops one chatty peer from starving everyone else. |
BLACKLIST_TTL |
600 s | Completion-memory window: how long a finalized (from, message_id) blocks late frames for itself. Sized above worst-case sender airtime (a near-MTU Long Slow clip can take 2-3 min) so the blacklist outlives the TX. |
BLACKLIST_MAX |
100 | FIFO eviction once exceeded. |
NACK_MAX_ROUNDS |
400 | Per-message NACK budget (consecutive rounds without progress; resets on every accepted shard) before the receiver gives up. |
NACK_WINDOW_MS |
3000 | Quiet period after the last seen chunk before NACK'ing. |
DEAD_SENDER_TIMEOUT † |
120 s | Presume the sender dead after this much silence (no data/parity); suppress NACKs until message_timeout so the receiver stops NACK-flooding a peer that left the mesh. |
MAX_VALIDATION_STRIKES (impl) † |
3 | Eviction trigger for chatty bad senders (post-template). |
| Constant | Value | Why |
|---|---|---|
MAX_RETRANSMITS_PER_MESSAGE † |
2_400 | Per-message retransmit budget; matches widened receiver NACK_MAX_ROUNDS. |
DEFAULT_RETAIN_TTL † |
1200 s | How long OutgoingVoiceRegistry keeps frames for late NACKs (burst + linger safety margin). |
DEFAULT_LINGER (SendRequest) |
600 s | How long VoiceSender stays subscribed to NACKs after burst end. |
| Cooldown clamp | 1-30 s | Park window after each retransmit batch (pacing × frames). |
The constants marked † are experimental heuristic safety valves, not
wire-format guarantees. They cap NACK and retransmit storms and bound
reassembler/registry state so a dead, slow, or misbehaving peer can't flood
the channel or exhaust local memory. The values are tuned empirically against
real LoRa presets and may change between releases without a
PROTOCOL_VERSION bump, so interop never depends on their exact value.
-
Avoiding channel flooding:
-
DEAD_SENDER_TIMEOUT- stop NACKing a sender that has gone silent / left the mesh. -
MAX_RETRANSMITS_PER_MESSAGE- cap a sender's retransmit storm when a peer NACKs in a loop.
-
-
Resource bounding:
-
DEFAULT_RETAIN_TTL- garbage-collect the sender'sOutgoingVoiceRegistry. -
MAX_VALIDATION_STRIKES- evict a chatty bad sender from its scarce per-sender reassembly slot.
-
Adaptive per modem preset (Config.LoRaConfig.modem_preset). Each value
is tuned so pacing >= air_time(recommended_chunk_size) with ~30 %
headroom for firmware CSMA, queue drain, and ACK windows; sending faster
overruns the radio's small outbound queue and drops frames before they
reach the air. Source of truth: ModemPreset::pacing.
| Modem preset | Pacing |
|---|---|
SHORT_TURBO |
150 ms |
SHORT_FAST |
250 ms |
SHORT_SLOW |
400 ms |
MEDIUM_FAST |
500 ms |
MEDIUM_SLOW |
700 ms |
LONG_FAST |
900 ms |
LONG_MODERATE |
1200 ms |
LONG_SLOW |
1800 ms |
VERY_LONG_SLOW |
3000 ms |
| Unknown | 500 ms |
Source of truth: ModemPreset::recommended_chunk_size.
| Modem preset | chunk_size |
|---|---|
SHORT_TURBO, SHORT_FAST
|
215 (MAX_BODY_SIZE) |
SHORT_SLOW, MEDIUM_FAST
|
160 |
MEDIUM_SLOW |
96 |
LONG_FAST |
199 |
LONG_MODERATE, LONG_SLOW, VERY_LONG_SLOW
|
48 |
Severe loss (>40 %) requires nearly 1:1 parity for Reed–Solomon to close without relying on NACK retransmit rounds:
| Mesh profile | parity_count |
|---|---|
| Short / quiet | 10 % |
| Medium / mixed | 20 % |
| Long / lossy | 33 % |
| High-loss (>40 %) / broadcast | 100 % (up to 128) |
For quick sanity-checking message budgets:
chunk_size |
Codec / bitrate | max_audio |
Approx. duration |
|---|---|---|---|
| 215 | OPUS @ 16 kbps | 54 825 B | ~27 s |
| 160 | AMR-NB @ MR795 (7.95 kbps) | 40 800 B | ~41 s |
| 128 | AMR-NB @ MR795 | 32 640 B | ~33 s |
| 96 | AMR-NB @ MR795 | 24 480 B | ~25 s |
| 48 | AMR-NB @ MR795 | 12 240 B | ~12 s |
Durations are rough — they assume packed codec frames with no padding.
→ Continue to Error Catalogue.