Files
rust-xmpp/README.md
T
wt e9329ccbb2
Test, build and publish / All tests and Linux binary (push) Failing after 23s
Test, build and publish / Container smoke test and Gitea publish (push) Skipped
- Исправлена задержка доставки MUC с растущим архивом: после каждого
сообщения
  больше не выполняется полный scan/rewrite архива для expiry. Очистка
  остаётся
  в maintenance и перед MAM-запросами; append и crash checkpoint до
  fanout сохранены.
- Неизменённые native config/persistent index не перезаписываются при
  каждом
  сообщении. Удалённые файлы восстанавливаются, ошибки экспорта
  повторяются.
- CSI больше не сохраняет SM snapshot при отсутствии изменения durable
  очереди.
  Изменённая очередь сохраняется до отправки; при ошибке записи очередь
  откатывается.
- Личные сообщения, IQ и входящая федерация к аккаунтам больше не
  захватывают
  общий MUC mutex, ожидая несвязанную работу с комнатными архивами.
- Добавлены регрессии native exports/archive scanning/CSI rollback и
  реальный
  TLS latency check в verify-local.sh, автоматически включённый и в CI.

Измерения и границы подтверждения:
[docs/MESSAGE-LATENCY.md](docs/MESSAGE-LATENCY.md).
Результаты итогового прогона:
[docs/VALIDATION-0.8.1.md](docs/VALIDATION-0.8.1.md).

- Личные сообщения и SM ACK больше не ждут сетевую отправку push.
  Уведомления
  отправляются через очередь1024 с максимум8параллельных маршрутов;
  worker
  и его задачи отменяются при завершении serve. Ошибки очереди/маршрута
  логируются.
- Offline сообщение сохраняется до публикации push, чтобы проснувшийся
  клиент
  мог сразу получить его. Подтверждена очередь при первом TLS stream
  push gateway.
- По умолчанию CSI считает важными bodyless OMEMO legacy/2, delivery
  receipts
  и chat markers. Явный список `csi_important_payloads` заменяет
  расширенные defaults.
  Низкоприоритетный headline по-прежнему буферизуется. Policy
  обновляется и при SM resume.
- Выбор адресатов и carbons фильтрует владельцев до захвата session
  mutex;
  зависшая сессия чужого аккаунта не задерживает этот путь. Duplicate SM
  ACK
  без изменения durable counters/queue не переписывает snapshot.
- Bind2 и MAM metadata IQ читают только первый/последний native record
  вместо
  сканирования всей истории. Индекс не требуется; recovery/лимиты записи
  сохранены.
- Добавлен `message-processing-slow`: обработка message дольше250мс,
  поля
  duration_ms/route, без payload/токенов. Это время обработки сервером,
  не peer receipt.
- Новые сетевые регрессии включены в verify-local.sh/GitHub CI.

Причины, изменение CSI policy, измерения и ограничения:
[docs/PERSONAL-MESSAGE-LATENCY.md](docs/PERSONAL-MESSAGE-LATENCY.md).
2026-10-21 11:20:09 +07:00

18 KiB
Raw Blame History

Rust XMPP 0.8.2

Сервер на Rust, разрабатываемый для замены Prosody 13.0 nightly 100, cafd74b9c5ea с предоставленными модулями. Читает существующий Lua-конфиг, а также JSON, YAML/YML и TOML. Использует внутреннее файловое хранилище Prosody: конвертация аккаунтов и истории для проверенных сценариев не нужна. Nginx не требуется: HTTPS, WebSocket, BOSH и загрузка файлов обслуживаются самим сервером; coturn остаётся отдельным сервисом.

Это работающая экспериментальная реализация, полная взаимозаменяемость ещё не достигнута. Уже реализованы вход, сообщения, контакты, MAM, MUC, PEP/pubsub, закладки, offline, carbons, SM, push, TLS-федерация и HTTP. Точные ограничения перечислены в docs/COMPATIBILITY.md, проверки — в docs/VALIDATION.md.

