Добавлен group_id в etcp_router и topo_group, удалён msg_transport

- 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 тестов
This commit is contained in:
Evgeny committed 2026-07-22 15:51:03 +03:00
1 parent 5265783164
commit 852ce401e7
37 files changed
+375 -1125

No files matched your search

-2
View File
@@ -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 \
-19
View File
@@ -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;
-2
View File
@@ -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)
-2
View File
@@ -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]` | игнорируется | (зарезервировано) |
-638
View File
@@ -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 <stdlib.h>
#include <string.h>
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#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);
}
-126
View File
@@ -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 <stdint.h>
#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 */
-69
View File
@@ -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-топологии. |
+3 -2
View File
@@ -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);
+4 -3
View File
@@ -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);
}
// ====================================================================
+16 -15
View File
@@ -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);
}
+15 -14
View File
@@ -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;
+16 -15
View File
@@ -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;
}
+3 -2
View File
@@ -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);
}
// ====================================================================
+6 -6
View File
@@ -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);
+75 -57
View File
@@ -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;
}
+27 -26
View File
@@ -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);
+1 -1
View File
@@ -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);
+75 -33
View File
@@ -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;
+12 -1
View File
@@ -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;
+65 -13
View File
@@ -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;
+12
View File
@@ -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);
+1 -1
View File
@@ -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)
-1
View File
@@ -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)
+1 -23
View File
@@ -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;
+1 -4
View File
@@ -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;
+2 -4
View File
@@ -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-прокси клиент (опционально) |