You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

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} + 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

Основные структуры

Структура Назначение
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