Нестандартные HTTP-пути и TLS reverse proxy: docs/HTTP-PROXY.md. Пример для слияния с действующим конфигом: examples/reverse-proxy.fragment.yaml.

MUC и восстановление после сбоя, включая SM resume: docs/MUC-RECOVERY.md. Изменения 0.8.0: CHANGELOG-0.8.0.md.

Встроенный http_altconnect: docs/HTTP-ALTCONNECT.md.

Сборка и изолированный запуск

Нужны Rust 1.99.1 (rustup установит версию из rust-toolchain.toml), C-компилятор и make. Для тестовых сертификатов и сетевых проверок нужны OpenSSL CLI, Bash и Python 3; HTTP-тест дополнительно использует Python websockets. Системные CA-сертификаты нужны для проверки удалённых серверов федерации. Cargo.lock фиксирует зависимости; первая сборка требует их загрузки.

cd rust-xmpp
cargo build --release --locked
bash scripts/make-demo.sh
./target/release/rust-xmpp serve demo/config.toml --experimental

Demo слушает только 127.0.0.1:55222 и создаёт отдельное хранилище demo/data. Аккаунты: alice@localhost / alice-test-only и bob@localhost / bob-test-only. Для ручного клиента используйте STARTTLS и доверьте сгенерированному demo/cert.pem. make-demo.sh не перезаписывает существующий demo. Сертификаты и аккаунты в исходный архив не включены.

Существующий конфиг без редактирования

./target/release/rust-xmpp check-config /etc/prosody/prosody.cfg.lua
./target/release/rust-xmpp serve /etc/prosody/prosody.cfg.lua --experimental

check-config проверяет разбор и базовые типы; ограничения runtime проверяются при serve. Существующий Lua-файл читается непосредственно, преобразовывать его в другой формат не требуется. Процессу нужны права на сертификат, ключ, каталог данных и Unix admin socket. Используйте тот же UID/GID, что и Prosody, чтобы сохранять доступ при возврате к нему.

Первую проверку выполняйте на копии данных с отдельными портами: сервер пишет аккаунты, историю, комнаты и другие данные в обычном режиме. Одновременно запускать Rust и Prosody с одним каталогом данных нельзя. Между экземплярами Rust действует блокировка inode каталога данных, в том числе при разных портах и путях-синонимах. Prosody в этой блокировке не участвует. Команда create-user также отказывается писать в каталог работающего Rust-сервера; для изменения аккаунтов во время работы используйте admin shell. Для переключения остановите один процесс и запустите другой. Резервная копия нужна для проверки отката до переключения рабочего сервера; тестирование формата не доказывает совместимость всех ваших записей.

Ваш Docker Compose

Распакуйте каталог rust-xmpp рядом с исходным docker-compose.yml. Дополнительный файл заменяет образ только сервиса prosody. Порты, тома, healthcheck prosodyctl check и сервис coturn наследуются из исходного файла.

docker compose -f docker-compose.yml -f rust-xmpp/compose.override.yml config
docker compose -f docker-compose.yml -f rust-xmpp/compose.override.yml up -d --build prosody

Эта команда запускает сервер на томах из исходного Compose; применяйте её после проверки на копии. Исходные docker-compose.yml и prosody.cfg.lua редактировать не требуется. Образ содержит CA-сертификаты и команду prosodyctl, совместимую с указанным healthcheck. Это проверка ответа работающего процесса через admin socket, а не полный аналог диагностики prosodyctl check.

Entrypoint определяет UID/GID владельца /var/lib/prosody и запускает процесс с этими правами, не меняя рекурсивно владельцев существующих файлов. Если каталог принадлежит root, а файлы внутри другому UID, задайте XMPP_UID и XMPP_GID в окружении контейнера через дополнительный Compose-файл. При другом пути данных задайте также XMPP_DATA_DIR. Выбранный пользователь должен читать TLS-ключ и писать данные. Docker-образ в среде разработки не собирался: здесь нет Docker; состав образа и override подготовлены, но запуск на целевом Docker ещё предстоит проверить.

