From 9ef501a2fbd0a9281f11e4d12f48c120cfc23105 Mon Sep 17 00:00:00 2001 From: evgeny Date: Fri, 11 Sep 2026 18:13:48 +0300 Subject: [PATCH] =?UTF-8?q?etcp=5Fconnections:=20=D1=81=D0=BE=D0=B1=D1=80?= =?UTF-8?q?=D0=B0=D1=82=D1=8C=20forward-=D0=BE=D0=B1=D1=8A=D1=8F=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B2=20=D0=B1=D0=BB=D0=BE?= =?UTF-8?q?=D0=BA=20=D0=B8=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D1=82?= =?UTF-8?q?=D1=8C=20=D0=BF=D0=BE=D1=8F=D1=81=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F?= =?UTF-8?q?=20=D0=BA=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D1=8F=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/transport_layer/etcp_connections.c | 92 ++++++++++++++++++++------ 1 file changed, 72 insertions(+), 20 deletions(-) diff --git a/src/transport_layer/etcp_connections.c b/src/transport_layer/etcp_connections.c index 5edbe736..00d441b1 100644 --- a/src/transport_layer/etcp_connections.c +++ b/src/transport_layer/etcp_connections.c @@ -32,20 +32,29 @@ #include "../lib/mem.h" #include "etcp.h" +// Читаемое имя типа сокета (CFG_SERVER_TYPE_*) для логов. static const char* server_type_str(uint8_t type) { static const char* names[] = {"UNKNOWN", "PUBLIC", "NAT", "PRIVATE", "LOCAL"}; return type < 5 ? names[type] : "?"; } +// Читаемое имя NAT-типа (NAT_TYPE_*/NAT_VERIFIED_*) для логов. static const char* nat_type_str(uint8_t nat_type) { if (nat_type >= 4 && nat_type <= 7) nat_type -= 4; static const char* names[] = {"UNKNOWN", "EIM", "STRICT", "DIRECT"}; return nat_type < 4 ? names[nat_type] : "?"; } +/* ── Forward declarations ──────────────────────────────────────────── + * Только static-функции, используемые раньше своего определения. + * Не-static функции уже объявлены в etcp_connections.h. */ static void tcp_link_close_cb(struct stcp_link *sl, int err, void *arg); -void etcp_link_enter_ready_tcp(struct ETCP_LINK *link); +static void etcp_link_send_init(struct ETCP_LINK* link, uint8_t reset, uint8_t collision); +static void etcp_link_init_timer_cbk(void* arg); +static void burst_resp_timeout_cb(void* arg); +static int etcp_tcp_send(struct ETCP_DGRAM* dgram); -// TCP server: on new incoming connection → create ETCP_LINK + enter ready +// STCP-сервер: новое входящее TCP-соединение → найти/создать ETCP_CONN по node_id +// pubkey пира, создать TCP-линк и поднять его (ready). void tcp_server_on_link(struct stcp_link *link, struct ETCP_SOCKET *tcp_sock) { struct UTUN_INSTANCE *inst = tcp_sock->instance; DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "tcp_server_on_link: link=%p tcp_sock=%p inst=%p inst->ua=%p", @@ -90,19 +99,9 @@ void tcp_server_on_link(struct stcp_link *link, struct ETCP_SOCKET *tcp_sock) { etcp_link_enter_ready_tcp(tlink); } -// Forward declaration -void etcp_connections_read_callback_socket(socket_t sock, void* arg); -static void etcp_link_remove_from_connections(struct ETCP_SOCKET* conn, struct ETCP_LINK* link); - -static void etcp_link_send_init(struct ETCP_LINK* link, uint8_t reset, uint8_t collision); -//static int etcp_link_send_reset(struct ETCP_LINK* link); -static void etcp_link_init_timer_cbk(void* arg); -static void link_stats_timer_cb(void* arg); -static void burst_resp_timeout_cb(void* arg); -static int etcp_tcp_send(struct ETCP_DGRAM* dgram); - -// === Burst sender functions === +// === Burst sender: замер пропускной способности линка === +// Старт burst: отправка пачки пакетов подряд для измерения bandwidth. void etcp_link_burst_start(struct ETCP_LINK* link) { if (!link || !link->etcp || !link->etcp->instance) return; link->burst_active = 1; @@ -116,6 +115,7 @@ void etcp_link_burst_start(struct ETCP_LINK* link) { if (link->etcp->link_ready_for_send_fn) link->etcp->link_ready_for_send_fn(link->etcp); } +// Возможность стартовать burst: линк насыщен (inflight достиг лимита) и прошёл интервал. void etcp_link_burst_check(struct ETCP_LINK* link) { if (!link || !link->etcp) return; if (link->burst_active) return; @@ -126,6 +126,7 @@ void etcp_link_burst_check(struct ETCP_LINK* link) { etcp_link_burst_start(link); } +// Завершение burst: сброс флага, запуск таймера ожидания ответа с замерами пира. void etcp_link_burst_finish(struct ETCP_LINK* link) { if (!link || !link->etcp || !link->etcp->instance) return; link->burst_active = 0; @@ -134,6 +135,7 @@ void etcp_link_burst_finish(struct ETCP_LINK* link) { if (link->etcp->link_ready_for_send_fn) link->etcp->link_ready_for_send_fn(link->etcp); } +// Таймаут ожидания ответа на burst — просто сбрасываем таймер. static void burst_resp_timeout_cb(void* arg) { struct ETCP_LINK* link = (struct ETCP_LINK*)arg; if (!link) return; @@ -144,6 +146,8 @@ static void burst_resp_timeout_cb(void* arg) { #define INIT_TIMEOUT_INITIAL 500 #define INIT_TIMEOUT_MAX 50000 +// Клиент: собрать и отправить INIT_REQUEST (handshake) — заголовок, padding для обфускации +// размера и обфусцированный pubkey. reset=1 → запрос сброса эпохи, collision=1 → ответ на коллизию. static void etcp_link_send_init(struct ETCP_LINK* link, uint8_t reset, uint8_t collision) { DEBUG_TRACE(DEBUG_CATEGORY_ETCP, ""); DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "link=%p, is_server=%d, reset=%d, collision=%d", link, link ? link->is_server : -1, reset, collision); @@ -247,6 +251,7 @@ static void etcp_link_send_init(struct ETCP_LINK* link, uint8_t reset, uint8_t c link->init_retry_count++; } +// Периодический повтор INIT до установления связи (с экспоненциальным backoff до INIT_TIMEOUT_MAX). static void etcp_link_init_timer_cbk(void* arg) { DEBUG_TRACE(DEBUG_CATEGORY_ETCP, ""); struct ETCP_LINK* link = (struct ETCP_LINK*)arg; @@ -266,6 +271,7 @@ static void etcp_link_init_timer_cbk(void* arg) { else etcp_link_send_init(link,0,0); } +// Сброс таймера INIT на начальный таймаут (используется при каждом новом handshake). void etcp_link_restart_init_timer(struct ETCP_LINK* link) { DEBUG_TRACE(DEBUG_CATEGORY_ETCP, ""); if (link->init_timer) uasync_cancel_timeout(link->etcp->instance->ua, link->init_timer); @@ -273,7 +279,8 @@ void etcp_link_restart_init_timer(struct ETCP_LINK* link) { link->init_timer = uasync_set_timeout(link->etcp->instance->ua, link->init_timeout, link, etcp_link_init_timer_cbk, "link_init"); } -void etcp_link_enter_init(struct ETCP_LINK* link) {// +// Клиент: переход в handshake — отправить INIT и запустить таймер повторов. +void etcp_link_enter_init(struct ETCP_LINK* link) { DEBUG_TRACE(DEBUG_CATEGORY_ETCP, ""); if (!link) return; int old_state = link->link_state; @@ -285,6 +292,7 @@ void etcp_link_enter_init(struct ETCP_LINK* link) {// etcp_link_restart_init_timer(link); } +// Клиент: повторный handshake после разрыва — уведомить о падении, отправить INIT, снять keepalive. void etcp_link_enter_reinit(struct ETCP_LINK* link) { DEBUG_TRACE(DEBUG_CATEGORY_ETCP, ""); if (!link) return; @@ -305,6 +313,7 @@ void etcp_link_enter_reinit(struct ETCP_LINK* link) { } +// Собирает 19-байтовый ключ из sockaddr (port+addr+family) для hash-индекса links_queue. static void sockaddr_to_key(struct sockaddr_storage* addr, uint8_t key[LINK_ADDR_KEY_SIZE], int is_tcp) { memset(key, 0, LINK_ADDR_KEY_SIZE); if (!addr) return; @@ -323,6 +332,7 @@ static void sockaddr_to_key(struct sockaddr_storage* addr, uint8_t key[LINK_ADDR // find_link_index, realloc_links, insert_link, remove_link — УДАЛЕНЫ. Заменены на ll_queue с хеш-индексом. +// Вставка линка в links_queue сокета по hash-ключу адреса; при дубле адреса другого коннекта — коллизия. static int insert_link_queue(struct ETCP_SOCKET* e_sock, struct ETCP_LINK* link) { DEBUG_TRACE(DEBUG_CATEGORY_ETCP, ""); if (!e_sock || !link || !e_sock->links_queue) return -1; @@ -368,6 +378,7 @@ static int insert_link_queue(struct ETCP_SOCKET* e_sock, struct ETCP_LINK* link) return 0; } +// Удаление линка из links_queue сокета (освобождение hash-записи). static void remove_link_from_queue(struct ETCP_LINK* link) { DEBUG_TRACE(DEBUG_CATEGORY_ETCP, ""); if (!link || !link->link_queue_entry) return; @@ -377,6 +388,7 @@ static void remove_link_from_queue(struct ETCP_LINK* link) { link->link_queue_entry = NULL; } +// Сравнение двух sockaddr_storage (family + addr + port) без учёта прочих полей. static int sockaddr_equal(const struct sockaddr_storage* a, const struct sockaddr_storage* b) { if (!a || !b || a->ss_family != b->ss_family) return 0; if (a->ss_family == AF_INET) { @@ -392,6 +404,7 @@ static int sockaddr_equal(const struct sockaddr_storage* a, const struct sockadd return 0; } +// Поиск линка в сокете по remote-адресу (через hash-индекс links_queue). struct ETCP_LINK* etcp_link_find_by_addr(struct ETCP_SOCKET* e_sock, struct sockaddr_storage* addr, int is_tcp) { DEBUG_TRACE(DEBUG_CATEGORY_ETCP, ""); if (!e_sock || !addr || !e_sock->links_queue) return NULL; @@ -437,6 +450,7 @@ struct ETCP_LINK* etcp_select_collision_link(struct ETCP_CONN* conn, const struc return NULL; } +// Поиск линка по remote_link_id (id, под которым линк известен пиру). struct ETCP_LINK* etcp_link_find_by_remote_id(struct ETCP_CONN* conn, uint8_t remote_link_id) { DEBUG_TRACE(DEBUG_CATEGORY_ETCP, ""); if (!conn || remote_link_id == 0) return NULL; @@ -448,6 +462,7 @@ struct ETCP_LINK* etcp_link_find_by_remote_id(struct ETCP_CONN* conn, uint8_t re return NULL; } +// Выделение свободного local_link_id (0-255): битовая маска занятых id + циклический поиск. int etcp_find_free_local_link_id(struct ETCP_CONN* etcp) { DEBUG_TRACE(DEBUG_CATEGORY_ETCP, ""); if (!etcp) return -1; @@ -477,8 +492,8 @@ int etcp_find_free_local_link_id(struct ETCP_CONN* etcp) { } -// =============================== - +// Создание UDP-сокета приёма/отправки кодограмм: bind к interface_addr, настройка буферов, +// регистрация в uasync и добавление в instance->etcp_sockets. struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct CFG_SERVER* server) { DEBUG_TRACE(DEBUG_CATEGORY_ETCP, ""); if (!instance || !server) return NULL; @@ -726,6 +741,7 @@ struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct CFG_S return e_sock; } +// Удаление UDP-сокета: снятие с uasync, закрытие fd, закрытие всех линков и освобождение. void etcp_socket_remove(struct ETCP_SOCKET* conn) { DEBUG_TRACE(DEBUG_CATEGORY_ETCP, ""); if (!conn) return; @@ -767,6 +783,8 @@ void etcp_socket_remove(struct ETCP_SOCKET* conn) { /* ── TCP socket management ── */ +// TCP-сокет (запись ETCP_SOCKET с is_tcp=1): определение bind-адреса по конфигу. +// Сам listen/accept выполняет stcp_server — здесь только модель сокета. struct ETCP_SOCKET* tcp_socket_add(struct UTUN_INSTANCE* instance, struct CFG_SERVER* server) { if (!instance || !server) return NULL; @@ -855,6 +873,7 @@ struct ETCP_SOCKET* tcp_socket_add(struct UTUN_INSTANCE* instance, struct CFG_SE return ts; } +// Удаление TCP-сокета из списка instance->etcp_sockets. void tcp_socket_remove(struct ETCP_SOCKET* sock) { if (!sock || !sock->instance) return; struct UTUN_INSTANCE* inst = sock->instance; @@ -865,6 +884,8 @@ void tcp_socket_remove(struct ETCP_SOCKET* sock) { u_free(sock); } +// Создание нового ETCP_LINK: аллокация, выделение local_link_id, инициализация BBR/keepalive, +// вставка в список коннекта и links_queue сокета. Для outbound UDP сразу запускает handshake. struct ETCP_LINK* etcp_link_new(struct ETCP_CONN* etcp, struct ETCP_SOCKET* conn, struct sockaddr_storage* remote_addr, uint8_t is_server) { DEBUG_TRACE(DEBUG_CATEGORY_ETCP, ""); if (!etcp) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "null etcp"); return NULL; } @@ -970,6 +991,7 @@ struct ETCP_LINK* etcp_link_new(struct ETCP_CONN* etcp, struct ETCP_SOCKET* conn return link; } +// Установка нового лимита inflight с клампингом в [INFLIGHT_LIM_MIN, max_inflight] и уведомлением коннекта. void etcp_link_update_inflight_lim(struct ETCP_LINK* link, uint32_t new_lim) { if (!link || !link->etcp) return; if (new_lim < INFLIGHT_LIM_MIN) new_lim = INFLIGHT_LIM_MIN; @@ -991,6 +1013,8 @@ static void etcp_inflight_nullify_link(struct ll_queue* q, struct ETCP_LINK* dea } } +// Закрытие линка: отмена таймеров (init/shaper/keepalive/tcp), удаление из списков и очереди, +// зануление ссылок inflight (защита от use-after-free) и освобождение памяти. void etcp_link_close(struct ETCP_LINK* link) { DEBUG_TRACE(DEBUG_CATEGORY_ETCP, ""); if (!link) return; @@ -1065,6 +1089,8 @@ void etcp_link_close(struct ETCP_LINK* link) { // ====== TCP link helpers ====== +// Поднять TCP-линк в ready: синхронизация reset-эпохи (gop/rid), keepalive, ed25519, +// mark initialized + link_status=1, уведомить коннект и loadbalancer. void etcp_link_enter_ready_tcp(struct ETCP_LINK *link) { if (!link || !link->etcp) return; struct ETCP_CONN *etcp = link->etcp; @@ -1108,6 +1134,7 @@ void etcp_link_enter_ready_tcp(struct ETCP_LINK *link) { etcp->initialized, etcp->links_up, etcp->tcp_link_count); } +// Повторная попытка STCP-подключения с экспоненциальным backoff (до 30 с). static void tcp_link_reconnect_cb(void *arg) { struct ETCP_LINK *link = (struct ETCP_LINK *)arg; if (!link || !link->etcp || !link->etcp->instance) return; @@ -1122,6 +1149,7 @@ static void tcp_link_reconnect_cb(void *arg) { stcp_link_set_on_close(sl, tcp_link_close_cb, link); } +// Исходящее TCP-подключение линка: stcp_link_connect + установка close-callback. void etcp_tcp_link_start_connect(struct ETCP_LINK *link, struct sockaddr_storage *addr, uint16_t port) { if (!link || !link->etcp || !addr) return; /* link->conn опционален: NULL = без локального bind (ОС выбирает source IP/интерфейс). @@ -1136,6 +1164,7 @@ void etcp_tcp_link_start_connect(struct ETCP_LINK *link, struct sockaddr_storage link->conn ? sockaddr_storage_to_str(&link->conn->interface_addr).str : "auto"); } +// Запланировать реконнект TCP-линка после обрыва (через tcp_reconnect_timer). void etcp_tcp_link_start_reconnect(struct ETCP_LINK *link) { if (!link || !link->etcp || !link->etcp->instance || link->is_server) return; if (link->etcp->state == 2) return; @@ -1146,6 +1175,7 @@ void etcp_tcp_link_start_reconnect(struct ETCP_LINK *link) { link->tcp_reconnect_timer = uasync_set_timeout(link->etcp->instance->ua, (int)(link->tcp_reconnect_delay_ms * 10), link, tcp_link_reconnect_cb, "tcp_rct"); } +// Callback закрытия STCP-линка: серверный линк закрываем, клиентский — отправляем на реконнект. static void tcp_link_close_cb(struct stcp_link *sl, int err, void *arg) { struct ETCP_LINK *link = (struct ETCP_LINK *)arg; if (!link || !link->etcp) return; @@ -1173,6 +1203,7 @@ static void tcp_link_close_cb(struct stcp_link *sl, int err, void *arg) { } } +// Отправка ETCP_DGRAM по TCP: сборка буфера (timestamp+flag_up+data) и передача в stcp_link_send. static int etcp_tcp_send(struct ETCP_DGRAM* dgram) { struct ETCP_LINK *link = dgram->link; if (!link->tcp_link || !stcp_link_is_ready(link->tcp_link)) return -1; @@ -1198,6 +1229,7 @@ static int etcp_tcp_send(struct ETCP_DGRAM* dgram) { } +// Единая точка отправки UDP: через send_hook (если задан) или socket_sendto напрямую. ssize_t etcp_udp_send(struct ETCP_LINK* link, socket_t fd, const void* buf, size_t len, const struct sockaddr* addr, socklen_t addr_len) { if (link && link->send_hook) @@ -1205,6 +1237,7 @@ ssize_t etcp_udp_send(struct ETCP_LINK* link, socket_t fd, const void* buf, size return socket_sendto(fd, buf, len, addr, addr_len); } +// Зашифровать и отправить пакет: TCP → etcp_tcp_send, UDP → AES-CCM + socket_sendto. int etcp_encrypt_send(struct ETCP_DGRAM* dgram) { if (!dgram || !dgram->link) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Null pointer"); return -1; } if (dgram->link->is_tcp) return etcp_tcp_send(dgram); @@ -1255,6 +1288,7 @@ es_err: return -1; } +// Шифрует и отправляет готовый PING/PONG-датаграмм без линка (сырой sendto по fd). static int etcp_send_ping_raw(struct ETCP_DGRAM* dgram, socket_t fd, sc_context_t* sc, const struct sockaddr_storage* addr) { if (!dgram || !sc || !addr) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Null pointer in ping send"); @@ -1292,6 +1326,7 @@ static int etcp_send_ping_raw(struct ETCP_DGRAM* dgram, socket_t fd, sc_context_ return (int)sent; } +// Копирует пользовательские данные запроса в ответ (эхо) с ограничением буфера. static size_t etcp_build_ping_response_data(const uint8_t* req_data, size_t req_data_len, uint8_t* resp_buf, size_t resp_buf_len) { if (req_data_len > resp_buf_len) req_data_len = resp_buf_len; @@ -1299,6 +1334,7 @@ static size_t etcp_build_ping_response_data(const uint8_t* req_data, size_t req_ return req_data_len; } +// Таймаут пинга: снять из pending_pings и вызвать callback с success=0. static void ping_timeout_cbk(void* arg) { struct PING_CONTEXT* ctx = (struct PING_CONTEXT*)arg; if (!ctx || !ctx->cb) return; @@ -1318,6 +1354,8 @@ static void ping_timeout_cbk(void* arg) { u_free(ctx); } +// Отправка UDP-пинга через конкретный сокет: сборка PING-кодограммы (nonce, user_data, +// обфусцированный pubkey), регистрация в pending_pings с таймаутом. int etcp_send_ping_to_socket(struct UTUN_INSTANCE* instance, struct ETCP_SOCKET* e_sock, const uint8_t* peer_pubkey_bin, const struct sockaddr_storage* addr, int timeout_ms, etcp_ping_callback_t cb, void* user_arg, @@ -1420,6 +1458,7 @@ int etcp_send_ping_to_socket(struct UTUN_INSTANCE* instance, struct ETCP_SOCKET* return 0; } +// Отправка UDP-пинга: подбор сокета по family адреса, делегирование в etcp_send_ping_to_socket. int etcp_send_ping(struct UTUN_INSTANCE* instance, const uint8_t* peer_pubkey_bin, const struct sockaddr_storage* addr, int timeout_ms, etcp_ping_callback_t cb, void* user_arg, @@ -1446,12 +1485,14 @@ struct tcp_ping_adapter { void* arg; }; +// Адаптер: приводит callback STCP-пинга к типу etcp_ping_callback_t. static void tcp_ping_cb_adapter(int success, uint16_t rtt, void* arg) { struct tcp_ping_adapter* a = (struct tcp_ping_adapter*)arg; a->cb(success, rtt, a->arg, 0, NULL, 0); u_free(a); } +// TCP-пинг: STCP-хендшейк с пиром и замер RTT по handshake (через stcp_ping_send). int etcp_send_tcp_ping(struct UTUN_INSTANCE* instance, const uint8_t* peer_pubkey_bin, const struct sockaddr_storage* addr, int timeout_ms, etcp_ping_callback_t cb, void* user_arg) { @@ -1487,6 +1528,7 @@ int etcp_send_tcp_ping(struct UTUN_INSTANCE* instance, const uint8_t* peer_pubke // === Helpers extracted from etcp_connections_read_callback_socket === +// Обработка входящего PING: обновление RTT (если флаг SEND_RTT), ответ PONG с эхо-данными. static int handle_ping(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt, const struct sockaddr_storage* addr, const uint8_t* decrypted_pubkey, size_t pkt_len) { if (pkt_len < 23) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "PING too short: pkt_len=%zu from %s", pkt_len, sockaddr_storage_to_str(addr).str); @@ -1543,11 +1585,13 @@ static int handle_ping(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt, const return 0; } +// Пустой callback для RTT-ответа (получателю RTT-пинга ответ не важен). static void rtt_send_ping_cb(int success, uint16_t rtt, void* arg, uint64_t nonce, const uint8_t* resp_data, size_t resp_data_len) { (void)success; (void)rtt; (void)arg; (void)nonce; (void)resp_data; (void)resp_data_len; } +// Обработка входящего PONG: поиск pending_pings по nonce, вызов callback с RTT и данными. static int handle_pong(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt, const struct sockaddr_storage* addr, size_t pkt_len) { if (pkt_len < 23) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "PONG too short: pkt_len=%zu from %s", pkt_len, sockaddr_storage_to_str(addr).str); @@ -1610,6 +1654,8 @@ static int handle_pong(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt, const return 0; } +// Сервер: собрать и отправить INIT_RESPONSE (mtu, link_id, NAT-адрес клиента, ed25519), +// провести NAT-детекцию, поднять линк и запустить keepalive. static void send_init_response(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt, struct ETCP_LINK* link, struct ETCP_CONN* conn, const struct ETCP_INIT_REQUEST_PKT* req, const struct sockaddr_storage* addr, uint8_t send_reset, uint32_t req_src_ip, uint16_t req_src_port, size_t pkt_len) { struct ETCP_INIT_RESPONSE_PKT* resp = (struct ETCP_INIT_RESPONSE_PKT*)pkt->data; @@ -1747,6 +1793,7 @@ static void send_init_response(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pk if (link->etcp->instance->nat_det) nat_detection_link_ready(link->etcp->instance->nat_det, link); } +// Клиент: обработка INIT_RESPONSE — MTU, link_id, NAT-адрес, ed25519, keepalive, подъём линка. static int handle_init_response_client(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt, struct ETCP_LINK* link, uint8_t pkt_code, size_t pkt_len) { if (!e_sock) return -1; if (pkt_len < ETCP_INIT_RESP_SIZE) { @@ -1860,6 +1907,8 @@ static int handle_init_response_client(struct ETCP_SOCKET* e_sock, struct ETCP_D return 0; } +// Главный приёмник UDP-кодограмм: normal/init decrypt, диспетчеризация PING/PONG/INIT, +// создание/переиспользование линков и коннектов, обработка коллизий. void etcp_connections_read_callback_socket(socket_t sock, void* arg) { DEBUG_TRACE(DEBUG_CATEGORY_ETCP, ""); // DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "etcp_connections_read_callback fd=%d, socket=%p", fd, arg); @@ -2298,6 +2347,8 @@ ec_fr: return; } +// Обработка пакета, расшифрованного на установленном линке: keepalive-статус, INIT_RESPONSE, +// обычные данные → etcp_conn_input. int etcp_packet_decrypted(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt, struct ETCP_LINK* link, size_t pkt_len) { DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "Decrypt ok - normal pkt"); @@ -2362,9 +2413,6 @@ int etcp_packet_decrypted(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt, return 0; } -// Initialize only sockets (servers for incoming connections) -// Called before topo_group_init() to populate etcp_sockets for nodeinfo -// Returns: 0 = all OK, 1 = partial success (some sockets failed), -1 = fatal error (no sockets) /* Создаёт один серверный сокет из CFG_SERVER: UDP (etcp_socket_add) или TCP * (tcp_socket_add + stcp_server_listen + stcp_server_list_add). * Линки к соединениям не добавляет — это забота вызывающего. @@ -2401,6 +2449,9 @@ int etcp_create_server_socket(struct UTUN_INSTANCE* instance, struct CFG_SERVER* return 0; } +// Создание всех listen-сокетов из конфига ([server] секции); автосокеты пропускаются. +// Вызывается до topo_group_init() чтобы заполнить etcp_sockets для nodeinfo. +// Возврат: 0 = OK, 1 = частичный успех (часть сокетов не создана), -1 = фатально (нет сокетов). int init_sockets(struct UTUN_INSTANCE* instance) { DEBUG_TRACE(DEBUG_CATEGORY_ETCP, ""); if (!instance || !instance->config) return -1; @@ -2547,6 +2598,7 @@ struct NODE_CONN_DIRECT* etcp_config_client_reality(struct UTUN_INSTANCE* instan return handle; } +// Инициализация сети: listen-сокеты (если ещё нет) + client-соединения через NCD из конфига. int init_connections(struct UTUN_INSTANCE* instance) { DEBUG_TRACE(DEBUG_CATEGORY_ETCP, ""); if (!instance || !instance->config) return -1;