chat: invite-ссылки с несколькими адресами + ncd-адреса узлов (join)
This commit is contained in:
1 parent
d88dccfa19
commit
481872d5db
24 files changed
+517
-114
No files matched your search
@@ -86,6 +86,21 @@ static void smeta6_lookup(struct TOPO_SOCKMETA6* head, uint8_t sid, uint8_t* cfg
|
||||
if (m->id == sid) { *cfg = m->config_type; *nat = m->nat_type; return; }
|
||||
}
|
||||
|
||||
/* reality-параметры сокета → фиксированный blob для node_addresses.options.
|
||||
Возвращает 1 и заполняет opts, если у сокета есть reality; иначе 0. */
|
||||
static int reality_opts_build(struct TOPO_NODE* ni, uint8_t sid, struct TOPO_ADDR_REALITY_OPTS* opts) {
|
||||
if (!ni || !opts) return 0;
|
||||
for (const struct TOPO_REALITY_SOCK* r = ni->reality_socks; r; r = r->next) {
|
||||
if (r->socket_id != sid) continue;
|
||||
memcpy(opts->short_id, r->short_id, 8);
|
||||
memcpy(opts->server_pubkey, r->server_pubkey, 32);
|
||||
memcpy(opts->version, r->version, 3);
|
||||
memcpy(opts->server_name, r->server_name, TOPO_REALITY_SNAME_MAX);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ── Персистенция адресов узла (источник истины — BGP/topo_group) ── */
|
||||
|
||||
int topo_node_sqlite_addrs_put(sqlite3* db, uint64_t node_id, struct TOPO_NODE* ni) {
|
||||
@@ -109,17 +124,19 @@ int topo_node_sqlite_addrs_put(sqlite3* db, uint64_t node_id, struct TOPO_NODE*
|
||||
|
||||
sqlite3_stmt* is = NULL;
|
||||
if (sqlite3_prepare_v2(db,
|
||||
"INSERT INTO node_addresses(node_id,family,protocol,address,port,addr_type,config_type,nat_type,socket_id)"
|
||||
" VALUES(?,?,?,?,?,?,?,?,?)", -1, &is, NULL) != SQLITE_OK) {
|
||||
"INSERT INTO node_addresses(node_id,family,protocol,address,port,addr_type,config_type,nat_type,socket_id,options)"
|
||||
" VALUES(?,?,?,?,?,?,?,?,?,?)", -1, &is, NULL) != SQLITE_OK) {
|
||||
sqlite3_exec(db, "COMMIT", NULL, NULL, NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int written = 0;
|
||||
struct TOPO_ADDR_REALITY_OPTS ropts;
|
||||
for (const struct TOPO_ADDR4* a = ni->v4_addrs; a; a = a->next) {
|
||||
uint8_t cfg, nat; smeta4_lookup(ni->v4_sock_meta, a->socket_id, &cfg, &nat);
|
||||
int at = (a->type == TOPO_ADDR_INTERFACE) ? addr_type_from_ip(4, a->addr)
|
||||
: addr_type_classify(cfg, nat);
|
||||
int has_reality = (a->protocol & TOPO_PROTO_REALITY) && reality_opts_build(ni, a->socket_id, &ropts);
|
||||
sqlite3_bind_int64(is, 1, (sqlite3_int64)node_id);
|
||||
sqlite3_bind_int(is, 2, 4);
|
||||
sqlite3_bind_int(is, 3, (int)a->protocol);
|
||||
@@ -129,6 +146,8 @@ int topo_node_sqlite_addrs_put(sqlite3* db, uint64_t node_id, struct TOPO_NODE*
|
||||
sqlite3_bind_int(is, 7, (int)cfg);
|
||||
sqlite3_bind_int(is, 8, (int)nat);
|
||||
sqlite3_bind_int(is, 9, (int)a->socket_id);
|
||||
if (has_reality) sqlite3_bind_blob(is, 10, &ropts, sizeof(ropts), SQLITE_STATIC);
|
||||
else sqlite3_bind_null(is, 10);
|
||||
if (sqlite3_step(is) != SQLITE_DONE)
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "addrs_put: INSERT failed node=%016llx fam=4 sock=%d at=%d cfg=%d nat=%d addr=%d.%d.%d.%d:%d: %s",
|
||||
(unsigned long long)node_id, a->socket_id, at, cfg, nat,
|
||||
@@ -140,6 +159,7 @@ int topo_node_sqlite_addrs_put(sqlite3* db, uint64_t node_id, struct TOPO_NODE*
|
||||
uint8_t cfg, nat; smeta6_lookup(ni->v6_sock_meta, a->socket_id, &cfg, &nat);
|
||||
int at = (a->type == TOPO_ADDR_INTERFACE) ? ADDR_TYPE_NETIF
|
||||
: addr_type_classify(cfg, nat);
|
||||
int has_reality = (a->protocol & TOPO_PROTO_REALITY) && reality_opts_build(ni, a->socket_id, &ropts);
|
||||
sqlite3_bind_int64(is, 1, (sqlite3_int64)node_id);
|
||||
sqlite3_bind_int(is, 2, 6);
|
||||
sqlite3_bind_int(is, 3, (int)a->protocol);
|
||||
@@ -149,6 +169,8 @@ int topo_node_sqlite_addrs_put(sqlite3* db, uint64_t node_id, struct TOPO_NODE*
|
||||
sqlite3_bind_int(is, 7, (int)cfg);
|
||||
sqlite3_bind_int(is, 8, (int)nat);
|
||||
sqlite3_bind_int(is, 9, (int)a->socket_id);
|
||||
if (has_reality) sqlite3_bind_blob(is, 10, &ropts, sizeof(ropts), SQLITE_STATIC);
|
||||
else sqlite3_bind_null(is, 10);
|
||||
if (sqlite3_step(is) != SQLITE_DONE)
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "addrs_put: INSERT failed node=%016llx fam=6 sock=%d at=%d cfg=%d nat=%d: %s",
|
||||
(unsigned long long)node_id, a->socket_id, at, cfg, nat, sqlite3_errmsg(db));
|
||||
@@ -255,6 +277,7 @@ int topo_node_sqlite_init(sqlite3* db) {
|
||||
" config_type INTEGER DEFAULT 0,"
|
||||
" nat_type INTEGER DEFAULT 0,"
|
||||
" socket_id INTEGER NOT NULL DEFAULT 0,"
|
||||
" options BLOB," // reality-параметры (TOPO_ADDR_REALITY_OPTS)
|
||||
" created_at INTEGER DEFAULT (unixepoch())"
|
||||
");"
|
||||
"CREATE INDEX IF NOT EXISTS idx_na_node ON node_addresses(node_id);"
|
||||
@@ -284,6 +307,29 @@ int topo_node_sqlite_init(sqlite3* db) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* migration: добавить колонку options в уже существующую node_addresses (idempotent) */
|
||||
{
|
||||
sqlite3_stmt* cs = NULL;
|
||||
int has_options = 0;
|
||||
if (sqlite3_prepare_v2(db, "PRAGMA table_info(node_addresses)", -1, &cs, NULL) == SQLITE_OK) {
|
||||
while (sqlite3_step(cs) == SQLITE_ROW) {
|
||||
const char* cn = (const char*)sqlite3_column_text(cs, 1);
|
||||
if (cn && strcmp(cn, "options") == 0) { has_options = 1; break; }
|
||||
}
|
||||
sqlite3_finalize(cs);
|
||||
}
|
||||
if (!has_options) {
|
||||
char* aerr = NULL;
|
||||
int arc = sqlite3_exec(db, "ALTER TABLE node_addresses ADD COLUMN options BLOB", NULL, NULL, &aerr);
|
||||
if (arc != SQLITE_OK) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_BGP, "topo_node_sqlite_init: ALTER TABLE ADD options failed: %s", aerr ? aerr : "?");
|
||||
if (aerr) sqlite3_free(aerr);
|
||||
} else {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_BGP, "topo_node_sqlite_init: migrated node_addresses (added options column)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* backfill: вывести deleted из adm_tags (idempotent, самовосстановление) */
|
||||
{
|
||||
sqlite3_stmt* s = NULL;
|
||||
@@ -945,11 +991,12 @@ struct TOPO_NODE* topo_node_sqlite_node_load(sqlite3* db, struct TOPO_GROUPS* gr
|
||||
|
||||
struct TOPO_ADDR4* v4_head = NULL; struct TOPO_ADDR4* v4_tail = NULL;
|
||||
struct TOPO_SOCKMETA4* m4_head = NULL; struct TOPO_SOCKMETA4* m4_tail = NULL;
|
||||
struct TOPO_REALITY_SOCK* r_head = NULL; struct TOPO_REALITY_SOCK* r_tail = NULL;
|
||||
uint8_t sock_id_counter = 0;
|
||||
{
|
||||
sqlite3_stmt* s = NULL;
|
||||
if (sqlite3_prepare_v2(db,
|
||||
"SELECT address,port,addr_type,socket_id,protocol,config_type,nat_type FROM node_addresses"
|
||||
"SELECT address,port,addr_type,socket_id,protocol,config_type,nat_type,options FROM node_addresses"
|
||||
" WHERE node_id=? AND family=4 ORDER BY addr_type",
|
||||
-1, &s, NULL) == SQLITE_OK) {
|
||||
sqlite3_bind_int64(s, 1, (sqlite3_int64)node_id);
|
||||
@@ -983,6 +1030,22 @@ struct TOPO_NODE* topo_node_sqlite_node_load(sqlite3* db, struct TOPO_GROUPS* gr
|
||||
else { m4_tail->next = m4; m4_tail = m4; }
|
||||
}
|
||||
}
|
||||
if (sqlite3_column_type(s, 7) == SQLITE_BLOB
|
||||
&& sqlite3_column_bytes(s, 7) == TOPO_ADDR_REALITY_OPTS_SIZE
|
||||
&& (proto & TOPO_PROTO_REALITY)) {
|
||||
const struct TOPO_ADDR_REALITY_OPTS* o = (const struct TOPO_ADDR_REALITY_OPTS*)sqlite3_column_blob(s, 7);
|
||||
struct TOPO_REALITY_SOCK* r = u_calloc(1, sizeof(*r));
|
||||
if (r) {
|
||||
r->socket_id = sock_id;
|
||||
memcpy(r->short_id, o->short_id, 8);
|
||||
memcpy(r->server_pubkey, o->server_pubkey, 32);
|
||||
memcpy(r->version, o->version, 3);
|
||||
memcpy(r->server_name, o->server_name, TOPO_REALITY_SNAME_MAX);
|
||||
r->server_name[TOPO_REALITY_SNAME_MAX - 1] = 0;
|
||||
if (!r_head) r_head = r_tail = r;
|
||||
else { r_tail->next = r; r_tail = r; }
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3_finalize(s);
|
||||
}
|
||||
@@ -993,7 +1056,7 @@ struct TOPO_NODE* topo_node_sqlite_node_load(sqlite3* db, struct TOPO_GROUPS* gr
|
||||
{
|
||||
sqlite3_stmt* s = NULL;
|
||||
if (sqlite3_prepare_v2(db,
|
||||
"SELECT address,port,addr_type,socket_id,protocol,config_type,nat_type FROM node_addresses"
|
||||
"SELECT address,port,addr_type,socket_id,protocol,config_type,nat_type,options FROM node_addresses"
|
||||
" WHERE node_id=? AND family=6 ORDER BY addr_type",
|
||||
-1, &s, NULL) == SQLITE_OK) {
|
||||
sqlite3_bind_int64(s, 1, (sqlite3_int64)node_id);
|
||||
@@ -1027,6 +1090,22 @@ struct TOPO_NODE* topo_node_sqlite_node_load(sqlite3* db, struct TOPO_GROUPS* gr
|
||||
else { m6_tail->next = m6; m6_tail = m6; }
|
||||
}
|
||||
}
|
||||
if (sqlite3_column_type(s, 7) == SQLITE_BLOB
|
||||
&& sqlite3_column_bytes(s, 7) == TOPO_ADDR_REALITY_OPTS_SIZE
|
||||
&& (proto6 & TOPO_PROTO_REALITY)) {
|
||||
const struct TOPO_ADDR_REALITY_OPTS* o = (const struct TOPO_ADDR_REALITY_OPTS*)sqlite3_column_blob(s, 7);
|
||||
struct TOPO_REALITY_SOCK* r = u_calloc(1, sizeof(*r));
|
||||
if (r) {
|
||||
r->socket_id = sock_id;
|
||||
memcpy(r->short_id, o->short_id, 8);
|
||||
memcpy(r->server_pubkey, o->server_pubkey, 32);
|
||||
memcpy(r->version, o->version, 3);
|
||||
memcpy(r->server_name, o->server_name, TOPO_REALITY_SNAME_MAX);
|
||||
r->server_name[TOPO_REALITY_SNAME_MAX - 1] = 0;
|
||||
if (!r_head) r_head = r_tail = r;
|
||||
else { r_tail->next = r; r_tail = r; }
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3_finalize(s);
|
||||
}
|
||||
@@ -1043,6 +1122,7 @@ struct TOPO_NODE* topo_node_sqlite_node_load(sqlite3* db, struct TOPO_GROUPS* gr
|
||||
ni->v6_addrs = v6_head;
|
||||
ni->v4_sock_meta = m4_head;
|
||||
ni->v6_sock_meta = m6_head;
|
||||
ni->reality_socks = r_head;
|
||||
|
||||
DEBUG_INFO(DEBUG_CATEGORY_BGP, "node_load: node 0x%016llx loaded from DB name=%s v4=%d v6=%d",
|
||||
(unsigned long long)node_id, name ? name : "",
|
||||
|
||||
Reference in new issue
Block a user