Форматы конфигурации

Все форматы используют одну структуру: global и hosts; у хоста есть options и, для компонента, component. Надёжнее получить её из Lua:

./target/release/rust-xmpp convert /etc/prosody/prosody.cfg.lua json config.json
./target/release/rust-xmpp convert /etc/prosody/prosody.cfg.lua yaml config.yml
./target/release/rust-xmpp convert /etc/prosody/prosody.cfg.lua toml config.toml
./target/release/rust-xmpp check-config config.yml

Конвертер сохраняет области настроек и Include, не меняет исходный файл, не перезаписывает существующий выходной и создаёт его с правами 0600. Выходной файл содержит секреты конфигурации. Lua выполняется в ограниченной VM без системных библиотек; произвольные Lua-плагины не исполняются. Поддержка Lua в проекте также нужна для точного чтения файлов данных Prosody.

Команды и проверки

Полный локальный прогон: bash scripts/verify-local.sh. XMPP_LOAD_CHECK=1 добавляет нагрузочный сценарий; настройки native Prosody для дополнительных проверок описаны в scripts/prosody_compat/README.md.

cargo test --locked
cargo clippy --locked --all-targets -- -D warnings
cargo build --release --locked
python3 scripts/smoke.py                    # после make-demo.sh
python3 scripts/integration_xmpp.py
python3 tests/sasl_network.py --spawn --hash sha1
python3 tests/sasl_network.py --spawn --hash sha256
python3 tests/sasl2_bind.py target/release/rust-xmpp
python3 scripts/integration_http.py         # требует websockets
python3 scripts/load_smoke.py --clients 500 --accounts 100 --rounds 10 --message-rounds 10 --archive

Все сетевые тесты создают отдельные тестовые данные; кроме smoke с портом 55222, выбирают свободные loopback-порты. Оригинальная Prosody отдельно проверяет формат данных и пароли: инструкции в scripts/prosody_compat/README.md.

./target/release/rust-xmpp create-user CONFIG USER --password-stdin
./target/release/rust-xmpp check [CONFIG]
./target/release/rust-xmpp shell CONFIG 'server:status()'

Пароль create-user принимает через stdin; существующий аккаунт не заменяет. Admin shell реализует ограниченный набор команд управления сервером и аккаунтами. Произвольный Lua-код и горячая перезагрузка модулей не поддержаны.

Дополнительный SASL2 Bind2

Модуль sasl2_bind2 (alias bind2) включает привязку ресурса внутри SASL2, inline SM/CSI/Carbons и MAM metadata. Добавьте его в modules_enabled вместе с sasl2 только если эта функция нужна. Исходный конфиг по-прежнему работает без включения нового модуля. Ресурс генерируется случайно; прежние соединения того же аккаунта с тем же валидным UUIDv4 user-agent завершаются после успешного входа. Inline возобновление SM через SASL2 поддерживается, в том числе после перезапуска при наличии действующей сохранённой SM-сессии.

PEP, push и pre-authenticated roster

В 0.5.0 исправлены ответы disco для bare JID аккаунта. При включённых pep и cloud_notify (они уже есть в предоставленном конфиге) изменение конфига не требуется. После обновления переподключите аккаунт в клиенте, чтобы повторить service discovery. Push требует также настройки клиентского push-сервиса; реальный APNs/FCM шлюз здесь не имитируется.

При включённом roster клиент может обнаружить и вызвать контактную ad-hoc команду urn:xmpp:invite#invite на серверном JID. Она возвращает xmpp:…?roster;preauth=… и срок действия. Регистрацию аккаунта такое приглашение не разрешает. XEP-0379 presence tokens сохраняются даже для неизвестных серверу приглашений, созданных самим клиентом.

