Browse Source

fix: restore original source content after refactoring (accidental code changes removed)

topo_upd
Evgeny 2 months ago
parent
commit
542694a0e9
  1. 6
      src/routing_layer/conn_mgr.c
  2. 8
      src/routing_layer/route_connectivity.c
  3. 4
      src/routing_layer/route_ping.c
  4. 1
      src/routing_layer/topo_group.c
  5. 62
      src/routing_layer/topo_node.c
  6. 7
      src/routing_layer/topo_node.h
  7. 88
      src/routing_layer/topo_node_sqlite.c
  8. 3
      src/routing_layer/topo_node_sqlite.h
  9. 73
      src/transport_layer/etcp_connections.c
  10. 8
      src/transport_layer/etcp_connections.h

6
src/routing_layer/conn_mgr.c

@ -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 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; 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; 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, 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);
return; return;
} }
s = s->next; 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) { if (ctx->attempt < CONN_MGR_LOCAL_SCAN_ATTEMPTS && ctx->phase == 0) {
etcp_send_ping_to_socket(entry->mgr->instance, ctx->sock, 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, 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, 0); &ctx->addr, CONN_MGR_LOCAL_SCAN_TIMEOUT_MS, cm_ping_cb, ctx, NULL, 0);
return; return;
} }
DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "conn_mgr: %s failed for 0x%016llx after %d attempts", 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; } while (s) { if (s->local_addr.ss_family == AF_INET) break; s = s->next; }
if (!s) break; if (!s) break;
etcp_send_ping_to_socket(mgr->instance, s, nq->node->public_key, &sa, 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, 0); CONN_PROBE_TIMEOUT_MS, cm_bg_ping_noop_cb, NULL, NULL, 0);
break; break;
} }
} }

8
src/routing_layer/route_connectivity.c

@ -16,7 +16,6 @@
#include "topo_node.h" #include "topo_node.h"
#include "topo_group.h" #include "topo_group.h"
#include "route_connectivity.h" #include "route_connectivity.h"
#include "topo_node_sqlite.h"
#define CONN_MAX_SOCKET_CANDIDATES 8 #define CONN_MAX_SOCKET_CANDIDATES 8
@ -202,8 +201,7 @@ static void conn_probe_start_series(struct conn_probe_ctx* ctx) {
int ret = etcp_send_ping_to_socket(ctx->instance, sock, ctx->peer_pubkey, int ret = etcp_send_ping_to_socket(ctx->instance, sock, ctx->peer_pubkey,
&ctx->target_addr, ctx->timeout_ms, &ctx->target_addr, ctx->timeout_ms,
conn_probe_single_cb, ctx, NULL, 0, 0); conn_probe_single_cb, ctx, NULL, 0);
if (ret != 0) { if (ret != 0) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "probe: cannot start ping from socket %s", sock->name); DEBUG_ERROR(DEBUG_CATEGORY_BGP, "probe: cannot start ping from socket %s", sock->name);
ctx->count_sent = 3; // simulate full failure ctx->count_sent = 3; // simulate full failure
@ -233,7 +231,7 @@ static void conn_probe_single_cb(int success, uint16_t rtt, void* arg,
struct ETCP_SOCKET* sock = ctx->candidate_sockets[ctx->candidate_index]; struct ETCP_SOCKET* sock = ctx->candidate_sockets[ctx->candidate_index];
int ret = etcp_send_ping_to_socket(ctx->instance, sock, ctx->peer_pubkey, int ret = etcp_send_ping_to_socket(ctx->instance, sock, ctx->peer_pubkey,
&ctx->target_addr, ctx->timeout_ms, &ctx->target_addr, ctx->timeout_ms,
conn_probe_single_cb, ctx, NULL, 0, 0); conn_probe_single_cb, ctx, NULL, 0);
if (ret != 0) { if (ret != 0) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "probe: cannot continue ping from socket %s", sock->name); DEBUG_ERROR(DEBUG_CATEGORY_BGP, "probe: cannot continue ping from socket %s", sock->name);
ctx->count_sent = ctx->count_total; // force finish series ctx->count_sent = ctx->count_total; // force finish series
@ -281,8 +279,6 @@ 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", 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, (unsigned long long)ctx->nq->node->node_id,
c->interface_status, c->nat_status, c->real_status); 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);
} }
} }

4
src/routing_layer/route_ping.c

