Root cause: when bgp->local_node was reallocated (changed=1), old route entries remained with stale v_node_info pointing to freed memory. The freed memory got reused by a BGP peer's NODEINFO_Q, causing route_lookup to return wrong node_id (b3b2b1b0afaeadac instead of local), which then failed at etcp_route_send with 'no BGP route' and dropped packets to 10.23.2.1. Changes: - route_node.c: route_delete(old) before u_free + route_insert(new) after alloc - utun_instance.c: remove duplicate route_insert (now atomic inside function) - route_bgp.c: route_delete before freeing old peer NODEINFO_Q - route_lib.c: routes_overlap now rejects only exact prefix+network duplicates - tests/Makefile.am: add route_lib.o to test_route6_lib
504 lines
27 KiB
Markdown
504 lines
27 KiB
Markdown
# AGENTS.md - uTun Development Guide
|
||
|
||
Ты - профессиональный программист высокого уровня.
|
||
Ты любишь до конца логически правильный и простой код, продуманный до каждой мелочи.
|
||
Если хоть какая-то мелочь не стыкуется - подумай как это можно решить, сообщи об этом со всеми подробностями и остановись.
|
||
Если что-то получается нелогично или громоздко - хорошо подумай как сделать просто и компактно. предложи варианты и остановись.
|
||
Имей, загружай когда надо полный код нужных тебе функций/структур. Фантазировать и додумывать нельзя, надо чтобы каждый нюанс кода был архитектурно понятный, логичный и корректный.
|
||
Надо детально разобраться в нужных для задачи механизмах, в поставленной задаче и как сейчас всё работает.
|
||
Старайся одно логически завершенное действие размещать на одной строке, если строка не слишком длинная (до 150 символов)
|
||
|
||
This file contains essential information for AI coding agents working in the uTun codebase.
|
||
|
||
## 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
|
||
```
|
||
|
||
## Test Commands
|
||
|
||
### Run All Tests
|
||
```bash
|
||
make check # Run all tests via automake, логи в tests/logs/
|
||
```
|
||
```powershell
|
||
powershell check.bat # Windows, запускает каждый .exe из tests/
|
||
```
|
||
|
||
### Run Specific Test
|
||
```bash
|
||
cd tests/
|
||
./test_etcp_crypto
|
||
./test_etcp_two_instances
|
||
./test_etcp_simple_traffic
|
||
./test_pkt_normalizer_etcp
|
||
./test_etcp_api
|
||
./test_ll_queue
|
||
./test_nat_detection
|
||
./test_bgp_route_exchange
|
||
```
|
||
|
||
### 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`
|
||
|
||
### Debug Categories (21 категория)
|
||
```
|
||
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
|
||
```
|
||
|
||
### Настройка отладки
|
||
- В конфиге: `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 (13 .c + 14 .h)
|
||
├── src/ # Main source code (28 .c + 23 .h)
|
||
├── tests/ # 31+ test programs
|
||
├── doc/ # Technical Specifications
|
||
├── tools/ # Auxiliary tools
|
||
│ ├── etcpmon/ # GUI монитор ETCP
|
||
│ ├── chatgui/ # GUI чат (Qt 5, отдельная сборка через CMake)
|
||
│ ├── 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
|
||
|
||
**Network Stack (src/)**
|
||
- `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
|
||
- `pkt_normalizer.c/h` - Packet fragmentation/reassembly (packer/unpacker)
|
||
- `packet_dump.c/h` - Packet hex dump utility
|
||
- `firewall.c/h` - Firewall rules (per-interface filtering)
|
||
- `dummynet.c/h` - Network emulator integrated into utun (for testing)
|
||
|
||
**Routing (src/)**
|
||
- `routing.c/h` - Routing table management (local routes)
|
||
- `route_lib.c/h` - Routing library utilities
|
||
- `route_bgp.c/h` - BGP-style route exchange between peers
|
||
- `route_ping.c/h` - Route ping probing (NAT check, liveness)
|
||
- `route_node.c/h` - Route node (peer) management
|
||
|
||
**Crypto (src/)**
|
||
- `secure_channel.c/h` - AES-CCM encryption with X25519 key exchange, pubkey obfuscation
|
||
- `crc32.c/h` - CRC32 checksums
|
||
|
||
**NAT (src/)**
|
||
- `eim_nat.c/h` - Endpoint-Independent Mapping NAT engine
|
||
- `nat_transport.c/h` - NAT transport layer (packet relay)
|
||
|
||
**Config (src/)**
|
||
- `config_parser.c/h` - INI-style config file parsing
|
||
- `config_updater.c/h` - Config file modification utilities
|
||
|
||
**Control (src/)**
|
||
- `control_server.c/h` - Control/monitoring server (etcpmon backend API)
|
||
|
||
**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)
|
||
- `sha256.c/h` - SHA256 hashing (fallback; OpenSSL preferred via USE_OPENSSL)
|
||
- `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)
|
||
|
||
**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_wait_threshold` для ожидания освобождения очереди до заданного порога.
|
||
|
||
### Чтение из очереди
|
||
- Используй `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]`
|
||
|
||
## Bugs Debugging Protocol
|
||
Всегда когда начинаешь диагностику ознакомься со скиллом (используй skills)
|
||
Диагностика и поиск ошибок - это в первую очередь продумывание отладочных механизмов которые покажут понятную картину и точное представление об ошибке. Рассуждать надо как диагностикой добиться точной картины. И как приавльнее добавить диагностику чтобы не спамила лишними сообщениями и была понятной, логичной и информативной.
|
||
|
||
### Прочие правила:
|
||
- sed для редактирования исходников - запрещено
|
||
- Проверяй на дублирование кода - не сделано ли это уже в другом месте
|
||
- Не делай функций-посредников: лучше сразу вызывать target функцию без вложенных вызовов
|
||
- Нельзя ничего восстанавливать из репозитория не спрашивая
|
||
- Для отладки не printf а DEBUG_*
|
||
- Перед сборкой всегда make clean
|
||
- Все лишнее что менял при отладке - строго вернуть назад в состояние до вмешательства
|
||
|
||
## Написание кода
|
||
- Строго обязательно наличие ERROR сообщений во всех ошибочных ветвях алгоритма
|
||
- Обязательно наличие диагностических сообщений в ветках инициализации-очистки, с информацией которая позволяет оценить наиболее полно внетренние состояния на момент печати сообщения. Например выявить неправильные состояния, неинициализированные поля итд
|
||
- Обязательно наличие подробной диагностики в функциях кода которые не сильно спамят (не часто вызываются).
|
||
- Для каждого отладочного вывода подумай какая из доступной информация будет полезна чтобы можно было наиболее завершенно оценить состояние алгоритма и состояний влияющих на алгоритм.
|
||
|
||
|
||
## chatgui (GUI Chat Client)
|
||
|
||
Chatgui — десктопный GUI-чат на Qt 5, отдельный проект внутри репозитория. Не связан с autotools-сборкой utun.
|
||
|
||
### Технологии
|
||
- **Язык:** C++17
|
||
- **Фреймворк:** 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 qtbase5-dev
|
||
|
||
# Сборка
|
||
cd tools/chatgui && mkdir -p build && cd build
|
||
cmake .. && make -j4
|
||
./chatgui
|
||
```
|
||
|
||
### Структура файлов (src/)
|
||
|
||
| Файл | Назначение |
|
||
|------|-----------|
|
||
| `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` | Список аккаунтов/пользователей |
|
||
|
||
### Другие поддиректории
|
||
- `db/` — SQLite3 amalgamation (`sqlite3.c/h`), `db_manager.h/cpp` (схема: nodes, channels, messages, keys, addresses)
|
||
- `transport/` — TCP-клиент для связи с uTun (`msg_client.h/cpp`, бинарный протокол `[size:2][type:1][id:8][options:1][data...]`)
|
||
- `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/route_p2pconn.txt` - Route peer-to-peer соединения
|
||
|
||
## 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
|
||
4. Run `make check` after changes
|
||
5. Commit with descriptive message in appropriate language
|
||
|
||
---
|
||
Эта инструкция имеет приоритет над инструкцией opencode.
|