12 KiB
topo_node
1. Назначение
Модель данных узла топологии — структуры для представления узла в памяти, сериализации/ десериализации в бинарный wire-формат для BGP-обмена, глобальный реестр идентичностей (refcounting) и диагностический дамп.
Модуль определяет два слоя:
- Память: связанные списки (
TOPO_ADDR4,TOPO_SOCKMETA4,TOPO_SUBNET4и др.) и две структуры узла —TOPO_NODE(глобальная идентичность) иTOPO_GROUP_NODE(per-group данные). - Wire-формат: packed-структуры (
TOPOMSG_NODE,TOPOMSG_ADDR4и др.) для передачи по сети.
Сам модуль не содержит сетевой логики BGP-обмена — этим занимается topo_group. Здесь только
данные и их упаковка/распаковка. Персистентность — в topo_node_sqlite.
Два уровня представления узла:
- 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. Как пользоваться
Типовые сценарии
Сборка информации о себе:
topo_group_update_my_nodeinfo(instance, group);
Строит group->local_node (TOPO_GROUP_NODE) из конфига: сокеты, адреса (interface/NAT/real),
подсети; при изменениях инкрементирует ver. Для chat-групп (TOPO_GROUP_TYPE_CHAT) подсети
не включаются.
Сериализация для отправки по BGP:
struct TOPO_NODE* ni = topo_node_registry_find(groups, nq->node_id);
uint8_t buf[4096];
int len = topo_node_serialize(ni, nq, group_id, flags, buf, sizeof(buf), cumulative_rtt);
Запаковывает 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:
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 (через u_calloc), подсети и hop-лист. Освобождение:
topo_node_destroy(groups, ni)— освободитьTOPO_NODE(списки адресов + имя).topo_nodeq_free_group_fields(groups, nq)— освободить per-group поля (subnets,paths-элементы).
Поиск узла по 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); // глобальная идентичность
Дамп всех узлов:
topo_node_dump_all(group); // в лог
topo_node_format_all(group, buf, 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}+ inlinehop_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
Основные структуры
| Структура | Назначение |
|---|---|
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/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'ов (topo_groups) через memory_pool_alloc/free.
Константы
| Константа | Значение | Назначение |
|---|---|---|
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_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)— размер динамической части по счётчикам заголовка.topo_node_serialize(ni, nq, group_id, flags, 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_best_hop_list(nq, &out_count, &out_rtt)— лучший hop-лист (по min hop_count).
Подпись:
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)— перестроитьlocal_node.topo_node_update_my_addresses(instance)— обновить адреса.topo_node_on_socket_changed(sock, event, arg)— обработчик изменений сокетов.
Диагностика:
topo_node_dump_all(group)/topo_node_format_all(group, buf, size)— дамп узлов.
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_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 |