docs: clarify core, group and chat header contracts
This commit is contained in:
1 parent
72fee9e245
commit
01fcefdec5
19 files changed
+396
-414
No files matched your search
@@ -2,21 +2,11 @@
|
||||
* @file topo_node.h
|
||||
* @brief Модель данных узла сети — структуры, сериализация, wire-формат.
|
||||
*
|
||||
* Этот модуль определяет:
|
||||
* - Как узел представлен в памяти (TOPO_NODE, TOPO_GROUP_NODE, адреса, подсети)
|
||||
* - Как узел передаётся по сети (packed-структуры TOPOMSG_*)
|
||||
* - Как узел сериализуется/десериализуется (topo_node_serialize/deserialize)
|
||||
*
|
||||
* Хранение:
|
||||
* - Идентичность узла (pubkeys, адреса, имя) — в глобальном реестре TOPO_GROUPS->node_registry
|
||||
* Единственный экземпляр TOPO_NODE, разделяется между группами через group_ref_count.
|
||||
* - Per-group данные (node_id, paths, subnets, connectivity) — в TOPO_GROUP->nodes (очередь TOPO_GROUP_NODE)
|
||||
*
|
||||
* Основные понятия:
|
||||
* TOPO_NODE — глобальная идентичность узла. Встроен в node_registry как queue entry.
|
||||
* TOPO_GROUP_NODE — узел в контексте группы: node_id + paths, hop_list, связность
|
||||
* TOPO_NODEPATH — путь до узла через конкретное ETCP-соединение
|
||||
* TOPOMSG_NODE — wire-формат, передаваемый по NODEINFO
|
||||
* TOPO_NODE — общие ключи, имя и адреса; реестр хранит указатель с подсчётом ссылок.
|
||||
* Подписанная запись заменяется целиком при более свежем timestamp, вместе с подписью.
|
||||
* TOPO_GROUP_NODE — пути, подсети и состояние узла в конкретной группе.
|
||||
* TOPOMSG_NODE — сетевой формат. Модуль сериализует, подписывает и проверяет записи.
|
||||
* Работа с реестром и группами выполняется в потоке uasync экземпляра.
|
||||
*/
|
||||
#ifndef TOPO_NODE_H
|
||||
#define TOPO_NODE_H
|
||||
@@ -87,9 +77,11 @@ struct UTUN_INSTANCE;
|
||||
#define TOPO_GROUP_TYPE_UTUN 1
|
||||
#define TOPO_GROUP_TYPE_CHAT 2
|
||||
|
||||
/* Результаты проб адресов. *_time — timebase (0.1 ms), *_rtt — те же единицы;
|
||||
* *_status — PROBE_RESULT_*, probe_status — PROBE_STATUS_*. */
|
||||
struct TOPO_CONNECTIVITY {
|
||||
uint8_t probe_status;
|
||||
uint8_t pending_count;
|
||||
uint8_t pending_count; // незавершённые пробы
|
||||
uint64_t probe_start_time;
|
||||
uint16_t interface_min_rtt;
|
||||
uint16_t nat_min_rtt;
|
||||
@@ -103,7 +95,7 @@ struct TOPO_CONNECTIVITY {
|
||||
uint64_t real_probe_time;
|
||||
uint64_t ping_req_time;
|
||||
uint64_t last_ping_time;
|
||||
void* probe_list;
|
||||
void* probe_list; // принадлежащие узлу контексты текущих проб
|
||||
void* probe_deferred_wait; /* контекст отложенной пробы (standby_wait, Android) */
|
||||
};
|
||||
|
||||
@@ -171,17 +163,17 @@ struct TOPO_ADDR_REALITY_OPTS {
|
||||
struct _topo_head { struct _topo_head* next; };
|
||||
static inline int topo_list_count(struct _topo_head* head) { int n = 0; while (head) { n++; head = head->next; } return n; }
|
||||
|
||||
/** Глобальная идентичность узла. Встроен в TOPO_GROUPS->node_registry как queue entry. */
|
||||
/** Общая запись узла; node_registry хранит указатель на неё в отдельном ll_entry. */
|
||||
struct TOPO_NODE {
|
||||
struct ll_entry ll;
|
||||
uint32_t group_ref_count;
|
||||
uint32_t group_ref_count; // ссылки групп, ядра и временных пользователей
|
||||
uint64_t node_id; uint8_t ver;
|
||||
uint64_t timestamp; // 0 = неподписанные bootstrap-сведения
|
||||
uint8_t public_key[SC_PUBKEY_SIZE], ed25519_public_key[SC_PUBKEY_SIZE];
|
||||
uint8_t x25519_self_sig[64];
|
||||
uint8_t x25519_self_sig[64]; // Ed25519-подпись общей записи
|
||||
uint8_t client_type; // CLIENT_TYPE_SERVER/DESKTOP/MOBILE
|
||||
uint8_t client_activity; // CLIENT_ACTIVITY_STANDBY/ACTIVE
|
||||
char* node_name;
|
||||
char* node_name; // собственная строка; освобождается с записью
|
||||
struct TOPO_SOCKMETA4* v4_sock_meta;
|
||||
struct TOPO_ADDR4* v4_addrs;
|
||||
struct TOPO_SOCKMETA6* v6_sock_meta;
|
||||
@@ -196,9 +188,9 @@ struct TOPO_NODESUBNETS {
|
||||
|
||||
struct TOPO_NODEPATH {
|
||||
struct ll_entry ll;
|
||||
struct ETCP_CONN* conn;
|
||||
uint8_t hop_count;
|
||||
uint16_t cumulative_rtt;
|
||||
struct ETCP_CONN* conn; // заимствованный next-hop; транспорт удерживает сессия
|
||||
uint8_t hop_count; // число node_id в массиве сразу после структуры
|
||||
uint16_t cumulative_rtt; // RTT оставшейся цепочки, без локального линка (0.1 ms)
|
||||
};
|
||||
|
||||
/** Узел в контексте группы (per-group данные). Хранится в TOPO_GROUP->nodes (ll_queue). */
|
||||
@@ -213,52 +205,74 @@ struct TOPO_GROUP_NODE {
|
||||
uint64_t conn_mgr_intermediaries[CONN_MGR_MAX_INTERMEDIARIES]; // посредники для INDIRECT
|
||||
uint8_t conn_mgr_intermediariy_count; // количество посредников
|
||||
struct TOPO_CONNECTIVITY connectivity; // результаты ping-проб (interface/nat/real)
|
||||
uint8_t conn_presence; // NODE_CONN_* — какие подключения есть в принципе
|
||||
uint8_t conn_up; // NODE_CONN_* — какие из них подняты
|
||||
uint8_t conn_presence; // маска NCONN_*: известные виды подключения
|
||||
uint8_t conn_up; // маска NCONN_*: работающие виды подключения
|
||||
uint8_t radio; // 1 = узел слушает рацию канала (TOPO_FLAG_RADIO)
|
||||
struct NODE_CONN_DIRECT* handle; // активный ncd-handle прямого соединения к узлу
|
||||
struct NODE_CONN_DIRECT* handle; // не владеет транспортом; NCD принадлежит сессии группы
|
||||
};
|
||||
|
||||
// API — глобальный реестр TOPO_NODE
|
||||
/* Заимствованный указатель; ref нужен, если запись должна пережить удаление из группы. */
|
||||
struct TOPO_NODE* topo_node_registry_find(struct TOPO_GROUPS* groups, uint64_t node_id);
|
||||
/* Принять ni и вернуть запись с одной новой ссылкой. Может вернуть существующий объект.
|
||||
* При NULL входной ni остаётся у вызывающего. Подписанные записи сравниваются по timestamp. */
|
||||
struct TOPO_NODE* topo_node_registry_store(struct TOPO_GROUPS* groups, struct TOPO_NODE* ni);
|
||||
/* Добавить/снять ссылку; последняя unref удаляет запись из реестра и освобождает её. */
|
||||
void topo_node_registry_ref(struct TOPO_GROUPS* groups, uint64_t node_id);
|
||||
void topo_node_registry_unref(struct TOPO_GROUPS* groups, uint64_t node_id);
|
||||
/* Освободить отдельную запись и её списки; зарегистрированную запись отпускать через unref. */
|
||||
void topo_node_destroy(struct TOPO_GROUPS* groups, struct TOPO_NODE* ni);
|
||||
|
||||
// API — per-group
|
||||
/* Заимствованный узел группы, NULL если не найден. */
|
||||
struct TOPO_GROUP_NODE* topo_node_find_by_id(struct TOPO_GROUP* group, uint64_t node_id);
|
||||
/* Отпустить ссылку реестра и подсети; nq и paths не освобождает. */
|
||||
void topo_nodeq_free_group_fields(struct TOPO_GROUPS* groups, struct TOPO_GROUP_NODE* nq);
|
||||
/* Полное удаление узла из группы: отменяет влётные пробы, освобождает paths/subnets,
|
||||
* убирает из group->nodes и освобождает сам nq. Единственный корректный способ удаления узла. */
|
||||
void topo_nodeq_remove_node(struct TOPO_GROUP* group, struct TOPO_GROUP_NODE* nq);
|
||||
|
||||
/* Размер переменной части NODEINFO по счётчикам заголовка. */
|
||||
int topo_node_dyn_size(const struct TOPOMSG_NODE* msg);
|
||||
/* Собрать NODEINFO в out; длина или -1. Входные структуры остаются у вызывающего. */
|
||||
int topo_node_serialize(struct TOPO_NODE* ni, struct TOPO_GROUP_NODE* nq,
|
||||
uint64_t group_id, uint8_t flags,
|
||||
uint8_t* out, size_t out_max, uint16_t cumulative_rtt);
|
||||
/* Разобрать NODEINFO; 0/-1. Выходные объекты выделены отдельно и передаются вызывающему. */
|
||||
int topo_node_deserialize(struct TOPO_GROUP* group, const uint8_t* data, size_t len, struct TOPO_NODE** out_ni, struct TOPO_NODESUBNETS** out_subnets,
|
||||
uint64_t** out_hop_list, uint8_t* out_hop_count,
|
||||
uint16_t* out_cumulative_rtt);
|
||||
/* Заимствованный список hops: кратчайший живой путь, иначе первый сохранённый.
|
||||
* out_count обязателен; NULL означает отсутствие пути. */
|
||||
uint64_t* topo_node_best_hop_list(struct TOPO_GROUP_NODE* nq, uint8_t* out_count, uint16_t* out_rtt);
|
||||
|
||||
/* Обновить локальный узел группы и его анонс. 0/-1. */
|
||||
int topo_group_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct TOPO_GROUP* group);
|
||||
/* Создать подписанную локальную идентичность с отдельной ссылкой ядра. 0/-1. */
|
||||
int topo_node_init_self(struct UTUN_INSTANCE* instance);
|
||||
int topo_node_update_my_addresses(struct UTUN_INSTANCE* instance); /* 1=changed, 0=unchanged, -1=error */
|
||||
/* Обработчик изменений локального сокета: обновляет адреса узла. */
|
||||
void topo_node_on_socket_changed(struct ETCP_SOCKET* sock, int event, void* arg);
|
||||
/* Вывести диагностику узлов группы в лог / текстовый буфер. */
|
||||
void topo_node_dump_all(struct TOPO_GROUP* group);
|
||||
int topo_node_format_all(struct TOPO_GROUP* group, char* buf, size_t buf_size);
|
||||
/* 1, если хотя бы в одной группе пора повторить ping этого узла; иначе 0. */
|
||||
int topo_node_ping_request_cbk(struct TOPO_GROUPS* groups, uint64_t node_id);
|
||||
/* Обновить время ping и минимальные RTT во всех группах и БД; rtt в единицах 0.1 ms. */
|
||||
void topo_node_ping_update_rtt(struct TOPO_GROUPS* groups, uint64_t node_id, uint16_t rtt);
|
||||
/* Минимальный суммарный RTT живого пути в единицах 0.1 ms; UINT16_MAX, если неизвестен. */
|
||||
uint16_t topo_get_chain_rtt(struct TOPO_GROUP_NODE* nq);
|
||||
|
||||
/** Build canonical message for Ed25519 signature: x25519_pubkey || name || client_type || client_activity || addresses */
|
||||
/* Лимиты буфера подписываемых данных и полного сетевого NODEINFO. */
|
||||
#define TOPO_SIG_MSG_MAX_SIZE 2048
|
||||
#define TOPO_NODE_WIRE_MAX_SIZE 16384
|
||||
/* Канонические байты подписи: node_id, ver, timestamp, X25519-ключ, имя,
|
||||
* тип/активность и полные списки сокетов/адресов/Reality. Длина или -1. */
|
||||
int topo_node_build_sig_msg(struct TOPO_NODE* ni, uint8_t* buf, size_t buf_size);
|
||||
|
||||
/** Sign self NODEINFO with Ed25519: build_sig_msg + sc_ed25519_sign → ni->x25519_self_sig */
|
||||
/* Увеличить timestamp, подписать локальный NODEINFO и сохранить снимок в SQLite. 0/-1. */
|
||||
int topo_node_sign_self(struct UTUN_INSTANCE* instance, struct TOPO_NODE* ni);
|
||||
/* Проверить timestamp, привязку node_id к ключу и подпись. 0/-1. */
|
||||
int topo_node_verify(const struct TOPO_NODE* ni);
|
||||
|
||||
static inline const struct TOPO_SOCKMETA4* topo_v4_sock_meta(const struct TOPO_NODE* ni) { return ni->v4_sock_meta; }
|
||||
|
||||
Reference in new issue
Block a user