Browse Source

sqlite: add cache_size/mmap_size/temp_store PRAGMAs to db_sync and topo_group — 159x insert speedup, fix test_chat_sync_stress timeout

topo_upd
Evgeny 3 months ago
parent
commit
20f5e6c953
  1. 3
      src/db_sync.c
  2. 5
      src/topo_group.c
  3. 66
      src/topo_node_sqlite.c
  4. 1
      tools/chatgui/db/db_manager.h
  5. 6
      tools/chatgui/src/invite_link.cpp
  6. 1
      tools/chatgui/src/invite_link.h
  7. 1
      tools/chatgui/src/joindialog.cpp
  8. 21
      tools/chatgui/transport/chat_core.c
  9. 37
      tools/chatgui/transport/chat_sync.c
  10. 22
      tools/chatgui/transport/member_sync.c
  11. 2
      tools/chatgui/transport/utun_node.cpp

3
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;
}

5
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 {

66
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);
}
/* 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, "DELETE FROM node_addresses WHERE node_id=?", -1, &del_stmt, NULL) == SQLITE_OK) {
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);

1
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 {

6
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<char>(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<char>(addrs[i + j].socketId));
blob.append(addrs[i + j].address);
quint16 p = addrs[i + j].port;
blob.append(static_cast<char>((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<const char*>(data + off), ipLen);
off += ipLen;

1
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 {

1
tools/chatgui/src/joindialog.cpp

@ -172,6 +172,7 @@ void JoinDialog::onConnectClicked() {
QByteArray addrsBuf;
for (const auto& a : d.addrs) {
addrsBuf.append(static_cast<char>(a.family));
addrsBuf.append(static_cast<char>(a.socketId));
addrsBuf.append(a.address);
addrsBuf.append(static_cast<char>((a.port >> 8) & 0xFF));
addrsBuf.append(static_cast<char>(a.port & 0xFF));

21
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;

37
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);
}
}
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);
}
}

22
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);

2
tools/chatgui/transport/utun_node.cpp

@ -117,6 +117,7 @@ QList<NodeAddr> 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<NodeAddr> 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;

Loading…
Cancel
Save