Protokół
Tak musi mówić feeder, przekaźnik lub klient, aby współpracować z resztą sieci. Wzorcem jest crate wire w repozytorium Tally, jedyny kod w nim, który koduje lub dekoduje protokół, i używa go każdy plik wykonywalny. Liczby całkowite są wszędzie zapisywane jako big-endian.
Transport
Każdy przeskok to Noise_IK_25519_ChaChaPoly_BLAKE2s przez TCP. Każda wiadomość Noise jest wysyłana po dwubajtowym polu długości, ma najwyżej 65 535 bajtów razem z tagiem i przenosi wyłącznie całe rekordy.
Tożsamość to jeden klucz Ed25519. Klucz X25519, który uwierzytelnia Noise, jest z niego wyprowadzany (sk_to_curve25519 z libsodium), a pierwsza wiadomość handshake’u inicjatora zawiera jego 32-bajtowy klucz publiczny Ed25519, który strona odpowiadająca porównuje z kluczem potwierdzonym w handshake’u. Jeden klucz wszędzie identyfikuje jedną antenę.
Preambuła
Przed handshake’iem inicjator wysyła 16 bajtów otwartym tekstem. Są one zarazem prologiem Noise, więc zmiana choćby jednego bajtu powoduje niepowodzenie handshake’u. Dzięki nim sam handshake może się w przyszłości zmienić, a przekaźnik może podczas rotacji trzymać stary i nowy klucz.
Wersje
Następnie inicjator wysyła Hello z najniższą i najwyższą obsługiwaną wersją protokołu oraz swoją rolą. Strona odpowiadająca odpowiada Welcome z wersją, której obie strony będą odtąd używać, albo Goodbye z powodem i czasem oczekiwania. Od pierwszego bajtu do Welcome mija najwyżej 15 sekund, a każde wysłanie po nim ma limit 30 sekund. Wersja protokołu 1 jest na razie jedyna.
Przekaźnik obsługuje na zawsze każdą wersję protokołu, w jakiej kiedykolwiek wydano feeder. Zainstalowane feedery się nie aktualizują, a na tej zasadzie opiera się cała reszta protokołu.
Rekordy
Rekord to bajt typu, dwubajtowa długość treści i sama treść. Oto typy znane wersji 1 protokołu:
Zasady zmian
Feedery nigdy się nie aktualizują, więc oto zasady, które pozwalają zmieniać protokół bez nich:
- Nieznany typ jest pomijany, chyba że jego najwyższy bit (0x80) oznacza go jako krytyczny, co w uporządkowany sposób kończy sesję. Nowe rekordy nie są więc krytyczne, chyba że zignorowanie ich byłoby błędem.
- Treść może zawierać bajty za polami, które zna czytelnik, i są one ignorowane. Nowe pola dodaje się, dopisując je na końcu.
- Czytelnik zachowuje nieznaną sobie wartość wyliczenia jako wartość Other, nigdy jako błąd.
- Forma podpisana zachowuje ten sam prefiks w każdej wersji formatu i kończy się podpisem obejmującym wszystko przed nim, więc przekaźnik może weryfikować, kierować i deduplikować format, którego poza tym nie odczytuje.
- Format obserwacji to bajt typu z samego BEAST dla 1090 MHz. UAT 978 MHz dostaje nowe wartości i nie potrzebuje nowego rekordu, a przekaźniki przekazują dalej formaty, których nie znają.
Podpisana paczka
Paczka to około sekundy odbiorów jednego odbiornika. Format 1 ma taki układ:
Formaty obserwacji: 1 to Mode A/C (2 bajty), 2 to krótka Mode-S (7), 3 to długa Mode-S (14), D to downlink UAT 978 MHz, U to naziemny uplink UAT, każdy zapisany jako swój znak ASCII.
Podpis obejmuje tekst ASCII tally batch, bajt zerowy i każdy bajt paczki przed podpisem. Własne zdeduplikowane paczki przekaźnika podpisują zamiast tego tally relay batch, więc jedna nigdy nie może udawać drugiej.
Tożsamość paczki to skrót BLAKE2s-256 ze wszystkich jej bajtów, łącznie z podpisem. Przekaźniki deduplikują na jego podstawie, a wskazuje go pole Poprzednia następnej paczki.
Pierwsze 49 bajtów (format, klucz, identyfikator uruchomienia i numer kolejny) zachowuje swoje miejsce w każdym przyszłym formacie, a podpis zawsze jest na końcu.
Nikt nigdy nie kalibruje liczników przed MLAT: MLAT przekaźnika potrzebuje surowego licznika, żeby wyznaczyć pozycję.