12.3. Het pakketformaat¶
Elke byte die tussen de cam en de host over de lijn gaat, maakt deel uit van een pakket. Een pakket begint met een 10-byte header, bevat een payload van variabele lengte en eindigt met een 4-byte afsluitende CRC. Er verschijnen geen andere bytes op de lijn – zodra de host het 2-byte sync-woord heeft gezien, zijn de volgende bytes een header in precies deze volgorde.
12.3.1. De header¶
Tien bytes, gepakt zonder padding. Elk veld:
sync– het 16-bits woord0xD5AAin little-endian volgorde. Byte 0 op de lijn is0xAA, byte 1 is0xD5. Een ontvanger die bytes scant kan het begin van een pakket vinden door te zoeken naar het paarAA D5; alles ervoor wordt als rommel behandeld. De keuze van de waarde is bewust:0xAAen0xD5komen zelden voor in afdrukbare tekst, en het paar zal naar verwachting niet per ongeluk midden in een payload voorkomen.seq– één byte. Een teller die met één ophoogt voor elk pakket dat in een bepaalde richting wordt verzonden. De ontvanger controleert of het sequence number van het volgende pakket het verwachte is; zo niet, dan vraagt de betrouwbaarheidslaag om een hertransmissie.chan– één byte. De kanaal-ID waartoe dit pakket behoort. Kanalen 0..31 zijn bruikbaar; de ingebouwde kanalenstdin,stdout,streamen (optioneel)profilenemen vaste ID’s in die de cam reserveert.flags– één byte. Een bit-veld dat de ontvanger vertelt hoe het pakket te interpreteren:bit 0
ACK– dit pakket is een bevestiging van een eerder pakket.bit 1
NAK– dit pakket verwerpt een eerder pakket.bit 2
RTX– dit pakket is een hertransmissie.bit 3
ACK_REQ– de verzender wil dat dit pakket wordt bevestigd.bit 4
FRAGMENT– er volgen meer fragmenten na dit fragment in een groter bericht.bit 5
EVENT– dit pakket draagt een kanaal-event in plaats van data.bits 6 en 7 zijn gereserveerd.
opcode– één byte. De commando- of antwoordcode. De protocolbibliotheek reserveert opcode-bereiken per doel:0x00..0x0F– protocolcommando’s (SYNC, GET_CAPS, SET_CAPS, STATS, VERSION).0x10..0x1F– systeemcommando’s (RESET, BOOT, INFO, EVENT, MEMORY).0x20..0x2F– kanaalcommando’s (LIST, POLL, LOCK, UNLOCK, SHAPE, SIZE, READ, WRITE, IOCTL, EVENT).
len– twee bytes, little-endian. Het aantal payloadbytes dat na de header volgt. Een lengte van nul is toegestaan – veel bevestigingen en kleine commando’s dragen geen payload.crc– twee bytes. Een CRC-16 over de voorgaande acht header-bytes. Een ontvanger die een header met een slechte CRC krijgt, laat het hele pakket vallen zonder zelfs maar naar de payload te kijken.
12.3.2. De payload¶
Nul of meer bytes, door de framing-laag als ondoorzichtig behandeld. Wat er in de payload zit hangt af van de opcode: voor een CHANNEL_READ-antwoord is het de werkelijke kanaaldata; voor een GET_CAPS-antwoord is het een kleine vaste structuur; voor een kanaal-write is het wat de host ook maar heeft verzonden.
De maximale payloadgrootte hangt af van de grootte van de protocolbuffer van de cam (zie de tabel per board in protocol.init()). Berichten die langer zijn dan de limiet worden opgesplitst in fragmenten met de FRAGMENT-vlag gezet op alle behalve het laatste.
12.3.3. De afsluitende CRC¶
Vier bytes, een CRC-32 over de payload. Vangt corruptie op die de header-CRC niet kan zien, met name bij lange payloads waar een single-bit-fout midden in een frame anders door de mazen zou glippen.
Het opsplitsen van de integriteitscontrole over twee CRC’s is bewust. De header-CRC beschermt de framing-velden zelf – met name de payloadlengte. Zonder een aparte header-CRC zou een enkele bit-flip in de lengtebyte ervoor zorgen dat de ontvanger het verkeerde aantal bytes voor de payload leest en volledig uit synchronisatie raakt met de bytestroom; mét zo’n CRC wordt een beschadigde header meteen verworpen en zoekt de ontvanger opnieuw naar het volgende sync-woord. De payload-CRC beschermt vervolgens de berichttekst als een afzonderlijke kwestie, zodat een bit-flip in de data wordt gemeld als een corrupte payload in plaats van te worden aangezien voor een framing-fout.
Het formaat is klein genoeg om byte voor byte door te lopen, en het feit dat elk pakket dezelfde indeling heeft – sync, dan header, dan payload, dan CRC – betekent dat een met de hand geschreven parser in een scherm vol code past. Daarom is een kleine host-implementatie in C, Python of Rust een weekendproject; de protocolbibliotheek is de onderhouden Python-versie aan elke kant.