librats: Выпуск версии 3.0.x (библиотека для распределённых P2P-приложений и стриминга). И 3 приложения на ней

Всем привет! Я продолжаю развивать свою библиотеку для создания распределённых приложений. Она уже легла в основу новой версии rats-search (распределённый торрент-поисковик) и rasync (синхронизация папок, файлов и исходников между устройствами) и ratcast (распределенный видео-аудио стриминг и приложение наподобие Discord для совместного просмотра фильмов и видео-конференций с более высоким качеством и большим количеством участников и сложной p2p+MCU топологией), а также librats, судя по всему, используется в стороннем клиенте UltraVNC (VNC-клиент).
Библиотека позволяет развернуть собственную P2P-сеть, связать пользователей между собой и выстроить обмен данными через потоки разных типов — бинарные, строковые и другие. Главная особенность — автоматическое обнаружение участников (peer discovery) на основе mDNS и DHT Mainline протоколов без необходимости в серверах, что особенно актуально в условиях постоянных блокировок и сетевых ограничений. Общения происходит напрямую - без посредника.
На данный момент поддерживаются C/C++, Java (Android), Python и Node.js.
В этом обновлении значительно улучшен собственный QUIC-подобный протокол поверх UDP: добавлена поддержка app-limited-режима, управление перегрузкой переведено на BBRv3, реализована полноценная прямая коррекция ошибок (FEC), улучшен обход NAT, а также появился модуль rendezvous для развёртывания вспомогательных серверов, повышающих связность сетей.
Последний стабильный релиз на сегодня — 3.0.3. Исходный код и собранные бинарные файлы доступны для:
Windows (64-bit) / Windows (arm)
Linux (64-bit) / Linux (arm)
Android (32-bit / 64-bit)
macOS (arm)
librats официально доступен в репозитории Microsoft пакетного менеджера vcpkg и conan
https://github.com/librats/librats - на github
Доступ к функционалу библиотеки из других языков организован по принципу FFI (Foreign Function Interface).

Поддерживается следующие возможности:
Поиск пиров в сети — автоматическое обнаружение участников через DHT (совместим с BitTorrent Mainline DHT) для глобальной сети и через mDNS для локальной.
Обход NAT без настройки роутера — встроенная поддержка UPnP, NAT-PMP, STUN, Hole punching (координация через модуль PEX) и Relay. Библиотека сама просит роутер пробросить порт, поэтому пиры за NAT могут принимать входящие соединения без ручной настройки. Используются разные механизмы прохода роутеров вплоть до node-релей механизмов где каждый участник помогает связывать всех со всеми.
Сквозное шифрование — протокол Noise (Curve25519 + ChaCha20-Poly1305) с автоматическим управлением ключами, взаимной аутентификацией и совершенной прямой секретностью.
Передача файлов — потоковая отправка файлов и целых папок с контролем целостности, возможностью паузы/возобновления/отмены и атомарной доставкой.
Масштабируемый обмен сообщениями — протокол GossipSub для публикации/подписки по темам с организацией сообщений и их фильтрацией.
Поддержка многих языков — единый API для C++, C, Node.js (с TypeScript), Java/Android и Python, работающий на Windows, Linux, macOS и Android.
Равноправная поддержка UDP и TCP — В librats 3.x используется QUIC-подобный протокол, доработанный для app-limited-сценариев и построенный на современных алгоритмах: BBRv3 для управления перегрузкой, RACK для обнаружения потерь, FEC для их восстановления и др. Он одинаково хорошо подходит как для передачи файлов, так и для видеостриминга.
Удобный API для разработчика — событийная модель (
on(),once(),off()), обмен сообщениями в JSON, отслеживание состояния соединений в реальном времени и гибкая система логирования.
Теперь подробнее остановлюсь на отдельных изменениях и улучшениях версии 3.0.x, а затем перейду к приложениям на основе librats.
Прежний UdpStream, по сути один байтовый поток поверх UDP, удалён. Вместо него появился собственный движок, устроенный по образцу QUIC, с шифрованием на базе Noise.
Теперь для каждого типа сообщений используется отдельный поток, и потеря пакета тормозит только тот поток, который его вёз. Блокировка начала очереди (head-of-line blocking) между подсистемами устранена: передача файлов, gossip и служебные сообщения больше не мешают друг другу, а разные типы потоков (например, видео и аудио) получили собственные настраиваемые приоритеты.
Появилась полноценная миграция соединений. Если вы используете librats на телефоне, переключение между мобильной сетью и Wi-Fi больше не рвёт соединение.
Появилась поддержка разгрузки GSO/GRO на Linux и USO/URO на Windows. Это позволяет ещё эффективнее использовать гигабитные каналы и снижает нагрузку на CPU при передаче данных.
Реализовано управление перегрузкой BBRv3. Многое было честно позаимствовано из реализации Google для ядра Linux :) Однако даже она не идеальна для стриминга видео и аудио и для медленных потоков, где BBR — не лучшее решение, поэтому доработок пришлось сделать немало. Алгоритм Reno тоже сохранён: для любителей ретро, а заодно для сравнения и поиска регрессий.
Улучшен пейсинг: сложность обработки ACK-пакетов снижена с O(размер окна) до O(объём фактической работы). Внутренний оптимизатор доволен :).
Появилась поддержка Live-сообщений, которые допустимо терять, если они не успели дойти вовремя. Это именно то, что нужно для видеостриминга в реальном времени.
Появилась поддержка FEC (прямой коррекции ошибок). В связке BBR + FEC librats теперь гораздо увереннее работает в сетях с плохим качеством связи: при потерях 1–10 % пакетов скорость почти не падает и проблем с передачей практически не возникает.

