История разработки мессенджера Mercury, часть 2: полный P2P
Две хорошие новости для любителей интернета, технологий, мессенджеров и дневников разработки.
Как вы, конечно, помните, я разрабатываю мессенджер неподвластный цензуре и свободный от подписок и рекламы. Ну или посмотрите предыдущий пост Как написать собственный мессенджер и сохранить рассудок, кто не помнит.
Первая версия мессенджера, про которую был предыдущий пост, работала на технологии WebRTC: это хорошо проработанный набор протоколов для установления прямого соединения между устройствами через интернет и передачи текстовой/бинарной и медиа информации, такой как голос и видео. WebRTC настолько популярен, что, в общем-то, все видеоконференции сейчас работают на этом фреймворке - его поддержка вшита во все браузеры а для мобильных разработчиков поставляются и регулярно обновляются готовые библиотеки. Если очень кратко, два клиента, которые хотят установить прямое соединение, получают информацию о своем присутствии в интернете от STUN-сервера (сокр. от англ. Session Traversal Utilities for NAT, это сетевой протокол, который позволяет клиенту определить свой внешний IP-адрес, способ трансляции адреса и порта во внешней сети) и публикует все что нашел на особом сигнальном сервере. Сигнальный сервер для обоих клиентов должен быть один и тот же, а STUN-сервера - какие угодно, их много публичных и бесплатных.
Проблемы начинаются, когда один или оба клиента спрятаны за NAT (Network Adress Translation, это технология, которые используют роутеры чтобы преобразовать адреса внутренней сети в адреса интернета и обратно) и входящие соединения невозможны, то есть в современном интернете - практически всегда. Для того, чтобы устройства все-таки смогли как-то установить соединение, WebRTC предполагает использование TURN-серверов (Traversal Using Relays around NAT), специальных реле, которые передают зашифрованные аудио/видео/данные потоки между устройствами когда прямое соединение не может быть установлено. Для своего приложения я использовал TURN-сервера от metered.ca.
Когда я опубликовал первую версию мессенджера, внезапно обнаружилось, что metered.ca в России заблокирован, давно и прочно. Общение не задалось.
Так вот, первая хорошая новость - я, наконец-то, полностью, окончательно и бесповоротно (потому что я никогда не возьмусь переделывать это взад) перевел мессенджер на libp2p. Это открытый фреймворк для разработки P2P приложений, со встроенным шифрованием, обходом NAT и поиском клиентов в распределенных хэш-таблицах. libp2p подразумевает, что где-то в интернете должны быть доступны стартовые ноды с известными адресами, а дальше по мере роста количества клиентов, распределенная сеть будет становиться все устойчивее и устойчивее. Пока я выкатил 4 стартовые ноды, и, если их заблокируют, я легко смогу перевыпустить их с новыми адресами и обновить приложение.




Япония, к слову, не блокирует ничего пока, там и первая версия работала. Но обновленная - намного лучше.
libp2p работает немного похоже на WebRTC но есть и принципиальные отличия. Например, когда клиент ААА хочет установить соединение с клиентом АББ, в случае WebRTC этим занимался сигнальный сервер - он знал контактные данные обоих клиентов и дружил их друг с другом:
В случае libp2p, никакого сервера больше нет, некому сообщить ААА контактные данные АББ и наоборот. Но вместо этой потенциальной точки отказа, у нас есть распределенная хэш-таблица с контактными данными, где ААА может запросить контакты АББ и инициировать соединение. Дальше либо будет установлено прямое соединение если это возможно, если нет, то потоки данных будут транслироваться через одну из нод, до которой оба ААА и АББ соединения уже установили. Практически можно сказать, что вместо одного большого сигнального сервера у нас теперь много маленьких сигнальненьких серверочков.
Аудио и видео звонки я оставил работать через WebRTC, для этого в свои ноды я добавил встроенный TURN-сервер на основе открытого coturn. Так как контакты обоих устройств уже известны - вы не можете позвонить не установив соединение - сигнальный сервер не нужен. 4 слабеньких ноды - это, конечно, не панацея, но пару сотен одновременных звонков выдержат. В теории, если надо, и для усиленной безопасности, люди смогут публиковать в интернете свои собственные ноды - и привязать их к приложению, это все уже реализовано.
И это вторая хорошая новость - я собираюсь открыть исходники под какой-нибудь подходящей лицензией, и уже начал подготовку - автосборки, автоформат кода, автовыполнение тестов при открытии пулл-реквестов, и все такое. Процесс небыстрый, к сожалению.
Из других нововведений: добавил групповые чаты, один аккаунт теперь может быть зарегистрирован на нескольких устройствах, все они будут синхронизированы, улучшена передача файлов.
В следующем посте, пожалуй, расскажу об интересном механизме синхронизации сообщений. Так как мой мессенджер не имеет серверной части, вся переписка хранится на устройстве. Для переезда с одного телефона на другой, можно сделать зашифрованный бэкап, но если единственный телефон умер - переписку не восстановить. Но есть вариант загрузить всю историю сообщений от ваших собеседников! И она загрузится. Если, конечно, вы не потеряли сам аккаунт, так что не забывайте сохранять фразу безопасности в надежном месте.
Если захотите пощупать это приложение самостоятельно, ссылку на Google Play я оставлю в комментариях.







