Skip to content

Packet Format and Topics

Muhammad Nuzaihan edited this page Aug 22, 2026 · 1 revision

Packet Format and Topics

CdpPacket wire format

Defined in src/CdpPacket.h. Fixed 27-byte header, up to 229 bytes of data (PACKET_LENGTH = 256, HEADER_LENGTH = 27, MAX_DATA_LENGTH = 229):

|0       |8       |16  |20|21|22|23  |27                                   255|
+--------+--------+----+--+--+--+----+----------------------------------------+
| SDUID  | DDUID  |MUID|T |DT|HC|DCRC|                 DATA                   |
+--------+--------+----+--+--+--+----+----------------------------------------+
Field Offset Length Meaning
SDUID 0 8 Source device unique ID
DDUID 8 8 Destination device unique ID (or BROADCAST_DUID/PAPADUCK_DUID)
MUID 16 4 Message unique ID (assigned by the bloom filter for dedup)
Topic 20 1 Application/protocol topic (see below)
Duck type 21 1 Sender's DuckType
Hop count 22 1 Incremented on each relay, capped at MAX_HOPS = 6
Data CRC 23 4 CRC32 of the data section
Data 27 ≤229 Payload (application data or protocol-internal, depending on topic)

PAPADUCK_DUID is all-zero bytes; BROADCAST_DUID is all-0xFF bytes.

reservedTopic — core CDP protocol topics (0x00–0x0F)

enum reservedTopic {
  unused = 0x00,
  ping = 0x01,
  pong = 0x02,
  ack = 0x04,
  cmd = 0x05,
  rreq = 0x06,
  rrep = 0x07,
  max_reserved = 0x0F
};

rreq/rrep drive route discovery (see Routing and Mesh). Any sendData() call with topic < max_reserved is rejected — application code must use topics values instead.

topics — application and security topics (0x10+)

enum topics {
  status = 0x10,
  cpm = 0x11,
  sensor = 0x13,
  alert = 0x14,
  health = 0x15,
  dcmd = 0x16,
  encrypted_cmd = 0x1B,
  sealed_uplink = 0x1C,
  identity_announce = 0x1D,
  encrypted_data = 0x1E,
  group_broadcast = 0x1F,
  gps = 0xEA,
  mq7 = 0xEF,
  gp2y = 0xFA,
  bmp280 = 0xFB,
  dht11 = 0xFC,
  pir = 0xFD,
  bmp180 = 0xFE,
  max_topics = 0xFF
};

The five encryption-related topics (0x1B0x1F) are documented in detail in Security and Encryption. In every case, the leading application topic byte inside the data section is sent in the clear (but bound into the AEAD's additional authenticated data), so relays and observers can distinguish which encryption mode was used without being able to decrypt the payload or see what it actually contains.

Application payloads (protobuf)

src/payloads/duck_payloads.proto defines the structured payloads carried inside sensor/gps/alert/health/status topics; src/payloads/DuckPayloads.h provides matching encode/decode helpers built on nanopb.

Message Topic Purpose
GpsReading gps Fix status, source (device/phone), lat/lng (as *_e7 fixed-point), altitude, speed, heading, satellite count, battery %
SosAlert alert Origin (device/phone), optional GPS fix, battery %
HealthStatus health Counter, free memory
MTalk (custom, MamaDuck-to-MamaDuck chat) Kind (message/ack), message ID, text
StatusMsg / StatusReport status Wraps either an SosAlert or a StatusMsg (phone/device-composed text) in one envelope
OpText (custom, operator/mesh text topics) Free text

Each encode function (encodeGps, encodeSos, encodeHealth, encodeMTalk, encodeStatusReportSos, encodeStatusReportMsg, encodeOpText) prepends a one-byte format marker (kLegacyText = 0x00 or kProtobuf = 0x01) so a receiver can tell whether a payload is the newer protobuf encoding or the legacy plain-text format, via isProtobuf().

Payloads are always protobuf-encoded before any encryption is applied (see Security and Encryption) — encryption treats the already-serialized bytes as one opaque blob, never the other way around.

Clone this wiki locally