Появилась статистика путей (PathStats) — обратная связь для управления стримингом: оценка полосы пропускания, pacing rate, RTT, потери, счётчики и т. п.
В версии 3.0.3 появилась подсистема Rendezvous. Два узла за NAT, которые знают друг друга только по общему ключу и не имеют общих пиров, находят друг друга через публичный сервер.
Сервер одновременно сообщает каждому из них внешний адрес (endpoint) другого, и попытки подключения в режиме hole punching идут навстречу друг другу. Если пробить NAT не удалось, соединение идёт через relay.
Подводя итог именно улучшений библиотеки теперь librats себя будет чувствовать гораздо увереннее в передаче данных - во многих тестах и замерах скорость передачи у меня выросла в 2-3 раза на том же интернет-канале, а передача видео/аудио и других потоков имеющих низкую скорость разгона и непостоянные зубчатые формы теперь не являются ограничением. Так же как плохие сети: плохой пинг, потери, дальнее расстояние - в гораздо меньшей степени будут сказываться на качестве соединения.
Для начала давайте пройдёмся по тому, что уже есть, чтобы не бежать впереди паровоза.
rats-search — это торрент-поисковик на Qt/C++. Он собирает базу данных торрентов, а участники P2P-сети могут искать по ней файлы и торренты, а также синхронизировать свои поисковые базы между собой.
https://github.com/librats/rats-search/releases
rats-search обновлён до версии 2.3.5. Он по-прежнему работает на ветке librats 2.x, но в ближайшее время перейдёт на свежую.
В последних версиях тоже немало улучшений. В том числе участники теперь могут обмениваться большими базами на миллион торрентов и больше: появилась полная репликация, тогда как до ветки 2.3 была возможна только частичная. Об этом меня не раз просили :) Также немного улучшен дизайн, а в настройках теперь можно выбрать себе шрифт.

Другая программа на основе библиотеки — rasync, распределённый аналог rsync. Он позволяет синхронизировать папки, исходный код и другие данные между устройствами. По сути, вы просто запускаете rasync на разных устройствах, и папки всё время остаются синхронизированными.
https://github.com/librats/rasync/releases
Работает это так. На одном компьютере вы запускаете:
rasync --key s3cr3t --discover ./documents ./photos ./codeгде ключ служит одновременно и ключом синхронизации, и ключом безопасности для шифрования данных. На другом устройстве вы делаете, в целом, то же самое — и получаете на выходе те же папки с документами, фотографиями и кодом. И так продолжаем делать с другими устройствами где вам нужна синхронизация.
можно поиграться с настройками или указать например другой путь для того же каталога
rasync --key s3cr3t --discover ./somefolder --name documents ./photos ./codeВ таком варианте документы сохранит в каталог с другим названием. А --discover включает обнаружение через все доступные источники (mDNS/DHT).

Пока тоже на 2.x
Ну и наконец переходим к новому. Мы с друзьями часто собираемся вместе посмотреть фильмы и сериалы. Discord у многих заблокирован, а вдобавок качество выше 720p там — только ПЛАТИ. Что ж, будем решать этот вопрос.
https://github.com/librats/ratcast/releases
Так появился RatCast — аналог комнат Discord, позволяющий организовывать видео- и аудиоконференции. Специально для него поверх librats создана библиотека libratcast.
Это аналог librist/SRT, позволяющий передавать видео и аудио в реальном времени. Для стриминга в приоритете AV1 + Opus. Если их поддержки нет, используется fallback на H.265, а затем на H.264. По возможности задействуются аппаратные кодеры и декодеры, например av1_nvenc на видеокартах NVIDIA.

Топология сети тоже устроена любопытно. Поскольку не раз звучало мнение, что P2P — не лучший вариант для стриминга, у RatCast есть также SFU/MCU-узлы и relay-узлы.
Таким образом, с участниками можно соединяться как напрямую, почти без задержек, так и через MCU-серверы на базе Rendezvous-узлов.
В итоге возможны несколько вариантов соединения, и из них выбирается наиболее эффективный:



Таким образом 7 участников сети могут выстроиться в такую замысловатую схему:

Пока данный проект еще в альфе. Но потиху движется :).
Пока бинарники доступны для Linux и Windows, Mac OS X версия еще не готова.
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.