Skip to content

Constants and Limits

acarteron edited this page Jun 13, 2026 · 6 revisions

Constants and Limits

← Home

Every numeric ceiling in the protocol, with rationale. The consts module is the source of truth for these values.


Wire format

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.

Message shape

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.

Confidentiality

V3 has no protocol-layer encryption. Confidentiality is delegated to Meshtastic's channel encryption (AES-256-CTR with the channel PSK). See Encryption.

Receiver resource bounds

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

Sender resource bounds

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

† Experimental flood-control & resource-bounding limits

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's OutgoingVoiceRegistry.
    • MAX_VALIDATION_STRIKES - evict a chatty bad sender from its scarce per-sender reassembly slot.

Sender pacing

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

Recommended chunk_size per preset

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

Recommended parity_count

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)

Capacity reference

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.

Clone this wiki locally