Document instance ownership, lifecycle, reload and callback contracts
This commit is contained in:
1 parent
f5488adab0
commit
0d14613244
1 file changed
+59
-36
+59
-36
@@ -1,8 +1,9 @@
|
||||
/* utun_instance — владелец ядра и сервисов одного узла.
|
||||
* Ядро содержит транспорт, маршрутизатор, идентичность и общую БД.
|
||||
* create → core_start; UTUN и чат запускаются отдельно через service_start/stop.
|
||||
* Все операции жизненного цикла — в потоке переданного uasync, вне callbacks сервисов.
|
||||
* destroy останавливает сервисы и освобождает ядро, но не сам uasync. */
|
||||
* Все операции — в потоке переданного UASYNC; stop/reload/destroy вне callbacks останавливаемых модулей.
|
||||
* Цикл uasync_poll запускает вызывающий; один UASYNC можно разделять между несколькими instance.
|
||||
* destroy останавливает сервисы и освобождает ядро, но не UASYNC. Подробности: utun_instance_doc.md. */
|
||||
#ifndef UTUN_INSTANCE_H
|
||||
#define UTUN_INSTANCE_H
|
||||
|
||||
@@ -34,8 +35,6 @@ extern "C" {
|
||||
#include "ntp_time.h"
|
||||
#include "ntp_node_time.h"
|
||||
|
||||
#include "etcp_api.h"
|
||||
#include "config_parser.h"
|
||||
#include "topo_group.h"
|
||||
#include "chat/chat_setting.h"
|
||||
#include "chat/chat_event.h"
|
||||
@@ -77,16 +76,16 @@ struct STUN_NAT;
|
||||
struct merkle_sync;
|
||||
|
||||
struct NETWORK_ENTRY {
|
||||
uint64_t id; // 56-bit (offset 0 = index key)
|
||||
uint8_t pubkey[SC_PUBKEY_SIZE]; // 32 bytes binary
|
||||
uint8_t signing_key[SC_PRIVKEY_SIZE]; // 32 bytes binary
|
||||
char name[64];
|
||||
uint64_t id; // 56-битный ID сети; первые 7 байт — ключ индекса
|
||||
uint8_t pubkey[SC_PUBKEY_SIZE]; // бинарный публичный ключ сети
|
||||
uint8_t signing_key[SC_PRIVKEY_SIZE]; // бинарный ключ подписи сети
|
||||
char name[64]; // имя [network:name], ASCIIZ
|
||||
};
|
||||
|
||||
// Queue entry for instance->connections (indexed by peer_node_id)
|
||||
struct conn_queue_entry {
|
||||
uint64_t peer_node_id;
|
||||
struct ETCP_CONN* conn;
|
||||
uint64_t peer_node_id; // ключ индекса, 0 до определения пира
|
||||
struct ETCP_CONN* conn; // живой транспорт; удаляется при close
|
||||
};
|
||||
|
||||
/* Постоянный транспорт ядра к пиру [client]; UTUN приобретает отдельный групповой запрос.
|
||||
@@ -112,9 +111,9 @@ struct tcp_conn_entry {
|
||||
// подписчикам (topo_group, keepalive и т.д.) при каждом изменении активности.
|
||||
typedef void (*utun_activity_cbk_fn)(struct UTUN_INSTANCE* instance, int active, void* arg);
|
||||
struct utun_activity_cbk_entry {
|
||||
utun_activity_cbk_fn fn;
|
||||
void* arg;
|
||||
struct utun_activity_cbk_entry* next;
|
||||
utun_activity_cbk_fn fn; // синхронный обработчик эффективной активности
|
||||
void* arg; // заимствованный контекст обработчика
|
||||
struct utun_activity_cbk_entry* next; // следующая подписка
|
||||
uint8_t removed; // tombstone до выхода из внешней рассылки
|
||||
};
|
||||
|
||||
@@ -123,16 +122,16 @@ struct utun_activity_cbk_entry {
|
||||
// sleeping=1 — пир ушёл в спячку (в фон), 0 — проснулся (дедлайн истёк / обычный keepalive).
|
||||
typedef void (*peer_sleep_cbk_fn)(struct UTUN_INSTANCE* instance, uint64_t peer_node_id, int sleeping, void* arg);
|
||||
struct peer_sleep_cbk_entry {
|
||||
peer_sleep_cbk_fn fn;
|
||||
void* arg;
|
||||
struct peer_sleep_cbk_entry* next;
|
||||
peer_sleep_cbk_fn fn; // синхронный обработчик sleep/wake пира
|
||||
void* arg; // заимствованный контекст обработчика
|
||||
struct peer_sleep_cbk_entry* next; // следующая подписка
|
||||
uint8_t removed; // снятая подписка не вызывается, память удерживает текущая рассылка
|
||||
};
|
||||
|
||||
// Состояние одного узла. Вложенные модули освобождаются через их lifecycle API.
|
||||
struct UTUN_INSTANCE {
|
||||
struct etcp_tx_history tx_history;
|
||||
struct reality_owner reality_owner;
|
||||
struct etcp_tx_history tx_history; // секундное окно ACK всех транспортов ядра
|
||||
struct reality_owner reality_owner; // relay и replay-кеш REALITY данного ядра
|
||||
uint8_t core_started, utun_started, chat_started; // успешный запуск ядра / UTUN / чата
|
||||
uint8_t destroying; // запрещает повторный запуск ядра/повторное destroy во время очистки
|
||||
|
||||
@@ -150,7 +149,7 @@ struct UTUN_INSTANCE {
|
||||
|
||||
struct ROUTE_TABLE* rt; // таблица маршрутов подсетей
|
||||
struct TOPO_GROUPS* topo_groups; // Groups module for topology exchange
|
||||
sqlite3* topo_sqlite_db; // Shared SQLite DB (nodes/channels/peers)
|
||||
sqlite3* topo_sqlite_db; // собственная общая SQLite; открывается при create с топологией
|
||||
struct NAT_DETECTION* nat_det; // NAT detection module
|
||||
struct STUN_NAT* stun_nat; // независимая локальная STUN-диагностика UDP
|
||||
struct stun_ports* stun_port_history; // ранее использованные STUN-порты; переживает reload config
|
||||
@@ -164,17 +163,17 @@ struct UTUN_INSTANCE {
|
||||
uint8_t my_ed25519_pubkey[SC_PUBKEY_SIZE]; // свой Ed25519 pubkey (для подписи метрик)
|
||||
uint8_t my_ed25519_privkey[SC_PRIVKEY_SIZE]; // свой Ed25519 privkey (derived from X25519)
|
||||
|
||||
uint8_t next_socket_id; // Counter for unique socket IDs (0-255)
|
||||
uint8_t next_socket_id; // начало поиска свободного ID 0..255; поколение различает повторное использование
|
||||
|
||||
// Заимствованный цикл событий: создаёт и уничтожает вызывающий.
|
||||
struct UASYNC* ua;
|
||||
|
||||
// State
|
||||
int running; // продолжать utun_instance_run; не флаг готовности сервисов
|
||||
int running; // продолжать цикл приложения; готовность задают отдельные *_started
|
||||
|
||||
// Connections (очередь всех подключений для instance)
|
||||
struct ll_queue* connections; // indexed by peer_node_id (0=pending), data=conn_queue_entry
|
||||
struct ll_queue* tcp_connections; // indexed by node_id, data=tcp_conn_entry [TCP-only]
|
||||
struct ll_queue* tcp_connections; // старый TCP-реестр tcp_conn_entry, fallback instance_find_conn; обычный STCP живёт в links
|
||||
|
||||
// Callback chain for new ETCP connections
|
||||
struct etcp_inst_cbk_entry* new_conn_cbks;
|
||||
@@ -224,7 +223,7 @@ struct UTUN_INSTANCE {
|
||||
// Media async engine (thread-per-task for crypto/file ops)
|
||||
struct media_async* media_async;
|
||||
|
||||
// Socket initialization status: 0=OK, 1=partial (some sockets failed), -1=error (none created)
|
||||
// Последний результат init/reload endpoint: 0=успех, -1=ошибка хотя бы одного обязательного endpoint.
|
||||
int socket_init_status;
|
||||
|
||||
// TCP proxy client (optional, NULL if not enabled)
|
||||
@@ -301,47 +300,71 @@ struct UTUN_INSTANCE {
|
||||
uint8_t ncd_control_bound; // 1 = etcp_bind(ETCP_ID_NCD_CONTROL) сделан
|
||||
};
|
||||
|
||||
// Создать ядро по файлу конфигурации; NULL при ошибке. Сервисы ещё не запущены.
|
||||
/* Создать ядро: ua заимствован, config_file — обязательный путь. Файл может создаваться/нормализоваться updater.
|
||||
* Уже открывает listeners, SQLite/топологию, router/proxy и мониторинг; core/UTUN/chat ещё не запущены.
|
||||
* Возвращает instance либо NULL с освобождением частично созданных ресурсов. */
|
||||
struct UTUN_INSTANCE* utun_instance_create(struct UASYNC* ua, const char* config_file);
|
||||
// При успехе забирает config; при ошибке config остаётся у вызывающего.
|
||||
/* Как create, но без updater и файлового parse: config должен содержать корректные ключи.
|
||||
* Успех передаёт владение config ядру; при NULL config остаётся caller (node_id мог быть исправлен).
|
||||
* log_file и debug меняют общий logger процесса даже при последующем отказе создания. */
|
||||
struct UTUN_INSTANCE* utun_instance_create_from_config(struct UASYNC* ua, struct utun_config* config);
|
||||
// Как create, но конфигурация передана строкой; строку не сохраняет.
|
||||
/* Как create из ASCIIZ config_text; строка заимствована лишь на вызов. Использует mkstemp в /tmp,
|
||||
* updater и файловый parse, затем unlink. Нужна доступная ФС; ошибки дают NULL. */
|
||||
struct UTUN_INSTANCE* utun_instance_create_from_str(struct UASYNC* ua, const char* config_text);
|
||||
// Остановить сервисы и освободить instance. Переданный uasync остаётся у вызывающего.
|
||||
/* Остановить сервисы/транспорт и освободить instance/config; NULL допустим. UASYNC остаётся caller.
|
||||
* Выполняет drain отложенных callbacks и join media workers; вызывать вне callbacks и без параллельных обращений.
|
||||
* Заимствованные SQLite statements/backup должны быть закрыты caller; BUSY логируется и переводится в close_v2. */
|
||||
void utun_instance_destroy(struct UTUN_INSTANCE* instance);
|
||||
/* Запустить общие сетевые службы и постоянные транспорты [client], без членства в группах. Повтор допустим; 0/-1. */
|
||||
/* Запустить репликацию, NCD/keepalive, [client], control и время; без вступления в группы. Успех: running=core_started=1.
|
||||
* Повтор успешного start — 0. Ошибка — -1; уже подготовленные ресурсы остаются для retry/destroy.
|
||||
* Отказ NTP/STUN не фатален. NULL/разрушаемый instance отклоняется. */
|
||||
int utun_core_start(struct UTUN_INSTANCE* instance);
|
||||
/* Запустить UTUN-группу, TUN/NAT по конфигу и групповые запросы к настроенным пирам. Нужен core_start; 0/-1. */
|
||||
/* Запустить UTUN-группу, TUN/NAT по конфигу и отдельные запросы к [client]. Нужны core_start и топология.
|
||||
* 0 — успех/уже запущен; -1 — откат ресурсов UTUN, ядро и чат сохраняются. */
|
||||
int utun_service_start(struct UTUN_INSTANCE* instance);
|
||||
/* Остановить UTUN, сохранив ядро и чат. Повтор допустим. */
|
||||
void utun_service_stop(struct UTUN_INSTANCE* instance);
|
||||
/* Запустить ядро, UTUN и включённый в конфиге чат. 0/-1. */
|
||||
/* Последовательно core_start → UTUN (при наличии топологии) → чат (chatserver_enabled).
|
||||
* 0/-1; ошибка позднего сервиса сохраняет ранее запущенные сервисы. */
|
||||
int utun_instance_init(struct UTUN_INSTANCE *instance);
|
||||
/* Перечитать конфигурацию, при необходимости пересоздать экземпляр; использовать возвращённый указатель. */
|
||||
/* Перечитать config_file через updater; ua должен совпадать с instance->ua. Всегда использовать результат.
|
||||
* Ошибка подготовки сохраняет прежний указатель. Смена негорячих global/подсетей либо automatic servers
|
||||
* пересоздаёт ядро с прежними core/UTUN/chat/running; ошибка после destroy возвращает NULL.
|
||||
* Ручные endpoints обновляются по имени и всем параметрам, неизменённые сохраняются (включая port=0).
|
||||
* Частичный reload не транзакционный: отказ endpoint логируется, новый config сохраняется для следующего retry. */
|
||||
struct UTUN_INSTANCE *utun_instance_reload(struct UTUN_INSTANCE *instance, struct UASYNC *ua, const char *config_file);
|
||||
/* Выполнять цикл событий до stop(). */
|
||||
void utun_instance_run(struct UTUN_INSTANCE *instance);
|
||||
/* Снять running и разбудить цикл; ресурсы освобождает destroy(), а не stop(). */
|
||||
void utun_instance_stop(struct UTUN_INSTANCE *instance);
|
||||
/* Глобальные переключатели создания TUN/топологии для тестов и встраивания. */
|
||||
/* Общий переключатель TUN (по умолчанию 0): влияет на последующий UTUN start и proxy test mode при create. */
|
||||
void utun_instance_set_tun_init_enabled(int enabled);
|
||||
/* Общий переключатель топологии (по умолчанию 1): влияет на последующие create, включая открытие SQLite. */
|
||||
void utun_instance_set_topo_group_enabled(int enabled);
|
||||
/* Сохраняет желаемый режим frontend; stream owners удерживают ACTIVE до последнего close.
|
||||
* Применяет эффективную активность и мобильный standby до уведомления подписчиков; выполнять в uasync-потоке.
|
||||
* Повторная команда согласует фактический режим без повторного BGP-события. 0 — успех, <0 — ошибка. */
|
||||
* Повторная команда согласует фактический режим без повторного BGP-события. SERVER — успешный no-op.
|
||||
* 0 — успех, -1 — NULL/ошибка standby с откатом режима. phone_state не меняется. */
|
||||
int utun_set_client_activity(struct UTUN_INSTANCE* instance, int active);
|
||||
/* Подписки уникальны по fn+arg, новые идут в голову; arg заимствован. NULL instance/fn — no-op,
|
||||
* OOM логируется без добавления. Remove из callback безопасен; память удерживается до конца внешней рассылки.
|
||||
* Новая подписка не получает уже начатое событие, но участвует во вложенном. Destroy внутри callback запрещён. */
|
||||
void utun_add_activity_cbk(struct UTUN_INSTANCE* instance, utun_activity_cbk_fn fn, void* arg);
|
||||
/* Удалить подписку fn+arg; отсутствие — no-op. Вложенная новая активность отменяет остаток старого события. */
|
||||
void utun_remove_activity_cbk(struct UTUN_INSTANCE* instance, utun_activity_cbk_fn fn, void* arg);
|
||||
/* Аналогичная подписка на peer_node_id/sleeping; nesting исполняется синхронно до продолжения внешней рассылки. */
|
||||
void utun_add_peer_sleep_cbk(struct UTUN_INSTANCE* instance, peer_sleep_cbk_fn fn, void* arg);
|
||||
/* Удалить peer-sleep подписку fn+arg; отсутствие/NULL — no-op. */
|
||||
void utun_remove_peer_sleep_cbk(struct UTUN_INSTANCE* instance, peer_sleep_cbk_fn fn, void* arg);
|
||||
/* Синхронно передать подписчикам node_id и sleeping (1 сон, 0 пробуждение); NULL instance — no-op. */
|
||||
void utun_fire_peer_sleep_cbk(struct UTUN_INSTANCE* instance, uint64_t peer_node_id, int sleeping);
|
||||
|
||||
// Diagnostic function for memory leak analysis
|
||||
/* Вывести sys/info счётчики ресурсов и простые sanity-проверки списков с меткой phase.
|
||||
* Живые ресурсы сами по себе не означают утечку; функция ничего не освобождает. */
|
||||
void utun_instance_diagnose_leaks(struct UTUN_INSTANCE* instance, const char* phase);
|
||||
|
||||
/* Найти транспорт по node_id в реестрах ETCP/TCP. Указатель заимствован.
|
||||
* NULL — не найден; ненулевой результат не гарантирует UP или готовность группы. */
|
||||
static inline struct ETCP_CONN* instance_find_conn(struct UTUN_INSTANCE* inst, uint64_t node_id) {
|
||||
if (!inst) return NULL;
|
||||
if (inst->connections) {
|
||||
struct ll_entry* e = queue_find_data_by_index(inst->connections, (const uint8_t*)&node_id);
|
||||
if (e) return ((struct conn_queue_entry*)e->data)->conn;
|
||||
|
||||
Reference in new issue
Block a user