Browse Source

docs: update file inventory and module header contracts

Refresh both AGENTS guides and clarify module purpose, usage, ownership, threading, return values and wire formats in headers. Remove the unused timeout_heap freed_count field and unimplemented getter.
master
evgeny 4 days ago
parent
commit
a97e8bcc1f
  1. 163
      AGENTS.md
  2. 10
      lib/audio_compressor.h
  3. 13
      lib/debug_config.h
  4. 5
      lib/json_flat.h
  5. 6
      lib/ll_queue.h
  6. 7
      lib/mem.h
  7. 8
      lib/memory_pool.h
  8. 6
      lib/opus_codec.h
  9. 4
      lib/platform_compat.h
  10. 11
      lib/serialize.h
  11. 2
      lib/silero_vad.h
  12. 5
      lib/socket_compat.h
  13. 3
      lib/speex_aec.h
  14. 3
      lib/swm_min.h
  15. 1
      lib/timeout_heap.c
  16. 22
      lib/timeout_heap.h
  17. 8
      lib/u_async.h
  18. 5
      src/broadcast.h
  19. 6
      src/chat/chat_core_priv.h
  20. 6
      src/chat/chat_headless_control.h
  21. 2
      src/chat/invite_build.h
  22. 7
      src/chat/invite_link.h
  23. 5
      src/config_parser.h
  24. 3
      src/config_updater.h
  25. 3
      src/dm/dm_core.h
  26. 11
      src/eim_nat.h
  27. 5
      src/firewall.h
  28. 5
      src/lwip_tcp/lwip_pbuf.h
  29. 7
      src/lwip_tcp/lwip_tcp.h
  30. 3
      src/lwip_tcp/lwip_tcp_opts.h
  31. 3
      src/lwip_tcp/lwip_tcp_priv.h
  32. 8
      src/media_async/attachment.h
  33. 11
      src/media_async/attachment_send.h
  34. 7
      src/media_async/voice_file.h
  35. 6
      src/media_delivery/media_delivery.h
  36. 4
      src/media_delivery/media_delivery_proto.h
  37. 5
      src/media_delivery/media_download.h
  38. 6
      src/media_delivery/media_index.h
  39. 5
      src/nat_transport.h
  40. 4
      src/ntp_node_time.h
  41. 5
      src/ntp_time.h
  42. 5
      src/proxy/icmp_proxy.h
  43. 8
      src/proxy/socks_proxy.h
  44. 5
      src/proxy/tcp_proxy_client.h
  45. 5
      src/proxy/tcp_proxy_server.h
  46. 4
      src/proxy/udp_proxy.h
  47. 2
      src/radio/radio_audio.h
  48. 4
      src/routing_layer/conn_mgr_priv.h
  49. 33
      src/routing_layer/route6_lib.h
  50. 4
      src/routing_layer/route_connectivity.h
  51. 13
      src/routing_layer/route_lib.h
  52. 13
      src/routing_layer/routing.h
  53. 9
      src/routing_layer/topo_node_sqlite.h
  54. 7
      src/transport_layer/crc32.h
  55. 4
      src/transport_layer/etcp_bbr.h
  56. 182
      src/transport_layer/etcp_connect.h
  57. 3
      src/transport_layer/etcp_debug.h
  58. 3
      src/transport_layer/etcp_dump.h
  59. 10
      src/transport_layer/etcp_loadbalancer.h
  60. 11
      src/transport_layer/etcp_session.h
  61. 3
      src/transport_layer/packet_dump.h
  62. 17
      src/transport_layer/pkt_normalizer.h
  63. 11
      src/transport_layer/secure_channel.h
  64. 4
      src/transport_layer/socket_monitor.h
  65. 10
      src/transport_layer/stcp.h
  66. 5
      src/transport_layer/stcp_client.h
  67. 6
      src/transport_layer/stcp_link.h
  68. 5
      src/transport_layer/stcp_server.h
  69. 6
      src/tun_if.h
  70. 44
      tools/chatgui-android/AGENTS.md
  71. 35
      tools/chatgui-android/headless/headless_control.h
  72. 6
      tools/chatgui-android/jni_bridge/android_jni_bridge.h
  73. 3
      tools/chatgui-android/libutun_lite/attachment_sender.h
  74. 23
      tools/chatgui-android/libutun_lite/instance_lite.h
  75. 13
      tools/chatgui-android/libutun_lite/invite_link_c.h
  76. 3
      tools/chatgui-android/libutun_lite/photo_sender.h
  77. 9
      tools/chatgui-android/libutun_lite/utun_config_api.h
  78. 4
      tools/chatgui-android/libutun_lite/video_sender.h
  79. 5
      tools/chatgui-android/libutun_lite/voice_recorder.h
  80. 6
      tools/chatgui/db/db_manager.h
  81. 1
      tools/chatgui/src/accountdelegate.h
  82. 2
      tools/chatgui/src/accountlist.h
  83. 2
      tools/chatgui/src/animtimer.h
  84. 2
      tools/chatgui/src/audiodevicesettingspage.h
  85. 3
      tools/chatgui/src/audiorecorder.h
  86. 1
      tools/chatgui/src/channeldelegate.h
  87. 2
      tools/chatgui/src/channellist.h
  88. 1
      tools/chatgui/src/channelsettingsdialog.h
  89. 2
      tools/chatgui/src/chatview.h
  90. 1
      tools/chatgui/src/creategroupdialog.h
  91. 1
      tools/chatgui/src/debug_ui.h
  92. 2
      tools/chatgui/src/emoji.h
  93. 1
      tools/chatgui/src/emojipanel.h
  94. 1
      tools/chatgui/src/emojitabbar.h
  95. 1
      tools/chatgui/src/flagpainter.h
  96. 2
      tools/chatgui/src/imageviewer_window.h
  97. 3
      tools/chatgui/src/inputbar.h
  98. 2
      tools/chatgui/src/invite_link.h
  99. 1
      tools/chatgui/src/inviteby.h
  100. 2
      tools/chatgui/src/invitedialog.h
  101. Some files were not shown because too many files have changed in this diff Show More

163
AGENTS.md

