conn_mgr.h: document in ll_queue style; config_parser/utun_instance updates
This commit is contained in:
1 parent
90ad64a106
commit
59d307f98b
5 files changed
+511
-118
No files matched your search
+60
-4
@@ -47,7 +47,8 @@ typedef enum {
|
||||
SECTION_NAT,
|
||||
SECTION_TCP_PROXY_CLIENT,
|
||||
SECTION_TCP_PROXY_SERVER,
|
||||
SECTION_MSG_TRANSPORT
|
||||
SECTION_MSG_TRANSPORT,
|
||||
SECTION_NETWORK
|
||||
} section_type_t;
|
||||
|
||||
static char* trim(char *str) {
|
||||
@@ -716,6 +717,21 @@ static int parse_client(const char *key, const char *value, struct CFG_CLIENT *c
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int parse_network(const char *key, const char *value, struct CFG_NETWORK *net, const char *filename, int line_num) {
|
||||
if (strcmp(key, "id") == 0) {
|
||||
net->id = strtoull(value, NULL, 16);
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(key, "pubkey") == 0) {
|
||||
return assign_string(net->pubkey_hex, sizeof(net->pubkey_hex), value);
|
||||
}
|
||||
if (strcmp(key, "signing_key") == 0) {
|
||||
return assign_string(net->signing_key_hex, sizeof(net->signing_key_hex), value);
|
||||
}
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "%s:%d: Unknown network option '%s'. Valid: id, pubkey, signing_key", filename, line_num, key);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static section_type_t parse_section_header(const char *line, char *name, size_t name_len) {
|
||||
if (line[0] != '[') return SECTION_UNKNOWN;
|
||||
|
||||
@@ -752,7 +768,8 @@ static section_type_t parse_section_header(const char *line, char *name, size_t
|
||||
|
||||
if (strcasecmp(type, "server") == 0) return SECTION_SERVER;
|
||||
if (strcasecmp(type, "client") == 0) return SECTION_CLIENT;
|
||||
|
||||
if (strcasecmp(type, "network") == 0) return SECTION_NETWORK;
|
||||
|
||||
return SECTION_UNKNOWN;
|
||||
}
|
||||
|
||||
@@ -779,6 +796,7 @@ static struct utun_config* parse_config_internal(FILE *fp, const char *filename)
|
||||
section_type_t cur_section = SECTION_UNKNOWN;
|
||||
struct CFG_SERVER *cur_server = NULL;
|
||||
struct CFG_CLIENT *cur_client = NULL;
|
||||
struct CFG_NETWORK *cur_network = NULL;
|
||||
char line[MAX_LINE_LEN];
|
||||
int line_num = 0;
|
||||
|
||||
@@ -802,6 +820,11 @@ static struct utun_config* parse_config_internal(FILE *fp, const char *filename)
|
||||
cfg->clients = cur_client;
|
||||
cur_client = NULL;
|
||||
}
|
||||
if (cur_section == SECTION_NETWORK && cur_network) {
|
||||
cur_network->next = cfg->networks;
|
||||
cfg->networks = cur_network;
|
||||
cur_network = NULL;
|
||||
}
|
||||
|
||||
char name[MAX_CONN_NAME_LEN];
|
||||
cur_section = parse_section_header(trimmed, name, sizeof(name));
|
||||
@@ -821,6 +844,13 @@ static struct utun_config* parse_config_internal(FILE *fp, const char *filename)
|
||||
goto error;
|
||||
}
|
||||
strcpy(cur_client->name, name);
|
||||
} else if (cur_section == SECTION_NETWORK) {
|
||||
cur_network = u_calloc(1, sizeof(struct CFG_NETWORK));
|
||||
if (!cur_network) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_MEMORY, "parse_config_internal: failed to allocate memory for network %s", name);
|
||||
goto error;
|
||||
}
|
||||
strcpy(cur_network->name, name);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -927,6 +957,11 @@ static struct utun_config* parse_config_internal(FILE *fp, const char *filename)
|
||||
// parse_msg_transport already printed the error
|
||||
}
|
||||
break;
|
||||
case SECTION_NETWORK:
|
||||
if (cur_network && parse_network(key, value, cur_network, filename, line_num) < 0) {
|
||||
// parse_network already printed the error
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEBUG_WARN(DEBUG_CATEGORY_CONFIG, "%s:%d: Key outside section: %s", filename, line_num, key);
|
||||
break;
|
||||
@@ -942,6 +977,10 @@ static struct utun_config* parse_config_internal(FILE *fp, const char *filename)
|
||||
cur_client->next = cfg->clients;
|
||||
cfg->clients = cur_client;
|
||||
}
|
||||
if (cur_section == SECTION_NETWORK && cur_network) {
|
||||
cur_network->next = cfg->networks;
|
||||
cfg->networks = cur_network;
|
||||
}
|
||||
|
||||
// Post-parse defaults: tun_enabled=1 if not explicitly disabled
|
||||
if (!cfg->global.tun_enabled && cfg->global.tun_ifname[0] == '\0' && cfg->global.tun_ip.family == AF_UNSPEC) {
|
||||
@@ -965,6 +1004,7 @@ error:
|
||||
free_cfg_client_links(cur_client->links);
|
||||
u_free(cur_client);
|
||||
}
|
||||
if (cur_network) u_free(cur_network);
|
||||
free_config(cfg);
|
||||
return NULL;
|
||||
}
|
||||
@@ -1003,6 +1043,14 @@ void free_config(struct utun_config *config) {
|
||||
client = next;
|
||||
}
|
||||
|
||||
// Free networks
|
||||
struct CFG_NETWORK *network = config->networks;
|
||||
while (network) {
|
||||
struct CFG_NETWORK *next = network->next;
|
||||
u_free(network);
|
||||
network = next;
|
||||
}
|
||||
|
||||
// Free route entries
|
||||
free_route_entries(config->route_subnets);
|
||||
free_route_entries(config->my_subnets);
|
||||
@@ -1097,8 +1145,16 @@ void print_config(const struct utun_config *cfg) {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_CONFIG, " allow=%s", ip_str);
|
||||
} else {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_CONFIG, " allow=%s:%d", ip_str, r->port);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "Networks:");
|
||||
struct CFG_NETWORK *net = cfg->networks;
|
||||
while (net) {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_CONFIG, " [network:%s] id=%012llx pubkey=%.64s signing_key=%.64s",
|
||||
net->name, (unsigned long long)net->id, net->pubkey_hex, net->signing_key_hex);
|
||||
net = net->next;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_CONFIG, " no rules");
|
||||
}
|
||||
|
||||
@@ -62,6 +62,14 @@ struct CFG_CLIENT {
|
||||
struct CFG_CLIENT *next; // Next client in linked list
|
||||
};
|
||||
|
||||
struct CFG_NETWORK {
|
||||
struct CFG_NETWORK* next;
|
||||
char name[64];
|
||||
uint64_t id; // 56-bit network ID
|
||||
char pubkey_hex[SC_PUBKEY_SIZE * 2 + 1]; // 64 hex chars
|
||||
char signing_key_hex[SC_PRIVKEY_SIZE * 2 + 1]; // 64 hex chars
|
||||
};
|
||||
|
||||
struct CFG_ROUTE_ENTRY {
|
||||
struct CFG_ROUTE_ENTRY* next;
|
||||
struct IP ip;
|
||||
@@ -180,6 +188,7 @@ struct utun_config {
|
||||
struct CFG_CLIENT* clients;
|
||||
struct CFG_ROUTE_ENTRY* route_subnets;
|
||||
struct CFG_ROUTE_ENTRY* my_subnets;
|
||||
struct CFG_NETWORK* networks;
|
||||
};
|
||||
|
||||
struct utun_config* parse_config(const char *filename);
|
||||
|
||||
+363
-114
@@ -13,178 +13,427 @@ struct ETCP_CONN;
|
||||
struct NODEINFO_Q;
|
||||
struct ROUTE_BGP;
|
||||
|
||||
#define CONN_MGR_MAX_CANDIDATES 3
|
||||
#define CONN_MGR_CANDIDATE_CACHE_MS 20000
|
||||
#define CONN_MGR_CANDIDATE_STALE_TB 300000
|
||||
#define CONN_MGR_CANDIDATE_PING_TB 20000
|
||||
#define CONN_MGR_BG_PING_INTERVAL_TB 1000
|
||||
#define CONN_MGR_BG_PING_CYCLE_MIN_TB 100000
|
||||
#define CONN_MGR_IDLE_CHECK_INTERVAL_TB 10000
|
||||
#define CONN_MGR_LOCAL_SCAN_ATTEMPTS 3
|
||||
#define CONN_MGR_LOCAL_SCAN_TIMEOUT_MS 100
|
||||
#define CONN_MGR_CONNECT_DIRECT_TIMEOUT_MS 5000
|
||||
#define CONN_MGR_CONNECT_REVERSE_TIMEOUT_MS 15000
|
||||
#define CONN_MGR_INTERM_EXCHANGE_TIMEOUT_MS 15000
|
||||
/**
|
||||
* @file conn_mgr.h
|
||||
* @brief Менеджер установки соединений. Трёхфазная машина подключения к нодам
|
||||
* с выбором оптимального пути: прямой → обратный → через посредников.
|
||||
*
|
||||
* Основные возможности:
|
||||
* - Автоматический выбор лучшего способа подключения к целевой ноде
|
||||
* - Фаза 1 (DIRECT): попытка прямого INIT-рукопожатия на все известные IPv4-адреса цели.
|
||||
* Итерация по парам (наш сокет, целевой адрес) с проверкой NAT-совместимости.
|
||||
* Таймаут: CONN_MGR_CONNECT_DIRECT_TIMEOUT_MS
|
||||
* - Фаза 2 (REVERSE): если у нас есть прямой IP, а у цели нет — отправляем DIRECT_REQ
|
||||
* с нашими адресами через BGP-маршрут. Цель сама инициирует INIT в нашу сторону.
|
||||
* Таймаут: CONN_MGR_CONNECT_REVERSE_TIMEOUT_MS
|
||||
* - Фаза 3 (INDIRECT): если DIRECT и REVERSE не сработали — обмениваемся через BGP
|
||||
* списками лучших промежуточных узлов-кандидатов с RTT, выбираем общих с минимальным
|
||||
* суммарным RTT. Трафик идёт через etcp_router (транзитная ретрансляция).
|
||||
* Таймаут: CONN_MGR_INTERM_EXCHANGE_TIMEOUT_MS
|
||||
* - Фоновое сканирование локальной сети (broadcast/multicast UDP-ping)
|
||||
* - Фоновое поддержание списка лучших кандидатов-посредников (периодический ping,
|
||||
* удаление stale-кандидатов)
|
||||
* - Фоновый обход всех известных BGP-нод для поддержания RTT-замеров
|
||||
* - Управление idle-таймаутом с автоматическим разрывом неактивных соединений
|
||||
*
|
||||
* @note Правила использования:
|
||||
* 1. conn_mgr_init() вызывается один раз при старте экземпляра utun
|
||||
* 2. conn_mgr_connect_node() — асинхронный вызов, результат приходит в callback
|
||||
* 3. Повторный вызов conn_mgr_connect_node для уже подключённой ноды вернёт
|
||||
* CONN_MGR_ERR_ALREADY_CONNECTED; для ноды в состоянии CONNECTING добавит
|
||||
* дополнительный callback в список
|
||||
* 4. conn_mgr_disconnect_node() отправляет DISCONNECT-пакет целевой ноде и
|
||||
* сбрасывает conn_mgr_type в NODEINFO_Q
|
||||
* 5. Для alien-нод (подключившихся к нам самостоятельно) используется
|
||||
* conn_mgr_add_alien_node() вместо conn_mgr_connect_node()
|
||||
* 6. conn_mgr_update_best_candidates() вызывается извне (обычно из route_connectivity)
|
||||
* для обновления RTT кандидатов
|
||||
*
|
||||
* @note Внутренние таймеры (всё в timebase-единицах, 1 tb = 0.1 мс):
|
||||
* - bg_ping_timer: фоновый ping нод (CONN_MGR_BG_PING_INTERVAL_TB)
|
||||
* - candidate_ping_timer: обновление RTT кандидатов (CONN_MGR_CANDIDATE_PING_TB)
|
||||
* - idle_timer: проверка неактивности подключённых нод (CONN_MGR_IDLE_CHECK_INTERVAL_TB)
|
||||
*/
|
||||
|
||||
#define CONN_MGR_OK 0
|
||||
#define CONN_MGR_ERR_NOT_FOUND -1
|
||||
#define CONN_MGR_ERR_NO_ADDRESSES -2
|
||||
#define CONN_MGR_ERR_TIMEOUT -3
|
||||
#define CONN_MGR_ERR_UNREACHABLE -4
|
||||
#define CONN_MGR_ERR_REFUSED -5
|
||||
#define CONN_MGR_ERR_ALREADY_CONNECTED -6
|
||||
#define CONN_MGR_ERR_INTERNAL -7
|
||||
/* ==================== Константы и лимиты ==================== */
|
||||
|
||||
#define CONN_MGR_MAX_CANDIDATES 3 ///< Макс. число лучших кандидатов-посредников
|
||||
#define CONN_MGR_CANDIDATE_CACHE_MS 20000 ///< Время жизни кандидата в кеше (мс) — не используется напрямую в .h
|
||||
#define CONN_MGR_CANDIDATE_STALE_TB 300000 ///< Порог устаревания кандидата (tb), после которого удаляется из списка
|
||||
#define CONN_MGR_CANDIDATE_PING_TB 20000 ///< Интервал фонового ping кандидатов (tb, ~2 сек)
|
||||
#define CONN_MGR_BG_PING_INTERVAL_TB 1000 ///< Интервал фонового ping BGP-нод (tb, ~100 мс)
|
||||
#define CONN_MGR_BG_PING_CYCLE_MIN_TB 100000 ///< Минимальная длительность полного цикла обхода нод (tb, ~10 сек)
|
||||
#define CONN_MGR_IDLE_CHECK_INTERVAL_TB 10000 ///< Интервал проверки idle-таймаута (tb, ~1 сек)
|
||||
#define CONN_MGR_LOCAL_SCAN_ATTEMPTS 3 ///< Число попыток локального сканирования
|
||||
#define CONN_MGR_LOCAL_SCAN_TIMEOUT_MS 100 ///< Таймаут локального сканирования (мс)
|
||||
#define CONN_MGR_CONNECT_DIRECT_TIMEOUT_MS 5000 ///< Таймаут фазы DIRECT (мс)
|
||||
#define CONN_MGR_CONNECT_REVERSE_TIMEOUT_MS 15000 ///< Таймаут фазы REVERSE (мс)
|
||||
#define CONN_MGR_INTERM_EXCHANGE_TIMEOUT_MS 15000 ///< Таймаут фазы INDIRECT (мс)
|
||||
|
||||
/* ==================== Коды возврата ==================== */
|
||||
|
||||
#define CONN_MGR_OK 0 ///< Успех
|
||||
#define CONN_MGR_ERR_NOT_FOUND -1 ///< Нода не найдена в BGP
|
||||
#define CONN_MGR_ERR_NO_ADDRESSES -2 ///< Нет известных адресов для подключения
|
||||
#define CONN_MGR_ERR_TIMEOUT -3 ///< Таймаут соединения
|
||||
#define CONN_MGR_ERR_UNREACHABLE -4 ///< Нода недостижима (все фазы провалились)
|
||||
#define CONN_MGR_ERR_REFUSED -5 ///< Соединение отклонено (зарезервировано)
|
||||
#define CONN_MGR_ERR_ALREADY_CONNECTED -6 ///< Уже подключены
|
||||
#define CONN_MGR_ERR_INTERNAL -7 ///< Внутренняя ошибка
|
||||
|
||||
/* ==================== Состояния ==================== */
|
||||
|
||||
/**
|
||||
* @enum CONN_MGR_STATE
|
||||
* @brief Состояние подключения к ноде.
|
||||
*/
|
||||
enum CONN_MGR_STATE {
|
||||
CONN_MGR_STATE_DISCONNECTED = 0,
|
||||
CONN_MGR_STATE_CONNECTING = 1,
|
||||
CONN_MGR_STATE_CONNECTED = 2,
|
||||
CONN_MGR_STATE_DISCONNECTED = 0, ///< Не подключены
|
||||
CONN_MGR_STATE_CONNECTING = 1, ///< В процессе установки соединения
|
||||
CONN_MGR_STATE_CONNECTED = 2, ///< Подключены
|
||||
};
|
||||
|
||||
/**
|
||||
* @enum CM_TRY_STATE
|
||||
* @brief Состояние отдельной попытки (локальное сканирование / основное подключение).
|
||||
*/
|
||||
enum CM_TRY_STATE {
|
||||
CM_TRY_NONE = 0,
|
||||
CM_TRY_PENDING = 1,
|
||||
CM_TRY_OK = 2,
|
||||
CM_TRY_FAILED = 3,
|
||||
CM_TRY_NONE = 0, ///< Попытка не начиналась
|
||||
CM_TRY_PENDING = 1, ///< Попытка в процессе
|
||||
CM_TRY_OK = 2, ///< Попытка успешна
|
||||
CM_TRY_FAILED = 3, ///< Попытка провалилась
|
||||
};
|
||||
|
||||
#define CONN_MGR_SUBCMD_DIRECT_REQ 0x01
|
||||
#define CONN_MGR_SUBCMD_DIRECT_RESP 0x02
|
||||
#define CONN_MGR_SUBCMD_INTERM_EXCHANGE_REQ 0x03
|
||||
#define CONN_MGR_SUBCMD_INTERM_EXCHANGE_RESP 0x04
|
||||
#define CONN_MGR_SUBCMD_INTERM_SELECTED 0x05
|
||||
#define CONN_MGR_SUBCMD_DISCONNECT 0x06
|
||||
/* ==================== Протокол CONN_MGR (ETCP_RT_ID_CONN_MGR = 0x11) ==================== */
|
||||
|
||||
/**
|
||||
* @defgroup conn_mgr_subcmd Подкоманды протокола CONN_MGR
|
||||
* @{
|
||||
*/
|
||||
#define CONN_MGR_SUBCMD_DIRECT_REQ 0x01 ///< "Я за NAT, подключись ко мне" — передача наших адресов цели
|
||||
#define CONN_MGR_SUBCMD_DIRECT_RESP 0x02 ///< Ответ на DIRECT_REQ (зарезервирован, не реализован)
|
||||
#define CONN_MGR_SUBCMD_INTERM_EXCHANGE_REQ 0x03 ///< Запрос обмена кандидатами-посредниками
|
||||
#define CONN_MGR_SUBCMD_INTERM_EXCHANGE_RESP 0x04 ///< Ответ с нашими кандидатами + замеры RTT до кандидатов инициатора
|
||||
#define CONN_MGR_SUBCMD_INTERM_SELECTED 0x05 ///< Выбранные посредники (финальный шаг INDIRECT-фазы)
|
||||
#define CONN_MGR_SUBCMD_DISCONNECT 0x06 ///< Уведомление о разрыве соединения
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @struct CONN_MGR_CANDIDATE
|
||||
* @brief Запись о кандидате-посреднике: идентификатор ноды + RTT до неё.
|
||||
*
|
||||
* Используется в списке best_candidates и во всех пакетах обмена кандидатами.
|
||||
*/
|
||||
struct CONN_MGR_CANDIDATE {
|
||||
uint64_t node_id;
|
||||
uint16_t rtt;
|
||||
uint64_t node_id; ///< Идентификатор ноды-кандидата
|
||||
uint16_t rtt; ///< RTT до кандидата (мс)
|
||||
} __attribute__((packed));
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
/**
|
||||
* @struct CONN_MGR_DIRECT_REQ
|
||||
* @brief Пакет фазы REVERSE: "подключись ко мне".
|
||||
*
|
||||
* Отправляется когда мы имеем прямой IP, но цель за NAT.
|
||||
* Содержит наши адреса, по которым цель должна инициировать INIT.
|
||||
*/
|
||||
struct CONN_MGR_DIRECT_REQ {
|
||||
uint8_t cmd;
|
||||
uint8_t subcmd;
|
||||
uint32_t request_id;
|
||||
uint8_t addr_count;
|
||||
uint8_t cmd; ///< ETCP_RT_ID_CONN_MGR
|
||||
uint8_t subcmd; ///< CONN_MGR_SUBCMD_DIRECT_REQ
|
||||
uint32_t request_id; ///< Идентификатор запроса для сопоставления ответа
|
||||
uint8_t addr_count; ///< Количество адресов, следующих за заголовком
|
||||
/* далее: addr_count записей по 8 байт каждая (type:1, ip:4, port:2, sock_id:1) */
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct CONN_MGR_DIRECT_RESP
|
||||
* @brief Ответ на DIRECT_REQ (зарезервирован, не отправляется).
|
||||
*/
|
||||
struct CONN_MGR_DIRECT_RESP {
|
||||
uint8_t cmd;
|
||||
uint8_t subcmd;
|
||||
uint32_t request_id;
|
||||
uint8_t accepted;
|
||||
uint8_t cmd; ///< ETCP_RT_ID_CONN_MGR
|
||||
uint8_t subcmd; ///< CONN_MGR_SUBCMD_DIRECT_RESP
|
||||
uint32_t request_id; ///< Идентификатор запроса
|
||||
uint8_t accepted; ///< 1 — принято, 0 — отклонено
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct CONN_MGR_INTERM_EXCHANGE_REQ
|
||||
* @brief Запрос обмена списками кандидатов-посредников (фаза INDIRECT, инициатор).
|
||||
*
|
||||
* Инициатор отправляет свой топ-4 кандидатов. Цель должна ответить
|
||||
* CONN_MGR_INTERM_EXCHANGE_RESP со своими кандидатами и замерами RTT до наших.
|
||||
*/
|
||||
struct CONN_MGR_INTERM_EXCHANGE_REQ {
|
||||
uint8_t cmd;
|
||||
uint8_t subcmd;
|
||||
uint32_t request_id;
|
||||
uint8_t candidate_count;
|
||||
struct CONN_MGR_CANDIDATE candidates[4];
|
||||
uint8_t cmd; ///< ETCP_RT_ID_CONN_MGR
|
||||
uint8_t subcmd; ///< CONN_MGR_SUBCMD_INTERM_EXCHANGE_REQ
|
||||
uint32_t request_id; ///< Идентификатор запроса
|
||||
uint8_t candidate_count; ///< Количество кандидатов в массиве (≤4)
|
||||
struct CONN_MGR_CANDIDATE candidates[4]; ///< Наши лучшие кандидаты с RTT
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct CONN_MGR_INTERM_EXCHANGE_RESP
|
||||
* @brief Ответ на INTERM_EXCHANGE_REQ (фаза INDIRECT, цель).
|
||||
*
|
||||
* Содержит два списка:
|
||||
* - my_candidates: лучшие кандидаты цели с RTT до них (измеренным целью)
|
||||
* - your_candidates: кандидаты инициатора, но с RTT, измеренным со стороны цели
|
||||
*/
|
||||
struct CONN_MGR_INTERM_EXCHANGE_RESP {
|
||||
uint8_t cmd;
|
||||
uint8_t subcmd;
|
||||
uint32_t request_id;
|
||||
uint8_t my_count;
|
||||
uint8_t your_count;
|
||||
struct CONN_MGR_CANDIDATE my_candidates[4];
|
||||
struct CONN_MGR_CANDIDATE your_candidates[4];
|
||||
uint8_t cmd; ///< ETCP_RT_ID_CONN_MGR
|
||||
uint8_t subcmd; ///< CONN_MGR_SUBCMD_INTERM_EXCHANGE_RESP
|
||||
uint32_t request_id; ///< Идентификатор запроса
|
||||
uint8_t my_count; ///< Количество наших кандидатов (≤4)
|
||||
uint8_t your_count; ///< Количество кандидатов инициатора (≤4)
|
||||
struct CONN_MGR_CANDIDATE my_candidates[4]; ///< Наши кандидаты + наш RTT до них
|
||||
struct CONN_MGR_CANDIDATE your_candidates[4]; ///< Кандидаты инициатора + наш RTT до них
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct CONN_MGR_INTERM_SELECTED
|
||||
* @brief Финальный выбор посредников (фаза INDIRECT).
|
||||
*
|
||||
* Инициатор вычисляет лучших общих посредников по сумме RTT
|
||||
* и отправляет выбранный список цели.
|
||||
*/
|
||||
struct CONN_MGR_INTERM_SELECTED {
|
||||
uint8_t cmd;
|
||||
uint8_t subcmd;
|
||||
uint32_t request_id;
|
||||
uint8_t count;
|
||||
struct CONN_MGR_CANDIDATE selected[3];
|
||||
uint8_t cmd; ///< ETCP_RT_ID_CONN_MGR
|
||||
uint8_t subcmd; ///< CONN_MGR_SUBCMD_INTERM_SELECTED
|
||||
uint32_t request_id; ///< Идентификатор запроса (всегда 0 для извещения)
|
||||
uint8_t count; ///< Количество выбранных посредников (≤3)
|
||||
struct CONN_MGR_CANDIDATE selected[3]; ///< Выбранные посредники (node_id + RTT от нас до них)
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct CONN_MGR_DISCONNECT
|
||||
* @brief Уведомление о разрыве соединения.
|
||||
*/
|
||||
struct CONN_MGR_DISCONNECT {
|
||||
uint8_t cmd;
|
||||
uint8_t subcmd;
|
||||
uint64_t node_id;
|
||||
uint8_t cmd; ///< ETCP_RT_ID_CONN_MGR
|
||||
uint8_t subcmd; ///< CONN_MGR_SUBCMD_DISCONNECT
|
||||
uint64_t node_id; ///< Идентификатор ноды, с которой разрываем соединение
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#define CONN_MGR_DIRECT_REQ_HDR_SIZE sizeof(struct CONN_MGR_DIRECT_REQ)
|
||||
#define CONN_MGR_DIRECT_RESP_HDR_SIZE sizeof(struct CONN_MGR_DIRECT_RESP)
|
||||
#define CONN_MGR_INTERM_EXCHANGE_REQ_SIZE sizeof(struct CONN_MGR_INTERM_EXCHANGE_REQ)
|
||||
#define CONN_MGR_INTERM_EXCHANGE_RESP_SIZE sizeof(struct CONN_MGR_INTERM_EXCHANGE_RESP)
|
||||
#define CONN_MGR_INTERM_SELECTED_SIZE sizeof(struct CONN_MGR_INTERM_SELECTED)
|
||||
#define CONN_MGR_DISCONNECT_SIZE sizeof(struct CONN_MGR_DISCONNECT)
|
||||
/* ==================== Размеры пакетов протокола ==================== */
|
||||
|
||||
#define CONN_MGR_DIRECT_REQ_HDR_SIZE sizeof(struct CONN_MGR_DIRECT_REQ) ///< Размер заголовка DIRECT_REQ (без addr_count адресов)
|
||||
#define CONN_MGR_DIRECT_RESP_HDR_SIZE sizeof(struct CONN_MGR_DIRECT_RESP) ///< Размер DIRECT_RESP
|
||||
#define CONN_MGR_INTERM_EXCHANGE_REQ_SIZE sizeof(struct CONN_MGR_INTERM_EXCHANGE_REQ) ///< Размер INTERM_EXCHANGE_REQ
|
||||
#define CONN_MGR_INTERM_EXCHANGE_RESP_SIZE sizeof(struct CONN_MGR_INTERM_EXCHANGE_RESP) ///< Размер INTERM_EXCHANGE_RESP (макс.)
|
||||
#define CONN_MGR_INTERM_SELECTED_SIZE sizeof(struct CONN_MGR_INTERM_SELECTED) ///< Размер INTERM_SELECTED
|
||||
#define CONN_MGR_DISCONNECT_SIZE sizeof(struct CONN_MGR_DISCONNECT) ///< Размер DISCONNECT
|
||||
|
||||
/* ==================== Callback-типы и внутренние структуры ==================== */
|
||||
|
||||
/**
|
||||
* @typedef conn_mgr_connect_callback_t
|
||||
* @brief Callback результата подключения.
|
||||
* @param result код возврата (CONN_MGR_OK или CONN_MGR_ERR_*)
|
||||
* @param node_id идентификатор ноды
|
||||
* @param arg пользовательский аргумент
|
||||
*/
|
||||
typedef void (*conn_mgr_connect_callback_t)(int result, uint64_t node_id, void* arg);
|
||||
|
||||
/**
|
||||
* @struct cm_cb_node
|
||||
* @brief Узел связного списка callback'ов для одной ноды.
|
||||
*
|
||||
* Позволяет регистрировать несколько callback'ов на одно подключение.
|
||||
* Новые callback'и добавляются в начало списка.
|
||||
*/
|
||||
struct cm_cb_node {
|
||||
conn_mgr_connect_callback_t cb;
|
||||
void* arg;
|
||||
struct cm_cb_node* next;
|
||||
conn_mgr_connect_callback_t cb; ///< Функция-callback
|
||||
void* arg; ///< Пользовательский аргумент
|
||||
struct cm_cb_node* next; ///< Следующий callback в списке
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct CONN_MGR_ENTRY
|
||||
* @brief Запись о подключении к одной ноде.
|
||||
*
|
||||
* Хранит состояние трёхфазной машины, список выбранных посредников,
|
||||
* idle-таймер и список ожидающих callback'ов.
|
||||
*/
|
||||
struct CONN_MGR_ENTRY {
|
||||
uint64_t node_id;
|
||||
uint8_t state;
|
||||
uint8_t conn_type;
|
||||
uint8_t alien;
|
||||
uint32_t idle_timeout_ms;
|
||||
uint64_t last_traffic_tb;
|
||||
void* idle_timer;
|
||||
uint64_t node_id; ///< Идентификатор целевой ноды
|
||||
uint8_t state; ///< Текущее состояние (enum CONN_MGR_STATE)
|
||||
uint8_t conn_type; ///< Тип соединения (CONN_TYPE_DIRECT/REVERSE/INDIRECT)
|
||||
uint8_t alien; ///< 1 — alien-нода (сама подключилась к нам), 0 — мы инициаторы
|
||||
uint32_t idle_timeout_ms; ///< Таймаут неактивности (мс), 0 — без таймаута
|
||||
uint64_t last_traffic_tb; ///< Время последнего трафика (tb) для idle-проверки
|
||||
void* idle_timer; ///< Хендл таймера idle-проверки
|
||||
|
||||
struct cm_cb_node* cb_list;
|
||||
struct cm_cb_node* cb_list; ///< Связный список callback'ов результата
|
||||
|
||||
uint64_t intermediaries[CONN_MGR_MAX_INTERMEDIARIES];
|
||||
uint8_t intermediariy_count;
|
||||
uint8_t rr_idx;
|
||||
uint64_t intermediaries[CONN_MGR_MAX_INTERMEDIARIES]; ///< Выбранные посредники (node_id)
|
||||
uint8_t intermediariy_count; ///< Количество выбранных посредников
|
||||
uint8_t rr_idx; ///< Round-robin индекс для выбора посредника при отправке
|
||||
|
||||
uint8_t local_scan_state;
|
||||
uint8_t main_connect_state;
|
||||
uint8_t local_scan_state; ///< Состояние локального сканирования (enum CM_TRY_STATE)
|
||||
uint8_t main_connect_state; ///< Состояние основного подключения (enum CM_TRY_STATE)
|
||||
struct {
|
||||
uint8_t phase;
|
||||
void* timer;
|
||||
uint32_t request_id;
|
||||
void* conn_ctx;
|
||||
uint8_t phase; ///< Текущая фаза: 1=DIRECT, 2=REVERSE, 3=INDIRECT
|
||||
void* timer; ///< Хендл таймера текущей фазы
|
||||
uint32_t request_id; ///< request_id для INDIRECT-обмена
|
||||
void* conn_ctx; ///< Контекст ETCP-соединения (для REVERSE)
|
||||
} main;
|
||||
|
||||
struct CONN_MGR* mgr;
|
||||
struct CONN_MGR* mgr; ///< Обратная ссылка на менеджер
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct CONN_MGR
|
||||
* @brief Корневая структура менеджера соединений.
|
||||
*
|
||||
* Создаётся один раз в conn_mgr_init(), хранится в UTUN_INSTANCE.
|
||||
* Содержит динамический массив entries, список лучших кандидатов,
|
||||
* таймеры фонового ping и список ожидающих обменов (reverse/exchange pending).
|
||||
*/
|
||||
struct CONN_MGR {
|
||||
struct UTUN_INSTANCE* instance;
|
||||
struct CONN_MGR_ENTRY* entries;
|
||||
size_t entry_count;
|
||||
size_t entry_capacity;
|
||||
struct UTUN_INSTANCE* instance; ///< Родительский экземпляр utun
|
||||
|
||||
void* bg_ping_timer;
|
||||
size_t bg_ping_cursor;
|
||||
uint64_t bg_ping_cycle_start_tb;
|
||||
struct CONN_MGR_ENTRY* entries; ///< Динамический массив записей о подключениях
|
||||
size_t entry_count; ///< Текущее количество записей
|
||||
size_t entry_capacity; ///< Выделенная ёмкость массива entries
|
||||
|
||||
void* candidate_ping_timer;
|
||||
void* bg_ping_timer; ///< Хендл таймера фонового ping BGP-нод
|
||||
size_t bg_ping_cursor; ///< Курсор текущей ноды в цикле обхода
|
||||
uint64_t bg_ping_cycle_start_tb; ///< Время старта текущего цикла обхода (tb)
|
||||
|
||||
struct CONN_MGR_CANDIDATE best_candidates[CONN_MGR_MAX_CANDIDATES];
|
||||
uint8_t best_candidate_count;
|
||||
void* candidate_ping_timer; ///< Хендл таймера обновления RTT кандидатов
|
||||
|
||||
uint32_t next_request_id;
|
||||
uint8_t initialized;
|
||||
struct CONN_MGR_CANDIDATE best_candidates[CONN_MGR_MAX_CANDIDATES]; ///< Топ кандидатов-посредников, отсортированных по RTT
|
||||
uint8_t best_candidate_count; ///< Количество актуальных кандидатов (≤CONN_MGR_MAX_CANDIDATES)
|
||||
|
||||
struct cm_reverse_pending* reverse_pending;
|
||||
struct cm_exchange_pending* exchange_pending;
|
||||
uint32_t next_request_id; ///< Счётчик request_id для INTERM_EXCHANGE
|
||||
uint8_t initialized; ///< Флаг инициализации
|
||||
|
||||
struct cm_reverse_pending* reverse_pending; ///< Связный список ожидающих REVERSE-подключений
|
||||
struct cm_exchange_pending* exchange_pending; ///< Связный список ожидающих INDIRECT-обменов
|
||||
};
|
||||
|
||||
/* ==================== Жизненный цикл ==================== */
|
||||
|
||||
/**
|
||||
* @brief Инициализирует менеджер соединений.
|
||||
* @param instance родительский экземпляр utun
|
||||
* @return указатель на CONN_MGR или NULL при ошибке
|
||||
*
|
||||
* Регистрирует обработчик в etcp_router для ETCP_RT_ID_CONN_MGR,
|
||||
* запускает фоновые таймеры (bg_ping, candidate_ping).
|
||||
*/
|
||||
struct CONN_MGR* conn_mgr_init(struct UTUN_INSTANCE* instance);
|
||||
void conn_mgr_destroy(struct CONN_MGR* mgr);
|
||||
|
||||
int conn_mgr_connect_node(struct CONN_MGR* mgr, uint64_t node_id,
|
||||
uint32_t idle_timeout_ms,
|
||||
conn_mgr_connect_callback_t cb, void* cb_arg);
|
||||
int conn_mgr_disconnect_node(struct CONN_MGR* mgr, uint64_t node_id);
|
||||
int conn_mgr_set_idle_timeout(struct CONN_MGR* mgr, uint64_t node_id, uint32_t timeout_ms);
|
||||
int conn_mgr_get_status(struct CONN_MGR* mgr, uint64_t node_id,
|
||||
uint8_t* out_state, uint8_t* out_conn_type);
|
||||
int conn_mgr_add_alien_node(struct CONN_MGR* mgr, const uint8_t* nodeinfo_data, size_t len);
|
||||
int conn_mgr_send(struct CONN_MGR* mgr, uint64_t node_id, struct ll_entry* entry);
|
||||
/**
|
||||
* @brief Уничтожает менеджер соединений.
|
||||
* @param mgr менеджер
|
||||
*
|
||||
* Освобождает все записи, таймеры, pending-структуры.
|
||||
* Вызывает cm_clear_nodeinfo для каждой записи.
|
||||
*/
|
||||
void conn_mgr_destroy(struct CONN_MGR* mgr);
|
||||
|
||||
/* ==================== Подключение / отключение ==================== */
|
||||
|
||||
/**
|
||||
* @brief Запускает асинхронное подключение к ноде.
|
||||
* @param mgr менеджер
|
||||
* @param node_id идентификатор целевой ноды
|
||||
* @param idle_timeout_ms таймаут неактивности (мс), 0 = без таймаута
|
||||
* @param cb callback результата (CONN_MGR_OK, CONN_MGR_ERR_TIMEOUT, CONN_MGR_ERR_UNREACHABLE и т.д.)
|
||||
* @param cb_arg пользовательский аргумент для callback
|
||||
* @return CONN_MGR_OK если процесс запущен, CONN_MGR_ERR_* при ошибке
|
||||
*
|
||||
* @note Если нода уже подключена — сразу вызывает callback с CONN_MGR_OK и возвращает CONN_MGR_OK.
|
||||
* @note Если нода в процессе подключения — добавляет callback в список ожидания.
|
||||
* @note Автоматически определяет наличие BGP-соединения (уже существующий ETCP-линк).
|
||||
* @note Для alien-нод используйте conn_mgr_add_alien_node().
|
||||
*/
|
||||
int conn_mgr_connect_node(struct CONN_MGR* mgr, uint64_t node_id,
|
||||
uint32_t idle_timeout_ms,
|
||||
conn_mgr_connect_callback_t cb, void* cb_arg);
|
||||
|
||||
/**
|
||||
* @brief Разрывает подключение к ноде.
|
||||
* @param mgr менеджер
|
||||
* @param node_id идентификатор ноды
|
||||
* @return CONN_MGR_OK или CONN_MGR_ERR_NOT_FOUND
|
||||
*
|
||||
* Отправляет DISCONNECT-пакет целевой ноде, сбрасывает conn_mgr_type в NODEINFO_Q,
|
||||
* уничтожает запись entry.
|
||||
*/
|
||||
int conn_mgr_disconnect_node(struct CONN_MGR* mgr, uint64_t node_id);
|
||||
|
||||
/* ==================== Управление idle-таймаутом ==================== */
|
||||
|
||||
/**
|
||||
* @brief Устанавливает idle-таймаут для подключённой ноды.
|
||||
* @param mgr менеджер
|
||||
* @param node_id идентификатор ноды
|
||||
* @param timeout_ms таймаут неактивности (мс), 0 = отключить проверку
|
||||
* @return CONN_MGR_OK или CONN_MGR_ERR_NOT_FOUND / CONN_MGR_ERR_INTERNAL
|
||||
*
|
||||
* Если таймаут > 0 и нода в состоянии CONNECTED — запускает периодический таймер.
|
||||
* При отсутствии трафика в течение timeout_ms соединение автоматически разрывается.
|
||||
*/
|
||||
int conn_mgr_set_idle_timeout(struct CONN_MGR* mgr, uint64_t node_id, uint32_t timeout_ms);
|
||||
|
||||
/**
|
||||
* @brief Получает текущий статус подключения к ноде.
|
||||
* @param mgr менеджер
|
||||
* @param node_id идентификатор ноды
|
||||
* @param out_state [out] состояние (enum CONN_MGR_STATE)
|
||||
* @param out_conn_type [out] тип соединения (CONN_TYPE_DIRECT/REVERSE/INDIRECT)
|
||||
* @return CONN_MGR_OK
|
||||
*/
|
||||
int conn_mgr_get_status(struct CONN_MGR* mgr, uint64_t node_id,
|
||||
uint8_t* out_state, uint8_t* out_conn_type);
|
||||
|
||||
/* ==================== Alien-ноды ==================== */
|
||||
|
||||
/**
|
||||
* @brief Регистрирует alien-ноду (подключившуюся к нам самостоятельно).
|
||||
* @param mgr менеджер
|
||||
* @param nodeinfo_data сырые данные NODEINFO (BGP-пакет)
|
||||
* @param len длина данных
|
||||
* @return CONN_MGR_OK или CONN_MGR_ERR_INTERNAL
|
||||
*
|
||||
* Alien-нода — это нода, которая сама инициировала INIT-подключение к нам.
|
||||
* Для неё не запускаются фазы подключения, сразу устанавливается CONN_MGR_STATE_CONNECTED.
|
||||
* Создаёт entry с флагом alien=1.
|
||||
*/
|
||||
int conn_mgr_add_alien_node(struct CONN_MGR* mgr, const uint8_t* nodeinfo_data, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Отправляет данные подключённой ноде через etcp_router.
|
||||
* @param mgr менеджер
|
||||
* @param node_id идентификатор целевой ноды
|
||||
* @param entry ll_entry с данными для отправки (освобождается после отправки)
|
||||
* @return CONN_MGR_OK или CONN_MGR_ERR_NOT_FOUND
|
||||
*
|
||||
* Для INDIRECT-соединений пакет автоматически маршрутизируется через
|
||||
* выбранного посредника (round-robin по intermediaries[]).
|
||||
* Обновляет last_traffic_tb для idle-проверки.
|
||||
*/
|
||||
int conn_mgr_send(struct CONN_MGR* mgr, uint64_t node_id, struct ll_entry* entry);
|
||||
|
||||
/* ==================== Управление кандидатами ==================== */
|
||||
|
||||
/**
|
||||
* @brief Обновляет RTT кандидата в списке лучших посредников.
|
||||
* @param mgr менеджер
|
||||
* @param node_id идентификатор ноды-кандидата
|
||||
* @param rtt RTT до кандидата (мс)
|
||||
*
|
||||
* Если кандидат уже в списке — обновляет RTT. Если нет — вставляет с сортировкой
|
||||
* по возрастанию RTT. Если список заполнен и новый кандидат имеет худший RTT —
|
||||
* игнорируется. Список всегда отсортирован: best_candidates[0] — наименьший RTT.
|
||||
*
|
||||
* @note Обычно вызывается из route_connectivity после успешного probe.
|
||||
*/
|
||||
void conn_mgr_update_best_candidates(struct CONN_MGR* mgr, uint64_t node_id, uint16_t rtt);
|
||||
|
||||
#endif
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <unistd.h>
|
||||
#include "../lib/platform_compat.h"
|
||||
#include "../lib/mem.h"
|
||||
#include "../lib/ll_queue.h"
|
||||
|
||||
|
||||
|
||||
@@ -85,6 +86,35 @@ static int instance_init_common(struct UTUN_INSTANCE* instance, struct UASYNC* u
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Initialize networks queue (indexed by 56-bit network id)
|
||||
instance->networks = queue_new(ua, 16, offsetof(struct NETWORK_ENTRY, id), 7, "networks");
|
||||
if (!instance->networks) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "Failed to create networks queue");
|
||||
return -1;
|
||||
}
|
||||
struct CFG_NETWORK *net = config->networks;
|
||||
while (net) {
|
||||
struct ll_entry *entry = queue_entry_new(sizeof(struct NETWORK_ENTRY));
|
||||
if (!entry) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_MEMORY, "Failed to allocate network entry for %s", net->name);
|
||||
net = net->next;
|
||||
continue;
|
||||
}
|
||||
struct NETWORK_ENTRY *ne = (struct NETWORK_ENTRY*)entry->data;
|
||||
ne->id = net->id & 0x00FFFFFFFFFFFFFFULL;
|
||||
for (int i = 0; i < SC_PUBKEY_SIZE; i++) {
|
||||
unsigned int b; sscanf(net->pubkey_hex + i * 2, "%2x", &b); ne->pubkey[i] = (uint8_t)b;
|
||||
}
|
||||
for (int i = 0; i < SC_PRIVKEY_SIZE; i++) {
|
||||
unsigned int b; sscanf(net->signing_key_hex + i * 2, "%2x", &b); ne->signing_key[i] = (uint8_t)b;
|
||||
}
|
||||
strncpy(ne->name, net->name, sizeof(ne->name) - 1);
|
||||
ne->name[sizeof(ne->name) - 1] = '\0';
|
||||
queue_data_put_with_index(instance->networks, entry);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "Network added: [%s] id=%012llx", ne->name, (unsigned long long)ne->id);
|
||||
net = net->next;
|
||||
}
|
||||
|
||||
// Create memory pools
|
||||
instance->ack_pool = memory_pool_init(sizeof(struct ACK_PACKET), "ack_pool");
|
||||
instance->data_pool = memory_pool_init(PACKET_DATA_SIZE, "data_pool");
|
||||
@@ -408,6 +438,16 @@ void utun_instance_destroy(struct UTUN_INSTANCE *instance) {
|
||||
instance->stcp_server = NULL;
|
||||
}
|
||||
|
||||
// Cleanup networks queue
|
||||
if (instance->networks) {
|
||||
struct ll_entry *entry;
|
||||
while ((entry = queue_data_get(instance->networks)) != NULL) {
|
||||
queue_entry_free(entry);
|
||||
}
|
||||
queue_free(instance->networks);
|
||||
instance->networks = NULL;
|
||||
}
|
||||
|
||||
// Cleanup config
|
||||
if (instance->config) {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_MEMORY, "[INSTANCE_DESTROY] Freeing configuration");
|
||||
@@ -754,6 +794,35 @@ struct UTUN_INSTANCE *utun_instance_reload(struct UTUN_INSTANCE *instance, struc
|
||||
l = next_l;
|
||||
}
|
||||
}
|
||||
// Reload networks: clear and repopulate
|
||||
if (instance->networks) {
|
||||
struct ll_entry *entry;
|
||||
while ((entry = queue_data_get(instance->networks)) != NULL) {
|
||||
queue_entry_free(entry);
|
||||
}
|
||||
struct CFG_NETWORK *net = new_config->networks;
|
||||
while (net) {
|
||||
struct ll_entry *new_entry = queue_entry_new(sizeof(struct NETWORK_ENTRY));
|
||||
if (!new_entry) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_MEMORY, "Failed to allocate network entry for reload: %s", net->name);
|
||||
net = net->next;
|
||||
continue;
|
||||
}
|
||||
struct NETWORK_ENTRY *ne = (struct NETWORK_ENTRY*)new_entry->data;
|
||||
ne->id = net->id & 0x00FFFFFFFFFFFFFFULL;
|
||||
for (int i = 0; i < SC_PUBKEY_SIZE; i++) {
|
||||
unsigned int b; sscanf(net->pubkey_hex + i * 2, "%2x", &b); ne->pubkey[i] = (uint8_t)b;
|
||||
}
|
||||
for (int i = 0; i < SC_PRIVKEY_SIZE; i++) {
|
||||
unsigned int b; sscanf(net->signing_key_hex + i * 2, "%2x", &b); ne->signing_key[i] = (uint8_t)b;
|
||||
}
|
||||
strncpy(ne->name, net->name, sizeof(ne->name) - 1);
|
||||
ne->name[sizeof(ne->name) - 1] = '\0';
|
||||
queue_data_put_with_index(instance->networks, new_entry);
|
||||
net = net->next;
|
||||
}
|
||||
DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "Networks reloaded");
|
||||
}
|
||||
fw_free(&instance->fw);
|
||||
fw_init(&instance->fw);
|
||||
fw_load_rules(&instance->fw, &new_config->global);
|
||||
|
||||
@@ -36,6 +36,13 @@ struct PING_CONTEXT;
|
||||
struct CONN_MGR;
|
||||
struct ETCP_CONNECT;
|
||||
|
||||
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];
|
||||
};
|
||||
|
||||
// uTun instance configuration
|
||||
struct UTUN_INSTANCE {
|
||||
// Identification
|
||||
@@ -119,6 +126,9 @@ struct UTUN_INSTANCE {
|
||||
// TCP proxy server (exit node)
|
||||
struct tcp_proxy_server tcp_proxy_server;
|
||||
|
||||
// Networks (queue of NETWORK_ENTRY, indexed by 56-bit id)
|
||||
struct ll_queue* networks;
|
||||
|
||||
// Pending background connections (etcp_connect API)
|
||||
struct ETCP_CONNECT* pending_connects;
|
||||
uint32_t etcp_connect_timeout_tb; // Initial timeout in 0.1ms units, default 20000 (2s)
|
||||
|
||||
Reference in new issue
Block a user