@ -309,7 +309,7 @@ static void route_ping_single_cb(int success,
ctx->timeout_ms, ctx->timeout_ms,
route_ping_single_cb, route_ping_single_cb,
ctx, ctx,
NULL, 0, 0); NULL, 0);
if (ret != 0) { if (ret != 0) {
/* Не смогли отправить следующий — завершаем серию досрочно */ /* Не смогли отправить следующий — завершаем серию досрочно */
@ -391,7 +391,7 @@ void route_ping_handle_req(struct NAT_DETECTION* nd, struct TOPO_GROUP* group,
ctx->timeout_ms, ctx->timeout_ms,
route_ping_single_cb, route_ping_single_cb,
ctx, ctx,
NULL, 0, 0); NULL, 0);
if (ret != 0) { if (ret != 0) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "ping req: cannot start first ping"); DEBUG_ERROR(DEBUG_CATEGORY_BGP, "ping req: cannot start first ping");

1
src/routing_layer/topo_group.c

@ -586,7 +586,6 @@ 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); 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); 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); if (group->instance->control_srv) control_server_notify_node_change(group->instance->control_srv, nodeinfo1);

62
src/routing_layer/topo_node.c

@ -13,8 +13,6 @@
#include "topo_group.h" #include "topo_group.h"
#include "route_lib.h" #include "route_lib.h"
#include "etcp_debug.h" #include "etcp_debug.h"
#include "topo_node_sqlite.h"
#include "../lib/u_async.h"
void topo_node_ref(struct TOPO_NODE* ni) { void topo_node_ref(struct TOPO_NODE* ni) {
if (!ni) return; if (!ni) return;
@ -264,55 +262,6 @@ struct TOPO_NODEQ* topo_node_find_by_id(struct TOPO_GROUP* group, uint64_t node_
return e ? (struct TOPO_NODEQ*)e : NULL; 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 ===== // ===== dump / format =====
static int is_node_connectivity_active(struct TOPO_CONNECTIVITY* c) { static int is_node_connectivity_active(struct TOPO_CONNECTIVITY* c) {
@ -321,8 +270,7 @@ static int is_node_connectivity_active(struct TOPO_CONNECTIVITY* c) {
|| c->nat_status != PROBE_RESULT_UNKNOWN || c->nat_status != PROBE_RESULT_UNKNOWN
|| c->real_status != PROBE_RESULT_UNKNOWN || c->real_status != PROBE_RESULT_UNKNOWN
|| c->probe_start_time != 0 || 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) { static const char* probe_status_str(uint8_t s) {
@ -412,11 +360,11 @@ void topo_node_dump_all(struct TOPO_GROUP* group) {
struct TOPO_CONNECTIVITY* c = &nq->connectivity; struct TOPO_CONNECTIVITY* c = &nq->connectivity;
if (is_node_connectivity_active(c)) { 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 last_ping_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",
probe_status_str(c->probe_status), probe_result_str(c->interface_status), c->interface_min_rtt, 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, 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, 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->last_ping_time); (unsigned long long)c->probe_start_time, (unsigned long long)c->ping_req_time);
} }
if (nq->conn_mgr_type != CONN_TYPE_NONE) { if (nq->conn_mgr_type != CONN_TYPE_NONE) {
char interm_buf[200] = ""; int ipos = 0; char interm_buf[200] = ""; int ipos = 0;
@ -500,11 +448,11 @@ int topo_node_format_all(struct TOPO_GROUP* group, char* buf, size_t buf_size) {
struct TOPO_CONNECTIVITY* c = &nq->connectivity; struct TOPO_CONNECTIVITY* c = &nq->connectivity;
if (is_node_connectivity_active(c)) { 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 last_ping_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\n",
probe_status_str(c->probe_status), probe_result_str(c->interface_status), c->interface_min_rtt, 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, 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, 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->last_ping_time); (unsigned long long)c->probe_start_time, (unsigned long long)c->ping_req_time);
} }
if (nq->conn_mgr_type != CONN_TYPE_NONE) { if (nq->conn_mgr_type != CONN_TYPE_NONE) {
FMT_ADD(" conn_mgr: type=%s intermediates=[", conn_mgr_type_str(nq->conn_mgr_type)); FMT_ADD(" conn_mgr: type=%s intermediates=[", conn_mgr_type_str(nq->conn_mgr_type));

7
src/routing_layer/topo_node.h

@ -31,7 +31,6 @@ extern "C" {
#include "secure_channel.h" #include "secure_channel.h"
struct TOPO_GROUP; struct TOPO_GROUP;
struct TOPO_GROUPS;
struct ETCP_SOCKET; struct ETCP_SOCKET;
struct UTUN_INSTANCE; struct UTUN_INSTANCE;
@ -101,12 +100,9 @@ struct TOPO_CONNECTIVITY {
uint64_t nat_probe_time; uint64_t nat_probe_time;
uint64_t real_probe_time; uint64_t real_probe_time;
uint64_t ping_req_time; uint64_t ping_req_time;
uint64_t last_ping_time; // время последнего успешного пинга (0.1ms timebase)
void* probe_list; void* probe_list;
}; };
#define PING_TTL_TB (86400ULL * 10000ULL) // 1 день в 0.1ms units
// ======================================================================= // =======================================================================
// Протокольные структуры (wire-format, packed, без next) // Протокольные структуры (wire-format, packed, без next)
// ======================================================================= // =======================================================================
@ -274,9 +270,6 @@ int topo_group_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct TOPO_GR
void topo_node_dump_all(struct TOPO_GROUP* group); 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_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 #ifdef __cplusplus
} }
#endif #endif

88
src/routing_layer/topo_node_sqlite.c

@ -78,22 +78,6 @@ int topo_node_sqlite_init(sqlite3* db) {
return -1; 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"); DEBUG_INFO(DEBUG_CATEGORY_BGP, "topo_node_sqlite tables initialized");
return 0; return 0;
} }
@ -251,8 +235,7 @@ int topo_node_sqlite_channel_put(sqlite3* db, const char* channel_id,
char sql[512]; char sql[512];
snprintf(sql, sizeof(sql), snprintf(sql, sizeof(sql),
"CREATE TABLE IF NOT EXISTS \"%s\" (" // таблица мемберов канала "CREATE TABLE IF NOT EXISTS \"%s\" (" // таблица мемберов канала
" id INTEGER PRIMARY KEY AUTOINCREMENT," " node_id INTEGER NOT NULL," // ид меббера группы
" node_id INTEGER NOT NULL UNIQUE," // ид мембера группы
" x25519_pubkey BLOB NOT NULL," // ключ мембера для шифрования " x25519_pubkey BLOB NOT NULL," // ключ мембера для шифрования
" ed25519_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) " 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)
@ -263,15 +246,11 @@ int topo_node_sqlite_channel_put(sqlite3* db, const char* channel_id,
" creator_sig BLOB," // валидация мембера админом канала " creator_sig BLOB," // валидация мембера админом канала
" adm_tags TEXT," // тэги которые может менять админ (json_flat style) " adm_tags TEXT," // тэги которые может менять админ (json_flat style)
" adm_tags_sig BLOB," // подпись тэгов adm_tags (может быть подписана ключом суперадмина или админов - проверяем перебором) " adm_tags_sig BLOB," // подпись тэгов adm_tags (может быть подписана ключом суперадмина или админов - проверяем перебором)
" 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_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, рекомендуемая для подключения
" node_RTT INTEGER" // задержка в ms " PRIMARY KEY (node_id))", peers_tbl);
")", peers_tbl);
char* err = NULL; char* err = NULL;
sqlite3_exec(db, sql, NULL, NULL, &err); 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); } 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; sqlite3_stmt* stmt = NULL;
if (sqlite3_prepare_v2(db, if (sqlite3_prepare_v2(db,
@ -523,64 +502,3 @@ int topo_node_sqlite_get_ed25519_pubkey(sqlite3* db, uint64_t node_id, uint8_t p
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
return rc; 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;
}

3
src/routing_layer/topo_node_sqlite.h

@ -49,7 +49,4 @@ 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_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]); 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 #endif

73
src/transport_layer/etcp_connections.c

@ -1011,8 +1011,7 @@ static void ping_timeout_cbk(void* arg) {
int etcp_send_ping_to_socket(struct UTUN_INSTANCE* instance, struct ETCP_SOCKET* e_sock, 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, const uint8_t* peer_pubkey_bin, const struct sockaddr_storage* addr,
int timeout_ms, etcp_ping_callback_t cb, void* user_arg, 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) { if (!instance || !e_sock || !peer_pubkey_bin || !addr || timeout_ms <= 0 || !cb) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "bad args"); DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "bad args");
return -1; return -1;
@ -1045,7 +1044,6 @@ int etcp_send_ping_to_socket(struct UTUN_INSTANCE* instance, struct ETCP_SOCKET*
memcpy(ctx->user_data, user_data, user_data_len); memcpy(ctx->user_data, user_data, user_data_len);
ctx->user_data_len = 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); struct ETCP_DGRAM* dgram = u_malloc(PACKET_DATA_SIZE);
if (!dgram) { if (!dgram) {
if (ctx->user_data) u_free(ctx->user_data); if (ctx->user_data) u_free(ctx->user_data);
@ -1058,7 +1056,6 @@ int etcp_send_ping_to_socket(struct UTUN_INSTANCE* instance, struct ETCP_SOCKET*
size_t offset = 0; size_t offset = 0;
uint8_t* p = dgram->data; uint8_t* p = dgram->data;
*p++ = ETCP_PING; *p++ = ETCP_PING;
*p++ = flags; // flags
uint64_t nid = htobe64(instance->node_id); uint64_t nid = htobe64(instance->node_id);
memcpy(p, &nid, 8); p += 8; memcpy(p, &nid, 8); p += 8;
uint64_t nonce_be = htobe64(ctx->nonce); uint64_t nonce_be = htobe64(ctx->nonce);
@ -1118,39 +1115,25 @@ 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); 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, return etcp_send_ping_to_socket(instance, e_sock, peer_pubkey_bin, addr, timeout_ms,
cb, user_arg, user_data, user_data_len, 0); cb, user_arg, user_data, user_data_len);
} }
// === Helpers extracted from etcp_connections_read_callback_socket === // === 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) { static int handle_ping(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt, const struct sockaddr_storage* addr, const uint8_t* decrypted_pubkey, size_t pkt_len) {
if (pkt_len < 23) { if (pkt_len < 22) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "PING too short: pkt_len=%zu from %s", pkt_len, sockaddr_storage_to_str(addr).str); DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "PING too short: pkt_len=%zu from %s", pkt_len, sockaddr_storage_to_str(addr).str);
return 7; return 7;
} }
uint8_t flags = pkt->data[1]; uint64_t nonce = be64toh(*(uint64_t*)(pkt->data + 9));
uint64_t peer_id = be64toh(*(uint64_t*)(pkt->data + 2)); uint16_t ulen = be16toh(*(uint16_t*)(pkt->data + 17));
uint64_t nonce = be64toh(*(uint64_t*)(pkt->data + 10)); const uint8_t* udata = (ulen > 0) ? (pkt->data + 19) : NULL;
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); struct ETCP_DGRAM* resp = u_malloc(PACKET_DATA_SIZE);
if (resp) { if (resp) {
resp->link = NULL; resp->link = NULL;
resp->noencrypt_len = SC_PUBKEY_ENC_SIZE; resp->noencrypt_len = SC_PUBKEY_ENC_SIZE;
uint8_t* p = resp->data; uint8_t* p = resp->data;
*p++ = ETCP_PONG; *p++ = ETCP_PONG;
*p++ = pong_flags;
uint64_t nid = htobe64(e_sock->instance->node_id); uint64_t nid = htobe64(e_sock->instance->node_id);
memcpy(p, &nid, 8); p += 8; memcpy(p, &nid, 8); p += 8;
uint64_t n = htobe64(nonce); uint64_t n = htobe64(nonce);
@ -1169,8 +1152,8 @@ static int handle_ping(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt, const
sc_context_t resp_sc; sc_context_t resp_sc;
sc_init_ctx(&resp_sc, &e_sock->instance->my_keys); 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) { 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 flags=%02x to=%s fd=%d", DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "PONG send nonce=%016llx to=%s fd=%d",
(unsigned long long)nonce, (unsigned)pong_flags, sockaddr_storage_to_str(addr).str, e_sock->fd); (unsigned long long)nonce, sockaddr_storage_to_str(addr).str, e_sock->fd);
etcp_send_ping_raw(resp, e_sock->fd, &resp_sc, addr); etcp_send_ping_raw(resp, e_sock->fd, &resp_sc, addr);
} }
u_free(resp); u_free(resp);
@ -1179,28 +1162,22 @@ static int handle_ping(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt, const
return 0; 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) { static int handle_pong(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt, const struct sockaddr_storage* addr, size_t pkt_len) {
if (pkt_len < 23) { if (pkt_len < 20) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "PONG too short: pkt_len=%zu from %s", pkt_len, sockaddr_storage_to_str(addr).str); DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "PONG too short: pkt_len=%zu from %s", pkt_len, sockaddr_storage_to_str(addr).str);
return 7; return 7;
} }
uint8_t flags = pkt->data[1]; uint64_t nonce = be64toh(*(uint64_t*)(pkt->data + 9));
uint64_t nonce = be64toh(*(uint64_t*)(pkt->data + 10));
uint16_t ulen = 0; uint16_t ulen = 0;
const uint8_t* udata = NULL; const uint8_t* udata = NULL;
if (pkt->data_len >= 20) { if (pkt->data_len >= 19) {
ulen = be16toh(*(uint16_t*)(pkt->data + 18)); ulen = be16toh(*(uint16_t*)(pkt->data + 17));
if (ulen > 0 && pkt->data_len >= 20 + ulen) { if (ulen > 0 && pkt->data_len >= 19 + ulen) {
udata = pkt->data + 20; udata = pkt->data + 19;
} }
} }
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "PONG recv nonce=%016llx flags=%02x data_len=%u from=%s socket=%s", DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "PONG recv nonce=%016llx data_len=%u from=%s socket=%s",
(unsigned long long)nonce, (unsigned)flags, (unsigned)pkt->data_len, (unsigned long long)nonce, (unsigned)pkt->data_len,
sockaddr_storage_to_str(addr).str, e_sock->name); sockaddr_storage_to_str(addr).str, e_sock->name);
struct PING_CONTEXT* ctx = e_sock->instance->pending_pings; struct PING_CONTEXT* ctx = e_sock->instance->pending_pings;
struct PING_CONTEXT* prev = NULL; struct PING_CONTEXT* prev = NULL;
@ -1216,21 +1193,9 @@ static int handle_pong(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt, const
} }
uint64_t now = get_time_tb(); uint64_t now = get_time_tb();
uint16_t rtt = (now >= ctx->send_time) ? (uint16_t)(now - ctx->send_time) : 0; 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 want_rtt=%d", DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "PONG matched nonce=%016llx rtt=%u",
(unsigned long long)nonce, (unsigned)rtt, (flags & ETCP_PING_FLAG_WANT_RTT) ? 1 : 0); (unsigned long long)nonce, (unsigned)rtt);
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); 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); if (ctx->user_data) u_free(ctx->user_data);
u_free(ctx); u_free(ctx);
break; break;
@ -1615,7 +1580,7 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
pkt->data_len=pkt_len-3; pkt->data_len=pkt_len-3;
pkt->noencrypt_len=0; pkt->noencrypt_len=0;
uint8_t code = pkt->data[0]; uint8_t code = pkt->data[0];
uint64_t peer_id = be64toh(*(uint64_t*)(pkt->data + 2)); uint64_t peer_id = be64toh(*(uint64_t*)(pkt->data + 1));
if (code == ETCP_PING) { if (code == ETCP_PING) {
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "X25519 decrypted: PING from peer=0x%016llx src=%s", 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); (unsigned long long)peer_id, sockaddr_storage_to_str(&addr).str);