@ -233,7 +233,7 @@ warn / error - ошибки и предупреждения (аномалии).
Актуальные имена и константы — в `lib/debug_config.h`, текстовые имена — в `lib/debug_config.c`.
Основные: `sys`, `connection`, `etcp`, `crypto`, `config`, `tun`, `routing`, `timers`, `bgp`,
`socket`, `control`, `dump`, `traffic`, `debug`, `general`, `nat`, `keepalive`, `etcp_route`,
`media`, `etcp_dump`, `chat`, `chat_sync`, `member_sync`, `proxy`, `video`, `reality`, `dm`, `call`, `radio`.
`media`, `etcp_dump`, `chat`, `chat_sync`, `member_sync`, `proxy`, `video`, `reality`, `dm`, `call`, `radio`, `vad`, `aec`.
UASYNC/LL_QUEUE/MEMORY/TIMING объединены в SYS, NORMALIZER/BBR — в ETCP; старые числовые списки не использовать.
### Настройка отладки
@ -275,35 +275,44 @@ UASYNC/LL_QUEUE/MEMORY/TIMING объединены в SYS, NORMALIZER/BBR — в
### Directory Structure
```
├── lib/ # Core libraries, SQLite, libopus/liblmdb
├── lib/ # uasync, очереди, SQLite, Opus, SpeexDSP, Silero VAD, SoundTouch, LMDB
├── src/ # Main source code
│ ├── transport_layer/ # ETCP, crypto, STCP, normalizer, NCD, BBR
│ ├── transport_layer/ # ETCP, сессии, crypto, STCP/REALITY, SOCKS-клиент, NCD, BBR
│ ├── routing_layer/ # Routing, группы/BGP, recovery, conn_mgr, etcp_router
│ ├── chat/ # P2P чат, join, db_sync, merkle_sync, member_sync
│ ├── dm/ # Личные сообщения и mailbox
│ ├── dm/ # Личные сообщения, E2E-вложения и offline-mailbox
│ ├── call/ # Звонки и общий голосовой стек
│ ├── radio/ # Групповая PTT-рация
│ ├── proxy/ # SOCKS5, TCP/UDP/ICMP прокси
│ ├── lwip_tcp/ # Встроенный lwIP TCP стек
│ ├── media_delivery/ # Доставка медиафайлов
│ ├── media_async/ # Фоновые задачи медиа
│ └── *.c/h # utun, config, TUN, firewall, NAT, NTP, control
│ ├── media_delivery/ # Блоки медиа каналов и передача неизменяемых файлов
│ ├── media_async/ # Фоновые задачи, метаданные вложений, подготовка голоса/видео
│ ├── video/ # Пробинг и транскодирование видео через FFmpeg
│ ├── dnsmasq/ # Архив исходников для встроенной сборки dnsmasq
│ └── *.c/h # utun, instance, config, TUN, firewall, NAT, NTP, control, broadcast
├── tests/ # Состав тестов и цели запуска: tests/Makefile.am
├── doc/ # Technical Specifications
├── tools/ # Auxiliary tools
│ ├── etcpmon/ # GUI монитор ETCP
│ ├── chatgui/ # GUI чат (Qt 6 с Qt 5 fallback, сборка CMake)
│ ├── chatgui-android/ # Android P2P чат (Jetpack Compose + libutun_lite)
│ ├── logreceiver/ # Приём UDP-логов Android
│ ├── chat_tcp_test/ # Сценарий проверки чата через TCP
│ ├── lightsout/ # Отдельная игра Lights Out на Qt
│ ├── lightsout-android/ # Android-версия Lights Out
│ ├── tdesktop-dev/ # Референс: Telegram Desktop (только для изучения)
│ ├── proxy/ # UDP прокси для тестов
│ └── bping/ # BPing (bandwidth ping)
│ ├── bping/ # BPing (bandwidth ping)
│ └── chatcli # Headless CLI; описание команд — chatcli_commands.txt
├── tinycrypt/ # TinyCrypt crypto library (external)
├── net_emulator/ # Network emulator (delays, loss, reordering)
└── c2/ # Test instance 2 (конфиг и бинарник для тестов)
└── net_emulator/ # Network emulator (delays, loss, reordering)
```
### File Overview
Пути ниже относительны к каталогу секции; `name.c/h` означает пару `.c` и `.h`.
Перечислены модули проекта; внутренние файлы сторонних библиотек сгруппированы по каталогам.
**Core (src/)**
- `utun.c` - Main program entry point, CLI parsing, daemon mode
- `utun_instance.c/h` - Создание ядра и независимый жизненный цикл UTUN/чата, владение общими ресурсами
@ -326,6 +335,7 @@ UASYNC/LL_QUEUE/MEMORY/TIMING объединены в SYS, NORMALIZER/BBR — в
- `etcp.c/h` - ETCP protocol implementation (inflight queues, retrans, ACK, RTT/jitter)
- `etcp_api.c/h` - ETCP public API (send/recv/bind callbacks)
- `etcp_connections.c/h` - Socket and link management, INIT handshake, keepalive, PING/PONG
- `etcp_session.c/h` - Согласование эпох ETCP-сессии через HELLO/CHALLENGE/CONFIRM и проверка принадлежности DATA сессии
- `etcp_loadbalancer.c/h` - Multi-link load balancing with traffic shaper
- `etcp_debug.c/h` - ETCP packet dump/formatting
- `etcp_dump.c/h` - ETCP дамп/декодирование пакетов
@ -342,11 +352,13 @@ UASYNC/LL_QUEUE/MEMORY/TIMING объединены в SYS, NORMALIZER/BBR — в
- `stcp_server.c/h` - STCP сервер
- `stcp_client.c/h` - STCP клиент
- `stcp_link.c/h` - STCP линк-уровень
- `socks_client.c/h` - Исходящий SOCKS5-транспорт: TCP CONNECT и UDP ASSOCIATE с переподключением control-сокета
- `node_conn_direct.c/h` - Общий прямой транспорт к пиру с отдельным handle каждого владельца; обновление линков по адресам узла
- `socket_monitor.c/h` - Socket state monitoring
- `reality.c/h` - REALITY-style TLS ClientHello/ServerHello камуфляж для STCP
- `reality_fingerprint.c/h` - Статические отпечатки (cipher suites, groups, ALPN) для REALITY-камуфляжа
- `reality_relay.c/h` - Релей неавторизованных клиентов на реальный HTTPS-сайт
- `call_ring.c/h` - Кольцевой трейс контрольных точек освобождения ETCP/STCP-ресурсов для диагностики teardown/UAF
**BBR (src/transport_layer/BBR/)**
- `bbr_v3.c` - BBR congestion control algorithm v3
@ -355,10 +367,10 @@ UASYNC/LL_QUEUE/MEMORY/TIMING объединены в SYS, NORMALIZER/BBR — в
- `routing.c/h` - Routing table (local)
- `route_lib.c/h` - Routing library
- `route6_lib.c/h` - IPv6 routing
- `route_ping.c/h` - Route ping probing (NAT check, liveness)
- `route_ping.c/h` - Пинг цели через явно выбранного BGP-посредника для NAT-проверки
- `route_connectivity.c/h` - Route connectivity checks
- `topo_group.c/h` - Сессии UTUN/CHAT (JOIN/ACCEPT, эпохи, READY), групповые запросы, NODEINFO/WITHDRAW и владение NCD
- `topo_group_connect.c/h` - Подбор пиров CHAT-группы: исторические → суперузлы/публичные → локальные; отменяемые запросы до READY
- `topo_group_connect.c/h` - Подбор пиров CHAT-группы по роли: суперузлы → desktop → mobile; история/RTT внутри класса, backoff и standby burst
- `topo_group_invite.c/h` - Получение описания канала через INVITE_INFO_REQ/RESP; добавление мембера реализовано в chat_join/chat_sync
- `topo_node.c/h` - Node management (модель узла: TOPO_NODE/TOPO_GROUP_NODE, сериализация, node_registry)
- `topo_node_sqlite.c/h` - SQLite persistence for nodes
@ -366,6 +378,7 @@ UASYNC/LL_QUEUE/MEMORY/TIMING объединены в SYS, NORMALIZER/BBR — в
- `conn_mgr.h` + `conn_mgr_core.c`/`conn_mgr_indirect.c`/`conn_mgr_monitor.c` + `conn_mgr_priv.h` — Connection Manager (handle-based API, 3-phase DIR/REV/IND)
- `etcp_router.c/h` - ETCP router/multiplexer (мультиплексирование каналов, transit forwarding)
- `nat_detection.c/h` - NAT type detection
- `sock_match.c/h` - Классификация локальных сокетов и адресов пира, отбор совместимых пар для прямого подключения
- `route_crypto.c/h` - Пред/пост-обработка SVC_ROUTE пакетов (encrypt-then-sign)
**Chat (src/chat/)** — децентрализованный P2P чат: сообщения и участники автоматически синхронизируются между всеми узлами канала без центрального сервера.
@ -390,12 +403,42 @@ UASYNC/LL_QUEUE/MEMORY/TIMING объединены в SYS, NORMALIZER/BBR — в
- `invite_build.c/h` - Сборка invite-ссылок utun:// (выбор лучшего узла + адреса)
- `invite_link.c/h` - Кодирование utun://: версия, пароль, channel_id, join_key, Reality-параметры, ключ и адреса узла
**Личные сообщения (src/dm/)**
- `dm_core.c/h` - Беседы двух узлов, подписанные E2E-сообщения, SQLite/outbox, доставка через router/mailbox и квитанции
- `dm_crypto.c/h` - Вывод ID беседы и ключа X25519, AES-256-CCM сообщений и потоковое шифрование/проверка медиа
- `dm_mailbox.c/h` - Offline-очередь суперузла: хранение подписанных сообщений и повтор доставки до квитанции получателя
- `dm_media.c/h` - Подготовка, доставка и публикация E2E-вложений; ciphertext-хранилище и отдельные квитанции файлов
- `dm_media_priv.h` - Внутренние SQL/control-операции для dm_media и dm_mailbox_media
- `dm_mailbox_media.c/h` - Сохраняемые задания суперузла для размещения медиа, доставки метаданных и удаления копий до DELETE_ACK
**Звонки (src/call/)**
- `call.c/h` - Сигналинг и медиа P2P-звонка через ETCP-router, состояния звонка и оптимизация пути через conn_mgr
- `call_proto.h` - Wire-формат сигналинга и медиа, треки/кодеки, причины завершения
- `call_audio.c/h` - Общий аудио-движок: кодирование/декодирование Opus, jitter-буфер и тоны, API feed/pull PCM
- `call_jitter.cpp/h` - FIFO кодированных Opus-кадров, адаптивный запас и SoundTouch time-stretch при воспроизведении
- `call_jitter_window.h` - Окно из десяти секундных интервалов для оценки глубины очереди и изменения задержки доставки
- `call_tones.c/h` - Генерация PCM-тонов паузы и завершения звонка
- `call_headless.c/h` - Отдельный TCP-аудиосокет headless-клиента: обмен PCM; сигналинг остаётся на control-сокете
**Рация (src/radio/)**
- `radio.c/h` - Передача Opus по CHAT-группе, подписки, дедупликация и пересылка по ветвям с подписчиками
- `radio_proto.h` - Wire-формат PTT: источник, поток, seq, FIN и hop-list против циклов
- `radio_audio.c/h` - Общий аудио-движок: независимые RX/TX, Opus, микширование источников, ручной PTT и VAD-автомат
- `radio_jitter.cpp/h` - Буфер кодированных кадров каждого источника с pre-roll и SoundTouch time-stretch на pull
- `radio_vad.h` - Ресемплинг 48→16 кГц и автомат авто-PTT с подтверждением речи, задержкой завершения и учётом занятого канала
- `radio_headless.c/h` - TCP-аудиосокет headless-рации: PCM и команды начала/конца PTT
**Прокси (src/proxy/)**
- `socks_proxy.c/h` - SOCKS5 прокси
- `proxy_protocol.h` - Общий TCP-протокол и управление потоком: CONNECTED, DATA, кредит WINDOW, упорядоченный FIN
- `socks_proxy.c/h` - Клиентские SOCKS5 CONNECT и HTTP proxy/CONNECT, DNS и передача потока выбранному exit-узлу
- `udp_proxy.c/h` - UDP прокси
- `icmp_proxy.c/h` - ICMP прокси
- `tcp_proxy_server.c/h` - TCP прокси (серверная сторона)
- `tcp_proxy_client.c/h` - TCP прокси (клиентская сторона)
- `tcp_proxy_server.c/h` - Exit-сторона TCP-прокси: реальные исходящие сокеты, потоки по (peer, stream_id), окна и half-close
- `tcp_proxy_client.c/h` - Клиентская сторона TCP-прокси: адаптер TUN/lwIP и обмен с настроенным exit через ETCP-router
**lwIP TCP (src/lwip_tcp/)**
- `lwip_tcp.c/h` - lwIP TCP стек
@ -404,31 +447,39 @@ UASYNC/LL_QUEUE/MEMORY/TIMING объединены в SYS, NORMALIZER/BBR — в
- `lwip_tcp_priv.h`, `lwip_tcp_opts.h` - Внутренние настройки lwIP
**Media Delivery (src/media_delivery/)**
- `media_delivery.c/h` + `media_delivery_proto.h` - Доставка медиафайлов, протокол
- `media_download.c/h` - Скачивание медиа
- `media_index.c/h` - Индексация медиафайлов
- `media_delivery.c/h` - Доставка блоков медиа каналов, учёт держателей, репликация доступности между суперузлами и relay
- `media_delivery_proto.h` - Кодограммы канального медиа: QUERY, BLOCK_REQ/CHUNK/DONE, HAVE_BLOCK и SUPER_REPL
- `media_download.c/h` - Загрузка блоков с выбором держателей, failover, контролем простоя, проверкой подписей и сборкой файла
- `media_index.c/h` - Индекс media_files: UUID, хеши и подписи блоков, асинхронная регистрация и удаление медиа канала
- `file_transfer.c/h` - Передача неизменяемого файла между заданными узлами; авторизация lookup и владение CM handle до завершения
**Media Async (src/media_async/)**
- `media_async.c/h` - Фоновые crypto/file-задачи: work в pthread, done в uasync; destroy ждёт workers и завершает ожидающие callbacks с CANCELLED
- `attachment.c/h` - Общие метаданные file/voice/video, проверка и компактная wire-сериализация
- `voice_file.c/h` - Worker-кодирование PCM в контейнер Opus с длительностью и waveform для desktop/Android
- `attachment_send.c/h` - Асинхронная подготовка голоса/видео и отправка в зафиксированный канал или DM
**Libraries (lib/)**
- `u_async.c/h` - Async event loop (epoll/poll/select, timers via timeout_heap)
- `ll_queue.c/h` - Двусвязная очередь одного uasync-потока с callbacks, хеш-индексом и ожиданием свободного места
- `memory_pool.c/h` - Fast object pool allocator (pre-allocated blocks)
- `memory_pool.c/h` - Пул объектов: ленивое выделение и повторное использование, до 64 свободных объектов в кеше
- `debug_config.c/h` - Debug logging system (levels, categories, dual output, runtime config)
- `timeout_heap.c/h` - Min-heap for timer management (used by u_async)
- `mem.c/h` - Memory wrappers with leak tracking (`u_malloc`/`u_free`/`u_calloc`/`u_strdup`)
- `serialize.c/h` - Binary serialization utilities
- `swm_min.c/h` - Sliding window minimum (for RTT min tracking)
- `getmyip.c/h` - Get local IP / default route detection
- `getmyip.c/h` - Локальный IP, который ОС выберет для UDP к заданному адресу (bind/connect/getsockname)
- `myip.c` - My IP helper (no header)
- `socket_compat.c/h` - Cross-platform socket compatibility (Linux/FreeBSD/Windows)
- `platform_compat.c/h` - Cross-platform compatibility layer (byte order, time, random)
- `radix.c/h` - Radix tree for IP routing lookups
- `tcp_io.c/h` - TCP I/O abstraction (Windows IOCP, Linux epoll)
- `tcp_io.c/h` - Неблокирующий TCP поверх uasync/ll_queue: backpressure, FIN/close и callbacks
- `sqlite3.c/h` - SQLite3 amalgamation (embedded database)
- `opus_codec.c/h` - Opus audio codec wrapper
- `audio_compressor.c/h` - Audio dynamic range compressor
- `speex_aec.c/h` - Эхоподавление SpeexDSP: согласование playback/capture PCM через линию задержки и диагностика её заполнения
- `silero_vad.c/h` - Стриминговый VAD через ONNX Runtime: окна 512 отсчётов, 16 кГц моно, вероятность речи и сброс состояния
- `silero_vad_model.inc` - Встроенная ONNX-модель Silero VAD для silero_vad_create_default
- `json_flat.c/h` - Flat JSON parser
- `strbuf.c/h` - Безопасный растущий printf-буфер (замена snprintf-цепочек)
- `async_dns.c/h` - Асинхронный (неблокирующий) DNS-резолвер A-записей поверх uasync, адаптер над libdns
@ -437,6 +488,8 @@ UASYNC/LL_QUEUE/MEMORY/TIMING объединены в SYS, NORMALIZER/BBR — в
- `dr_mp3.h` - MP3-декодер (single-header, на базе minimp3)
- `liblmdb/` - Встраиваемый key-value store LMDB
- `libopus/` - Встраиваемый кодек Opus
- `speexdsp/` - Встроенные исходники эхоканселлера SpeexDSP и KISS FFT
- `soundtouch-master/` - SoundTouch: изменение темпа аудио в jitter-буферах звонка и рации
- `wintun.h` - Wintun API header for Windows TUN driver
**Memory Pools in UTUN_INSTANCE:**
@ -616,7 +669,7 @@ cmake .. && make -j4
| Файл | Назначение |
|------|-----------|
| `main.cpp` | Точка входа, инициализация QApplication |
| `mainwindow.h/cpp` | Главное окно, QSplitter (ChannelList \| MessageList \| AccountList), трей |
| `mainwindow.h/cpp` | Главное окно, списки каналов/DM/участников, сообщения, трей, события ядра и окна звонков |
| `chatview.h/cpp` | QListView с фоновым изображением, hover-сигнал, drag-to-select |
| `messagelist.h/cpp` | Модель сообщений из БД, обновления доставки/медиа, анимации, состояние просмотра канала |
| `messagedelegate.h/cpp` | QStyledItemDelegate: бабблы, текст, цитаты, реакции, оверлей анимаций |
@ -646,10 +699,22 @@ cmake .. && make -j4
| `storagesettingspage.h/cpp` | Страница настроек хранилища |
| `soundsettingspage.h/cpp` | Страница настроек звука |
| `audiodevicesettingspage.h/cpp` | Страница настроек аудиоустройств |
| `sound_manager.h/cpp` | Управление звуками/уведомлениями |
| `audiorecorder.h/cpp` | Запись голосовых сообщений (захват аудио) |
| `voicemessageencoder.h/cpp` | Кодирование голосовых сообщений (Opus) |
| `sound_manager.h/cpp` | Общий miniaudio-контекст, уведомления/PCM, микширование голоса, маршруты устройств и восстановление |
| `audio_device.h/cpp` | Жизненный цикл miniaudio-устройства, прогресс callbacks, пауза и повтор запуска после сбоя |
| `audio_event_queue.h` | Ограниченная очередь PCM/команд с несколькими producers и резервом для управляющих событий |
| `audio_frame_ring.h` | Предвыделенное SPSC-кольцо кадров переменной длины под mutex; при переполнении удаляет старейший |
| `voice_audio_io.h/cpp` | Workers захвата/AEC и воспроизведения; упорядочивание PCM/PTT/mute и итоговый render-reference |
| `audiorecorder.h/cpp` | Захват голосовых сообщений, worker обработки PCM, компрессор, индикатор уровня и передача записи задаче |
| `voicemessageencoder.h/cpp` | Выбор Opus preset и создание медиа-каталога; кодирование выполняет общий voice_file |
| `voiceplayback.h/cpp` | Воспроизведение голосовых сообщений |
| `callwindow.h/cpp` | Окно звонка: состояния, управление, путь соединения и статистика аудио |
| `call_audio_engine.h/cpp` | Desktop-контур звонка: захват, VoiceAudioIo, общий выход SoundManager и завершение аудиосессии |
| `radio_audio_engine.h/cpp` | Desktop-контур рации: независимые захват/прослушивание, PTT/VAD и подключение к общему выходу |
| `radiopanel.h/cpp` | Панель активной рации: выбор аудиоустройств, VAD, PTT и состояние передачи из ядра |
| `radiosettingspage.h/cpp` | Настройки рации и запись глобальных сочетаний PTT |
| `ptt_hotkey_manager.h/cpp` | Глобальный PTT: физические клавиши Windows/X11, системный портал Wayland |
| `ptt_key_chord.h` | Хранение физических сочетаний с отдельными левыми/правыми модификаторами и запись одновременного нажатия |
| `ptt_portal.h/cpp` | D-Bus-сессия GlobalShortcuts для Wayland, настройка сочетаний и обработка нажатий/отпусканий |
| `media_blocks.h/cpp` | Чтение/сборка фрагментированных медиафайлов |
| `imageviewer_window.h/cpp` | Окно просмотра изображений |
| `videoplayer_engine.h/cpp` | Движок декодирования видео |
@ -659,10 +724,26 @@ cmake .. && make -j4
| `debug_ui.h` | Отладочный UI |
### Другие поддиректории
- `db/` — `db_manager.h/cpp`: доступ GUI к данным nodes, channels, msg_<channel>, peers_<channel> и состоянию интерфейса;
копия `db/sqlite3.c/h` не используется текущей CMake-целью, SQLite берётся из `lib/`
- `transport/` — интеграция с uTun: `gui_bridge.h/gui_bridge_impl.cpp` (Qt signal-based обмен), `node_config.h/cpp` (конфиг узла), `config_updater.h/cpp` (правка конфига), `utun_node.h/cpp` (обёртка узла), `miniaudio_impl.c` (single-header miniaudio в отдельной единице трансляции). Chat-логика (`chat_core`, `chat_sync` и т.д.) компилируется напрямую из `src/chat/`, роутинг — из `src/routing_layer/` (см. `libutun/CMakeLists.txt`)
- `transport/` — интеграция GUI с ядром; файлы перечислены ниже
- `libutun/CMakeLists.txt` — состав и зависимости CMake-сборки общего ядра из `src/` и `lib/`
- `CMakeLists.txt` — приложение vibechat, Qt-зависимости, ресурсы и цели GUI-тестов
- `tests/` — проверки аудиоустройств и восстановления, голосового тракта, jitter-буферов, PTT, кодирования и GUI-компонентов
- `resources/` — `bg.jpg`, `chatgui.qrc` (встраивает 5 TGS в бинарник), `animations/*.tgs`
- `zxing-cpp/` — встроенная библиотека QR-кодов; `third_party/qhotkey/` — исходники QHotkey
### Интеграция с ядром (transport/)
| Файл | Назначение |
|------|-----------|
| `gui_bridge.h` / `gui_bridge_impl.cpp` | Команды GUI → uasync и события ядра → Qt-сигналы |
| `utun_node.h/cpp` | Запуск и остановка ядра/чата в выделенном uasync-потоке |
| `node_config.h/cpp` | Загрузка и сохранение конфигурации узла |
| `config_updater.h/cpp` | Изменение настроек в конфиге |
| `miniaudio_impl.c` | Реализация single-header miniaudio в отдельной единице трансляции |
| `audio_diagnostics.h/cpp` | Диагностика этапов аудио и событий backend; записывает метаданные без PCM |
### Система анимированных эмодзи
@ -756,6 +837,7 @@ void lottie_animation_destroy(Lottie_Animation *anim);
---
## Key Documentation Files
- `doc/service_lifecycle.md` — ядро, независимые сервисы, владение ресурсами и остановка
- `doc/node_snapshot.md` — подписанная запись узла, timestamp, SQLite и обновление NCD
- `doc/etcp_protocol.txt` — ETCP: кодограммы, ACK, handshake, keepalive
@ -765,6 +847,12 @@ void lottie_animation_destroy(Lottie_Animation *anim);
- `src/routing_layer/topo_group.h` — протокол групповой сессии и критерий READY
- `tests/test_chat_join_e2e.c`, `tests/test_topo_recovery.c`, `tests/test_services.c` — проверки join, recovery и жизненного цикла
- `doc/dm_arch.md`, `doc/chat_call_arch.md` — личные сообщения и звонки
- `doc/proxy_protocol.md` — TCP/UDP/ICMP-прокси, управление окнами, half-close и проверки
- `doc/lwip_nuances.md` — особенности адаптированного lwIP TCP-стека
- `doc/linux_audio_recovery.md` — диагностика аудиотракта Linux, контракты владения и восстановление устройств
- `src/media_delivery/file_transfer.h`, `src/dm/dm_media.h` — контракты передачи файлов и E2E-вложений DM
- `src/call/call_audio.h`, `src/radio/radio_audio.h` — API общего голосового стека и правила потоков
- `tools/chatcli_commands.txt` — команды headless CLI, в том числе DM, звонки и рация
## Список задач по проекту
@ -785,6 +873,29 @@ C-библиотека `utun_lite` собирает `lib/` и `src/` по `libut
**Подробная инструкция:** `tools/chatgui-android/AGENTS.md`
**Chat-модули:** все файлы из `src/chat/` (описаны выше в секции «Chat») компилируются в `libutun_lite`.
### Основные файлы native-слоя
Пути относительны к `tools/chatgui-android/`; UI и Android-сервисы описаны в локальном `AGENTS.md`.
| Файл | Назначение |
|------|-----------|
| `libutun_lite/utun_sources.cmake` | Общий список исходников ядра для Android и headless |
| `libutun_lite/CMakeLists.txt` | Сборка native-библиотеки и зависимостей |
| `libutun_lite/instance_lite.c/h` | Запуск ядра/чата по INI-тексту и управление отдельным uasync-потоком |
| `libutun_lite/utun_config_api.c/h` | Провайдер конфигурации: callbacks Kotlin и значения для native-слоя |
| `libutun_lite/standby.c/h` | Фоновый duty-cycle, таймеры активных интервалов и ожидание пробуждения |
| `libutun_lite/invite_link_c.c/h` | Старая копия C-кодека; .c исключён из UTUN_SOURCES, рабочий код — src/chat/invite_link.c/h |
| `libutun_lite/attachment_sender.c/h` | Отправка файлов в канал через chat_msg_submit и канальный медиа-индекс |
| `libutun_lite/photo_sender.c/h` | Отправка фотографий в канал с MIME-типом и размерами изображения |
| `libutun_lite/video_sender.c/h` | Отправка видео через общий механизм подготовки вложений |
| `libutun_lite/voice_recorder.c/h` | Накопление PCM записи, компрессор и отправка голоса через общий attachment_send |
| `jni_bridge/android_jni_bridge.c/h` | JNI-команды и callbacks между Kotlin и C-ядром, события и аудио API |
| `jni_bridge/android_udp_log.c/h` | Потокобезопасный буфер UDP-логов с flush-таймером в потоке ядра |
| `headless/headless_main.c` | Отдельный каркас control-loop; сам не запускает ядро/чат |
| `headless/headless_control.c/h` | Каркас control-сокета; часть команд — заглушки, рабочий API — src/chat/chat_headless_control.c/h |
| `app/src/main/cpp/CMakeLists.txt` | NDK-сборка библиотеки приложения |
| `libutun_lite/tests/test_standby.c` | Проверка duty-cycle и жизненного цикла standby |
## Runtime
- После autotools-сборки бинарник — `src/utun`. Запуск из корня с TUN: `sudo ./src/utun -f -c utun.cfg`.
- Старый `utun_start.sh` ожидает `./utun` в корне. `utun_stop.sh` делает `killall -9 utun`, а не штатную остановку одного экземпляра.

10
lib/audio_compressor.h

@ -1,3 +1,9 @@
/* audio_compressor — адаптивное усиление int16 PCM (моно/стерео) с общей огибающей каналов.
* create → configure → обработка → destroy; объект использует один владелец, блокировок нет.
* Запись: push принимает произвольные порции, flush завершает хвост и lookahead; output принадлежит объекту.
* Поток: process_frame обрабатывает ровно sample_rate*block_duration_ms/1000*channels отсчётов,
* требует нулевого lookahead и пустого входного накопителя; in/out могут совпадать.
* count/output_size — interleaved отсчёты, не байты и не кадры на канал. Выключение даёт исходный PCM. */
#ifndef AUDIO_COMPRESSOR_H
#define AUDIO_COMPRESSOR_H
@ -19,7 +25,7 @@ typedef struct {
float max_gain_db;
float rise_rate_per_sec;
float release_rate_per_sec; /* скорость плавного снижения gain (0 = авто: rise*5) */
float target_level;
float target_level; /* Линейная амплитуда огибающей, не дБ; 0 задаёт default 0.25. */
} audio_compressor_config_t;
struct audio_compressor* audio_compressor_create(void);
@ -35,9 +41,11 @@ void audio_compressor_reset(struct audio_compressor* ac);
void audio_compressor_set_enabled(struct audio_compressor* ac, int enabled);
int audio_compressor_is_enabled(const struct audio_compressor* ac);
/* push копирует вход; push/flush возвращают 0 / -1. Ошибка накопления требует reset перед повтором. */
int audio_compressor_push(struct audio_compressor* ac, const int16_t* samples, size_t count);
int audio_compressor_flush(struct audio_compressor* ac);
/* Указатель действителен до изменения/освобождения выходного буфера; вызывающий его не освобождает. */
const int16_t* audio_compressor_output(const struct audio_compressor* ac);
size_t audio_compressor_output_size(const struct audio_compressor* ac);

13
lib/debug_config.h

@ -80,7 +80,7 @@ typedef int debug_category_t;
/* Debug configuration structure */
typedef struct {
debug_level_t level; // Global debug level (default: ERROR)
debug_level_t category_levels[DEBUG_CATEGORY_COUNT]; // Per-category levels (0 = disabled)
debug_level_t category_levels[DEBUG_CATEGORY_COUNT]; // Уровень категории: NONE наследует общий, DISABLED выключает
int timestamp_enabled; // Include timestamps in output
int function_name_enabled; // Include function names
int file_line_enabled; // Include file:line info
@ -99,18 +99,19 @@ extern debug_config_t g_debug_config;
void debug_config_init(void);
/* Set debug level */
// итоговый level = max (global level - здесь задается, category level)
// Общий уровень применяется к категориям с уровнем NONE.
void debug_set_level(debug_level_t level);
/* Set debug level for specific category (0 = disabled, otherwise uses that level) */
/* Уровень категории заменяет общий; NONE наследует его, DISABLED подавляет вывод. */
void debug_set_category_level(debug_category_t category, debug_level_t level);
/* Enable/disable specific categories */
/* enable фиксирует текущий общий уровень; disable возвращает к наследованию (NONE).
* Для полного выключения использовать debug_set_category_level(cat, DEBUG_LEVEL_DISABLED). */
void debug_enable_category(debug_category_t category);
void debug_disable_category(debug_category_t category);
void debug_set_categories(debug_category_t categories);
/* Set masks directly */
/* Установка уровня одной категории (аргумент categories — индекс, не битовая маска). */
void debug_set_masks(debug_category_t categories, debug_level_t level);
/* Configure output options */
@ -126,7 +127,7 @@ int debug_reopen_log(void);
void debug_enable_console(int enable);
// IP address to string (static buffer, single-threaded)
// IP/sockaddr в строку: результат возвращается по значению, освобождать не требуется.
typedef struct {
char str[54]; // INET6_ADDRSTRLEN(45) + 6chars (:port) + \0
} ip_str_t;

5
lib/json_flat.h

@ -2,7 +2,10 @@
* @file json_flat.h
* @brief Парсер плоского JSON без вложенности: {"key":"value",...}
*
* Только строковые значения. Callback получает полные строки без обрезания.
* Только строковые значения и обычные escapes; \uXXXX не поддерживается.
* Callback получает полные key/value, действительные только до его возврата.
* parse возвращает 0 при успехе/остановке callback, -1 при ошибке; остановка не проверяет остаток ввода.
* get ищет первый ключ и копирует значение с NUL, при малом буфере обрезает; 0 найден, -1 ошибка/нет ключа.
*/
#ifndef JSON_FLAT_H

6
lib/ll_queue.h

@ -1,6 +1,10 @@
#ifndef LL_QUEUE_H
#define LL_QUEUE_H
/* Очередь одного uasync-потока; наличие pthread-заголовков не делает её межпоточной.
* put может синхронно вызвать consumer/waiter. Держать владельцев живыми до завершения callbacks,
* waiter handle обнулять целиком и отменять до освобождения; entry и dgram освобождаются отдельно. */
#ifdef __cplusplus
extern "C" {
#endif
@ -306,7 +310,6 @@ void queue_waiter_cancel(struct ll_queue* q, struct queue_waiter_handle* h);
* @brief Добавляет элемент в конец очереди (FIFO).
* @param q очередь
* @param entry элемент
* @param id идентификатор для поиска
* @return 0 — успех, -1 — превышен лимит (элемент освобождён)
*/
int queue_data_put(struct ll_queue* q, struct ll_entry* entry);
@ -315,7 +318,6 @@ int queue_data_put(struct ll_queue* q, struct ll_entry* entry);
* @brief Добавляет элемент в начало очереди (LIFO, высокий приоритет).
* @param q очередь
* @param entry элемент
* @param id идентификатор
* @return 0 — успех, -1 — превышен лимит (элемент освобождён)
*/
int queue_data_put_first(struct ll_queue* q, struct ll_entry* entry);

7
lib/mem.h

@ -1,6 +1,9 @@
/**
* Memory management layer
* Provides wrappers for malloc/realloc/calloc/free with error handling
* mem — выделение памяти с защитными полями, местом аллокации и учётом живых блоков.
* Использовать u_malloc/u_calloc/u_realloc/u_strdup и парный u_free; обычный free к этим блокам неприменим.
* Макросы передают LOCATION автоматически. OOM возвращает NULL; обнаруженное повреждение завершает процесс.
* realloc при ошибке сохраняет старый блок, при size=0 освобождает его.
* Отчёт u_report_unfreed_blocks вызывать после остановки потоков, меняющих список аллокаций.
*/
#ifndef MEM_H
#define MEM_H

8
lib/memory_pool.h

@ -1,4 +1,9 @@
// memory_pool.h
/* memory_pool — повторное использование блоков фиксированного размера в одном потоке.
* init создаёт пустой пул; alloc выделяет блок по требованию или берёт свободный и обнуляет payload.
* free проверяет защитный хвост и возвращает не более MEMORY_POOL_MAX_FREE блоков в кеш.
* object_size должен вмещать void*: свободный блок хранит next в начале payload.
* Перед destroy вернуть все выданные блоки: destroy освобождает только кеш и сам пул.
* name заимствован до destroy; блок возвращать только своему пулу, внутренней синхронизации нет. */
#ifndef MEMORY_POOL_H
#define MEMORY_POOL_H
@ -40,6 +45,7 @@ size_t memory_pool_get_total_free_blocks(void);
#define memory_pool_alloc(pool) memory_pool_alloc_impl(pool, PLOCATION)
#define memory_pool_free(pool, obj) memory_pool_free_impl(pool, obj, PLOCATION)
/* Проверяет присутствие в кеше свободных блоков; не определяет состояние уже освобождённого через u_free блока. */
int memory_pool_is_freed(struct memory_pool* pool, void* obj);

6
lib/opus_codec.h

@ -1,3 +1,9 @@
/* opus_codec — владеющие обёртки encoder/decoder libopus для int16 interleaved PCM.
* create принимает частоту и 1/2 канала; неположительная частота → 48000, неверные каналы → моно.
* Encoder/decoder имеют состояние потока; каждому нужен один последовательный владелец.
* frame_samples — отсчёты НА КАНАЛ: PCM вмещает frame_samples*channels элементов.
* encode возвращает байты Opus, decode — отсчёты на канал; отрицательное значение означает ошибку.
* out_cap — байты; decode с data=NULL/len=0 использует PLC libopus. Освобождение — соответствующим destroy. */
#ifndef OPUS_CODEC_H
#define OPUS_CODEC_H

4
lib/platform_compat.h

@ -1,5 +1,7 @@
/**
* Platform compatibility layer for POSIX functions on Windows
* platform_compat — общие заголовки POSIX/Windows и адаптеры отсутствующих POSIX-функций.
* Также предоставляет криптографический random_bytes, адреса интерфейсов, выбор default route
* и классификацию публичных IPv4. Сокетные типы/ошибки и nonblocking API — в socket_compat.h.
*/
#ifndef PLATFORM_COMPAT_H

11
lib/serialize.h

@ -22,17 +22,20 @@
* • Все динамические данные (строки, массивы, списки) выделяются через u_malloc.
* • При encode длина переменных полей кодируется всегда 2 байтами (uint16_t, big-endian).
* • Для linked list в буфере сохраняется только количество узлов + сырые данные узлов
* (next-указатели НЕ сериализуются, они восстанавливаются при decode).
* (включая байты next/padding; decode заменяет next восстановленными ссылками).
* • serialize_decode принимает буфер БЕЗ заголовка.
* • serialize_free освобождает ВСЮ структуру и все вложенные динамические объекты.
* • Поля в schema.fields должны идти в порядке возрастания offset.
* • max_size (если > 0) — жёсткий лимит размера выходного буфера.
* • Поля кодируются в порядке schema.fields; фиксированные данные копируются без смены endian.
* • max_size (если > 0) — лимит encode; header при header_len > 0 обязателен.
* • Переменные counts ограничены 65535; elem_size=1 добавляет NUL и для byte-массивов.
* • Linked nodes копируются целиком, без рекурсивного кодирования вложенных указателей.
* • Этот формат зависит от ABI сырых полей; сериализация не нормализует размер/выравнивание структур.
*
* @example
* // 1. Описание структуры
* typedef struct Node {
* uint32_t value;
* struct Node* next; // next по offset = 4
* struct Node* next; // положение задаётся offsetof(Node, next)
* } Node;
*
* typedef struct {

2
lib/silero_vad.h

@ -3,7 +3,7 @@
*
* Запускает официальную стриминговую модель silero_vad.onnx (v5, ~2.3 МБ),
* которая по окну аудио возвращает вероятность наличия речи [0..1].
* Рекуррентное состояние (GRU) хранится внутри объекта и переносится между
* Рекуррентное состояние модели хранится внутри объекта и переносится между
* вызовами. Обёртка также хранит 64 последних отсчёта аудио и добавляет их
* перед новым окном: ONNX получает 576 отсчётов, публичный API принимает 512.
*

5
lib/socket_compat.h

@ -1,6 +1,7 @@
/**
* Socket compatibility layer for cross-platform support (POSIX / Windows)
* MSYS2 UCRT64 compatible
* Единые socket_t, коды ошибок и wrappers сокетов POSIX/Windows (включая MSYS2 UCRT64).
* platform_init/cleanup обслуживают Winsock; UDP/nonblocking/options/sendto/recvfrom — операции ОС.
* Созданные сокеты закрывает владелец через socket_close_wrapper; event loop находится в u_async.h.
*/
#ifndef SOCKET_COMPAT_H

3
lib/speex_aec.h

@ -5,6 +5,9 @@
* перед кодированием. Работает на interleaved int16 PCM, 1/2 канала, частота 48000 (можно
* 8000/16000/32000/48000), кадр 20 мс (960 сэмплов @48 кГц).
*
* Объект не имеет внутренних блокировок: feed/process/reset/get_stats выполняет один владелец
* либо вызывающий сериализует их общей блокировкой. Аппаратные callbacks сами AEC не вызывают.
*
* Модель использования (duplex-контур звонка):
* - рендер (far-end, то что пошло в динамик) → speex_aec_feed_playback();
* - захват (near-end, микрофон) → speex_aec_process_capture().

3
lib/swm_min.h

@ -1,4 +1,5 @@
/* sliding_window_min.h */
/* swm_min — минимум последних window_size целых значений (окно по числу добавлений, не по времени).
* create → add/get_min → destroy; память окна выделяется при create, внутренняя синхронизация отсутствует. */
#ifndef SLIDING_WINDOW_MIN_H
#define SLIDING_WINDOW_MIN_H

1
lib/timeout_heap.c

@ -28,7 +28,6 @@ TimeoutHeap *timeout_heap_create(size_t initial_capacity) {
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "Creating TH3...");
h->size = 0;
h->capacity = initial_capacity;
h->freed_count = 0;
h->user_data = NULL;
h->free_callback = NULL;
return h;

22
lib/timeout_heap.h

@ -1,4 +1,9 @@
// timeout_heap.h
/* timeout_heap — min-heap таймеров для uasync; сам не измеряет время и не вызывает таймеры.
* Владелец задаёт абсолютные expiration в одной шкале и извлекает готовые записи через peek/pop.
* cancel помечает запись; её data передаётся free_callback при последующей очистке или destroy.
* Без free_callback data не освобождается. Успешный pop передаёт data вызывающему.
* index_ptr, если задан, должен жить до удаления записи; heap обновляет индекс при перестановках.
* Все операции одного heap выполняются в одном потоке, внутренней синхронизации нет. */
#ifndef TIMEOUT_HEAP_H
#define TIMEOUT_HEAP_H
@ -11,7 +16,7 @@ extern "C" {
#include <stdint.h> // For uint64_t
#include <stddef.h> // For size_t
typedef uint64_t TimeoutTime; // e.g., milliseconds since epoch or from now
typedef uint64_t TimeoutTime; // Абсолютное время в шкале владельца (uasync использует timebase: 0.1 мс).
typedef struct {
TimeoutTime expiration; // Sort key (smaller = earlier)
@ -26,7 +31,6 @@ struct TimeoutHeap {
TimeoutEntry *heap; // Dynamic array
size_t size; // Current number of elements
size_t capacity; // Allocated size
size_t freed_count; // Number of freed timer nodes
void* user_data; // User data for free callback
void (*free_callback)(void* user_data, void* data); // Callback to free data
};
@ -48,7 +52,7 @@ void timeout_heap_destroy(TimeoutHeap *h);
* Set a callback function to free data when deleted nodes are removed.
* @param h The heap.
* @param user_data User data passed to callback.
* @param callback Callback function (if NULL, data is freed with free()).
* @param callback Освобождает data отменённых записей и всех записей при destroy; NULL оставляет data владельцу.
*/
void timeout_heap_set_free_callback(TimeoutHeap *h, void* user_data, void (*callback)(void* user_data, void* data));
@ -57,6 +61,7 @@ void timeout_heap_set_free_callback(TimeoutHeap *h, void* user_data, void (*call
* @param h The heap.
* @param expiration The expiration time.
* @param data User data associated with the timeout.
* @param index_ptr Optional pointer to a live size_t updated with the entry's zero-based heap index.
* @return 0 on success, -1 on allocation failure.
*/
int timeout_heap_push(TimeoutHeap *h, TimeoutTime expiration, void *data, size_t *index_ptr);
@ -88,15 +93,10 @@ int timeout_heap_pop(TimeoutHeap *h, TimeoutEntry *out);
*/
int timeout_heap_cancel(TimeoutHeap *h, TimeoutTime expiration, void *data);
/* Отмена по сохранённому индексу; data защищает от отмены чужой записи. 0 / -1, освобождение отложено. */
int timeout_heap_cancel_at(TimeoutHeap *h, size_t index, void *data);
/**
* Get the number of freed timer nodes.
* @param h The heap.
* @return Count of freed timer nodes.
*/
size_t timeout_heap_get_freed_count(TimeoutHeap *h);
/* Число записей, включая ещё не извлечённые отменённые; NULL → 0. */
size_t timeout_heap_get_size(TimeoutHeap *h);

8
lib/u_async.h

@ -1,6 +1,8 @@
// uasync.h
// модуль асинхронных операций. добавляем сокеты и таймауты и mainloop их обслуживает.
/* Цикл событий одного потока: сокеты (epoll/poll/select), таймеры и FIFO call_soon.
* create → регистрация callbacks → poll/mainloop → destroy вне callbacks после остановки владельцев.
* Таймауты задаются в timebase 0.1мс; arg принадлежит вызывающему, освобождает его callback/владелец.
* API сокетов/таймеров используется в потоке loop. Из другого потока — post/post_reserved и wakeup;
* публикация не продлевает время жизни ua/arg, их освобождение нужно согласовать с остановкой producers. */
#ifndef UASYNC_H
#define UASYNC_H

5
src/broadcast.h

@ -1,3 +1,8 @@
/* broadcast — рассылка данных соседям topo-группы с пересылкой и дедупликацией UUID.
* Контекст и кеш увиденных UUID принадлежат группе; TTL — срок хранения UUID, не счётчик сетевых хопов.
* init_instance регистрирует общий ETCP-диспетчер, init(group) создаёт состояние отдельной группы.
* Все вызовы/callbacks — uasync-поток; recv получает заимствованные uuid/data только на время callback.
* send копирует данные и возвращает 0 / -1; 0 не подтверждает доставку каждому участнику. */
#ifndef BROADCAST_H
#define BROADCAST_H

6
src/chat/chat_core_priv.h

@ -1,8 +1,8 @@
/*
* chat_core_priv.h — внутренний заголовок для под-модулей chat_core
*
* Предоставляет доступ к глобальному состоянию g_cc и общим хелперам.
* Не включать извне chat/ — только для chat_core*.c.
* Предоставляет per-instance chat_core_ctx через CC(inst), общие SQL/сериализационные хелперы
* и внутренние операции частей chat_core/member_sync. Не включать извне chat/.
*/
#ifndef CHAT_CORE_PRIV_H
@ -73,7 +73,7 @@ static inline size_t b64_decode(const char* src, size_t src_len, uint8_t* dst, s
return out;
}
/* ── Глобальное состояние (определено в chat_core.c) ── */
/* ── Состояние одного экземпляра (создаётся в chat_core.c) ── */
struct ms_props_cbk; /* member_sync.c */
struct ms_apply_cbk; /* member_sync.c */

6
src/chat/chat_headless_control.h

@ -6,8 +6,10 @@
* Response: {"id":N,"ok":true,"data":{...}} | {"id":N,"ok":false,"error":"..."}
* Event: {"event":"<type>",...}
*
* Commands: ping, status, channels, members, messages, send, invite,
* invite_nodes, connect, create_channel, subscribe, quit
* Команды каналов, DM, звонков/рации и настроек — в tools/chatcli_commands.txt;
* диспетчер реализации — chat_headless_control.c. Аудио PCM использует отдельные call/radio_headless сокеты.
* init регистрирует listener и события chat_event, destroy закрывает клиентов и снимает подписку.
* Все вызовы и команды исполняются в uasync-потоке экземпляра.
*/
#ifndef CHAT_HEADLESS_CONTROL_H
#define CHAT_HEADLESS_CONTROL_H

2
src/chat/invite_build.h

@ -3,7 +3,7 @@
*
* Общий модуль для всех GUI (desktop chatgui, Android, headless CLI).
* Логика выбора «лучшего узла» перенесена из tools/chatgui-android/jni_bridge.
* Работает в uasync-потоке, использует общий контекст g_cc.
* Работает в uasync-потоке, использует chat_core_ctx конкретного UTUN_INSTANCE.
*/
#ifndef INVITE_BUILD_H
#define INVITE_BUILD_H

7
src/chat/invite_link.h

@ -1,8 +1,11 @@
/*
* invite_link.h — invite-ссылки utun:// для каналов
*
* Формат: utun:// + base64(version | password? | channel_id | [header | pubkey | addrs]+)
* Совместим с десктопной (Qt) и Android (Kotlin) версиями.
* Версия 0x03: utun:// + base64(version | pass_len/password | channel_id | join_key |
* reality_has/params | блоки pubkey/addrs). ID/port кодируются big-endian; nodeId выводится из pubkey.
* Общий формат с desktop Qt и Android Kotlin. Сам кодек не подключает узел и не регистрирует join_key.
* decode: 0/-1; encode: длина base64 без utun:// и NUL/-1; serialize_addrs: число байтов/-1.
* Буферы предоставляет вызывающий; encode завершает строку NUL.
*/
#ifndef INVITE_LINK_H
#define INVITE_LINK_H

5
src/config_parser.h

@ -1,4 +1,7 @@
// config_parser.h - Configuration parser for utun application
/* INI-конфигурация ядра: слушающие сокеты, исходящие пиры, сети/подсети и настройки сервисов.
* parse_config читает файл, parse_config_from_buf — текст; filename задаёт источник в диагностике.
* Успех возвращает выделенную utun_config со списками; освобождение — только free_config.
* Парсер заполняет модель, запуск сетевых ресурсов выполняет utun_instance. */
#ifndef CONFIG_PARSER_H
#define CONFIG_PARSER_H

3
src/config_updater.h

@ -1,4 +1,5 @@
// config_updater.h - Configuration file updater
/* Обеспечивает идентичность X25519/node_id в INI-файле: проверяет поля и сохраняет исправленные ключи.
* config_ensure_keys_and_node_id меняет файл на диске; bytes_to_hex только форматирует буфер вызывающего. */
#ifndef CONFIG_UPDATER_H
#define CONFIG_UPDATER_H

3
src/dm/dm_core.h

@ -1,7 +1,8 @@
/*
* dm_core.h — прямой p2p чат между двумя пользователями (DM)
*
* Отдельная подсистема (НЕ канал): без TOPO_GROUP/member_sync/merkle.
* Личная беседа не создаёт отдельную TOPO_GROUP и не синхронизируется через member_sync/Merkle.
* Для доставки использует маршрут из общей CHAT-группы участников.
* - conv_id и content_key детерминированно выводятся обеими сторонами
* из своих ключей и pubkey пира (см. dm_crypto.h) — без переговоров.
* - сообщения идут через etcp_router (прямое соединение или релей),

11
src/eim_nat.h

@ -1,3 +1,9 @@
/* eim_nat — таблица Endpoint-Independent Mapping для IPv4 TCP/UDP и ICMP echo.
* init_ctx создаёт состояние из global_config; при отключённом NAT оставляет initialized=0.
* egress/ingress меняют IP/порты и checksums на месте, не отправляют пакеты и не владеют TUN/ETCP.
* Перед обработкой нужен инициализированный ctx; вызовы последовательны в uasync-потоке.
* gateway/internal IP — host order, internal_port — network order, внешний порт — host order.
* src_conn заимствован; срок жизни и выбор транспорта обратной отправки контролирует nat_transport. */
#ifndef EIM_NAT_H
#define EIM_NAT_H
@ -31,7 +37,7 @@ struct eim_nat_entry {
struct ETCP_CONN* src_conn; // cached connection for sendback
};
// Pure NAT engine state (no transport/TUN/ETCP fields)
// Состояние преобразования; TUN и транспортные ресурсы принадлежат nat_transport.
struct eim_nat_ctx {
uint32_t gateway_ip;
uint16_t port_start;
@ -47,8 +53,11 @@ struct global_config;
int eim_nat_init_ctx(struct eim_nat_ctx* ctx, const struct global_config* g);
void eim_nat_destroy_ctx(struct eim_nat_ctx* ctx);
/* 0 — обработано или пакет не подлежит NAT, -1 — ошибка; буфер принадлежит вызывающему. */
int eim_nat_egress(struct eim_nat_ctx* ctx, uint8_t* ip_data, size_t ip_len,
uint64_t src_node_id, struct ETCP_CONN* src_conn);
/* out_entry изменяется только при найденном mapping; заранее установить *out_entry=NULL.
* Запись заимствована у ctx. 0 само по себе не означает, что пакет был преобразован. */
int eim_nat_ingress(struct eim_nat_ctx* ctx, uint8_t* ip_data, size_t ip_len,
struct eim_nat_entry** out_entry);

5
src/firewall.h

@ -1,4 +1,7 @@
// firewall.h - Firewall rules for utun
/* firewall — список разрешённых пар IPv4/порт из global_config, без изменения системного firewall.
* init/обнуление → load_rules (копия и сортировка правил) → check → free; контекст использует один поток.
* check: 1 разрешено, 0 запрещено; port=0 в правиле разрешает все порты IP, bypass_all разрешает всё.
* IP и порт передавать в host order, как в CFG_FIREWALL_RULE. */
#ifndef FIREWALL_H
#define FIREWALL_H

5
src/lwip_tcp/lwip_pbuf.h

@ -1,4 +1,7 @@
// lwip_pbuf.h — simplified packet buffer (PBUF_RAM only)
/* Буферы TCP-пакетов: одна RAM-аллокация с запасом перед payload и ручным refcount.
* alloc создаёт ref=1; free уменьшает ссылки всех элементов цепочки и освобождает элементы с ref=0.
* header сдвигает payload в пределах запаса; header_force не проверяет запас при добавлении.
* chain только связывает элементы, без увеличения refcount и пересчёта tot_len. Синхронизации нет. */
#ifndef LWIP_PBUF_H
#define LWIP_PBUF_H

7
src/lwip_tcp/lwip_tcp.h

@ -1,4 +1,7 @@
// lwip_tcp.h — lwIP TCP public API (adapted for uTun)
/* Адаптированный lwIP TCP для TUN-прокси: TCP-состояния, retransmit, окна и callbacks потоков.
* init создаёт контекст с uasync-таймером; input получает TCP-сегмент после IPv4-заголовка,
* output callback передаёт сегмент внешнему IP/TUN-слою. destroy освобождает PCB и таймер.
* API и callbacks требуют последовательного выполнения; input использует общий рабочий контекст. */
#ifndef LWIP_TCP_H
#define LWIP_TCP_H
@ -85,7 +88,7 @@ typedef err_t (*tcp_poll_fn) (void *arg, struct tcp_pcb *pcb);
typedef void (*tcp_err_fn) (void *arg, err_t err);
typedef err_t (*tcp_connected_fn)(void *arg, struct tcp_pcb *pcb, err_t err);
// Output callback — called when TCP wants to send an IP packet
// Output callback получает TCP-сегмент и IP адреса отдельно; IPv4-заголовок строит вызывающий слой.
typedef err_t (*tcp_output_fn)(void *arg, struct pbuf *p, uint32_t src_ip, uint32_t dst_ip);
#define TCP_TRACE_SIZE 384

3
src/lwip_tcp/lwip_tcp_opts.h

@ -1,4 +1,5 @@
// lwip_tcp_opts.h — hardcoded TCP configuration (no #ifdefs)
/* Параметры встроенного TCP: MSS, окна, лимиты повторов и таймеры в миллисекундах.
* Используются lwip_tcp/in/out; runtime-интервал и пределы RTO меняет lwip_tcp_set_timer. */
#ifndef LWIP_TCP_OPTS_H
#define LWIP_TCP_OPTS_H

3
src/lwip_tcp/lwip_tcp_priv.h

@ -1,4 +1,5 @@
// lwip_tcp_priv.h — lwIP TCP internal API
/* Внутренний API адаптированного lwIP TCP: wire TCP header, сегменты, контекст и межфайловые функции.
* Используется lwip_tcp/in/out; внешние пользователи включают lwip_tcp.h. */
#ifndef LWIP_TCP_PRIV_H
#define LWIP_TCP_PRIV_H

8
src/media_async/attachment.h

@ -1,6 +1,8 @@
/* Общие метаданные готового вложения. Подготовка не знает адресата и транспорта.
* PM шифрует компактный wire-формат; GUI получает разобранные поля.
* encode/decode возвращают длину/0 или -1; неизвестные типы и лишние байты запрещены. */
/* attachment — общие метаданные file/voice/video, без хранения файла, адресата и транспорта.
* validate/decode возвращают 0 / -1, encode — число записанных байтов / -1.
* Формат: kind:1, name_len:2, duration_ms:4, width:2, height:2, UTF-8 basename, waveform:100 только для voice.
* Числа big-endian; имя 1..255 байт без разделителей пути, лишние wire-байты запрещены.
* Caller владеет struct/буферами; DM шифрует эти метаданные, GUI получает разобранные поля. */
#ifndef ATTACHMENT_H
#define ATTACHMENT_H
#include <stdint.h>

11
src/media_async/attachment_send.h

@ -1,7 +1,10 @@
/* Подготовить голос/видео и отправить в зафиксированную беседу. Вызывать trampoline
/* attachment_send — подготовить голос/видео и отправить в зафиксированный канал или DM. Вызывать trampoline
* через uasync_post. Request и PCM/compressor переходят во владение задачи;
* pcm_release освобождает pcm_owner, NULL означает PCM из u_malloc.
* Qt/Android используют общий результат подготовки, доставка остаётся в chat/dm. */
* Qt/Android используют общий результат подготовки, доставка остаётся в chat/dm.
* req выделяется u_calloc; caller заполняет target/is_dm, info и source либо PCM. inst должен жить до done.
* Подготовка выполняется в media_async worker, публикация и attachment-события — в uasync.
* output/id/error заполняет задача; temporary_source разрешает удалить принадлежащий приложению source. */
#ifndef ATTACHMENT_SEND_H
#define ATTACHMENT_SEND_H
#include "attachment.h"
@ -12,14 +15,14 @@ extern "C" {
#endif
struct attachment_send_req {
struct UTUN_INSTANCE* inst;
char target[64];
char target[64]; /* Десятичный channel_id либо conv_id без префикса dm:, зафиксированный до подготовки. */
int is_dm;
struct attachment_info info;
uint8_t id[16];
char source[1024], output[1024];
int transcode, temporary_source;
const int16_t* pcm;
size_t pcm_count;
size_t pcm_count; /* Для voice: int16, 48 кГц моно, число отсчётов. */
void* pcm_owner;
void (*pcm_release)(void* owner);
struct audio_compressor* compressor;

7
src/media_async/voice_file.h

@ -1,6 +1,9 @@
/* Существующий контейнер Opus голосовых Qt/Android. Вызывать только в worker.
/* voice_file — кодирование PCM в общий контейнер Opus голосовых сообщений Qt/Android. Вызывать только в worker.
* PCM принадлежит вызывающему; encode заполняет duration/waveform по реально
* записанным кадрам. При ошибке неполный файл удаляется. */
* записанным кадрам. При ошибке неполный файл удаляется; возврат 0 / -1.
* count — число interleaved int16 отсчётов; rate — 8/12/16/24/48 kHz, channels — 1/2, preset — 0..2.
* Пишутся полные кадры по 20мс (хвост отбрасывается), минимум 500мс, максимум 24ч.
* name задаёт caller; encode устанавливает kind=VOICE и обнуляет width/height. */
#ifndef VOICE_FILE_H
#define VOICE_FILE_H
#include "attachment.h"

6
src/media_delivery/media_delivery.h

@ -1,4 +1,8 @@
// media_delivery.h — распространение медиа (аудио/видео стриминг)
/* media_delivery — канальные медиафайлы: поиск держателей блоков, выдача/relay и репликация доступности.
* Суперузлы обмениваются block_availability, держатели отдают подписанные блоки, media_download собирает файл.
* init создаёт per-instance состояние, bind подключает протокол к router; destroy отменяет сетевую работу.
* Все операции — uasync-поток; долгие файловые/crypto-задачи выполняет media_async.
* E2E-файлы личных бесед используют dm_media/file_transfer, а не канальную таблицу доступности. */
#ifndef MEDIA_DELIVERY_H
#define MEDIA_DELIVERY_H

4
src/media_delivery/media_delivery_proto.h

@ -1,4 +1,6 @@
// media_delivery_proto.h — протокольные структуры media_delivery
/* media_delivery_proto — wire-структуры и подкоманды доставки блоков медиа CHAT-группы.
* Описывает запросы держателей, чанки, подтверждения наличия и репликацию между суперузлами.
* Это формат payload сервиса router, без группового маршрутизационного заголовка; обработчики — media_delivery/download. */
#ifndef MEDIA_DELIVERY_PROTO_H
#define MEDIA_DELIVERY_PROTO_H

5
src/media_delivery/media_download.h

@ -1,4 +1,7 @@
// media_download.h — скачивание блоков медиа
/* media_download — загрузка канального файла по media_index_result: QUERY держателей → блоки → проверка/сборка.
* Состояние хранит inst->media_delivery; каждый подключённый держатель удерживается через CM handle.
* Старт копирует метаданные result; callbacks и обработчики — uasync-поток, файловая проверка — media_async.
* Failover/таймер простоя ограничивают повторы; done сообщает результат, а не гарантирует доставку другим участникам. */
#ifndef MEDIA_DOWNLOAD_H
#define MEDIA_DOWNLOAD_H

6
src/media_delivery/media_index.h

@ -1,4 +1,7 @@
// media_index.h — таблица media_files + регистрация медиа с async-обработкой
/* media_index — индекс блоков канального файла в SQLite media_files: UUID, SHA256, Ed25519-подписи и location.
* init создаёт таблицу; register_async копирует/хеширует/подписывает файл в worker, затем commit и callback в uasync.
* db/ma/ua заимствованы и должны жить до завершения; доступ к БД выполняется в потоке ядра.
* Результат callback заимствован только до возврата. result_free освобождает block_ids/block_sigs, но не саму структуру. */
#ifndef MEDIA_INDEX_H
#define MEDIA_INDEX_H
@ -40,6 +43,7 @@ int media_index_register_downloaded(sqlite3* db, const uint8_t* media_id, const
const char* location, uint64_t node_id,
int64_t file_size, int64_t chunk_size, int chunk, int64_t offset);
/* Callback может быть синхронным при отказе запуска. err=0 даёт result, иначе result=NULL. */
void media_index_register_async(
struct media_async* ma, struct UASYNC* ua, sqlite3* db,
uint64_t node_id, const uint8_t* ed25519_privkey,

5
src/nat_transport.h

@ -1,4 +1,7 @@
// nat_transport.h — NAT transport layer (TUN + ETCP protocol handling)
/* IPv4 NAT через отдельный TUN и сервис ETCP_RT_ID_NAT в UTUN-router.
* nat_via_node_id задаёт удалённого провайдера; при 0 узел сам выполняет eim_nat для клиентов.
* init создаёт TUN/обработчики по nat_enabled; destroy снимает их и освобождает ресурсы.
* Контекст принадлежит UTUN_INSTANCE; очереди и callbacks работают в uasync. */
#ifndef NAT_TRANSPORT_H
#define NAT_TRANSPORT_H

4
src/ntp_node_time.h

@ -1,3 +1,7 @@
/* ntp_node_time — обмен временем с прямыми ETCP-пирами, дополнение к интернет-NTP.
* Несинхронизированный узел принимает коррекцию синхронизированного пира с оценкой половины RTT,
* затем передаёт время остальным; при последующих сообщениях сравнивает изменение смещения для диагностики.
* init привязывает ETCP_ID_NTP_TIME и подписку на соединения, destroy удаляет их; все вызовы — uasync. */
#ifndef NTP_NODE_TIME_H
#define NTP_NODE_TIME_H

5
src/ntp_time.h

@ -1,3 +1,8 @@
/* ntp_time — асинхронные UDP NTP-запросы с DNS и периодическим повтором в uasync-потоке ядра.
* Не меняет часы ОС: хранит local_time - ntp_time в instance->ntp.offset_us.
* get_us/get_seconds возвращают скорректированное wall-clock время; до синхронизации — локальное.
* init читает config и планирует первый цикл, destroy отменяет DNS/сокет/таймеры.
* synced означает наличие коррекции (в том числе полученной от пира), reachable — результат интернет-NTP. */
#ifndef NTP_TIME_H
#define NTP_TIME_H

5
src/proxy/icmp_proxy.h

@ -1,4 +1,7 @@
// icmp_proxy.h — ICMP echo (ping) прокси: клиент ↔ exit через etcp_router
/* IPv4 ICMP echo через UTUN-router: exit отправляет ping через raw socket, сопоставляет reply
* по собственному wire id/seq и восстанавливает исходные id/seq клиента. Запросы ограничены таймаутом.
* init/destroy и callbacks — в uasync; контекст принадлежит inst, роль берётся из tcp_proxy_server.enabled.
* test_loopback возвращает виртуальные ответы без сетевой отправки и предназначен для тестов. */
#ifndef ICMP_PROXY_H
#define ICMP_PROXY_H

8
src/proxy/socks_proxy.h

@ -1,4 +1,6 @@
// socks_proxy.h — SOCKS5 / HTTP CONNECT proxy (client side)
/* Локальные SOCKS5 CONNECT и HTTP proxy/CONNECT: DNS, handshake и передача TCP через удалённый exit.
* tcp_proxy_client владеет listener и списками соединений; их callbacks выполняются в uasync.
* init_listen заимствует указатели на списки/счётчики до close_listen; закрытие listener не освобождает клиентов. */
#ifndef SOCKS_PROXY_H
#define SOCKS_PROXY_H
@ -81,13 +83,13 @@ struct listen_ctx* socks_proxy_init_listen(struct UASYNC* ua, const char* addr_s
struct UTUN_INSTANCE* inst, uint64_t via_node_id, int is_http);
// Закрыть слушающий сокет и освободить listen_ctx.
// sock_out получает значение сокета (для последующего close).
// Если sock_out задан, в него записывается SOCKET_INVALID: сокет уже закрыт.
void socks_proxy_close_listen(struct UASYNC* ua, struct listen_ctx* ctx, socket_t* sock_out);
// Найти соединение по stream_id
struct socks_proxy_conn* socks_proxy_find_conn(struct socks_proxy_conn* head, uint32_t stream_id);
// Обработать входящее ETCP сообщение (DATA/CLOSE/ERROR/FIN)
// Обработать ответ exit: CONNECTED/DATA/WINDOW_UPDATE/CLOSE/ERROR/FIN.
// Возвращает 1 если обработано, 0 если stream_id не найден
int socks_proxy_handle_etcp(struct socks_proxy_conn** head, int* count,
uint32_t stream_id, uint8_t subcmd,

5
src/proxy/tcp_proxy_client.h

@ -1,4 +1,7 @@
// tcp_proxy_client.h — TCP прокси-клиент: стек lwIP TCP → ETCP → удалённый exit узел
/* Клиент TCP-прокси: принимает IPv4 с отдельного TUN через lwIP либо TCP от SOCKS/HTTP listener.
* Передаёт потоки через UTUN-router на via_node_id; proxy_flow обеспечивает окно и backpressure.
* create/destroy и callbacks — в uasync. Владеет созданными TUN/lwIP/listener/потоками,
* заимствует inst/ua/mappings до destroy. Без tun_name/tun_ip может работать только SOCKS/HTTP. */
#ifndef TCP_PROXY_CLIENT_H
#define TCP_PROXY_CLIENT_H

5
src/proxy/tcp_proxy_server.h

@ -1,4 +1,7 @@
// tcp_proxy_server.h — TCP прокси-сервер (exit node)
/* Exit TCP-прокси: принимает CONNECT/DATA через UTUN-router и открывает обычный TCP к назначению.
* Поток определяется парой peer_node_id/stream_id; proxy_flow согласует окна и half-close.
* init учитывает tcp_proxy_server_enabled в конфиге; destroy закрывает потоки и общий UDP/ICMP-прокси.
* Состояние принадлежит UTUN_INSTANCE, операции и callbacks выполняются в его uasync-потоке. */
#ifndef TCP_PROXY_SERVER_H
#define TCP_PROXY_SERVER_H

4
src/proxy/udp_proxy.h

@ -1,4 +1,6 @@
// udp_proxy.h — UDP датаграммный прокси: клиент ↔ exit через etcp_router
/* UDP из TUN через UTUN-router: клиент отправляет REQUEST, exit открывает сокет для кортежа адресов
* и возвращает REPLY. Потоки exit удаляются по таймауту неактивности.
* init/destroy и callbacks — в uasync; контекст принадлежит inst, роль берётся из tcp_proxy_server.enabled. */
#ifndef UDP_PROXY_H
#define UDP_PROXY_H

2
src/radio/radio_audio.h

@ -75,7 +75,7 @@ int radio_audio_vad_mode(void);
/* Текущее состояние передачи: ручной PTT либо сработавший VAD. */
int radio_audio_transmitting(void);
/* uasync-поток: принятый Opus-кадр источника (декодируем + кладём в ring). */
/* uasync-поток: копируем Opus-кадр в jitter источника; декодирование/растяжение — на pull в RX-потоке. */
void radio_audio_on_frame(struct UTUN_INSTANCE* inst, uint64_t group_id,
uint64_t src_node_id, uint16_t stream_id, uint16_t seq,
uint8_t fin, const uint8_t* opus, int len, void* arg);

4
src/routing_layer/conn_mgr_priv.h

@ -1,3 +1,7 @@
/* conn_mgr_priv — внутренние состояния, wire-команды и общие операции трёх частей conn_mgr.
* core управляет handles и попытками, indirect — согласованием посредников, monitor — оценкой/обновлением путей.
* Все структуры принадлежат менеджеру topo-группы и используются в его uasync-потоке.
* Сервисы подключаются через conn_mgr.h; поля ENTRY/CANDIDATE не являются внешним API. */
#ifndef CONN_MGR_PRIV_H
#define CONN_MGR_PRIV_H

33
src/routing_layer/route6_lib.h

@ -1,3 +1,7 @@
/* route6_lib — локальная IPv6-таблица подсетей на BSD radix с longest-prefix lookup.
* Очередь индексирует записи по node_id для удаления всех подсетей узла; TOPO_GROUP_NODE заимствован.
* create/insert/lookup/delete/destroy — в одном uasync-потоке; маршруты удалять до освобождения узла.
* addr — 16 сетевых байтов. Результат lookup принадлежит таблице и живёт до удаления записи/destroy. */
#ifndef ROUTE6_LIB_H
#define ROUTE6_LIB_H
@ -13,36 +17,7 @@ extern "C" {
#include "../lib/u_async.h"
/*
Диапазон Назначение
::/128 Неопределенный адрес (unspecified). Используется до назначения адреса интерфейсу.
::1/128 Адрес обратной петли (loopback), аналог 127.0.0.1 в IPv4.
2000::/3 Глобально маршрутизируемые (Global Unicast) адреса. Основное адресное пространство Интернета.
fc00::/7 Уникальные локальные адреса (ULA), аналог частных IPv4 (10.0.0.0/8, 192.168.0.0/16). На практике обычно используется fd00::/8.
fe80::/10 Локальные канальные адреса (Link-Local). Автоматически назначаются интерфейсам и работают только в пределах одного сегмента сети. Не маршрутизируются.
ff00::/8 Multicast-адреса. Используются вместо широковещания (broadcast), которого в IPv6 нет.
100::/64 Адреса для протокола Discard-Only. Предназначены для тестирования и отладки.
64:ff9b::/96 Префикс для трансляции IPv4↔IPv6 (NAT64).
64:ff9b:1::/48 Расширенный префикс NAT64.
2001:db8::/32 Зарезервирован для документации и примеров. Не используется в Интернете.
2002::/16 6to4-адреса (устаревший механизм перехода с IPv4 на IPv6).
2001::/32 Teredo (устаревшая технология туннелирования IPv6 через IPv4).
::ffff:0:0/96 IPv4-mapped IPv6 addresses. Используются ОС для представления IPv4-адресов в IPv6 API.
Адреса узлов сети формируются по следующему принципу:
FCxx:xxxx:xxxx:xxxx : yyyy:yyyy:yyyy:yyyy - local network: x = network id, y - node id.
-- network id --- ---- node id ------
FDxx/8 - опциональные ipv6 подсети узлов /64 (если нужно)
В разных node_groups общие:
- nodelists с их настройками (глобальная таблица)
- одинаковые линки между nodes (т.к. только один линк между парой узлов)
- При маршрутизации используем только узлы
*/
// таблица маршрутизации IPv6 на radix tree + ll_queue (поиск по node_id для удаления)

4
src/routing_layer/route_connectivity.h

@ -1,3 +1,7 @@
/* route_connectivity — прямые UDP/TCP-пробы адресов узла для оценки достижимости и RTT.
* probe_node запускает серии из подходящих локальных сокетов и обновляет nq->connectivity;
* результат используется топологией, сама проба не создаёт READY-сессию группы.
* Состояние привязано к TOPO_GROUP_NODE: отменить пробы до удаления узла/группы. Все операции — uasync. */
#ifndef ROUTE_CONNECTIVITY_H
#define ROUTE_CONNECTIVITY_H

13
src/routing_layer/route_lib.h

@ -1,3 +1,8 @@
/* route_lib — локальная IPv4-таблица подсетей UTUN, отсортированный массив без пересечения маршрутов.
* create → insert/add_local_subnet → lookup → delete/destroy; все операции в одном uasync-потоке.
* network/dest_ip/parse_subnet — host order; только is_local_subnet принимает network order.
* TOPO_GROUP_NODE заимствован: удалить его маршруты до освобождения узла.
* lookup возвращает элемент массива, действительный до следующего изменения таблицы. */
#ifndef ROUTE_LIB_H
#define ROUTE_LIB_H
@ -32,7 +37,7 @@ typedef enum {
* Структура представляет собой отдельную запись в таблице маршрутизации с детальной информацией о маршруте.
*/
struct ROUTE_ENTRY {
uint32_t network; // Сетевой адрес (big-endian)
uint32_t network; // Сетевой адрес в host order
uint8_t prefix_length; // Длина префикса подсети
struct TOPO_GROUP_NODE* v_node_info; // узел владелец этих маршрутов. null если - локальный маршрут.
};
@ -78,7 +83,7 @@ void route_table_destroy(struct ROUTE_TABLE *table);
* @brief Вставляет в таблицу маршрутизации все подсети для указанного узла
* @param node узел, все маршруты которого нужно добавить
*
* @return true если вставка/обновление успешно
* @return true если подсети добавлены; false при отсутствии подсетей, пересечении или ошибке выделения памяти
*/
bool route_insert(struct ROUTE_TABLE *table, struct TOPO_GROUP_NODE *node);
@ -94,7 +99,7 @@ void route_delete(struct ROUTE_TABLE *table, struct TOPO_GROUP_NODE *node);
* @brief Выполняет поиск маршрута для заданного IP-адреса
*
* @param table Указатель на таблицу маршрутизации
* @param dest_ip Целевой IP-адрес
* @param dest_ip Целевой IPv4-адрес в host order
* @return найденный маршрут или NULL
*/
struct ROUTE_ENTRY* route_lookup(struct ROUTE_TABLE *table, uint32_t dest_ip);
@ -110,7 +115,7 @@ void route_table_print(const struct ROUTE_TABLE *table);
* @brief Парсит строку подсети в сетевой адрес и длину префикса
*
* @param subnet_str Строка подсети (например, "192.168.1.0/24")
* @param network Указатель для сохранения сетевого адреса
* @param network Указатель для сохранения адреса в host order
* @param prefix_length Указатель для сохранения длины префикса
* @return 0 при успехе, -1 при ошибке
*/

13
src/routing_layer/routing.h

@ -1,4 +1,7 @@
// routing.h - Centralized routing module for utun
/* routing — обмен IPv4-пакетами UTUN между локальным TUN и сервисом DATA ETCP-router.
* create создаёт таблицу, bind регистрирует DATA после инициализации router; set_tun подключает очередь TUN.
* route_pkt принимает [cmd:1][IPv4...] и забирает entry/dgram; все вызовы выполняются в uasync-потоке.
* Групповые пути ведёт topo_group, пересылку через промежуточные узлы — etcp_router. */
#ifndef ROUTING_H
#define ROUTING_H
@ -36,22 +39,20 @@ int routing_bind(struct UTUN_INSTANCE* instance);
void routing_destroy(struct UTUN_INSTANCE* instance);
/**
* @brief Register ETCP connection with routing
* Called from pn_init() to register connection's normalizer output queue
* @brief Исторический вызов из pn_init: сейчас только диагностический no-op, очереди не регистрирует
* @param etcp ETCP connection
*/
void routing_add_conn(struct ETCP_CONN* etcp);
/**
* @brief Unregister ETCP connection from routing
* Called from pn_deinit() to unregister connection's normalizer output queue
* @brief Исторический вызов из pn_deinit: сейчас только диагностический no-op
* @param etcp ETCP connection
*/
void routing_del_conn(struct ETCP_CONN* etcp);
/**
* @brief Set TUN interface for routing
* Called from utun_instance_init() after tun_init()
* Вызывается при подключении TUN к UTUN-сервису
* @param instance UTUN instance with configured tun
*/
void routing_set_tun(struct UTUN_INSTANCE* instance);

9
src/routing_layer/topo_node_sqlite.h

@ -1,3 +1,8 @@
/* topo_node_sqlite — хранение подписанных снимков узлов, адресов, каналов и блоков мемберов в общей SQLite.
* Модель/проверка подписей/registry — topo_node и member_sync; этот модуль реализует SQL-операции в uasync-потоке.
* snapshot_put проверяет подпись и сохраняет только более свежий timestamp; node_load предпочитает snapshot.
* db/groups заимствованы. Возвращённый TOPO_NODE без registry ref: передать registry либо уничтожить через topo_node_destroy.
* Массивы out_ids/out_ch_ids/out_peers принадлежат вызывающему и освобождаются u_free. */
#ifndef TOPO_NODE_SQLITE_H
#define TOPO_NODE_SQLITE_H
@ -101,8 +106,8 @@ void topo_node_sqlite_update_rtt(sqlite3* db, uint64_t node_id, uint16_t rtt);
* @param groups нужен для выделения адресов из memory_pool
* @return TOPO_NODE* или NULL если узел не найден/нет адресов
*
* Загружает pubkey, name из nodes, IPv4/UDP-адреса из node_addresses.
* Вызывающий должен передать владение через topo_node_registry_acquire().
* Сначала загружает и проверяет подписанный snapshot; при его отсутствии собирает сведения nodes/node_addresses.
* Вызывающий передаёт владение через topo_node_registry_acquire() либо вызывает topo_node_destroy().
*/
struct TOPO_NODE* topo_node_sqlite_node_load(sqlite3* db, struct TOPO_GROUPS* groups, uint64_t node_id);

7
src/transport_layer/crc32.h

@ -1,3 +1,8 @@
/* crc32 — табличный CRC-32 с отражённым полиномом 0xEDB88320.
* calc для непустого блока начинает с UINT32_MAX и инвертирует результат.
* calc_ex/update возвращают внутренний CRC без финальной инверсии: для потока начать с UINT32_MAX,
* последовательно update и в конце инвертировать. NULL/пустой calc → UINT32_MAX, update → исходный CRC.
* Таблица общая, без блокировки: при нескольких потоках выполнить init до их запуска. */
#ifndef CRC32_H
#define CRC32_H
@ -25,4 +30,4 @@ uint32_t crc32_update(uint32_t crc, const uint8_t *data, size_t len);
#ifdef __cplusplus
}
#endif
#endif // CRC32_H
#endif // CRC32_H

4
src/transport_layer/etcp_bbr.h

@ -1,3 +1,7 @@
/* etcp_bbr — модель congestion control одного ETCP-линка: состояния BBR, окно и pacing rate.
* ETCP собирает bbr_rate_sample из ACK/потерь и вызывает init/main/note_loss/tx_start в uasync-потоке.
* Модуль не отправляет пакеты: возвращённые лимиты применяет линк/loadbalancer.
* cwnd/inflight/delivered — байты, interval/rtt — микросекунды, pacing_rate — байты в секунду. */
#pragma once
#include <stdint.h>

182
src/transport_layer/etcp_connect.h

@ -8,178 +8,22 @@ struct ETCP_CONN;
struct TOPO_GROUP_NODE;
typedef void (*etcp_connect_callback_t)(void* arg, struct ETCP_CONN* conn, int type);
/**
* ============================================================================
* etcp_connect() — асинхронное подключение к удалённому узлу
* ============================================================================
*
* Инициирует (или находит существующее) ETCP-соединение к узлу.
* Вызов неблокирующий: коллбэк cb вызывается асинхронно по мере прохождения
* фаз установки соединения.
*
* @param inst UTUN_INSTANCE
* @param node узел-адресат (TOPO_GROUP_NODE). Из node->node берутся:
* - node_id — идентификатор узла (0 = вычислить из pubkey)
* - public_key — X25519 pubkey (32 байта)
* - v4_addrs / v6_addrs — адреса для создания линков
* @param cb коллбэк (etcp_connect_callback_t)
* @param arg пользовательский аргумент, передаваемый в cb
* @param flags битовая маска интересующих фаз: ETCP_CONNECT_EARLY(1) |
* ETCP_CONNECT_LATE(2)
* @return 0 при успехе, -1 при ошибке (до вызова коллбэка)
*
*
* ---- Деривация node_id ----
*
* Если node->node->node_id == 0, он вычисляется из public_key:
* node_id = SHA256(pubkey, 32)[0..7] & 0x7FFFFFFFFFFFFFFF
*
* Требования к ключу:
* - public_key не NULL
* - не все 32 байта нулевые
* Иначе — возврат -1 без вызова коллбэка.
*
* Вычисленный node_id сохраняется обратно в node->node->node_id.
*
*
* ---- Индексация соединения ----
*
* Сразу после etcp_connection_create() conn->peer_node_id устанавливается
* в node_id, что позволяет etcp_conn_queue_set_ready() (при инициализации
* первого линка) переиндексировать запись в очереди inst->connections
* с key=0 на key=node_id.
*
* До переиндексации соединение находится в очереди с key=0 и доступно
* только через connect_find() в pending_connects или по совпадению адреса.
*
*
* ---- Поиск существующего соединения ----
*
* Перед созданием нового conn выполняется поиск:
*
* a. instance_find_conn(inst, node_id) — активное соединение в очереди
* inst->connections (UDP) или inst->tcp_connections (TCP)
* b. connect_find(inst, node_id) — контекст в inst->pending_connects
*
* Возможные комбинации:
*
* 1. conn && ctx — уже подключается
* ├─ ctx->done (таймаут уже сработал) → cb(arg, NULL, 0) сразу
* └─ иначе → cb добавляется в ctx->cb_list (ждёт своей фазы)
*
* 2. !conn && ctx — контекст есть, но conn был удалён (редкий случай)
* → cb добавляется в ctx->cb_list
*
* 3. conn && !ctx — соединение рабочее, контекста нет (входящее/серверное)
* ├─ conn->state == 0 (pending, ещё не инициализирован):
* │ → создаётся ctx с connect_init_cb, initial_timer
* │ → ctx добавляется в pending_connects
* │ → ожидание инициализации в обычном порядке
* │
* └─ conn->state == 1 (ready, уже проинициализирован):
* → connect_deliver(ctx, ETCP_CONNECT_LATE) сразу
* → контекст освобождается; готовность топологии принадлежит группе
*
* 4. !conn && !ctx — новое подключение (основной путь)
* → etcp_connection_create(inst, NULL)
* → conn->peer_node_id = node_id (индексация deferred до queue_set_ready)
* → sc_init_ctx + sc_set_peer_public_key — настройка крипто
* → connect_create_links_v4/v6 — создание UDP + TCP линков
* → initial_timer = uasync_set_timeout(connect_timeout_tb, ...)
* → ctx добавляется в pending_connects
*
*
* ---- Фазы доставки коллбэков ----
*
* connect_init_cb (вызывается при conn->initialized, первый линк отдал рукопожатие):
*
* Подсчитывается total_links и up_links (link_state == 3):
*
* ├─ total_links == 1: один линк — EARLY не нужен
* │ → connect_deliver(ctx, ETCP_CONNECT_LATE) — сразу LATE
* │ → ctx освобождается
* │
* ├─ up_links == total_links: все линки уже UP (link_state==3)
* │ → connect_deliver(ctx, ETCP_CONNECT_LATE) — сразу LATE
* │ → ctx освобождается
* │
* └─ иначе (часть линков UP, часть ещё в handshake):
* → connect_deliver(ctx, ETCP_CONNECT_EARLY) — уведомить о доступности
* → initial_timer отменяется
* → запускается settle_timer = min_rtt * 8 (clamped [500ms, 2s] в 0.1ms)
*
* connect_settle_timeout_cb (settle-таймер):
* ├─ Закрывает неинициализированные линки (!link->initialized)
* ├─ Закрывает TCP-линк если !tcp_ready
* ├─ Убирает connect_init_cb из conn->cbks
* └─ connect_deliver(ctx, ETCP_CONNECT_LATE) → ctx освобождается
*
* connect_initial_timeout_cb (initial_timer):
* ├─ ctx->done = 1
* ├─ Закрывает TCP-линк
* ├─ connect_deliver(ctx, 0) → cb(arg, NULL, 0) для всех
* ├─ etcp_connection_close(conn) — закрывает соединение
* └─ ctx освобождается
*
*
* ---- Ошибки ----
*
* Коллбэк вызывается с type=0, conn=NULL в случаях:
* - initial_timer истёк (ни один линк не инициализировался)
* - все линки были закрыты до завершения handshake
* - ошибка аллокации / крипто на этапе создания
*
*
* ---- Штатное закрытие исходящих соединений ----
*
* Пути завершения ctx:
*
* 1. Таймаут установки (connect_initial_timeout_cb):
* stcp_link_close(tcp_link) → etcp_connection_close(conn) → connect_cancel(ctx)
*
* 2. Settle таймаут (connect_settle_timeout_cb):
* stcp_link_close(tcp_link) (если !tcp_ready) → connect_cancel(ctx)
*
* 3. Штатное закрытие через utun_instance_destroy():
* utun_instance_destroy(inst)
* ├── etcp_connection_close(conn) для всех conn
* │ Фаза 1 (detach): закрыть линки, удалить из inst->connections, state=2
* │ Фаза 2 (deferred): uasync_call_soon(ua, conn, etcp_connection_free_deferred)
* │
* ├── while (immediate_queue_head) uasync_poll(ua, 0)
* │ └── etcp_connection_free_resources(conn)
* │ ├── drain_and_free_queue(*)
* │ ├── etcp_connect_cancel_for_conn(inst, conn)
* │ └── u_free(etcp)
* │
* └── memory_pool_destroy(pkt/ack/data)
*
* ============================================================================
*/
/* Внутренний установщик прямого ETCP-транспорта; владельцы используют node_conn_direct.h.
* node->node_id должен находиться в node_registry: оттуда берутся ключ и IPv4/IPv6 адреса.
* Подключение создаёт UDP/STCP-линки либо подписывает callback на текущую попытку к тому же узлу.
* Все вызовы/callbacks — в uasync. flags — непустая маска ETCP_CONNECT_EARLY/LATE (etcp_api.h).
* EARLY означает появление транспорта; LATE — завершение выбора линков. Они не означают READY группы.
* При одном/полностью готовом наборе линков обе запрошенные фазы выдаются подряд;
* иначе после EARLY ждём settle 0.5..2с и удаляем неинициализированные линки.
* Для уже готового соединения callback вызывается внутри etcp_connect, до возврата.
* conn в callback заимствован. type=0/conn=NULL — отказ; initial timeout закрывает соединение.
* Возврат 0 означает принятую попытку/выданный результат; -1 — ошибка, причём некоторые
* ошибки создания также вызывают cb(NULL,0). Обработчик должен учитывать оба способа отказа. */
int etcp_connect(struct UTUN_INSTANCE* instance, struct TOPO_GROUP_NODE* node,
etcp_connect_callback_t cb, void* arg, uint8_t flags);
/*
* ============================================================================
* etcp_connect_cancel_for_conn()
* ============================================================================
*
* Аналог приватного connect_cancel(), но ищет ETCP_CONNECT ctx по совпадению
* ctx->conn == conn (а не по указателю на ctx).
*
* Делает:
* 1. Удаляет ctx из inst->pending_connects
* 2. ctx->done = 1; ctx->conn = NULL
* 3. uasync_cancel_timeout(initial_timer / settle_timer)
* 4. u_free(ctx)
*
* НЕ закрывает ctx->tcp_link (чужая ответственность).
*
* Вызывается ТОЛЬКО из etcp_connection_free_resources (фаза 2 deferred cleanup).
* НЕ вызывать из mainloop / uasync_poll callbacks — conn уже может быть в state=2.
*
* ============================================================================
*/
/* Снять таймеры/контекст по conn без уведомления callbacks. Только teardown соединения,
* когда connect_init_cb больше не может быть вызван; транспорт освобождает вызывающий слой. */
void etcp_connect_cancel_for_conn(struct UTUN_INSTANCE* inst, struct ETCP_CONN* conn);
/* Полная отмена pending-коннекта по node_id: снимает коллбэки с conn (conn остаётся

3
src/transport_layer/etcp_debug.h

@ -1,3 +1,6 @@
/* etcp_debug — форматирование IPv4 в host order и диагностический разбор секций ETCP_DGRAM.
* ip_to_string возвращает строку по значению. dump_pkt_sections пишет DEBUG категории dump,
* не меняет пакет и не проверяет его криптографию; состояние pkt/link читается в uasync-потоке. */
#ifndef ETCP_DEBUG_H
#define ETCP_DEBUG_H

3
src/transport_layer/etcp_dump.h

@ -1,3 +1,6 @@
/* etcp_dump — снимки состояния ETCP-соединений/линков, очередей и сокетов экземпляра.
* Вызывается в uasync-потоке, пишет DEBUG категории etcp_dump; не меняет состояние и не владеет объектами.
* conn_state выводит один conn, all_conns/sockets — соответствующие списки, all — оба списка. */
#ifndef ETCP_DUMP_H
#define ETCP_DUMP_H

10
src/transport_layer/etcp_loadbalancer.h

@ -1,4 +1,6 @@
// etcp_loadbalancer.h - Load Balancer for ETCP Channels
/* etcp_loadbalancer — выбор доступного линка одного ETCP_CONN с учётом cwnd, inflight и pacing/shaper.
* select_link возвращает заимствованный готовый линк или NULL. send шифрует/отправляет пакет и учитывает shaper,
* link_ready пробуждает packet_request_fn после снятия ограничений; все вызовы — uasync-поток соединения. */
#ifndef ETCP_LOADBALANCER_H
#define ETCP_LOADBALANCER_H
@ -20,13 +22,13 @@ struct ETCP_LINK* etcp_loadbalancer_select_link(struct ETCP_CONN* etcp);
// Когда линк снова ready (timer или link_ready) - loadbalancer должен вызвать ETCP_CONN->packet_request_fn(etcp)
//void etcp_loadbalancer_update_after_send(struct ETCP_LINK* link, size_t pkt_size); - это надо заменить на:
// Передать dgram с установленным link: после отправки (включая ошибку сокета) возвращает dgram в pkt_pool.
void etcp_loadbalancer_send(struct ETCP_DGRAM* dgram);
// сообщаем в loadbalancer о готовности линка (вызывается из таймера, ACK, изменения лимита)
void loadbalancer_link_ready(struct ETCP_LINK* link);
// проверяет все условия блокировки отправки (включая inflight_bytes)
// Проверяет готовность shaper (burst разрешён); cwnd/inflight учитывает select_link отдельно.
int loadbalancer_link_can_send(struct ETCP_LINK* link);
// Получить состояние связи ETCP: 1 - есть живой линк, 0 - все недоступны
@ -36,4 +38,4 @@ int etcp_loadbalancer_get_link_status(struct ETCP_CONN* etcp);
}
#endif
#endif // ETCP_LOADBALANCER_H
#endif // ETCP_LOADBALANCER_H

11
src/transport_layer/etcp_session.h

@ -1,3 +1,7 @@
/* etcp_session — подтверждение эпох одного ETCP_CONN, чтобы старые DATA не попадали в новый поток.
* HELLO/CHALLENGE/CONFIRM отправляются по инициализированным линкам, вне надёжного потока/normalizer.
* Обработчик вызывается после проверки защиты пакета; принадлежность сессии проверяет accept_data.
* Состояние и retry-таймер принадлежат ETCP_CONN. Все вызовы — его uasync-поток; перед teardown нужен cancel. */
#ifndef ETCP_SESSION_H
#define ETCP_SESSION_H
#include <stddef.h>
@ -11,11 +15,16 @@ struct ETCP_CONN;
#define ETCP_SESSION_HEADER_SIZE 17
#define ETCP_SESSION_CONTROL_SIZE 25
/* Authenticated link control, independent of the reliable stream and its normalizer. */
/* Запустить обязательное подтверждение; при таймауте неподтверждённое соединение закрывается. */
void etcp_session_start(struct ETCP_CONN* conn);
/* Предложить ненулевую эпоху пира для challenge; это ещё не разрешает приём DATA новой эпохи. */
void etcp_session_observe(struct ETCP_CONN* conn, uint64_t peer_epoch);
/* Отменить retry и сбросить candidate/cookie; подтверждённые reset_id/peer_reset_id сохраняются. */
void etcp_session_cancel(struct ETCP_CONN* conn);
/* 1 — control распознан (в том числе отброшен как ошибочный), 0 — не control. Буфер остаётся у вызывающего. */
int etcp_session_receive(struct ETCP_CONN* conn, const uint8_t* data, size_t len);
/* Записать 17-байтный заголовок code/sender/target; epochs — big-endian, cookie/body добавляет вызывающий. */
void etcp_session_encode(uint8_t* data, uint8_t code, uint64_t sender, uint64_t target);
/* 1 — DATA принадлежит готовой текущей сессии, 0 — ошибочная/старая. Заголовок не снимает, поток не обрабатывает. */
int etcp_session_accept_data(struct ETCP_CONN* conn, const uint8_t* data, size_t len);
#endif

3
src/transport_layer/packet_dump.h

@ -1,3 +1,6 @@
/* packet_dump — текстовая сводка IPv4-пакета: адреса, транспортные поля и короткий hex-фрагмент.
* Принимает IP-пакет без ETCP-заголовка. Результат в общем static-буфере перезаписывается каждым вызовом;
* его не освобождать, для хранения скопировать. Модуль не потокобезопасен и сам в лог не пишет. */
#ifndef PACKET_DUMP_H
#define PACKET_DUMP_H

17
src/transport_layer/pkt_normalizer.h

@ -1,4 +1,8 @@
// pkt_normalizer.h (упрощенная версия)
/* pkt_normalizer — упаковка кодограмм сервисов в надёжный байтовый поток ETCP и обратная сборка.
* input принимает целые кодограммы, packer добавляет длину и делит поток под MTU;
* unpacker читает etcp->output_queue и выдаёт целые кодограммы в output/etcp_int_recv.
* Содержимое cmd сервисов непрозрачно для normalizer. Контекст принадлежит ETCP_CONN,
* владеет своими очередями/частичными буферами/ожиданием backpressure; все вызовы — uasync. */
#ifndef PKT_NORMALIZER_H
#define PKT_NORMALIZER_H
@ -11,14 +15,7 @@ extern "C" {
#include "../lib/u_async.h"
#include <stdint.h>
/*
формат кодограмм: <cmd 1 byte> <data ... n bytes>
cmd = 0 - пакет для передачи адресату (далее содержимое пакета)
cmd = 1 - элемент роутинг-таблицы (далее один маршрут)
cmd = 2 - запрос роутинг-таблицы (без данных)
*/
/* Формат входной кодограммы: [cmd:1][данные сервиса...]; максимальная длина — PKTNORM_MAX_DGRAM_SIZE. */
#define PKTNORM_MAX_DGRAM_SIZE 16384
@ -78,4 +75,4 @@ void pn_unpacker_reset_state(struct PKTNORM* pn);
#ifdef __cplusplus
}
#endif
#endif // PKT_NORMALIZER_H
#endif // PKT_NORMALIZER_H

11
src/transport_layer/secure_channel.h

@ -1,4 +1,9 @@
// secure_channel.h
/* secure_channel — криптографические операции транспорта, без сокетов и сетевого handshake.
* Инициализировать локальные X25519-ключи → init_ctx → set_peer_public_key → encrypt/decrypt.
* ctx заимствует SC_MYKEYS до конца использования; состояние счётчиков и stream-объекты имеют одного владельца.
* Пакеты: AES-128-CCM над plaintext+CRC32; выход = nonce(13)+ciphertext+tag(16).
* Отдельные API дают обфускацию ключа, потоковый AES-CTR и Ed25519; CTR сам по себе не аутентифицирует данные.
* Возврат SC_OK / отрицательный SC_ERR_*; caller владеет входными/выходными буферами. */
#ifndef SECURE_CHANNEL_H
#define SECURE_CHANNEL_H
@ -66,7 +71,9 @@ sc_status_t sc_init_local_keys(struct SC_MYKEYS *mykeys, const char *public_key,
sc_status_t sc_set_peer_public_key(sc_context_t *ctx, const uint8_t *peer_public_key, int mode);// mode: 0-bin 1-hex key format
sc_status_t sc_compute_public_key_from_private(const uint8_t *private_key, uint8_t *public_key);
// Криптографические операции
/* Выходные длины только заполняются, не задают capacity! Для encrypt выделить plaintext_len+33 байта,
* для decrypt — ciphertext_len-33. Пустой plaintext запрещён; decrypt проверяет CCM tag и CRC.
* Проверка повторного посещения/эпохи транспорта находится выше этого модуля. */
sc_status_t sc_encrypt(sc_context_t *ctx, const uint8_t *plaintext, size_t plaintext_len, uint8_t *ciphertext, size_t *ciphertext_len);
sc_status_t sc_decrypt(sc_context_t *ctx, const uint8_t *ciphertext, size_t ciphertext_len, uint8_t *plaintext, size_t *plaintext_len);

4
src/transport_layer/socket_monitor.h

@ -1,3 +1,7 @@
/* socket_monitor — наблюдение за адресами интерфейсов и маршрутами ОС для ETCP-сокетов.
* init подключает уведомления ОС к uasync экземпляра; изменения обновляют interface_addr и сетевое состояние.
* auto_socket отдельно создаёт/удаляет сокеты. destroy отключает наблюдение до освобождения экземпляра.
* Публичные операции и изменения ETCP_SOCKET — в потоке uasync. */
#ifndef SOCKET_MONITOR_H
#define SOCKET_MONITOR_H

10
src/transport_layer/stcp.h

@ -1,4 +1,8 @@
// stcp.h — Streaming TCP: shared structures, constants, connection lifecycle
/* stcp — зашифрованное фреймирование поверх TCP: handshake ключей/эпох, AES-CTR поток и CRC кадров.
* Этот заголовок — внутренние структуры и I/O; создание исходящих/входящих соединений — client/server,
* интеграция с ETCP_LINK — stcp_link.h. Все операции одного соединения выполняются в uasync-потоке.
* do_close закрывает I/O и вызывает on_close; окончательное освобождение зависит от владельца conn.
* recv_on_chunk получает заимствованный буфер только на время callback; rx_queue получает отдельную копию. */
#ifndef STCP_H
#define STCP_H
@ -163,12 +167,12 @@ int stcp_frame_decrypt(uint8_t *data, size_t len, struct sc_stream_state *strea
void stcp_pending_queue(struct stcp_conn *c, const uint8_t *data, size_t len);
void stcp_pending_clear(struct stcp_conn *c);
// takes ownership of data (must be u_malloc'd, will be u_free'd)
// data из u_malloc: 0 — отправлен и освобождён, 1 — принят для досылки; -1 оставляет data вызывающему.
int stcp_try_send(struct stcp_conn *c, uint8_t *data, size_t len);
void stcp_write_cb(socket_t sock, void *arg);
void stcp_flush_pending(struct stcp_conn *c);
// unified recv: read from TCP, grow recv_buf, calls stcp_recv_try. returns 1=data, 0=wait, -1=error/closed
// Читает TCP в recv_buf: 1 — новые байты, 0 — ждать, -1 — ошибка/закрыто. Разбор через stcp_recv_try вызывает владелец.
int stcp_conn_read(struct stcp_conn *c);
// set next expected chunk: need=0+streaming=1 enters DATA stream mode

5
src/transport_layer/stcp_client.h

@ -1,4 +1,7 @@
// stcp_client.h — STCP client: connect, handshake
/* stcp_client — асинхронные TCP connect и STCP-handshake, с опциональными SOCKS5 и REALITY.
* connect возвращает владеющий handle или NULL; готовность DATA сообщает ready_cb, закрытие — close_cb.
* get_conn заимствует conn из handle. destroy отменяет подключение/закрывает conn и делает handle недействительным.
* Все API/callbacks — uasync-поток; TCP-ping использует отдельный короткий handshake и не создаёт ETCP-сессию. */
#ifndef STCP_CLIENT_H
#define STCP_CLIENT_H

6
src/transport_layer/stcp_link.h

@ -1,4 +1,8 @@
// stcp_link.h — STCP link management (TCP connection via STCP protocol)
/* stcp_link — адаптер STCP-соединения к ETCP_LINK: handshake, очереди DATA, ready/close callbacks.
* Серверный путь создаёт входящие линки, connect запускает исходящий для заданного ETCP_LINK.
* send копирует data в tx_queue (0 / -1); ready означает готовность STCP, не READY topo-группы.
* close гасит callback внезапного разрыва и откладывает teardown; после close handle не использовать.
* API и callbacks — uasync-поток. Указатели get_* заимствованы; адреса peer/local используют static-буферы. */
#ifndef STCP_LINK_H
#define STCP_LINK_H

5
src/transport_layer/stcp_server.h

@ -1,4 +1,7 @@
// stcp_server.h — STCP server: listen, accept, handshake
/* stcp_server — TCP listener и входящий STCP-handshake для одного UTUN_INSTANCE.
* create → connect_cb для готовых conn → destroy; сервер владеет listener и списком принятых соединений.
* destroy закрывает также принятые conn и вызывает их close callbacks; все операции — uasync-поток.
* set_reality включает TLS-камуфляж и relay неавторизованных клиентов; результат conn callback заимствован. */
#ifndef STCP_SERVER_H
#define STCP_SERVER_H

6
src/tun_if.h

@ -1,4 +1,8 @@
// tun_if.h - Cross-platform TUN interface management for utun
/* Кроссплатформенный TUN: init создаёт интерфейс и очереди, close освобождает их.
* output_queue несёт TUN → ядро, input_queue — ядро → TUN; формат очереди: префикс(1) + IP-пакет.
* tun_write принимает тот же префикс и пропускает его при записи; tun_inject_packet принимает чистый IP.
* Основной API — в uasync; Windows read-thread передаёт пакеты через tun_packet_handler.
* test_mode использует очереди вместо устройства ОС. */
#ifndef TUN_IF_H
#define TUN_IF_H

44
tools/chatgui-android/AGENTS.md

@ -19,8 +19,12 @@ tools/chatgui-android/
│ ├── instance_lite.h/c # жизненный цикл (старт/стоп/рестарт, ключи)
│ ├── utun_config_api.h/c # конфиг-провайдер (Kotlin → C)
│ ├── invite_link_c.h/c # старая копия парсера; .c не входит в UTUN_SOURCES
│ ├── voice_recorder.h/c # запись голосовых (PCM→Opus→канал)
│ └── attachment_sender.h/c # отправка файлов в канал
│ ├── voice_recorder.h/c # накопление PCM; voice/file подготовка через общий attachment_send
│ ├── attachment_sender.h/c # отправка обычных файлов в канал
│ ├── photo_sender.h/c # отправка готовых изображений в канал
│ ├── video_sender.h/c # готовый MP4 → attachment_send (канал/PM)
│ ├── standby.h/c # фоновые ACTIVE/SLEEP интервалы и отменяемое ожидание
│ └── tests/test_standby.c # тесты duty-cycle
│
├── headless/ # CLI для Linux (тестирование без Android)
│ ├── CMakeLists.txt
@ -28,7 +32,8 @@ tools/chatgui-android/
│ └── headless_control.c/h # управляющий TCP-сокет (JSON/text протокол)
│
├── jni_bridge/ # JNI прослойка C ↔ Kotlin
│ └── android_jni_bridge.c/h # C API + JNI-функции (компилятся только для Android)
│ ├── android_jni_bridge.c/h # C API; JNI-функции — только Android
│ └── android_udp_log.c/h # UDP-лог: общий буфер, flush в uasync
│
├── app/ # Android приложение (Gradle + NDK + Compose)
│ ├── build.gradle.kts
@ -45,20 +50,24 @@ tools/chatgui-android/
│ │ │ ├── InviteLink.kt # парсер utun://base64blob
│ │ │ ├── ConfigProvider.kt # конфиг из DataStore
│ │ │ ├── LogManager.kt # лог-менеджер
│ │ │ └── ServerEntry.kt # модели данных
│ │ │ ├── ServerEntry.kt # модель listen-сокета
│ │ │ ├── CallAudioEngine.kt # capture/playback звонка через native voice stack
│ │ │ ├── RadioAudioEngine.kt # capture/playback и PTT рации
│ │ │ └── UtunConnectionService.kt # Android Telecom ConnectionService для P2P-звонков
│ │ ├── viewmodel/
│ │ │ └── ChatViewModel.kt # StateFlow для UI
│ │ ├── ui/screens/
│ │ │ ├── ChannelListScreen.kt # список каналов + join/create
│ │ │ ├── ChatScreen.kt # сообщения + ввод
│ │ │ ├── JoinChannelDialog.kt # диалог подключения по invite
│ │ │ ├── QrScanScreen.kt # CameraX + ML Kit QR-сканер
│ │ │ ├── QrScannerPreview.kt # CameraX + ML Kit QR-сканер
│ │ │ ├── SettingsScreen.kt # настройки
│ │ │ └── LogScreen.kt # лог-просмотр
│ │ ├── ui/components/
│ │ │ └── MessageBubble.kt # бабблы сообщений + InputBar
│ │ └── headless/
│ │ └── HeadlessService.kt # фоновый сервис
│ │ ├── HeadlessService.kt # foreground-service фонового ядра
│ │ └── BootReceiver.kt # запуск фонового сервиса после загрузки устройства
│ └── res/
│
└── doc/ # документация
@ -263,15 +272,27 @@ port=9999
- `../../src/chat/invite_link.c/h` — Общий C-код формата invite-ссылок; Android разбирает ссылки в `data/InviteLink.kt`.
Старый `libutun_lite/invite_link_c.c` не компилируется текущим списком источников
- `libutun_lite/utun_config_api.h/c` — Поставщик конфигурации из Kotlin в C-ядро через callback-интерфейс (get_string, get_int64, get_int)
- `libutun_lite/voice_recorder.h/c` — Запись голосовых сообщений: накопление PCM-сэмплов с компрессором, кодирование в Opus-файл, отправка в канал через chat_core
- `libutun_lite/voice_recorder.h/c` — Накопление PCM 48 kHz mono с компрессором; stop передаёт запись в общий attachment_send для фонового кодирования и публикации в канал/PM
- `src/call/call_audio.h/c` (+ `voice_jitter.cpp`, `call_tones.c`, SoundTouch) — единый голосовой стек звонка (`libutun_voice`), собирается через `src/call/voice_sources.cmake`; Opus encode (PCM→peer) и decode + адаптивный джиттер-буфер + time-stretch (PCM отдаётся через `nativeCallAudioPull`). Аудио I/O в Kotlin (AudioRecord/AudioTrack)
- `libutun_lite/attachment_sender.h/c` — Отправка файлов в канал: копирование в media-директорию и регистрация через chat_core (media_index → db_sync)
- `libutun_lite/photo_sender.h/c` — Отправка готового изображения в канал с MIME-типом и размерами; подготовка картинки выполняется в Android
- `libutun_lite/video_sender.h/c` — Отправка подготовленного MP4 в канал/PM через attachment_send; задача владеет временным cache-файлом
- `libutun_lite/standby.h/c` — ACTIVE/SLEEP интервалы фонового режима, callbacks смены фазы и отменяемые wait handles
- `jni_bridge/android_udp_log.h/c` — Потокобезопасный буфер логов; timer flush привязан к текущему uasync и снимается при restart
- `libutun_lite/utun_sources.cmake` — Общий список источников: `lib/*.c` и рекурсивный `src/*.c` подхватываются автоматически;
файлы самой обёртки перечислены в `_cfg_src`, исключения — через `list(FILTER/REMOVE_ITEM)`
### Kotlin-слой
- `data/NativeLib.kt` — Kotlin-обёртка над C-библиотекой: все вызовы из Kotlin транслируются в JNI-функции
- `data/CallAudioEngine.kt` — Аудио-движок звонка: AudioRecord/AudioTrack, audio-focus, потоки захвата (feed) / воспроизведения (pull из C-стека)
- `data/RadioAudioEngine.kt` — Аудио-движок рации: AudioRecord/AudioTrack, feed/pull native-стека и управление capture/PTT
- `data/RadioPttHolds.kt` — Отдельные владельцы ручного PTT: кнопка, overlay и volume-клавиши; отпускание одного не снимает остальные
- `data/RadioOverlayService.kt` — Плавающее окно PTT поверх других приложений
- `data/ConversationTarget.kt` — Типизированный target канала/PM для асинхронных операций
- `data/AudioRecorderManager.kt` — Android-захват PCM голосового сообщения и управление native voice_recorder
- `data/CallController.kt` / `CallState.kt` — Управление состоянием и действиями P2P-звонка
- `data/CallAudioRouter.kt` — Выбор аудиомаршрута звонка: earpiece/speaker/headset
- `data/TelecomCallManager.kt` / `UtunConnection.kt` / `UtunConnectionService.kt` — Интеграция P2P-звонков с Android Telecom
- `data/ChatRepository.kt` — Хранилище данных: буферизация сообщений и каналов между C-ядром и UI через StateFlow
- `data/InviteLink.kt` — Разбор invite-ссылок: извлекает ID канала, публичный ключ, адреса для подключения
- `data/ConfigProvider.kt` — Настройки DataStore и генерация INI-текста для запуска C-ядра
@ -279,8 +300,15 @@ port=9999
- `viewmodel/ChatViewModel.kt` — ViewModel: StateFlow-состояние для UI (список каналов, сообщения, статус)
- `ui/screens/ChannelListScreen.kt` — Главный экран: список каналов, кнопки Join (по invite-ссылке) и Create
- `ui/screens/ChatScreen.kt` — Экран чата: список сообщений + поле ввода
- `ui/screens/DmChatScreen.kt` — Экран личной беседы
- `ui/screens/MemberListScreen.kt` — Участники канала и действия над выбранным участником
- `ui/screens/CallScreen.kt` / `IncomingCallDialog.kt` — Активный и входящий звонок
- `ui/screens/PhotoRecordScreen.kt` / `VideoRecordScreen.kt` — Съёмка и подготовка media через CameraX
- `ui/screens/PhotoViewerScreen.kt` / `VideoPlayerScreen.kt` — Просмотр локальных изображений и видео
- `ui/screens/InviteLinkDialog.kt` — Выдача invite-ссылки и QR
- `ui/screens/FirstLaunchScreen.kt` — Первичная настройка приложения
- `ui/screens/JoinChannelDialog.kt` — Диалог подключения к каналу: ввод/вставка invite-ссылки, предпросмотр, кнопка Connect
- `ui/screens/QrScanScreen.kt` — QR-сканер для invite-ссылок (CameraX + ML Kit)
- `ui/screens/QrScannerPreview.kt` — QR-сканер для invite-ссылок (CameraX + ML Kit)
- `MainActivity.kt` — Точка входа Android-приложения: навигация между экранами, QrScan → JoinDialog flow
### Headless

35
tools/chatgui-android/headless/headless_control.h

@ -1,32 +1,9 @@
/*
* headless_control.h — JSON control socket for uTun headless mode
*
* JSON line protocol:
* Request: {"id":N,"cmd":"<command>",...params}
* Response: {"id":N,"ok":true,"data":{...}} | {"id":N,"ok":false,"error":"..."}
* Event: {"event":"<type>",...}
*
* Commands:
* ping — alive check
* status — node info, uptime, connections
* connect — STCP connect to peer
* disconnect — STCP disconnect
* connections — list active connections
* create_channel — create chat channel
* channels — list channels
* send — send message to channel
* messages — get messages from channel
* debug_level — get/set debug levels
* subscribe — subscribe to events
* join — join channel via invite link
* quit — disconnect client
*
* Events (after subscribe):
* log — {"event":"log","level":"info","cat":"ETCP","msg":"..."}
* msg — {"event":"msg","ch":"id","author":"hex","ts":123}
* peer_online/offline
* channel_created/joined
*/
/* Каркас TCP-управления Android headless: init → регулярный poll → destroy в одном потоке.
* ua сейчас не используется; основной рабочий API чата — src/chat/chat_headless_control.h.
* JSON line: {"id":N,"cmd":"..."} → {"id":N,"ok":true,"data":...} либо error.
* ping/status/connections/debug_level возвращают заглушки; subscribe/quit управляют клиентом.
* join/chat_setting обращаются к запущенному instance_lite; прочие команды дают not implemented.
* event/broadcast_log отправляют JSON подписанным клиентам. Этот модуль сам ядро не запускает. */
#ifndef HEADLESS_CONTROL_H
#define HEADLESS_CONTROL_H