Переподключение в 0.6.0

Повторная привязка одного ресурса по умолчанию заменяет старое соединение, как в Prosody. conflict_resolve поддерживает kick_old, kick_new, increment и random. Если явно задан kick_new, занятый ресурс по-прежнему получит protocol conflict — это выбранная политика.

SM восстанавливается при гонке со старым TCP и внутри SASL2. Исправлено освобождение ресурсов при BOSH/WebSocket close. Подробности: CHANGELOG-0.6.0.md.

Android SASL в 0.6.1

Добавлен tls-server-end-point для TLS1.2/1.3 и исправлена SSDP-проверка соединений WebSocket без channel binding. Причина воспроизводимого not-authorized в Conversations, область тестирования и ограничения описаны в CHANGELOG-0.6.1.md и docs/ANDROID-SASL.md.

Логирование в 0.7.0

Добавлены журнал TLS/SASL/bind/SM с единым connection ID, точные причины отказов, файлы/console, JSON/plain и SIGHUP rotation reopen. Для диагностики Conversations/monocles используйте docs/LOGGING.md.

Исправления 0.7.5

Cached SASL2 Bind2/SM requests допускают legacy fallback, XEP-0258/0077 объявляются для Gajim; policy/classifications схема может использоваться как каталог labels. Дубликаты одинаковых log destinations устранены. Подробности — CHANGELOG-0.7.5.md.

HTTP Upload в 0.7.9

Несколько upload components с разными HTTP hosts или mounts и S3-compatible gateway с multipart streaming описаны в docs/HTTP-UPLOAD.md. Добавлены offline миграция с SHA-256/resume, точечная очистка multipart и карантин неопределённого completion. Реальные 10 GiB через MinIO проверены с описанной адаптацией тестовой среды. Изменения и границы подтверждения — CHANGELOG-0.7.9.md.

MUC и SM после сбоя в 0.8.0

MUC фиксирует конфигурацию, роли, членство и ограниченную историю без MAM до публикации соответствующего ответа. Последний сохранённый журнал позволяет восстановить persistent и временные комнаты после аварийной остановки. Heartbeat обновляет живое состояние; срок уже ожидающего восстановления не продлевается повторным запуском. muc_recovery_grace_period задаётся в секундах: по умолчанию 300, пределы 1..604800.

Действующие приватные SM-записи восстанавливают логические сессии и MUC до открытия listeners, поэтому offline-доставка может попасть в сохранённую очередь. XEP-0198 resume через legacy SASL или SASL2 требует нового TLS/SASL-транспорта и токена того же владельца; TCP/TLS-сокеты не сохраняются. Без действующей SM-записи MUC ожидает новую аутентификацию точного полного JID и available presence либо обычный явный MUC-вход.

Native-файлы экспортируются для Prosody; источником согласованного crash recovery Rust служит собственный журнал. Перед откатом ознакомьтесь с порядком переключения. Произвольные community Lua-модули не выполняются; неизвестные явно включённые MUC-модули отклоняются при запуске. Результаты проверки — в docs/VALIDATION-0.8.0.md.

GitHub Actions и Gitea Registry

Полные тесты, Linux binary artifact и Docker push после проверок: настройка workflow. Registry и credentials задаются через GitHub Actions variables/secrets.

Задержка сообщений в0.8.1

Устранены полный проход по MUC-архиву на каждом сообщении, повторные записи неизменённых native-файлов и no-op CSI checkpoints. Проверенный сценарий с100000 MAM-записей: median MUC delivery2.5с→4.7мс на loopback. Причины, измерения и границы.

Личные сообщения в0.8.2

Push routing больше не блокирует отправителя/SM ACK; CSI defaults немедленно передают bodyless OMEMO и receipts. Bind2/MAM metadata не сканируют всю историю. Причины, тесты и конфигурация.