|
|
|
|
@ -32,6 +32,12 @@ static void peers_table_name(const char* ch_id, char* buf, size_t sz) {
|
|
|
|
|
snprintf(buf, sz, "peers_%s", san); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int adm_tags_deleted(const char* tags) { |
|
|
|
|
if (!tags || !tags[0]) return 0; |
|
|
|
|
char buf[16]; |
|
|
|
|
return json_flat_get(tags, "deleted", buf, sizeof(buf)) == 0 && strcmp(buf, "yes") == 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* ── Классификация адресов (локально, по IP) ── */ |
|
|
|
|
|
|
|
|
|
static int addr_type_from_ip(int family, const uint8_t* addr) { |
|
|
|
|
@ -292,6 +298,9 @@ int topo_node_sqlite_init(sqlite3* db) {
|
|
|
|
|
snprintf(isql, sizeof(isql), |
|
|
|
|
"ALTER TABLE \"%s\" ADD COLUMN source INTEGER NOT NULL DEFAULT 0", tbl); |
|
|
|
|
sqlite3_exec(db, isql, NULL, NULL, NULL); |
|
|
|
|
snprintf(isql, sizeof(isql), |
|
|
|
|
"ALTER TABLE \"%s\" ADD COLUMN deleted INTEGER NOT NULL DEFAULT 0", tbl); |
|
|
|
|
sqlite3_exec(db, isql, NULL, NULL, NULL); |
|
|
|
|
} |
|
|
|
|
sqlite3_finalize(s); |
|
|
|
|
} |
|
|
|
|
@ -338,6 +347,7 @@ int topo_node_sqlite_channel_put(sqlite3* db, const char* channel_id,
|
|
|
|
|
" node_RTT INTEGER," /* RTT до узла в мс, часть индекса (node_type, node_RTT) */ |
|
|
|
|
" connected INTEGER NOT NULL DEFAULT 0," /* 1 = было активное подключение к узлу */ |
|
|
|
|
" storage INTEGER NOT NULL DEFAULT 0," /* 1 = приоритетный хранитель аттачей */ |
|
|
|
|
" deleted INTEGER NOT NULL DEFAULT 0," /* 1 = аккаунт удалён владельцем (не отображаем, не подключаемся) */ |
|
|
|
|
" local_nick TEXT," /* локальный ник (GUI only, не синхронизируется) */ |
|
|
|
|
" source INTEGER NOT NULL DEFAULT 0" /* 0=полная merkle-запись 1=упрощённый плейсхолдер topo_group
|
|
|
|
|
(не участвует в merkle-хеше, дополняется полной записью) */ |
|
|
|
|
@ -424,7 +434,7 @@ int topo_node_sqlite_member_put(sqlite3* db, const char* channel_id, uint64_t no
|
|
|
|
|
|
|
|
|
|
if (adm_tags || adm_tags_sig || storage > 0) { |
|
|
|
|
snprintf(sql, sizeof(sql), |
|
|
|
|
"UPDATE \"%s\" SET adm_tags=?, adm_tags_sig=?, storage=? WHERE node_id=?", peers_tbl); |
|
|
|
|
"UPDATE \"%s\" SET adm_tags=?, adm_tags_sig=?, storage=?, deleted=? WHERE node_id=?", peers_tbl); |
|
|
|
|
sqlite3_stmt* u = NULL; |
|
|
|
|
if (sqlite3_prepare_v2(db, sql, -1, &u, NULL) == SQLITE_OK) { |
|
|
|
|
if (adm_tags && adm_tags[0]) sqlite3_bind_text(u, 1, adm_tags, -1, SQLITE_STATIC); |
|
|
|
|
@ -432,7 +442,8 @@ int topo_node_sqlite_member_put(sqlite3* db, const char* channel_id, uint64_t no
|
|
|
|
|
if (adm_tags_sig) sqlite3_bind_blob(u, 2, adm_tags_sig, 64, SQLITE_STATIC); |
|
|
|
|
else sqlite3_bind_null(u, 2); |
|
|
|
|
sqlite3_bind_int(u, 3, storage); |
|
|
|
|
sqlite3_bind_int64(u, 4, (sqlite3_int64)node_id); |
|
|
|
|
sqlite3_bind_int(u, 4, adm_tags_deleted(adm_tags)); |
|
|
|
|
sqlite3_bind_int64(u, 5, (sqlite3_int64)node_id); |
|
|
|
|
sqlite3_step(u); sqlite3_finalize(u); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
@ -512,7 +523,7 @@ int topo_node_sqlite_member_owner_put(sqlite3* db, const char* channel_id, uint6
|
|
|
|
|
char peers_tbl[80]; peers_table_name(channel_id, peers_tbl, sizeof(peers_tbl)); |
|
|
|
|
char sql[256]; |
|
|
|
|
snprintf(sql, sizeof(sql), |
|
|
|
|
"UPDATE \"%s\" SET adm_tags=?, adm_tags_sig=?, storage=? WHERE node_id=?", peers_tbl); |
|
|
|
|
"UPDATE \"%s\" SET adm_tags=?, adm_tags_sig=?, storage=?, deleted=? WHERE node_id=?", peers_tbl); |
|
|
|
|
sqlite3_stmt* u = NULL; |
|
|
|
|
if (sqlite3_prepare_v2(db, sql, -1, &u, NULL) != SQLITE_OK) return -1; |
|
|
|
|
if (adm_tags && adm_tags[0]) sqlite3_bind_text(u, 1, adm_tags, -1, SQLITE_STATIC); |
|
|
|
|
@ -520,7 +531,8 @@ int topo_node_sqlite_member_owner_put(sqlite3* db, const char* channel_id, uint6
|
|
|
|
|
if (adm_tags_sig) sqlite3_bind_blob(u, 2, adm_tags_sig, 64, SQLITE_STATIC); |
|
|
|
|
else sqlite3_bind_null(u, 2); |
|
|
|
|
sqlite3_bind_int(u, 3, storage); |
|
|
|
|
sqlite3_bind_int64(u, 4, (sqlite3_int64)node_id); |
|
|
|
|
sqlite3_bind_int(u, 4, adm_tags_deleted(adm_tags)); |
|
|
|
|
sqlite3_bind_int64(u, 5, (sqlite3_int64)node_id); |
|
|
|
|
sqlite3_step(u); sqlite3_finalize(u); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
@ -785,32 +797,34 @@ int topo_node_sqlite_nodeinfo_updated(sqlite3* db, uint64_t node_id) {
|
|
|
|
|
while (sqlite3_step(s) == SQLITE_ROW) { |
|
|
|
|
const char* tbl = (const char*)sqlite3_column_text(s, 0); |
|
|
|
|
|
|
|
|
|
int node_type = base_type; int is_storage = 0; |
|
|
|
|
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) { |
|
|
|
|
char buf[64]; |
|
|
|
|
int node_type = base_type; int is_storage = 0; int is_deleted = 0; |
|
|
|
|
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) { |
|
|
|
|
char buf[64]; |
|
|
|
|
if (best_at == ADDR_TYPE_DIRECT && base_type == 1) { |
|
|
|
|
if (json_flat_get(tags, "supernode", buf, sizeof(buf)) == 0 && strcmp(buf, "yes") == 0) node_type = 4; |
|
|
|
|
if (json_flat_get(tags, "storage", buf, sizeof(buf)) == 0 && strcmp(buf, "yes") == 0) is_storage = 1; |
|
|
|
|
} |
|
|
|
|
is_deleted = adm_tags_deleted(tags); |
|
|
|
|
} |
|
|
|
|
sqlite3_finalize(a); |
|
|
|
|
} |
|
|
|
|
sqlite3_finalize(a); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
snprintf(sql, sizeof(sql), |
|
|
|
|
"UPDATE \"%s\" SET node_type=?, storage=? WHERE node_id=?", tbl); |
|
|
|
|
"UPDATE \"%s\" SET node_type=?, storage=?, deleted=? 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_int(u, 2, is_storage); |
|
|
|
|
sqlite3_bind_int64(u, 3, (sqlite3_int64)node_id); |
|
|
|
|
sqlite3_bind_int(u, 3, is_deleted); |
|
|
|
|
sqlite3_bind_int64(u, 4, (sqlite3_int64)node_id); |
|
|
|
|
sqlite3_step(u); sqlite3_finalize(u); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
@ -1013,7 +1027,7 @@ int topo_node_sqlite_get_connected_peers(sqlite3* db, const char* channel_id,
|
|
|
|
|
if (!db || !channel_id || !out_ids || !out_count) return -1; |
|
|
|
|
*out_ids = NULL; *out_count = 0; |
|
|
|
|
char peers_tbl[80]; peers_table_name(channel_id, peers_tbl, sizeof(peers_tbl)); |
|
|
|
|
char sql[128]; snprintf(sql, sizeof(sql), "SELECT node_id FROM \"%s\" WHERE connected=1", peers_tbl); |
|
|
|
|
char sql[192]; snprintf(sql, sizeof(sql), "SELECT node_id FROM \"%s\" WHERE connected=1 AND deleted=0", peers_tbl); |
|
|
|
|
sqlite3_stmt* st = NULL; |
|
|
|
|
if (sqlite3_prepare_v2(db, sql, -1, &st, NULL) != SQLITE_OK) return -1; |
|
|
|
|
int cnt = 0; |
|
|
|
|
@ -1030,13 +1044,15 @@ int topo_node_sqlite_get_connected_peers(sqlite3* db, const char* channel_id,
|
|
|
|
|
|
|
|
|
|
int topo_node_sqlite_get_public_peers(sqlite3* db, const char* channel_id, |
|
|
|
|
uint64_t** out_ids, int* out_count, uint64_t self_node_id) { |
|
|
|
|
if (!db || !out_ids || !out_count) return -1; |
|
|
|
|
if (!db || !channel_id || !out_ids || !out_count) return -1; |
|
|
|
|
*out_ids = NULL; *out_count = 0; |
|
|
|
|
(void)channel_id; |
|
|
|
|
const char* sql = |
|
|
|
|
char peers_tbl[80]; peers_table_name(channel_id, peers_tbl, sizeof(peers_tbl)); |
|
|
|
|
char sql[384]; snprintf(sql, sizeof(sql), |
|
|
|
|
"SELECT DISTINCT na.node_id FROM node_addresses na" |
|
|
|
|
" WHERE na.node_id!=?1 AND na.family IN (4,6) AND na.addr_type IN (1,2)" |
|
|
|
|
" AND EXISTS (SELECT 1 FROM nodes n WHERE n.node_id=na.node_id)"; |
|
|
|
|
" AND EXISTS (SELECT 1 FROM nodes n WHERE n.node_id=na.node_id)" |
|
|
|
|
" AND NOT EXISTS (SELECT 1 FROM \"%s\" p WHERE p.node_id=na.node_id AND p.deleted=1)", |
|
|
|
|
peers_tbl); |
|
|
|
|
sqlite3_stmt* st = NULL; |
|
|
|
|
if (sqlite3_prepare_v2(db, sql, -1, &st, NULL) != SQLITE_OK) return -1; |
|
|
|
|
sqlite3_bind_int64(st, 1, (sqlite3_int64)self_node_id); |
|
|
|
|
@ -1058,7 +1074,7 @@ int topo_node_sqlite_get_supernode_peers(sqlite3* db, const char* channel_id,
|
|
|
|
|
*out_ids = NULL; *out_count = 0; |
|
|
|
|
char peers_tbl[80]; peers_table_name(channel_id, peers_tbl, sizeof(peers_tbl)); |
|
|
|
|
char sql[256]; snprintf(sql, sizeof(sql), |
|
|
|
|
"SELECT p.node_id FROM \"%s\" p WHERE p.node_type=4" |
|
|
|
|
"SELECT p.node_id FROM \"%s\" p WHERE p.node_type=4 AND p.deleted=0" |
|
|
|
|
" AND EXISTS (SELECT 1 FROM node_addresses na WHERE na.node_id=p.node_id AND na.family IN (4,6))", |
|
|
|
|
peers_tbl); |
|
|
|
|
sqlite3_stmt* st = NULL; |
|
|
|
|
@ -1077,13 +1093,15 @@ int topo_node_sqlite_get_supernode_peers(sqlite3* db, const char* channel_id,
|
|
|
|
|
|
|
|
|
|
int topo_node_sqlite_get_local_peers(sqlite3* db, const char* channel_id, |
|
|
|
|
uint64_t** out_ids, int* out_count, uint64_t self_node_id) { |
|
|
|
|
if (!db || !out_ids || !out_count) return -1; |
|
|
|
|
if (!db || !channel_id || !out_ids || !out_count) return -1; |
|
|
|
|
*out_ids = NULL; *out_count = 0; |
|
|
|
|
(void)channel_id; |
|
|
|
|
const char* sql = |
|
|
|
|
char peers_tbl[80]; peers_table_name(channel_id, peers_tbl, sizeof(peers_tbl)); |
|
|
|
|
char sql[384]; snprintf(sql, sizeof(sql), |
|
|
|
|
"SELECT DISTINCT na.node_id FROM node_addresses na" |
|
|
|
|
" WHERE na.node_id!=?1 AND na.family IN (4,6) AND na.addr_type IN (0,3)" |
|
|
|
|
" AND EXISTS (SELECT 1 FROM nodes n WHERE n.node_id=na.node_id)"; |
|
|
|
|
" AND EXISTS (SELECT 1 FROM nodes n WHERE n.node_id=na.node_id)" |
|
|
|
|
" AND NOT EXISTS (SELECT 1 FROM \"%s\" p WHERE p.node_id=na.node_id AND p.deleted=1)", |
|
|
|
|
peers_tbl); |
|
|
|
|
sqlite3_stmt* st = NULL; |
|
|
|
|
if (sqlite3_prepare_v2(db, sql, -1, &st, NULL) != SQLITE_OK) return -1; |
|
|
|
|
sqlite3_bind_int64(st, 1, (sqlite3_int64)self_node_id); |
|
|
|
|
|