6
tools/chatgui-android/jni_bridge/android_jni_bridge.h

@ -2,7 +2,8 @@
* android_jni_bridge.h — JNI bridge API (C side)
*
* Provides lifecycle management and callbacks between C core and Kotlin.
* For Android, compiled via NDK into libutun_lite.so.
* NDK собирает bridge вместе с ядром в libutun.so. Действия передаются в uasync;
* callbacks логов/событий вызываются из native-потоков, UI переносит их в свой поток.
*/
#ifndef ANDROID_JNI_BRIDGE_H
#define ANDROID_JNI_BRIDGE_H
@ -51,7 +52,8 @@ void utun_bridge_create_channel(const char* name, const char* channel_id);
void utun_bridge_connect_node(const char* address, int port, const char* pubkey_hex);
/* Join channel via invite link.
addr_data format: family(1) + socketId(1) + address(4|16) + port(2 BE) per addr */
addrs_data — результат invite_serialize_addrs: Reality-префикс и
family(1) + socketId(1) + proto(1) + address(4|16) + port(2 BE) для каждого адреса. */
void utun_bridge_join_channel(uint64_t channel_id, uint64_t node_id,
const uint8_t* pubkey_bin,
const uint8_t* addrs_data, int addr_count,

3
tools/chatgui-android/libutun_lite/attachment_sender.h

@ -1,3 +1,6 @@
/* Android-обёртка отправки обычного файла в канал через chat_core_submit_trampoline.
* Строит имя назначения в db_path/media/channel_id, копирование/индексацию выполняет media_index.
* 0 = запрос поставлен в uasync, -1 = отказ подготовки. Исходный файл нужен до завершения media-задачи. */
#ifndef ATTACHMENT_SENDER_H
#define ATTACHMENT_SENDER_H

23
tools/chatgui-android/libutun_lite/instance_lite.h

@ -1,9 +1,7 @@
/*
* instance_lite.h — lightweight uTun instance lifecycle for Android
*
* Kotlin generates INI config text, passes to instance_lite_start().
* C side parses it, creates uasync+ETCP+bgp+chat stack, runs in a pthread.
* Mirrors UtunNode::runLoop() from tools/chatgui/transport/utun_node.cpp.
* Android-владелец одного ядра: INI из Kotlin → pthread с uasync → core_start + chat_service_start.
* UTUN-сервис не запускается. Поток владеет instance/ua; UI передаёт работу через uasync.
* Полученные handles заимствованы и могут смениться при restart; сохранять их между рестартами нельзя.
*/
#ifndef INSTANCE_LITE_H
#define INSTANCE_LITE_H
@ -17,14 +15,12 @@ extern "C" {
struct UASYNC;
struct UTUN_INSTANCE;
/* Start full uTun stack from INI config text.
* Creates a pthread for uasync event loop.
* Returns 0 on success, -1 on error.
* Config format: same as utun INI (see node_config.cpp saveFull). */
/* Копирует INI и запускает поток. 0 = поток создан либо уже запущен, -1 = ошибка запуска.
* Готовность самого ядра появляется позже: проверять is_running и события инициализации. */
int instance_lite_start(const char* config_text);
/* Signal stop and wait for thread to exit.
* Calls chat_sync_destroy, chat_core_destroy, utun_instance_destroy, uasync_destroy. */
/* Сигнализировать stop и дождаться потока; поток уничтожает instance, затем uasync.
* Вызывать с управляющего потока при существующем instance, не из callback ядра. */
void instance_lite_stop(void);
/* Returns non-zero if instance is running. */
@ -44,9 +40,8 @@ void instance_lite_set_event_handler(instance_lite_event_fn handler);
* Call from any thread. Keys are regenerated asynchronously. */
void instance_lite_regenerate_keys(void);
/* Restart the instance internally (no thread kill). Stops chat_sync/chat_core,
* re-parses config, regenerates keys if needed, reopens DB, re-inits.
* Posts to uasync thread — restart happens asynchronously. */
/* Копирует INI, будит poll-loop и пересоздаёт instance и uasync внутри worker.
* Если ядро не работает, выполняет stop/start. Обновление асинхронное; старые handles утрачивают силу. */
void instance_lite_restart(const char* new_config_text);
/* Лёгкое обновление сокетов (auto_sockets=android): перечитывает [server] секции

13
tools/chatgui-android/libutun_lite/invite_link_c.h

@ -1,3 +1,6 @@
/* Старая отдельная копия C-кодека utun://; invite_link_c.c исключён из текущего UTUN_SOURCES.
* Рабочее общее API — src/chat/invite_link.h, Qt/Kotlin используют тот же формат версии 0x03.
* Эти структуры не следует смешивать с InviteData общего API. */
#ifndef INVITE_LINK_C_H
#define INVITE_LINK_C_H
@ -48,17 +51,17 @@ struct InviteDataC {
};
/* decode utun://base64 link string, returns 0 on success, -1 on error.
error buffer must be at least 256 bytes */
error_buf необязателен, текст ошибки ограничивается error_buf_size. */
int invite_link_decode(const char* link, size_t link_len, struct InviteDataC* out,
char* error_buf, size_t error_buf_size);
/* encode invite data to utun://base64 string.
password may be NULL (v1 format, no password).
out buffer must be large enough (~512 bytes safe).
returns written length (excluding null), or -1 on error */
password=NULL означает пустой пароль в версии 0x03.
out_size включает utun://, base64 и NUL; недостаточная ёмкость даёт -1.
returns base64 length (excluding prefix and null), or -1 on error */
int invite_link_encode(const struct InviteDataC* data, const char* password, char* out, size_t out_size);
/* serialize per-addr format for chat_sync_connect_from_invite():
/* serialize for chat_sync_connect_from_invite(): Reality-префикс + адреса:
family(1) + socketId(1) + proto(1) + address(4|16) + port(2 BE)
returns total bytes written, or -1 if buf too small */
int invite_serialize_addrs(const struct InviteDataC* data, uint8_t* buf, size_t buf_size);

3
tools/chatgui-android/libutun_lite/photo_sender.h

@ -1,3 +1,6 @@
/* Отправка уже подготовленного изображения в канал: MIME выбирается по расширению, width/height даёт caller.
* Не декодирует и не масштабирует изображение; ставит копирование/индексацию в chat_core/media_index.
* 0 = запрос поставлен в uasync, -1 = отказ. src_file_path должен существовать до завершения задачи. */
#ifndef PHOTO_SENDER_H
#define PHOTO_SENDER_H

9
tools/chatgui-android/libutun_lite/utun_config_api.h

@ -1,9 +1,8 @@
/*
* utun_config_api.h — configuration provider API for Android
*
* C core requests config values from Kotlin via callbacks.
* For headless, a stub provider reads from environment variables.
* For Android, JNI bridge sets callbacks that query Kotlin DataStore.
* Callback-провайдер отдельных настроек native-обёртки. Без провайдера/accessor возвращает default.
* Основной конфиг ядра передаётся INI-текстом в instance_lite_start, а не через этот интерфейс.
* set_provider заимствует таблицу callbacks; она и возвращаемые строки должны жить во время вызовов.
* Провайдер установить до запуска потребителей: синхронизации внутри модуля нет.
*/
#ifndef UTUN_CONFIG_API_H
#define UTUN_CONFIG_API_H

4
tools/chatgui-android/libutun_lite/video_sender.h

@ -1,3 +1,7 @@
/* Отправка подготовленного MP4 в канал или dm:conv_id через общий attachment_send.
* Android передаёт duration_ms/width/height; повторного транскодирования здесь нет. db_path не используется.
* 0 = запрос поставлен в uasync, -1 = отказ. Передаётся владение временным cache-файлом:
* задача удаляет src_file_path после подготовки. Результат публикации приходит событием ядра. */
#ifndef VIDEO_SENDER_H
#define VIDEO_SENDER_H

5
tools/chatgui-android/libutun_lite/voice_recorder.h

@ -1,3 +1,8 @@
/* Android-накопитель голосового: init → start(target,48000,1) → feed PCM int16 → stop либо cancel.
* target — channel_id либо dm:conv_id. feed копирует count mono-сэмплов; управление защищено mutex.
* stop отсоединяет PCM/компрессор и ставит attachment_send в uasync: encode/file работа идёт в worker.
* stop=0 означает постановку подготовки либо отбрасывание записи короче 500мс, не доставку сообщения.
* deinit освобождает текущую запись; завершение сетевой отправки отслеживается событиями ядра. */
#ifndef VOICE_RECORDER_H
#define VOICE_RECORDER_H

6
tools/chatgui/db/db_manager.h

@ -1,3 +1,7 @@
/* SQLite-представление данных для desktop UI: каналы/сообщения/узлы, локальные имена и диагностика БД.
* setDb заимствует handle ядра, destructor закрывает свои statement-курсоры, но не SQLite.
* Перед уничтожением БД закрыть курсоры и сбросить ссылку. Сетевые и подписанные изменения идут через chat_core;
* методы чтения возвращают самостоятельные Qt-значения. */
#ifndef DB_MANAGER_H
#define DB_MANAGER_H
@ -120,7 +124,7 @@ public:
QList<AccountRow> getAccounts(bool contactsOnly = false) const;
AccountRow getAccount(quint64 nodeId) const;
/* ── UI state (read-only используем QSettings, оставлен для совместимости) ── */
/* ── Чтение UI state из SQLite ── */
QString getUiState(const QString& key) const;
int getUiStateInt(const QString& key, int defaultVal) const;

1
tools/chatgui/src/accountdelegate.h

@ -1,3 +1,4 @@
/* Отрисовка строки участника AccountList: аватар, имя, online и служебные значки. */
#pragma once
#include <QStyledItemDelegate>

2
tools/chatgui/src/accountlist.h

@ -1,3 +1,5 @@
/* Панель участников выбранного канала и live-диагностика выбранного узла.
* Получает события bridge в GUI-потоке; запросы звонка и PM отдаёт через signals. */
#pragma once
#include <QWidget>

2
tools/chatgui/src/animtimer.h

@ -1,3 +1,5 @@
/* Общий GUI-таймер анимированных emoji: регистрирует LottieIcon и выдаёт ticked.
* play запускает минимум PlaybackMs; shutdown останавливает таймер и очищает регистрацию. */
#pragma once
#include <QObject>

2
tools/chatgui/src/audiodevicesettingspage.h

@ -1,3 +1,5 @@
/* Настройки capture/playback, Opus, компрессора, AEC и рации; тест микрофона и динамика.
* loadFromDb заполняет форму, applyAndSave применяет выбранные значения. */
#pragma once
#include <QWidget>
#include <QComboBox>

3
tools/chatgui/src/audiorecorder.h

@ -1,3 +1,6 @@
/* Запись голосового сообщения: capture 48 kHz mono → очередь → worker PCM/компрессора.
* GUI управляет init/start/stop/shutdown; meterOnly измеряет уровень без накопления записи.
* takeRecording передаёт остановленные PCM/компрессор в attachment_send_req для фоновой подготовки. */
#pragma once
#include <QObject>

1
tools/chatgui/src/channeldelegate.h

@ -1,3 +1,4 @@
/* Роли модели и отрисовка ChannelList: канал/PM, последнее сообщение, unread и кнопки действий. */
#pragma once
#include <QStyledItemDelegate>

2
tools/chatgui/src/channellist.h

@ -1,3 +1,5 @@
/* Список каналов и PM с unread/online; загружает данные DbManager и принимает обновления bridge.
* Выбор и действия пользователя передаёт наружу signals; виджет используется в GUI-потоке. */
#pragma once
#include <QWidget>

1
tools/chatgui/src/channelsettingsdialog.h

@ -1,3 +1,4 @@
/* Локальные настройки выбранного канала: autoplay голосовых, звук сообщений и режим PTT. */
#pragma once
#include <QDialog>

2
tools/chatgui/src/chatview.h

@ -1,3 +1,5 @@
/* Вид истории сообщений: фон, выделение строк/текста, копирование и прокрутка вниз.
* MessageDelegate рисует содержимое; ChatView обрабатывает мышь и клавиатуру. */
#pragma once
#include <QListView>

1
tools/chatgui/src/creategroupdialog.h

@ -1,3 +1,4 @@
/* Диалог ввода имени нового канала. groupName возвращает имя для создания канала вызывающим кодом. */
#pragma once
#include <QDialog>

1
tools/chatgui/src/debug_ui.h

@ -1,3 +1,4 @@
/* Макросы логирования GUI через общий debug_config, категория GENERAL. */
#pragma once
extern "C" {

2
tools/chatgui/src/emoji.h

@ -1,3 +1,5 @@
/* Каталог Unicode/анимированных emoji и соответствие Unicode → ресурс анимации.
* detectEmojiOnly возвращает 1..3 для текста только из emoji/пробелов; иначе 0. */
#pragma once
#include <QString>

1
tools/chatgui/src/emojipanel.h

@ -1,3 +1,4 @@
/* Панель выбора emoji по категориям; выбранный Unicode передаётся в composer через emojiSelected. */
#pragma once
#include <QWidget>

1
tools/chatgui/src/emojitabbar.h

@ -1,3 +1,4 @@
/* Отрисовка вкладок категорий EmojiPanel с собственным стилем выбранной вкладки. */
#pragma once
#include <QTabBar>

1
tools/chatgui/src/flagpainter.h

@ -1,3 +1,4 @@
/* Отрисовка флагов участника (supernode/admin/moder/deleted) и отдельного значка storage. */
#ifndef FLAGPAINTER_H
#define FLAGPAINTER_H

2
tools/chatgui/src/imageviewer_window.h

@ -1,3 +1,5 @@
/* Окно просмотра локального изображения: масштаб колесом, перенос мышью и fullscreen.
* loadFile загружает изображение; closed сообщает владельцу о закрытии окна. */
#pragma once
#include <QWidget>

3
tools/chatgui/src/inputbar.h

@ -1,3 +1,6 @@
/* Composer канала/PM: текст, emoji, запись голосового и выбор вложений.
* Контекст target фиксируется в запросе вложения; подготовку и отправку выполняет ядро.
* Переданный submitAttachment request должен принять и освободить обработчик сигнала. */
#pragma once
#include <QWidget>

2
tools/chatgui/src/invite_link.h

@ -1,3 +1,5 @@
/* Qt-кодек utun://: channelId/joinKey, пароль, Reality и адреса connection-узла.
* decodeInviteLink возвращает ошибку в InviteData.error; подключения выполняет UtunNode/chat_sync. */
#pragma once
#include <QString>

1
tools/chatgui/src/inviteby.h

@ -1,3 +1,4 @@
/* Диалог приглашения узла по его utun:// ссылке в текущий канал; ждёт результата ядра через bridge. */
#pragma once
#include <QDialog>

2
tools/chatgui/src/invitedialog.h

@ -1,3 +1,5 @@
/* Диалог выдачи invite-ссылки и QR: запрашивает кандидатов и зарегистрированную ссылку у ядра.
* requestId связывает асинхронный ответ с текущим запросом; URL отображается после LINK_READY. */
#pragma once
#include <QDialog>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save