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/rasync

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

Так появился RatCast — аналог комнат Discord, позволяющий организовывать видео- и аудиоконференции. Специально для него поверх librats создана библиотека libratcast.

Это аналог librist/SRT, позволяющий передавать видео и аудио в реальном времени. Для стриминга в приоритете AV1 + Opus. Если их поддержки нет, используется fallback на H.265, а затем на H.264. По возможности задействуются аппаратные кодеры и декодеры, например av1_nvenc на видеокартах NVIDIA.

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

Таким образом, с участниками можно соединяться как напрямую, почти без задержек, так и через MCU-серверы на базе Rendezvous-узлов.

В итоге возможны несколько вариантов соединения, и из них выбирается наиболее эффективный:

стриминг идет напрямую участникам

стриминг идет напрямую участникам
p2p участник является ретранслятором (MCU-сервером)

p2p участник является ретранслятором (MCU-сервером)
c replay сервером

c replay сервером

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

Пока данный проект еще в альфе. Но потиху движется :).

Пока бинарники доступны для Linux и Windows, Mac OS X версия еще не готова.


Спасибо всем за внимание.

ссылка на оригинал статьи https://habr.com/ru/articles/1099136/