topo: invite вынесен в topo_group_invite, conn_mgr упрощён до 3-фазного open; member_sync: полный пересчёт merkle-дерева при старте
- 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-файлы и тесты
This commit is contained in:
1 parent
1899f3a00f
commit
aee44943fa
37 files changed
+1502
-1118
No files matched your search
+110
-102
@@ -2,76 +2,88 @@
|
||||
|
||||
## 1. Назначение
|
||||
|
||||
Модель данных узла топологии — структуры данных для представления узла в памяти, сериализации/десериализации в бинарный wire-формат для BGP-обмена, учёт ссылок (refcounting) и диагностический дамп.
|
||||
Модель данных узла топологии — структуры для представления узла в памяти, сериализации/
|
||||
десериализации в бинарный wire-формат для BGP-обмена, глобальный реестр идентичностей
|
||||
(refcounting) и диагностический дамп.
|
||||
|
||||
Модуль определяет два слоя представлений:
|
||||
- **Память:** связанные списки (`TOPO_ADDR4`, `TOPO_SOCKMETA4`, `TOPO_SUBNET4` и др.) для удобной модификации.
|
||||
- **Wire-формат:** packed-структуры (`TOPOMSG_NODE`, `TOPOMSG_ADDR4` и др.) для передачи по сети без выравнивания.
|
||||
Модуль определяет два слоя:
|
||||
- **Память:** связанные списки (`TOPO_ADDR4`, `TOPO_SOCKMETA4`, `TOPO_SUBNET4` и др.) и две
|
||||
структуры узла — `TOPO_NODE` (глобальная идентичность) и `TOPO_GROUP_NODE` (per-group данные).
|
||||
- **Wire-формат:** packed-структуры (`TOPOMSG_NODE`, `TOPOMSG_ADDR4` и др.) для передачи по сети.
|
||||
|
||||
Сам модуль не содержит сетевой логики BGP-обмена — этим занимается `topo_group`. Здесь только данные и их упаковка/распаковка.
|
||||
Сам модуль не содержит сетевой логики BGP-обмена — этим занимается `topo_group`. Здесь только
|
||||
данные и их упаковка/распаковка. Персистентность — в `topo_node_sqlite`.
|
||||
|
||||
Узлы персистентно хранятся в SQLite через модуль `topo_node_sqlite`. Память для элементов списков (адреса, сокет-мета, подсети) выделяется из memory pool'ов из `topo_groups`.
|
||||
Два уровня представления узла:
|
||||
- **TOPO_NODE** — глобальная идентичность (pubkeys, имя, адреса, self-signature). Хранится один
|
||||
раз в глобальном реестре `TOPO_GROUPS->node_registry` (hash по node_id), разделяется между
|
||||
группами через `group_ref_count`.
|
||||
- **TOPO_GROUP_NODE** — узел в контексте группы: `node_id`, `paths`, `subnets`, `last_ver`,
|
||||
`connectivity`, `conn_presence/conn_up`, `handle`. Хранится в `TOPO_GROUP->nodes`.
|
||||
|
||||
## 2. Как пользоваться
|
||||
|
||||
### Типовые сценарии
|
||||
|
||||
**Создание/обновление информации о себе:**
|
||||
**Сборка информации о себе:**
|
||||
```c
|
||||
topo_group_update_my_nodeinfo(instance, group);
|
||||
```
|
||||
Строит `TOPO_NODEQ` (в `group->local_node`) из конфига: собирает список сокетов, адресов (interface/NAT/real), подсетей; при изменениях инкрементирует `ver` и помечает `dirty=1`. Для chat-групп (`TOPO_GROUP_TYPE_CHAT`) подсети не включаются.
|
||||
Строит `group->local_node` (`TOPO_GROUP_NODE`) из конфига: сокеты, адреса (interface/NAT/real),
|
||||
подсети; при изменениях инкрементирует `ver`. Для chat-групп (`TOPO_GROUP_TYPE_CHAT`) подсети
|
||||
не включаются.
|
||||
|
||||
**Сериализация для отправки по BGP:**
|
||||
```c
|
||||
uint8_t buf[2048];
|
||||
int len = topo_node_serialize(group, nq, buf, sizeof(buf));
|
||||
struct TOPO_NODE* ni = topo_node_registry_find(groups, nq->node_id);
|
||||
uint8_t buf[4096];
|
||||
int len = topo_node_serialize(ni, nq, buf, sizeof(buf), cumulative_rtt);
|
||||
```
|
||||
Запаковывает `TOPO_NODEQ` → бинарный буфер: заголовок `TOPOMSG_NODE`, затем имя узла, v4/v6 sock_meta, v4/v6 адреса, подсети (если `TOPO_FLAG_SEND_SUBNETS`), транзитные узлы и hop-лист.
|
||||
Запаковывает `TOPO_NODE` + per-group данные (`TOPO_GROUP_NODE`) в буфер: заголовок
|
||||
`TOPOMSG_NODE`, затем имя узла, v4/v6 sock_meta, v4/v6 адреса, подсети (если
|
||||
`TOPO_FLAG_SEND_SUBNETS`) и hop-лист (через `topo_node_best_hop_list`).
|
||||
|
||||
**Десериализация при получении NODEINFO:**
|
||||
```c
|
||||
struct TOPO_NODE *ni = NULL;
|
||||
struct TOPO_NODESUBNETS *subnets = NULL;
|
||||
struct TOPOMSG_TRANZIT *tranzit = NULL;
|
||||
uint8_t tranzit_count = 0;
|
||||
uint64_t *hop_list = NULL;
|
||||
uint8_t hop_count = 0;
|
||||
topo_node_deserialize(group, data, data_len, &ni, &subnets, &tranzit, &tranzit_count, &hop_list, &hop_count);
|
||||
struct TOPO_NODE* ni = NULL;
|
||||
struct TOPO_NODESUBNETS* subnets = NULL;
|
||||
uint64_t* hop_list = NULL; uint8_t hop_count = 0;
|
||||
uint16_t cumulative_rtt = 0;
|
||||
topo_node_deserialize(group, data, data_len, &ni, &subnets, &hop_list, &hop_count, &cumulative_rtt);
|
||||
```
|
||||
Восстанавливает `TOPO_NODE`, подсети, транзит и hop-лист из бинарного буфера. Элементы списков аллоцируются из memory pool'ов. Выделенная память должна быть освобождена:
|
||||
- `topo_node_unref(ni)` — освобождает `TOPO_NODE` и `node_name`
|
||||
- `topo_node_free_lists(group, nq)` — освобождает списки обратно в пулы, а также `subnets`, `tranzit_data`, `hop_list`
|
||||
Восстанавливает `TOPO_NODE` (через `u_calloc`), подсети и hop-лист. Освобождение:
|
||||
- `topo_node_destroy(groups, ni)` — освободить `TOPO_NODE` (списки адресов + имя).
|
||||
- `topo_nodeq_free_group_fields(groups, nq)` — освободить per-group поля (`subnets`, `paths`-элементы).
|
||||
|
||||
**Поиск узла по ID:**
|
||||
```c
|
||||
struct TOPO_NODEQ *nq = topo_node_find_by_id(group, node_id);
|
||||
struct TOPO_GROUP_NODE* nq = topo_node_find_by_id(group, node_id); // per-group
|
||||
struct TOPO_NODE* ni = topo_node_registry_find(groups, node_id); // глобальная идентичность
|
||||
```
|
||||
Использует хеш-индекс очереди `group->nodes` (ключ — `node_id`, 8 байт).
|
||||
|
||||
**Дамп всех узлов:**
|
||||
```c
|
||||
topo_node_dump_all(group); // в лог
|
||||
topo_node_format_all(group, buf, size); // в строку
|
||||
topo_node_dump_all(group); // в лог
|
||||
topo_node_format_all(group, buf, size); // в строку
|
||||
```
|
||||
|
||||
### Ключевые концепции
|
||||
|
||||
- **TOPO_NODE** — базовые данные узла: pubkey (X25519), ed25519_pubkey, имя, версия, групповой ID. Разделяется между группами через счётчик ссылок.
|
||||
|
||||
- **TOPO_NODEQ** — запись в очереди узлов группы. Содержит `TOPO_NODE*` (общий), плюс динамические пути, подсети, транзитные узлы, hop-лист, связность, conn_mgr. Все поля аллоцированы отдельно и освобождаются через `topo_node_free_lists()`.
|
||||
|
||||
- **TOPO_NODEPATH** — путь до узла через конкретное ETCP-соединение. Хранится в `paths`-очереди типа `ll_queue`. После самой структуры идёт массив `uint64_t hop[hop_count]` (variable-length).
|
||||
|
||||
- **Счётчик ссылок:** `topo_node_ref()`/`topo_node_unref()`. При падении счётчика до 0 освобождается `node_name` и сам `TOPO_NODE`. Сами списки адресов и sock_meta освобождаются отдельно через `free_lists()`.
|
||||
|
||||
- **Адреса бывают трёх типов:** `TOPO_ADDR_INTERFACE` (LAN-адрес), `TOPO_ADDR_NAT` (после детекции NAT), `TOPO_ADDR_REAL` (подтверждённый прямой адрес). Для каждого сокета может быть до 3 адресов в списке.
|
||||
|
||||
- **TOPO_CONNECTIVITY** — локальное состояние связности (не передаётся по BGP): статус зондирования (NONE/IN_PROGRESS/DONE), результаты для interface/nat/real адресов, минимальные RTT, время зондирования.
|
||||
|
||||
- **TOPO_FLAG_SEND_SUBNETS** — флаг в `TOPO_NODE.flags`: если установлен, подсети сериализуются и включаются в wire-формат. Для chat-групп сбрасывается в 0.
|
||||
|
||||
- **Wire-протокол:** заголовок `TOPOMSG_NODE` (75 байт packed) + динамическая часть: `node_name` (0-255 байт), `SOCKMETA4*N`, `ADDR4*N`, `SOCKMETA6*N`, `ADDR6*N`, опционально подсети, транзит, hop-лист. Размер динамической части вычисляется функцией `topo_node_dyn_size()`.
|
||||
- **Глобальный реестр**: `TOPO_NODE` хранится один раз в `node_registry`; `topo_node_registry_store`
|
||||
дедуплицирует по `node_id` (возвращает существующий при совпадении). `registry_ref/unref`
|
||||
управляют `group_ref_count`; при 0 — `topo_node_destroy`.
|
||||
- **Путь**: `TOPO_NODEPATH = {conn, hop_count, cumulative_rtt}` + inline `hop_list[hop_count]`
|
||||
сразу после структуры. Полный hop-лист для отправки — `topo_node_best_hop_list`.
|
||||
- **Self-signature**: `x25519_self_sig` — Ed25519-подпись над каноническим сообщением
|
||||
(`topo_node_build_sig_msg`: pubkey || имя || client_type || client_activity || адреса).
|
||||
Ставится `topo_node_sign_self`, проверяется в `topo_group_process_nodeinfo`.
|
||||
- **Адреса трёх типов**: `TOPO_ADDR_INTERFACE` (LAN), `TOPO_ADDR_NAT` (после детекции),
|
||||
`TOPO_ADDR_REAL` (подтверждённый прямой). Для каждого сокета — до 3 адресов.
|
||||
- **TOPO_CONNECTIVITY** — локальное состояние связности (не передаётся по BGP): probe_status
|
||||
(NONE/IN_PROGRESS/DONE/DEFERRED), RTT и статусы interface/nat/real, `probe_deferred_wait`.
|
||||
- **TOPO_FLAG_SEND_SUBNETS** — если установлен, подсети сериализуются; для chat-групп сброшен.
|
||||
- **Wire-протокол**: заголовок `TOPOMSG_NODE` (packed) + динамика: `node_name`, `SOCKMETA4*N`,
|
||||
`ADDR4*N`, `SOCKMETA6*N`, `ADDR6*N`, опционально подсети, hop-лист. Размер динамики — `topo_node_dyn_size()`.
|
||||
|
||||
## 3. API
|
||||
|
||||
@@ -79,92 +91,88 @@ topo_node_format_all(group, buf, size); // в строку
|
||||
|
||||
| Структура | Назначение |
|
||||
|-----------|-----------|
|
||||
| `struct TOPO_NODE` | Идентичность узла: pubkeys (X25519+Ed25519), имя, версия, group_id, node_id, списки v4/v6 сокет-метаданных и адресов. Счётчик ссылок. |
|
||||
| `struct TOPO_NODEQ` | Запись в очереди группы. Содержит `TOPO_NODE*`, подсети, транзитные данные, hop-лист, очередь `paths` (TOPO_NODEPATH), связность, conn_mgr. `best_socket` — указатель на лучший ETCP-сокет для связи. |
|
||||
| `struct TOPO_NODEPATH` | Путь до узла через ETCP-соединение с hop_count. Variable-length: после структуры идёт `uint64_t hop[]`. |
|
||||
| `struct TOPO_NODESUBNETS` | Списки v4 и v6 подсетей, анонсируемых узлом. Отдельный malloc, может быть NULL. |
|
||||
| `struct TOPO_CONNECTIVITY` | Локальное состояние проверки связности: статусы зондирования, RTT для interface/nat/real адресов. |
|
||||
| `struct TOPOMSG_NODE` | Packed-заголовок wire-формата (75 байт). Содержит счётчики элементов динамической части. |
|
||||
| `struct TOPOMSG_ADDR4/6` | Packed wire-формат одного адреса (addr, port, type, socket_id, protocol). |
|
||||
| `struct TOPOMSG_SOCKMETA4/6` | Packed wire-формат метаданных сокета (id, config_type, nat_type). |
|
||||
| `struct TOPOMSG_SUBNET4/6` | Packed wire-формат подсети (addr, prefix_length). |
|
||||
| `struct TOPOMSG_TRANZIT` | Packed wire-формат транзитного узла (node_id, rtt, link_q). |
|
||||
| `struct TOPO_NODE` | Глобальная идентичность узла: `flags`, `group_id`, `node_id`, `ver`, `public_key`, `ed25519_public_key`, `x25519_self_sig`, `client_type`, `client_activity`, `node_name`, списки v4/v6 sock_meta и addrs, `group_ref_count` |
|
||||
| `struct TOPO_GROUP_NODE` | Per-group запись: `node_id`, `subnets`, `paths` (queue TOPO_NODEPATH), `last_ver`, `conn_mgr_*`, `connectivity`, `conn_presence`, `conn_up`, `handle` (ncd) |
|
||||
| `struct TOPO_NODEPATH` | Путь через ETCP_CONN: `{conn, hop_count, cumulative_rtt}` + inline `hop_list[]` |
|
||||
| `struct TOPO_NODESUBNETS` | v4/v6 подсети узла (отдельный malloc, может быть NULL) |
|
||||
| `struct TOPO_CONNECTIVITY` | Связность: probe_status, RTT, статусы interface/nat/real, probe-тайминги |
|
||||
| `struct TOPOMSG_NODE` | Packed-заголовок wire-формата: счётчики, `hop_count`, `client_type/activity`, `cumulative_rtt` |
|
||||
| `struct TOPOMSG_ADDR4/6` | Packed wire одного адреса (addr, port, type, socket_id, protocol) |
|
||||
| `struct TOPOMSG_SOCKMETA4/6` | Packed wire сокет-метаданных (id, config_type, nat_type) |
|
||||
| `struct TOPOMSG_SUBNET4/6` | Packed wire подсети (addr, prefix_length) |
|
||||
|
||||
### Вспомогательные типы в памяти (связанные списки)
|
||||
|
||||
| Тип | Назначение |
|
||||
|-----|-----------|
|
||||
| `struct TOPO_SOCKMETA4` | Элемент списка v4 сокет-метаданных (next*, id, config_type, nat_type). |
|
||||
| `struct TOPO_ADDR4` | Элемент списка v4 адресов (next*, addr[4], port, type, socket_id, protocol). |
|
||||
| `struct TOPO_SOCKMETA6` | Элемент списка v6 сокет-метаданных. |
|
||||
| `struct TOPO_ADDR6` | Элемент списка v6 адресов. |
|
||||
| `struct TOPO_SUBNET4` | Элемент списка v4 подсетей (next*, addr[4], prefix_length). |
|
||||
| `struct TOPO_SUBNET6` | Элемент списка v6 подсетей. |
|
||||
| `struct TOPO_SOCKMETA4/6` | Элемент списка сокет-метаданных (next*, id, config_type, nat_type) |
|
||||
| `struct TOPO_ADDR4/6` | Элемент списка адресов (next*, addr, port, type, socket_id, protocol) |
|
||||
| `struct TOPO_SUBNET4/6` | Элемент списка подсетей (next*, addr, prefix_length) |
|
||||
|
||||
Все элементы списков аллоцируются из memory pool'ов и освобождаются через `memory_pool_free()`.
|
||||
Элементы списков аллоцируются из memory pool'ов (`topo_groups`) через `memory_pool_alloc/free`.
|
||||
|
||||
### Константы
|
||||
|
||||
| Константа | Значение | Назначение |
|
||||
|-----------|---------|-----------|
|
||||
| `TOPO_ADDR_INTERFACE` | 0 | Интерфейсный (LAN) адрес сокета |
|
||||
| `TOPO_ADDR_NAT` | 1 | NAT-адрес после детекции |
|
||||
| `TOPO_ADDR_REAL` | 2 | Подтверждённый прямой адрес |
|
||||
| `TOPO_PROTO_UDP` | 0x01 | UDP-транспорт |
|
||||
| `TOPO_PROTO_TCP` | 0x02 | TCP-транспорт |
|
||||
| `PROBE_STATUS_NONE` | 0 | Зондирование не запускалось |
|
||||
| `PROBE_STATUS_IN_PROGRESS` | 1 | Зондирование идёт |
|
||||
| `PROBE_STATUS_DONE` | 2 | Зондирование завершено |
|
||||
| `PROBE_RESULT_UNKNOWN` | 0 | Результат неизвестен |
|
||||
| `PROBE_RESULT_REACHABLE` | 1 | Адрес достижим |
|
||||
| `PROBE_RESULT_UNREACHABLE` | 2 | Адрес недостижим |
|
||||
| `CONN_TYPE_DIRECT` | 1 | Прямое соединение |
|
||||
| `CONN_TYPE_REVERSE` | 2 | Обратное соединение |
|
||||
| `CONN_TYPE_INDIRECT` | 3 | Соединение через посредника |
|
||||
| `TOPO_FLAG_SEND_SUBNETS` | 0x01 | Флаг: отправлять подсети |
|
||||
| `TOPO_GROUP_UTUN` | `0x8000000000000000ULL` | ID группы uTun по умолчанию |
|
||||
| `TOPO_ADDR_INTERFACE` / `TOPO_ADDR_NAT` / `TOPO_ADDR_REAL` | 0/1/2 | Тип адреса |
|
||||
| `TOPO_PROTO_UDP` / `TOPO_PROTO_TCP` | 0x01/0x02 | Транспорт |
|
||||
| `ADDR_TYPE_NETIF/DIRECT/NAT_EIM/NAT_STRICT` | 0/1/2/3 | Классификация адреса |
|
||||
| `PROBE_STATUS_NONE/IN_PROGRESS/DONE/DEFERRED` | 0/1/2/3 | Состояние пробы |
|
||||
| `PROBE_RESULT_UNKNOWN/REACHABLE/UNREACHABLE` | 0/1/2 | Результат пробы |
|
||||
| `CONN_TYPE_NONE/DIRECT/REVERSE/INDIRECT` | 0/1/2/3 | Стратегия соединения |
|
||||
| `CLIENT_TYPE_SERVER/DESKTOP/MOBILE` | 0/1/2 | Тип клиента |
|
||||
| `CLIENT_ACTIVITY_STANDBY/ACTIVE` | 0/1 | Режим |
|
||||
| `NCONN_DIRECT/INDIRECT/BGP` | 1/2/4 | Биты наличия соединений |
|
||||
| `TOPO_FLAG_SEND_SUBNETS` | 0x01 | Отправлять подсети |
|
||||
| `TOPO_GROUP_UTUN` | `0x8000000000000000ULL` | ID utun-группы по умолчанию |
|
||||
| `TOPO_GROUP_TYPE_UTUN/CHAT` | 1/2 | Тип группы |
|
||||
| `CONN_MGR_MAX_INTERMEDIARIES` | 3 | Максимум посредников |
|
||||
|
||||
### Функции
|
||||
|
||||
**Управление памятью и refcounting:**
|
||||
- `topo_node_ref(ni)` — увеличить счётчик ссылок на `TOPO_NODE`.
|
||||
- `topo_node_unref(ni)` — уменьшить счётчик; при 0 освободить `node_name` и `TOPO_NODE` (но не списки — их надо предварительно освободить через `topo_node_free_lists`).
|
||||
- `topo_node_free_lists(group, nq)` — освободить все списки адресов/sock_meta обратно в memory pool'ы, освободить `subnets`, `tranzit_data`, `hop_list`, сделать `unref` на `node`, обнулить указатели.
|
||||
**Реестр и refcounting:**
|
||||
- `topo_node_registry_find(groups, node_id)` — найти `TOPO_NODE` в глобальном реестре.
|
||||
- `topo_node_registry_store(groups, ni)` — сохранить с дедупликацией (возвращает существующий при совпадении).
|
||||
- `topo_node_registry_ref/unref(groups, node_id)` — инкремент/декремент `group_ref_count`.
|
||||
- `topo_node_destroy(groups, ni)` — освободить `TOPO_NODE` (списки адресов + имя).
|
||||
|
||||
**Per-group:**
|
||||
- `topo_node_find_by_id(group, node_id)` — найти `TOPO_GROUP_NODE` по node_id (hash).
|
||||
- `topo_nodeq_free_group_fields(groups, nq)` — освободить per-group поля (subnets, paths) + unref глобального TOPO_NODE.
|
||||
|
||||
**Сериализация:**
|
||||
- `topo_node_dyn_size(msg)` — вычислить размер динамической части wire-формата по полям-счётчикам заголовка `TOPOMSG_NODE`. Не учитывает сам заголовок.
|
||||
- `topo_node_serialize(group, nq, out, out_max)` — сериализовать `TOPO_NODEQ` в бинарный буфер. Возвращает количество записанных байт или -1 при ошибке (переполнение или невалидные аргументы). Формат: заголовок `TOPOMSG_NODE`, затем name, v4 sock_meta, v4 addrs, v6 sock_meta, v6 addrs, подсети (опционально), tranzit, hop_list.
|
||||
- `topo_node_dyn_size(msg)` — размер динамической части по счётчикам заголовка.
|
||||
- `topo_node_serialize(ni, nq, out, out_max, cumulative_rtt)` — сериализовать `TOPO_NODE` + per-group в буфер.
|
||||
- `topo_node_deserialize(group, data, len, &out_ni, &out_subnets, &out_hop_list, &out_hop_count, &out_cumulative_rtt)` — восстановить из wire-формата.
|
||||
|
||||
**Десериализация:**
|
||||
- `topo_node_deserialize(group, data, len, &out_ni, &out_subnets, &out_tranzit, &out_tranzit_count, &out_hop_list, &out_hop_count)` — восстановить `TOPO_NODE`, подсети, транзит и hop-лист из бинарного wire-формата. Аллоцирует `TOPO_NODE` через `u_calloc` (ref_count=1), элементы списков — из memory pool'ов, `subnets`, `tranzit_data`, `hop_list` — отдельными `u_malloc`. Возвращает 0 при успехе, -1 при несоответствии размера или ошибке аллокации. Если подсети есть в wire-формате но флаг `TOPO_FLAG_SEND_SUBNETS` не установлен, они пропускаются.
|
||||
**Пути:**
|
||||
- `topo_node_best_hop_list(nq, &out_count, &out_rtt)` — лучший hop-лист (по min hop_count).
|
||||
|
||||
**Поиск:**
|
||||
- `topo_node_find_by_id(group, node_id)` — найти `TOPO_NODEQ` в очереди группы по `node_id` через хеш-индекс. Возвращает NULL если не найден.
|
||||
**Подпись:**
|
||||
- `topo_node_build_sig_msg(ni, buf, buf_size)` — каноническое сообщение для Ed25519-подписи.
|
||||
- `topo_node_sign_self(instance, ni)` — подписать свой NODEINFO (`x25519_self_sig`).
|
||||
|
||||
**Обновление информации о себе:**
|
||||
- `topo_group_update_my_nodeinfo(instance, group)` — перестроить `group->local_node` (`TOPO_NODEQ`) из текущих данных инстанса (сокеты, NAT, адреса, подсети, ключи). Сравнивает количество элементов с предыдущим значением; если есть изменения — освобождает старый `local_node`, создаёт новый, инкрементирует `ver`, помечает `dirty=1`. Обновляет таблицу маршрутов (`route_delete`/`route_insert`). Для chat-групп подсети не включаются. Возвращает количество v4 подсетей.
|
||||
**Обновление о себе:**
|
||||
- `topo_group_update_my_nodeinfo(instance, group)` — перестроить `local_node`.
|
||||
- `topo_node_update_my_addresses(instance)` — обновить адреса.
|
||||
- `topo_node_on_socket_changed(sock, event, arg)` — обработчик изменений сокетов.
|
||||
|
||||
**Диагностика:**
|
||||
- `topo_node_dump_all(group)` — дамп всех узлов группы в лог (DEBUG_CATEGORY_BGP). Для каждого узла выводит: ID, имя, версию, pubkeys, v4/v6 сокеты и адреса, подсети, транзитные узлы, пути (с hop-ами), статус связности, conn_mgr. Пропускает узлы с `node==NULL`.
|
||||
- `topo_node_format_all(group, buf, buf_size)` — аналогичный дамп в строковый буфер. Возвращает количество записанных байт. При переполнении добавляет `[TRUNCATED]`.
|
||||
- `topo_node_dump_all(group)` / `topo_node_format_all(group, buf, size)` — дамп узлов.
|
||||
|
||||
**Inline-аксессоры (из .h):**
|
||||
- `topo_v4_sock_meta(ni)` / `topo_v4_addrs(ni)` / `topo_v6_sock_meta(ni)` / `topo_v6_addrs(ni)` — получить списки из `TOPO_NODE`.
|
||||
- `topo_v4_subnets(r)` / `topo_v6_subnets(r)` — получить списки подсетей из `TOPO_NODESUBNETS*` (NULL-safe).
|
||||
- `topo_list_count(head)` — посчитать количество элементов в любом из списков (next — первое поле).
|
||||
**Inline-аксессоры (.h):**
|
||||
- `topo_v4_sock_meta/addr`, `topo_v6_sock_meta/addr`, `topo_v4_subnets/topo_v6_subnets`, `topo_list_count`.
|
||||
|
||||
### Зависимости
|
||||
|
||||
| Модуль | Использование |
|
||||
|--------|--------------|
|
||||
| `ll_queue.h` | `TOPO_NODEQ` — запись в очереди, хеш-индекс по `node_id`, `paths` — вложенная очередь |
|
||||
| `secure_channel.h` | `SC_PUBKEY_SIZE` (32) для массивов pubkey/ed25519 |
|
||||
| `mem.h` | `u_malloc`, `u_calloc`, `u_free`, `u_strdup` |
|
||||
| `memory_pool.h` | `memory_pool_alloc`/`memory_pool_free` для элементов списков (пулы из `topo_groups`) |
|
||||
| `debug_config.h` | `DEBUG_INFO`, `DEBUG_WARN`, `DEBUG_ERROR`, `log_dump` |
|
||||
| `topo_group.h` | `struct TOPO_GROUP` (аргумент большинства функций) |
|
||||
| `etcp.h` | `struct ETCP_CONN`, `struct ETCP_SOCKET` |
|
||||
| `config_parser.h` | `struct CFG_ROUTE_ENTRY`, `struct CFG_SERVER` (при построении local_node) |
|
||||
| `route_lib.h` | `route_insert()`, `route_delete()` (при обновлении local_node) |
|
||||
| `etcp_debug.h` | `ip_to_str()` (для дампа адресов и подсетей) |
|
||||
| `utun_instance.h` | `struct UTUN_INSTANCE` (аргумент `topo_group_update_my_nodeinfo`) |
|
||||
| `ll_queue.h` | `TOPO_GROUP_NODE` — запись в очереди (hash по node_id), `paths` — вложенная очередь |
|
||||
| `secure_channel.h` | `SC_PUBKEY_SIZE` (32) |
|
||||
| `mem.h` | `u_malloc`, `u_calloc`, `u_free` |
|
||||
| `memory_pool.h` | Элементы списков из пулов `topo_groups` |
|
||||
| `debug_config.h` | Логирование (BGP) |
|
||||
| `topo_group.h` | `struct TOPO_GROUP`, `TOPO_GROUPS` |
|
||||
| `route_lib.h` | `route_insert/route_delete` |
|
||||
| `utun_instance.h` | `struct UTUN_INSTANCE` |
|
||||
Reference in new issue
Block a user