Le protocole
Voici ce qu’un feeder, un relais ou un client doit parler pour interopérer. La référence est le crate wire du dépôt Tally, le seul code du dépôt qui encode ou décode le protocole, et tous les binaires l’utilisent. Les entiers sont partout en big-endian.
Transport
Chaque saut utilise Noise_IK_25519_ChaChaPoly_BLAKE2s sur TCP. Chaque message Noise est précédé d’une longueur sur deux octets, fait au plus 65 535 octets tag compris, et ne transporte que des enregistrements entiers.
L’identité est une seule clé Ed25519. La clé X25519 qu’authentifie Noise en est dérivée (sk_to_curve25519 de libsodium), et le premier message de handshake de l’initiateur porte sa clé publique Ed25519 de 32 octets, que le répondeur compare à la clé prouvée par le handshake. Une seule clé désigne une antenne partout.
Le préambule
Avant le handshake, l’initiateur envoie 16 octets en clair. Ils servent aussi de prologue Noise, si bien qu’un octet modifié fait échouer le handshake, et ils permettent au handshake lui-même d’évoluer plus tard, et à un relais de détenir une ancienne et une nouvelle clé pendant une rotation.
Versions
L’initiateur envoie ensuite Hello avec les versions de protocole la plus basse et la plus haute qu’il parle, et son rôle. Le répondeur répond Welcome avec la version que tous deux parleront désormais, ou Goodbye avec une raison et le délai à attendre. Du premier octet à Welcome, il s’écoule au plus 15 secondes, et chaque envoi qui suit a une échéance de 30. La version de protocole 1 est la seule à ce jour.
Un relais accepte, pour toujours, toute version de protocole qu’un feeder a jamais livrée. Les feeders installés ne se mettent pas à jour, et tout le reste du protocole repose sur cette règle.
Enregistrements
Un enregistrement est un octet de type, une longueur de corps sur deux octets, puis le corps. Voici les types que connaît la version 1 du protocole :
Règles d’évolution
Les feeders ne se mettent jamais à jour ; voici donc les règles qui permettent au protocole d’évoluer sans eux :
- Un type inconnu est ignoré, sauf si son bit de poids fort (0x80) le marque comme critique, ce qui termine proprement la session. Un nouvel enregistrement n’est donc pas critique, sauf si l’ignorer serait une erreur.
- Un corps peut porter des octets après les champs qu’un lecteur connaît, et ceux-ci sont ignorés. Les nouveaux champs s’ajoutent à la fin.
- Un lecteur conserve une valeur d’énumération qu’il ne connaît pas comme la valeur Other, jamais comme une erreur.
- Une forme signée garde le même préfixe dans chaque version de format et se termine par sa signature sur tout ce qui la précède, si bien qu’un relais peut vérifier, router et dédoublonner un format qu’il ne sait pas lire par ailleurs.
- Le format d’une observation est l’octet de type de BEAST lui-même pour le 1090 MHz. L’UAT 978 MHz prend de nouvelles valeurs sans nouvel enregistrement, et les relais transmettent les formats qu’ils ne connaissent pas.
Le lot signé
Un lot correspond à environ une seconde de réceptions d’un même récepteur. Le format 1 se présente ainsi :
Formats d’observation : 1 pour Mode A/C (2 octets), 2 pour Mode-S court (7), 3 pour Mode-S long (14), D pour une liaison descendante UAT 978 MHz, U pour une liaison montante UAT depuis le sol, chacun écrit sous la forme de son caractère ASCII.
La signature couvre le texte ASCII tally batch, un octet nul, et chaque octet du lot avant la signature. Les lots dédoublonnés propres à un relais signent tally relay batch à la place, si bien que l’un ne peut jamais passer pour l’autre.
L’identité d’un lot est le hachage BLAKE2s-256 de tous ses octets, signature comprise. Les relais dédoublonnent sur cette base, et le champ Précédent du lot suivant y fait référence.
Les 49 premiers octets (format, clé, identifiant de démarrage et séquence) gardent leur place dans tout format futur, et la signature vient toujours en dernier.
Personne ne calibre jamais les compteurs avant la MLAT : la MLAT d’un relais a besoin du compteur brut pour calculer une position.