From 852ce401e7fe8bc2f6b0fefa924ffec7ad80b04d Mon Sep 17 00:00:00 2001 From: Evgeny Date: Wed, 22 Jul 2026 15:51:03 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=20group=5Fid=20=D0=B2=20etcp=5Frouter=20=D0=B8=20topo=5F?= =?UTF-8?q?group,=20=D1=83=D0=B4=D0=B0=D0=BB=D1=91=D0=BD=20msg=5Ftransport?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - etcp_router: SVC_ROUTE_HDR (+8B), ETCP_ROUTER_CONN/TRANSIT_QUEUE хеши расширены под group_id - Все caller'ы (proxy, routing, conn_mgr, nat, chatgui, tests) обновлены - topo_group: глобальный реестр TOPO_NODE по node_id, ref_count=0 при создании - BGP-обмен активируется для всех групп (а не только дефолтной) - Протокол: group_id добавлен в WITHDRAW/TABLE_REQ/TABLE_COMPLETE/ERR_GROUP_MISMATCH - Per-connection коллбэки заменены на instance-level conn_status - msg_transport полностью удалён из проекта 57/57 тестов --- AGENTS.md | 1 - ARCHITECTURE.md | 10 +- cross-build-win.sh | 2 +- src/Makefile.am | 2 - src/config_parser.c | 19 - src/config_parser.h | 2 - src/config_parser_doc.md | 2 - src/msg_transport.c | 638 ------------------------ src/msg_transport.h | 126 ----- src/msg_transport_doc.md | 69 --- src/nat_transport.c | 5 +- src/proxy/icmp_proxy.c | 7 +- src/proxy/socks_proxy.c | 31 +- src/proxy/tcp_proxy_client.c | 29 +- src/proxy/tcp_proxy_server.c | 31 +- src/proxy/udp_proxy.c | 5 +- src/routing_layer/conn_mgr.c | 12 +- src/routing_layer/etcp_router.c | 132 ++--- src/routing_layer/etcp_router.h | 53 +- src/routing_layer/routing.c | 2 +- src/routing_layer/topo_group.c | 108 ++-- src/routing_layer/topo_group.h | 13 +- src/routing_layer/topo_node.c | 78 ++- src/routing_layer/topo_node.h | 12 + src/transport_layer/etcp_api.h | 2 +- src/transport_layer/etcp_api_doc.md | 1 - src/utun_instance.c | 24 +- src/utun_instance.h | 5 +- src/utun_instance_doc.md | 6 +- tests/test_etcp_router.c | 6 +- tests/test_etcp_router_reconnect.c | 2 +- tests/test_etcp_router_unit.c | 49 +- tests/test_nat_transport.c | 4 +- tools/chatgui/chat_tz.txt | 2 +- tools/chatgui/libutun/CMakeLists.txt | 1 - tools/chatgui/transport/node_config.cpp | 6 - tools/chatgui/transport/utun_node.cpp | 3 +- 37 files changed, 375 insertions(+), 1125 deletions(-) delete mode 100644 src/msg_transport.c delete mode 100644 src/msg_transport.h delete mode 100644 src/msg_transport_doc.md diff --git a/AGENTS.md b/AGENTS.md index 87aae62d..96943619 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -300,7 +300,6 @@ KEEPALIVE=21, ETCPROUTE=22, BBR=23, ETCP_DUMP=24 - `control_server.c/h` - Control/monitoring server (etcpmon backend API) **Транспорт сообщений (src/)** -- `msg_transport.c/h` - Транспорт сообщений (чат, команды) - `db_sync.c/h` - Синхронизация БД между узлами **Прокси (src/proxy/)** diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 4a2b41dd..86045123 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -41,7 +41,7 @@ uTun — защищённый VPN-туннель с собственным на ┌─────────────────────────────────────────────────────────────────┐ │ Layer 4: Приложения │ │ routing (IP-форвардинг), proxy (SOCKS5/TCP/UDP/ICMP), chat, │ -│ db_sync (P2P БД), msg_transport (IPC), NTP, NAT │ +│ db_sync (P2P БД), NTP, NAT │ ├─────────────────────────────────────────────────────────────────┤ │ Layer 3: etcp_router — сервисная маршрутизация │ │ seq-нумерация, дедупликация, реордеринг, ретрансмиссия, │ @@ -822,7 +822,7 @@ ETCP туннель от клиента uasync_mainloop() ├── Сокеты: │ ├── UDP listen (все [server] сокеты) - │ ├── TCP listen (control_server, msg_transport, STCP) + │ ├── TCP listen (control_server, STCP) │ └── TUN fd (read/write через uasync callback) ├── Таймеры: │ ├── ETCP: retrans, ack_response, keepalive @@ -907,8 +907,7 @@ utun_instance_init(instance): 3. nat_transport_init(instance) // NAT транспорт 4. init_connections(instance) // ETCP соединения из [client] 5. control_server_init() // мониторинг - 6. msg_transport_init() // IPC транспорт - 7. running = 1 + 6. running = 1 8. ntp_time_init() // NTP синхронизация 9. ntp_node_time_init() // межузловое время ``` @@ -919,8 +918,7 @@ utun_instance_init(instance): utun_instance_destroy(instance): 1. running = 0 2. Отмена NTP таймеров - 3. msg_transport_destroy() // сначала IPC - 4. control_server_destroy() // потом мониторинг + 3. control_server_destroy() // потом мониторинг 5. Закрытие всех UDP сокетов // etcp_socket_remove() для каждого 6. db_sync_destroy() 7. etcp_connection_close() для всех соединений в connections diff --git a/cross-build-win.sh b/cross-build-win.sh index dd5f5527..a0b3e1c1 100755 --- a/cross-build-win.sh +++ b/cross-build-win.sh @@ -201,7 +201,7 @@ SRC_SOURCES=( transport_layer/etcp_debug.c transport_layer/etcp_dump.c transport_layer/secure_channel.c transport_layer/crc32.c transport_layer/stcp_link.c transport_layer/stcp.c transport_layer/stcp_server.c transport_layer/stcp_client.c transport_layer/pkt_normalizer.c transport_layer/packet_dump.c transport_layer/etcp_api.c - control_server.c msg_transport.c + control_server.c firewall.c eim_nat.c nat_transport.c transport_layer/dummynet.c etcp_router.c proxy/udp_proxy.c proxy/socks_proxy.c diff --git a/src/Makefile.am b/src/Makefile.am index ce5fda04..9b887fee 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -40,7 +40,6 @@ utun_CORE_SOURCES = \ transport_layer/etcp_api.c \ transport_layer/etcp_connect.c \ control_server.c \ - msg_transport.c \ firewall.c \ eim_nat.c \ nat_transport.c \ @@ -96,7 +95,6 @@ libutun_a_SOURCES = \ transport_layer/etcp_api.c \ transport_layer/etcp_connect.c \ control_server.c \ - msg_transport.c \ firewall.c \ eim_nat.c \ nat_transport.c \ diff --git a/src/config_parser.c b/src/config_parser.c index 4a5ed5aa..21ac07f2 100644 --- a/src/config_parser.c +++ b/src/config_parser.c @@ -47,7 +47,6 @@ typedef enum { SECTION_NAT, SECTION_TCP_PROXY_CLIENT, SECTION_TCP_PROXY_SERVER, - SECTION_MSG_TRANSPORT, SECTION_NETWORK, SECTION_GUI, SECTION_NTP @@ -459,17 +458,6 @@ static int parse_control(const char *key, const char *value, struct global_confi return -1; } -static int parse_msg_transport(const char *key, const char *value, struct global_config *global, const char *filename, int line_num) { - if (strcmp(key, "port") == 0) { - char port_str[16]; - snprintf(port_str, sizeof(port_str), "%s", value); - parse_sockaddr("127.0.0.1", port_str, &global->msg_transport_sock); - return 0; - } - DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "%s:%d: Unknown msg_transport option '%s'. Valid: port", filename, line_num, key); - return -1; -} - static int parse_tcp_proxy_client(const char *key, const char *value, struct global_config *global, const char *filename, int line_num) { if (strcmp(key, "enabled") == 0) { global->tcp_proxy_client_enabled = strcasecmp(value, "yes") == 0 || strcasecmp(value, "1") == 0 || strcasecmp(value, "true") == 0; @@ -764,7 +752,6 @@ static section_type_t parse_section_header(const char *line, char *name, size_t if (strcasecmp(section, "nat") == 0) return SECTION_NAT; if (strcasecmp(section, "tcp_proxy_client") == 0) return SECTION_TCP_PROXY_CLIENT; if (strcasecmp(section, "tcp_proxy_server") == 0) return SECTION_TCP_PROXY_SERVER; - if (strcasecmp(section, "msg_transport") == 0) return SECTION_MSG_TRANSPORT; if (strcasecmp(section, "ntp") == 0) return SECTION_NTP; if (strcasecmp(section, "gui") == 0) return SECTION_GUI; @@ -970,11 +957,6 @@ static struct utun_config* parse_config_internal(FILE *fp, const char *filename) cfg->global.tcp_recv_buf = atoi(value); } break; - case SECTION_MSG_TRANSPORT: - if (parse_msg_transport(key, value, &cfg->global, filename, line_num) < 0) { - // 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 @@ -1122,7 +1104,6 @@ struct utun_config* parse_config_from_buf(const char *buf, size_t len, const cha case SECTION_NAT: cfg->global.nat_enabled = 1; parse_nat(key, value, &cfg->global, filename, line_num); break; case SECTION_TCP_PROXY_CLIENT: cfg->global.tcp_proxy_client_enabled = 1; parse_tcp_proxy_client(key, value, &cfg->global, filename, line_num); break; case SECTION_TCP_PROXY_SERVER: cfg->global.tcp_proxy_server_enabled = 1; if (strcmp(key, "tcp_recv_buf") == 0) cfg->global.tcp_recv_buf = atoi(value); break; - case SECTION_MSG_TRANSPORT: parse_msg_transport(key, value, &cfg->global, filename, line_num); break; case SECTION_NETWORK: if (cur_network) parse_network(key, value, cur_network, filename, line_num); break; case SECTION_NTP: if (strcmp(key, "enabled") == 0) cfg->global.ntp_enabled = strcasecmp(value, "yes") == 0 || strcasecmp(value, "1") == 0 || strcasecmp(value, "true") == 0; else if (strcmp(key, "server") == 0) { struct CFG_NTP_SERVER *ns = u_calloc(1, sizeof(struct CFG_NTP_SERVER)); if (ns) { strncpy(ns->name, value, sizeof(ns->name) - 1); ns->name[sizeof(ns->name) - 1] = '\0'; ns->next = cfg->global.ntp_servers; cfg->global.ntp_servers = ns; cfg->global.ntp_server_count++; } } else if (strcmp(key, "interval") == 0) { cfg->global.ntp_resync_interval = atoi(value); if (cfg->global.ntp_resync_interval < 60) cfg->global.ntp_resync_interval = 60; } else DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "%s:%d: Unknown ntp option '%s'", filename, line_num, key); break; case SECTION_GUI: break; diff --git a/src/config_parser.h b/src/config_parser.h index 35408c74..fcbae86b 100644 --- a/src/config_parser.h +++ b/src/config_parser.h @@ -115,8 +115,6 @@ struct global_config { int mtu; struct sockaddr_storage control_sock; char control_ip[MAX_ADDR_LEN]; // Control server IP address - struct sockaddr_storage msg_transport_sock; - // Debug and logging configuration char log_file[256]; // Path to log file (empty = stdout) char db_path[256]; // Path to SQLite database (empty = disabled) diff --git a/src/config_parser_doc.md b/src/config_parser_doc.md index f3040960..096cdbed 100644 --- a/src/config_parser_doc.md +++ b/src/config_parser_doc.md @@ -68,8 +68,6 @@ free_config(cfg); | `[nat]` | `parse_nat()` | `tun_ifname`, `tun_ip`, `nat_via`, `port_start`, `port_end`, `forward` (proto:ip:in_port:ext_port) | | `[tcp_proxy_client]` | `parse_tcp_proxy_client()` | `enabled`, `tun_name`, `tun_ip`, `mtu`, `via_node`, `socks_*`, `http_proxy_*`, `forward` (port -> ip:port) | | `[tcp_proxy_server]` | inline | `tcp_recv_buf` | -| `[msg_transport]` | `parse_msg_transport()` | `port` | -| `[debug]` | inline | `категория=уровень` (до 16 категорий) | | `[ntp]` | inline | `enabled`, `server`, `interval` | | `[gui]` | игнорируется | (зарезервировано) | diff --git a/src/msg_transport.c b/src/msg_transport.c deleted file mode 100644 index b715cc18..00000000 --- a/src/msg_transport.c +++ /dev/null @@ -1,638 +0,0 @@ -/* - * msg_transport.c — TCP-сервер транспорта сообщений (local IPC → ETCP) - * - * Принимает TCP-соединения от локальных приложений (протокол msg_transport.h), - * привязывает к remote peer и пересылает данные через etcp_router. - */ - -#include "msg_transport.h" -#include "utun_instance.h" -#include "etcp_router.h" -#include "etcp.h" -#include "secure_channel.h" -#include "topo_group.h" -#include "../lib/u_async.h" -#include "../lib/debug_config.h" -#include "../lib/mem.h" - -#include -#include - -#ifdef _WIN32 -#include -#include -#else -#include -#include -#include -#include -#include -#include -#endif - -#ifndef DEBUG_CATEGORY_MSGTRANSPORT -#define DEBUG_CATEGORY_MSGTRANSPORT DEBUG_CATEGORY_GENERAL -#endif - -/* ============================================================================ - * Внутренние структуры - * ============================================================================ */ - -struct msg_client { - struct msg_client* next; - struct msg_transport* transport; - socket_t fd; - void* socket_id; - uint8_t recv_buffer[MSG_MAX_MSG_SIZE]; - uint16_t recv_len; - uint64_t bound_peer_id; /* 0 = не забинден */ - uint8_t is_localhost; /* 1 = подключение с loopback */ -}; - -struct msg_transport { - struct UTUN_INSTANCE* instance; - struct UASYNC* ua; - socket_t listen_fd; - void* listen_socket_id; - struct sockaddr_storage bind_addr; - struct msg_client* clients; - uint32_t client_count; - uint32_t max_clients; - uint8_t svc_id; - struct msg_transport_counters counters; -}; - -/* ============================================================================ - * Forward declarations - * ============================================================================ */ - -static void accept_callback(socket_t fd, void* arg); -static void client_read_callback(socket_t fd, void* arg); -static void client_except_callback(socket_t fd, void* arg); -static void close_client(struct msg_transport* t, struct msg_client* client); - -static void handle_client_data(struct msg_transport* t, struct msg_client* client); -static void on_etcp_recv(struct ETCP_CONN* conn, struct ll_entry* entry); - -static int forward_to_peer(struct msg_transport* t, uint64_t dst_peer_id, - const uint8_t* data, size_t data_len, int is_signed); -static void send_response(struct msg_client* client, uint8_t type, uint64_t id, - const uint8_t* data, size_t data_len); -static void send_error(struct msg_client* client, uint8_t error_code, const char* msg); - -/* ============================================================================ - * Инициализация / завершение - * ============================================================================ */ - -int msg_transport_init(struct msg_transport** out, - struct UTUN_INSTANCE* instance, - struct UASYNC* ua, - struct sockaddr_storage* bind_addr, - uint32_t max_clients, - uint8_t svc_id) { - if (!out || !instance || !ua || !bind_addr) { - DEBUG_ERROR(DEBUG_CATEGORY_MSGTRANSPORT, "invalid args out=%p inst=%p ua=%p addr=%p", - (void*)out, (void*)instance, (void*)ua, (void*)bind_addr); - return -1; - } - if (bind_addr->ss_family == 0) { - DEBUG_INFO(DEBUG_CATEGORY_MSGTRANSPORT, "bind_addr has no family, skipping"); - *out = NULL; - return 0; - } - - struct msg_transport* t = u_calloc(1, sizeof(*t)); - if (!t) { - DEBUG_ERROR(DEBUG_CATEGORY_MSGTRANSPORT, "u_calloc failed"); - return -1; - } - t->instance = instance; - t->ua = ua; - t->max_clients = max_clients ? max_clients : 8; - t->svc_id = svc_id; - memcpy(&t->bind_addr, bind_addr, sizeof(*bind_addr)); - - int family = bind_addr->ss_family; - t->listen_fd = socket(family, SOCK_STREAM, IPPROTO_TCP); - -#ifdef _WIN32 - if (t->listen_fd == INVALID_SOCKET) { - DEBUG_ERROR(DEBUG_CATEGORY_MSGTRANSPORT, "socket() failed: %d", WSAGetLastError()); - u_free(t); return -1; - } - u_long nonblock = 1; - ioctlsocket(t->listen_fd, FIONBIO, &nonblock); - int reuse = 1; - setsockopt(t->listen_fd, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)); -#else - if (t->listen_fd < 0) { - DEBUG_ERROR(DEBUG_CATEGORY_MSGTRANSPORT, "socket() failed: %s", strerror(errno)); - u_free(t); return -1; - } - int reuse = 1; - setsockopt(t->listen_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); - int flags = fcntl(t->listen_fd, F_GETFL, 0); - if (flags >= 0) fcntl(t->listen_fd, F_SETFL, flags | O_NONBLOCK); -#endif - - socklen_t addr_len = (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); - -#ifdef _WIN32 - if (bind(t->listen_fd, (struct sockaddr*)bind_addr, addr_len) == SOCKET_ERROR) { - DEBUG_ERROR(DEBUG_CATEGORY_MSGTRANSPORT, "bind() failed: %d", WSAGetLastError()); - closesocket(t->listen_fd); u_free(t); return -1; - } - if (listen(t->listen_fd, 5) == SOCKET_ERROR) { - DEBUG_ERROR(DEBUG_CATEGORY_MSGTRANSPORT, "listen() failed: %d", WSAGetLastError()); - closesocket(t->listen_fd); u_free(t); return -1; - } -#else - if (bind(t->listen_fd, (struct sockaddr*)bind_addr, addr_len) < 0) { - DEBUG_ERROR(DEBUG_CATEGORY_MSGTRANSPORT, "bind() failed: %s", strerror(errno)); - close(t->listen_fd); u_free(t); return -1; - } - if (listen(t->listen_fd, 5) < 0) { - DEBUG_ERROR(DEBUG_CATEGORY_MSGTRANSPORT, "listen() failed: %s", strerror(errno)); - close(t->listen_fd); u_free(t); return -1; - } -#endif - - t->listen_socket_id = uasync_add_socket_t(ua, t->listen_fd, - accept_callback, NULL, NULL, t); - if (!t->listen_socket_id) { - DEBUG_ERROR(DEBUG_CATEGORY_MSGTRANSPORT, "uasync_add_socket_t failed for listen_fd"); -#ifdef _WIN32 - closesocket(t->listen_fd); -#else - close(t->listen_fd); -#endif - u_free(t); return -1; - } - - if (etcp_router_bind(instance, svc_id, on_etcp_recv) != 0) { - DEBUG_ERROR(DEBUG_CATEGORY_MSGTRANSPORT, "etcp_router_bind(svc_id=%u) failed", svc_id); - uasync_remove_socket_t(ua, t->listen_fd); -#ifdef _WIN32 - closesocket(t->listen_fd); -#else - close(t->listen_fd); -#endif - u_free(t); return -1; - } - - if (family == AF_INET) { - struct sockaddr_in* sin = (struct sockaddr_in*)bind_addr; - DEBUG_INFO(DEBUG_CATEGORY_MSGTRANSPORT, "msg_transport listening on %s:%d svc_id=%u", - ip_to_str(&sin->sin_addr, AF_INET).str, ntohs(sin->sin_port), svc_id); - } else { - struct sockaddr_in6* sin6 = (struct sockaddr_in6*)bind_addr; - DEBUG_INFO(DEBUG_CATEGORY_MSGTRANSPORT, "msg_transport listening on [%s]:%d svc_id=%u", - ip_to_str(&sin6->sin6_addr, AF_INET6).str, ntohs(sin6->sin6_port), svc_id); - } - - *out = t; - return 0; -} - -void msg_transport_shutdown(struct msg_transport* t) { - if (!t) return; - - while (t->clients) close_client(t, t->clients); - -#ifdef _WIN32 - if (t->listen_fd != INVALID_SOCKET) { - uasync_remove_socket_t(t->ua, t->listen_fd); - t->listen_socket_id = NULL; - closesocket(t->listen_fd); - t->listen_fd = INVALID_SOCKET; - } -#else - if (t->listen_fd >= 0) { - uasync_remove_socket_t(t->ua, t->listen_fd); - t->listen_socket_id = NULL; - close(t->listen_fd); - t->listen_fd = -1; - } -#endif - - DEBUG_INFO(DEBUG_CATEGORY_MSGTRANSPORT, "msg_transport shutdown complete svc_id=%u", t->svc_id); - memset(t, 0, sizeof(*t)); - u_free(t); -} - -void msg_transport_get_counters(struct msg_transport* t, struct msg_transport_counters* c) { - if (t && c) memcpy(c, &t->counters, sizeof(*c)); -} - -/* ============================================================================ - * TCP-клиенты: accept / read / close - * ============================================================================ */ - -static void accept_callback(socket_t fd, void* arg) { - struct msg_transport* t = (struct msg_transport*)arg; - - struct sockaddr_storage client_addr; - socklen_t addr_len = sizeof(client_addr); - -#ifdef _WIN32 - socket_t client_fd = accept(fd, (struct sockaddr*)&client_addr, &addr_len); - if (client_fd == INVALID_SOCKET) { - int err = WSAGetLastError(); - if (err != WSAEWOULDBLOCK) - DEBUG_ERROR(DEBUG_CATEGORY_MSGTRANSPORT, "accept() failed: %d", err); - return; - } - u_long nonblock = 1; - ioctlsocket(client_fd, FIONBIO, &nonblock); -#else - socket_t client_fd = accept(fd, (struct sockaddr*)&client_addr, &addr_len); - if (client_fd < 0) { - if (errno != EAGAIN && errno != EWOULDBLOCK) - DEBUG_ERROR(DEBUG_CATEGORY_MSGTRANSPORT, "accept() failed: %s", strerror(errno)); - return; - } - int flags = fcntl(client_fd, F_GETFL, 0); - if (flags >= 0) fcntl(client_fd, F_SETFL, flags | O_NONBLOCK); -#endif - - if (t->client_count >= t->max_clients) { - DEBUG_WARN(DEBUG_CATEGORY_MSGTRANSPORT, "max_clients=%u reached, rejecting", t->max_clients); -#ifdef _WIN32 - closesocket(client_fd); -#else - close(client_fd); -#endif - return; - } - - struct msg_client* client = u_calloc(1, sizeof(*client)); - if (!client) { - DEBUG_ERROR(DEBUG_CATEGORY_MSGTRANSPORT, "u_calloc(msg_client) failed"); -#ifdef _WIN32 - closesocket(client_fd); -#else - close(client_fd); -#endif - return; - } - client->fd = client_fd; - client->transport = t; - - /* Определяем loopback */ - if (client_addr.ss_family == AF_INET) { - struct sockaddr_in* sin = (struct sockaddr_in*)&client_addr; - client->is_localhost = (ntohl(sin->sin_addr.s_addr) == 0x7F000001u); /* 127.0.0.1 */ - } else if (client_addr.ss_family == AF_INET6) { - struct sockaddr_in6* sin6 = (struct sockaddr_in6*)&client_addr; - static const uint8_t loopback_v6[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}; - client->is_localhost = (memcmp(&sin6->sin6_addr, loopback_v6, 16) == 0); - } else { - client->is_localhost = 0; - } - - client->socket_id = uasync_add_socket_t(t->ua, client_fd, - client_read_callback, NULL, - client_except_callback, client); - if (!client->socket_id) { - DEBUG_ERROR(DEBUG_CATEGORY_MSGTRANSPORT, "uasync_add_socket_t failed for client"); - u_free(client); -#ifdef _WIN32 - closesocket(client_fd); -#else - close(client_fd); -#endif - return; - } - - client->next = t->clients; - t->clients = client; - t->client_count++; - t->counters.accepted++; - - DEBUG_INFO(DEBUG_CATEGORY_MSGTRANSPORT, "msg_transport client connected (total=%u)", t->client_count); -} - -static void client_read_callback(socket_t fd, void* arg) { - struct msg_client* client = (struct msg_client*)arg; - struct msg_transport* t = client->transport; - - uint8_t* buf = client->recv_buffer + client->recv_len; - size_t buf_space = MSG_MAX_MSG_SIZE - client->recv_len; - -#ifdef _WIN32 - int received = recv(fd, (char*)buf, (int)buf_space, 0); - if (received == SOCKET_ERROR) { - int err = WSAGetLastError(); - if (err != WSAEWOULDBLOCK) { - if (err == 10054) { close_client(t, client); return; } - DEBUG_ERROR(DEBUG_CATEGORY_MSGTRANSPORT, "recv() error: %d", err); - close_client(t, client); - } - return; - } -#else - ssize_t received = recv(fd, buf, buf_space, 0); - if (received < 0) { - if (errno != EAGAIN && errno != EWOULDBLOCK) { - DEBUG_ERROR(DEBUG_CATEGORY_MSGTRANSPORT, "recv() error: %s", strerror(errno)); - close_client(t, client); - } - return; - } -#endif - if (received == 0) { - close_client(t, client); - return; - } - - client->recv_len += (uint16_t)received; - if (client->recv_len > MSG_MAX_MSG_SIZE) { - DEBUG_ERROR(DEBUG_CATEGORY_MSGTRANSPORT, "recv buffer overflow"); - close_client(t, client); - return; - } - handle_client_data(t, client); -} - -static void client_except_callback(socket_t fd, void* arg) { - struct msg_client* client = (struct msg_client*)arg; - DEBUG_ERROR(DEBUG_CATEGORY_MSGTRANSPORT, "client socket exception"); - close_client(client->transport, client); - (void)fd; -} - -static void close_client(struct msg_transport* t, struct msg_client* client) { - if (!t || !client) return; - -#ifdef _WIN32 - if (client->fd != INVALID_SOCKET) { - uasync_remove_socket_t(t->ua, client->fd); - closesocket(client->fd); - } -#else - if (client->fd >= 0) { - uasync_remove_socket_t(t->ua, client->fd); - close(client->fd); - } -#endif - - struct msg_client** curr = &t->clients; - while (*curr) { - if (*curr == client) { *curr = client->next; break; } - curr = &(*curr)->next; - } - t->client_count--; - t->counters.closed++; - u_free(client); - - DEBUG_INFO(DEBUG_CATEGORY_MSGTRANSPORT, "msg_transport client disconnected (total=%u)", t->client_count); -} - -/* ============================================================================ - * Обработка входящих сообщений от TCP-клиента - * ============================================================================ */ - -static void handle_client_data(struct msg_transport* t, struct msg_client* client) { - while (client->recv_len >= MSG_HDR_SIZE) { - struct msg_header* hdr = (struct msg_header*)client->recv_buffer; - - if (msg_validate_header(hdr) != 0) { - DEBUG_ERROR(DEBUG_CATEGORY_MSGTRANSPORT, "invalid header size=%u type=0x%02x", hdr->size, hdr->type); - send_error(client, MSG_ERR_INVALID_MSG, "Invalid message header"); - close_client(t, client); - return; - } - if (client->recv_len < hdr->size) break; - - uint8_t* payload = client->recv_buffer + MSG_HDR_SIZE; - uint16_t payload_size = hdr->size - MSG_HDR_SIZE; - - switch (hdr->type) { - - case MSG_CTL_BIND: { - uint64_t peer_id = hdr->id; - if (peer_id == 0) { - send_error(client, MSG_ERR_INVALID_MSG, "BIND with zero peer_id"); - break; - } - /* Проверить конфликт: этот peer_id уже занят другим клиентом */ - struct msg_client* other = t->clients; - while (other) { - if (other != client && other->bound_peer_id == peer_id) { - send_error(client, MSG_ERR_ID_TAKEN, "peer_id already bound by another client"); - DEBUG_WARN(DEBUG_CATEGORY_MSGTRANSPORT, "BIND peer=%016llx rejected: already bound", - (unsigned long long)peer_id); - break; - } - other = other->next; - } - if (other) break; /* конфликт */ - client->bound_peer_id = peer_id; - send_response(client, MSG_RSP_BIND_OK, peer_id, NULL, 0); - t->counters.bind_count++; - DEBUG_INFO(DEBUG_CATEGORY_MSGTRANSPORT, "BIND peer=%016llx", (unsigned long long)peer_id); - break; - } - - case MSG_CTL_UNBIND: - client->bound_peer_id = 0; - t->counters.unbind_count++; - DEBUG_INFO(DEBUG_CATEGORY_MSGTRANSPORT, "UNBIND"); - break; - - case MSG_CTL_GET_PUBKEY: - send_response(client, MSG_RSP_PUBKEY, 0, - t->instance->my_keys.public_key, SC_PUBKEY_SIZE); - break; - - case MSG_CTL_GET_PRIVKEY: - if (!client->is_localhost) { - send_error(client, MSG_ERR_ACCESS_DENIED, "private key only available from localhost"); - DEBUG_WARN(DEBUG_CATEGORY_MSGTRANSPORT, "GET_PRIVKEY denied: not localhost"); - break; - } - send_response(client, MSG_RSP_PRIVKEY, 0, - t->instance->my_keys.private_key, SC_PRIVKEY_SIZE); - break; - - case MSG_CTL_GET_PEER_INFO: { - uint64_t peer_id = hdr->id; - struct TOPO_GROUP* group = topo_groups_get_default(t->instance->topo_groups); - if (!group) { - send_error(client, MSG_ERR_PEER_NOT_FOUND, "BGP not initialized"); - break; - } - struct TOPO_NODEQ* nq = topo_node_find_by_id(group, peer_id); - if (!nq) { - send_error(client, MSG_ERR_PEER_NOT_FOUND, "peer not found"); - DEBUG_WARN(DEBUG_CATEGORY_MSGTRANSPORT, "GET_PEER_INFO: peer=%016llx not found", - (unsigned long long)peer_id); - break; - } - uint8_t buf[SC_PUBKEY_SIZE * 2]; - memcpy(buf, nq->node->public_key, SC_PUBKEY_SIZE); - memcpy(buf + SC_PUBKEY_SIZE, nq->node->ed25519_public_key, SC_PUBKEY_SIZE); - send_response(client, MSG_RSP_PEER_INFO, peer_id, buf, SC_PUBKEY_SIZE * 2); - DEBUG_INFO(DEBUG_CATEGORY_MSGTRANSPORT, "GET_PEER_INFO: peer=%016llx sent pubkey+edpub", - (unsigned long long)peer_id); - break; - } - - case MSG_DATA_SEND: { - uint64_t dst = hdr->id ? hdr->id : client->bound_peer_id; - if (dst == 0) { - send_error(client, MSG_ERR_NOT_BOUND, "Not bound to any peer"); - break; - } - if (payload_size == 0) break; - int is_signed = (hdr->options & MSG_OPT_SIGNED) ? 1 : 0; - if (forward_to_peer(t, dst, payload, payload_size, is_signed) != 0) { - send_error(client, MSG_ERR_SEND_FAILED, "Failed to forward message to peer"); - t->counters.drops_no_route++; - } - break; - } - - default: - DEBUG_WARN(DEBUG_CATEGORY_MSGTRANSPORT, "unknown message type 0x%02x from client", hdr->type); - send_error(client, MSG_ERR_INVALID_MSG, "Unknown message type"); - break; - } - - uint16_t msg_size = hdr->size; - if (client->recv_len > msg_size) - memmove(client->recv_buffer, client->recv_buffer + msg_size, client->recv_len - msg_size); - client->recv_len -= msg_size; - } -} - -/* ============================================================================ - * Отправка пиру через etcp_router - * ============================================================================ */ - -static int forward_to_peer(struct msg_transport* t, uint64_t dst_peer_id, - const uint8_t* data, size_t data_len, int is_signed) { - struct ETCP_ROUTER_CONN* rconn = etcp_router_conn_get(t->instance, dst_peer_id, t->svc_id); - if (!rconn) { - DEBUG_WARN(DEBUG_CATEGORY_MSGTRANSPORT, "forward_to_peer: no route to %016llx", (unsigned long long)dst_peer_id); - return -1; - } - - int ret; - if (is_signed) { - ret = etcp_router_conn_send_signed(rconn, data, data_len); - } else { - ret = etcp_router_conn_send(rconn, data, data_len); - } - if (ret != 0) { - DEBUG_WARN(DEBUG_CATEGORY_MSGTRANSPORT, "forward_to_peer: send failed to %016llx (signed=%d)", - (unsigned long long)dst_peer_id, is_signed); - return -1; - } - t->counters.msg_sent_to_peer++; - return 0; -} - -/* ============================================================================ - * Приём от пира через etcp_router → доставка TCP-клиенту - * ============================================================================ */ - -static void on_etcp_recv(struct ETCP_CONN* conn, struct ll_entry* entry) { - if (!conn || !entry) return; - struct UTUN_INSTANCE* inst = conn->instance; - if (!inst) { queue_dgram_free(entry); queue_entry_free(entry); return; } - - struct msg_transport* t = inst->msg_t; - if (!t) { - DEBUG_WARN(DEBUG_CATEGORY_MSGTRANSPORT, "msg_transport not initialized on instance"); - queue_dgram_free(entry); queue_entry_free(entry); return; - } - - uint8_t* payload = entry->dgram + 1; - size_t payload_len = entry->len - 1; - uint64_t src_node_id = conn->peer_node_id; - - DEBUG_TRACE(DEBUG_CATEGORY_MSGTRANSPORT, "from %016llx len=%zu", - (unsigned long long)src_node_id, payload_len); - - /* Ищем клиента привязанного к этому пиру */ - struct msg_client* client = t->clients; - while (client) { - if (client->bound_peer_id == src_node_id) break; - client = client->next; - } - - if (!client) { - DEBUG_WARN(DEBUG_CATEGORY_MSGTRANSPORT, "no client bound to %016llx, dropping", - (unsigned long long)src_node_id); - t->counters.drops_no_client++; - queue_dgram_free(entry); - queue_entry_free(entry); - return; - } - - t->counters.msg_recv_from_peer++; - - /* Формируем MSG_DATA_RECV */ - size_t total = MSG_HDR_SIZE + payload_len; - uint8_t* buf = u_malloc(total); - if (!buf) { - DEBUG_ERROR(DEBUG_CATEGORY_MSGTRANSPORT, "u_malloc failed"); - queue_dgram_free(entry); queue_entry_free(entry); return; - } - struct msg_header* hdr = (struct msg_header*)buf; - msg_build_header(hdr, (uint16_t)payload_len, MSG_DATA_RECV, src_node_id, 0); - memcpy(buf + MSG_HDR_SIZE, payload, payload_len); - -#ifdef _WIN32 - send(client->fd, (const char*)buf, (int)total, 0); -#else - send(client->fd, buf, total, 0); -#endif - u_free(buf); - t->counters.msg_sent_to_client++; - - queue_dgram_free(entry); - queue_entry_free(entry); -} - -/* ============================================================================ - * Помощники отправки ответов TCP-клиенту - * ============================================================================ */ - -static void send_response(struct msg_client* client, uint8_t type, uint64_t id, - const uint8_t* data, size_t data_len) { - size_t total = MSG_HDR_SIZE + data_len; - uint8_t* buf = u_malloc(total); - if (!buf) return; - - struct msg_header* hdr = (struct msg_header*)buf; - msg_build_header(hdr, (uint16_t)data_len, type, id, 0); - if (data_len > 0) memcpy(buf + MSG_HDR_SIZE, data, data_len); - -#ifdef _WIN32 - send(client->fd, (const char*)buf, (int)total, 0); -#else - send(client->fd, buf, total, 0); -#endif - u_free(buf); -} - -static void send_error(struct msg_client* client, uint8_t error_code, const char* msg) { - size_t msg_len = strlen(msg); - size_t total = MSG_HDR_SIZE + 1 + msg_len; - uint8_t* buf = u_malloc(total); - if (!buf) return; - - struct msg_header* hdr = (struct msg_header*)buf; - msg_build_header(hdr, (uint16_t)(1 + msg_len), MSG_RSP_ERROR, 0, 0); - buf[MSG_HDR_SIZE] = error_code; - memcpy(buf + MSG_HDR_SIZE + 1, msg, msg_len); - -#ifdef _WIN32 - send(client->fd, (const char*)buf, (int)total, 0); -#else - send(client->fd, buf, total, 0); -#endif - u_free(buf); -} diff --git a/src/msg_transport.h b/src/msg_transport.h deleted file mode 100644 index 54169402..00000000 --- a/src/msg_transport.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * msg_transport.h — TCP-сервер транспорта сообщений (local IPC → ETCP) - * - * Принимает TCP-соединения от локальных приложений. - * Каждое соединение привязывается (BIND) к конкретному remote peer node_id. - * Сообщения от локального клиента пересылаются пиру через etcp_router, - * сообщения от пира доставляются локальному клиенту. - * - * Формат фрейма на TCP: - * [size:2 (uint16_t, native endian)] [type:1] [id:8 (uint64_t)] [options:1] [data...] - * size включает само поле size. - */ - -#ifndef MSG_TRANSPORT_H -#define MSG_TRANSPORT_H - -#include -#include "../lib/socket_compat.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* ============================================================================ - * Протокол - * ============================================================================ */ - -#define MSG_MAX_MSG_SIZE 8192 -#define MSG_SIGN_SIZE 64 /* Ed25519 */ - -/* Options byte bits */ -#define MSG_OPT_SIGNED 0x01 - -/* Типы сообщений */ -#define MSG_CTL_BIND 0x01 /* GUI→utun: привязать TCP-соединение к пиру id */ -#define MSG_CTL_UNBIND 0x02 /* GUI→utun: отвязать */ -#define MSG_CTL_GET_PUBKEY 0x03 /* GUI→utun: запросить публичный ключ */ -#define MSG_CTL_GET_PRIVKEY 0x04 /* GUI→utun: запросить приватный ключ (только localhost) */ -#define MSG_CTL_GET_PEER_INFO 0x05 /* GUI→utun: запросить ключи пира id (pubkey + ed25519_pubkey) */ -#define MSG_DATA_SEND 0x10 /* GUI→utun: отправить сообщение пиру id */ -#define MSG_DATA_RECV 0x11 /* utun→GUI: получено сообщение от пира id */ -#define MSG_RSP_BIND_OK 0xE1 /* utun→GUI: BIND успешен */ -#define MSG_RSP_PUBKEY 0xE2 /* utun→GUI: публичный ключ (32 байта) */ -#define MSG_RSP_PRIVKEY 0xE3 /* utun→GUI: приватный ключ (32 байта) */ -#define MSG_RSP_PEER_INFO 0xE4 /* utun→GUI: ключи пира (pubkey+edpub=64 байта) */ -#define MSG_RSP_ERROR 0xFF /* utun→GUI: ошибка */ - -/* Коды ошибок для MSG_RSP_ERROR */ -#define MSG_ERR_INVALID_MSG 0x01 -#define MSG_ERR_NOT_BOUND 0x02 -#define MSG_ERR_NO_ROUTE 0x03 -#define MSG_ERR_SEND_FAILED 0x04 -#define MSG_ERR_ACCESS_DENIED 0x07 -#define MSG_ERR_PEER_NOT_FOUND 0x08 -#define MSG_ERR_ID_TAKEN 0x06 - -#pragma pack(push, 1) -struct msg_header { - uint16_t size; /* полный размер сообщения, включая это поле */ - uint8_t type; /* тип (MSG_CTL_* / MSG_DATA_* / MSG_RSP_*) */ - uint64_t id; /* peer node_id */ - uint8_t options; /* битовые флаги (MSG_OPT_*) */ -}; -#pragma pack(pop) - -#define MSG_HDR_SIZE sizeof(struct msg_header) /* 12 */ - -static inline void msg_build_header(struct msg_header* hdr, - uint16_t payload_size, - uint8_t msg_type, - uint64_t id, - uint8_t options) { - hdr->size = MSG_HDR_SIZE + payload_size; - hdr->type = msg_type; - hdr->id = id; - hdr->options = options; -} - -static inline int msg_validate_header(const struct msg_header* hdr) { - if (hdr->size < MSG_HDR_SIZE || hdr->size > MSG_MAX_MSG_SIZE) return -1; - return 0; -} - -/* ============================================================================ - * Счётчики (диагностика) - * ============================================================================ */ - -struct UTUN_INSTANCE; -struct UASYNC; - -struct msg_transport; - -struct msg_transport_counters { - uint64_t accepted; - uint64_t closed; - uint64_t bind_count; - uint64_t unbind_count; - uint64_t msg_sent_to_peer; - uint64_t msg_recv_from_peer; - uint64_t msg_sent_to_client; - uint64_t errors; - uint64_t drops_no_client; - uint64_t drops_no_route; -}; - -/* ============================================================================ - * API - * ============================================================================ */ - -int msg_transport_init(struct msg_transport** out, - struct UTUN_INSTANCE* instance, - struct UASYNC* ua, - struct sockaddr_storage* bind_addr, - uint32_t max_clients, - uint8_t svc_id); - -void msg_transport_shutdown(struct msg_transport* t); - -void msg_transport_get_counters(struct msg_transport* t, - struct msg_transport_counters* c); - -#ifdef __cplusplus -} -#endif - -#endif /* MSG_TRANSPORT_H */ diff --git a/src/msg_transport_doc.md b/src/msg_transport_doc.md deleted file mode 100644 index 0afb322e..00000000 --- a/src/msg_transport_doc.md +++ /dev/null @@ -1,69 +0,0 @@ -# Msg Transport (msg_transport) - -## 1. Назначение -TCP-сервер для обмена сообщениями между локальными приложениями (например, chatgui) и удалёнными пирами через ETCP. Принимает TCP-соединения от локальных клиентов, привязывает (BIND) их к конкретному `peer_node_id` и пересылает данные туда-обратно через `etcp_router`. Поддерживает подписанные сообщения (Ed25519). - -## 2. Как пользоваться -1. Вызвать `msg_transport_init()` — создаёт слушающий TCP-сокет, регистрирует callback `on_etcp_recv` в `etcp_router_bind()`. -2. Локальное приложение (chatgui) подключается по TCP и шлёт фреймы протокола. -3. При остановке вызвать `msg_transport_shutdown()`. - -**Протокол фрейма:** -``` -[size:2][type:1][id:8][options:1][data...] -``` -- `size` — полный размер (включая поле size), native endian, до 8192 байт. -- `type` — команда (`MSG_CTL_*`, `MSG_DATA_*`, `MSG_RSP_*`). -- `id` — `peer_node_id` (uint64_t). -- `options` — битовые флаги (`MSG_OPT_SIGNED = 0x01`). - -**Нюансы:** -- Приватный ключ (`GET_PRIVKEY`) отдаётся только подключениям с loopback (127.0.0.1 / ::1). -- Каждый `peer_id` может быть забинден только одним клиентом одновременно. -- Сообщения от пира без привязанного клиента молча дропаются (счётчик `drops_no_client`). - -## 3. API - -### Структуры - -| Структура | Назначение | -|-----------|-----------| -| `struct msg_transport` | Состояние сервера: `listen_fd`, связный список `clients`, `svc_id`, счётчики. | -| `struct msg_client` | Состояние TCP-клиента: `fd`, буфер приёма, `bound_peer_id`, флаг `is_localhost`. | -| `struct msg_header` | Заголовок фрейма: `size`, `type`, `id`, `options` (12 байт, packed). | -| `struct msg_transport_counters` | Счётчики: accepted, closed, bind/unbind, msg_sent/recv, errors, drops. | - -### Функции - -| Функция | Назначение | -|---------|-----------| -| `msg_transport_init(out, instance, ua, bind_addr, max_clients, svc_id)` | Создать сервер, привязаться к порту, зарегистрировать `svc_id` в `etcp_router_bind`. | -| `msg_transport_shutdown(t)` | Закрыть всех клиентов, освободить сокет. | -| `msg_transport_get_counters(t, c)` | Скопировать счётчики в переданную структуру. | -| `msg_build_header(hdr, payload_size, msg_type, id, options)` | Заполнить заголовок фрейма (inline). | -| `msg_validate_header(hdr)` | Проверить корректность заголовка (inline). | - -### Типы сообщений - -| Тип | Направление | Описание | -|-----|-------------|----------| -| `MSG_CTL_BIND` (0x01) | GUI→utun | Привязать TCP-соединение к пиру `id`. Ответ: `RSP_BIND_OK`. | -| `MSG_CTL_UNBIND` (0x02) | GUI→utun | Отвязать соединение. | -| `MSG_CTL_GET_PUBKEY` (0x03) | GUI→utun | Запросить свой публичный ключ. Ответ: `RSP_PUBKEY` (32 байта). | -| `MSG_CTL_GET_PRIVKEY` (0x04) | GUI→utun | Запросить приватный ключ (только localhost). Ответ: `RSP_PRIVKEY` (32 байта). | -| `MSG_CTL_GET_PEER_INFO` (0x05) | GUI→utun | Запросить ключи пира `id`. Ответ: `RSP_PEER_INFO` (pubkey + ed25519_pubkey = 64 байта). | -| `MSG_DATA_SEND` (0x10) | GUI→utun | Отправить данные пиру `id` (через `etcp_router_conn_send` / `send_signed`). | -| `MSG_DATA_RECV` (0x11) | utun→GUI | Получены данные от пира `id`. | -| `MSG_RSP_ERROR` (0xFF) | utun→GUI | Ошибка (1 байт код + текст). | - -### Коды ошибок - -| Код | Константа | Описание | -|-----|-----------|----------| -| 0x01 | `MSG_ERR_INVALID_MSG` | Некорректный заголовок или тип. | -| 0x02 | `MSG_ERR_NOT_BOUND` | Нет привязки к пиру. | -| 0x03 | `MSG_ERR_NO_ROUTE` | Нет маршрута до пира. | -| 0x04 | `MSG_ERR_SEND_FAILED` | Ошибка отправки. | -| 0x06 | `MSG_ERR_ID_TAKEN` | `peer_id` уже занят другим клиентом. | -| 0x07 | `MSG_ERR_ACCESS_DENIED` | Доступ запрещён (например, `GET_PRIVKEY` не с loopback). | -| 0x08 | `MSG_ERR_PEER_NOT_FOUND` | Пир не найден в BGP-топологии. | diff --git a/src/nat_transport.c b/src/nat_transport.c index 0a9a5522..43da63b0 100644 --- a/src/nat_transport.c +++ b/src/nat_transport.c @@ -6,6 +6,7 @@ #include "tun_if.h" #include "etcp_api.h" #include "etcp_router.h" +#include "../routing_layer/topo_node.h" #include "../lib/debug_config.h" #include "../lib/mem.h" #include "../lib/ll_queue.h" @@ -47,7 +48,7 @@ static void nat_transport_client_tun_out_cb(struct ll_queue* q, void* arg) { queue_dgram_free(pkt); queue_entry_free(pkt); queue_resume_callback(q); - int ret = etcp_route_send(inst, tr->nat_via_node_id, new_entry, 0); + int ret = etcp_route_send(inst, TOPO_GROUP_UTUN, tr->nat_via_node_id, new_entry, 0); if (ret != 0) { DEBUG_WARN(DEBUG_CATEGORY_NAT, "NAT client: etcp_route_send to provider %016llx failed", (unsigned long long)tr->nat_via_node_id); @@ -90,7 +91,7 @@ static void nat_transport_provider_tun_out_cb(struct ll_queue* q, void* arg) { queue_dgram_free(pkt); queue_entry_free(pkt); queue_resume_callback(q); - int send_ret = etcp_route_send(inst, entry->src_node_id, new_entry, 0); + int send_ret = etcp_route_send(inst, TOPO_GROUP_UTUN, entry->src_node_id, new_entry, 0); if (send_ret != 0) { DEBUG_WARN(DEBUG_CATEGORY_NAT, "NAT provider: etcp_route_send back to node %016llx failed", (unsigned long long)entry->src_node_id); diff --git a/src/proxy/icmp_proxy.c b/src/proxy/icmp_proxy.c index df382a1b..35fed5f4 100644 --- a/src/proxy/icmp_proxy.c +++ b/src/proxy/icmp_proxy.c @@ -5,6 +5,7 @@ #include "etcp_router.h" #include "utun_instance.h" #include "tun_if.h" +#include "../routing_layer/topo_node.h" #include "../lib/u_async.h" #include "../lib/debug_config.h" #include "../lib/ll_queue.h" @@ -143,7 +144,7 @@ static void raw_read_cb(socket_t sock, void* arg) { memcpy(e->dgram + 20, &icmp_hdr->icmp_seq, 2); if (payload_len > 0) memcpy(e->dgram + ICMP_PROXY_HDR_SIZE, payload, payload_len); e->len = ICMP_PROXY_HDR_SIZE + payload_len; - int ret = etcp_route_send(g_icmp_ctx->inst, r->client_node_id, e, 0); + int ret = etcp_route_send(g_icmp_ctx->inst, TOPO_GROUP_UTUN, r->client_node_id, e, 0); if (ret != 0) DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "icmp_proxy: etcp_route_send reply failed: %d", ret); else DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "icmp_proxy: reply forwarded to client %016llx", (unsigned long long)r->client_node_id); u_free(r); @@ -181,7 +182,7 @@ static void exit_handle_request(struct ETCP_CONN* conn, struct ll_entry* entry) memcpy(e->dgram + 20, &echo_seq, 2); if (payload_len > 0) memcpy(e->dgram + ICMP_PROXY_HDR_SIZE, payload, payload_len); e->len = ICMP_PROXY_HDR_SIZE + payload_len; - etcp_route_send(inst, client_node_id, e, 0); + etcp_route_send(inst, TOPO_GROUP_UTUN, client_node_id, e, 0); } else queue_entry_free(e); } } else { @@ -246,7 +247,7 @@ int icmp_proxy_send_to_exit(struct UTUN_INSTANCE* inst, uint64_t exit_node_id, memcpy(e->dgram + 20, &echo_seq, 2); if (payload_len > 0) memcpy(e->dgram + ICMP_PROXY_HDR_SIZE, payload, payload_len); e->len = ICMP_PROXY_HDR_SIZE + payload_len; - return etcp_route_send(inst, exit_node_id, e, 0); + return etcp_route_send(inst, TOPO_GROUP_UTUN, exit_node_id, e, 0); } // ==================================================================== diff --git a/src/proxy/socks_proxy.c b/src/proxy/socks_proxy.c index 33f459b0..80db5a91 100644 --- a/src/proxy/socks_proxy.c +++ b/src/proxy/socks_proxy.c @@ -5,6 +5,7 @@ #include "etcp_api.h" #include "etcp_router.h" #include "utun_instance.h" +#include "../routing_layer/topo_node.h" #include "../lib/u_async.h" #include "../lib/debug_config.h" #include "../lib/ll_queue.h" @@ -29,7 +30,7 @@ static void on_error_cb(struct tcp_conn* tc, int err, void* arg); static void on_closed_cb(struct tcp_conn* tc, void* arg); static void tx_waiter_cb(struct ll_queue* q, void* arg); -static int send_msg(struct UTUN_INSTANCE* inst, uint64_t dst, uint8_t subcmd, uint32_t sid, const uint8_t* data, size_t len, int force); +static int send_msg(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t dst, uint8_t subcmd, uint32_t sid, const uint8_t* data, size_t len, int force); struct listen_ctx { socket_t listen_sock; @@ -46,7 +47,7 @@ struct listen_ctx { // ==================================================================== // Отправка сообщений через ETCP // ==================================================================== -static int send_msg(struct UTUN_INSTANCE* inst, uint64_t dst, uint8_t subcmd, uint32_t sid, const uint8_t* data, size_t len, int force) { +static int send_msg(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t dst, uint8_t subcmd, uint32_t sid, const uint8_t* data, size_t len, int force) { struct ll_entry* e = queue_entry_new(0); if (!e) { DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "socks_proxy: queue_entry_new failed subcmd=%02x sid=%08x", subcmd, sid); return -1; } e->dgram = u_malloc(TCP_PROXY_HDR_SIZE + len); @@ -60,7 +61,7 @@ static int send_msg(struct UTUN_INSTANCE* inst, uint64_t dst, uint8_t subcmd, ui queue_dgram_free(e); queue_entry_free(e); return -1; } e->len = (uint16_t)(TCP_PROXY_HDR_SIZE + len); - int ret = etcp_route_send(inst, dst, e, force); + int ret = etcp_route_send(inst, group_id, dst, e, force); DEBUG_TRACE(DEBUG_CATEGORY_TRAFFIC, "SOCKS send_msg subcmd=%02x sid=%08x len=%zu force=%d → ret=%d", subcmd, sid, len, force, ret); return ret; @@ -72,28 +73,28 @@ static int send_connect(struct socks_proxy_conn* c) { DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "SOCKS proxy: CONNECT sid=%08x to %d.%d.%d.%d:%d via_node=%016llx %s", c->stream_id, c->dest_ip[0], c->dest_ip[1], c->dest_ip[2], c->dest_ip[3], ntohs(c->dest_port), (unsigned long long)c->via_node_id, c->is_http ? "http" : "socks"); - return send_msg(c->inst, c->via_node_id, TCP_PROXY_SUBCMD_CONNECT, c->stream_id, buf, 6, 1); + return send_msg(c->inst, TOPO_GROUP_UTUN, c->via_node_id, TCP_PROXY_SUBCMD_CONNECT, c->stream_id, buf, 6, 1); } static int send_data(struct socks_proxy_conn* c, const uint8_t* data, uint16_t len) { - return send_msg(c->inst, c->via_node_id, TCP_PROXY_SUBCMD_DATA, c->stream_id, data, len, 0); + return send_msg(c->inst, TOPO_GROUP_UTUN, c->via_node_id, TCP_PROXY_SUBCMD_DATA, c->stream_id, data, len, 0); } static void send_close(struct socks_proxy_conn* c) { DEBUG_TRACE(DEBUG_CATEGORY_TRAFFIC, "SOCKS send CLOSE sid=%08x", c->stream_id); - if (send_msg(c->inst, c->via_node_id, TCP_PROXY_SUBCMD_CLOSE, c->stream_id, NULL, 0, 1) < 0) c->close_pending = 1; + if (send_msg(c->inst, TOPO_GROUP_UTUN, c->via_node_id, TCP_PROXY_SUBCMD_CLOSE, c->stream_id, NULL, 0, 1) < 0) c->close_pending = 1; else { c->close_pending = 0; c->close_sent = 1; } } static void send_error(struct socks_proxy_conn* c) { DEBUG_TRACE(DEBUG_CATEGORY_TRAFFIC, "SOCKS send ERROR sid=%08x", c->stream_id); - if (send_msg(c->inst, c->via_node_id, TCP_PROXY_SUBCMD_ERROR, c->stream_id, NULL, 0, 1) < 0) c->close_pending = 1; + if (send_msg(c->inst, TOPO_GROUP_UTUN, c->via_node_id, TCP_PROXY_SUBCMD_ERROR, c->stream_id, NULL, 0, 1) < 0) c->close_pending = 1; else { c->close_pending = 0; c->close_sent = 1; } } static void send_fin(struct socks_proxy_conn* c) { DEBUG_TRACE(DEBUG_CATEGORY_TRAFFIC, "SOCKS send FIN sid=%08x", c->stream_id); - send_msg(c->inst, c->via_node_id, TCP_PROXY_SUBCMD_FIN, c->stream_id, NULL, 0, 1); + send_msg(c->inst, TOPO_GROUP_UTUN, c->via_node_id, TCP_PROXY_SUBCMD_FIN, c->stream_id, NULL, 0, 1); } // ==================================================================== @@ -331,7 +332,7 @@ static void process_http_request(struct socks_proxy_conn* c) { u_free(pkt); } else { c->tx_buf = pkt; c->tx_len = total; - etcp_router_on_send_ready(c->inst, c->via_node_id, ETCP_RT_ID_TCP_PROXY, &c->tx_waiter, tx_waiter_cb, c); + etcp_router_on_send_ready(c->inst, TOPO_GROUP_UTUN, c->via_node_id, ETCP_RT_ID_TCP_PROXY, &c->tx_waiter, tx_waiter_cb, c); } c->buf_len = 0; @@ -395,7 +396,7 @@ static void on_read_cb(struct ll_queue* q, void* arg) { if (c->tx_buf) { memcpy(c->tx_buf, e->dgram, e->len); c->tx_len = e->len; } else { DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "socks_proxy: tx_buf malloc=%u failed sid=%08x — drop", e->len, c->stream_id); } memory_pool_free(c->tc->data_pool, e->dgram); queue_entry_free(e); - etcp_router_on_send_ready(c->inst, c->via_node_id, ETCP_RT_ID_TCP_PROXY, &c->tx_waiter, tx_waiter_cb, c); + etcp_router_on_send_ready(c->inst, TOPO_GROUP_UTUN, c->via_node_id, ETCP_RT_ID_TCP_PROXY, &c->tx_waiter, tx_waiter_cb, c); DEBUG_DEBUG(DEBUG_CATEGORY_SOCKET, "SOCKS PROXY BP: sid=%08x tx_buf=%u waiter_reg", c->stream_id, c->tx_len); } } @@ -410,7 +411,7 @@ static void tx_waiter_cb(struct ll_queue* q, void* arg) { u_free(c->tx_buf); c->tx_buf = NULL; c->tx_len = 0; queue_resume_callback(c->tc->read_queue); } else { - etcp_router_on_send_ready(c->inst, c->via_node_id, ETCP_RT_ID_TCP_PROXY, &c->tx_waiter, tx_waiter_cb, c); + etcp_router_on_send_ready(c->inst, TOPO_GROUP_UTUN, c->via_node_id, ETCP_RT_ID_TCP_PROXY, &c->tx_waiter, tx_waiter_cb, c); } } @@ -524,7 +525,7 @@ int socks_proxy_handle_etcp(struct socks_proxy_conn** head, int* count, if (subcmd == TCP_PROXY_SUBCMD_CLOSE) { DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "socks_proxy: REM_CLOSED sid=%08x", stream_id); c->rem_closed = 1; - etcp_router_cancel_send_ready(c->inst, c->via_node_id, ETCP_RT_ID_TCP_PROXY, &c->tx_waiter); + etcp_router_cancel_send_ready(c->inst, TOPO_GROUP_UTUN, c->via_node_id, ETCP_RT_ID_TCP_PROXY, &c->tx_waiter); tcp_conn_push_close(c->tc); return 1; } @@ -532,7 +533,7 @@ int socks_proxy_handle_etcp(struct socks_proxy_conn** head, int* count, if (subcmd == TCP_PROXY_SUBCMD_ERROR) { DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "socks_proxy: ERROR from exit sid=%08x", stream_id); c->rem_closed = 1; - etcp_router_cancel_send_ready(c->inst, c->via_node_id, ETCP_RT_ID_TCP_PROXY, &c->tx_waiter); + etcp_router_cancel_send_ready(c->inst, TOPO_GROUP_UTUN, c->via_node_id, ETCP_RT_ID_TCP_PROXY, &c->tx_waiter); tcp_conn_push_close(c->tc); return 1; } @@ -557,12 +558,12 @@ void socks_proxy_conn_free(struct socks_proxy_conn* c) { if (c->close_pending && c->inst) { c->close_pending = 0; uint8_t subcmd = c->tc && c->tc->error ? TCP_PROXY_SUBCMD_ERROR : TCP_PROXY_SUBCMD_CLOSE; - send_msg(c->inst, c->via_node_id, subcmd, c->stream_id, NULL, 0, 1); + send_msg(c->inst, TOPO_GROUP_UTUN, c->via_node_id, subcmd, c->stream_id, NULL, 0, 1); } if (head) { struct socks_proxy_conn** prev = head; while (*prev) { if (*prev == c) { *prev = c->next; if (count) (*count)--; break; } prev = &(*prev)->next; } } if (c->tx_buf) { u_free(c->tx_buf); c->tx_buf = NULL; c->tx_len = 0; } if (c->tc) { tcp_conn_destroy(c->tc); c->tc = NULL; } - if (c->inst) etcp_router_waiter_cancel(c->inst, c->via_node_id, &c->tx_waiter); + if (c->inst) etcp_router_waiter_cancel(c->inst, TOPO_GROUP_UTUN, c->via_node_id, &c->tx_waiter); u_free(c); } diff --git a/src/proxy/tcp_proxy_client.c b/src/proxy/tcp_proxy_client.c index 33196ddc..d04cfd84 100644 --- a/src/proxy/tcp_proxy_client.c +++ b/src/proxy/tcp_proxy_client.c @@ -9,6 +9,7 @@ #include "utun_instance.h" #include "etcp.h" #include "etcp_api.h" +#include "../routing_layer/topo_node.h" #include "etcp_router.h" #include "tcp_proxy_server.h" #include "udp_proxy.h" @@ -42,7 +43,7 @@ static err_t tcp_proxy_client_output_cb(void *arg, struct pbuf *p, uint32_t src_ static void tcp_proxy_client_feed_from_transport(struct tcp_proxy_client_conn *pc); static struct ll_entry* tcp_proxy_client_entry_from_data(struct memory_pool* pool, const uint8_t* data, uint16_t len); static void tcp_proxy_client_conn_free(struct tcp_proxy_client_conn *pc); -static int tcp_proxy_client_send_msg(struct UTUN_INSTANCE* inst, uint64_t dst, uint8_t subcmd, uint32_t sid, const uint8_t* data, size_t len, int force); +static int tcp_proxy_client_send_msg(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t dst, uint8_t subcmd, uint32_t sid, const uint8_t* data, size_t len, int force); static int tcp_proxy_client_send_data(struct tcp_proxy_client_conn* pc, const uint8_t* data, uint16_t len); static void tcp_proxy_client_tx_waiter_cb(struct ll_queue* q, void* arg); @@ -64,7 +65,7 @@ static struct ll_entry* tcp_proxy_client_entry_from_data(struct memory_pool* poo // ==================================================================== // Протокол: сборка и отправка сообщений прокси через ETCP // ==================================================================== -static int tcp_proxy_client_send_msg(struct UTUN_INSTANCE* inst, uint64_t dst, uint8_t subcmd, +static int tcp_proxy_client_send_msg(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t dst, uint8_t subcmd, uint32_t sid, const uint8_t* data, size_t len, int force) { struct ll_entry* e = queue_entry_new(0); if (!e) { DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "queue_entry_new failed subcmd=%02x sid=%08x", subcmd, sid); return -1; } @@ -75,7 +76,7 @@ static int tcp_proxy_client_send_msg(struct UTUN_INSTANCE* inst, uint64_t dst, u memcpy(e->dgram + 2, &sid, 4); if (len > 0) memcpy(e->dgram + TCP_PROXY_HDR_SIZE, data, len); e->len = TCP_PROXY_HDR_SIZE + len; - return etcp_route_send(inst, dst, e, force); + return etcp_route_send(inst, group_id, dst, e, force); } static int tcp_proxy_client_send_connect(struct tcp_proxy_client_conn* pc) { @@ -84,19 +85,19 @@ static int tcp_proxy_client_send_connect(struct tcp_proxy_client_conn* pc) { DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "TCP proxy client: CONNECT sid=%08x to %d.%d.%d.%d:%d via node %016llx", pc->stream_id, pc->dest_ip[0], pc->dest_ip[1], pc->dest_ip[2], pc->dest_ip[3], ntohs(pc->dest_port), (unsigned long long)pc->proxy->via_node_id); - return tcp_proxy_client_send_msg(pc->proxy->inst, pc->proxy->via_node_id, + return tcp_proxy_client_send_msg(pc->proxy->inst, TOPO_GROUP_UTUN, pc->proxy->via_node_id, TCP_PROXY_SUBCMD_CONNECT, pc->stream_id, buf, 6, 1); } static int tcp_proxy_client_send_data(struct tcp_proxy_client_conn* pc, const uint8_t* data, uint16_t len) { DEBUG_TRACE(DEBUG_CATEGORY_TRAFFIC, "PROXY SEND sid=%08x len=%u", pc->stream_id, len); - return tcp_proxy_client_send_msg(pc->proxy->inst, pc->proxy->via_node_id, + return tcp_proxy_client_send_msg(pc->proxy->inst, TOPO_GROUP_UTUN, pc->proxy->via_node_id, TCP_PROXY_SUBCMD_DATA, pc->stream_id, data, len, 0); } static int tcp_proxy_client_send_close(struct tcp_proxy_client_conn* pc) { DEBUG_TRACE(DEBUG_CATEGORY_TRAFFIC, "PROXY SEND sid=%08x", pc->stream_id); - int ret = tcp_proxy_client_send_msg(pc->proxy->inst, pc->proxy->via_node_id, + int ret = tcp_proxy_client_send_msg(pc->proxy->inst, TOPO_GROUP_UTUN, pc->proxy->via_node_id, TCP_PROXY_SUBCMD_CLOSE, pc->stream_id, NULL, 0, 1); if (ret < 0) { pc->close_pending = 1; return -1; } pc->close_pending = 0; @@ -105,7 +106,7 @@ static int tcp_proxy_client_send_close(struct tcp_proxy_client_conn* pc) { } static int tcp_proxy_client_send_error(struct tcp_proxy_client_conn* pc) { - int ret = tcp_proxy_client_send_msg(pc->proxy->inst, pc->proxy->via_node_id, + int ret = tcp_proxy_client_send_msg(pc->proxy->inst, TOPO_GROUP_UTUN, pc->proxy->via_node_id, TCP_PROXY_SUBCMD_ERROR, pc->stream_id, NULL, 0, 1); if (ret < 0) { pc->close_pending = 1; return -1; } pc->close_pending = 0; @@ -115,7 +116,7 @@ static int tcp_proxy_client_send_error(struct tcp_proxy_client_conn* pc) { static int tcp_proxy_client_send_fin(struct tcp_proxy_client_conn* pc) { DEBUG_INFO(DEBUG_CATEGORY_TRAFFIC, "PROXY FIN RELAY sid=%08x", pc->stream_id); - return tcp_proxy_client_send_msg(pc->proxy->inst, pc->proxy->via_node_id, + return tcp_proxy_client_send_msg(pc->proxy->inst, TOPO_GROUP_UTUN, pc->proxy->via_node_id, TCP_PROXY_SUBCMD_FIN, pc->stream_id, NULL, 0, 1); } @@ -306,7 +307,7 @@ static err_t tcp_proxy_client_recv_cb(void *arg, struct tcp_pcb *pcb, struct pbu if (ret == 0) { tcp_recved(pcb, len); u_free(data); } else { pc->tx_buf = data; pc->tx_len = len; - etcp_router_waiter_register(pc->proxy->inst, pc->proxy->via_node_id, &pc->tx_waiter, + etcp_router_waiter_register(pc->proxy->inst, TOPO_GROUP_UTUN, pc->proxy->via_node_id, &pc->tx_waiter, tcp_proxy_client_tx_waiter_cb, pc); } } else DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "PROXY recv malloc(%u) failed sid=%08x", len, pc->stream_id); @@ -418,7 +419,7 @@ static void tcp_proxy_client_conn_free(struct tcp_proxy_client_conn *pc) { if (pc->close_pending && p && p->inst) { pc->close_pending = 0; uint8_t subcmd = pc->error ? TCP_PROXY_SUBCMD_ERROR : TCP_PROXY_SUBCMD_CLOSE; - tcp_proxy_client_send_msg(p->inst, p->via_node_id, subcmd, pc->stream_id, NULL, 0, 1); + tcp_proxy_client_send_msg(p->inst, TOPO_GROUP_UTUN, p->via_node_id, subcmd, pc->stream_id, NULL, 0, 1); } struct tcp_proxy_client_conn **prev = &p->conns; while (*prev) { if (*prev == pc) { *prev = pc->next; p->conn_count--; break; } prev = &(*prev)->next; } @@ -428,7 +429,7 @@ static void tcp_proxy_client_conn_free(struct tcp_proxy_client_conn *pc) { queue_free(pc->to_lwip); pc->to_lwip = NULL; } if (pc->tx_buf) { u_free(pc->tx_buf); pc->tx_buf = NULL; pc->tx_len = 0; } - if (pc->proxy && pc->proxy->inst) etcp_router_waiter_cancel(pc->proxy->inst, pc->proxy->via_node_id, &pc->tx_waiter); + if (pc->proxy && pc->proxy->inst) etcp_router_waiter_cancel(pc->proxy->inst, TOPO_GROUP_UTUN, pc->proxy->via_node_id, &pc->tx_waiter); u_free(pc); } @@ -463,7 +464,7 @@ static void tcp_proxy_client_handle_close(struct tcp_proxy_client* p, uint32_t s DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "PROXY REM_CLOSED sid=%08x fin_local=%d pcb_state=%u", stream_id, pc->fin_local, pc->pcb ? pc->pcb->state : 0); pc->rem_closed = 1; if (pc->tx_buf) { u_free(pc->tx_buf); pc->tx_buf = NULL; pc->tx_len = 0; } - etcp_router_waiter_cancel(pc->proxy->inst, pc->proxy->via_node_id, &pc->tx_waiter); + etcp_router_waiter_cancel(pc->proxy->inst, TOPO_GROUP_UTUN, pc->proxy->via_node_id, &pc->tx_waiter); if (pc->pcb) { tcp_arg(pc->pcb, NULL); tcp_recv(pc->pcb, NULL); @@ -491,7 +492,7 @@ static void tcp_proxy_client_handle_error(struct tcp_proxy_client* p, uint32_t s } pc->rem_closed = 1; if (pc->tx_buf) { u_free(pc->tx_buf); pc->tx_buf = NULL; pc->tx_len = 0; } - etcp_router_waiter_cancel(pc->proxy->inst, pc->proxy->via_node_id, &pc->tx_waiter); + etcp_router_waiter_cancel(pc->proxy->inst, TOPO_GROUP_UTUN, pc->proxy->via_node_id, &pc->tx_waiter); tcp_proxy_client_conn_free(pc); } @@ -671,7 +672,7 @@ void tcp_proxy_client_destroy(struct tcp_proxy_client* p) { queue_free(pc->to_lwip); pc->to_lwip = NULL; } if (pc->tx_buf) { u_free(pc->tx_buf); pc->tx_buf = NULL; pc->tx_len = 0; } - if (p->inst) etcp_router_waiter_cancel(p->inst, p->via_node_id, &pc->tx_waiter); + if (p->inst) etcp_router_waiter_cancel(p->inst, TOPO_GROUP_UTUN, p->via_node_id, &pc->tx_waiter); u_free(pc); pc = next; } p->conns = NULL; diff --git a/src/proxy/tcp_proxy_server.c b/src/proxy/tcp_proxy_server.c index 1fcf64ba..5668915c 100644 --- a/src/proxy/tcp_proxy_server.c +++ b/src/proxy/tcp_proxy_server.c @@ -7,6 +7,7 @@ #include "etcp_router.h" #include "utun_instance.h" #include "config_parser.h" +#include "../routing_layer/topo_node.h" #include "../lib/u_async.h" #include "../lib/debug_config.h" #include "../lib/ll_queue.h" @@ -34,7 +35,7 @@ static void pause_resume_cb(struct ll_queue* q, void* arg); static void close_retry_cb(void* arg); static void diag_timer_cb(void* arg); static void retry_timer_cb(void* arg); -static int send_msg(struct UTUN_INSTANCE* inst, uint64_t dst, uint8_t subcmd, +static int send_msg(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t dst, uint8_t subcmd, uint32_t sid, const uint8_t* data, size_t len, int force); static void send_close(struct tcp_proxy_server_conn* rc); static void send_error(struct tcp_proxy_server_conn* rc); @@ -48,7 +49,7 @@ static inline int write_pending(struct tcp_conn* tc) { // Отправка сообщений через ETCP // ==================================================================== -static int send_msg(struct UTUN_INSTANCE* inst, uint64_t dst, uint8_t subcmd, +static int send_msg(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t dst, uint8_t subcmd, uint32_t sid, const uint8_t* data, size_t len, int force) { struct ll_entry* e = queue_entry_new(0); if (!e) { DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "tcp_proxy_server: queue_entry_new failed subcmd=%02x sid=%08x", subcmd, sid); return -1; } @@ -63,7 +64,7 @@ static int send_msg(struct UTUN_INSTANCE* inst, uint64_t dst, uint8_t subcmd, queue_dgram_free(e); queue_entry_free(e); return -1; } e->len = TCP_PROXY_HDR_SIZE + len; - return etcp_route_send(inst, dst, e, force); + return etcp_route_send(inst, group_id, dst, e, force); } static void close_retry_cb(void* arg) { @@ -74,7 +75,7 @@ static void close_retry_cb(void* arg) { struct UTUN_INSTANCE* inst = rc->ctx ? rc->ctx->inst : NULL; if (!inst) return; uint8_t subcmd = (rc->tc && rc->tc->error) ? TCP_PROXY_SUBCMD_ERROR : TCP_PROXY_SUBCMD_CLOSE; - if (send_msg(inst, rc->peer_node_id, subcmd, rc->stream_id, NULL, 0, 1) < 0) { + if (send_msg(inst, TOPO_GROUP_UTUN, rc->peer_node_id, subcmd, rc->stream_id, NULL, 0, 1) < 0) { rc->close_backoff = rc->close_backoff < 5000 ? rc->close_backoff * 2 : 5000; rc->close_timer = uasync_set_timeout(rc->ua, rc->close_backoff, rc, close_retry_cb, "tps_close_retry"); return; @@ -85,7 +86,7 @@ static void close_retry_cb(void* arg) { static void send_close(struct tcp_proxy_server_conn* rc) { struct UTUN_INSTANCE* inst = rc->ctx ? rc->ctx->inst : NULL; if (!inst) return; - if (send_msg(inst, rc->peer_node_id, TCP_PROXY_SUBCMD_CLOSE, rc->stream_id, NULL, 0, 1) < 0) { + if (send_msg(inst, TOPO_GROUP_UTUN, rc->peer_node_id, TCP_PROXY_SUBCMD_CLOSE, rc->stream_id, NULL, 0, 1) < 0) { rc->close_pending = 1; rc->close_backoff = 50; if (!rc->close_timer) @@ -96,7 +97,7 @@ static void send_close(struct tcp_proxy_server_conn* rc) { static void send_error(struct tcp_proxy_server_conn* rc) { struct UTUN_INSTANCE* inst = rc->ctx ? rc->ctx->inst : NULL; if (!inst) return; - if (send_msg(inst, rc->peer_node_id, TCP_PROXY_SUBCMD_ERROR, rc->stream_id, NULL, 0, 1) < 0) { + if (send_msg(inst, TOPO_GROUP_UTUN, rc->peer_node_id, TCP_PROXY_SUBCMD_ERROR, rc->stream_id, NULL, 0, 1) < 0) { rc->close_pending = 1; rc->close_backoff = 50; if (!rc->close_timer) @@ -107,7 +108,7 @@ static void send_error(struct tcp_proxy_server_conn* rc) { static void send_fin(struct tcp_proxy_server_conn* rc) { struct UTUN_INSTANCE* inst = rc->ctx ? rc->ctx->inst : NULL; if (!inst) return; - send_msg(inst, rc->peer_node_id, TCP_PROXY_SUBCMD_FIN, rc->stream_id, NULL, 0, 1); + send_msg(inst, TOPO_GROUP_UTUN, rc->peer_node_id, TCP_PROXY_SUBCMD_FIN, rc->stream_id, NULL, 0, 1); } // ==================================================================== @@ -214,7 +215,7 @@ static void read_queue_drain_cb(struct ll_queue* q, void* arg) { struct ll_entry* e; if (rc->tx_buf) { - int ret = send_msg(inst, rc->peer_node_id, TCP_PROXY_SUBCMD_DATA, rc->stream_id, rc->tx_buf, rc->tx_len, 0); + int ret = send_msg(inst, TOPO_GROUP_UTUN, rc->peer_node_id, TCP_PROXY_SUBCMD_DATA, rc->stream_id, rc->tx_buf, rc->tx_len, 0); DEBUG_DEBUG(DEBUG_CATEGORY_SOCKET, "TPS TXBUF RETRY: sid=%08x len=%u ret=%d", rc->stream_id, rc->tx_len, ret); if (ret == 0) { u_free(rc->tx_buf); rc->tx_buf = NULL; rc->tx_len = 0; @@ -225,7 +226,7 @@ static void read_queue_drain_cb(struct ll_queue* q, void* arg) { return; } } else { - etcp_router_on_send_ready(inst, rc->peer_node_id, ETCP_RT_ID_TCP_PROXY, + etcp_router_on_send_ready(inst, TOPO_GROUP_UTUN, rc->peer_node_id, ETCP_RT_ID_TCP_PROXY, &rc->pause_waiter, pause_resume_cb, rc); if (!rc->retry_timer) rc->retry_timer = uasync_set_timeout(rc->ua, 5000, rc, retry_timer_cb, "tps_retry"); DEBUG_DEBUG(DEBUG_CATEGORY_SOCKET, "TPS TXBUF BP AGAIN: sid=%08x waiter_reg", rc->stream_id); @@ -250,7 +251,7 @@ static void read_queue_drain_cb(struct ll_queue* q, void* arg) { queue_resume_callback(q); return; } - int ret = send_msg(inst, rc->peer_node_id, TCP_PROXY_SUBCMD_DATA, rc->stream_id, e->dgram, e->len, 0); + int ret = send_msg(inst, TOPO_GROUP_UTUN, rc->peer_node_id, TCP_PROXY_SUBCMD_DATA, rc->stream_id, e->dgram, e->len, 0); rc->bytes_relayed += e->len; rc->drain_count++; DEBUG_TRACE(DEBUG_CATEGORY_TRAFFIC, "TPS DRAIN #%u sid=%08x len=%u → ret=%d rq=%d", rc->drain_count, rc->stream_id, e->len, ret, q->count); @@ -264,7 +265,7 @@ static void read_queue_drain_cb(struct ll_queue* q, void* arg) { memory_pool_free(rc->tc->data_pool, e->dgram); queue_entry_free(e); DEBUG_DEBUG(DEBUG_CATEGORY_SOCKET, "SOCK:BACKPRESSURE fd=%d sid=%08x — buffered %u for retry", (int)rc->tc->sock, rc->stream_id, rc->tx_len); - etcp_router_on_send_ready(inst, rc->peer_node_id, ETCP_RT_ID_TCP_PROXY, + etcp_router_on_send_ready(inst, TOPO_GROUP_UTUN, rc->peer_node_id, ETCP_RT_ID_TCP_PROXY, &rc->pause_waiter, pause_resume_cb, rc); if (!rc->retry_timer) rc->retry_timer = uasync_set_timeout(rc->ua, 5000, rc, retry_timer_cb, "tps_retry"); } @@ -285,7 +286,7 @@ static void retry_timer_cb(void* arg) { rc->retry_timer = NULL; if (!rc->tx_buf || !rc->tc || rc->tc->sock == SOCKET_INVALID || rc->cli_closed) return; struct UTUN_INSTANCE* inst = rc->ctx ? rc->ctx->inst : NULL; - int ret = send_msg(inst, rc->peer_node_id, TCP_PROXY_SUBCMD_DATA, rc->stream_id, rc->tx_buf, rc->tx_len, 1); + int ret = send_msg(inst, TOPO_GROUP_UTUN, rc->peer_node_id, TCP_PROXY_SUBCMD_DATA, rc->stream_id, rc->tx_buf, rc->tx_len, 1); DEBUG_DEBUG(DEBUG_CATEGORY_SOCKET, "TPS RETRY TIMER: sid=%08x len=%u force=1 ret=%d", rc->stream_id, rc->tx_len, ret); if (ret == 0) { u_free(rc->tx_buf); rc->tx_buf = NULL; rc->tx_len = 0; @@ -325,13 +326,13 @@ void tcp_proxy_server_conn_free(struct tcp_proxy_server_conn* rc) { if (rc->close_pending && rc->ctx && rc->ctx->inst) { rc->close_pending = 0; uint8_t subcmd = (rc->tc && rc->tc->error) ? TCP_PROXY_SUBCMD_ERROR : TCP_PROXY_SUBCMD_CLOSE; - send_msg(rc->ctx->inst, rc->peer_node_id, subcmd, rc->stream_id, NULL, 0, 1); + send_msg(rc->ctx->inst, TOPO_GROUP_UTUN, rc->peer_node_id, subcmd, rc->stream_id, NULL, 0, 1); } if (rc->ctx) { struct tcp_proxy_server_conn** prev = &rc->ctx->conns; while (*prev) { if (*prev == rc) { *prev = rc->next; rc->ctx->conn_count--; break; } prev = &(*prev)->next; } } - if (rc->ctx && rc->ctx->inst) etcp_router_cancel_send_ready(rc->ctx->inst, rc->peer_node_id, ETCP_RT_ID_TCP_PROXY, &rc->pause_waiter); + if (rc->ctx && rc->ctx->inst) etcp_router_cancel_send_ready(rc->ctx->inst, TOPO_GROUP_UTUN, rc->peer_node_id, ETCP_RT_ID_TCP_PROXY, &rc->pause_waiter); if (rc->tx_buf) { u_free(rc->tx_buf); rc->tx_buf = NULL; rc->tx_len = 0; } if (rc->retry_timer) { uasync_cancel_timeout(rc->ua, rc->retry_timer); rc->retry_timer = NULL; } if (rc->close_timer) { uasync_cancel_timeout(rc->ua, rc->close_timer); rc->close_timer = NULL; } @@ -383,7 +384,7 @@ int tcp_proxy_server_handle_connect(struct UTUN_INSTANCE* inst, struct ll_entry* if (ret < 0 && errno != EINPROGRESS) { DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "TCP proxy server: connect() to %d.%d.%d.%d:%d failed: %s", dest_ip[0], dest_ip[1], dest_ip[2], dest_ip[3], ntohs(dest_port), strerror(errno)); - send_msg(inst, src_node_id, TCP_PROXY_SUBCMD_ERROR, stream_id, NULL, 0, 1); + send_msg(inst, TOPO_GROUP_UTUN, src_node_id, TCP_PROXY_SUBCMD_ERROR, stream_id, NULL, 0, 1); ctx->conn_count--; tcp_conn_destroy(rc->tc); u_free(rc); queue_dgram_free(entry); queue_entry_free(entry); return -1; } diff --git a/src/proxy/udp_proxy.c b/src/proxy/udp_proxy.c index 7356d1df..911c0336 100644 --- a/src/proxy/udp_proxy.c +++ b/src/proxy/udp_proxy.c @@ -5,6 +5,7 @@ #include "etcp_router.h" #include "utun_instance.h" #include "tun_if.h" +#include "../routing_layer/topo_node.h" #include "../lib/u_async.h" #include "../lib/debug_config.h" #include "../lib/ll_queue.h" @@ -64,7 +65,7 @@ static void flow_read_cb(socket_t sock, void* arg) { memcpy(e->dgram + UDP_PROXY_HDR_SIZE, buf, n); e->len = UDP_PROXY_HDR_SIZE + n; - etcp_route_send(g_udp_ctx->inst, f->client_node_id, e, 0); + etcp_route_send(g_udp_ctx->inst, TOPO_GROUP_UTUN, f->client_node_id, e, 0); } // ==================================================================== @@ -169,7 +170,7 @@ int udp_proxy_send_to_exit(struct UTUN_INSTANCE* inst, uint64_t exit_node_id, memcpy(e->dgram + 20, &dst_port, 2); if (payload_len > 0) memcpy(e->dgram + UDP_PROXY_HDR_SIZE, payload, payload_len); e->len = UDP_PROXY_HDR_SIZE + payload_len; - return etcp_route_send(inst, exit_node_id, e, 0); + return etcp_route_send(inst, TOPO_GROUP_UTUN, exit_node_id, e, 0); } // ==================================================================== diff --git a/src/routing_layer/conn_mgr.c b/src/routing_layer/conn_mgr.c index d88e0fad..6454a16f 100644 --- a/src/routing_layer/conn_mgr.c +++ b/src/routing_layer/conn_mgr.c @@ -238,7 +238,7 @@ int conn_mgr_disconnect_node(struct CONN_MGR* mgr, uint64_t node_id) { pkt.subcmd = CONN_MGR_SUBCMD_DISCONNECT; pkt.node_id = node_id; struct ll_entry* qe = queue_entry_new(0); - if (qe) { qe->dgram = u_malloc(sizeof(pkt)); memcpy(qe->dgram, &pkt, sizeof(pkt)); qe->len = sizeof(pkt); etcp_route_send(mgr->instance, node_id, qe, 1); } + if (qe) { qe->dgram = u_malloc(sizeof(pkt)); memcpy(qe->dgram, &pkt, sizeof(pkt)); qe->len = sizeof(pkt); etcp_route_send(mgr->instance, TOPO_GROUP_UTUN, node_id, qe, 1); } cm_clear_nodeinfo(mgr, node_id); cm_entry_destroy(entry); entry->state = CONN_MGR_STATE_DISCONNECTED; @@ -272,7 +272,7 @@ int conn_mgr_send(struct CONN_MGR* mgr, uint64_t node_id, struct ll_entry* entry struct CONN_MGR_ENTRY* e = cm_find_entry(mgr, node_id); if (!e || e->state != CONN_MGR_STATE_CONNECTED) { queue_entry_free(entry); return -1; } e->last_traffic_tb = get_time_tb(); - struct ETCP_ROUTER_CONN* rconn = etcp_router_conn_get(mgr->instance, node_id, ETCP_RT_ID_CONN_MGR); + struct ETCP_ROUTER_CONN* rconn = etcp_router_conn_get(mgr->instance, TOPO_GROUP_UTUN, node_id, ETCP_RT_ID_CONN_MGR); if (!rconn) { queue_entry_free(entry); return -1; } int ret = etcp_router_conn_send(rconn, entry->dgram, entry->len); queue_entry_free(entry); @@ -567,7 +567,7 @@ static void cm_start_phase_reverse(struct CONN_MGR_ENTRY* entry) { if (!qe) { u_free(pkt); cm_deliver_result(entry, CONN_MGR_ERR_INTERNAL); return; } qe->dgram = pkt; qe->len = (uint16_t)pkt_size; - etcp_route_send(entry->mgr->instance, entry->node_id, qe, 1); + etcp_route_send(entry->mgr->instance, TOPO_GROUP_UTUN, entry->node_id, qe, 1); struct cm_reverse_pending* rp = u_calloc(1, sizeof(struct cm_reverse_pending)); if (rp) { rp->request_id = req_id; rp->entry = entry; rp->next = entry->mgr->reverse_pending; @@ -625,7 +625,7 @@ static int cm_start_phase_indirect(struct CONN_MGR_ENTRY* entry) { qe->dgram = u_malloc(sizeof(req)); memcpy(qe->dgram, &req, sizeof(req)); qe->len = (uint16_t)sizeof(req); - etcp_route_send(entry->mgr->instance, entry->node_id, qe, 1); + etcp_route_send(entry->mgr->instance, TOPO_GROUP_UTUN, entry->node_id, qe, 1); entry->main.timer = uasync_set_timeout(mgr->instance->ua, CONN_MGR_INTERM_EXCHANGE_TIMEOUT_MS * 10, entry, cm_exchange_timeout_cb, "conn_mgr_interm_exch"); { @@ -693,7 +693,7 @@ static void cm_compute_intermediaries(struct CONN_MGR_ENTRY* entry, struct CONN_ if (nq) pkt.selected[i].rtt = cm_get_node_min_rtt(nq); } struct ll_entry* qe = queue_entry_new(0); - if (qe) { qe->dgram = u_malloc(sizeof(pkt)); memcpy(qe->dgram, &pkt, sizeof(pkt)); qe->len = sizeof(pkt); etcp_route_send(entry->mgr->instance, entry->node_id, qe, 1); } + if (qe) { qe->dgram = u_malloc(sizeof(pkt)); memcpy(qe->dgram, &pkt, sizeof(pkt)); qe->len = sizeof(pkt); etcp_route_send(entry->mgr->instance, TOPO_GROUP_UTUN, entry->node_id, qe, 1); } entry->conn_type = CONN_TYPE_INDIRECT; entry->state = CONN_MGR_STATE_CONNECTED; @@ -877,7 +877,7 @@ static void cm_handle_interm_exchange_req(struct ETCP_CONN* conn, qe->dgram = u_malloc(resp_size); memcpy(qe->dgram, &resp, resp_size); qe->len = (uint16_t)resp_size; - etcp_route_send(mgr->instance, conn->peer_node_id, qe, 1); + etcp_route_send(mgr->instance, TOPO_GROUP_UTUN, conn->peer_node_id, qe, 1); } DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "conn_mgr: sent EXCHANGE_RESP to 0x%016llx my=%u your=%u", (unsigned long long)conn->peer_node_id, resp.my_count, resp.your_count); diff --git a/src/routing_layer/etcp_router.c b/src/routing_layer/etcp_router.c index 5ef58621..e3c59f9a 100644 --- a/src/routing_layer/etcp_router.c +++ b/src/routing_layer/etcp_router.c @@ -32,7 +32,7 @@ static void router_try_assembly(struct ETCP_ROUTER_CONN* rconn, struct ETCP_CONN static void router_deliver(struct ETCP_ROUTER_CONN* rconn, struct ETCP_CONN* conn, const uint8_t* payload, size_t payload_len); static int router_send_one(struct ETCP_ROUTER_CONN* rconn, const uint8_t* payload, size_t pl_len); static int router_send_one_flags(struct ETCP_ROUTER_CONN* rconn, const uint8_t* payload, size_t pl_len, uint8_t flag_bits, int is_signed); -static void router_send_to(struct UTUN_INSTANCE* inst, uint64_t dst, uint8_t svc_id, uint8_t flag_bits); +static void router_send_to(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t dst, uint8_t svc_id, uint8_t flag_bits); static void router_drain_send_q(struct ETCP_ROUTER_CONN* rconn); static void router_send_resume_cb(void* arg); static void router_no_route_retry_cb(void* arg); @@ -58,23 +58,26 @@ static void router_update_minrtt(struct ETCP_ROUTER_CONN* rconn); // Транзитные очереди — per (src, dst) pair, backpressure через waiter на send_input_q static struct TRANSIT_QUEUE* transit_queue_find(struct ETCP_CONN* conn, + uint64_t group_id, uint64_t src_node_id, uint64_t dst_node_id) { if (!conn->transit_queues) return NULL; - uint8_t key[16]; - memcpy(key, &src_node_id, 8); - memcpy(key + 8, &dst_node_id, 8); + uint8_t key[24]; + memcpy(key, &group_id, 8); + memcpy(key + 8, &src_node_id, 8); + memcpy(key + 16, &dst_node_id, 8); return (struct TRANSIT_QUEUE*)queue_find_data_by_index(conn->transit_queues, key); } static struct TRANSIT_QUEUE* transit_queue_get_or_create(struct ETCP_CONN* conn, + uint64_t group_id, uint64_t src_node_id, uint64_t dst_node_id) { if (!conn->transit_queues) { struct UASYNC* ua = conn->instance ? conn->instance->ua : NULL; if (!ua) { DEBUG_ERROR(DEBUG_CATEGORY_ETCPROUTE, "transit_queue_get_or_create: no ua"); return NULL; } - conn->transit_queues = queue_new(ua, TRANSIT_QUEUE_HASH, 0, 16, "transit_q_reg"); + conn->transit_queues = queue_new(ua, TRANSIT_QUEUE_HASH, 0, 24, "transit_q_reg"); if (!conn->transit_queues) { DEBUG_ERROR(DEBUG_CATEGORY_ETCPROUTE, "transit_queue_get_or_create: queue_new failed"); return NULL; } } - struct TRANSIT_QUEUE* tq = transit_queue_find(conn, src_node_id, dst_node_id); + struct TRANSIT_QUEUE* tq = transit_queue_find(conn, group_id, src_node_id, dst_node_id); if (tq) return tq; size_t data_size = sizeof(struct TRANSIT_QUEUE) - sizeof(struct ll_entry); tq = (struct TRANSIT_QUEUE*)queue_entry_new(data_size); @@ -83,14 +86,18 @@ static struct TRANSIT_QUEUE* transit_queue_get_or_create(struct ETCP_CONN* conn, return NULL; } memset(&tq->waiter, 0, sizeof(tq->waiter)); + tq->group_id = group_id; + tq->src_node_id = src_node_id; + tq->dst_node_id = dst_node_id; tq->conn = conn; tq->q = queue_new(conn->instance->ua, 0, 0, 0, "transit_pair_q"); if (!tq->q) { queue_entry_free(&tq->ll); return NULL; } - memcpy(tq->ll.data, &src_node_id, 8); - memcpy(tq->ll.data + 8, &dst_node_id, 8); + memcpy(tq->ll.data, &group_id, 8); + memcpy(tq->ll.data + 8, &src_node_id, 8); + memcpy(tq->ll.data + 16, &dst_node_id, 8); queue_data_put_with_index(conn->transit_queues, &tq->ll); - DEBUG_INFO(DEBUG_CATEGORY_ETCPROUTE, "transit_q: new src=%016llx dst=%016llx", - (unsigned long long)src_node_id, (unsigned long long)dst_node_id); + DEBUG_INFO(DEBUG_CATEGORY_ETCPROUTE, "transit_q: new group=%016llx src=%016llx dst=%016llx", + (unsigned long long)group_id, (unsigned long long)src_node_id, (unsigned long long)dst_node_id); return tq; } @@ -136,11 +143,13 @@ void etcp_router_transit_queues_destroy(struct ETCP_CONN* conn) { // ==================================================================== static struct ETCP_ROUTER_CONN* router_conn_find(struct UTUN_INSTANCE* inst, + uint64_t group_id, uint64_t remote_node_id, uint8_t svc_id) { if (!inst || !inst->router_conns) return NULL; - uint8_t key[9]; - memcpy(key, &remote_node_id, 8); - key[8] = svc_id; + uint8_t key[17]; + memcpy(key, &group_id, 8); + memcpy(key + 8, &remote_node_id, 8); + key[16] = svc_id; return (struct ETCP_ROUTER_CONN*)queue_find_data_by_index(inst->router_conns, key); } @@ -161,6 +170,7 @@ static int router_send_one_flags(struct ETCP_ROUTER_CONN* rconn, const uint8_t* if (!dgram) { if (!flag_bits) rconn->tx_seq--; rconn->c_pkts_send_err++; return -1; } struct SVC_ROUTE_HDR* hdr = (struct SVC_ROUTE_HDR*)dgram; hdr->cmd = ETCP_RT_ID_SVC_ROUTE; + hdr->group_id = rconn->group_id; hdr->dst_node_id = rconn->remote_node_id; hdr->src_node_id = inst->node_id; hdr->seq = seq; @@ -178,7 +188,7 @@ static int router_send_one_flags(struct ETCP_ROUTER_CONN* rconn, const uint8_t* if (pl_len > 0) memcpy(dgram + SVC_ROUTE_HDR_SIZE, payload, pl_len); struct ETCP_CONN* conn = NULL; - struct TOPO_GROUP* group = topo_groups_get_default(inst->topo_groups); + struct TOPO_GROUP* group = topo_groups_find(inst->topo_groups, rconn->group_id); if (group) { struct TOPO_NODEQ* nq = topo_node_find_by_id(group, rconn->remote_node_id); if (nq && nq->conn_mgr_type == CONN_TYPE_INDIRECT && nq->conn_mgr_intermediariy_count > 0) { @@ -258,12 +268,13 @@ static int router_send_one_flags(struct ETCP_ROUTER_CONN* rconn, const uint8_t* } // Отправка без conn (RST для неизвестного src) -static void router_send_to(struct UTUN_INSTANCE* inst, uint64_t dst, uint8_t svc_id, uint8_t flag_bits) { - struct ETCP_CONN* conn = topo_group_find_conn_for_node(topo_groups_get_default(inst->topo_groups), dst); +static void router_send_to(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t dst, uint8_t svc_id, uint8_t flag_bits) { + struct ETCP_CONN* conn = topo_group_find_conn_for_node(topo_groups_find(inst->topo_groups, group_id), dst); if (!conn) return; struct SVC_ROUTE_HDR* hdr = (struct SVC_ROUTE_HDR*)u_malloc(SVC_ROUTE_HDR_SIZE); if (!hdr) return; hdr->cmd = ETCP_RT_ID_SVC_ROUTE; + hdr->group_id = group_id; hdr->dst_node_id = dst; hdr->src_node_id = inst->node_id; hdr->seq = 0; @@ -314,7 +325,7 @@ static void router_close_and_notify(struct ETCP_ROUTER_CONN* rconn) { rconn->closed = 1; router_send_close_to_service(rconn); // Отправляем CLOSE удалённой стороне - struct ETCP_CONN* conn = topo_group_find_conn_for_node(topo_groups_get_default(inst->topo_groups), rconn->remote_node_id); + struct ETCP_CONN* conn = topo_group_find_conn_for_node(topo_groups_find(inst->topo_groups, rconn->group_id), rconn->remote_node_id); if (conn) router_send_one_flags(rconn, NULL, 0, ROUTER_FLAG_CLOSE, 0); // Таймеры if (rconn->ack_timer) { uasync_cancel_timeout(inst->ua, rconn->ack_timer); rconn->ack_timer = NULL; } @@ -349,8 +360,8 @@ static void router_close_and_notify(struct ETCP_ROUTER_CONN* rconn) { } if (inst->router_conns) queue_remove_data(inst->router_conns, &rconn->ll); - DEBUG_INFO(DEBUG_CATEGORY_ETCPROUTE, "router_conn: closed remote=%016llx svc_id=%u", - (unsigned long long)rconn->remote_node_id, rconn->svc_id); + DEBUG_INFO(DEBUG_CATEGORY_ETCPROUTE, "router_conn: closed group=%016llx remote=%016llx svc_id=%u", + (unsigned long long)rconn->group_id, (unsigned long long)rconn->remote_node_id, rconn->svc_id); uasync_call_soon(inst->ua, rconn, router_close_finalize); } @@ -389,7 +400,7 @@ static void router_no_route_retry_cb(void* arg) { struct ETCP_ROUTER_CONN* rconn = (struct ETCP_ROUTER_CONN*)arg; if (rconn->closed) return; rconn->no_route_timer = NULL; - struct ETCP_CONN* c = topo_group_find_conn_for_node(topo_groups_get_default(rconn->inst->topo_groups), rconn->remote_node_id);; + struct ETCP_CONN* c = topo_group_find_conn_for_node(topo_groups_find(rconn->inst->topo_groups, rconn->group_id), rconn->remote_node_id);; if (c) { DEBUG_INFO(DEBUG_CATEGORY_ETCPROUTE, "router: route appeared for %016llx svc_id=%u, draining send_q=%d", (unsigned long long)rconn->remote_node_id, rconn->svc_id, queue_entry_count(rconn->send_q)); @@ -412,6 +423,7 @@ static void router_retransmit_one(struct ETCP_ROUTER_CONN* rconn, struct ROUTER_ if (!dgram) { rconn->c_pkts_send_err++; return; } struct SVC_ROUTE_HDR* hdr = (struct SVC_ROUTE_HDR*)dgram; hdr->cmd = ETCP_RT_ID_SVC_ROUTE; + hdr->group_id = rconn->group_id; hdr->dst_node_id = rconn->remote_node_id; hdr->src_node_id = inst->node_id; hdr->seq = inf->seq; @@ -420,7 +432,7 @@ static void router_retransmit_one(struct ETCP_ROUTER_CONN* rconn, struct ROUTER_ hdr->timestamp = get_current_timestamp(); struct ETCP_CONN* conn = NULL; - struct TOPO_GROUP* group = topo_groups_get_default(inst->topo_groups); + struct TOPO_GROUP* group = topo_groups_find(inst->topo_groups, rconn->group_id); if (group) { struct TOPO_NODEQ* nq = topo_node_find_by_id(group, rconn->remote_node_id); if (nq && nq->conn_mgr_type == CONN_TYPE_INDIRECT && nq->conn_mgr_intermediariy_count > 0) { @@ -618,7 +630,7 @@ static void router_ack_do_send(struct ETCP_ROUTER_CONN* rconn) { static void router_send_ack(struct ETCP_ROUTER_CONN* rconn) { struct UTUN_INSTANCE* inst = rconn->inst; - struct ETCP_CONN* conn = topo_group_find_conn_for_node(topo_groups_get_default(inst->topo_groups), rconn->remote_node_id); + struct ETCP_CONN* conn = topo_group_find_conn_for_node(topo_groups_find(inst->topo_groups, rconn->group_id), rconn->remote_node_id); if (!conn) { DEBUG_WARN(DEBUG_CATEGORY_ETCPROUTE, "router_ack: no route to %016llx svc_id=%u", (unsigned long long)rconn->remote_node_id, rconn->svc_id); @@ -628,6 +640,7 @@ static void router_send_ack(struct ETCP_ROUTER_CONN* rconn) { struct SVC_ROUTE_HDR* hdr = (struct SVC_ROUTE_HDR*)u_malloc(SVC_ROUTE_HDR_SIZE); if (!hdr) { DEBUG_ERROR(DEBUG_CATEGORY_ETCPROUTE, "router_ack: u_malloc failed"); return; } hdr->cmd = ETCP_RT_ID_SVC_ROUTE; + hdr->group_id = rconn->group_id; hdr->dst_node_id = rconn->remote_node_id; hdr->src_node_id = inst->node_id; hdr->seq = rconn->rx_seq; @@ -768,7 +781,7 @@ static void router_incoming_q_cb(struct ll_queue* q, void* arg) { queue_data_put_with_index(rconn->recv_q, rq); - struct ETCP_CONN* conn = topo_group_find_conn_for_node(topo_groups_get_default(rconn->inst->topo_groups), rconn->remote_node_id);; + struct ETCP_CONN* conn = topo_group_find_conn_for_node(topo_groups_find(rconn->inst->topo_groups, rconn->group_id), rconn->remote_node_id);; if (seq == rconn->rx_seq) router_try_assembly(rconn, conn); router_schedule_ack(rconn); queue_resume_callback(q); @@ -788,7 +801,7 @@ static int router_verify_signature(struct UTUN_INSTANCE* inst, struct ll_entry* } size_t actual_payload = *pl_len - SC_SIGN_SIZE; uint8_t* sig = (uint8_t*)entry->dgram + SVC_ROUTE_HDR_SIZE + actual_payload; - struct TOPO_GROUP* group = topo_groups_get_default(inst->topo_groups); + struct TOPO_GROUP* group = topo_groups_find(inst->topo_groups, hdr->group_id); struct TOPO_NODEQ* nq = group ? topo_node_find_by_id(group, hdr->src_node_id) : NULL; if (!nq) { DEBUG_WARN(DEBUG_CATEGORY_ETCPROUTE, "router: SIGNED packet from unknown node %016llx — dropping", @@ -818,7 +831,7 @@ static int router_verify_signature(struct UTUN_INSTANCE* inst, struct ll_entry* if (sc_stream_sign_verify(&vfy_state, sig, SC_SIGN_SIZE) != SC_OK) { DEBUG_WARN(DEBUG_CATEGORY_ETCPROUTE, "router: signature verification FAILED for node %016llx svc_id=%u — dropping", (unsigned long long)hdr->src_node_id, hdr->svc_id); - struct ETCP_ROUTER_CONN* sr = router_conn_find(inst, hdr->src_node_id, hdr->svc_id); + struct ETCP_ROUTER_CONN* sr = router_conn_find(inst, hdr->group_id, hdr->src_node_id, hdr->svc_id); if (sr) sr->c_sign_fail++; free_entry(entry); return -1; } @@ -875,13 +888,13 @@ static void router_handle_ack(struct UTUN_INSTANCE* inst, struct ETCP_ROUTER_CON static void router_forward_transit(struct UTUN_INSTANCE* inst, struct ll_entry* entry, struct SVC_ROUTE_HDR* hdr) { - struct ETCP_CONN* next = topo_group_find_conn_for_node(topo_groups_get_default(inst->topo_groups), hdr->dst_node_id); + struct ETCP_CONN* next = topo_group_find_conn_for_node(topo_groups_find(inst->topo_groups, hdr->group_id), hdr->dst_node_id); if (!next) { DEBUG_WARN(DEBUG_CATEGORY_ETCPROUTE, "etcp_router: no route to %016llx svc_id=%u, dropping", (unsigned long long)hdr->dst_node_id, hdr->svc_id); free_entry(entry); return; } - struct TRANSIT_QUEUE* tq = transit_queue_find(next, hdr->src_node_id, hdr->dst_node_id); + struct TRANSIT_QUEUE* tq = transit_queue_find(next, hdr->group_id, hdr->src_node_id, hdr->dst_node_id); if (!tq && next->send_input_q && queue_entry_count(next->send_input_q) == 0) { DEBUG_TRACE(DEBUG_CATEGORY_ETCPROUTE, "etcp_router: forwarding svc_id=%u → %016llx via %s", @@ -892,7 +905,7 @@ static void router_forward_transit(struct UTUN_INSTANCE* inst, struct ll_entry* } if (!tq) { - tq = transit_queue_get_or_create(next, hdr->src_node_id, hdr->dst_node_id); + tq = transit_queue_get_or_create(next, hdr->group_id, hdr->src_node_id, hdr->dst_node_id); if (!tq) { free_entry(entry); return; } } int was_empty = (queue_entry_count(tq->q) == 0); @@ -914,8 +927,8 @@ static int router_check_peer_restart(struct UTUN_INSTANCE* inst, struct ETCP_ROU "router: peer restart sess_id=%u→%u svc_id=%u from %016llx", rconn->peer_sess_id, incoming_sess, hdr->svc_id, (unsigned long long)hdr->src_node_id); - etcp_router_conn_restart(inst, hdr->src_node_id, hdr->svc_id); - *prconn = etcp_router_conn_get(inst, hdr->src_node_id, hdr->svc_id); + etcp_router_conn_restart(inst, hdr->group_id, hdr->src_node_id, hdr->svc_id); + *prconn = etcp_router_conn_get(inst, hdr->group_id, hdr->src_node_id, hdr->svc_id); if (!*prconn) return -1; (*prconn)->peer_sess_id = incoming_sess; rconn = *prconn; @@ -987,7 +1000,7 @@ static void etcp_router_recv_cb(struct ETCP_CONN* conn, struct ll_entry* entry) if (router_verify_signature(inst, entry, hdr, &pl_len) != 0) return; - struct ETCP_ROUTER_CONN* rconn = router_conn_find(inst, hdr->src_node_id, hdr->svc_id); + struct ETCP_ROUTER_CONN* rconn = router_conn_find(inst, hdr->group_id, hdr->src_node_id, hdr->svc_id); if (pl_len == 0 && (hdr->flags & (ROUTER_FLAG_CLOSE | ROUTER_FLAG_RST))) { if (rconn) router_close_and_notify(rconn); @@ -996,7 +1009,7 @@ static void etcp_router_recv_cb(struct ETCP_CONN* conn, struct ll_entry* entry) if (pl_len == 0) { router_handle_ack(inst, rconn, hdr->seq, hdr->src_node_id, hdr->timestamp); free_entry(entry); return; } if (!rconn) { - rconn = etcp_router_conn_get(inst, hdr->src_node_id, hdr->svc_id); + rconn = etcp_router_conn_get(inst, hdr->group_id, hdr->src_node_id, hdr->svc_id); if (!rconn) { free_entry(entry); return; } rconn->peer_sess_id = (hdr->flags >> ROUTER_SESS_ID_SHIFT) & 0x3; } @@ -1017,7 +1030,7 @@ int etcp_router_init(struct UTUN_INSTANCE* inst) { if (!inst) { DEBUG_ERROR(DEBUG_CATEGORY_ETCPROUTE, "NULL instance"); return -1; } memset(&inst->router_bindings, 0, sizeof(inst->router_bindings)); inst->router_conns = queue_new(inst->ua, - ROUTER_CONN_HASH_SIZE, 0, 9, "router_conns"); + ROUTER_CONN_HASH_SIZE, 0, 17, "router_conns"); if (!inst->router_conns) { DEBUG_ERROR(DEBUG_CATEGORY_ETCPROUTE, "queue_new(router_conns) failed"); return -1; @@ -1069,7 +1082,7 @@ int etcp_router_unbind(struct UTUN_INSTANCE* inst, uint8_t svc_id) { return 0; } -int etcp_route_send(struct UTUN_INSTANCE* inst, uint64_t dst_node_id, struct ll_entry* entry, int force) { +int etcp_route_send(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t dst_node_id, struct ll_entry* entry, int force) { if (!inst || !entry) { DEBUG_ERROR(DEBUG_CATEGORY_ETCPROUTE, "NULL inst=%p entry=%p", (void*)inst, (void*)entry); if (entry) { queue_dgram_free(entry); queue_entry_free(entry); } return -1; @@ -1089,9 +1102,9 @@ int etcp_route_send(struct UTUN_INSTANCE* inst, uint64_t dst_node_id, struct ll_ return 0; } - struct ETCP_CONN* etcp_conn = topo_group_find_conn_for_node(topo_groups_get_default(inst->topo_groups), dst_node_id); + struct ETCP_CONN* etcp_conn = topo_group_find_conn_for_node(topo_groups_find(inst->topo_groups, group_id), dst_node_id); if (!etcp_conn) { - struct ETCP_ROUTER_CONN* rconn = etcp_router_conn_get(inst, dst_node_id, svc_id); + struct ETCP_ROUTER_CONN* rconn = etcp_router_conn_get(inst, group_id, dst_node_id, svc_id); if (!rconn) { queue_dgram_free(entry); queue_entry_free(entry); return -1; } int eq_ret = router_enqueue_send(rconn, entry->dgram + 1, payload_len, force); queue_dgram_free(entry); queue_entry_free(entry); @@ -1105,7 +1118,7 @@ int etcp_route_send(struct UTUN_INSTANCE* inst, uint64_t dst_node_id, struct ll_ return -1; } - struct ETCP_ROUTER_CONN* rconn = etcp_router_conn_get(inst, dst_node_id, svc_id); + struct ETCP_ROUTER_CONN* rconn = etcp_router_conn_get(inst, group_id, dst_node_id, svc_id); if (!rconn) { queue_dgram_free(entry); queue_entry_free(entry); return -1; } if ((int32_t)(rconn->tx_seq - rconn->tx_acked) >= (int32_t)router_effective_max_inflight(rconn)) { @@ -1119,32 +1132,32 @@ int etcp_route_send(struct UTUN_INSTANCE* inst, uint64_t dst_node_id, struct ll_ return ret; } -int etcp_router_input_q_count(struct UTUN_INSTANCE* inst, uint64_t node_id) { - if (!inst || !topo_groups_get_default(inst->topo_groups)) return -1; - struct ETCP_CONN* conn = topo_group_find_conn_for_node(topo_groups_get_default(inst->topo_groups), node_id); +int etcp_router_input_q_count(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t node_id) { + if (!inst || !topo_groups_find(inst->topo_groups, group_id)) return -1; + struct ETCP_CONN* conn = topo_group_find_conn_for_node(topo_groups_find(inst->topo_groups, group_id), node_id); if (!conn || !conn->normalizer || !conn->normalizer->input) return -1; return queue_entry_count(conn->normalizer->input); } -void etcp_router_waiter_register(struct UTUN_INSTANCE* inst, uint64_t peer_node_id, +void etcp_router_waiter_register(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t peer_node_id, struct queue_waiter_handle* h, queue_threshold_callback_fn callback, void* arg) { - if (!inst || !topo_groups_get_default(inst->topo_groups) || !h) return; - struct ETCP_CONN* conn = topo_group_find_conn_for_node(topo_groups_get_default(inst->topo_groups), peer_node_id); + if (!inst || !topo_groups_find(inst->topo_groups, group_id) || !h) return; + struct ETCP_CONN* conn = topo_group_find_conn_for_node(topo_groups_find(inst->topo_groups, group_id), peer_node_id); if (!conn || !conn->normalizer || !conn->normalizer->input) return; queue_waiter_wait(conn->normalizer->input, h, callback, arg); } -void etcp_router_waiter_cancel(struct UTUN_INSTANCE* inst, uint64_t peer_node_id, +void etcp_router_waiter_cancel(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t peer_node_id, struct queue_waiter_handle* h) { - if (!inst || !topo_groups_get_default(inst->topo_groups) || !h) return; - struct ETCP_CONN* conn = topo_group_find_conn_for_node(topo_groups_get_default(inst->topo_groups), peer_node_id); + if (!inst || !topo_groups_find(inst->topo_groups, group_id) || !h) return; + struct ETCP_CONN* conn = topo_group_find_conn_for_node(topo_groups_find(inst->topo_groups, group_id), peer_node_id); if (!conn || !conn->normalizer || !conn->normalizer->input) return; queue_waiter_cancel(conn->normalizer->input, h); } -void etcp_router_conn_restart(struct UTUN_INSTANCE* inst, uint64_t remote_node_id, uint8_t svc_id) { - struct ETCP_ROUTER_CONN* rconn = router_conn_find(inst, remote_node_id, svc_id); +void etcp_router_conn_restart(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t remote_node_id, uint8_t svc_id) { + struct ETCP_ROUTER_CONN* rconn = router_conn_find(inst, group_id, remote_node_id, svc_id); if (!rconn) return; DEBUG_INFO(DEBUG_CATEGORY_ETCPROUTE, "router_restart: svc_id=%u remote=%016llx — resetting local state", @@ -1241,19 +1254,19 @@ void etcp_router_conn_restart(struct UTUN_INSTANCE* inst, uint64_t remote_node_i rconn->closed = 0; } -void etcp_router_on_send_ready(struct UTUN_INSTANCE* inst, uint64_t node_id, uint8_t svc_id, +void etcp_router_on_send_ready(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t node_id, uint8_t svc_id, struct queue_waiter_handle* h, queue_threshold_callback_fn callback, void* arg) { if (!inst || !h) return; - struct ETCP_ROUTER_CONN* rconn = router_conn_find(inst, node_id, svc_id); + struct ETCP_ROUTER_CONN* rconn = router_conn_find(inst, group_id, node_id, svc_id); if (!rconn || !rconn->send_q) return; queue_waiter_wait(rconn->send_q, h, callback, arg); } -void etcp_router_cancel_send_ready(struct UTUN_INSTANCE* inst, uint64_t node_id, uint8_t svc_id, +void etcp_router_cancel_send_ready(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t node_id, uint8_t svc_id, struct queue_waiter_handle* h) { if (!inst || !h) return; - struct ETCP_ROUTER_CONN* rconn = router_conn_find(inst, node_id, svc_id); + struct ETCP_ROUTER_CONN* rconn = router_conn_find(inst, group_id, node_id, svc_id); if (!rconn || !rconn->send_q) return; queue_waiter_cancel(rconn->send_q, h); } @@ -1263,16 +1276,21 @@ void etcp_router_cancel_send_ready(struct UTUN_INSTANCE* inst, uint64_t node_id, // ==================================================================== struct ETCP_ROUTER_CONN* etcp_router_conn_get(struct UTUN_INSTANCE* inst, + uint64_t group_id, uint64_t remote_node_id, uint8_t svc_id) { if (!inst || !inst->router_conns) return NULL; - struct ETCP_ROUTER_CONN* rconn = router_conn_find(inst, remote_node_id, svc_id); + struct ETCP_ROUTER_CONN* rconn = router_conn_find(inst, group_id, remote_node_id, svc_id); if (rconn) return rconn; size_t data_size = sizeof(struct ETCP_ROUTER_CONN) - sizeof(struct ll_entry); rconn = (struct ETCP_ROUTER_CONN*)queue_entry_new(data_size); if (!rconn) { DEBUG_ERROR(DEBUG_CATEGORY_ETCPROUTE, "router_conn_get: queue_entry_new failed"); return NULL; } + rconn->group_id = group_id; rconn->remote_node_id = remote_node_id; rconn->svc_id = svc_id; + memcpy(rconn->ll.data, &group_id, 8); + memcpy(rconn->ll.data + 8, &remote_node_id, 8); + rconn->ll.data[16] = svc_id; rconn->last_dgram_ts = get_current_timestamp(); rconn->rtt = 0; rconn->rtt_jitter = 0; @@ -1333,8 +1351,8 @@ struct ETCP_ROUTER_CONN* etcp_router_conn_get(struct UTUN_INSTANCE* inst, queue_set_threshold(rconn->incoming_q, 0, 0); rconn->incoming_data_ready = 0; queue_set_threshold(rconn->send_q, ROUTER_MAX_SEND_Q_PACKETS - 1, 0); - DEBUG_INFO(DEBUG_CATEGORY_ETCPROUTE, "router_conn: new conn remote=%016llx svc_id=%u", - (unsigned long long)remote_node_id, svc_id); + DEBUG_INFO(DEBUG_CATEGORY_ETCPROUTE, "router_conn: new conn group=%016llx remote=%016llx svc_id=%u", + (unsigned long long)group_id, (unsigned long long)remote_node_id, svc_id); queue_data_put_with_index(inst->router_conns, &rconn->ll); return rconn; } @@ -1408,7 +1426,7 @@ void etcp_router_pause_retrans_for_node(struct UTUN_INSTANCE* inst, uint64_t rem } } -void etcp_router_conn_close_all_for_node(struct UTUN_INSTANCE* inst, uint64_t remote_node_id) { +void etcp_router_conn_close_all_for_node(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t remote_node_id) { if (!inst || !inst->router_conns) return; // Iterate via hash chains to avoid inf-loop from put-back in FIFO iteration struct ll_entry* to_close[256]; @@ -1419,7 +1437,7 @@ void etcp_router_conn_close_all_for_node(struct UTUN_INSTANCE* inst, uint64_t re while (entry) { struct ll_entry* next = entry->hash_next; struct ETCP_ROUTER_CONN* rconn = (struct ETCP_ROUTER_CONN*)entry; - if (rconn->remote_node_id == remote_node_id) + if (rconn->group_id == group_id && rconn->remote_node_id == remote_node_id) to_close[count++] = entry; entry = next; } diff --git a/src/routing_layer/etcp_router.h b/src/routing_layer/etcp_router.h index 51ff32ce..4930da69 100644 --- a/src/routing_layer/etcp_router.h +++ b/src/routing_layer/etcp_router.h @@ -3,7 +3,7 @@ // Упрощённый TCP поверх ETCP: восстановление порядка, дедупликация, без переповторов // // Формат SVC_ROUTE пакета: -// [cmd:1] [dst_node_id:8] [src_node_id:8] [seq:4] [svc_id:1] [flags:1] [payload...] +// [cmd:1] [group_id:8] [dst_node_id:8] [src_node_id:8] [seq:4] [svc_id:1] [flags:1] [timestamp:2] [payload...] // flags: bit7=START, bit6=RST, bit5-4=sess_id(0-3) // ACK-пакет: тот же заголовок, seq=rx_seq, payload_len=0 #ifndef ETCP_ROUTER_H @@ -22,6 +22,7 @@ extern "C" { #pragma pack(push, 1) struct SVC_ROUTE_HDR { uint8_t cmd; // ETCP_ID_SVC_ROUTE (0x03) / ETCP_RT_ID_SVC_ROUTE + uint64_t group_id; // идентификатор группы uint64_t dst_node_id; uint64_t src_node_id; uint32_t seq; // data: tx_seq; ACK: rx_seq (ожидаемый seq) @@ -30,7 +31,7 @@ struct SVC_ROUTE_HDR { uint16_t timestamp; // часы отправителя (0.1ms), для RTT; ACK: эхо последнего data-пакета }; #pragma pack(pop) -#define SVC_ROUTE_HDR_SIZE sizeof(struct SVC_ROUTE_HDR) // 25 +#define SVC_ROUTE_HDR_SIZE sizeof(struct SVC_ROUTE_HDR) // 33 #define SVC_ROUTE_MAX_BINDINGS 256 // Биты в flags @@ -41,24 +42,26 @@ struct SVC_ROUTE_HDR { #define ROUTER_SESS_ID_SHIFT 4 #define ROUTER_SESS_ID_MASK 0x30 -// Очередь транзитных пакетов для пары (src_node_id, dst_node_id) +// Очередь транзитных пакетов для пары (group_id, src_node_id, dst_node_id) // Создаётся когда не получается отправить пакет в ETCP напрямую, // удаляется когда очередь становится пустой. -// ll.data[0..15] = src:8 + dst:8 — совпадает с полями ниже по памяти +// ll.data[0..23] = group_id:8 + src:8 + dst:8 — совпадает с полями ниже по памяти struct TRANSIT_QUEUE { - struct ll_entry ll; // data[0..15] = src_node_id:8 + dst_node_id:8 (16-byte hash index) - uint64_t src_node_id; // = data[0..7] - uint64_t dst_node_id; // = data[8..15] + struct ll_entry ll; // data[0..23] = group_id:8 + src_node_id:8 + dst_node_id:8 (24-byte hash index) + uint64_t group_id; // = data[0..7] + uint64_t src_node_id; // = data[8..15] + uint64_t dst_node_id; // = data[16..23] struct ll_queue* q; // FIFO транзитных пакетов (ll_entry с dgram), начиная с data[16] struct queue_waiter_handle waiter; // backpressure waiter на bp-очередь (normalizer->input или tx_queue) struct ETCP_CONN* conn; // next_hop (для etcp_send в drain_cb) }; -// Состояние одного логического подключения (remote_node_id + svc_id) +// Состояние одного логического подключения (group_id + remote_node_id + svc_id) struct ETCP_ROUTER_CONN { - struct ll_entry ll; // data[0..7]=remote_node_id, data[8]=svc_id — хеш-индекс - uint64_t remote_node_id; // = data[0..7] - uint8_t svc_id; // = data[8] + struct ll_entry ll; // data[0..15]=group_id:8+remote_node_id:8, data[16]=svc_id — хеш-индекс + uint64_t group_id; // = data[0..7] + uint64_t remote_node_id; // = data[8..15] + uint8_t svc_id; // = data[16] uint16_t last_dgram_ts; // последний timestamp датаграммы (rx или tx, timebase 0.1ms) uint16_t rtt; // измеренный RTT (0.1ms) int32_t rtt_jitter; // EMA jitter, fixed-point *65536 (как в ETCP) @@ -170,11 +173,11 @@ int etcp_router_bind(struct UTUN_INSTANCE* inst, uint8_t svc_id, etcp_recv_fn c int etcp_router_unbind(struct UTUN_INSTANCE* inst, uint8_t svc_id); // Отправить сервисный пакет (авто-conn, seq, inflight-контроль через send_q) -int etcp_route_send(struct UTUN_INSTANCE* inst, uint64_t dst_node_id, struct ll_entry* entry, int force); +int etcp_route_send(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t dst_node_id, struct ll_entry* entry, int force); -// Найти/создать состояние seq-подключения по (remote_node_id, svc_id) +// Найти/создать состояние seq-подключения по (group_id, remote_node_id, svc_id) struct ETCP_ROUTER_CONN* etcp_router_conn_get(struct UTUN_INSTANCE* inst, - uint64_t remote_node_id, uint8_t svc_id); + uint64_t group_id, uint64_t remote_node_id, uint8_t svc_id); // Отправить данные с авто-seq и контролем inflight // data: payload без svc_id, flags: битовые флаги (зарезервировано) @@ -200,30 +203,28 @@ void etcp_router_conn_close_async(struct ETCP_ROUTER_CONN* rconn, // Используется при etcp_conn_reinit чтобы избежать гонки с очисткой ETCP-очередей void etcp_router_pause_retrans_for_node(struct UTUN_INSTANCE* inst, uint64_t remote_node_id); -// Закрыть все router_conn для указанного remote_node_id (peer умер) -void etcp_router_conn_close_all_for_node(struct UTUN_INSTANCE* inst, uint64_t remote_node_id); +// Закрыть все router_conn для указанного (group_id, remote_node_id) (peer умер) +void etcp_router_conn_close_all_for_node(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t remote_node_id); -// Возвращает количество пакетов в очереди normalizer->input для узла node_id -int etcp_router_input_q_count(struct UTUN_INSTANCE* inst, uint64_t node_id); +// Возвращает количество пакетов в очереди normalizer->input для узла node_id в группе group_id +int etcp_router_input_q_count(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t node_id); // Backpressure: зарегистрировать/отменить waiter на normalizer->input очереди -void etcp_router_waiter_register(struct UTUN_INSTANCE* inst, uint64_t peer_node_id, +void etcp_router_waiter_register(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t peer_node_id, struct queue_waiter_handle* h, queue_threshold_callback_fn callback, void* arg); -void etcp_router_waiter_cancel(struct UTUN_INSTANCE* inst, uint64_t peer_node_id, +void etcp_router_waiter_cancel(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t peer_node_id, struct queue_waiter_handle* h); // Backpressure: зарегистрировать/отменить waiter на send_q очереди -// h — handle из структуры сервиса, callback вызывается когда send_q.count <= threshold (128) -void etcp_router_on_send_ready(struct UTUN_INSTANCE* inst, uint64_t node_id, uint8_t svc_id, +void etcp_router_on_send_ready(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t node_id, uint8_t svc_id, struct queue_waiter_handle* h, queue_threshold_callback_fn callback, void* arg); -void etcp_router_cancel_send_ready(struct UTUN_INSTANCE* inst, uint64_t node_id, uint8_t svc_id, +void etcp_router_cancel_send_ready(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t node_id, uint8_t svc_id, struct queue_waiter_handle* h); -// Сбросить состояние роутера для конкретного peer+svc (перезапуск удалённой стороны). -// Очищает send_q/recv_q, уведомляет сервис через cb(NULL, entry) с remote_node_id. -void etcp_router_conn_restart(struct UTUN_INSTANCE* inst, uint64_t remote_node_id, uint8_t svc_id); +// Сбросить состояние роутера для конкретного peer+svc в группе (перезапуск удалённой стороны). +void etcp_router_conn_restart(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t remote_node_id, uint8_t svc_id); // Удалить все транзитные очереди соединения (вызывается при закрытии ETCP_CONN) void etcp_router_transit_queues_destroy(struct ETCP_CONN* conn); diff --git a/src/routing_layer/routing.c b/src/routing_layer/routing.c index fcf1db01..29c0443b 100644 --- a/src/routing_layer/routing.c +++ b/src/routing_layer/routing.c @@ -144,7 +144,7 @@ void route_pkt(struct UTUN_INSTANCE* instance, struct ll_entry* entry, uint64_t } else { DEBUG_TRACE(DEBUG_CATEGORY_ROUTING, "route_pkt: sending %zu bytes to node %016llx dst=%s", ip_len, (unsigned long long)nq->node->node_id, ip_to_str(&addr, AF_INET).str); - int send_err = etcp_route_send(instance, nq->node->node_id, entry, 1); + int send_err = etcp_route_send(instance, nq->node->group_id, nq->node->node_id, entry, 1); if (send_err != 0) { DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_pkt: etcp_route_send failed: dst=%s err=%d", ip_to_str(&addr, AF_INET).str, send_err); diff --git a/src/routing_layer/topo_group.c b/src/routing_layer/topo_group.c index 680b8791..e957f82c 100644 --- a/src/routing_layer/topo_group.c +++ b/src/routing_layer/topo_group.c @@ -38,6 +38,7 @@ static void topo_group_send_table_request(struct TOPO_GROUP* group, struct ETCP_ if (!req) return; req->cmd = ETCP_ID_TOPO_ENTRY; req->subcmd = TOPO_SUBCMD_REQUEST_TABLE; + req->group_id = group->group_id; struct ll_entry* e = queue_entry_new(0); if (!e) { u_free(req); return; } e->dgram = (uint8_t*)req; e->len = sizeof(struct TOPOMSG_TABLE_REQ); @@ -50,6 +51,7 @@ static void topo_group_send_table_complete(struct TOPO_GROUP* group, struct ETCP if (!req) return; req->cmd = ETCP_ID_TOPO_ENTRY; req->subcmd = TOPO_SUBCMD_TABLE_COMPLETE; + req->group_id = group->group_id; struct ll_entry* e = queue_entry_new(0); if (!e) { u_free(req); return; } e->dgram = (uint8_t*)req; e->len = sizeof(struct TOPOMSG_TABLE_REQ); @@ -123,7 +125,7 @@ static void topo_group_broadcast_withdraw(struct TOPO_GROUP* group, uint64_t nod struct TOPOMSG_WITHDRAW_PKT* pkt = u_calloc(1, sizeof(struct TOPOMSG_WITHDRAW_PKT)); if (!pkt) return; pkt->cmd = ETCP_ID_TOPO_ENTRY; pkt->subcmd = TOPO_SUBCMD_WITHDRAW; - pkt->node_id = node_id; pkt->wd_source = wd_source; + pkt->group_id = group->group_id; pkt->node_id = node_id; pkt->wd_source = wd_source; struct ll_entry* e = group->senders_list ? group->senders_list->head : NULL; while (e) { struct TOPO_GROUP_CONN_ITEM* item = (struct TOPO_GROUP_CONN_ITEM*)e->data; @@ -145,12 +147,29 @@ static void topo_group_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry* if (!from_conn || !entry || entry->len < 2) { if (entry) { queue_dgram_free(entry); queue_entry_free(entry); } return; } struct UTUN_INSTANCE* instance = from_conn->instance; if (!instance || !instance->topo_groups) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "invalid instance/topo_groups"); queue_dgram_free(entry); queue_entry_free(entry); return; } - struct TOPO_GROUP* group = topo_groups_get_default(instance->topo_groups); - if (!group) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "no default group"); queue_dgram_free(entry); queue_entry_free(entry); return; } uint8_t* data = entry->dgram; uint8_t cmd = data[0]; uint8_t subcmd = data[1]; if (cmd != ETCP_ID_TOPO_ENTRY) { queue_dgram_free(entry); queue_entry_free(entry); return; } - DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP recv %s from %s len=%zu", group_subcmd_name(subcmd), from_conn->log_name, entry->len); + uint64_t pkt_group_id = 0; + if (subcmd == TOPO_SUBCMD_NODEINFO && entry->len >= 3) { + pkt_group_id = ((struct TOPOMSG_NODEINFO_PKT*)data)->node.group_id; + } else if (subcmd == TOPO_SUBCMD_WITHDRAW && entry->len >= sizeof(struct TOPOMSG_WITHDRAW_PKT)) { + pkt_group_id = ((struct TOPOMSG_WITHDRAW_PKT*)data)->group_id; + } else if (subcmd == TOPO_SUBCMD_REQUEST_TABLE && entry->len >= sizeof(struct TOPOMSG_TABLE_REQ)) { + pkt_group_id = ((struct TOPOMSG_TABLE_REQ*)data)->group_id; + } else if (subcmd == TOPO_SUBCMD_TABLE_COMPLETE && entry->len >= sizeof(struct TOPOMSG_TABLE_REQ)) { + pkt_group_id = ((struct TOPOMSG_TABLE_REQ*)data)->group_id; + } else if (subcmd == TOPO_SUBCMD_ERR_GROUP_MISMATCH && entry->len >= sizeof(struct TOPOMSG_ERR_GROUP_MISMATCH)) { + pkt_group_id = ((struct TOPOMSG_ERR_GROUP_MISMATCH*)data)->group_id; + } + + struct TOPO_GROUP* group = topo_groups_find(instance->topo_groups, pkt_group_id); + if (!group) { + DEBUG_WARN(DEBUG_CATEGORY_BGP, "BGP recv %s from %s: group %016llx not found, dropping", group_subcmd_name(subcmd), from_conn->log_name, (unsigned long long)pkt_group_id); + queue_dgram_free(entry); queue_entry_free(entry); return; + } + + DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP recv %s from %s len=%zu group=%016llx", group_subcmd_name(subcmd), from_conn->log_name, entry->len, (unsigned long long)pkt_group_id); if (subcmd == TOPO_SUBCMD_NODEINFO) { nodeinfo_dump_log(data, entry->len); topo_group_process_nodeinfo(group, from_conn, data, entry->len); } else if (subcmd == TOPO_SUBCMD_WITHDRAW) topo_group_process_withdraw(group, from_conn, data, entry->len); @@ -159,8 +178,8 @@ static void topo_group_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry* else if (subcmd == TOPO_SUBCMD_ERR_GROUP_MISMATCH) { if (entry->len >= sizeof(struct TOPOMSG_ERR_GROUP_MISMATCH)) { struct TOPOMSG_ERR_GROUP_MISMATCH* err = (struct TOPOMSG_ERR_GROUP_MISMATCH*)data; - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "Group type mismatch from %s: expected_type=%u received_flags=0x%02x", - from_conn->log_name, err->expected_type, err->received_flags); + DEBUG_ERROR(DEBUG_CATEGORY_BGP, "Group mismatch from %s: expected=%u received=0x%02x group=%016llx", + from_conn->log_name, err->expected_type, err->received_flags, (unsigned long long)err->group_id); } } @@ -172,25 +191,13 @@ static void topo_group_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry* // Init / Destroy / New / Remove conn // ============================================================================ -static void topo_group_on_conn_up(struct ETCP_CONN* conn, void* arg) { - (void)arg; - if (conn && conn->instance && conn->instance->topo_groups) { - struct TOPO_GROUP* group = topo_groups_get_default(conn->instance->topo_groups); - if (group) { DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP peer UP: %s peer=%016llx", conn->log_name, (unsigned long long)conn->peer_node_id); topo_group_new_conn(group, conn); } - } -} -static void topo_group_on_conn_down(struct ETCP_CONN* conn, void* arg) { - (void)arg; - if (conn && conn->instance && conn->instance->topo_groups) { - struct TOPO_GROUP* group = topo_groups_get_default(conn->instance->topo_groups); - if (group) { DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP peer DOWN: %s peer=%016llx", conn->log_name, (unsigned long long)conn->peer_node_id); topo_group_remove_conn(group, conn); } - } -} -static void topo_group_etcp_conn_cbk(struct ETCP_CONN* conn, void* arg) { - (void)arg; - if (conn && conn->instance && conn->instance->topo_groups) { - struct TOPO_GROUP* group = topo_groups_get_default(conn->instance->topo_groups); - if (group) { DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP set callbacks: %s", conn->log_name); etcp_conn_add_up_cbk(conn, topo_group_on_conn_up, group); etcp_conn_add_down_cbk(conn, topo_group_on_conn_down, group); } +static void topo_group_conn_status(struct ETCP_CONN* conn, int status, void* arg) { + struct TOPO_GROUPS* groups = (struct TOPO_GROUPS*)arg; + if (!conn || !groups) return; + struct ll_entry* fe = groups->group_list->head; + while (fe) { struct TOPO_GROUP* g = (struct TOPO_GROUP*)fe; fe = fe->next; + if (status == ETCP_CONN_STATUS_UP) topo_group_new_conn(g, conn); + if (status == ETCP_CONN_STATUS_DOWN) topo_group_remove_conn(g, conn); } } @@ -246,6 +253,9 @@ struct TOPO_GROUPS* topo_groups_init(struct UTUN_INSTANCE* instance) { g->group_list = queue_new(instance->ua, 16, 0, 8, "topo_groups"); if (!g->group_list) { u_free(g); DEBUG_ERROR(DEBUG_CATEGORY_BGP, "group_list queue creation failed"); return NULL; } + g->node_registry = queue_new(instance->ua, TOPO_NODE_REGISTRY_HASH_SIZE, 0, 8, "node_registry"); + if (!g->node_registry) { queue_free(g->group_list); u_free(g); DEBUG_ERROR(DEBUG_CATEGORY_BGP, "node_registry queue creation failed"); return NULL; } + g->v4_sock_meta_pool = memory_pool_init(sizeof(struct TOPO_SOCKMETA4), "to_v4sock"); g->v4_addr_pool = memory_pool_init(sizeof(struct TOPO_ADDR4), "to_v4addr"); g->v6_sock_meta_pool = memory_pool_init(sizeof(struct TOPO_SOCKMETA6), "to_v6sock"); @@ -281,14 +291,14 @@ struct TOPO_GROUPS* topo_groups_init(struct UTUN_INSTANCE* instance) { memory_pool_destroy(g->v4_sock_meta_pool); memory_pool_destroy(g->v4_addr_pool); memory_pool_destroy(g->v6_sock_meta_pool); memory_pool_destroy(g->v6_addr_pool); memory_pool_destroy(g->v4_subnet_pool); memory_pool_destroy(g->v6_subnet_pool); - queue_free(g->group_list); u_free(g); + queue_free(g->node_registry); queue_free(g->group_list); u_free(g); DEBUG_ERROR(DEBUG_CATEGORY_BGP, "failed to create default group"); return NULL; } queue_data_put_with_index(g->group_list, &default_group->ll); etcp_bind(instance, ETCP_ID_TOPO_ENTRY, topo_group_receive_cbk); - etcp_add_new_conn_cbk(instance, topo_group_etcp_conn_cbk, NULL); + etcp_add_conn_status_cbk(instance, topo_group_conn_status, g); DEBUG_INFO(DEBUG_CATEGORY_BGP, "TOPO groups initialized (with default group)"); return g; @@ -300,6 +310,7 @@ void topo_groups_destroy(struct UTUN_INSTANCE* instance) { DEBUG_INFO(DEBUG_CATEGORY_BGP, "node_id=%016llx", (unsigned long long)instance->node_id); etcp_unbind(instance, ETCP_ID_TOPO_ENTRY); + etcp_remove_conn_status_cbk(instance, topo_group_conn_status, instance->topo_groups); route_connectivity_cancel_all(instance); struct TOPO_GROUPS* g = instance->topo_groups; @@ -307,6 +318,16 @@ void topo_groups_destroy(struct UTUN_INSTANCE* instance) { while ((ge = queue_data_get(g->group_list)) != NULL) { struct TOPO_GROUP* grp = (struct TOPO_GROUP*)ge; topo_group_destroy(grp); queue_entry_free(ge); } queue_free(g->group_list); + if (g->node_registry) { + struct ll_entry* re; + while ((re = queue_data_get(g->node_registry)) != NULL) { + struct TOPO_NODE_REG_ENTRY* r = (struct TOPO_NODE_REG_ENTRY*)re; + topo_node_unref(r->node); + queue_entry_free(re); + } + queue_free(g->node_registry); + } + memory_pool_destroy(g->v4_sock_meta_pool); memory_pool_destroy(g->v4_addr_pool); memory_pool_destroy(g->v6_sock_meta_pool); @@ -336,6 +357,20 @@ struct TOPO_GROUP* topo_groups_create_group(struct TOPO_GROUPS* g, uint64_t grou if (!group) return NULL; if (channel_id) { strncpy(group->channel_id, channel_id, sizeof(group->channel_id) - 1); group->channel_id[sizeof(group->channel_id) - 1] = '\0'; } queue_data_put_with_index(g->group_list, &group->ll); + + struct ll_queue* connections = g->instance->connections; + if (connections) { + for (uint32_t slot = 0; slot < connections->hash_size; slot++) { + struct ll_entry* entry = connections->hash_table[slot]; + while (entry) { + struct conn_queue_entry* cqe = (struct conn_queue_entry*)entry; + if (cqe->conn && cqe->peer_node_id != 0) + topo_group_new_conn(group, cqe->conn); + entry = entry->hash_next; + } + } + } + DEBUG_INFO(DEBUG_CATEGORY_BGP, "Group created: group_id=%016llx type=%u ch_id=%s", (unsigned long long)group_id, group_type, group->channel_id); return group; } @@ -390,7 +425,7 @@ void topo_group_remove_conn(struct TOPO_GROUP* group, struct ETCP_CONN* conn) { struct ll_entry* entry = node_entry; if (entry) { queue_remove_data(group->nodes, entry); queue_entry_free(entry); } nodes_removed++; - etcp_router_conn_close_all_for_node(group->instance, key); + etcp_router_conn_close_all_for_node(group->instance, group->group_id, key); uint64_t wd_src = (key == conn->peer_node_id) ? conn->instance->node_id : conn->peer_node_id; topo_group_broadcast_withdraw(group, key, wd_src, NULL); DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "Removed node %016llx after link down", (unsigned long long)key); @@ -468,6 +503,7 @@ static void topo_group_send_err_group_mismatch(struct TOPO_GROUP* group, struct struct TOPOMSG_ERR_GROUP_MISMATCH* pkt = u_calloc(1, sizeof(struct TOPOMSG_ERR_GROUP_MISMATCH)); if (!pkt) return; pkt->cmd = ETCP_ID_TOPO_ENTRY; pkt->subcmd = TOPO_SUBCMD_ERR_GROUP_MISMATCH; + pkt->group_id = group->group_id; pkt->expected_type = expected_type; pkt->received_flags = received_flags; struct ll_entry* e = queue_entry_new(0); if (!e) { u_free(pkt); return; } @@ -481,6 +517,12 @@ int topo_group_process_nodeinfo(struct TOPO_GROUP* group, struct ETCP_CONN* from struct TOPOMSG_NODEINFO_PKT* pkt = (struct TOPOMSG_NODEINFO_PKT*)data; struct TOPOMSG_NODE* ni = &pkt->node; + if (ni->group_id != group->group_id) { + DEBUG_ERROR(DEBUG_CATEGORY_BGP, "NODEINFO group_id mismatch from %s: expected=%016llx got=%016llx", + from->log_name, (unsigned long long)group->group_id, (unsigned long long)ni->group_id); + return -1; + } + // Проверка соответствия типа группы uint8_t expected_flags = (group->group_type == TOPO_GROUP_TYPE_CHAT) ? 0 : TOPO_FLAG_SEND_SUBNETS; if ((ni->flags & TOPO_FLAG_SEND_SUBNETS) != expected_flags) { @@ -538,8 +580,8 @@ int topo_group_process_nodeinfo(struct TOPO_GROUP* group, struct ETCP_CONN* from } if (nodeinfo1) { - nodeinfo1->node = new_ni; topo_node_ref(new_ni); - nodeinfo1->hash_node_id = new_ni->node_id; + nodeinfo1->node = topo_node_registry_acquire(group->instance->topo_groups, new_ni); + nodeinfo1->hash_node_id = nodeinfo1->node ? nodeinfo1->node->node_id : 0; nodeinfo1->subnets = new_subnets; u_free(nodeinfo1->tranzit_data); nodeinfo1->tranzit_data = new_tranzit; nodeinfo1->tranzit_count = new_tranzit_count; @@ -547,11 +589,11 @@ int topo_group_process_nodeinfo(struct TOPO_GROUP* group, struct ETCP_CONN* from nodeinfo1->hop_count = new_hop_count; } else { struct ll_entry* qe = queue_entry_new(sizeof(struct TOPO_NODEQ)); - if (!qe) { topo_node_unref(new_ni); u_free(new_tranzit); u_free(new_hop_list); u_free(new_subnets); return -1; } + if (!qe) { topo_node_free_raw(group->instance->topo_groups, new_ni); u_free(new_tranzit); u_free(new_hop_list); u_free(new_subnets); return -1; } nodeinfo1 = (struct TOPO_NODEQ*)qe; memset((uint8_t*)nodeinfo1 + sizeof(struct ll_entry), 0, sizeof(*nodeinfo1) - sizeof(struct ll_entry)); - nodeinfo1->node = new_ni; topo_node_ref(new_ni); - nodeinfo1->hash_node_id = new_ni->node_id; + nodeinfo1->node = topo_node_registry_acquire(group->instance->topo_groups, new_ni); + nodeinfo1->hash_node_id = nodeinfo1->node ? nodeinfo1->node->node_id : 0; nodeinfo1->subnets = new_subnets; nodeinfo1->tranzit_data = new_tranzit; nodeinfo1->tranzit_count = new_tranzit_count; nodeinfo1->hop_list = new_hop_list; nodeinfo1->hop_count = new_hop_count; diff --git a/src/routing_layer/topo_group.h b/src/routing_layer/topo_group.h index afd4e639..3f5d47d5 100644 --- a/src/routing_layer/topo_group.h +++ b/src/routing_layer/topo_group.h @@ -76,16 +76,18 @@ struct TOPOMSG_NODEINFO_PKT { struct TOPOMSG_WITHDRAW_PKT { uint8_t cmd; uint8_t subcmd; + uint64_t group_id; // идентификатор группы uint64_t node_id; // удаляемый узел (который стал недоступен) uint64_t wd_source; // узел который инициировал withdraw (при удалении он должен быть в hoplist или = current node_id) } __attribute__((packed)); /** - * @brief Пакет запроса полной таблицы + * @brief Пакет запроса полной таблицы / завершения синхронизации */ struct TOPOMSG_TABLE_REQ { uint8_t cmd; uint8_t subcmd; + uint64_t group_id; // идентификатор группы } __attribute__((packed)); /** @@ -94,6 +96,7 @@ struct TOPOMSG_TABLE_REQ { struct TOPOMSG_ERR_GROUP_MISMATCH { uint8_t cmd; uint8_t subcmd; + uint64_t group_id; // идентификатор группы uint8_t expected_type; uint8_t received_flags; } __attribute__((packed)); @@ -105,6 +108,13 @@ struct TOPO_GROUP_CONN_ITEM { struct ETCP_LINK; +#define TOPO_NODE_REGISTRY_HASH_SIZE 256 + +struct TOPO_NODE_REG_ENTRY { + struct ll_entry ll; // data[0..7] = node_id (hash key) + struct TOPO_NODE* node; +}; + /** * @brief Группа топологии (одна на каждый group_id: utun, чат-группа, …) */ @@ -126,6 +136,7 @@ struct TOPO_GROUP { struct TOPO_GROUPS { struct UTUN_INSTANCE* instance; struct ll_queue* group_list; // ll_queue of TOPO_GROUP entries + struct ll_queue* node_registry; // глобальный реестр TOPO_NODE* по node_id (hash=8) struct memory_pool* v4_sock_meta_pool; struct memory_pool* v4_addr_pool; struct memory_pool* v6_sock_meta_pool; diff --git a/src/routing_layer/topo_node.c b/src/routing_layer/topo_node.c index d58a80ee..03edb123 100644 --- a/src/routing_layer/topo_node.c +++ b/src/routing_layer/topo_node.c @@ -48,6 +48,18 @@ static void free_v6_sub_list(struct memory_pool* pool, struct TOPO_SUBNET6* head while (head) { struct TOPO_SUBNET6* next = head->next; memory_pool_free(pool, head); head = next; } } +void topo_node_free_raw(struct TOPO_GROUPS* groups, struct TOPO_NODE* ni) { + if (!ni) return; + if (groups) { + free_v4_sock_list(groups->v4_sock_meta_pool, ni->v4_sock_meta); + free_v4_addr_list(groups->v4_addr_pool, ni->v4_addrs); + free_v6_sock_list(groups->v6_sock_meta_pool, ni->v6_sock_meta); + free_v6_addr_list(groups->v6_addr_pool, ni->v6_addrs); + } + u_free(ni->node_name); + u_free(ni); +} + void topo_node_free_lists(struct TOPO_GROUP* group, struct TOPO_NODEQ* nq) { if (!group || !nq) return; if (nq->node) { @@ -57,7 +69,7 @@ void topo_node_free_lists(struct TOPO_GROUP* group, struct TOPO_NODEQ* nq) { free_v6_addr_list(group->instance->topo_groups->v6_addr_pool, nq->node->v6_addrs); nq->node->v4_sock_meta = NULL; nq->node->v4_addrs = NULL; nq->node->v6_sock_meta = NULL; nq->node->v6_addrs = NULL; - topo_node_unref(nq->node); + topo_node_registry_release(group->instance->topo_groups, nq->node); nq->node = NULL; } if (nq->subnets) { @@ -70,6 +82,46 @@ void topo_node_free_lists(struct TOPO_GROUP* group, struct TOPO_NODEQ* nq) { u_free(nq->hop_list); nq->hop_list = NULL; nq->hop_count = 0; } +// ===== глобальный реестр TOPO_NODE ===== + +static struct TOPO_NODE* node_registry_find(struct TOPO_GROUPS* groups, uint64_t node_id) { + if (!groups || !groups->node_registry) return NULL; + struct ll_entry* e = queue_find_data_by_index(groups->node_registry, &node_id); + return e ? ((struct TOPO_NODE_REG_ENTRY*)e)->node : NULL; +} + +struct TOPO_NODE* topo_node_registry_acquire(struct TOPO_GROUPS* groups, struct TOPO_NODE* ni) { + if (!groups || !ni) return NULL; + struct TOPO_NODE* existing = node_registry_find(groups, ni->node_id); + if (existing) { + topo_node_ref(existing); + topo_node_free_raw(groups, ni); + return existing; + } + struct ll_entry* qe = queue_entry_new(sizeof(struct TOPO_NODE_REG_ENTRY)); + if (!qe) { + DEBUG_ERROR(DEBUG_CATEGORY_BGP, "registry_acquire: queue_entry_new failed for node=%016llx", (unsigned long long)ni->node_id); + return NULL; + } + struct TOPO_NODE_REG_ENTRY* re = (struct TOPO_NODE_REG_ENTRY*)qe; + re->node = ni; + topo_node_ref(ni); + memcpy(re->ll.data, &ni->node_id, 8); + queue_data_put_with_index(groups->node_registry, &re->ll); + return ni; +} + +void topo_node_registry_release(struct TOPO_GROUPS* groups, struct TOPO_NODE* ni) { + if (!groups || !ni) return; + uint64_t node_id = ni->node_id; + uint32_t prev_ref = ni->ref_count; + topo_node_unref(ni); + if (prev_ref == 1) { + struct ll_entry* e = groups->node_registry ? queue_find_data_by_index(groups->node_registry, &node_id) : NULL; + if (e) { queue_remove_data(groups->node_registry, e); queue_entry_free(e); } + } +} + // ===== serialization ===== int topo_node_dyn_size(const struct TOPOMSG_NODE* msg) { @@ -167,7 +219,7 @@ int topo_node_deserialize(struct TOPO_GROUP* group, const uint8_t* data, size_t struct TOPO_NODE* ni = u_calloc(1, sizeof(struct TOPO_NODE)); if (!ni) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "alloc TOPO_NODE failed"); return -1; } - ni->ref_count = 1; + ni->ref_count = 0; ni->flags = msg->flags; ni->group_id = msg->group_id; ni->node_id = msg->node_id; @@ -186,46 +238,46 @@ int topo_node_deserialize(struct TOPO_GROUP* group, const uint8_t* data, size_t for (int i = 0; i < msg->local_v4_sockets; i++) { const struct TOPOMSG_SOCKMETA4* w = (const struct TOPOMSG_SOCKMETA4*)dp; dp += sizeof(*w); struct TOPO_SOCKMETA4* e = memory_pool_alloc(group->instance->topo_groups->v4_sock_meta_pool); - if (!e) { topo_node_unref(ni); return -1; } + if (!e) { topo_node_free_raw(group->instance->topo_groups, ni); return -1; } e->id = w->id; e->config_type = w->config_type; e->nat_type = w->nat_type; e->next = ni->v4_sock_meta; ni->v4_sock_meta = e; } for (int i = 0; i < msg->local_v4_addrs; i++) { const struct TOPOMSG_ADDR4* w = (const struct TOPOMSG_ADDR4*)dp; dp += sizeof(*w); struct TOPO_ADDR4* e = memory_pool_alloc(group->instance->topo_groups->v4_addr_pool); - if (!e) { topo_node_unref(ni); return -1; } + if (!e) { topo_node_free_raw(group->instance->topo_groups, ni); return -1; } memcpy(e->addr, w->addr, 4); e->port = w->port; e->type = w->type; e->socket_id = w->socket_id; e->protocol = w->protocol; e->next = ni->v4_addrs; ni->v4_addrs = e; } for (int i = 0; i < msg->local_v6_sockets; i++) { const struct TOPOMSG_SOCKMETA6* w = (const struct TOPOMSG_SOCKMETA6*)dp; dp += sizeof(*w); struct TOPO_SOCKMETA6* e = memory_pool_alloc(group->instance->topo_groups->v6_sock_meta_pool); - if (!e) { topo_node_unref(ni); return -1; } + if (!e) { topo_node_free_raw(group->instance->topo_groups, ni); return -1; } e->id = w->id; e->config_type = w->config_type; e->nat_type = w->nat_type; e->next = ni->v6_sock_meta; ni->v6_sock_meta = e; } for (int i = 0; i < msg->local_v6_addrs; i++) { const struct TOPOMSG_ADDR6* w = (const struct TOPOMSG_ADDR6*)dp; dp += sizeof(*w); struct TOPO_ADDR6* e = memory_pool_alloc(group->instance->topo_groups->v6_addr_pool); - if (!e) { topo_node_unref(ni); return -1; } + if (!e) { topo_node_free_raw(group->instance->topo_groups, ni); return -1; } memcpy(e->addr, w->addr, 16); e->port = w->port; e->type = w->type; e->socket_id = w->socket_id; e->protocol = w->protocol; e->next = ni->v6_addrs; ni->v6_addrs = e; } if (out_subnets && (msg->flags & TOPO_FLAG_SEND_SUBNETS) && (msg->local_v4_subnets || msg->local_v6_subnets)) { struct TOPO_NODESUBNETS* r = u_calloc(1, sizeof(struct TOPO_NODESUBNETS)); - if (!r) { topo_node_unref(ni); return -1; } + if (!r) { topo_node_free_raw(group->instance->topo_groups, ni); return -1; } for (int i = 0; i < msg->local_v4_subnets; i++) { const struct TOPOMSG_SUBNET4* w = (const struct TOPOMSG_SUBNET4*)dp; dp += sizeof(*w); struct TOPO_SUBNET4* e = memory_pool_alloc(group->instance->topo_groups->v4_subnet_pool); - if (!e) { u_free(r); topo_node_unref(ni); return -1; } + if (!e) { u_free(r); topo_node_free_raw(group->instance->topo_groups, ni); return -1; } memcpy(e->addr, w->addr, 4); e->prefix_length = w->prefix_length; e->next = r->v4_subnets; r->v4_subnets = e; } for (int i = 0; i < msg->local_v6_subnets; i++) { const struct TOPOMSG_SUBNET6* w = (const struct TOPOMSG_SUBNET6*)dp; dp += sizeof(*w); struct TOPO_SUBNET6* e = memory_pool_alloc(group->instance->topo_groups->v6_subnet_pool); - if (!e) { u_free(r); topo_node_unref(ni); return -1; } + if (!e) { u_free(r); topo_node_free_raw(group->instance->topo_groups, ni); return -1; } memcpy(e->addr, w->addr, 16); e->prefix_length = w->prefix_length; e->next = r->v6_subnets; r->v6_subnets = e; } @@ -241,14 +293,14 @@ int topo_node_deserialize(struct TOPO_GROUP* group, const uint8_t* data, size_t if (out_tranzit && msg->tranzit_nodes > 0) { size_t tsz = msg->tranzit_nodes * sizeof(struct TOPOMSG_TRANZIT); *out_tranzit = u_malloc(tsz); - if (!*out_tranzit) { topo_node_unref(ni); return -1; } + if (!*out_tranzit) { topo_node_free_raw(group->instance->topo_groups, ni); return -1; } memcpy(*out_tranzit, dp, tsz); dp += tsz; *out_tranzit_count = msg->tranzit_nodes; } if (out_hop_list && msg->hop_count > 0) { size_t hsz = msg->hop_count * 8; *out_hop_list = u_malloc(hsz); - if (!*out_hop_list) { topo_node_unref(ni); return -1; } + if (!*out_hop_list) { topo_node_free_raw(group->instance->topo_groups, ni); return -1; } memcpy(*out_hop_list, dp, hsz); dp += hsz; *out_hop_count = msg->hop_count; } @@ -600,7 +652,7 @@ int topo_group_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct TOPO_GR struct TOPO_NODE* ni = u_calloc(1, sizeof(struct TOPO_NODE)); if (!ni) { u_free(lq); group->local_node = NULL; return -1; } - ni->ref_count = 1; + ni->ref_count = 0; ni->flags = (group->group_type == TOPO_GROUP_TYPE_CHAT) ? 0 : TOPO_FLAG_SEND_SUBNETS; ni->group_id = group->group_id; ni->node_id = instance->node_id; @@ -609,7 +661,7 @@ int topo_group_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct TOPO_GR memcpy(ni->ed25519_public_key, group->ed25519_public_key, SC_PUBKEY_SIZE); if (name_len) { ni->node_name = u_malloc(name_len + 1); if (ni->node_name) { memcpy(ni->node_name, instance->name, name_len); ni->node_name[name_len] = 0; } } - lq->node = ni; + lq->node = topo_node_registry_acquire(instance->topo_groups, ni); lq->hash_node_id = ni->node_id; lq->hop_count = 0; lq->dirty = 1; diff --git a/src/routing_layer/topo_node.h b/src/routing_layer/topo_node.h index 8f80a7d5..f0acec43 100644 --- a/src/routing_layer/topo_node.h +++ b/src/routing_layer/topo_node.h @@ -252,8 +252,20 @@ struct TOPO_NODEQ { struct TOPO_NODEQ* topo_node_find_by_id(struct TOPO_GROUP* group, uint64_t node_id); +// Владение TOPO_NODE: создаётся с ref_count=0. Владелец вызывает topo_node_ref() чтобы завладеть. +// При отказе от владения — topo_node_unref(). При ref_count=0 узел удаляется. void topo_node_ref(struct TOPO_NODE* ni); void topo_node_unref(struct TOPO_NODE* ni); + +// Глобальный реестр TOPO_NODE* (по node_id). Каждый узел хранится один раз. +// При помещении в реестр и при получении из реестра владение берётся (ref++). +// При освобождении из реестра владение возвращается (unref, при ref=0 — удаление). +struct TOPO_NODE* topo_node_registry_acquire(struct TOPO_GROUPS* groups, struct TOPO_NODE* ni); +void topo_node_registry_release(struct TOPO_GROUPS* groups, struct TOPO_NODE* ni); + +// Освободить узел без учёта ref_count (для ошибок после deserialize, пока ref=0). +void topo_node_free_raw(struct TOPO_GROUPS* groups, struct TOPO_NODE* ni); + void topo_node_free_lists(struct TOPO_GROUP* group, struct TOPO_NODEQ* nq); int topo_node_dyn_size(const struct TOPOMSG_NODE* msg); diff --git a/src/transport_layer/etcp_api.h b/src/transport_layer/etcp_api.h index 450f182b..daf78055 100644 --- a/src/transport_layer/etcp_api.h +++ b/src/transport_layer/etcp_api.h @@ -41,7 +41,7 @@ extern "C" { #define ETCP_RT_ID_TCP_PROXY 0x04 // TCP proxy (клиент ↔ exit) #define ETCP_RT_ID_UDP_PROXY 0x05 // UDP datagram прокси (client ↔ exit) #define ETCP_RT_ID_ICMP_PROXY 0x06 // ICMP echo прокси (ping через exit) -#define ETCP_RT_ID_MSG_TRANSPORT 0x10 // msg_transport — локальный IPC транспорт сообщений + #define ETCP_RT_ID_CONN_MGR 0x11 // Connection Manager — management connections // Connection status events (instance-level callback) diff --git a/src/transport_layer/etcp_api_doc.md b/src/transport_layer/etcp_api_doc.md index c807dd25..00203b61 100644 --- a/src/transport_layer/etcp_api_doc.md +++ b/src/transport_layer/etcp_api_doc.md @@ -63,7 +63,6 @@ etcp_set_new_conn_cbk(instance, on_new_conn, my_data); - `ETCP_RT_ID_TCP_PROXY` (0x04) — TCP-прокси - `ETCP_RT_ID_UDP_PROXY` (0x05) — UDP-прокси - `ETCP_RT_ID_ICMP_PROXY` (0x06) — ICMP-прокси -- `ETCP_RT_ID_MSG_TRANSPORT` (0x10) — локальный IPC-транспорт сообщений - `ETCP_RT_ID_CONN_MGR` (0x11) — управление соединениями - `ETCP_ID_NTP_TIME` (0x04) — синхронизация времени (raw ETCP, P2P) diff --git a/src/utun_instance.c b/src/utun_instance.c index 83a456ed..146ad5d4 100644 --- a/src/utun_instance.c +++ b/src/utun_instance.c @@ -16,7 +16,7 @@ #include "db_sync.h" #include "stcp_server.h" #include "control_server.h" -#include "msg_transport.h" + #include "../lib/u_async.h" #include "../lib/debug_config.h" #include "../lib/sha256.h" @@ -399,13 +399,6 @@ void utun_instance_destroy(struct UTUN_INSTANCE *instance) { ntp_time_destroy(instance); ntp_node_time_destroy(instance); - // Shutdown message transport server - if (instance->msg_t) { - DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "Shutting down message transport server"); - msg_transport_shutdown(instance->msg_t); - instance->msg_t = NULL; - } - // Shutdown control server first if (instance->control_srv) { DEBUG_INFO(DEBUG_CATEGORY_CONTROL, "Shutting down control server"); @@ -635,21 +628,6 @@ int utun_instance_init(struct UTUN_INSTANCE *instance) { } } - // Initialize message transport server if configured - if (instance->config->global.msg_transport_sock.ss_family != 0) { - int mt_ret = msg_transport_init(&instance->msg_t, instance, instance->ua, - &instance->config->global.msg_transport_sock, - 8, ETCP_RT_ID_MSG_TRANSPORT); - if (mt_ret != 0) { - DEBUG_WARN(DEBUG_CATEGORY_GENERAL, "Failed to initialize msg_transport, continuing without IPC transport"); - instance->msg_t = NULL; - } else { - DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "Message transport server initialized"); - } - } else { - instance->msg_t = NULL; - } - // Start the main loop instance->running = 1; diff --git a/src/utun_instance.h b/src/utun_instance.h index c4d71c3d..479b2553 100644 --- a/src/utun_instance.h +++ b/src/utun_instance.h @@ -40,7 +40,7 @@ struct ETCP_ROUTER_BINDINGS; struct TOPO_GROUP; struct TOPO_GROUPS; struct control_server; -struct msg_transport; + struct PING_CONTEXT; struct CONN_MGR; struct ETCP_CONNECT; @@ -126,9 +126,6 @@ struct UTUN_INSTANCE { // Control server for monitoring struct control_server* control_srv; - // Message transport server (local IPC → ETCP) - struct msg_transport* msg_t; - // Firewall struct firewall_ctx fw; diff --git a/src/utun_instance_doc.md b/src/utun_instance_doc.md index 07726371..7a09ba60 100644 --- a/src/utun_instance_doc.md +++ b/src/utun_instance_doc.md @@ -28,8 +28,7 @@ utun_instance_init(inst); // запускает всю цепочку иниц 3. `nat_transport_init` — NAT (если включён в конфиге) 4. `init_connections` — ETCP-сокеты, клиентские подключения, handshake 5. `control_server_init` — сервер мониторинга (etcpmon) -6. `msg_transport_init` — IPC-транспорт сообщений (чат, команды) -7. `ntp_time_init` + `ntp_node_time_init` — синхронизация времени +6. `ntp_time_init` + `ntp_node_time_init` — синхронизация времени ### Основной цикл ```c @@ -44,7 +43,7 @@ while (inst->running) { utun_instance_stop(inst); // running=0, wakeup utun_instance_destroy(inst); // полный cleanup в обратном порядке ``` -`destroy` гарантирует порядок: NTP→msg_transport→control→ETCP sockets→db_sync→connections→pings→TUN→tcp_proxy→routing→NAT→etcp_router→conn_mgr→BGP→fw→stcp→networks→config→pools. **uasync не уничтожается** — вызывающий код должен сам вызвать `uasync_destroy()`. +`destroy` гарантирует порядок: NTP→control→ETCP sockets→db_sync→connections→pings→TUN→tcp_proxy→routing→NAT→etcp_router→conn_mgr→BGP→fw→stcp→networks→config→pools. **uasync не уничтожается** — вызывающий код должен сам вызвать `uasync_destroy()`. ### Reload (SIGHUP) ```c @@ -78,7 +77,6 @@ inst = utun_instance_reload(inst, ua, "utun.conf"); | `pkt_pool` | `struct memory_pool*` | Пул для `struct ETCP_DGRAM` | | `ack_pool` | `struct memory_pool*` | Пул для `struct ACK_PACKET` | | `control_srv` | `struct control_server*` | Сервер мониторинга (etcpmon backend) | -| `msg_t` | `struct msg_transport*` | IPC-транспорт сообщений | | `fw` | `struct firewall_ctx` | Контекст файрвола | | `nat` / `nat_tr` | `struct eim_nat_ctx` / `nat_transport_ctx` | EIM NAT + транспорт | | `tcp_proxy_client` | `struct tcp_proxy_client*` | TCP-прокси клиент (опционально) | diff --git a/tests/test_etcp_router.c b/tests/test_etcp_router.c index beea0f1a..abe48b83 100644 --- a/tests/test_etcp_router.c +++ b/tests/test_etcp_router.c @@ -243,7 +243,7 @@ static int send_one_pkt(uint32_t seq, int data_len) { memcpy(e->dgram, buf, 10 + data_len); e->len = 10 + data_len; - return etcp_route_send(cli, server_node_id, e, 0); + return etcp_route_send(cli, TOPO_GROUP_UTUN, server_node_id, e, 0); } // ======================== Server handler ======================== @@ -338,7 +338,7 @@ static int test_loopback(void) { uint8_t data[6] = { 0xF0, 0xAA, 0xBB, 0xCC, 0x00, 0x00 }; struct ll_entry* e = queue_entry_new(0); e->dgram = u_malloc(6); memcpy(e->dgram, data, 6); e->len = 6; - etcp_route_send(srv, srv->node_id, e, 0); + etcp_route_send(srv, TOPO_GROUP_UTUN, srv->node_id, e, 0); etcp_router_unbind(srv, 0xF0); if (loop_rcvd != 1 || !loop_ok) { printf("[FAIL] loopback: rcvd=%d ok=%d\n", loop_rcvd, loop_ok); @@ -540,7 +540,7 @@ static void monitor(void* arg) { sb->recv, sb->sent, sb->dropped, sb->lost, sb->queue_max); // Router stats - struct ETCP_ROUTER_CONN* rconn = etcp_router_conn_get(cli, server_node_id, TEST_SVC_ID); + struct ETCP_ROUTER_CONN* rconn = etcp_router_conn_get(cli, TOPO_GROUP_UTUN, server_node_id, TEST_SVC_ID); if (rconn) { printf(" router: tx_seq=%u rx_seq=%u tx_acked=%u c_pkts_sent=%u c_pkts_rcvd=%u c_dup_dropped=%u c_oob_dropped=%u\n", rconn->tx_seq, rconn->rx_seq, rconn->tx_acked, diff --git a/tests/test_etcp_router_reconnect.c b/tests/test_etcp_router_reconnect.c index 6adc8caa..5ce4636c 100644 --- a/tests/test_etcp_router_reconnect.c +++ b/tests/test_etcp_router_reconnect.c @@ -146,7 +146,7 @@ static int send_one_pkt(void) { gen_payload(g_seq, buf+7, len); struct ll_entry* e=queue_entry_new(0); if(!e){u_free(buf);return -1;} e->dgram=buf; e->len=7+len; - int ret = etcp_route_send(g_a, node_c, e, 0); + int ret = etcp_route_send(g_a, TOPO_GROUP_UTUN, node_c, e, 0); if (ret == 0) g_seq++; return ret; } diff --git a/tests/test_etcp_router_unit.c b/tests/test_etcp_router_unit.c index 4f9324a1..f5158f71 100644 --- a/tests/test_etcp_router_unit.c +++ b/tests/test_etcp_router_unit.c @@ -65,6 +65,7 @@ static void inject(etcp_recv_fn recv_cb, struct UTUN_INSTANCE* inst, struct SVC_ROUTE_HDR hdr; memset(&hdr, 0, sizeof(hdr)); hdr.cmd = ETCP_RT_ID_SVC_ROUTE; + hdr.group_id = TOPO_GROUP_UTUN; hdr.dst_node_id = inst->node_id; hdr.src_node_id = src; hdr.seq = seq; @@ -194,6 +195,7 @@ static void inject_signed(etcp_recv_fn recv_cb, struct UTUN_INSTANCE* inst, struct SVC_ROUTE_HDR* hdr = (struct SVC_ROUTE_HDR*)dgram; memset(hdr, 0, SVC_ROUTE_HDR_SIZE); hdr->cmd = ETCP_RT_ID_SVC_ROUTE; + hdr->group_id = TOPO_GROUP_UTUN; hdr->dst_node_id = inst->node_id; hdr->src_node_id = src; hdr->seq = seq; @@ -282,7 +284,7 @@ static int test_conn_get_create(void) { struct UASYNC* ua; struct UTUN_INSTANCE inst; etcp_recv_fn recv_cb; SETUP(); - struct ETCP_ROUTER_CONN* c = etcp_router_conn_get(&inst, TEST_REMOTE_NODE, TEST_SVC_ID); + struct ETCP_ROUTER_CONN* c = etcp_router_conn_get(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE, TEST_SVC_ID); if (!c) FAIL("conn_get returned NULL"); if (c->remote_node_id != TEST_REMOTE_NODE) FAIL("wrong remote_node_id"); if (c->svc_id != TEST_SVC_ID) FAIL("wrong svc_id"); @@ -305,14 +307,14 @@ static int test_conn_get_reuse(void) { struct UASYNC* ua; struct UTUN_INSTANCE inst; etcp_recv_fn recv_cb; SETUP(); - struct ETCP_ROUTER_CONN* c1 = etcp_router_conn_get(&inst, TEST_REMOTE_NODE, TEST_SVC_ID); + struct ETCP_ROUTER_CONN* c1 = etcp_router_conn_get(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE, TEST_SVC_ID); if (!c1) FAIL("c1 NULL"); - struct ETCP_ROUTER_CONN* c2 = etcp_router_conn_get(&inst, TEST_REMOTE_NODE, TEST_SVC_ID); + struct ETCP_ROUTER_CONN* c2 = etcp_router_conn_get(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE, TEST_SVC_ID); if (c1 != c2) FAIL("reuse: different pointers"); - struct ETCP_ROUTER_CONN* c3 = etcp_router_conn_get(&inst, TEST_REMOTE_NODE2, TEST_SVC_ID); + struct ETCP_ROUTER_CONN* c3 = etcp_router_conn_get(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE2, TEST_SVC_ID); if (c3 == c1) FAIL("different remote, same pointer"); - struct ETCP_ROUTER_CONN* c4 = etcp_router_conn_get(&inst, TEST_REMOTE_NODE, TEST_SVC_ID2); + struct ETCP_ROUTER_CONN* c4 = etcp_router_conn_get(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE, TEST_SVC_ID2); if (c4 == c1) FAIL("different svc, same pointer"); etcp_router_conn_close(c1); @@ -328,11 +330,11 @@ static int test_conn_close(void) { struct UASYNC* ua; struct UTUN_INSTANCE inst; etcp_recv_fn recv_cb; SETUP(); - struct ETCP_ROUTER_CONN* c1 = etcp_router_conn_get(&inst, TEST_REMOTE_NODE, TEST_SVC_ID); + struct ETCP_ROUTER_CONN* c1 = etcp_router_conn_get(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE, TEST_SVC_ID); if (!c1) FAIL("c1 NULL"); c1->tx_seq = 99; // mark etcp_router_conn_close(c1); - struct ETCP_ROUTER_CONN* c2 = etcp_router_conn_get(&inst, TEST_REMOTE_NODE, TEST_SVC_ID); + struct ETCP_ROUTER_CONN* c2 = etcp_router_conn_get(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE, TEST_SVC_ID); if (!c2) FAIL("c2 NULL"); if (c2->tx_seq != 0 || c2->rx_seq != 0) FAIL("not fresh after close+reopen"); @@ -348,7 +350,7 @@ static int test_in_order(void) { TEST("in-order delivery (seq 0,1,2)"); struct UASYNC* ua; struct UTUN_INSTANCE inst; etcp_recv_fn recv_cb; SETUP(); - struct ETCP_ROUTER_CONN* c = etcp_router_conn_get(&inst, TEST_REMOTE_NODE, TEST_SVC_ID); + struct ETCP_ROUTER_CONN* c = etcp_router_conn_get(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE, TEST_SVC_ID); if (!c) FAIL("conn_get failed"); rx_reset(0xAA); @@ -371,7 +373,7 @@ static int test_out_of_order(void) { TEST("out-of-order (0,2,3 then 1 → assembly to 3)"); struct UASYNC* ua; struct UTUN_INSTANCE inst; etcp_recv_fn recv_cb; SETUP(); - struct ETCP_ROUTER_CONN* c = etcp_router_conn_get(&inst, TEST_REMOTE_NODE, TEST_SVC_ID); + struct ETCP_ROUTER_CONN* c = etcp_router_conn_get(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE, TEST_SVC_ID); if (!c) FAIL("conn_get failed"); rx_reset(0xBB); @@ -398,7 +400,7 @@ static int test_duplicate_same(void) { TEST("duplicate — same seq injected twice"); struct UASYNC* ua; struct UTUN_INSTANCE inst; etcp_recv_fn recv_cb; SETUP(); - struct ETCP_ROUTER_CONN* c = etcp_router_conn_get(&inst, TEST_REMOTE_NODE, TEST_SVC_ID); + struct ETCP_ROUTER_CONN* c = etcp_router_conn_get(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE, TEST_SVC_ID); if (!c) FAIL("conn_get failed"); rx_reset(0xCC); @@ -420,7 +422,7 @@ static int test_duplicate_past(void) { TEST("duplicate — past seq (already delivered)"); struct UASYNC* ua; struct UTUN_INSTANCE inst; etcp_recv_fn recv_cb; SETUP(); - struct ETCP_ROUTER_CONN* c = etcp_router_conn_get(&inst, TEST_REMOTE_NODE, TEST_SVC_ID); + struct ETCP_ROUTER_CONN* c = etcp_router_conn_get(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE, TEST_SVC_ID); if (!c) FAIL("conn_get failed"); rx_reset(0xDD); @@ -443,7 +445,7 @@ static int test_out_of_bounds(void) { TEST("out of bounds — seq too far ahead"); struct UASYNC* ua; struct UTUN_INSTANCE inst; etcp_recv_fn recv_cb; SETUP(); - struct ETCP_ROUTER_CONN* c = etcp_router_conn_get(&inst, TEST_REMOTE_NODE, TEST_SVC_ID); + struct ETCP_ROUTER_CONN* c = etcp_router_conn_get(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE, TEST_SVC_ID); if (!c) FAIL("conn_get failed"); rx_reset(0xEE); @@ -466,7 +468,7 @@ static int test_circular_wrap(void) { TEST("32-bit circular wrap-around"); struct UASYNC* ua; struct UTUN_INSTANCE inst; etcp_recv_fn recv_cb; SETUP(); - struct ETCP_ROUTER_CONN* c = etcp_router_conn_get(&inst, TEST_REMOTE_NODE, TEST_SVC_ID); + struct ETCP_ROUTER_CONN* c = etcp_router_conn_get(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE, TEST_SVC_ID); if (!c) FAIL("conn_get failed"); c->rx_seq = 0xFFFFFFFE; @@ -491,7 +493,7 @@ static int test_data_integrity(void) { TEST("data integrity — payload preserved"); struct UASYNC* ua; struct UTUN_INSTANCE inst; etcp_recv_fn recv_cb; SETUP(); - struct ETCP_ROUTER_CONN* c = etcp_router_conn_get(&inst, TEST_REMOTE_NODE, TEST_SVC_ID); + struct ETCP_ROUTER_CONN* c = etcp_router_conn_get(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE, TEST_SVC_ID); if (!c) FAIL("conn_get failed"); rx_reset(0x77); @@ -511,7 +513,7 @@ static int test_ack_receive(void) { TEST("ACK receive — tx_acked updated"); struct UASYNC* ua; struct UTUN_INSTANCE inst; etcp_recv_fn recv_cb; SETUP(); - struct ETCP_ROUTER_CONN* c = etcp_router_conn_get(&inst, TEST_REMOTE_NODE, TEST_SVC_ID); + struct ETCP_ROUTER_CONN* c = etcp_router_conn_get(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE, TEST_SVC_ID); if (!c) FAIL("conn_get failed"); rx_reset(0x00); @@ -532,7 +534,7 @@ static int test_ack_timer(void) { TEST("ACK timer scheduled on data receive"); struct UASYNC* ua; struct UTUN_INSTANCE inst; etcp_recv_fn recv_cb; SETUP(); - struct ETCP_ROUTER_CONN* c = etcp_router_conn_get(&inst, TEST_REMOTE_NODE, TEST_SVC_ID); + struct ETCP_ROUTER_CONN* c = etcp_router_conn_get(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE, TEST_SVC_ID); if (!c) FAIL("conn_get failed"); if (c->ack_timer != NULL) FAIL("ack_timer set before any data"); @@ -554,7 +556,7 @@ static int test_send_q(void) { TEST("send_q — inflight full queues, not lost"); struct UASYNC* ua; struct UTUN_INSTANCE inst; etcp_recv_fn recv_cb; SETUP(); - struct ETCP_ROUTER_CONN* c = etcp_router_conn_get(&inst, TEST_REMOTE_NODE, TEST_SVC_ID); + struct ETCP_ROUTER_CONN* c = etcp_router_conn_get(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE, TEST_SVC_ID); if (!c) FAIL("conn_get failed"); // Simulate full inflight: set tx_acked far behind tx_seq @@ -594,7 +596,7 @@ static int test_loopback(void) { memcpy(e->dgram, buf, 4); e->len = 4; - if (etcp_route_send(&inst, inst.node_id, e, 0) != 0) FAIL("loopback send failed"); + if (etcp_route_send(&inst, TOPO_GROUP_UTUN, inst.node_id, e, 0) != 0) FAIL("loopback send failed"); if (rx.delivered != 1) FAIL("loopback not delivered"); if (rx.errors != 0) FAIL("loopback data mismatch"); @@ -607,7 +609,7 @@ static int test_timestamp(void) { TEST("last_dgram_ts updated on data"); struct UASYNC* ua; struct UTUN_INSTANCE inst; etcp_recv_fn recv_cb; SETUP(); - struct ETCP_ROUTER_CONN* c = etcp_router_conn_get(&inst, TEST_REMOTE_NODE, TEST_SVC_ID); + struct ETCP_ROUTER_CONN* c = etcp_router_conn_get(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE, TEST_SVC_ID); if (!c) FAIL("conn_get failed"); uint16_t before = c->last_dgram_ts; @@ -630,7 +632,7 @@ static int test_conn_send_no_bgp(void) { TEST("conn_send — no BGP returns error"); struct UASYNC* ua; struct UTUN_INSTANCE inst; etcp_recv_fn recv_cb; SETUP(); - struct ETCP_ROUTER_CONN* c = etcp_router_conn_get(&inst, TEST_REMOTE_NODE, TEST_SVC_ID); + struct ETCP_ROUTER_CONN* c = etcp_router_conn_get(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE, TEST_SVC_ID); if (!c) FAIL("conn_get failed"); uint8_t data[4] = { 1, 2, 3, 4 }; @@ -669,7 +671,7 @@ static int test_rst_flag(void) { inject(recv_cb, &inst, TEST_REMOTE_NODE, TEST_SVC_ID, n, data + 1, 2, 0, ROUTER_FLAG_RST); if (g_notify_count != 1) FAIL("RST should notify service"); - struct ETCP_ROUTER_CONN* c = etcp_router_conn_get(&inst, TEST_REMOTE_NODE, TEST_SVC_ID); + struct ETCP_ROUTER_CONN* c = etcp_router_conn_get(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE, TEST_SVC_ID); if (!c) FAIL("new rconn should exist"); etcp_router_conn_close(c); @@ -733,7 +735,7 @@ static int test_sess_id_wrap(void) { uint8_t f3 = (3 << ROUTER_SESS_ID_SHIFT); rx_reset(0xD1); - struct ETCP_ROUTER_CONN* c = etcp_router_conn_get(&inst, TEST_REMOTE_NODE, TEST_SVC_ID); + struct ETCP_ROUTER_CONN* c = etcp_router_conn_get(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE, TEST_SVC_ID); if (!c) FAIL("rconn not found"); c->peer_sess_id = 3; @@ -769,7 +771,7 @@ static int test_server_reinit(void) { recv_cb = inst.api_bindings.callbacks[ETCP_RT_ID_SVC_ROUTE]; if (!recv_cb) FAIL("recv_cb not bound"); - struct ETCP_ROUTER_CONN* c = etcp_router_conn_get(&inst, TEST_REMOTE_NODE, TEST_SVC_ID); + struct ETCP_ROUTER_CONN* c = etcp_router_conn_get(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE, TEST_SVC_ID); if (!c) FAIL("rconn after reinit"); if (c->start_sent != 0) FAIL("start_sent != 0 after reinit"); if (c->sess_id != 0) FAIL("sess_id != 0 after reinit"); @@ -868,6 +870,7 @@ static int test_sign_too_short(void) { struct SVC_ROUTE_HDR hdr; memset(&hdr, 0, sizeof(hdr)); hdr.cmd = ETCP_RT_ID_SVC_ROUTE; + hdr.group_id = TOPO_GROUP_UTUN; hdr.dst_node_id = inst.node_id; hdr.src_node_id = SIGNER_NODE; hdr.seq = 0; diff --git a/tests/test_nat_transport.c b/tests/test_nat_transport.c index dc3d3b4c..a38c1b58 100644 --- a/tests/test_nat_transport.c +++ b/tests/test_nat_transport.c @@ -307,7 +307,7 @@ static int test_provider_egress(void) { entry->dgram = dgram; entry->len = total; - int ret = etcp_route_send(inst_client, g_provider_node_id, entry, 0); + int ret = etcp_route_send(inst_client, TOPO_GROUP_UTUN, g_provider_node_id, entry, 0); if (ret != 0) { DEBUG_ERROR(DEBUG_CATEGORY_NAT, "etcp_route_send failed"); queue_dgram_free(entry); @@ -476,7 +476,7 @@ static int test_full_roundtrip(void) { struct ll_entry* entry = queue_entry_new(0); entry->dgram = dgram; entry->len = total; - int ret = etcp_route_send(inst_client, g_provider_node_id, entry, 0); + int ret = etcp_route_send(inst_client, TOPO_GROUP_UTUN, g_provider_node_id, entry, 0); if (ret != 0) { DEBUG_ERROR(DEBUG_CATEGORY_NAT, "etcp_route_send failed"); queue_dgram_free(entry); queue_entry_free(entry); return 0; } // Poll for provider to process egress diff --git a/tools/chatgui/chat_tz.txt b/tools/chatgui/chat_tz.txt index 0f13037f..77dd7459 100644 --- a/tools/chatgui/chat_tz.txt +++ b/tools/chatgui/chat_tz.txt @@ -31,7 +31,7 @@ CREATE TABLE my_nodes ( ); --- 3. nodes — известные удалённые узлы (получаем через msg_transport от utun) +-- 3. nodes — известные удалённые узлы (получаем через utun) CREATE TABLE nodes ( node_id INTEGER PRIMARY KEY, name TEXT, diff --git a/tools/chatgui/libutun/CMakeLists.txt b/tools/chatgui/libutun/CMakeLists.txt index be040aa3..c356eb94 100644 --- a/tools/chatgui/libutun/CMakeLists.txt +++ b/tools/chatgui/libutun/CMakeLists.txt @@ -89,7 +89,6 @@ set(UTUN_COMMON_SOURCES ${SRC_DIR}/transport_layer/etcp_api.c ${SRC_DIR}/transport_layer/etcp_connect.c ${SRC_DIR}/control_server.c - ${SRC_DIR}/msg_transport.c ${SRC_DIR}/firewall.c ${SRC_DIR}/eim_nat.c ${SRC_DIR}/nat_transport.c diff --git a/tools/chatgui/transport/node_config.cpp b/tools/chatgui/transport/node_config.cpp index 7ac31db1..43f9ec81 100644 --- a/tools/chatgui/transport/node_config.cpp +++ b/tools/chatgui/transport/node_config.cpp @@ -66,10 +66,6 @@ static const QSet TCP_PROXY_SERVER_KEYS = { "enabled", "tcp_recv_buf" }; -static const QSet MSG_TRANSPORT_KEYS = { - "port" -}; - static const QSet NETWORK_KEYS = { "id", "pubkey", "signing_key" }; @@ -97,7 +93,6 @@ static bool isSectionValid(const QString& section) { if (section == "routing" || section == "route") return true; if (section == "tcp_proxy_client") return true; if (section == "tcp_proxy_server") return true; - if (section == "msg_transport") return true; if (section == "ntp") return true; return false; } @@ -115,7 +110,6 @@ static const QSet* keysForSection(const QString& section) { if (section == "routing" || section == "route") return &ROUTING_KEYS; if (section == "tcp_proxy_client") return &TCP_PROXY_CLIENT_KEYS; if (section == "tcp_proxy_server") return &TCP_PROXY_SERVER_KEYS; - if (section == "msg_transport") return &MSG_TRANSPORT_KEYS; if (section == "ntp") return &NTP_KEYS; return nullptr; // [debug] — free-form, no key validation } diff --git a/tools/chatgui/transport/utun_node.cpp b/tools/chatgui/transport/utun_node.cpp index ba0965f1..dbbeb595 100644 --- a/tools/chatgui/transport/utun_node.cpp +++ b/tools/chatgui/transport/utun_node.cpp @@ -27,6 +27,7 @@ extern "C" { #include "db_sync.h" #include "gui_bridge.h" #include "topo_node_sqlite.h" +#include "topo_node.h" } #define ETCP_RT_ID_CHAT 0x11 @@ -88,7 +89,7 @@ void UtunNode::send(uint64_t dstNodeId, const QByteArray& data) { struct ll_entry* entry = queue_entry_new(data.size()); if (!entry) return; memcpy(entry->data, data.constData(), data.size()); - etcp_route_send(m_instance, dstNodeId, entry, 0); + etcp_route_send(m_instance, TOPO_GROUP_UTUN, dstNodeId, entry, 0); } QString UtunNode::nodeIdHex() const {