stcp: ed25519 pubkey exchange in handshake, fix instance destroy segfault, fix chat_tcp_test

- u_async.c: process immediate_queue BEFORE epoll_wait in uasync_poll
- stcp_link.c: defensive NULL etcp_conn/etcp_link in stcp_link_close
- utun_instance.c: move stcp_server_list_destroy_all to Phase J (before ETCP),
  add deferred drain in both Phase J and L
- stcp.h/c: STCP_HS_ENC_CLIENT 6→38, STCP_HS_ENC_SERVER 7→39,
  exchange ed25519_pubkey in both handshake directions
- etcp_connections.c: copy peer_ed25519 from STCP to ETCP_CONN in
  etcp_link_enter_ready_tcp; guard link->etcp in tcp_link_close_cb
- chat_sync.c: fix lk->conn NULL dereference for TCP links
- test_stcp.c: update stcp_server_create/stcp_client_connect callsites
- tools/chat_tcp_test: change transport udp→tcp
This commit is contained in:
evgeny committed 2026-08-07 00:48:27 +03:00
1 parent a3783b5f55
commit 38c9f229bc
1272 files changed
+968388 -1

No files matched your search

+114
View File
@@ -0,0 +1,114 @@
# utun_instance — Корневой инстанс (центральный оркестратор)
## 1. Назначение
`UTUN_INSTANCE` — **центральная структура всего процесса uTun**. Владеет всеми подсистемами: TUN, таблица маршрутов, BGP-группы, ETCP-сокеты/соединения, control-сервер, message transport, firewall, NAT, TCP-прокси, memory pools, NTP, синхронизация БД, менеджер соединений.
Это **единственная точка входа для инициализации и завершения** всех компонентов. Порядок инициализации и destroy строго определён — от низкоуровневых подсистем к высокоуровневым и обратно.
## 2. Как пользоваться
### Создание
```c
struct UASYNC* ua = uasync_create();
struct UTUN_INSTANCE* inst = utun_instance_create(ua, "utun.conf"); // из файла
// или
struct UTUN_INSTANCE* inst = utun_instance_create_from_config(ua, config); // из готовой структуры
// или
struct UTUN_INSTANCE* inst = utun_instance_create_from_str(ua, config_text); // из строки (тесты)
```
### Инициализация (оркестрация)
```c
utun_instance_init(inst); // запускает всю цепочку инициализации
```
`utun_instance_init()` **не вызывает** `utun_instance_create()` — create только аллоцирует память и загружает конфиг. `init` запускает все подсистемы в строгом порядке:
1. `db_sync_init` — распределённая БД с репликацией
2. `routing_set_tun` — привязка TUN к таблице маршрутов
3. `nat_transport_init` — NAT (если включён в конфиге)
4. `init_connections` — ETCP-сокеты, клиентские подключения, handshake
5. `control_server_init` — сервер мониторинга (etcpmon)
6. `ntp_time_init` + `ntp_node_time_init` — синхронизация времени
### Основной цикл
```c
inst->running = 1;
while (inst->running) {
uasync_poll(inst->ua, 100);
}
```
### Остановка и destroy
```c
utun_instance_stop(inst); // running=0, wakeup
utun_instance_destroy(inst); // полный cleanup в обратном порядке
```
`destroy` гарантирует порядок: NTP→control→ETCP sockets→db_sync→connections→pings→TUN→tcp_proxy→routing→NAT→etcp_router→conn_mgr→BGP→fw→stcp→networks→config→pools. **uasync не уничтожается** — вызывающий код должен сам вызвать `uasync_destroy()`.
### Reload (SIGHUP)
```c
inst = utun_instance_reload(inst, ua, "utun.conf");
```
Сравнивает старый и новый конфиг:
- Если изменились ключи/node_id/tun_ifname → **полный перезапуск** (destroy + create + init)
- Иначе — **селективное обновление**: только изменённые/добавленные/удалённые сокеты, клиенты, линки. Неизменённые не трогаются (без close, без сброса таймеров).
## 3. API
### Структура `UTUN_INSTANCE` — ключевые поля
| Поле | Тип | Назначение |
|------|-----|------------|
| `name` | `char[16]` | Имя инстанса из конфига |
| `config` | `struct utun_config*` | Полный разобранный конфиг |
| `node_id` | `uint64_t` | Идентификатор узла (из конфига или derived из privkey) |
| `my_keys` | `struct SC_MYKEYS` | Пара ключей X25519 (pub/priv) |
| `my_ed25519_pubkey` / `_privkey` | `uint8_t[32]` | Ed25519 ключи (для подписи) |
| `ua` | `struct UASYNC*` | Главный event loop (один на поток) |
| `running` | `int` | Флаг работы главного цикла |
| `tun` | `struct tun_if*` | TUN-интерфейс |
| `route_subnets` | `struct CFG_ROUTE_ENTRY*` | Маршруты для добавления/удаления системных роутов |
| `rt` | `struct ROUTE_TABLE*` | Таблица маршрутов |
| `topo_groups` | `struct TOPO_GROUPS*` | BGP-подобный обмен маршрутами |
| `connections` | `struct ll_queue*` | Очередь всех ETCP-соединений (индекс по peer_node_id) |
| `etcp_sockets` | `struct ETCP_SOCKET*` | Связный список UDP-сокетов |
| `stcp_server` | `struct stcp_server*` | STCP TCP-сервер |
| `data_pool` | `struct memory_pool*` | Пул для данных пакетов (payload) |
| `pkt_pool` | `struct memory_pool*` | Пул для `struct ETCP_DGRAM` |
| `ack_pool` | `struct memory_pool*` | Пул для `struct ACK_PACKET` |
| `control_srv` | `struct control_server*` | Сервер мониторинга (etcpmon backend) |
| `fw` | `struct firewall_ctx` | Контекст файрвола |
| `nat` / `nat_tr` | `struct eim_nat_ctx` / `nat_transport_ctx` | EIM NAT + транспорт |
| `tcp_proxy_client` | `struct tcp_proxy_client*` | TCP-прокси клиент (опционально) |
| `tcp_proxy_server` | `struct tcp_proxy_server` | TCP-прокси сервер (exit node) |
| `router_bindings` / `router_conns` | | Привязки и соединения ETCP-роутера |
| `conn_mgr` | `struct CONN_MGR*` | Менеджер соединений (может быть NULL) |
| `db_sync` | `struct DB_SYNC*` | Распределённая синхронизация БД (может быть NULL) |
| `networks` | `struct ll_queue*` | Очередь сетей (NETWORK_ENTRY, индекс по 56-bit id) |
| `pending_connects` | `struct ETCP_CONNECT*` | Ожидающие фоновые подключения |
| `ntp` / `ntp_node` | `struct NTP_TIME` / `NTP_NODE_TIME` | Синхронизация времени |
| `stats_dir` | `char[512]` | Путь `<config_dir>/stats/` для файлов метрик |
| `next_socket_id` | `uint8_t` | Счётчик уникальных ID сокетов (0–255) |
| `socket_init_status` | `int` | Статус инициализации сокетов: 0=OK, 1=частично, -1=ошибка |
| `routed_packets` / `dropped_packets` | `uint64_t` | Счётчики маршрутизированных/отброшенных пакетов |
### Основные функции
| Функция | Описание |
|---------|----------|
| `utun_instance_create(ua, config_file)` | Загрузка конфига, аллокация инстанса, вызов `instance_init_common()`. Возвращает готовый к `init` инстанс или NULL |
| `utun_instance_create_from_config(ua, config)` | Создание из уже разобранного конфига (владение передаётся инстансу) |
| `utun_instance_create_from_str(ua, config_text)` | Создание из строки конфига (временный файл → parse → delete). Для тестов |
| `utun_instance_init(instance)` | **Основной оркестратор инициализации**. Запускает все подсистемы в правильном порядке, устанавливает `running=1` |
| `utun_instance_destroy(instance)` | **Полный cleanup** всех ресурсов в обратном порядке зависимостей |
| `utun_instance_stop(instance)` | Установка `running=0` + `uasync_wakeup()` для выхода из mainloop |
| `utun_instance_reload(instance, ua, config_file)` | Перезагрузка конфига по SIGHUP: полная при изменении ключей/TUN, иначе селективная |
| `utun_instance_set_tun_init_enabled(enabled)` | Глобальный флаг: включать инициализацию TUN или нет (для тестов без TUN) |
| `utun_instance_diagnose_leaks(instance, phase)` | Диагностика: подсчёт ETCP-сокетов/соединений/линков, проверка утечек пулов и TUN |
### Внутренние (static)
| Функция | Описание |
|---------|----------|
| `instance_init_common(instance, ua, config)` | Общая инициализация для всех create-функций: ключи, node_id, networks, memory pools, routing, TUN, сокеты, BGP, conn_mgr, firewall, etcp_router, routing_bind, tcp_proxy_server/client |
| `local_sockaddr_equal(a, b)` | Сравнение двух sockaddr_storage (IPv4/IPv6) — используется в reload |