Jeśli ktoś jeszcze nie zna - Tox to protokół komunikacyjny (i rodzina komunikatorów) obsługujący chat, przesyłanie plików, rozmowy głosowe oraz wideo, całkowicie p2p - bez serwerów ani supernode'ów jak Skype. Pierwszorzędnym celem projektu jest prostota użytkowania i intuicyjność, cel drugorzędny to prywatność. To, moim zdaniem, projekt którego świat otwartych protokołów komunikacyjnych potrzebował, bo XMPP nadaje się co najwyżej do chatu albo przesyłania XML-i, a SIP ma niewiele wspólnego z niezawodnością i prostotą obsługi. Tox naprawdę działa, nawet za pięcioma firewallami emacsem przez sendmail, chociaż implementacje klientów mogą pozostawiać jeszcze trochę do życzenia.
Projekt Tox jest bardzo ładnie podzielony na klienty i bibliotekę z referencyjną implementacją protokołu. Po bliższym przyjrzeniu się, okazało się że libtoxcore udostępnia dość wysokopoziomowe API, które z kolei pozwala na wysyłanie dowolnych pakietów i wybranie czy mają być stratne czy nie. Pakiety są w sposób przezroczysty dla użytkownika szyfrowane, przepuszczane przez firewall i onion-routowane przez pośredników (z bardzo małym opóźnieniem w porównaniu np. do Tora).
W obliczu takich faktów po prostu nie mogłem nie napisać programu który tuneluje połączenia TCP przez sieć Toxa. Program składa się z serwera - uruchamianego na maszynie do której chcemy się łączyć, za pięcioma firewallami, emacsem przez sendmail - i klienta - na maszynie z której łączymy się do serwera. Serwer generuje sobie identyfikator w sieci Tox, który spisujemy bądź podajemy koledze, który następnie podaje go klientowi. Poza tym, klient działa jak lokalne forwardowanie portów w SSH, jeśli wiesz co robi ssh -L 2222:localhost:22, wiesz jak działa klient (ukradłem nawet składnię SSH).
Wewnętrznie trzeba było opracować mini-protokół do otwierania nowych tuneli, zamykania istniejących i segmentacji/składania strumieni TCP po obu stronach. Protokół pozwala na otwarcie do 65536 strumieni na jednym serwerze - zakładając że nikt nie będzie używał tego programu do sprzedaży narkotyków za bitcoiny, będzie OK ;)
Robiłem testy opóźnień i przepustowości. Dwa komputery miały w normalnych warunkach (bez Toxa) RTT pinga ~50 ms i wolniejszy z nich był na łączu 60/6 Mbit. Pingi zaimplementowałem jako część protokołu więc może być tak, że popełniłem tu jakiś błąd bo sockety w C programowałem ostatnio dobrze ponad 10 lat temu. Wyszło że RTT zależy mocno od ścieżki którą klient sobie obierze (przypominam - onion routing). Przy niektórych połączeniach było stałe 100-150 ms, a zaraz potem po zabiciu i ponownym wystartowaniu klienta już 500 ms z pojedynczymi pakietami idącymi nawet kilka sekund. Ale nawet przy takim połączeniu dało się używać tunelowanego SSH w miarę interaktywnie - było znacznie lepiej niż w pociągu po 3G.
Testy przepustowości wypadły lepiej i nauczyły mnie czegoś nowego o protokole. Używałem NetStraina i przy tym samym połączeniu prędkość wahała się między 500 kbit/s a 5 Mbit/s przy wysyłaniu i nawet do 17 Mbit/s przy odbieraniu (przypominam - łącze było asymetryczne i ograniczone do 6 Mbit/s wysyłania). Jestem w stanie uwierzyć że 17 Mbit/s nie jest ograniczeniem Toxa ani węzłów pośredniczących tylko programu, który przy tej prędkości wyrzucał do konsoli ogromne ilości danych. Przy okazji dowiedziałem się o protokole czegoś, czego nie wiedziałem - monitorowałem iftopem ruch wychodzący z mojego komputera i nie było żadnego pojedynczego hosta do którego szło, dajmy na to, to 17 Mbit/s. Ruch szedł do kilku hostów i sumował się do 17 Mbit/s (około). Uważam że to rewelacyjne :)
Program nie jest gotowy, w tej chwili wyszedł już ze stadium proof of concept ale ma swoje problemy implementacyjne. Moje C trochę zardzewiało i niektóre rzeczy robię źle (np. trochę cieknie pamięć). Docelowo chcę mieć również możliwość forwardowania standardowego wejścia/wyjścia do zdalnego portu żeby móc używać programu jako ProxyCommand w SSH.
Jeśli ktoś chce mimo wszystko potestować to tu są źródła a tu binarki.