BGP: фикс владения адресами в реестре (мульти-группа), проброс group_id в сервис (conn_mgr per-group), membership-фильтр create_group; тест media через chat-группу
This commit is contained in:
1 parent
6c9a47b201
commit
42a94aa916
14 files changed
+324
-71
No files matched your search
@@ -703,8 +703,8 @@ void cm_start_phase_reverse(struct CONN_MGR_ENTRY* entry) {
|
||||
/* Принимающая сторона REVERSE: получили DIRECT_REQ от инициатора — открываем
|
||||
* NCD-соединение к нему, добавляем линки по адресам из запроса. При INIT
|
||||
* вызывается cm_reverse_init_cb. */
|
||||
void cm_handle_direct_req(struct ETCP_CONN* conn, const uint8_t* data, size_t len) {
|
||||
struct CONN_MGR* mgr = conn->instance->conn_mgr; if (!mgr) return;
|
||||
void cm_handle_direct_req(struct ETCP_CONN* conn, struct CONN_MGR* mgr, const uint8_t* data, size_t len) {
|
||||
if (!mgr) return;
|
||||
struct CM_DIRECT_REQ* req = (struct CM_DIRECT_REQ*)data;
|
||||
if (len < CM_DIRECT_REQ_H_SIZE + (size_t)req->addr_count * 8) { DEBUG_WARN(DEBUG_CATEGORY_GENERAL, "conn_mgr: DIRECT_REQ too short"); return; }
|
||||
DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "conn_mgr: got DIRECT_REQ from 0x%016llx with %u addrs",
|
||||
@@ -744,12 +744,15 @@ void conn_mgr_router_recv_handler(struct ETCP_CONN* conn, struct ll_entry* entry
|
||||
return;
|
||||
}
|
||||
uint8_t* d = entry->dgram + ROUTER_SVC_PAYLOAD_OFF; size_t len = entry->len - ROUTER_SVC_PAYLOAD_OFF; uint8_t sub = d[1];
|
||||
struct CONN_MGR* mgr = conn->instance->conn_mgr;
|
||||
/* conn_mgr — per-group: резолвим группу из заголовка доставки, а не instance->conn_mgr */
|
||||
uint64_t group_id; memcpy(&group_id, entry->dgram + ROUTER_SVC_GROUP_OFF, 8);
|
||||
struct TOPO_GROUP* grp = topo_groups_find(conn->instance->topo_groups, group_id);
|
||||
struct CONN_MGR* mgr = grp ? grp->conn_mgr : conn->instance->conn_mgr;
|
||||
if (mgr) { struct CONN_MGR_ENTRY* e = cm_find_entry(mgr, conn->peer_node_id); if (e && e->state == CONN_MGR_STATE_CONNECTED) e->last_traffic_tb = get_time_tb(); }
|
||||
switch (sub) {
|
||||
case CM_SUBCMD_DIRECT_REQ: cm_handle_direct_req(conn, d, len); break;
|
||||
case CM_SUBCMD_DIRECT_REQ: cm_handle_direct_req(conn, mgr, d, len); break;
|
||||
case CM_SUBCMD_DIRECT_RESP: break;
|
||||
case CM_SUBCMD_INTERM_EXCHANGE_REQ: if (len >= CM_EXCHANGE_REQ_SIZE) cm_handle_interm_exchange_req(conn, (struct CM_EXCHANGE_REQ*)d); break;
|
||||
case CM_SUBCMD_INTERM_EXCHANGE_REQ: if (len >= CM_EXCHANGE_REQ_SIZE) cm_handle_interm_exchange_req(conn, mgr, (struct CM_EXCHANGE_REQ*)d); break;
|
||||
case CM_SUBCMD_INTERM_EXCHANGE_RESP: if (mgr) cm_handle_interm_exchange_resp(mgr, d, len); break;
|
||||
case CM_SUBCMD_INTERM_SELECTED: if (mgr) cm_handle_interm_selected(mgr, d, len); break;
|
||||
case CM_SUBCMD_DISCONNECT: if (len >= CM_DISCONNECT_SIZE && mgr) cm_handle_disconnect(mgr, ((struct CM_DISCONNECT*)d)->node_id); break;
|
||||
|
||||
@@ -121,8 +121,8 @@ void cm_handle_interm_selected(struct CONN_MGR* mgr, const uint8_t* data, size_t
|
||||
/* Цель получила EXCHANGE_REQ: измеряет RTT до кандидатов инициатора (если
|
||||
* замеры протухли — запускает probe), отправляет EXCHANGE_RESP со СВОИМИ
|
||||
* кандидатами + замерами RTT до кандидатов инициатора. */
|
||||
void cm_handle_interm_exchange_req(struct ETCP_CONN* conn, struct CM_EXCHANGE_REQ* req) {
|
||||
struct CONN_MGR* mgr=conn->instance->conn_mgr; if(!mgr)return;
|
||||
void cm_handle_interm_exchange_req(struct ETCP_CONN* conn, struct CONN_MGR* mgr, struct CM_EXCHANGE_REQ* req) {
|
||||
if (!mgr) return;
|
||||
uint64_t now=get_time_tb();
|
||||
for(uint8_t i=0;i<req->candidate_count&&i<4;i++){
|
||||
struct TOPO_GROUP_NODE* nq=topo_node_find_by_id(mgr->group,req->candidates[i].node_id);
|
||||
|
||||
@@ -142,7 +142,7 @@ void cm_start_phase_direct(struct CONN_MGR_ENTRY* entry);
|
||||
void cm_start_phase_reverse(struct CONN_MGR_ENTRY* entry);
|
||||
void cm_start_phase_indirect(struct CONN_MGR_ENTRY* entry);
|
||||
void cm_start_local_scan(struct CONN_MGR_ENTRY* entry);
|
||||
void cm_handle_direct_req(struct ETCP_CONN* conn, const uint8_t* data, size_t len);
|
||||
void cm_handle_direct_req(struct ETCP_CONN* conn, struct CONN_MGR* mgr, const uint8_t* data, size_t len);
|
||||
void cm_handle_disconnect(struct CONN_MGR* mgr, uint64_t node_id);
|
||||
void cm_reverse_init_cb(struct ETCP_CONN* conn, int event, void* arg);
|
||||
void cm_reverse_timeout_cb(void* arg);
|
||||
@@ -164,7 +164,7 @@ uint8_t cm_sock_v6_classify(const struct ETCP_SOCKET* s);
|
||||
void cm_exchange_timeout_cb(void* arg);
|
||||
void cm_compute_intermediaries(struct CONN_MGR_ENTRY* entry, struct CM_EXCHANGE_RESP* resp);
|
||||
void cm_exchange_probe_retry_cb(void* arg);
|
||||
void cm_handle_interm_exchange_req(struct ETCP_CONN* conn, struct CM_EXCHANGE_REQ* req);
|
||||
void cm_handle_interm_exchange_req(struct ETCP_CONN* conn, struct CONN_MGR* mgr, struct CM_EXCHANGE_REQ* req);
|
||||
void cm_handle_interm_exchange_resp(struct CONN_MGR* mgr, const uint8_t* data, size_t len);
|
||||
void cm_handle_interm_selected(struct CONN_MGR* mgr, const uint8_t* data, size_t len);
|
||||
|
||||
|
||||
@@ -329,6 +329,7 @@ static void router_send_close_to_service(struct ETCP_ROUTER_CONN* rconn) {
|
||||
memcpy(e->dgram + ROUTER_SVC_SRC_OFF, &rconn->remote_node_id, 8);
|
||||
memcpy(e->dgram + ROUTER_SVC_DST_OFF, &inst->node_id, 8);
|
||||
e->dgram[ROUTER_SVC_FLAGS_OFF] = 0;
|
||||
memcpy(e->dgram + ROUTER_SVC_GROUP_OFF, &rconn->group_id, 8);
|
||||
e->len = ROUTER_SVC_HDR_SIZE;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCPROUTE, "router_close_svc: svc_id=%u remote=%016llx",
|
||||
rconn->svc_id, (unsigned long long)rconn->remote_node_id);
|
||||
@@ -847,9 +848,9 @@ static void router_idle_ack_timer_cb(void* arg) {
|
||||
// Reorder / assembly (аналог etcp_output_try_assembly)
|
||||
// ====================================================================
|
||||
|
||||
// Доставка сервисной кодограммы в едином формате [svc_id][src][dst][rx_flags][payload].
|
||||
// Доставка сервисной кодограммы в едином формате [svc_id][src][dst][rx_flags][group_id][payload].
|
||||
// Для loopback (dst == self) src и dst оба = self, rx_flags = 0.
|
||||
static void router_deliver_loopback(struct UTUN_INSTANCE* inst, uint8_t svc_id, struct ll_entry* entry) {
|
||||
static void router_deliver_loopback(struct UTUN_INSTANCE* inst, uint64_t group_id, uint8_t svc_id, struct ll_entry* entry) {
|
||||
etcp_recv_fn cb = inst->router_bindings.callbacks[svc_id];
|
||||
if (!cb) { queue_dgram_free(entry); queue_entry_free(entry); return; }
|
||||
size_t payload_len = entry->len - 1;
|
||||
@@ -861,6 +862,7 @@ static void router_deliver_loopback(struct UTUN_INSTANCE* inst, uint8_t svc_id,
|
||||
memcpy(e->dgram + ROUTER_SVC_SRC_OFF, &inst->node_id, 8);
|
||||
memcpy(e->dgram + ROUTER_SVC_DST_OFF, &inst->node_id, 8);
|
||||
e->dgram[ROUTER_SVC_FLAGS_OFF] = 0;
|
||||
memcpy(e->dgram + ROUTER_SVC_GROUP_OFF, &group_id, 8);
|
||||
if (payload_len > 0) memcpy(e->dgram + ROUTER_SVC_PAYLOAD_OFF, entry->dgram + 1, payload_len);
|
||||
e->len = ROUTER_SVC_HDR_SIZE + payload_len;
|
||||
queue_dgram_free(entry); queue_entry_free(entry);
|
||||
@@ -904,6 +906,7 @@ static void router_deliver(struct ETCP_ROUTER_CONN* rconn, struct ETCP_CONN* con
|
||||
memcpy(svc_entry->dgram + ROUTER_SVC_SRC_OFF, &rconn->remote_node_id, 8);
|
||||
memcpy(svc_entry->dgram + ROUTER_SVC_DST_OFF, &inst->node_id, 8);
|
||||
svc_entry->dgram[ROUTER_SVC_FLAGS_OFF] = rx_flags;
|
||||
memcpy(svc_entry->dgram + ROUTER_SVC_GROUP_OFF, &rconn->group_id, 8);
|
||||
if (payload_len > 0) memcpy(svc_entry->dgram + ROUTER_SVC_PAYLOAD_OFF, payload, payload_len);
|
||||
if (decoded) u_free(decoded);
|
||||
|
||||
@@ -1295,7 +1298,7 @@ int etcp_route_send(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t dst_
|
||||
|
||||
if (dst_node_id == inst->node_id) {
|
||||
DEBUG_TRACE(DEBUG_CATEGORY_ETCPROUTE, "loopback svc_id=%u len=%zu", svc_id, payload_len);
|
||||
router_deliver_loopback(inst, svc_id, entry);
|
||||
router_deliver_loopback(inst, group_id, svc_id, entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1324,6 +1327,7 @@ void etcp_router_conn_restart(struct UTUN_INSTANCE* inst, uint64_t group_id, uin
|
||||
memcpy(e->dgram + ROUTER_SVC_SRC_OFF, &remote_node_id, 8);
|
||||
memcpy(e->dgram + ROUTER_SVC_DST_OFF, &inst->node_id, 8);
|
||||
e->dgram[ROUTER_SVC_FLAGS_OFF] = 0;
|
||||
memcpy(e->dgram + ROUTER_SVC_GROUP_OFF, &group_id, 8);
|
||||
e->len = ROUTER_SVC_HDR_SIZE;
|
||||
cb(loopback_conn(inst), e);
|
||||
} else { queue_entry_free(e); }
|
||||
|
||||
@@ -40,14 +40,16 @@ struct SVC_ROUTE_HDR {
|
||||
#define SVC_ROUTE_MAX_BINDINGS 256
|
||||
|
||||
// Единый формат доставки сервисной кодограммы (router → сервис):
|
||||
// [svc_id:1][src_node_id:8][dst_node_id:8][rx_flags:1][payload...]
|
||||
// [svc_id:1][src_node_id:8][dst_node_id:8][rx_flags:1][group_id:8][payload...]
|
||||
// src/dst — реальные end-to-end узлы из SVC_ROUTE заголовка (не промежуточные).
|
||||
// rx_flags — биты ROUTER_FLAG_ENCRYPTED/SIGNED, бывшие на wire (статус для сервиса).
|
||||
// group_id — группа SVC_ROUTE-пакета (для per-group сервисов вроде conn_mgr).
|
||||
#define ROUTER_SVC_SRC_OFF 1
|
||||
#define ROUTER_SVC_DST_OFF 9
|
||||
#define ROUTER_SVC_FLAGS_OFF 17
|
||||
#define ROUTER_SVC_PAYLOAD_OFF 18
|
||||
#define ROUTER_SVC_HDR_SIZE 18 // svc_id(1) + src_node_id(8) + dst_node_id(8) + rx_flags(1)
|
||||
#define ROUTER_SVC_GROUP_OFF 18
|
||||
#define ROUTER_SVC_PAYLOAD_OFF 26
|
||||
#define ROUTER_SVC_HDR_SIZE 26 // svc_id(1) + src_node_id(8) + dst_node_id(8) + rx_flags(1) + group_id(8)
|
||||
|
||||
// Биты в flags
|
||||
#define ROUTER_FLAG_START 0x80
|
||||
|
||||
@@ -511,12 +511,25 @@ struct TOPO_GROUP* topo_groups_create_group(struct TOPO_GROUPS* g, uint64_t grou
|
||||
|
||||
struct ll_queue* connections = g->instance->connections;
|
||||
if (connections) {
|
||||
sqlite3* db = g->instance->topo_sqlite_db;
|
||||
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);
|
||||
if (cqe->conn && cqe->peer_node_id != 0) {
|
||||
if (group_type == TOPO_GROUP_TYPE_CHAT && db) {
|
||||
/* CHAT: добавляем conn только если пир — член именно этого канала */
|
||||
uint64_t* chs = NULL; int chn = 0;
|
||||
if (topo_node_sqlite_get_member_channels(db, cqe->peer_node_id, &chs, &chn) == 0) {
|
||||
for (int i = 0; i < chn; i++) {
|
||||
if (chs[i] == group_id) { topo_group_new_conn(group, cqe->conn); break; }
|
||||
}
|
||||
}
|
||||
u_free(chs);
|
||||
} else {
|
||||
topo_group_new_conn(group, cqe->conn);
|
||||
}
|
||||
}
|
||||
entry = entry->hash_next;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,6 +132,21 @@ uint64_t* topo_node_best_hop_list(struct TOPO_GROUP_NODE* nq, uint8_t* out_count
|
||||
return (uint64_t*)((uint8_t*)best + sizeof(struct TOPO_NODEPATH));
|
||||
}
|
||||
|
||||
/* Освобождает списки адресов (sock_meta + addrs + reality) узла в глобальном реестре.
|
||||
* Адреса — глобальная идентичность узла, шарится между группами через node_registry,
|
||||
* поэтому освобождаются только при последнем unref (topo_node_registry_unref). */
|
||||
static void topo_node_identity_free(struct TOPO_GROUPS* groups, struct TOPO_NODE* ni) {
|
||||
if (!groups || !ni) return;
|
||||
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);
|
||||
free_reality_sock_list(ni->reality_socks);
|
||||
ni->v4_sock_meta = NULL; ni->v4_addrs = NULL;
|
||||
ni->v6_sock_meta = NULL; ni->v6_addrs = NULL;
|
||||
ni->reality_socks = NULL;
|
||||
}
|
||||
|
||||
void topo_node_free_raw(struct TOPO_GROUPS* groups, struct TOPO_NODE* ni) {
|
||||
if (!ni) return;
|
||||
if (groups) {
|
||||
@@ -151,18 +166,7 @@ void topo_node_destroy(struct TOPO_GROUPS* groups, struct TOPO_NODE* ni) {
|
||||
|
||||
void topo_nodeq_free_group_fields(struct TOPO_GROUPS* groups, struct TOPO_GROUP_NODE* nq) {
|
||||
if (!groups || !nq) return;
|
||||
struct TOPO_NODE* ni = topo_node_registry_find(groups, nq->node_id);
|
||||
if (ni) {
|
||||
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);
|
||||
free_reality_sock_list(ni->reality_socks);
|
||||
ni->v4_sock_meta = NULL; ni->v4_addrs = NULL;
|
||||
ni->v6_sock_meta = NULL; ni->v6_addrs = NULL;
|
||||
ni->reality_socks = NULL;
|
||||
topo_node_registry_unref(groups, nq->node_id);
|
||||
}
|
||||
topo_node_registry_unref(groups, nq->node_id);
|
||||
if (nq->subnets) {
|
||||
free_v4_sub_list(groups->v4_subnet_pool, nq->subnets->v4_subnets);
|
||||
free_v6_sub_list(groups->v6_subnet_pool, nq->subnets->v6_subnets);
|
||||
@@ -183,22 +187,42 @@ struct TOPO_NODE* topo_node_registry_find(struct TOPO_GROUPS* groups, uint64_t n
|
||||
return node;
|
||||
}
|
||||
|
||||
/* Является ли входящий узел полной идентичностью (BGP NODEINFO / локальный узел).
|
||||
* Partial-узлы из invite/DB-load не несут ed25519 — по ним идентичность не перезаписываем. */
|
||||
static int topo_node_is_full_identity(const struct TOPO_NODE* ni) {
|
||||
for (int i = 0; i < SC_PUBKEY_SIZE; i++) if (ni->ed25519_public_key[i]) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct TOPO_NODE* topo_node_registry_store(struct TOPO_GROUPS* groups, struct TOPO_NODE* ni) {
|
||||
if (!groups || !ni) return NULL;
|
||||
struct TOPO_NODE* existing = topo_node_registry_find(groups, ni->node_id);
|
||||
if (existing) {
|
||||
int n4 = topo_list_count((struct _topo_head*)ni->v4_addrs);
|
||||
int n6 = topo_list_count((struct _topo_head*)ni->v6_addrs);
|
||||
int e4 = topo_list_count((struct _topo_head*)existing->v4_addrs);
|
||||
int e6 = topo_list_count((struct _topo_head*)existing->v6_addrs);
|
||||
int drop4 = (e4 && n4), drop6 = (e6 && n6);
|
||||
if (drop4 || drop6)
|
||||
DEBUG_WARN(DEBUG_CATEGORY_BGP, "registry_store: node=%016llx EXISTS — dropping new addrs v4=%d v6=%d (existing v4=%d v6=%d)",
|
||||
(unsigned long long)ni->node_id, drop4 ? n4 : 0, drop6 ? n6 : 0, e4, e6);
|
||||
topo_node_ref(existing);
|
||||
if (!existing->v4_addrs && ni->v4_addrs) { existing->v4_addrs = ni->v4_addrs; ni->v4_addrs = NULL; }
|
||||
if (!existing->v6_addrs && ni->v6_addrs) { existing->v6_addrs = ni->v6_addrs; ni->v6_addrs = NULL; }
|
||||
if (!existing->reality_socks && ni->reality_socks) { existing->reality_socks = ni->reality_socks; ni->reality_socks = NULL; }
|
||||
|
||||
/* Идентичность (ver/имя/pubkeys/подпись) — авторитетна у полного NODEINFO,
|
||||
* иначе реестр держит устаревший ver/имя и форвард nodeinfo ломает подпись. */
|
||||
if (topo_node_is_full_identity(ni)) {
|
||||
existing->ver = ni->ver;
|
||||
existing->client_type = ni->client_type;
|
||||
existing->client_activity = ni->client_activity;
|
||||
memcpy(existing->public_key, ni->public_key, SC_PUBKEY_SIZE);
|
||||
memcpy(existing->ed25519_public_key, ni->ed25519_public_key, SC_PUBKEY_SIZE);
|
||||
memcpy(existing->x25519_self_sig, ni->x25519_self_sig, 64);
|
||||
if (ni->node_name) {
|
||||
if (existing->node_name) u_free(existing->node_name);
|
||||
existing->node_name = ni->node_name; ni->node_name = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Адреса — глобальная идентичность. Обновляем каждый список, который входящий узел несёт
|
||||
* (частичные узлы заполняют только то, что знают, не затирая остальное). */
|
||||
if (ni->v4_sock_meta) { free_v4_sock_list(groups->v4_sock_meta_pool, existing->v4_sock_meta); existing->v4_sock_meta = ni->v4_sock_meta; ni->v4_sock_meta = NULL; }
|
||||
if (ni->v4_addrs) { free_v4_addr_list(groups->v4_addr_pool, existing->v4_addrs); existing->v4_addrs = ni->v4_addrs; ni->v4_addrs = NULL; }
|
||||
if (ni->v6_sock_meta) { free_v6_sock_list(groups->v6_sock_meta_pool, existing->v6_sock_meta); existing->v6_sock_meta = ni->v6_sock_meta; ni->v6_sock_meta = NULL; }
|
||||
if (ni->v6_addrs) { free_v6_addr_list(groups->v6_addr_pool, existing->v6_addrs); existing->v6_addrs = ni->v6_addrs; ni->v6_addrs = NULL; }
|
||||
if (ni->reality_socks) { free_reality_sock_list(existing->reality_socks); existing->reality_socks = ni->reality_socks; ni->reality_socks = NULL; }
|
||||
|
||||
topo_node_free_raw(groups, ni);
|
||||
return existing;
|
||||
}
|
||||
@@ -223,6 +247,8 @@ void topo_node_registry_unref(struct TOPO_GROUPS* groups, uint64_t node_id) {
|
||||
struct TOPO_NODE* ni = topo_node_registry_find(groups, node_id);
|
||||
if (!ni) return;
|
||||
uint32_t prev_ref = ni->group_ref_count;
|
||||
if (prev_ref == 1)
|
||||
topo_node_identity_free(groups, ni);
|
||||
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;
|
||||
|
||||
Reference in new issue
Block a user