Files
utun2/tools/chatgui-android/doc/ARCHITECTURE.md
T
evgeny 38c9f229bc stcp: ed25519 pubkey exchange in handshake, fix instance destroy segfault, fix chat_tcp_test
- u_async.c: process immediate_queue BEFORE epoll_wait in uasync_poll
- stcp_link.c: defensive NULL etcp_conn/etcp_link in stcp_link_close
- utun_instance.c: move stcp_server_list_destroy_all to Phase J (before ETCP),
  add deferred drain in both Phase J and L
- stcp.h/c: STCP_HS_ENC_CLIENT 6→38, STCP_HS_ENC_SERVER 7→39,
  exchange ed25519_pubkey in both handshake directions
- etcp_connections.c: copy peer_ed25519 from STCP to ETCP_CONN in
  etcp_link_enter_ready_tcp; guard link->etcp in tcp_link_close_cb
- chat_sync.c: fix lk->conn NULL dereference for TCP links
- test_stcp.c: update stcp_server_create/stcp_client_connect callsites
- tools/chat_tcp_test: change transport udp→tcp
2026-08-07 00:48:27 +03:00

282 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# chatgui-android — Архитектура
## 1. Обзор
Android-версия чатгуи: P2P чат на базе STCP (Secure TCP) вместо ETCP/UDP.
Весь UDP-стек (ETCP, BBR, loadbalancer, pkt_normalizer, NAT, routing, TUN) исключён.
Сетевой транспорт: только STCP (X25519 + AES-CCM поверх TCP).
Приложение работает в двух режимах:
- **Headless** — без UI, с управляющим TCP-сокетом (для отладки сетевого стека)
- **Full UI** — Android приложение с Jetpack Compose интерфейсом
## 2. Уровни приложения
```
┌─────────────────────────────────────────────────┐
│ Android App (Kotlin / Jetpack Compose) │
│ ├─ UI Layer (Compose) │
│ │ ├─ ChannelListScreen │
│ │ ├─ ChatScreen (MessageList + InputBar) │
│ │ ├─ CreateChannelDialog │
│ │ └─ JoinChannelDialog │
│ ├─ ViewModel Layer │
│ │ └─ ChatViewModel (StateFlow, Coroutines) │
│ ├─ Repository Layer │
│ │ ├─ ChatRepository (JNI → native) │
│ │ └─ DbRepository (Room, read-only) │
│ └─ NativeLib.kt (JNI declarations) │
├─────────────────────────────────────────────────┤
│ JNI Bridge (C: android_jni_bridge.c) │
│ ├─ Kotlin → C: init/send/create/connect │
│ └─ C → Kotlin: callbacks via JNI CallVoidMethod │
├─────────────────────────────────────────────────┤
│ Headless Control (встроен в libutun_lite) │
│ ├─ TCP control socket (текстовый протокол) │
│ ├─ Команды: connect, send, status, debug, ... │
│ └─ Events: MSG, PEER_ONLINE/OFFLINE, ... │
├─────────────────────────────────────────────────┤
│ libutun_lite.so │
│ ├─ Core: uasync, ll_queue, memory_pool, │
│ │ debug_config, timeout_heap │
│ ├─ Crypto: secure_channel (X25519+AES-CCM), │
│ │ crc32, sha256 │
│ ├─ Transport: STCP (server/client/link) │
│ ├─ Chat: chat_core, chat_event, chat_sync, │
│ │ member_sync, merkle_sync │
│ ├─ DB: sqlite3 (WAL, чтение из GUI, запись │
│ │ из uasync) │
│ └─ Platform: socket_compat, platform_compat │
│ (Linux/Android) │
└─────────────────────────────────────────────────┘
```
## 3. Потоковая модель (Android)
- **Main thread (UI)** — Compose rendering, ViewModel state
- **uasync thread** — event loop (один на процесс, как и в desktop-версии)
- STCP соединения: каждое = одно TCP-соединение в uasync
- chat_core: все DB-записи из этого потока
- chat_sync: P2P синхронизация через STCP
- **DB:** SQLite WAL mode
- uasync thread: INSERT/UPDATE/DELETE (через chat_core)
- Main thread: SELECT (через Room/DbRepository, read-only)
## 4. Потоковая модель (Headless, Linux)
Один процесс, один uasync-поток. Всё в одном потоке, включая control socket.
Дополнительный поток для control socket не нужен — uasync обрабатывает и сеть и control-команды.
## 5. STCP вместо ETCP — изменения
### 5.1. Что уходит
| Модуль | Причина |
|--------|---------|
| ETCP (etcp.c, etcp_api.c, etcp_connections.c, etcp_router.c, etcp_loadbalancer.c, etcp_bbr.c, etcp_connect.c) | Заменено на STCP link |
| BBR (bbr_v3.c) | Congestion control для ETCP |
| pkt_normalizer.c | Фрагментация/сборка — не нужна для потокового STCP |
| dummynet.c | Эмулятор сети для отладки ETCP |
| tun_if/tun_linux/tun_windows/tun_route | Нет VPN-туннеля |
| routing, route_lib, route6_lib, route_ping, route_connectivity | Нет роутинга трафика |
| eim_nat, nat_transport | Нет NAT-транспорта |
| topo_group, topo_node, topo_node_lmdb | BGP-топология — прямые P2P |
| conn_mgr | Менеджер ETCP-соединений |
| firewall, proxy/*, lwip_tcp/*, uip/* | Не нужны |
| ntp_time, ntp_node_time | Пока не нужны (можно добавить позже) |
| packet_dump, etcp_debug, etcp_dump | Отладочные утилиты ETCP |
### 5.2. chat_sync — адаптация
Десктопная версия chat_sync использует ETCP-роутер: множество каналов мультиплексируется
через одно ETCP-соединение. В Android-версии каждое P2P-соединение — отдельный STCP линк.
Замены в chat_sync.c:
- `etcp_send(conn, svc_id, data)` → `stcp_link_send(link, data)`
- `etcp_api_bind(svc_id, callback)` → приём из `stcp_link` rx_queue
- Каждый peer = одно `stcp_link` соединение
- Сервер: `stcp_server_listen()` принимает входящие
### 5.3. merkle_sync — адаптация
merkle_sync — универсальный протокол синхронизации на Merkle-деревьях.
В десктопе работает поверх ETCP-сервиса. В Android-версии:
- Вместо etcp_send в рамках ETCP-сервиса → отправка напрямую через stcp_link
- Формат wire-сообщений не меняется (MSG_HASHES, MSG_REQUEST, MSG_BATCH)
- Изменяется только транспорт: вместо ETCP datagram → STCP stream
## 6. Control Socket (Headless)
Управляющий TCP-сокет для отладки и управления без UI.
Аналог `control_server` из utun, но с текстовым протоколом для простоты ручного тестирования.
Порт: настраивается в конфиге (по умолчанию 9999).
### Команды (клиент → сервер)
```
connect <addr> <port> [pubkey_hex] — STCP-подключение к пиру
disconnect <node_id> — отключиться от пира
connections — список активных STCP-соединений
create_channel <name> — создать канал
invite <channel_id> — invite-ссылка (utun://...)
join <invite_string> — подключиться по invite
send <channel_id> <text> — отправить сообщение
messages <channel_id> [limit] — последние сообщения
channels — список каналов
status — статус (соединения, каналы, ключи)
debug <cat>=<level> — debug level на лету
debug_level — показать уровни отладки
subscribe <events> — подписаться на push-события
help — список команд
quit — отключиться от control (не остановка сервера)
```
### Unsolicited events (сервер → клиент, только после subscribe)
```
EVENT MSG <channel_id> <author_hex> — новое сообщение
EVENT PEER_ONLINE <node_id_hex> — пир подключился
EVENT PEER_OFFLINE <node_id_hex> — пир отключился
EVENT CHANNEL_CREATED <channel_id> — канал создан (локально)
EVENT CHANNEL_JOINED <channel_id> — канал принят (по invite)
EVENT CONN_RESULT <node_id_hex> <ok|err> — результат connect
EVENT DB_READY — БД открыта и готова
EVENT STATUS <text> — периодический статус
```
## 7. База данных (SQLite)
Схема та же, что в десктопной версии chatgui (см. `tools/chatgui/doc/desc.txt`).
БД открывается в WAL-режиме. Записи — из uasync-потока, чтение — из любого.
Таблицы:
- `channels` — каналы (channel_id, name, ключи X25519/Ed25519, подписи)
- `msg_<channel_id>` — сообщения per-channel (id, author, content_type, data, timestamp, chain_hash, signature)
- `peers_<channel_id>` — участники канала (node_id, online, x25519, ed25519, join_sig, адреса)
- `nodes` — узлы (node_id, x25519_pubkey, ed25519_pubkey, name, online)
- `node_addresses` — адреса узлов (node_id, family, address, port)
- `accounts` — локальные аккаунты/контакты
- `ui_state` — key-value для UI состояния
- `merkle_tree_hash` — сохранённые хеши Merkle-дерева
- `local_identity` — локальные ключи узла
## 8. Структура каталогов
```
tools/chatgui-android/
├── doc/
│ ├── ARCHITECTURE.md # этот документ
│ └── IMPL_PLAN.md # план реализации с этапами
├── libutun_lite/ # урезанное C-ядро (статическая библиотека)
│ ├── CMakeLists.txt
│ └── utun_lite.h # публичное API
├── headless/ # CLI для Linux (тестирование без Android)
│ ├── CMakeLists.txt
│ ├── headless_main.c # точка входа
│ └── headless_control.c/h # управляющий TCP-сокет
├── jni_bridge/ # JNI прослойка
│ ├── CMakeLists.txt # (только для Android NDK)
│ └── android_jni_bridge.c # JNI-функции + коллбэки
├── app/ # Android приложение
│ ├── build.gradle.kts
│ └── src/main/
│ ├── AndroidManifest.xml
│ ├── cpp/ # NDK: jni_bridge + линковка libutun_lite
│ │ └── CMakeLists.txt
│ ├── java/com/utun/chat/
│ │ ├── ChatApplication.kt
│ │ ├── MainActivity.kt
│ │ ├── ui/screens/ # Compose экраны
│ │ ├── ui/components/# Compose компоненты
│ │ ├── viewmodel/ # ViewModels
│ │ ├── data/ # Repository, NativeLib.kt, Room DAOs
│ │ └── headless/ # HeadlessService.kt (фоновый сервис)
│ └── res/
└── CMakeLists.txt # корневой (для headless + libutun_lite)
```
## 9. Минимальный набор C-файлов (libutun_lite)
### lib/ (infrastructure)
- `u_async.c/h` — event loop (epoll на Linux, poll/select fallback)
- `ll_queue.c/h` — lock-free очередь с хеш-индексом
- `memory_pool.c/h` — пулы объектов
- `debug_config.c/h` — логирование (уровни, категории, файл/консоль)
- `timeout_heap.c/h` — min-heap таймеров
- `sha256.c/h` — SHA256 (fallback; приоритет OpenSSL)
- `mem.c/h` — u_malloc/u_free/u_calloc (wrappers)
- `platform_compat.c/h` — кроссплатформенность (byte order, time, random)
- `socket_compat.c/h` — кроссплатформенные сокеты
- `serialize.c/h` — бинарная сериализация
### src/transport_layer/ (crypto + STCP)
- `secure_channel.c/h` — AES-CCM + X25519 key exchange + pubkey obfuscation
- `crc32.c/h` — CRC32 checksum
- `stcp.c/h` — STCP connection lifecycle (session keys, buffers, state machine)
- `stcp_server.c/h` — STCP server (listen, accept, handshake)
- `stcp_client.c/h` — STCP client (connect, handshake)
- `stcp_link.c/h` — STCP link management (обёртка над stcp_conn для etcp-подобного API)
### src/chat/ (чатовая логика)
- `chat_core.c/h` + `chat_core_priv.h` — центральный API чата (send, create channel, connect)
- `chat_event.c/h` — система нотификаций (MSG_RECEIVED, PEER_ONLINE, ...)
- `chat_channel.c` — операции с каналами (создание, invite, join)
- `chat_msg.c` — приём/отправка/сохранение сообщений
- `chat_status.c` — сбор статуса для control socket / UI
- `chat_profile.c` — профиль узла (имя, ключи)
- `chat_sync.c/h` — P2P синхронизация (адаптирована под STCP)
- `member_sync.c/h` — синхронизация мемберов
- `merkle_sync.c/h` — Merkle-дерево синхронизации
- `db_sync.c/h` — DB синхронизация (вставка/обновление записей синхронизации)
### Упрощённый вариант src/ (без TUN/ETCP/BGP)
- `utun_instance_lite.c/h` — облегчённый instance (только ua, my_keys, db, stcp_server, control_socket)
- `config_parser.c/h` — парсинг конфига (без ETCP/TUN/BGP-секций)
### Внешние
- `lib/sqlite3.c/h` — SQLite amalgamation
- OpenSSL (Crypto) — SHA256, AES-CCM, X25519, Ed25519
## 10. Конфиг (chatgui-android.cfg)
Формат INI, упрощённый относительно десктопной версии:
```ini
[node]
private_key = hex...
public_key = hex...
node_name = My Node
listen_port = 12345 ; STCP server port
[control]
port = 9999 ; управляющий сокет
bind_ip = 127.0.0.1
[db]
path = chat_data/chats.db
[debug]
console_level = info
file_level = debug
log_file = utun.log
debug_categories = stcp=debug,chat_core=info
```
## 11. Отличие от десктопной версии
| Аспект | Desktop (chatgui) | Android (chatgui-android) |
|--------|------------------|--------------------------|
| UI | Qt 6 Widgets (C++) | Jetpack Compose (Kotlin) |
| Bridge | gui_bridge (Qt signals) | JNI callbacks + StateFlow |
| Core сборка | CMake → libutun.a (все src/) | CMake → libutun_lite.a (выборочно) |
| Транспорт | ETCP (UDP) + STCP (TCP) | STCP только (TCP) |
| VPN | TUN + routing + BGP | Нет |
| NAT | EIM NAT engine | Нет |
| Аудио | miniaudio + opus | Нет (пока) |
| Эмодзи/анимации | rlottie + TGS | Нет (пока) |
| QR | zxing-cpp | Нет (пока) |
| FFmpeg | Да | Нет |
| Control | control_server (binary protocol) | headless_control (text protocol) |
| Платформы | Linux, FreeBSD, Windows | Linux (headless), Android (app) |