8
src/transport_layer/etcp_connections.h

@ -37,9 +37,6 @@ extern "C" {
#define ETCP_PONG 0x07 #define ETCP_PONG 0x07
#define ETCP_KEEPALIVE 0x08 #define ETCP_KEEPALIVE 0x08
#define ETCP_PING_FLAG_WANT_RTT 0x01 // в PONG: хочу получить RTT от пингера
#define ETCP_PING_FLAG_SEND_RTT 0x02 // в PING: несу RTT для получателя
/* Адаптивный keepalive */ /* Адаптивный keepalive */
#define KA_PERIOD_MIN_MS 200 #define KA_PERIOD_MIN_MS 200
#define KA_PERIOD_MAX_MS 10000 #define KA_PERIOD_MAX_MS 10000
@ -113,7 +110,6 @@ struct PING_CONTEXT {
uint64_t nonce; uint64_t nonce;
void* timeout_timer; void* timeout_timer;
uint64_t send_time; // время отправки пинга в 0.1ms uint64_t send_time; // время отправки пинга в 0.1ms
uint8_t peer_pubkey[SC_PUBKEY_SIZE];
uint8_t* user_data; uint8_t* user_data;
size_t user_data_len; size_t user_data_len;
}; };
@ -343,12 +339,10 @@ int etcp_send_ping(struct UTUN_INSTANCE* instance, const uint8_t* peer_pubkey_bi
const uint8_t* user_data, size_t user_data_len); const uint8_t* user_data, size_t user_data_len);
// шлёт пинг на addr используя pubkey. в пакет помещает user_data[user_len]. при получении ответа или таймауте вызывает callback. // шлёт пинг на 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, 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, const uint8_t* peer_pubkey_bin, const struct sockaddr_storage* addr,
int timeout_ms, etcp_ping_callback_t cb, void* user_arg, 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); void etcp_connections_read_callback_socket(socket_t sock, void* arg);

Loading…
Cancel
Save