MAM append использует один sync вместо четырёх, SM checkpoint — один вместо двух. Checksummed redo journals сохраняют commit-before-ACK и восстанавливают native archive/SM JSON exports после аварии. - Ограничены рост журналов, ротация и tombstone GC. Старый `.rappend` и legacy JSON импортируются. Retain/save/purge не возвращают удалённые записи. - Recovery синхронизирует валидный journal перед публикацией состояния; проверка checksum не заменяет durability barrier. EIO при adoption блокирует startup или offline handoff. Новые fault fixtures проверяют сохранность журнала и retry. - Replay SM проверяет checksum/JSON всех frames, но создаёт и валидирует полный Record только для последнего snapshot, сокращая работу с superseded queues. - `message-processing-slow` содержит времена MAM отправителя/получателя, доставки, carbons, offline/push и handled, а также число ресурсов/копий. Payload и секреты не добавляются в логи. - Добавлена offline команда `storage-checkpoint CONFIG`: durable экспорт и передача archive writer/подготовка отката на legacy Rust. Не запускайте другого writer и не удаляйте journals до успешного завершения команды. - Новые crash, partial-write, corruption, EIO, recovery, handoff и latency регрессии включены в GitHub Actions через verify-local.sh; отчёты сохраняются. Измерения, ограничения и эксплуатация: [docs/DURABLE-MESSAGE-IO.md](docs/DURABLE-MESSAGE-IO.md), [docs/VALIDATION-0.8.3.md](docs/VALIDATION-0.8.3.md).
261 lines
18 KiB
Markdown
261 lines
18 KiB
Markdown
# Rust XMPP 0.8.3
|
||
|
||
Сервер на 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/COMPATIBILITY.md),
|
||
проверки — в [docs/VALIDATION.md](docs/VALIDATION.md).
|
||
|
||
Нестандартные HTTP-пути и TLS reverse proxy: [docs/HTTP-PROXY.md](docs/HTTP-PROXY.md).
|
||
Пример для слияния с действующим конфигом: `examples/reverse-proxy.fragment.yaml`.
|
||
|
||
MUC и восстановление после сбоя, включая SM resume:
|
||
[docs/MUC-RECOVERY.md](docs/MUC-RECOVERY.md).
|
||
Изменения 0.8.0: [CHANGELOG-0.8.0.md](CHANGELOG-0.8.0.md).
|
||
|
||
Встроенный http_altconnect: [docs/HTTP-ALTCONNECT.md](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 фиксирует зависимости; первая сборка требует их загрузки.
|
||
|
||
```bash
|
||
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. Сертификаты и аккаунты в исходный архив не включены.
|
||
|
||
## Существующий конфиг без редактирования
|
||
|
||
```bash
|
||
./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 наследуются из исходного файла.
|
||
|
||
```bash
|
||
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:
|
||
|
||
```bash
|
||
./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`.
|
||
|
||
```bash
|
||
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](scripts/prosody_compat/README.md).
|
||
|
||
```bash
|
||
./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](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](CHANGELOG-0.6.1.md) и
|
||
[docs/ANDROID-SASL.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](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](CHANGELOG-0.7.5.md).
|
||
|
||
## HTTP Upload в 0.7.9
|
||
|
||
Несколько upload components с разными HTTP hosts или mounts и S3-compatible
|
||
gateway с multipart streaming описаны в [docs/HTTP-UPLOAD.md](docs/HTTP-UPLOAD.md).
|
||
Добавлены offline миграция с SHA-256/resume, точечная очистка multipart и
|
||
карантин неопределённого completion. Реальные 10 GiB через MinIO проверены с
|
||
описанной адаптацией тестовой среды. Изменения и границы подтверждения —
|
||
[CHANGELOG-0.7.9.md](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 служит собственный журнал. Перед откатом ознакомьтесь с
|
||
[порядком переключения](docs/MUC-RECOVERY.md). Произвольные community Lua-модули
|
||
не выполняются; неизвестные явно включённые MUC-модули отклоняются при запуске.
|
||
Результаты проверки — в
|
||
[docs/VALIDATION-0.8.0.md](docs/VALIDATION-0.8.0.md).
|
||
|
||
## GitHub Actions и Gitea Registry
|
||
|
||
Полные тесты, Linux binary artifact и Docker push после проверок:
|
||
[настройка workflow](docs/GITHUB-ACTIONS.md). Registry и credentials задаются
|
||
через GitHub Actions variables/secrets.
|
||
|
||
## Задержка сообщений в0.8.1
|
||
|
||
Устранены полный проход по MUC-архиву на каждом сообщении, повторные записи
|
||
неизменённых native-файлов и no-op CSI checkpoints. Проверенный сценарий
|
||
с100000 MAM-записей: median MUC delivery2.5с→4.7мс на loopback.
|
||
[Причины, измерения и границы](docs/MESSAGE-LATENCY.md).
|
||
|
||
## Личные сообщения в0.8.2
|
||
|
||
Push routing больше не блокирует отправителя/SM ACK; CSI defaults немедленно
|
||
передают bodyless OMEMO и receipts. Bind2/MAM metadata не сканируют всю историю.
|
||
[Причины, тесты и конфигурация](docs/PERSONAL-MESSAGE-LATENCY.md).
|
||
|
||
## Durable IO личных сообщений в0.8.3
|
||
|
||
Сокращены последовательные sync MAM/SM через checksummed redo journals,
|
||
добавлены замеры этапов медленной обработки и crash/replay проверки.
|
||
Перед передачей файлов Prosody/откатом выполните offline `storage-checkpoint`.
|
||
[Durability, команда handoff и диагностика](docs/DURABLE-MESSAGE-IO.md).
|