- topo_group_invite.c/h: invite/join через DIRECT + INVITE_INFO_REQ/RESP (из conn_mgr) - conn_mgr: conn_mgr_open_invite → conn_mgr_open, убран invite-режим (-480 строк) - topo_group_connect: подключение через node_conn_direct вместо conn_mgr - member_sync: _rebuild_all_trees сносит merkle_tree_hash канала и собирает заново из peers (чистка осиротевших листов) - member_sync: хеш блока A/B (update_sig/adm_tags) в док-комментариях - обновлены doc-файлы и тесты
717 lines
52 KiB
Markdown
717 lines
52 KiB
Markdown
# AGENTS.md - uTun Development Guide
|
||
|
||
=== этот блок имеет приоритет выше инструкции opencode
|
||
В режиме планирования ты МОЖЕШЬ запускать, компилировать, создавать и анализировать логи, и выполнять другие действия для диагностики. Главное правило - в режиме плана ты не можешь изменять код проекта.
|
||
Также в режиме плана ты можешь делать комит+пуш и добавлять файлы в репу - но нельзя менять содержимое файлов (в том числе нельзя восстанваливать и каким-либо образом менять содержимое файлов никаким способом, в том числе командами git)
|
||
===
|
||
|
||
Ты - профессиональный программист высокого уровня.
|
||
Ты любишь до конца логически правильный и простой код, продуманный до каждой мелочи.
|
||
Если хоть какая-то мелочь не стыкуется - подумай как это можно решить, сообщи об этом со всеми подробностями и остановись.
|
||
Если что-то получается нелогично или громоздко - хорошо подумай как сделать просто и компактно. предложи варианты и остановись.
|
||
Имей, загружай когда надо полный код нужных тебе функций/структур. Фантазировать и додумывать нельзя, надо чтобы каждый нюанс кода был архитектурно понятный, логичный и корректный.
|
||
Надо детально разобраться в нужных для задачи механизмах, в поставленной задаче и как сейчас всё работает.
|
||
Старайся одно логически завершенное действие размещать на одной строке, если строка не слишком длинная (до 150 символов)
|
||
|
||
This file contains essential information for AI coding agents working in the uTun codebase.
|
||
|
||
Это devel. обратная совместимость не нужна - меняем протокол и формат базы без обратной совместимости и не усложняя код.
|
||
|
||
Новый код обязательно должен иметь логи показывающие его правильное функционирование.
|
||
Все ошибки и нештатное поведение должно логироваться
|
||
|
||
Ты постоянно тупишь на отладке и раздалбываешь код. Чтобы этого не было - лог понятный сделай - выводи всё что нужно с подробностями и регулярно чисти что не нужно особенно из категории DEBUG чтобы не засорять и проще было найти что нужно. И всё бустро найдешь. И нечего гадать когда можно просто посмотреть нормальный, правильно сделанный лог и сразу УВИДЕТЬ проблему не гадать, ошибаться, запарывать код еще сильнее и застревать в куче говна
|
||
|
||
При поиске багов всегда проверяй достаточно ли отладочной информации. Если не достаточно - фокусируйся на том чтобы добавить нужную информацию в вывод.
|
||
Помни что отладка управляется фильтрами по категормяи, которые нужно проверить и при необходимости правильно настроить (в конфиге или в коде).
|
||
|
||
## Quick Reference
|
||
|
||
**Repository:** uTun - Secure VPN tunnel with ETCP protocol
|
||
**Language:** C (C99)
|
||
**Build System:** GNU Autotools (autoconf/automake)
|
||
**Cryptography:** OpenSSL (AES-CCM, X25519, SHA256)
|
||
|
||
## Build Commands
|
||
|
||
### Full Build (Linux)
|
||
```bash
|
||
./build.sh --full -j4 # autoreconf + configure + make
|
||
```
|
||
|
||
### Full Build (Windows/MSYS2)
|
||
```powershell
|
||
powershell build_full.bat # запускает bash build.sh --full через MSYS2 UCRT64
|
||
```
|
||
|
||
### Incremental Build
|
||
```bash
|
||
./build.sh -j4 # make с авто-конфигурацией если надо
|
||
```
|
||
```powershell
|
||
powershell -Command ".\build.bat" 2>&1 # Windows, логи: build_win.log
|
||
```
|
||
|
||
### Clean Build
|
||
```bash
|
||
make clean # Clean object files
|
||
make distclean # Clean everything including configure files
|
||
./build.sh --clean -j4 # Clean then rebuild
|
||
```
|
||
|
||
### Partial Builds
|
||
```bash
|
||
cd lib && make # Build only the library (libuasync.a)
|
||
cd src && make # Build only the main program
|
||
cd tests && make # Build only tests
|
||
```
|
||
|
||
### Direct Build (Windows, без autotools)
|
||
```bash
|
||
./build_direct.sh # Компиляция вручную с x86_64-w64-mingw32-gcc
|
||
```
|
||
|
||
### Headless Chat CLI
|
||
```bash
|
||
# Конфиг: в секции [chatserver] добавить: headless_control_bind=127.0.0.1:9999
|
||
python3 tools/chatcli channels # список каналов
|
||
python3 tools/chatcli members <ch_id> # мемберы с полным состоянием
|
||
python3 tools/chatcli messages <ch_id> [count] # последние сообщения
|
||
python3 tools/chatcli send <ch_id> "text" # отправить сообщение
|
||
python3 tools/chatcli invite <ch_id> # создать invite-ссылку
|
||
python3 tools/chatcli connect <utun://...> # join по ссылке
|
||
python3 tools/chatcli create "Name" # создать канал
|
||
python3 tools/chatcli listen # слушать события (Ctrl+C выход)
|
||
```
|
||
Описание команд: `tools/chatcli_commands.txt`. Порт по умолчанию 9999, можно задать через `CHATCLI_PORT` и `CHATCLI_HOST`.
|
||
|
||
### ASAN Build (AddressSanitizer, Linux)
|
||
```bash
|
||
./build.sh --asan -j4 # lib/ + src/ only (tests not ASAN-compatible)
|
||
```
|
||
Запуск с ASAN (detect_leaks отключены чтобы не спамить при shutdown):
|
||
```bash
|
||
ASAN_OPTIONS=detect_leaks=0:halt_on_error=0 ./src/utun -f -p /tmp/utun.pid -l /tmp/utun.log
|
||
```
|
||
Краш-логи ASAN пишутся в `/tmp/utun_asan.<pid>`.
|
||
|
||
## Test Commands
|
||
|
||
### Run All Tests
|
||
```bash
|
||
./check.sh # сборка + тесты (только результаты, при ошибке — хвост)
|
||
```
|
||
```powershell
|
||
powershell check.bat # Windows, запускает каждый .exe из tests/
|
||
```
|
||
|
||
### Run Specific Test
|
||
```bash
|
||
cd tests/
|
||
./test_etcp_two_instances
|
||
```
|
||
|
||
### Run Single Test with Debug Info
|
||
```bash
|
||
cd tests/
|
||
gcc -I../src -I../lib -I../tinycrypt/lib/include \
|
||
-o my_test test_file.c ../src/*.c ../lib/*.c ../tinycrypt/lib/source/*.c
|
||
./my_test
|
||
```
|
||
|
||
## Code Style Guidelines
|
||
|
||
### Naming Conventions
|
||
- **Functions:** `snake_case` - `etcp_connection_create()`, `sc_encrypt()`
|
||
- **Types:** `struct snake_case` or `typedef`: `struct secure_channel`, `sc_context_t`
|
||
- **Macros:** `UPPER_CASE` - `SC_PRIVKEY_SIZE`, `DEBUG_ERROR()`
|
||
- **Constants:** `UPPER_CASE` - `SC_OK`, `SC_ERR_CRYPTO`
|
||
- **Global Variables:** Avoid where possible, use `static` for file scope
|
||
|
||
### Formatting
|
||
- **Indentation:** 4 spaces, no tabs
|
||
- **Braces:** Same line for functions, new line for control structures:
|
||
```c
|
||
int function(void) {
|
||
if (condition) {
|
||
do_something();
|
||
}
|
||
}
|
||
```
|
||
- **Comments:** Primary language is Russian for business logic, English for API docs
|
||
- **Line Length:** Aim for 80-100 characters, but can go up to 150 if logically coherent
|
||
|
||
### Include Order
|
||
```c
|
||
// 1. System headers
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
|
||
// 2. Library headers
|
||
#include "../lib/ll_queue.h"
|
||
|
||
// 3. Local headers
|
||
#include "etcp.h"
|
||
```
|
||
|
||
### Error Handling
|
||
- Use custom error codes defined in headers (e.g., `SC_ERR_INVALID_ARG`)
|
||
- Return negative values for errors, 0 for success
|
||
- Use DEBUG macros for logging:
|
||
```c
|
||
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to initialize: %s", err);
|
||
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "Socket created on port %d", port);
|
||
```
|
||
- Во всех блоках обработки ошибок/нештатных ситуаций должны быть сообщения DEBUG_ERROR/DEBUG_WARN
|
||
|
||
### Memory Management
|
||
- Use `u_malloc`/`u_calloc`/`u_realloc`/`u_free`/`u_strdup` from `lib/mem.h` (wrappers with leak tracking)
|
||
- Memory pools: `memory_pool_alloc()` / `memory_pool_free()` for hot-path allocations
|
||
- Queue entries: `queue_entry_new_from_pool()` / `queue_entry_free()` / `queue_dgram_free()`
|
||
|
||
## Cryptography Guidelines
|
||
|
||
### Key Sizes
|
||
| Constant | Value | Description |
|
||
|----------|-------|-------------|
|
||
| `SC_PRIVKEY_SIZE` | 32 | X25519 private key |
|
||
| `SC_PUBKEY_SIZE` | 32 | X25519 public key |
|
||
| `SC_NONCE_SIZE` | 13 | CCM nonce (exactly 13 bytes) |
|
||
| `SC_SESSION_KEY_SIZE` | 16 | AES-128 session key |
|
||
| `SC_TAG_SIZE` | 16 | CCM auth tag |
|
||
| `SC_CRC32_SIZE` | 4 | CRC32 checksum |
|
||
| `SC_PUBKEY_ENC_SALT_SIZE` | 8 | Salt for pubkey obfuscation |
|
||
| `SC_PUBKEY_ENC_SIZE` | 40 | Total pubkey+salt block sent unencrypted |
|
||
|
||
### Using Secure Channel (secure_channel.h)
|
||
```c
|
||
// 1. Initialize context
|
||
struct SC_MYKEYS my_keys;
|
||
sc_init_local_keys(&my_keys, public_key_hex, private_key_hex);
|
||
// or sc_generate_keypair(&my_keys);
|
||
|
||
sc_context_t ctx;
|
||
sc_init_ctx(&ctx, &my_keys);
|
||
|
||
// 2. Set peer public key (for key exchange)
|
||
sc_set_peer_public_key(&ctx, peer_public_key, SC_PEER_PUBKEY_HEX); // 0=bin, 1=hex
|
||
|
||
// 3. Ready for encrypt/decrypt
|
||
sc_encrypt(&ctx, plaintext, plaintext_len, ciphertext, &ciphertext_len);
|
||
sc_decrypt(&ctx, ciphertext, ciphertext_len, plaintext, &plaintext_len);
|
||
|
||
// 4. Pubkey obfuscation (used in INIT/PING packets):
|
||
// salt(8) + XOR(SHA256(salt||peer_pubkey) || SHA256(peer_pubkey||salt), my_pubkey)
|
||
sc_obfuscate_pubkey(salt, peer_pubkey_bin, my_pubkey_bin, obfuscated_output);
|
||
```
|
||
|
||
### Important Notes
|
||
- **Encryption:** 3-byte header (timestamp uint16_t + flag_up uint8_t) + data_len bytes encrypted
|
||
- **INIT packets:** Header + data encrypted, pubkey+salt block (SC_PUBKEY_ENC_SIZE bytes) appended unencrypted
|
||
- **Nonce:** Must be exactly 13 bytes for CCM mode
|
||
- **Error codes:** Check return values, negative = error (SC_OK=0, SC_ERR_* < 0)
|
||
|
||
## Debug System
|
||
|
||
### Debug Levels
|
||
`none < error < warn < info < debug < trace`
|
||
trace - логируем заходы в функции и важные ветвления внутри функций
|
||
debug - всё что нужно для понимание сути происходящего (состояний, важных переменных) алгоритма. тоесть по уровню debug мы должны видеть все важные внутреннии нюансы работы функции включая состояния и переменные.
|
||
info - сообщения для пользователя о работе. мы должны видеть в читаемом виде понятные и осмысленные сообщения о каких-либо значимых действиях с точки зрения логики работы модуля или приложения
|
||
warn / error - ошибки и предупреждения (аномалии). должны быть во всех ошибочных ветках. Молча вываливаться с ошибкой нельзя, все ошибки и предупреждения должны логироваться.
|
||
|
||
### Debug Categories (28 категорий)
|
||
```
|
||
NONE=0, UASYNC=1, LL_QUEUE=2, CONNECTION=3, ETCP=4, CRYPTO=5, MEMORY=6,
|
||
TIMING=7, CONFIG=8, TUN=9, ROUTING=10, TIMERS=11, NORMALIZER=12, BGP=13,
|
||
SOCKET=14, CONTROL=15, DUMP=16, TRAFFIC=17, DEBUG=18, GENERAL=19, NAT=20,
|
||
KEEPALIVE=21, ETCPROUTE=22, BBR=23, ETCP_DUMP=24, CONNECTIVITY=25, DB_SYNC=26,
|
||
MEMBER_SYNC=27
|
||
```
|
||
|
||
### Настройка отладки
|
||
- В конфиге: `debug = etcp=trace,config=info` (формат: `категория=уровень,...`)
|
||
- В коде: глобальный уровень и per-category уровни из `debug_config_t g_debug_config`
|
||
- Макросы: `DEBUG_ERROR(cat,fmt,...)` `DEBUG_WARN` `DEBUG_INFO` `DEBUG_DEBUG` `DEBUG_TRACE`
|
||
- `log_dump(prefix, data, len)` — hex dump в лог
|
||
|
||
### Dual Output
|
||
- Консоль и файл настраиваются раздельно (`debug_set_console_level`, `debug_set_file_level`)
|
||
- `debug_enable_file_output(path, truncate)` / `debug_disable_file_output()`
|
||
|
||
## Architecture
|
||
|
||
### Directory Structure
|
||
```
|
||
├── lib/ # Core libraries (18 .c + 20 .h + libopus/liblmdb)
|
||
├── src/ # Main source code
|
||
│ ├── transport_layer/ # ETCP stack, crypto, STCP, normalizer, BBR (~30 файлов)
|
||
│ ├── routing_layer/ # Routing, BGP, conn_mgr, etcp_router, NAT detection (~20 файлов)
|
||
│ ├── chat/ # P2P чат, db_sync, merkle_sync, member_sync (17 файлов)
|
||
│ ├── proxy/ # SOCKS5, TCP/UDP/ICMP прокси (10 файлов)
|
||
│ ├── lwip_tcp/ # Встроенный lwIP TCP стек (7 файлов)
|
||
│ ├── media_delivery/ # Доставка медиафайлов (6 файлов)
|
||
│ ├── media_async/ # Асинхронный движок медиа (2 файла)
|
||
│ └── *.c/h # Корневые модули: utun, config, TUN, firewall, NAT, NTP, control (~14 файлов)
|
||
├── tests/ # ~70 тестов, 64 в check_PROGRAMS
|
||
├── 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)
|
||
│ ├── tdesktop-dev/ # Референс: Telegram Desktop (только для изучения)
|
||
│ ├── proxy/ # UDP прокси для тестов
|
||
│ └── bping/ # BPing (bandwidth ping)
|
||
├── tinycrypt/ # TinyCrypt crypto library (external)
|
||
├── net_emulator/ # Network emulator (delays, loss, reordering)
|
||
└── c2/ # Test instance 2 (конфиг и бинарник для тестов)
|
||
```
|
||
|
||
### File Overview
|
||
|
||
**Core (src/)**
|
||
- `utun.c` - Main program entry point, CLI parsing, daemon mode
|
||
- `utun_instance.c/h` - Root instance lifecycle, config loading, all submodule init
|
||
- `tun_if.c/h` - TUN interface API (init/write/close, cross-platform)
|
||
- `tun_linux.c` `tun_freebsd.c` `tun_windows.c` - Platform-specific TUN implementations
|
||
- `tun_route.c/h` - TUN routing table sync
|
||
- `config_parser.c/h` - INI-style config file parsing
|
||
- `config_updater.c/h` - Config file modification utilities
|
||
- `control_server.c/h` - Control/monitoring server (etcpmon backend API)
|
||
- `firewall.c/h` - Firewall rules (per-interface filtering)
|
||
- `eim_nat.c/h` - Endpoint-Independent Mapping NAT engine
|
||
- `nat_transport.c/h` - NAT transport layer (packet relay)
|
||
- `ntp_time.c/h` - NTP time synchronization
|
||
- `ntp_node_time.c/h` - Inter-node time synchronization
|
||
|
||
**Transport Layer (src/transport_layer/)**
|
||
- `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_loadbalancer.c/h` - Multi-link load balancing with traffic shaper
|
||
- `etcp_debug.c/h` - ETCP packet dump/formatting
|
||
- `etcp_dump.c/h` - ETCP дамп/декодирование пакетов
|
||
- `etcp_bbr.c/h` - BBR congestion control for ETCP
|
||
- `etcp_connect.c/h` - ETCP outbound connections
|
||
- `pkt_normalizer.c/h` - Packet fragmentation/reassembly (packer/unpacker)
|
||
- `packet_dump.c/h` - Packet hex dump utility
|
||
- `dummynet.c/h` - Network emulator integrated into utun (for testing)
|
||
- `secure_channel.c/h` - AES-CCM encryption with X25519 key exchange, pubkey obfuscation
|
||
- `crc32.c/h` - CRC32 checksums
|
||
- `stcp.c/h` - STCP протокол (Secure TCP)
|
||
- `stcp_server.c/h` - STCP сервер
|
||
- `stcp_client.c/h` - STCP клиент
|
||
- `stcp_link.c/h` - STCP линк-уровень
|
||
- `node_conn_direct.c/h` - Direct config-based connections
|
||
- `socket_monitor.c/h` - Socket state monitoring
|
||
|
||
**BBR (src/transport_layer/BBR/)**
|
||
- `bbr_v3.c` - BBR congestion control algorithm v3
|
||
|
||
**Routing Layer (src/routing_layer/)**
|
||
- `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_connectivity.c/h` - Route connectivity checks
|
||
- `topo_group.c/h` - BGP-like route exchange between nodes (NODEINFO/WITHDRAW, изолированные группы UTUN/CHAT)
|
||
- `topo_group_connect.c/h` - Авто-подключение к узлам CHAT-группы (3 фазы, бесконечный цикл)
|
||
- `topo_group_invite.c/h` - Invite/join канала через прямое ncd-подключение (INVITE_INFO_REQ/RESP)
|
||
- `topo_node.c/h` - Node management (модель узла: TOPO_NODE/TOPO_GROUP_NODE, сериализация, node_registry)
|
||
- `topo_node_sqlite.c/h` - SQLite persistence for nodes
|
||
- `topo_recovery.c/h` - Восстановление каскадно отвалившихся узлов после разрыва соединения
|
||
- `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
|
||
|
||
**Chat (src/chat/)** — децентрализованный P2P чат: сообщения и участники автоматически синхронизируются между всеми узлами канала без центрального сервера.
|
||
- `chat_core.c/h` - Главный модуль чата. Единственная точка входа из GUI: принять сообщение, создать канал, изменить настройку. Управляет БД и жизненным циклом всех chat-модулей
|
||
- `chat_core_priv.h` - Внутренний API для частей chat_core: общий контекст и утилиты БД. Снаружи не используется
|
||
- `chat_sync.c/h` - Связывает чат с ETCP-сетью: отслеживает появление/разрыв соединений, обновляет онлайн-статус узлов, запускает синхронизацию участников каналов, обрабатывает приглашения
|
||
- `chat_event.c/h` - Доставка событий из ядра чата в GUI. Единый механизм: любой модуль отправляет событие (новое сообщение, смена участников, статус), GUI получает через один обработчик
|
||
- `chat_setting.c/h` - Настройки чата: проверяет корректность значений, хранит текущие. Используется и headless-парсером конфига, и GUI. Не зависит от других модулей
|
||
- `db_sync.c/h` - Автоматическая репликация данных между подключёнными узлами. Запись на одном узле — появляется у всех остальных. Криптоподписи и цепочка хешей защищают от подделок
|
||
- `member_sync.c/h` - Синхронизация участников каналов поверх merkle_sync. Два подписанных блока (мембер/владелец), по-блочное сравнение версий, верификация подписей. Удаление — только битая запись
|
||
- `merkle_sync.c/h` - Универсальный движок синхронизации на Merkle-деревьях (5 уровней × 32 бакета, SHA256). Пиры обмениваются хешами и передают только различия; per-session out-очередь с backpressure. Не привязан к конкретному типу данных (коллбэки `data_ops`)
|
||
- `chat_profile.c` - Собственный профиль: имя узла, сетевые адреса, сохранение UI-состояния (часть chat_core)
|
||
- `chat_channel.c` - Создание и настройка каналов: готовит таблицы в БД, генерирует криптоключи, запускает подключение ко всем участникам (часть chat_core)
|
||
- `chat_msg.c` - Отправка и приём сообщений: запись в локальную БД, автоматическая рассылка всем участникам канала (часть chat_core)
|
||
- `chat_status.c` - Сбор диагностики: текущее время, активные соединения, типы NAT. Отправляется в GUI (часть chat_core)
|
||
|
||
**Прокси (src/proxy/)**
|
||
- `socks_proxy.c/h` - SOCKS5 прокси
|
||
- `udp_proxy.c/h` - UDP прокси
|
||
- `icmp_proxy.c/h` - ICMP прокси
|
||
- `tcp_proxy_server.c/h` - TCP прокси (серверная сторона)
|
||
- `tcp_proxy_client.c/h` - TCP прокси (клиентская сторона)
|
||
|
||
**lwIP TCP (src/lwip_tcp/)**
|
||
- `lwip_tcp.c/h` - lwIP TCP стек
|
||
- `lwip_tcp_out.c` / `lwip_tcp_in.c` - Исходящий/входящий трафик
|
||
- `lwip_pbuf.c/h` - Пакетные буферы lwIP
|
||
- `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 Async (src/media_async/)**
|
||
- `media_async.c/h` - Асинхронный движок (thread-per-task для crypto/file операций)
|
||
|
||
**Libraries (lib/)**
|
||
- `u_async.c/h` - Async event loop (epoll/poll/select, timers via timeout_heap)
|
||
- `ll_queue.c/h` - Lock-free linked list queue with callbacks, hash index, threshold waiter
|
||
- `memory_pool.c/h` - Fast object pool allocator (pre-allocated blocks)
|
||
- `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
|
||
- `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)
|
||
- `sqlite3.c/h` - SQLite3 amalgamation (embedded database)
|
||
- `opus_codec.c/h` - Opus audio codec wrapper
|
||
- `audio_compressor.c/h` - Audio dynamic range compressor
|
||
- `json_flat.c/h` - Flat JSON parser
|
||
- `wintun.h` - Wintun API header for Windows TUN driver
|
||
|
||
**Memory Pools in UTUN_INSTANCE:**
|
||
- `data_pool` — для данных пакетов (payload), используется input_queue/output_queue фрагментами
|
||
- `pkt_pool` — для struct ETCP_DGRAM (сетевые пакеты на отправку/приём)
|
||
- `ack_pool` — для struct ACK_PACKET (подтверждения приёма)
|
||
|
||
### Key Components
|
||
- **UASYNC:** One per thread. Async event loop (epoll/poll), timers via timeout_heap
|
||
- **LL_QUEUE:** Lock-free queue with auto-callback, hash index lookup, threshold waiter
|
||
- **Memory Pool:** Fast allocation for hot-path objects (packets, inflight entries, fragments)
|
||
- **ETCP:** TCP-like reliable protocol with encryption, multi-link, load balancing
|
||
- **Secure Channel:** AES-CCM + X25519 key exchange, nonce-based encryption, pubkey obfuscation
|
||
|
||
## Queue Usage Rules
|
||
|
||
## Работа с очередями. Важно!
|
||
С очередью следуею работать придерживаясь следующих правил:
|
||
- при сетевом обмене не забиваем очередь. всегда используем Пороговое ожидание (backpressure).
|
||
- для работы с очередью полностью загрузи ll_queue.h и пойми как работает.
|
||
|
||
### Запись в очередь
|
||
- Очереди забивать нельзя. Добавляй следующий элемент только когда очередь стала пустой.
|
||
- Порог задаётся через `queue_set_threshold(q, max_packets, max_bytes)`.
|
||
- Используй `queue_waiter_wait` для ожидания освобождения очереди до заданного порога.
|
||
|
||
### Чтение из очереди
|
||
- Используй `queue_set_callback`: при вызове callback обработай один или несколько элементов, потом вызови `queue_resume_callback`.
|
||
- Внутри коллбэка ОБЯЗАТЕЛЬНО: `queue_data_get(q)` → обработать элемент → `queue_resume_callback(q)`
|
||
- Без вызова `queue_resume_callback` очередь навсегда застрянет
|
||
|
||
### Поиск
|
||
- `queue_data_put_with_index(q, entry)` — добавляет с индексом для быстрого поиска (offset/size заданы при queue_new)
|
||
- `queue_find_data_by_index(q, key)` — поиск по индексу через хеш-таблицу (размер ключа из q->index_size)
|
||
|
||
## u_async Rules
|
||
- Нельзя использовать в одном потоке несколько u_async. Один поток = всегда 1 uasync instance
|
||
- Нельзя использовать sleep/usleep если есть uasync. Нужно использовать `uasync_set_timeout`.
|
||
- Таймеры: `uasync_set_timeout(ua, timeout_tb, arg, callback, name)` — timebase units (0.1ms)
|
||
Возвращает `void*` handle, отмена: `uasync_cancel_timeout(ua, handle)`.
|
||
|
||
## Config Rules
|
||
- В серверном конфиге только собственные ключи и нет секций `[client]`
|
||
- В клиентском конфиге есть собственные ключи и pubkey каждого сервера в секции `[client]`
|
||
- Chat-настройки хранятся в секции `[chat]`. Парсер вызывает `chat_setting_set(key, value)` для каждого ключа — неизвестные ключи вызывают ошибку. Пример:
|
||
```ini
|
||
[chat]
|
||
storage_autoload=1
|
||
storage_autoload_maxsize_mb=10
|
||
storage_maxsize_gb=1
|
||
opus_codec_preset=1
|
||
compressor_enabled=0
|
||
compressor_max_gain_db=25
|
||
compressor_rise_rate=10
|
||
media_download_max_peers=3
|
||
```
|
||
|
||
## Bugs Debugging Protocol
|
||
Всегда когда начинаешь диагностику ознакомься со скиллом (используй skills)
|
||
Диагностика и поиск ошибок - это в первую очередь продумывание отладочных механизмов которые покажут понятную картину и точное представление об ошибке. Рассуждать надо как диагностикой добиться точной картины. И как приавльнее добавить диагностику чтобы не спамила лишними сообщениями и была понятной, логичной и информативной.
|
||
|
||
Важное правило отладки: вся отладка сводится к тому чтобы сделать удобные логи которые наглядно показывают поведение и проблемы. без лишнего мусора, компактно и по существу. очень желательно с деталями которые сильно повышают качество отладки.
|
||
при отладке нельзя: гадать и долго пытаться разбирать код пытаяясь найти причину. гораздо надёжнее с помощью логов понято точное поведение.
|
||
Если логов много - записывай в файл и потом анализируй.
|
||
Если видишь спам-логи - подумай как их выборочно отключить чтобы не мешали.
|
||
|
||
Для отладки добавляй в DEBUG_CATEGORY_DEBUG диагностические сообщения где надо. И включи эту категорию в настройках. Убирай только после проверки (путём запуска) когда все ошибки устранены.
|
||
сообщение выводится по или - либо debug_set_level(DEBUG_LEVEL_TRACE) - выводится ВСЁ независимо от настроек по категориям. Тоесть берется max(global level, category lavel)
|
||
|
||
Твой бич - ты постоянно гадаешь и анализируешь код. Что приводит к снежному кобу ошибок и неверных гипотез. 10 раз повторяю - только логи логи логи и никакого гадания. Лоооги!!! правильные логи покажут всё с предельной точностью. Вся суть отладки - информативные логи
|
||
И смотри логи. не задавливай их grep-ом. лучше больше. единственное с чем борись - это бесполезные спам логи.
|
||
Проблемы часто не там где их ищешь. Поэтому анализируй более полно логи и приглядывайся к любым подозрительным местам. А не одну строку выгребай грепом безуспешно по 10му кругу когда реальная проблема в другом месте.
|
||
Ты часто как слепой котёнок не смотришь по сторонам, пытаясь найти проблему где сам придумал и логично что ничего не получается.
|
||
Правльный подход: оптимиировать логи под конкретный баг. Убрать спам и вывести всё что относится к отлаживаемому механизму со всеми нужными подробностями. Прогнать и внимательно проанализировать ВЕСЬ это лог. Если он слишком большой - думай как выводить только нужное не в ущерб информативности.
|
||
|
||
Но полезные смотри всегда, и всегда оставляй логи которые выводятся нечасто.
|
||
Частые логи - это трафик которые >100 раз повторяются. Но которые мало раз обязательно оставлять и выводить.
|
||
можешь в тесте включить логи в нужный интервал чтобы не спамить. debug_set_level(DEBUG_LEVEL_TRACE) и выключить debug_set_level(DEBUG_LEVEL_NONE)
|
||
Если видишь проблему и ее решение неочевидно то выстраивай диагностику вокруг неё пока не будет очевидно где и что происходит не так. Это базовое и обязательное требование к отладке.
|
||
Подробные логи ты должен выводить не обрезая всегда и анализировать. Если лог большой - выведи в файл и анализируй файл.
|
||
Рассуждение должно быть примерно таким:
|
||
- данные повреждаются при отправке.
|
||
- где и почему непонятно. надо продумать ключевые точки где получим максимум полезной информации и не было большого объёма вывода лога.
|
||
- где лучше? каждый пакет логировать - много, но будет предельно точная картина
|
||
- Еще хорошо бы время - так мы заодно сможем найти проблемы с производительностью, найти проблемные места застревания кода.
|
||
- Но это большой объём. Можно ли без него? можно но это будет малоэффективно и хороших альтернатив пока не видно.
|
||
- Значит логируем весь трафик, а заодно включим полную трассировку функций.
|
||
- Запустили. Записали весь процесс в файл. Теперь можно анализировать. Давай сперва посчитаю количество строк с дампом: ... 50000.
|
||
- давай сделаю простой скрипт который дамп прочитает и сохранит в файл. И сверю с оригинальным файлом
|
||
- Давай заодно возьму произвольный фрагмент лога и изучу еа предмет явных проблем. Особенно инициализацию и освобождение ресурсов.
|
||
Сколько времени занимает, нет ли заклиниваний, нет ли ошибок или странностей
|
||
|
||
### Диагностические сообщения (DEBUG_WARN DEBUG_ERROR)
|
||
Сообщения должны говорить что случилось и с какими деталями.
|
||
Обязательно выводить подробные собощения об ошибках (даже если нужен небольшой дополнительный код чтобы эти детали сформировать и привести в читаемый вид).
|
||
Полезны подробности об инициализации-завершении которые помогают понять внутренние состояния
|
||
Диагностические сообщения - важный момент. надо про диагностику помнить.
|
||
Для хорошей диагностики надо проанализировать как архитектор - какие есть нюансы в архитектуре и что полезно будет видеть в дебаг выводе чтобы понять полную картину происходящего.
|
||
|
||
### Запрещено (опыт 2026-07-31 — потеря всех некоммиченных изменений):
|
||
- `git checkout -- <wildcard>` / `git checkout -- src/` — безвозвратный откат ВСЕХ файлов
|
||
- `sed` для массовых правок исходников — замены разъезжаются, ломают код, часы на восстановление
|
||
- Пакетные замены через Bash в 10+ файлах одновременно
|
||
- Повторять эти ошибки: потеря + попытка отката git checkout = двойная потеря
|
||
|
||
### Правила безопасного рефакторинга:
|
||
1. Правки ТОЛЬКО через Edit tool — одна точечная замена с контекстом
|
||
2. После каждого файла → `git add <file>`
|
||
3. Каждые 2-3 файла → `git commit -m "..."` (не дожидаясь сборки)
|
||
4. Никакого `sed` / `awk` / `perl -i` для правки исходников
|
||
5. Перед откатом → сначала коммит всего, потом `git revert` конкретного коммита
|
||
|
||
### Прочие правила:
|
||
- sed для редактирования исходников - запрещено
|
||
- Проверяй на дублирование кода - не сделано ли это уже в другом месте
|
||
- Не делай функций-посредников: лучше сразу вызывать target функцию без вложенных вызовов
|
||
- Нельзя ничего восстанавливать из репозитория не спрашивая
|
||
- Для отладки не printf а DEBUG_*
|
||
- Запрещено прямое включение arpa/inet.h, sys/time.h, unistd.h — использовать ../lib/platform_compat.h + socket_compat.h
|
||
- Перед сборкой всегда make clean
|
||
- Все лишнее что менял при отладке - строго вернуть назад в состояние до вмешательства
|
||
|
||
## Написание кода
|
||
- Строго обязательно наличие ERROR сообщений во всех ошибочных ветвях алгоритма
|
||
- Обязательно наличие диагностических сообщений в ветках инициализации-очистки, с информацией которая позволяет оценить наиболее полно внетренние состояния на момент печати сообщения. Например выявить неправильные состояния, неинициализированные поля итд
|
||
- Обязательно наличие подробной диагностики в функциях кода которые не сильно спамят (не часто вызываются).
|
||
- Для каждого отладочного вывода подумай какая из доступной информация будет полезна чтобы можно было наиболее завершенно оценить состояние алгоритма и состояний влияющих на алгоритм.
|
||
|
||
|
||
## chatgui (GUI Chat Client)
|
||
|
||
Chatgui — десктопный GUI-чат на Qt 6 (Qt 5 fallback), отдельный проект внутри репозитория. Не связан с autotools-сборкой utun.
|
||
|
||
В chat gui интегрированы библиотеки utun. Чат и библиотеки работают в разных потоках. Поэтому нужно использовать семафоры, сокеты или другие механизмы синхронизации (uasync_post, uasync_memsync, uasync_get_wakeup_fd)
|
||
|
||
База данных sqlite в chatgui: можно писать (update) из потока utun / instance. можно только читать из gui потока.
|
||
|
||
### Технологии
|
||
- **Язык:** C++20
|
||
- **Фреймворк:** Qt 6 (предпочитаемый) или Qt 5.15+ (Widgets + Network)
|
||
- **Сборка:** CMake 3.16+
|
||
- **БД:** SQLite3 (WAL mode, встроенный `db/sqlite3.c` amalgamation)
|
||
- **Анимации:** rlottie (C API) + zlib (gzip-декомпрессия TGS)
|
||
|
||
### Сборка
|
||
```bash
|
||
# Установка зависимостей
|
||
sudo apt install librlottie-dev zlib1g-dev qt6-base-dev
|
||
# или qtbase5-dev для Qt 5 fallback
|
||
|
||
# Сборка
|
||
cd tools/chatgui && mkdir -p build && cd build
|
||
cmake .. && make -j4
|
||
./chatgui
|
||
```
|
||
|
||
### Конфиг и логи чатгуи
|
||
- **Конфиг:** `tools/chatgui/build/chatgui.cfg` (в `.gitignore`, содержит приватные ключи)
|
||
- Секция `[gui]`: `debug_file`, `debug_level`, `debug_categories=cat=level,...`
|
||
- Секция `[control]`: `ip`, `port` для подключения etcpmon
|
||
- Секция `[ntp]`: синхронизация времени
|
||
- **Лог:** `tools/chatgui/build/chatgui.log` (путь задаётся в конфиге `debug_file`)
|
||
- **БД чата:** `tools/chatgui/build/chat_data/` (SQLite, путь из `db_path` в конфиге)
|
||
|
||
### Структура файлов (src/)
|
||
|
||
| Файл | Назначение |
|
||
|------|-----------|
|
||
| `main.cpp` | Точка входа, инициализация QApplication |
|
||
| `mainwindow.h/cpp` | Главное окно, QSplitter (ChannelList \| MessageList \| AccountList), трей |
|
||
| `chatview.h/cpp` | QListView с фоновым изображением, hover-сигнал, drag-to-select |
|
||
| `messagelist.h/cpp` | QStandardItemModel, stub-данные, инициализация анимаций, hover→activate |
|
||
| `messagedelegate.h/cpp` | QStyledItemDelegate: бабблы, текст, цитаты, реакции, оверлей анимаций |
|
||
| `emoji.h/cpp` | EmojiData/EmojiCategory/EmojiType, 4 категории, `g_animatedEmojiMap` |
|
||
| `emojipanel.h/cpp` | Эмодзи-пикер: QTabWidget + QGridLayout, EmojiButton с hover-анимацией |
|
||
| `emojitabbar.h/cpp` | Кастомный QTabBar для эмодзи-панели |
|
||
| `inputbar.h/cpp` | Поле ввода (QTextEdit), вставка эмодзи, отправка по Enter |
|
||
| `lottieicon.h/cpp` | Загрузка TGS (gzip→zlib), рендер кадров через `lottie_animation_render` |
|
||
| `animtimer.h/cpp` | Синглтон-таймер 30fps, refcount activate/deactivate, сигнал ticked |
|
||
| `channellist.h/cpp` `channeldelegate.h/cpp` | Список каналов с аватарами и превью |
|
||
| `accountlist.h/cpp` | Список аккаунтов/пользователей |
|
||
| `joindialog.h/cpp` | Диалог присоединения к группе/каналу |
|
||
| `invitedialog.h/cpp` | Диалог приглашения пользователя |
|
||
| `invite_link.h/cpp` | Логика invite-ссылок |
|
||
| `settingsdialog.h/cpp` | Окно настроек |
|
||
| `creategroupdialog.h/cpp` | Диалог создания группы |
|
||
| `networksettingspage.h/cpp` | Страница сетевых настроек |
|
||
| `qrcode_utils.h/cpp` | Утилиты для QR-кодов |
|
||
| `debug_ui.h` | Отладочный UI |
|
||
|
||
### Другие поддиректории
|
||
- `db/` — SQLite3 amalgamation (`sqlite3.c/h`), `db_manager.h/cpp` (схема: nodes, node_addresses, channels, msg_<channel>, peers_<channel>, local_identity, accounts, ui_state)
|
||
- `transport/` — интеграция с uTun: `gui_bridge.h/gui_bridge_impl.cpp` (Qt signal-based обмен), `chat_core.h/c` (управление), `chat_sync.h/c` (синхронизация), `db_sync_stub.c` (заглушка БД), `node_config.h/cpp`, `config_updater.h/cpp`, `utun_node.h/cpp`, `topo_node_sqlite.h/c`
|
||
- `resources/` — `bg.jpg`, `chatgui.qrc` (встраивает 5 TGS в бинарник), `animations/*.tgs`
|
||
|
||
### Система анимированных эмодзи
|
||
|
||
#### Формат
|
||
TGS = gzip-сжатый Lottie JSON. Холст 512×512, 60fps, 90–180 кадров. Декомпрессия через zlib (`inflateInit2` с `16+MAX_WBITS`).
|
||
|
||
#### Ключевые компоненты
|
||
```
|
||
LottieIcon — загрузка TGS, рендер кадров (rlottie C API)
|
||
↓
|
||
AnimTimer (синглтон) — таймер 33ms, refcount activate/deactivate
|
||
├── в сообщениях: → MessageDelegate::paint()
|
||
│ drawAnimatedEmojiOverlay() — QTextLayout → позиции эмодзи → drawImage()
|
||
│ drawStatusBar() — анимированные реакции вместо drawText()
|
||
│
|
||
├── в панели: → EmojiButton (наследует QPushButton)
|
||
│ per-button QTimer, enterEvent/leaveEvent, собственный paintEvent
|
||
│
|
||
└── активация: → ChatView::hoveredIndexChanged
|
||
MessageList проверяет текст/реакции сообщения на g_animatedEmojiMap
|
||
есть анимация → AnimTimer::activate() / нет → deactivate()
|
||
```
|
||
|
||
#### Инициализация
|
||
1. `MessageList` конструктор: загружает все `EmojiType::Animation` из `builtinEmojiSet()`, создаёт `LottieIcon`, регистрирует в `AnimTimer`
|
||
2. **Должно быть ДО создания `EmojiPanel`** — иначе `EmojiButton` получит `nullptr`
|
||
3. `g_animatedEmojiMap` заполняется при старте (Unicode → animPath)
|
||
|
||
#### Текущий маппинг (5 эмодзи)
|
||
| Unicode | Shortcode | TGS-файл |
|
||
|---------|-----------|----------|
|
||
| ✨ `U+2728` | `:sparkles:` | `sparkles_emoji.tgs` |
|
||
| 🏳️ `U+1F3F3` | `:flag:` | `white_flag_emoji.tgs` |
|
||
| 👋 `U+1F44B` | `:wave:` | `greeting.tgs` |
|
||
| ✋ `U+270B` | `:raised_hand:` | `stop.tgs` |
|
||
| 🤖 `U+1F916` | `:robot:` | `robot.tgs` |
|
||
|
||
#### Рендеринг в сообщениях
|
||
- Текст рисуется через `QPainter::drawText(Qt::TextWordWrap)`
|
||
- `drawAnimatedEmojiOverlay()` повторяет layout через `QTextLayout` с теми же параметрами
|
||
- Для каждого эмодзи из `g_animatedEmojiMap` находит пиксельную позицию через `QTextLine::cursorToX()`
|
||
- Рендерит кадр через `LottieIcon::renderFrame(currentFrame(), size)` и рисует `drawImage()`
|
||
- Размер эмодзи масштабирован ×1.3 относительно высоты строки
|
||
- Аналогично для реакций в `drawStatusBar()`
|
||
|
||
#### Drag-to-select
|
||
- Одиночный клик снимает выделение (если было), не стартует новое
|
||
- Движение ≥5px от точки нажатия стартует выделение (`m_selStart`/`m_selEnd`)
|
||
- Ctrl+C копирует: для одного сообщения — выделенный фрагмент, для нескольких — `[time] author: text`
|
||
|
||
### Важные правила chatgui
|
||
- `CMAKE_AUTORCC ON` обязателен для компиляции `.qrc`-ресурсов
|
||
- Иконки должны быть зарегистрированы в `AnimTimer` ДО создания `EmojiPanel`
|
||
- `EmojiButton` НЕ использует `Q_OBJECT` (в анонимном namespace) — таймер через лямбду, каст через `dynamic_cast`
|
||
- Координаты `indexAt()`: `viewport()->mapFrom(this, event->pos())`
|
||
|
||
---
|
||
|
||
## tdesktop-dev (референсный проект Telegram Desktop)
|
||
|
||
**Расположение:** `tools/tdesktop-dev/` — полный клон [Telegram Desktop](https://github.com/telegramdesktop/tdesktop).
|
||
|
||
**Статус:** референс. Не собирается, не модифицируется, в `.gitignore`.
|
||
|
||
**Назначение:**
|
||
- Источник TGS-анимаций (`Telegram/Resources/animations/` — 99+ файлов)
|
||
- Образец использования rlottie/lib_lottie API
|
||
- Архитектурный референс для GUI-компонентов
|
||
|
||
**Правила:**
|
||
- НЕ модифицировать файлы внутри `tdesktop-dev/`
|
||
- НЕ коммитить изменения из `tdesktop-dev/`
|
||
- НЕ ссылаться в сборке на код/библиотеки из tdesktop-dev
|
||
- Можно копировать TGS-файлы в `tools/chatgui/resources/animations/`
|
||
|
||
**Полезные поддиректории:**
|
||
- `Telegram/Resources/animations/` — TGS-анимации (dice, reactions, emoji, UI)
|
||
- `Telegram/lib_lottie/` — C++ обёртка над rlottie (SinglePlayer, MultiPlayer, Icon, FrameGenerator)
|
||
- `Telegram/ThirdParty/rlottie/` — submodule rlottie (обычно не выкачан)
|
||
|
||
**rlottie C API (ключевые функции):**
|
||
```c
|
||
Lottie_Animation *lottie_animation_from_data(const char *data, const char *key, const char *resource_path);
|
||
void lottie_animation_get_size(const Lottie_Animation *anim, size_t *w, size_t *h);
|
||
size_t lottie_animation_get_totalframe(const Lottie_Animation *anim);
|
||
double lottie_animation_get_framerate(const Lottie_Animation *anim);
|
||
void lottie_animation_render(Lottie_Animation *anim, size_t frame, uint32_t *buf, size_t w, size_t h, size_t stride);
|
||
void lottie_animation_destroy(Lottie_Animation *anim);
|
||
```
|
||
|
||
---
|
||
|
||
## Key Documentation Files
|
||
- `/doc/etcp_protocol.txt` - ETCP протокол (формат кодограмм, ACK, handshake, keepalive)
|
||
- `/doc/etcp_arch.md` - ETCP архитектура
|
||
- `/doc/etcp_config.txt` - Конфигурация ETCP
|
||
- `/doc/etcp_router_arch.md` - ETCP роутер архитектура
|
||
- `/doc/route_p2pconn.txt` - Route peer-to-peer соединения
|
||
- `/src/route_bgp.txt` - BGP обмен маршрутами (дизайн-документ)
|
||
|
||
## chatgui-android (Android P2P Chat)
|
||
|
||
**Расположение:** `tools/chatgui-android/`
|
||
|
||
Android-версия чатгуи — P2P чат на STCP (TCP), UI на Jetpack Compose (Kotlin).
|
||
C-ядро: `libutun_lite` (выборочная компиляция нужных .c из `lib/` и `src/`).
|
||
Сборка: CMake (headless, Linux) + Gradle/NDK (Android APK).
|
||
- 'fw' - собрать и обновить chatgui-android на телефоне (clean + сборка + install)
|
||
|
||
**Подробная инструкция:** `tools/chatgui-android/AGENTS.md`
|
||
**Chat-модули:** все файлы из `src/chat/` (описаны выше в секции «Chat») компилируются в `libutun_lite`.
|
||
|
||
## Runtime
|
||
- Запуск utun от root (для tun): `/home/vnc1/proj/utun3/utun_start.sh`
|
||
- Стоп utun: `sudo /home/vnc1/proj/utun3/utun_stop1.sh`
|
||
- Логи: `utun.log` (stdout), `utun_err.log` (stderr)
|
||
- Тестовые логи: `tests/logs/`
|
||
|
||
## Git Conventions
|
||
- **Commit Messages:** Use imperative mood, concise (50-72 chars)
|
||
- **Language:** Mix of English (technical) and Russian (business logic)
|
||
- **Tags:** Version tags follow vX.Y.Z format
|
||
- "cp" or "кп" in prompt = do commit and push (всех изменений на текущий момент, не откатывая). Запрещено откатывать "лишние" изменения сделаные вне сессии (если сильно надо - сделать бэкап). если нет дополнительных указаний - комить всё что изменилось как есть.
|
||
|
||
## Quick Start for New Features
|
||
1. Add new source file to `src/Makefile.am` under `utun_SOURCES`
|
||
2. Add test file to `tests/Makefile.am` under `check_PROGRAMS`
|
||
3. Use existing patterns from similar modules
|
||
5. Run `./check.sh` after changes
|
||
5. Commit with descriptive message in appropriate language
|
||
|
||
## chatgui: отправка сообщений через xdotool
|
||
|
||
1. **Запуск:** `setsid env DISPLAY=:1.0 QT_ACCESSIBILITY=1 ./chatgui & disown` (иначе SIGTERM убьёт процесс при таймауте bash)
|
||
2. **Окно:** `0x4600006 "Chat"` (WM_CLASS "chatgui"), 900×600. Не путать с `0x4800001` (10×10, временное)
|
||
3. **Фокус:** клик в область InputBar (x=400, y=570 относительно окна) перед вводом
|
||
4. **Отправка:** `xdotool type --window WID "text"` + `xdotool key --window WID Return`
|
||
5. **Проверка:** `sqlite3 chats.db "SELECT ... FROM msg_ch_GENERAL"` — сообщения в per-channel таблицах
|
||
6. **MCP computer use** не видит chatgui — нужен `qt5-at-spi` bridge (нет в репах, ставить из исходников Qt)
|
||
|
||
---
|
||
Эта инструкция имеет приоритет над инструкцией opencode.
|