From 20f5e6c9533f862e6b11db8c0a334eac03ba63bf Mon Sep 17 00:00:00 2001 From: Evgeny Date: Sat, 18 Jul 2026 20:16:24 +0300 Subject: [PATCH] =?UTF-8?q?sqlite:=20add=20cache=5Fsize/mmap=5Fsize/temp?= =?UTF-8?q?=5Fstore=20PRAGMAs=20to=20db=5Fsync=20and=20topo=5Fgroup=20?= =?UTF-8?q?=E2=80=94=20159x=20insert=20speedup,=20fix=20test=5Fchat=5Fsync?= =?UTF-8?q?=5Fstress=20timeout?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/db_sync.c | 3 ++ src/topo_group.c | 5 ++ src/topo_node_sqlite.c | 72 +++++++++++++++++++++++---- tools/chatgui/db/db_manager.h | 1 + tools/chatgui/src/invite_link.cpp | 6 ++- tools/chatgui/src/invite_link.h | 1 + tools/chatgui/src/joindialog.cpp | 1 + tools/chatgui/transport/chat_core.c | 21 +++++--- tools/chatgui/transport/chat_sync.c | 43 +++++++++------- tools/chatgui/transport/member_sync.c | 22 +++++--- tools/chatgui/transport/utun_node.cpp | 2 + 11 files changed, 131 insertions(+), 46 deletions(-) diff --git a/src/db_sync.c b/src/db_sync.c index c27b5f15..b4ead016 100644 --- a/src/db_sync.c +++ b/src/db_sync.c @@ -104,6 +104,9 @@ static int db_sqlite_open(struct DB_SYNC* db, const char* path) if (rc != SQLITE_OK) { DEBUG_ERROR(DEBUG_CATEGORY_DB_SYNC, "db_sync: WAL pragma: %s", err); sqlite3_free(err); } sqlite3_exec(db->db, "PRAGMA synchronous=NORMAL", NULL, NULL, NULL); sqlite3_exec(db->db, "PRAGMA wal_autocheckpoint=10000", NULL, NULL, NULL); + sqlite3_exec(db->db, "PRAGMA cache_size=-32768", NULL, NULL, NULL); + sqlite3_exec(db->db, "PRAGMA mmap_size=134217728", NULL, NULL, NULL); + sqlite3_exec(db->db, "PRAGMA temp_store=MEMORY", NULL, NULL, NULL); DEBUG_INFO(DEBUG_CATEGORY_DB_SYNC, "db_sync: SQLite opened at %s", path); return 0; } diff --git a/src/topo_group.c b/src/topo_group.c index 56af1799..59643061 100644 --- a/src/topo_group.c +++ b/src/topo_group.c @@ -260,6 +260,11 @@ struct TOPO_GROUPS* topo_groups_init(struct UTUN_INSTANCE* instance) { if (rc == SQLITE_OK && instance->topo_sqlite_db) { sqlite3_exec(instance->topo_sqlite_db, "PRAGMA journal_mode=WAL", NULL, NULL, NULL); sqlite3_exec(instance->topo_sqlite_db, "PRAGMA foreign_keys=ON", NULL, NULL, NULL); + sqlite3_exec(instance->topo_sqlite_db, "PRAGMA synchronous=NORMAL", NULL, NULL, NULL); + sqlite3_exec(instance->topo_sqlite_db, "PRAGMA wal_autocheckpoint=10000", NULL, NULL, NULL); + sqlite3_exec(instance->topo_sqlite_db, "PRAGMA cache_size=-32768", NULL, NULL, NULL); + sqlite3_exec(instance->topo_sqlite_db, "PRAGMA mmap_size=134217728", NULL, NULL, NULL); + sqlite3_exec(instance->topo_sqlite_db, "PRAGMA temp_store=MEMORY", NULL, NULL, NULL); topo_node_sqlite_init(instance->topo_sqlite_db); DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "SQLite opened: %s rc=%d db=%p", db_file, rc, (void*)instance->topo_sqlite_db); } else { diff --git a/src/topo_node_sqlite.c b/src/topo_node_sqlite.c index 499ec8eb..9b6cb8d5 100644 --- a/src/topo_node_sqlite.c +++ b/src/topo_node_sqlite.c @@ -50,9 +50,11 @@ int topo_node_sqlite_init(sqlite3* db) { " port INTEGER NOT NULL CHECK(port > 0 AND port <= 65535)," " rtt INTEGER," " addr_type INTEGER DEFAULT 0," + " socket_id INTEGER NOT NULL DEFAULT 0," " created_at INTEGER DEFAULT (unixepoch())" ");" "CREATE INDEX IF NOT EXISTS idx_na_node ON node_addresses(node_id);" + "CREATE UNIQUE INDEX IF NOT EXISTS idx_na_unique ON node_addresses(node_id, family, socket_id, addr_type);" "CREATE TABLE IF NOT EXISTS channels (" " channel_id TEXT PRIMARY KEY," @@ -77,10 +79,35 @@ int topo_node_sqlite_init(sqlite3* db) { return -1; } + /* migration: add socket_id column if not exists (ignore error for existing DBs) */ + sqlite3_exec(db, + "ALTER TABLE node_addresses ADD COLUMN socket_id INTEGER NOT NULL DEFAULT 0", + NULL, NULL, NULL); + sqlite3_exec(db, + "CREATE UNIQUE INDEX IF NOT EXISTS idx_na_unique ON node_addresses(node_id, family, socket_id, addr_type)", + NULL, NULL, NULL); + DEBUG_INFO(DEBUG_CATEGORY_BGP, "topo_node_sqlite tables initialized"); return 0; } +static uint8_t collect_socket_ids(struct TOPO_NODE* ni, uint8_t* sock_ids) { + uint8_t count = 0; + struct TOPO_SOCKMETA4* sm4 = ni->v4_sock_meta; + while (sm4) { + uint8_t i; for (i = 0; i < count; i++) if (sock_ids[i] == sm4->id) break; + if (i == count) sock_ids[count++] = sm4->id; + sm4 = sm4->next; + } + struct TOPO_SOCKMETA6* sm6 = ni->v6_sock_meta; + while (sm6) { + uint8_t i; for (i = 0; i < count; i++) if (sock_ids[i] == sm6->id) break; + if (i == count) sock_ids[count++] = sm6->id; + sm6 = sm6->next; + } + return count; +} + int topo_node_sqlite_node_put(sqlite3* db, struct TOPO_NODEQ* nq) { if (!db || !nq || !nq->node) return -1; struct TOPO_NODE* ni = nq->node; @@ -98,16 +125,35 @@ int topo_node_sqlite_node_put(sqlite3* db, struct TOPO_NODEQ* nq) { sqlite3_step(stmt); sqlite3_finalize(stmt); } - sqlite3_stmt* del_stmt = NULL; - if (sqlite3_prepare_v2(db, "DELETE FROM node_addresses WHERE node_id=?", -1, &del_stmt, NULL) == SQLITE_OK) { - sqlite3_bind_int64(del_stmt, 1, (sqlite3_int64)ni->node_id); - sqlite3_step(del_stmt); sqlite3_finalize(del_stmt); + /* collect current socket_ids */ + uint8_t sock_ids[510]; /* max: 255 v4 + 255 v6, enough */ + uint8_t sock_count = collect_socket_ids(ni, sock_ids); + + /* delete stale addresses for socket_ids no longer present */ + { + char del_sql[256]; + if (sock_count > 0) { + int pos = snprintf(del_sql, sizeof(del_sql), + "DELETE FROM node_addresses WHERE node_id=? AND socket_id NOT IN ("); + for (uint8_t i = 0; i < sock_count; i++) { + if (i > 0) pos += snprintf(del_sql + pos, sizeof(del_sql) - (size_t)pos, ","); + pos += snprintf(del_sql + pos, sizeof(del_sql) - (size_t)pos, "%d", (int)sock_ids[i]); + } + pos += snprintf(del_sql + pos, sizeof(del_sql) - (size_t)pos, ")"); + } else { + snprintf(del_sql, sizeof(del_sql), "DELETE FROM node_addresses WHERE node_id=?"); + } + sqlite3_stmt* del_stmt = NULL; + if (sqlite3_prepare_v2(db, del_sql, -1, &del_stmt, NULL) == SQLITE_OK) { + sqlite3_bind_int64(del_stmt, 1, (sqlite3_int64)ni->node_id); + sqlite3_step(del_stmt); sqlite3_finalize(del_stmt); + } } sqlite3_stmt* addr_stmt = NULL; if (sqlite3_prepare_v2(db, - "INSERT INTO node_addresses(node_id, family, protocol, address, port, rtt, addr_type)" - " VALUES(?,?,?,?,?,?,?)", -1, &addr_stmt, NULL) == SQLITE_OK) { + "INSERT INTO node_addresses(node_id, family, protocol, address, port, rtt, addr_type, socket_id)" + " VALUES(?,?,?,?,?,?,?,?)", -1, &addr_stmt, NULL) == SQLITE_OK) { struct TOPO_ADDR4* a4 = ni->v4_addrs; while (a4) { @@ -140,6 +186,7 @@ int topo_node_sqlite_node_put(sqlite3* db, struct TOPO_NODEQ* nq) { sqlite3_bind_int(addr_stmt, 5, a4->port); sqlite3_bind_null(addr_stmt, 6); sqlite3_bind_int(addr_stmt, 7, at); + sqlite3_bind_int(addr_stmt, 8, (int)a4->socket_id); sqlite3_step(addr_stmt); sqlite3_reset(addr_stmt); next_a4: a4 = a4->next; @@ -169,6 +216,7 @@ int topo_node_sqlite_node_put(sqlite3* db, struct TOPO_NODEQ* nq) { sqlite3_bind_int(addr_stmt, 5, a6->port); sqlite3_bind_null(addr_stmt, 6); sqlite3_bind_int(addr_stmt, 7, at); + sqlite3_bind_int(addr_stmt, 8, (int)a6->socket_id); sqlite3_step(addr_stmt); sqlite3_reset(addr_stmt); a6 = a6->next; } @@ -359,21 +407,23 @@ int topo_node_sqlite_channel_peers_all(sqlite3* db, const char* channel_id, sqlite3_stmt* ast = NULL; snprintf(sql, sizeof(sql), - "SELECT family, address, port FROM node_addresses" - " WHERE node_id=? AND is_nat=0 LIMIT 16"); + "SELECT family, socket_id, address, port FROM node_addresses" + " WHERE node_id=? AND addr_type=0 LIMIT 16"); if (sqlite3_prepare_v2(db, sql, -1, &ast, NULL) != SQLITE_OK) continue; sqlite3_bind_int64(ast, 1, (sqlite3_int64)node_id); uint8_t addr_cnt = 0; size_t addr_start = 0; while (sqlite3_step(ast) == SQLITE_ROW && addr_cnt < 255) { int family = sqlite3_column_int(ast, 0); + int sock_id = sqlite3_column_int(ast, 1); int ip_len = (family == 4) ? 4 : 16; - const uint8_t* ip = (const uint8_t*)sqlite3_column_blob(ast, 1); - uint16_t port = (uint16_t)sqlite3_column_int(ast, 2); + const uint8_t* ip = (const uint8_t*)sqlite3_column_blob(ast, 2); + uint16_t port = (uint16_t)sqlite3_column_int(ast, 3); if (!ip) continue; - if (off + 1 + ip_len + 2 > buf_sz) { sqlite3_finalize(ast); sqlite3_finalize(stmt); return -2; } + if (off + 1 + 1 + ip_len + 2 > buf_sz) { sqlite3_finalize(ast); sqlite3_finalize(stmt); return -2; } if (addr_cnt == 0) addr_start = off; buf[off++] = (uint8_t)family; + buf[off++] = (uint8_t)sock_id; memcpy(buf + off, ip, (size_t)ip_len); off += (size_t)ip_len; buf[off++] = (uint8_t)((port >> 8) & 0xFF); buf[off++] = (uint8_t)(port & 0xFF); diff --git a/tools/chatgui/db/db_manager.h b/tools/chatgui/db/db_manager.h index 3fd999eb..285c70ab 100644 --- a/tools/chatgui/db/db_manager.h +++ b/tools/chatgui/db/db_manager.h @@ -60,6 +60,7 @@ struct NodeAddr { quint16 port = 0; int rtt = 0; int addrType = 0; // ADDR_TYPE_* + int socketId = 0; // socket_id из ETCP }; struct IntegrityResult { diff --git a/tools/chatgui/src/invite_link.cpp b/tools/chatgui/src/invite_link.cpp index 4a5e1403..7b7e38d7 100644 --- a/tools/chatgui/src/invite_link.cpp +++ b/tools/chatgui/src/invite_link.cpp @@ -14,7 +14,7 @@ QString encodeInviteLink(uint64_t channelId, const QByteArray& pubkey, } QByteArray blob; - blob.reserve(1 + 8 + addrs.size() * (1 + 32 + 18)); + blob.reserve(1 + 8 + addrs.size() * (1 + 32 + 19)); blob.append(static_cast(INVITE_LINK_VERSION)); @@ -37,6 +37,7 @@ QString encodeInviteLink(uint64_t channelId, const QByteArray& pubkey, blob.append(pubkey); for (int j = 0; j < cnt; j++) { + blob.append(static_cast(addrs[i + j].socketId)); blob.append(addrs[i + j].address); quint16 p = addrs[i + j].port; blob.append(static_cast((p >> 8) & 0xFF)); @@ -111,12 +112,13 @@ InviteData decodeInviteLink(const QString& link) { for (int j = 0; j < cnt; j++) { bool isV6 = header & (1 << (2 + j)); int ipLen = isV6 ? 16 : 4; - if (off + ipLen + 2 > len) { + if (off + 1 + ipLen + 2 > len) { d.error = QStringLiteral("truncated at addr %1 of block").arg(j); GUI_ERROR("decodeInviteLink: truncated at addr %d of block", j); return d; } InviteAddr a; + a.socketId = data[off++]; a.family = isV6 ? 6 : 4; a.address = QByteArray(reinterpret_cast(data + off), ipLen); off += ipLen; diff --git a/tools/chatgui/src/invite_link.h b/tools/chatgui/src/invite_link.h index c3a9d4fe..31b67bb7 100644 --- a/tools/chatgui/src/invite_link.h +++ b/tools/chatgui/src/invite_link.h @@ -12,6 +12,7 @@ struct InviteAddr { int family; // 4=IPv4, 6=IPv6 QByteArray address; quint16 port; + uint8_t socketId; // socket_id из ETCP }; struct InviteData { diff --git a/tools/chatgui/src/joindialog.cpp b/tools/chatgui/src/joindialog.cpp index 8e740b90..3d9c522b 100644 --- a/tools/chatgui/src/joindialog.cpp +++ b/tools/chatgui/src/joindialog.cpp @@ -172,6 +172,7 @@ void JoinDialog::onConnectClicked() { QByteArray addrsBuf; for (const auto& a : d.addrs) { addrsBuf.append(static_cast(a.family)); + addrsBuf.append(static_cast(a.socketId)); addrsBuf.append(a.address); addrsBuf.append(static_cast((a.port >> 8) & 0xFF)); addrsBuf.append(static_cast(a.port & 0xFF)); diff --git a/tools/chatgui/transport/chat_core.c b/tools/chatgui/transport/chat_core.c index 6b15fea8..9c9f5627 100644 --- a/tools/chatgui/transport/chat_core.c +++ b/tools/chatgui/transport/chat_core.c @@ -318,8 +318,8 @@ void chat_core_sync_my_addresses(void) { sqlite3_stmt* ins = NULL; sqlite3_prepare_v2(g_cc.db, - "INSERT OR REPLACE INTO node_addresses(node_id,family,protocol,address,port,addr_type)" - " VALUES(?,?,1,?,?,0)", -1, &ins, NULL); + "INSERT OR REPLACE INTO node_addresses(node_id,family,protocol,address,port,addr_type,socket_id)" + " VALUES(?,?,1,?,?,0,?)", -1, &ins, NULL); if (!ins) return; struct ETCP_SOCKET* sock = g_cc.inst->etcp_sockets; @@ -334,6 +334,7 @@ void chat_core_sync_my_addresses(void) { sqlite3_bind_int(ins, 2, 4); sqlite3_bind_blob(ins, 3, &sin->sin_addr, 4, SQLITE_STATIC); sqlite3_bind_int(ins, 4, (int)ntohs(sin->sin_port)); + sqlite3_bind_int(ins, 5, (int)sock->sock_id); sqlite3_step(ins); sqlite3_reset(ins); } else if (sa->ss_family == AF_INET6) { struct sockaddr_in6* sin6 = (struct sockaddr_in6*)sa; @@ -341,6 +342,7 @@ void chat_core_sync_my_addresses(void) { sqlite3_bind_int(ins, 2, 6); sqlite3_bind_blob(ins, 3, &sin6->sin6_addr, 16, SQLITE_STATIC); sqlite3_bind_int(ins, 4, (int)ntohs(sin6->sin6_port)); + sqlite3_bind_int(ins, 5, (int)sock->sock_id); sqlite3_step(ins); sqlite3_reset(ins); } sock = sock->next; @@ -611,17 +613,19 @@ void chat_core_connect_from_invite(struct chat_invite* inv) { } sqlite3_stmt* is = NULL; if (sqlite3_prepare_v2(g_cc.db, - "INSERT INTO node_addresses(node_id,family,protocol,address,port,addr_type)" - " VALUES(?,?,1,?,?,0)", -1, &is, NULL) == SQLITE_OK) { + "INSERT INTO node_addresses(node_id,family,protocol,address,port,addr_type,socket_id)" + " VALUES(?,?,1,?,?,0,?)", -1, &is, NULL) == SQLITE_OK) { const uint8_t* src = inv->addrs_data; for (int i = 0; i < inv->addr_count; i++) { uint8_t family = *src++; + uint8_t sid = *src++; if (family == 4) { sqlite3_bind_int64(is, 1, (sqlite3_int64)node_id); sqlite3_bind_int(is, 2, 4); sqlite3_bind_blob(is, 3, src, 4, SQLITE_STATIC); src += 4; uint16_t port = ((uint16_t)src[0] << 8) | src[1]; src += 2; sqlite3_bind_int(is, 4, (int)port); + sqlite3_bind_int(is, 5, (int)sid); sqlite3_step(is); sqlite3_reset(is); } else { src += 18; @@ -1003,11 +1007,12 @@ void chat_core_create_channel(struct chat_channel_create* req) { if (!sa) sa = s->local_addr.ss_family ? &s->local_addr : NULL; if (sa && sa->ss_family == AF_INET) { struct sockaddr_in* sin = (struct sockaddr_in*)sa; - my_addrs[my_addr_cnt * 7] = 4; - memcpy(my_addrs + my_addr_cnt * 7 + 1, &sin->sin_addr, 4); + my_addrs[my_addr_cnt * 8] = 4; + my_addrs[my_addr_cnt * 8 + 1] = s->sock_id; + memcpy(my_addrs + my_addr_cnt * 8 + 2, &sin->sin_addr, 4); uint16_t port = ntohs(sin->sin_port); - my_addrs[my_addr_cnt * 7 + 5] = (uint8_t)(port >> 8); - my_addrs[my_addr_cnt * 7 + 6] = (uint8_t)(port & 0xFF); + my_addrs[my_addr_cnt * 8 + 6] = (uint8_t)(port >> 8); + my_addrs[my_addr_cnt * 8 + 7] = (uint8_t)(port & 0xFF); my_addr_cnt++; } s = s->next; diff --git a/tools/chatgui/transport/chat_sync.c b/tools/chatgui/transport/chat_sync.c index 597afc94..90b1f568 100644 --- a/tools/chatgui/transport/chat_sync.c +++ b/tools/chatgui/transport/chat_sync.c @@ -699,7 +699,7 @@ void chat_sync_connect_from_invite(uint64_t channel_id, uint64_t node_id, inv->node_id = node_id; memcpy(inv->pubkey, pubkey_bin, 32); - size_t addrs_sz = (size_t)addr_count * 7; + size_t addrs_sz = (size_t)addr_count * 8; inv->addrs_data = u_malloc(addrs_sz); if (!inv->addrs_data) { u_free(inv); return; } memcpy(inv->addrs_data, addrs_data, addrs_sz); @@ -933,12 +933,13 @@ static void cs_handle_channel_info_resp(struct chat_sync* cs, uint64_t peer, struct sockaddr_in* sin = (struct sockaddr_in*)&lk->remote_addr; uint8_t ip[4]; memcpy(ip, &sin->sin_addr, 4); uint16_t port = ntohs(sin->sin_port); char sql[256]; snprintf(sql, sizeof(sql), - "INSERT OR REPLACE INTO node_addresses(node_id,family,address,port,addr_type) VALUES(?,4,?,?,0)"); + "INSERT OR REPLACE INTO node_addresses(node_id,family,address,port,addr_type,socket_id) VALUES(?,4,?,?,0,?)"); sqlite3_stmt* as = NULL; if (sqlite3_prepare_v2(vdb, sql, -1, &as, NULL) == SQLITE_OK) { sqlite3_bind_int64(as, 1, (sqlite3_int64)peer); sqlite3_bind_blob(as, 2, ip, 4, SQLITE_STATIC); sqlite3_bind_int(as, 3, port); + sqlite3_bind_int(as, 4, (int)lk->conn->sock_id); sqlite3_step(as); sqlite3_finalize(as); DEBUG_DEBUG(DEBUG_CATEGORY_DB_SYNC, "%s: saved inviter addr peer=%016llx %d.%d.%d.%d:%d", CS_ID, (unsigned long long)peer, ip[0], ip[1], ip[2], ip[3], port); @@ -991,8 +992,9 @@ static void cs_handle_channel_info_resp(struct chat_sync* cs, uint64_t peer, else { sock = sock->next; continue; } if (sa->ss_family == AF_INET) { struct sockaddr_in* sin = (struct sockaddr_in*)sa; - if (joff + 7 > sizeof(jbuf)) break; + if (joff + 8 > sizeof(jbuf)) break; jbuf[joff++] = 4; + jbuf[joff++] = sock->sock_id; memcpy(jbuf + joff, &sin->sin_addr, 4); joff += 4; uint16_t p = ntohs(sin->sin_port); jbuf[joff++] = (uint8_t)((p >> 8) & 0xFF); @@ -1000,8 +1002,9 @@ static void cs_handle_channel_info_resp(struct chat_sync* cs, uint64_t peer, addr_cnt++; } else if (sa->ss_family == AF_INET6) { struct sockaddr_in6* sin6 = (struct sockaddr_in6*)sa; - if (joff + 19 > sizeof(jbuf)) break; + if (joff + 20 > sizeof(jbuf)) break; jbuf[joff++] = 6; + jbuf[joff++] = sock->sock_id; memcpy(jbuf + joff, &sin6->sin6_addr, 16); joff += 16; uint16_t p = ntohs(sin6->sin6_port); jbuf[joff++] = (uint8_t)((p >> 8) & 0xFF); @@ -1066,22 +1069,24 @@ static void cs_handle_channel_join(struct chat_sync* cs, uint64_t peer, } /* save/update node addresses */ - for (uint8_t i = 0; i < addr_cnt && p + 1 <= pl + len; i++) { + for (uint8_t i = 0; i < addr_cnt && p + 2 <= pl + len; i++) { uint8_t fm = *p++; + uint8_t sid = *p++; int ip_len = (fm == 4) ? 4 : 16; if (p + ip_len + 2 > pl + len) break; const uint8_t* ip = p; p += ip_len; uint16_t port = ((uint16_t)p[0] << 8) | p[1]; p += 2; char sql[256]; snprintf(sql, sizeof(sql), - "INSERT OR REPLACE INTO node_addresses(node_id,family,address,port,addr_type)" - " VALUES(?,?,?,?,0)"); + "INSERT OR REPLACE INTO node_addresses(node_id,family,address,port,addr_type,socket_id)" + " VALUES(?,?,?,?,0,?)"); sqlite3_stmt* stmt = NULL; if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) == SQLITE_OK) { sqlite3_bind_int64(stmt, 1, (sqlite3_int64)node_id); sqlite3_bind_int(stmt, 2, fm); sqlite3_bind_blob(stmt, 3, ip, ip_len, SQLITE_STATIC); sqlite3_bind_int(stmt, 4, (int)port); + sqlite3_bind_int(stmt, 5, (int)sid); sqlite3_step(stmt); sqlite3_finalize(stmt); } } @@ -1189,27 +1194,29 @@ static void cs_handle_welcome(struct chat_sync* cs, uint64_t peer, topo_node_sqlite_node_update_verified(db, node_id, peer_name, x25519, ed_pub, join_ts); for (uint8_t j = 0; j < ac; j++) { - if (p + 1 > pl + len) break; + if (p + 2 > pl + len) break; uint8_t fm = *p++; + uint8_t sid = *p++; int ip_len = (fm == 4) ? 4 : 16; if (p + ip_len + 2 > pl + len) break; const uint8_t* ip = p; p += ip_len; uint16_t port = ((uint16_t)p[0] << 8) | p[1]; p += 2; char sql[256]; snprintf(sql, sizeof(sql), - "INSERT OR REPLACE INTO node_addresses(node_id,family,address,port,addr_type)" - " VALUES(?,?,?,?,0)"); + "INSERT OR REPLACE INTO node_addresses(node_id,family,address,port,addr_type,socket_id)" + " VALUES(?,?,?,?,0,?)"); sqlite3_stmt* stmt = NULL; if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) == SQLITE_OK) { sqlite3_bind_int64(stmt, 1, (sqlite3_int64)node_id); sqlite3_bind_int(stmt, 2, fm); sqlite3_bind_blob(stmt, 3, ip, ip_len, SQLITE_STATIC); sqlite3_bind_int(stmt, 4, (int)port); + sqlite3_bind_int(stmt, 5, (int)sid); sqlite3_step(stmt); sqlite3_finalize(stmt); - } - member_sync_cancel(g_cs->inst, peer, ch_id); - member_sync_set_online(g_cs->inst, peer, 0); -} + } + } + member_sync_cancel(g_cs->inst, peer, ch_id); + member_sync_set_online(g_cs->inst, peer, 0); } cs_refresh_channels(cs); @@ -1283,22 +1290,24 @@ static void cs_handle_peer_upsert(struct chat_sync* cs, uint64_t peer, } for (uint8_t i = 0; i < ac; i++) { - if (p + 1 > pl + len) break; + if (p + 2 > pl + len) break; uint8_t fm = *p++; + uint8_t sid = *p++; int ip_len = (fm == 4) ? 4 : 16; if (p + ip_len + 2 > pl + len) break; const uint8_t* ip = p; p += ip_len; uint16_t port = ((uint16_t)p[0] << 8) | p[1]; p += 2; char sql[256]; snprintf(sql, sizeof(sql), - "INSERT OR REPLACE INTO node_addresses(node_id,family,address,port,addr_type)" - " VALUES(?,?,?,?,0)"); + "INSERT OR REPLACE INTO node_addresses(node_id,family,address,port,addr_type,socket_id)" + " VALUES(?,?,?,?,0,?)"); sqlite3_stmt* stmt = NULL; if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) == SQLITE_OK) { sqlite3_bind_int64(stmt, 1, (sqlite3_int64)node_id); sqlite3_bind_int(stmt, 2, fm); sqlite3_bind_blob(stmt, 3, ip, ip_len, SQLITE_STATIC); sqlite3_bind_int(stmt, 4, (int)port); + sqlite3_bind_int(stmt, 5, (int)sid); sqlite3_step(stmt); sqlite3_finalize(stmt); } } diff --git a/tools/chatgui/transport/member_sync.c b/tools/chatgui/transport/member_sync.c index d78e53b1..0cfb8ee1 100644 --- a/tools/chatgui/transport/member_sync.c +++ b/tools/chatgui/transport/member_sync.c @@ -165,18 +165,20 @@ static int _member_get_items(void* ctx, const char* ns, uint8_t level, sqlite3_stmt* as = NULL; sqlite3_prepare_v2(db, - "SELECT family, address, port FROM node_addresses WHERE node_id=? AND addr_type=0" + "SELECT family, socket_id, address, port FROM node_addresses WHERE node_id=? AND addr_type=0" " ORDER BY family, address, port", -1, &as, NULL); uint8_t addrs[2048]; int addr_off = 0; int addr_count = 0; if (as) { sqlite3_bind_int64(as, 1, (sqlite3_int64)nid); - while (sqlite3_step(as) == SQLITE_ROW && addr_off < (int)sizeof(addrs) - 7) { + while (sqlite3_step(as) == SQLITE_ROW && addr_off < (int)sizeof(addrs) - 8) { int fam = sqlite3_column_int(as, 0); + int sid = sqlite3_column_int(as, 1); addrs[addr_off++] = (uint8_t)fam; + addrs[addr_off++] = (uint8_t)sid; int ip_sz = fam == 4 ? 4 : 16; - memcpy(addrs + addr_off, sqlite3_column_blob(as, 1), (size_t)ip_sz); + memcpy(addrs + addr_off, sqlite3_column_blob(as, 2), (size_t)ip_sz); addr_off += ip_sz; - uint16_t p = (uint16_t)sqlite3_column_int(as, 2); + uint16_t p = (uint16_t)sqlite3_column_int(as, 3); addrs[addr_off++] = (uint8_t)(p >> 8); addrs[addr_off++] = (uint8_t)(p & 0xFF); addr_count++; @@ -243,8 +245,9 @@ static int _member_apply_items(void* ctx, const char* ns, uint8_t ac = *mp++; mrem--; const uint8_t* addrs = mp; int consumed = 0; - for (int a = 0; a < (int)ac && mrem >= (size_t)(1 + consumed); a++) { + for (int a = 0; a < (int)ac && mrem >= (size_t)(2 + consumed); a++) { uint8_t fam = mp[consumed]; consumed++; + uint8_t sid = mp[consumed]; consumed++; int sz = fam == 4 ? 4 : 16; consumed += sz + 2; } @@ -336,18 +339,21 @@ int member_sync_put(struct UTUN_INSTANCE* inst, const char* ch_id, sqlite3_stmt* as = NULL; sqlite3_prepare_v2(db, - "INSERT INTO node_addresses(node_id,family,protocol,address,port,addr_type)" - " VALUES(?,?,1,?,?,0)", -1, &as, NULL); + "INSERT INTO node_addresses(node_id,family,protocol,address,port,addr_type,socket_id)" + " VALUES(?,?,1,?,?,0,?)", -1, &as, NULL); if (as) { const uint8_t* p = addrs_data; for (int i = 0; i < addr_count; i++) { - uint8_t fam = *p++; int ip_sz = fam == 4 ? 4 : 16; + uint8_t fam = *p++; + uint8_t sid = *p++; + int ip_sz = fam == 4 ? 4 : 16; sqlite3_bind_int64(as, 1, (sqlite3_int64)member_id); sqlite3_bind_int(as, 2, fam); sqlite3_bind_blob(as, 3, p, ip_sz, SQLITE_STATIC); p += ip_sz; uint16_t port = ((uint16_t)p[0] << 8) | p[1]; p += 2; sqlite3_bind_int(as, 4, port); + sqlite3_bind_int(as, 5, (int)sid); sqlite3_step(as); sqlite3_reset(as); } sqlite3_finalize(as); diff --git a/tools/chatgui/transport/utun_node.cpp b/tools/chatgui/transport/utun_node.cpp index ff02718a..1518c702 100644 --- a/tools/chatgui/transport/utun_node.cpp +++ b/tools/chatgui/transport/utun_node.cpp @@ -117,6 +117,7 @@ QList UtunNode::getInviteAddresses(DbManager* db) { while (link) { if (link->link_state == 3 && link->nat_type == NAT_TYPE_DIRECT) { NodeAddr a; + a.socketId = link->conn ? (int)link->conn->sock_id : 0; struct sockaddr_storage* sa = &link->remote_addr; if (sa->ss_family == AF_INET) { struct sockaddr_in* sin = (struct sockaddr_in*)sa; @@ -149,6 +150,7 @@ QList UtunNode::getInviteAddresses(DbManager* db) { else { sock = sock->next; continue; } NodeAddr a; + a.socketId = (int)sock->sock_id; if (sa->ss_family == AF_INET) { struct sockaddr_in* sin = (struct sockaddr_in*)sa; a.family = 4;