refactor: move transport (etcp/stcp/normalizer) to transport_layer/, routing (bgp/pings/topo*) to routing_layer/

This commit is contained in:
Evgeny committed 2026-07-21 20:25:41 +03:00
1 parent 3dda701c67
commit fcf3fb7f51
146 files changed
+582 -333

No files matched your search

+59 -56
View File
@@ -7,48 +7,48 @@ utun_CORE_SOURCES = \
utun_instance.c \
config_parser.c \
config_updater.c \
route_lib.c \
route6_lib.c \
topo_group.c \
route_ping.c \
nat_detection.c \
topo_node.c \
topo_node_sqlite.c \
route_connectivity.c \
conn_mgr.c \
routing_layer/route_lib.c \
routing_layer/route6_lib.c \
routing_layer/topo_group.c \
routing_layer/route_ping.c \
routing_layer/nat_detection.c \
routing_layer/topo_node.c \
routing_layer/topo_node_sqlite.c \
routing_layer/route_connectivity.c \
routing_layer/conn_mgr.c \
db_sync.c \
routing.c \
routing_layer/routing.c \
tun_if.c \
tun_route.c \
tun_linux.c \
tun_freebsd.c \
tun_windows.c \
etcp.c \
etcp_connections.c \
etcp_bbr.c \
etcp_loadbalancer.c \
etcp_debug.c \
etcp_dump.c \
secure_channel.c \
crc32.c \
stcp_link.c \
stcp.c \
stcp_server.c \
stcp_client.c \
pkt_normalizer.c \
packet_dump.c \
etcp_api.c \
etcp_connect.c \
transport_layer/etcp.c \
transport_layer/etcp_connections.c \
transport_layer/etcp_bbr.c \
transport_layer/etcp_loadbalancer.c \
transport_layer/etcp_debug.c \
transport_layer/etcp_dump.c \
transport_layer/secure_channel.c \
transport_layer/crc32.c \
transport_layer/stcp_link.c \
transport_layer/stcp.c \
transport_layer/stcp_server.c \
transport_layer/stcp_client.c \
transport_layer/pkt_normalizer.c \
transport_layer/packet_dump.c \
transport_layer/etcp_api.c \
transport_layer/etcp_connect.c \
control_server.c \
msg_transport.c \
firewall.c \
eim_nat.c \
nat_transport.c \
dummynet.c \
transport_layer/dummynet.c \
ntp_time.c \
ntp_node_time.c \
proxy/tcp_proxy_client.c \
etcp_router.c \
routing_layer/etcp_router.c \
proxy/tcp_proxy_server.c \
proxy/udp_proxy.c \
proxy/socks_proxy.c \
@@ -63,48 +63,48 @@ libutun_a_SOURCES = \
utun_instance.c \
config_parser.c \
config_updater.c \
route_lib.c \
route6_lib.c \
topo_group.c \
route_ping.c \
nat_detection.c \
topo_node.c \
topo_node_sqlite.c \
route_connectivity.c \
conn_mgr.c \
routing_layer/route_lib.c \
routing_layer/route6_lib.c \
routing_layer/topo_group.c \
routing_layer/route_ping.c \
routing_layer/nat_detection.c \
routing_layer/topo_node.c \
routing_layer/topo_node_sqlite.c \
routing_layer/route_connectivity.c \
routing_layer/conn_mgr.c \
db_sync.c \
routing.c \
routing_layer/routing.c \
tun_if.c \
tun_route.c \
tun_linux.c \
tun_freebsd.c \
tun_windows.c \
etcp.c \
etcp_connections.c \
etcp_bbr.c \
etcp_loadbalancer.c \
etcp_debug.c \
etcp_dump.c \
secure_channel.c \
crc32.c \
stcp_link.c \
stcp.c \
stcp_server.c \
stcp_client.c \
pkt_normalizer.c \
packet_dump.c \
etcp_api.c \
etcp_connect.c \
transport_layer/etcp.c \
transport_layer/etcp_connections.c \
transport_layer/etcp_bbr.c \
transport_layer/etcp_loadbalancer.c \
transport_layer/etcp_debug.c \
transport_layer/etcp_dump.c \
transport_layer/secure_channel.c \
transport_layer/crc32.c \
transport_layer/stcp_link.c \
transport_layer/stcp.c \
transport_layer/stcp_server.c \
transport_layer/stcp_client.c \
transport_layer/pkt_normalizer.c \
transport_layer/packet_dump.c \
transport_layer/etcp_api.c \
transport_layer/etcp_connect.c \
control_server.c \
msg_transport.c \
firewall.c \
eim_nat.c \
nat_transport.c \
dummynet.c \
transport_layer/dummynet.c \
ntp_time.c \
ntp_node_time.c \
proxy/tcp_proxy_client.c \
etcp_router.c \
routing_layer/etcp_router.c \
proxy/tcp_proxy_server.c \
proxy/udp_proxy.c \
proxy/socks_proxy.c \
@@ -123,6 +123,9 @@ utun_SOURCES = utun.c
# Include paths
utun_CFLAGS = \
-I$(top_srcdir)/lib \
-I$(top_srcdir)/src \
-I$(top_srcdir)/src/transport_layer \
-I$(top_srcdir)/src/routing_layer \
-I$(top_srcdir)/src/uip \
-g \
-DUSE_SQLITE \
File renamed without changes.
@@ -416,7 +416,7 @@ static void cm_start_local_scan(struct CONN_MGR_ENTRY* entry) {
struct sockaddr_storage sa; memset(&sa, 0, sizeof(sa)); memcpy(&sa, &sin, sizeof(sin));
struct cm_ping_ctx* ctx = u_calloc(1, sizeof(struct cm_ping_ctx)); if (!ctx) continue;
ctx->entry = entry; ctx->addr = sa; ctx->sock = s; ctx->phase = 0; ctx->attempt = 0;
etcp_send_ping_to_socket(entry->mgr->instance, s, target->node->public_key, &sa, CONN_MGR_LOCAL_SCAN_TIMEOUT_MS, cm_ping_cb, ctx, NULL, 0);
etcp_send_ping_to_socket(entry->mgr->instance, s, target->node->public_key, &sa, CONN_MGR_LOCAL_SCAN_TIMEOUT_MS, cm_ping_cb, ctx, NULL, 0, 0);
return;
}
s = s->next;
@@ -519,7 +519,7 @@ static void cm_ping_cb(int success, uint16_t rtt, void* arg, uint64_t nonce,
if (ctx->attempt < CONN_MGR_LOCAL_SCAN_ATTEMPTS && ctx->phase == 0) {
etcp_send_ping_to_socket(entry->mgr->instance, ctx->sock,
topo_node_find_by_id(topo_groups_get_default(entry->mgr->instance->topo_groups), entry->node_id)->node->public_key,
&ctx->addr, CONN_MGR_LOCAL_SCAN_TIMEOUT_MS, cm_ping_cb, ctx, NULL, 0);
&ctx->addr, CONN_MGR_LOCAL_SCAN_TIMEOUT_MS, cm_ping_cb, ctx, NULL, 0, 0);
return;
}
DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "conn_mgr: %s failed for 0x%016llx after %d attempts",
@@ -943,7 +943,7 @@ static void cm_bg_ping_timer_cb(void* arg) {
while (s) { if (s->local_addr.ss_family == AF_INET) break; s = s->next; }
if (!s) break;
etcp_send_ping_to_socket(mgr->instance, s, nq->node->public_key, &sa,
CONN_PROBE_TIMEOUT_MS, cm_bg_ping_noop_cb, NULL, NULL, 0);
CONN_PROBE_TIMEOUT_MS, cm_bg_ping_noop_cb, NULL, NULL, 0, 0);
break;
}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -16,6 +16,7 @@
#include "topo_node.h"
#include "topo_group.h"
#include "route_connectivity.h"
#include "topo_node_sqlite.h"
#define CONN_MAX_SOCKET_CANDIDATES 8
@@ -201,7 +202,8 @@ static void conn_probe_start_series(struct conn_probe_ctx* ctx) {
int ret = etcp_send_ping_to_socket(ctx->instance, sock, ctx->peer_pubkey,
&ctx->target_addr, ctx->timeout_ms,
conn_probe_single_cb, ctx, NULL, 0);
conn_probe_single_cb, ctx, NULL, 0, 0);
if (ret != 0) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "probe: cannot start ping from socket %s", sock->name);
ctx->count_sent = 3; // simulate full failure
@@ -231,7 +233,7 @@ static void conn_probe_single_cb(int success, uint16_t rtt, void* arg,
struct ETCP_SOCKET* sock = ctx->candidate_sockets[ctx->candidate_index];
int ret = etcp_send_ping_to_socket(ctx->instance, sock, ctx->peer_pubkey,
&ctx->target_addr, ctx->timeout_ms,
conn_probe_single_cb, ctx, NULL, 0);
conn_probe_single_cb, ctx, NULL, 0, 0);
if (ret != 0) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "probe: cannot continue ping from socket %s", sock->name);
ctx->count_sent = ctx->count_total; // force finish series
@@ -279,6 +281,8 @@ static void conn_probe_finish(struct conn_probe_ctx* ctx, int ok) {
DEBUG_INFO(DEBUG_CATEGORY_BGP, "connectivity probe DONE for node %016llx: intf=%d nat=%d real=%d",
(unsigned long long)ctx->nq->node->node_id,
c->interface_status, c->nat_status, c->real_status);
if (ctx->instance && ctx->instance->topo_sqlite_db)
topo_node_sqlite_nodeinfo_updated(ctx->instance->topo_sqlite_db, ctx->nq->node->node_id);
}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -309,7 +309,7 @@ static void route_ping_single_cb(int success,
ctx->timeout_ms,
route_ping_single_cb,
ctx,
NULL, 0);
NULL, 0, 0);
if (ret != 0) {
/* Не смогли отправить следующий — завершаем серию досрочно */
@@ -391,7 +391,7 @@ void route_ping_handle_req(struct NAT_DETECTION* nd, struct TOPO_GROUP* group,
ctx->timeout_ms,
route_ping_single_cb,
ctx,
NULL, 0);
NULL, 0, 0);
if (ret != 0) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "ping req: cannot start first ping");
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -586,6 +586,7 @@ int topo_group_process_nodeinfo(struct TOPO_GROUP* group, struct ETCP_CONN* from
topo_node_sqlite_member_put(sdb, group->channel_id, node_id, NULL, 0, NULL, 0, NULL, NULL, NULL, NULL);
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "SQLite member_put: ch=%s node=%016llx", group->channel_id, (unsigned long long)node_id);
}
topo_node_sqlite_nodeinfo_updated(sdb, node_id);
}
}
if (group->instance->control_srv) control_server_notify_node_change(group->instance->control_srv, nodeinfo1);
File renamed without changes.
File renamed without changes.
@@ -13,6 +13,8 @@
#include "topo_group.h"
#include "route_lib.h"
#include "etcp_debug.h"
#include "topo_node_sqlite.h"
#include "../lib/u_async.h"
void topo_node_ref(struct TOPO_NODE* ni) {
if (!ni) return;
@@ -262,6 +264,55 @@ struct TOPO_NODEQ* topo_node_find_by_id(struct TOPO_GROUP* group, uint64_t node_
return e ? (struct TOPO_NODEQ*)e : NULL;
}
int topo_node_ping_request_cbk(struct TOPO_GROUPS* groups, uint64_t node_id) {
if (!groups || !groups->group_list) return 0;
uint64_t now = get_time_tb();
struct ll_entry* ge = groups->group_list->head;
while (ge) {
struct TOPO_GROUP* g = (struct TOPO_GROUP*)ge;
struct TOPO_NODEQ* nq = topo_node_find_by_id(g, node_id);
if (nq) {
struct TOPO_CONNECTIVITY* c = &nq->connectivity;
if (c->last_ping_time == 0 || (now - c->last_ping_time) > PING_TTL_TB) {
DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "ping_request_cbk: node=%016llx last_ping=%llu now=%llu stale=1",
(unsigned long long)node_id, (unsigned long long)c->last_ping_time, (unsigned long long)now);
return 1;
}
DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "ping_request_cbk: node=%016llx last_ping=%llu now=%llu stale=0",
(unsigned long long)node_id, (unsigned long long)c->last_ping_time, (unsigned long long)now);
}
ge = ge->next;
}
return 0;
}
void topo_node_ping_update_rtt(struct TOPO_GROUPS* groups, uint64_t node_id, uint16_t rtt) {
if (!groups || !groups->group_list) {
DEBUG_WARN(DEBUG_CATEGORY_BGP, "ping_update_rtt: no groups, node=%016llx rtt=%u", (unsigned long long)node_id, (unsigned)rtt);
return;
}
uint64_t now = get_time_tb();
struct ll_entry* ge = groups->group_list->head;
while (ge) {
struct TOPO_GROUP* g = (struct TOPO_GROUP*)ge;
struct TOPO_NODEQ* nq = topo_node_find_by_id(g, node_id);
if (nq) {
nq->connectivity.last_ping_time = now;
if (nq->connectivity.interface_min_rtt == 0 || rtt < nq->connectivity.interface_min_rtt)
nq->connectivity.interface_min_rtt = rtt;
if (nq->connectivity.nat_min_rtt == 0 || rtt < nq->connectivity.nat_min_rtt)
nq->connectivity.nat_min_rtt = rtt;
if (nq->connectivity.real_min_rtt == 0 || rtt < nq->connectivity.real_min_rtt)
nq->connectivity.real_min_rtt = rtt;
DEBUG_INFO(DEBUG_CATEGORY_BGP, "ping_update_rtt: node=%016llx rtt=%u (%llu) group=%016llx",
(unsigned long long)node_id, (unsigned)rtt, (unsigned long long)now, (unsigned long long)g->group_id);
if (groups->instance && groups->instance->topo_sqlite_db)
topo_node_sqlite_nodeinfo_updated(groups->instance->topo_sqlite_db, node_id);
}
ge = ge->next;
}
}
// ===== dump / format =====
static int is_node_connectivity_active(struct TOPO_CONNECTIVITY* c) {
@@ -270,7 +321,8 @@ static int is_node_connectivity_active(struct TOPO_CONNECTIVITY* c) {
|| c->nat_status != PROBE_RESULT_UNKNOWN
|| c->real_status != PROBE_RESULT_UNKNOWN
|| c->probe_start_time != 0
|| c->ping_req_time != 0;
|| c->ping_req_time != 0
|| c->last_ping_time != 0;
}
static const char* probe_status_str(uint8_t s) {
@@ -360,11 +412,11 @@ void topo_node_dump_all(struct TOPO_GROUP* group) {
struct TOPO_CONNECTIVITY* c = &nq->connectivity;
if (is_node_connectivity_active(c)) {
DEBUG_INFO(DEBUG_CATEGORY_BGP, " connectivity: probe=%s iface=%s(%u) nat=%s(%u) real=%s(%u) pend=%u iface_rtt=%u nat_rtt=%u real_rtt=%u start_tb=%llu ping_req_tb=%llu",
DEBUG_INFO(DEBUG_CATEGORY_BGP, " connectivity: probe=%s iface=%s(%u) nat=%s(%u) real=%s(%u) pend=%u iface_rtt=%u nat_rtt=%u real_rtt=%u start_tb=%llu ping_req_tb=%llu last_ping_tb=%llu",
probe_status_str(c->probe_status), probe_result_str(c->interface_status), c->interface_min_rtt,
probe_result_str(c->nat_status), c->nat_min_rtt, probe_result_str(c->real_status), c->real_min_rtt,
c->pending_count, c->interface_min_rtt, c->nat_min_rtt, c->real_min_rtt,
(unsigned long long)c->probe_start_time, (unsigned long long)c->ping_req_time);
(unsigned long long)c->probe_start_time, (unsigned long long)c->ping_req_time, (unsigned long long)c->last_ping_time);
}
if (nq->conn_mgr_type != CONN_TYPE_NONE) {
char interm_buf[200] = ""; int ipos = 0;
@@ -448,11 +500,11 @@ int topo_node_format_all(struct TOPO_GROUP* group, char* buf, size_t buf_size) {
struct TOPO_CONNECTIVITY* c = &nq->connectivity;
if (is_node_connectivity_active(c)) {
FMT_ADD(" connectivity: probe=%s iface=%s(%u) nat=%s(%u) real=%s(%u) pend=%u iface_rtt=%u nat_rtt=%u real_rtt=%u start_tb=%llu ping_req_tb=%llu\n",
FMT_ADD(" connectivity: probe=%s iface=%s(%u) nat=%s(%u) real=%s(%u) pend=%u iface_rtt=%u nat_rtt=%u real_rtt=%u start_tb=%llu ping_req_tb=%llu last_ping_tb=%llu\n",
probe_status_str(c->probe_status), probe_result_str(c->interface_status), c->interface_min_rtt,
probe_result_str(c->nat_status), c->nat_min_rtt, probe_result_str(c->real_status), c->real_min_rtt,
c->pending_count, c->interface_min_rtt, c->nat_min_rtt, c->real_min_rtt,
(unsigned long long)c->probe_start_time, (unsigned long long)c->ping_req_time);
(unsigned long long)c->probe_start_time, (unsigned long long)c->ping_req_time, (unsigned long long)c->last_ping_time);
}
if (nq->conn_mgr_type != CONN_TYPE_NONE) {
FMT_ADD(" conn_mgr: type=%s intermediates=[", conn_mgr_type_str(nq->conn_mgr_type));
@@ -31,6 +31,7 @@ extern "C" {
#include "secure_channel.h"
struct TOPO_GROUP;
struct TOPO_GROUPS;
struct ETCP_SOCKET;
struct UTUN_INSTANCE;
@@ -100,9 +101,12 @@ struct TOPO_CONNECTIVITY {
uint64_t nat_probe_time;
uint64_t real_probe_time;
uint64_t ping_req_time;
uint64_t last_ping_time; // время последнего успешного пинга (0.1ms timebase)
void* probe_list;
};
#define PING_TTL_TB (86400ULL * 10000ULL) // 1 день в 0.1ms units
// =======================================================================
// Протокольные структуры (wire-format, packed, без next)
// =======================================================================
@@ -270,6 +274,9 @@ int topo_group_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct TOPO_GR
void topo_node_dump_all(struct TOPO_GROUP* group);
int topo_node_format_all(struct TOPO_GROUP* group, char* buf, size_t buf_size);
int topo_node_ping_request_cbk(struct TOPO_GROUPS* groups, uint64_t node_id);
void topo_node_ping_update_rtt(struct TOPO_GROUPS* groups, uint64_t node_id, uint16_t rtt);
#ifdef __cplusplus
}
#endif
File renamed without changes.
@@ -78,6 +78,22 @@ int topo_node_sqlite_init(sqlite3* db) {
return -1;
}
{
sqlite3_stmt* s = NULL;
if (sqlite3_prepare_v2(db,
"SELECT name FROM sqlite_master WHERE type='table' AND name LIKE 'peers\\_%' ESCAPE '\\'",
-1, &s, NULL) == SQLITE_OK) {
char isql[256];
while (sqlite3_step(s) == SQLITE_ROW) {
const char* tbl = (const char*)sqlite3_column_text(s, 0);
snprintf(isql, sizeof(isql),
"CREATE INDEX IF NOT EXISTS \"idx_%s_type_rtt\" ON \"%s\" (node_type, node_RTT)", tbl, tbl);
sqlite3_exec(db, isql, NULL, NULL, NULL);
}
sqlite3_finalize(s);
}
}
DEBUG_INFO(DEBUG_CATEGORY_BGP, "topo_node_sqlite tables initialized");
return 0;
}
@@ -235,7 +251,8 @@ int topo_node_sqlite_channel_put(sqlite3* db, const char* channel_id,
char sql[512];
snprintf(sql, sizeof(sql),
"CREATE TABLE IF NOT EXISTS \"%s\" (" // таблица мемберов канала
" node_id INTEGER NOT NULL," // ид меббера группы
" id INTEGER PRIMARY KEY AUTOINCREMENT,"
" node_id INTEGER NOT NULL UNIQUE," // ид мембера группы
" x25519_pubkey BLOB NOT NULL," // ключ мембера для шифрования
" ed25519_pubkey BLOB NOT NULL," // ключ мембера для подписи
" join_sig BLOB NOT NULL," // подпись мембера неизменяемая (при присоединении) сh_x25519_pubkey(32) || ch_ed25519_pubkey(32) || node_id(8 LE) || node_x25519_pubkey(32) || join_ts(8 LE)
@@ -246,11 +263,15 @@ int topo_node_sqlite_channel_put(sqlite3* db, const char* channel_id,
" creator_sig BLOB," // валидация мембера админом канала
" adm_tags TEXT," // тэги которые может менять админ (json_flat style)
" adm_tags_sig BLOB," // подпись тэгов adm_tags (может быть подписана ключом суперадмина или админов - проверяем перебором)
" node_type INTEGER NOT NULL," // ENUM(0-'PRIV',1-'NAT',2-'EIM-NAT',3-'PUBLIC',4-SUPERNODE) тип ноды - private (только нода подключается), nat (односторонние подключения), eim-nat (доступны подключения но надо запрашивать ip), public - на прямых ip (но может быть недоступна в чебурнетах), supernode - на прямых ip, рекомендуемая для подключения
" PRIMARY KEY (node_id))", peers_tbl);
" node_type INTEGER NOT NULL DEFAULT 0," // ENUM(0-'PRIV',1-'NAT',2-'EIM-NAT',3-'PUBLIC',4-SUPERNODE) тип ноды - private (только нода подключается), nat (односторонние подключения), eim-nat (доступны подключения но надо запрашивать ip), public - на прямых ip (но может быть недоступна в чебурнетах), supernode - на прямых ip, рекомендуемая для подключения
" node_RTT INTEGER" // задержка в ms
")", peers_tbl);
char* err = NULL;
sqlite3_exec(db, sql, NULL, NULL, &err);
if (err) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_node_sqlite_channel_put peers: %s", err); sqlite3_free(err); }
snprintf(sql, sizeof(sql),
"CREATE INDEX IF NOT EXISTS \"idx_%s_type_rtt\" ON \"%s\" (node_type, node_RTT)", peers_tbl, peers_tbl);
sqlite3_exec(db, sql, NULL, NULL, NULL);
sqlite3_stmt* stmt = NULL;
if (sqlite3_prepare_v2(db,
@@ -502,3 +523,64 @@ int topo_node_sqlite_get_ed25519_pubkey(sqlite3* db, uint64_t node_id, uint8_t p
sqlite3_finalize(stmt);
return rc;
}
int topo_node_sqlite_nodeinfo_updated(sqlite3* db, uint64_t node_id) {
if (!db) return -1;
int best_at = -1;
{
sqlite3_stmt* s = NULL;
if (sqlite3_prepare_v2(db,
"SELECT addr_type FROM node_addresses WHERE node_id=?", -1, &s, NULL) == SQLITE_OK) {
sqlite3_bind_int64(s, 1, (sqlite3_int64)node_id);
while (sqlite3_step(s) == SQLITE_ROW) {
int at = sqlite3_column_int(s, 0);
if (at == ADDR_TYPE_DIRECT) { best_at = ADDR_TYPE_DIRECT; break; }
if (best_at < 0 || at < best_at) best_at = at;
}
sqlite3_finalize(s);
}
}
static const int at2type[] = { [ADDR_TYPE_NETIF]=1, [ADDR_TYPE_DIRECT]=1, [ADDR_TYPE_NAT_EIM]=2, [ADDR_TYPE_NAT_STRICT]=1 };
int base_type = (best_at < 0) ? 0 : at2type[best_at];
sqlite3_stmt* s = NULL;
if (sqlite3_prepare_v2(db,
"SELECT name FROM sqlite_master WHERE type='table' AND name LIKE 'peers\\_%' ESCAPE '\\'",
-1, &s, NULL) != SQLITE_OK) return -1;
char sql[256];
while (sqlite3_step(s) == SQLITE_ROW) {
const char* tbl = (const char*)sqlite3_column_text(s, 0);
int node_type = base_type;
if (best_at == ADDR_TYPE_DIRECT && base_type == 1) {
snprintf(sql, sizeof(sql),
"SELECT adm_tags FROM \"%s\" WHERE node_id=?", tbl);
sqlite3_stmt* a = NULL;
if (sqlite3_prepare_v2(db, sql, -1, &a, NULL) == SQLITE_OK) {
sqlite3_bind_int64(a, 1, (sqlite3_int64)node_id);
if (sqlite3_step(a) == SQLITE_ROW) {
const char* tags = (const char*)sqlite3_column_text(a, 0);
if (tags && strstr(tags, "supernode=yes")) node_type = 4;
}
sqlite3_finalize(a);
}
}
snprintf(sql, sizeof(sql),
"UPDATE \"%s\" SET node_type=? WHERE node_id=?", tbl);
sqlite3_stmt* u = NULL;
if (sqlite3_prepare_v2(db, sql, -1, &u, NULL) == SQLITE_OK) {
sqlite3_bind_int(u, 1, node_type);
sqlite3_bind_int64(u, 2, (sqlite3_int64)node_id);
sqlite3_step(u); sqlite3_finalize(u);
}
}
sqlite3_finalize(s);
DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "nodeinfo_updated: node=%016llx best_at=%d base_type=%d",
(unsigned long long)node_id, best_at, base_type);
return 0;
}
@@ -49,4 +49,7 @@ int topo_node_sqlite_node_set_online(sqlite3* db, uint64_t node_id, int online);
int topo_node_sqlite_node_get_online(sqlite3* db, uint64_t node_id);
int topo_node_sqlite_get_ed25519_pubkey(sqlite3* db, uint64_t node_id, uint8_t pubkey_out[32]);
/** Пересчитывает node_type во всех peers_* таблицах на основе addr_type из node_addresses */
int topo_node_sqlite_nodeinfo_updated(sqlite3* db, uint64_t node_id);
#endif
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1011,7 +1011,8 @@ static void ping_timeout_cbk(void* arg) {
int etcp_send_ping_to_socket(struct UTUN_INSTANCE* instance, struct ETCP_SOCKET* e_sock,
const uint8_t* peer_pubkey_bin, const struct sockaddr_storage* addr,
int timeout_ms, etcp_ping_callback_t cb, void* user_arg,
const uint8_t* user_data, size_t user_data_len) {
const uint8_t* user_data, size_t user_data_len,
uint8_t flags) {
if (!instance || !e_sock || !peer_pubkey_bin || !addr || timeout_ms <= 0 || !cb) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "bad args");
return -1;
@@ -1044,6 +1045,7 @@ int etcp_send_ping_to_socket(struct UTUN_INSTANCE* instance, struct ETCP_SOCKET*
memcpy(ctx->user_data, user_data, user_data_len);
ctx->user_data_len = user_data_len;
}
memcpy(ctx->peer_pubkey, peer_pubkey_bin, SC_PUBKEY_SIZE);
struct ETCP_DGRAM* dgram = u_malloc(PACKET_DATA_SIZE);
if (!dgram) {
if (ctx->user_data) u_free(ctx->user_data);
@@ -1056,6 +1058,7 @@ int etcp_send_ping_to_socket(struct UTUN_INSTANCE* instance, struct ETCP_SOCKET*
size_t offset = 0;
uint8_t* p = dgram->data;
*p++ = ETCP_PING;
*p++ = flags; // flags
uint64_t nid = htobe64(instance->node_id);
memcpy(p, &nid, 8); p += 8;
uint64_t nonce_be = htobe64(ctx->nonce);
@@ -1115,25 +1118,39 @@ int etcp_send_ping(struct UTUN_INSTANCE* instance, const uint8_t* peer_pubkey_bi
}
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "ping N1 [%s]", sockaddr_storage_to_str(addr).str);
return etcp_send_ping_to_socket(instance, e_sock, peer_pubkey_bin, addr, timeout_ms,
cb, user_arg, user_data, user_data_len);
cb, user_arg, user_data, user_data_len, 0);
}
// === Helpers extracted from etcp_connections_read_callback_socket ===
static int handle_ping(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt, const struct sockaddr_storage* addr, const uint8_t* decrypted_pubkey, size_t pkt_len) {
if (pkt_len < 22) {
if (pkt_len < 23) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "PING too short: pkt_len=%zu from %s", pkt_len, sockaddr_storage_to_str(addr).str);
return 7;
}
uint64_t nonce = be64toh(*(uint64_t*)(pkt->data + 9));
uint16_t ulen = be16toh(*(uint16_t*)(pkt->data + 17));
const uint8_t* udata = (ulen > 0) ? (pkt->data + 19) : NULL;
uint8_t flags = pkt->data[1];
uint64_t peer_id = be64toh(*(uint64_t*)(pkt->data + 2));
uint64_t nonce = be64toh(*(uint64_t*)(pkt->data + 10));
uint16_t ulen = be16toh(*(uint16_t*)(pkt->data + 18));
const uint8_t* udata = (ulen > 0) ? (pkt->data + 20) : NULL;
if ((flags & ETCP_PING_FLAG_SEND_RTT) && ulen >= 2) {
uint16_t rtt_val = be16toh(*(uint16_t*)udata);
topo_node_ping_update_rtt(e_sock->instance->topo_groups, peer_id, rtt_val);
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "PING rtt=%u from peer=%016llx", (unsigned)rtt_val, (unsigned long long)peer_id);
}
uint8_t pong_flags = 0;
if (e_sock->instance->topo_groups && topo_node_ping_request_cbk(e_sock->instance->topo_groups, peer_id))
pong_flags |= ETCP_PING_FLAG_WANT_RTT;
struct ETCP_DGRAM* resp = u_malloc(PACKET_DATA_SIZE);
if (resp) {
resp->link = NULL;
resp->noencrypt_len = SC_PUBKEY_ENC_SIZE;
uint8_t* p = resp->data;
*p++ = ETCP_PONG;
*p++ = pong_flags;
uint64_t nid = htobe64(e_sock->instance->node_id);
memcpy(p, &nid, 8); p += 8;
uint64_t n = htobe64(nonce);
@@ -1152,8 +1169,8 @@ static int handle_ping(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt, const
sc_context_t resp_sc;
sc_init_ctx(&resp_sc, &e_sock->instance->my_keys);
if (sc_set_peer_public_key(&resp_sc, decrypted_pubkey, SC_PEER_PUBKEY_BIN) == SC_OK) {
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "PONG send nonce=%016llx to=%s fd=%d",
(unsigned long long)nonce, sockaddr_storage_to_str(addr).str, e_sock->fd);
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "PONG send nonce=%016llx flags=%02x to=%s fd=%d",
(unsigned long long)nonce, (unsigned)pong_flags, sockaddr_storage_to_str(addr).str, e_sock->fd);
etcp_send_ping_raw(resp, e_sock->fd, &resp_sc, addr);
}
u_free(resp);
@@ -1162,22 +1179,28 @@ static int handle_ping(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt, const
return 0;
}
static void rtt_send_ping_cb(int success, uint16_t rtt, void* arg, uint64_t nonce,
const uint8_t* resp_data, size_t resp_data_len) {
(void)success; (void)rtt; (void)arg; (void)nonce; (void)resp_data; (void)resp_data_len;
}
static int handle_pong(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt, const struct sockaddr_storage* addr, size_t pkt_len) {
if (pkt_len < 20) {
if (pkt_len < 23) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "PONG too short: pkt_len=%zu from %s", pkt_len, sockaddr_storage_to_str(addr).str);
return 7;
}
uint64_t nonce = be64toh(*(uint64_t*)(pkt->data + 9));
uint8_t flags = pkt->data[1];
uint64_t nonce = be64toh(*(uint64_t*)(pkt->data + 10));
uint16_t ulen = 0;
const uint8_t* udata = NULL;
if (pkt->data_len >= 19) {
ulen = be16toh(*(uint16_t*)(pkt->data + 17));
if (ulen > 0 && pkt->data_len >= 19 + ulen) {
udata = pkt->data + 19;
if (pkt->data_len >= 20) {
ulen = be16toh(*(uint16_t*)(pkt->data + 18));
if (ulen > 0 && pkt->data_len >= 20 + ulen) {
udata = pkt->data + 20;
}
}
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "PONG recv nonce=%016llx data_len=%u from=%s socket=%s",
(unsigned long long)nonce, (unsigned)pkt->data_len,
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "PONG recv nonce=%016llx flags=%02x data_len=%u from=%s socket=%s",
(unsigned long long)nonce, (unsigned)flags, (unsigned)pkt->data_len,
sockaddr_storage_to_str(addr).str, e_sock->name);
struct PING_CONTEXT* ctx = e_sock->instance->pending_pings;
struct PING_CONTEXT* prev = NULL;
@@ -1193,9 +1216,21 @@ static int handle_pong(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt, const
}
uint64_t now = get_time_tb();
uint16_t rtt = (now >= ctx->send_time) ? (uint16_t)(now - ctx->send_time) : 0;
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "PONG matched nonce=%016llx rtt=%u",
(unsigned long long)nonce, (unsigned)rtt);
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "PONG matched nonce=%016llx rtt=%u want_rtt=%d",
(unsigned long long)nonce, (unsigned)rtt, (flags & ETCP_PING_FLAG_WANT_RTT) ? 1 : 0);
uint64_t pong_peer_id = be64toh(*(uint64_t*)(pkt->data + 2));
topo_node_ping_update_rtt(e_sock->instance->topo_groups, pong_peer_id, rtt);
ctx->cb(1, rtt, ctx->arg, nonce, udata, ulen);
if ((flags & ETCP_PING_FLAG_WANT_RTT) && ctx->peer_pubkey[0] != 0) {
uint8_t rtt_buf[2];
rtt_buf[0] = (uint8_t)(rtt >> 8);
rtt_buf[1] = (uint8_t)(rtt & 0xFF);
etcp_send_ping_to_socket(e_sock->instance, e_sock, ctx->peer_pubkey, addr, 1000,
rtt_send_ping_cb, NULL, rtt_buf, 2, ETCP_PING_FLAG_SEND_RTT);
}
if (ctx->user_data) u_free(ctx->user_data);
u_free(ctx);
break;
@@ -1580,7 +1615,7 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
pkt->data_len=pkt_len-3;
pkt->noencrypt_len=0;
uint8_t code = pkt->data[0];
uint64_t peer_id = be64toh(*(uint64_t*)(pkt->data + 1));
uint64_t peer_id = be64toh(*(uint64_t*)(pkt->data + 2));
if (code == ETCP_PING) {
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "X25519 decrypted: PING from peer=0x%016llx src=%s",
(unsigned long long)peer_id, sockaddr_storage_to_str(&addr).str);
@@ -37,6 +37,9 @@ extern "C" {
#define ETCP_PONG 0x07
#define ETCP_KEEPALIVE 0x08
#define ETCP_PING_FLAG_WANT_RTT 0x01 // в PONG: хочу получить RTT от пингера
#define ETCP_PING_FLAG_SEND_RTT 0x02 // в PING: несу RTT для получателя
/* Адаптивный keepalive */
#define KA_PERIOD_MIN_MS 200
#define KA_PERIOD_MAX_MS 10000
@@ -110,6 +113,7 @@ struct PING_CONTEXT {
uint64_t nonce;
void* timeout_timer;
uint64_t send_time; // время отправки пинга в 0.1ms
uint8_t peer_pubkey[SC_PUBKEY_SIZE];
uint8_t* user_data;
size_t user_data_len;
};
@@ -339,10 +343,12 @@ int etcp_send_ping(struct UTUN_INSTANCE* instance, const uint8_t* peer_pubkey_bi
const uint8_t* user_data, size_t user_data_len);
// шлёт пинг на addr используя pubkey. в пакет помещает user_data[user_len]. при получении ответа или таймауте вызывает callback.
// flags: ETCP_PING_FLAG_SEND_RTT — user_data содержит RTT для peer
int etcp_send_ping_to_socket(struct UTUN_INSTANCE* instance, struct ETCP_SOCKET* e_sock,
const uint8_t* peer_pubkey_bin, const struct sockaddr_storage* addr,
int timeout_ms, etcp_ping_callback_t cb, void* user_arg,
const uint8_t* user_data, size_t user_data_len);
const uint8_t* user_data, size_t user_data_len,
uint8_t flags);
void etcp_connections_read_callback_socket(socket_t sock, void* arg);
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.