From 3e0b9483b7a6ed5e636d2481d41402b28f378d2d Mon Sep 17 00:00:00 2001 From: Evgeny Date: Sat, 18 Jul 2026 02:46:53 +0300 Subject: [PATCH] fix chatgui: channel persistence & peer list after restart - chat_core_sync_my_addresses(): remove private IP filter (192.168, 10.x, etc.) so LAN addresses are stored for direct connections - topo_node_sqlite_channel_peers_all(): include peers without addresses in WELCOME message (was skipped entirely, causing empty peer list) - chat_core_create_channel(): pass real local addresses to member_sync_put() instead of NULL,0 - chat_core_init(): log number of channels loaded from DB on startup --- src/topo_node_sqlite.c | 12 +++++++---- tools/chatgui/transport/chat_core.c | 31 +++++++++++++++++++---------- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/src/topo_node_sqlite.c b/src/topo_node_sqlite.c index 6d67f6a6..499ec8eb 100644 --- a/src/topo_node_sqlite.c +++ b/src/topo_node_sqlite.c @@ -380,13 +380,17 @@ int topo_node_sqlite_channel_peers_all(sqlite3* db, const char* channel_id, addr_cnt++; } sqlite3_finalize(ast); - if (addr_cnt == 0) continue; size_t peer_needed = 8 + 32 + 32 + 1 + 64 + 8 + 64 + 8 + 1 + (size_t)nl + 1; size_t addr_sz = off - addr_start; - if (off + peer_needed > buf_sz) { sqlite3_finalize(stmt); return -2; } - memmove(buf + addr_start + peer_needed, buf + addr_start, addr_sz); - off = addr_start; + if (addr_cnt > 0) { + if (off + peer_needed > buf_sz) { sqlite3_finalize(stmt); return -2; } + memmove(buf + addr_start + peer_needed, buf + addr_start, addr_sz); + off = addr_start; + } else { + if (off + peer_needed + 1 > buf_sz) { sqlite3_finalize(stmt); return -2; } + addr_sz = 0; + } memcpy(buf + off, &node_id, 8); off += 8; memcpy(buf + off, x25519, 32); off += 32; memcpy(buf + off, ed_pub, 32); off += 32; diff --git a/tools/chatgui/transport/chat_core.c b/tools/chatgui/transport/chat_core.c index e8696515..1d2ecd8f 100644 --- a/tools/chatgui/transport/chat_core.c +++ b/tools/chatgui/transport/chat_core.c @@ -200,11 +200,13 @@ int chat_core_init(struct UTUN_INSTANCE* inst, const char* db_path) { sqlite3_stmt* stmt = NULL; if (sqlite3_prepare_v2(g_cc.db, "SELECT channel_id FROM channels ORDER BY created_at ASC", -1, &stmt, NULL) == SQLITE_OK) { + int loaded = 0; while (sqlite3_step(stmt) == SQLITE_ROW) { const char* ch = (const char*)sqlite3_column_text(stmt, 0); - if (ch && ch[0]) chat_core_ensure_channel_ready(ch); + if (ch && ch[0]) { chat_core_ensure_channel_ready(ch); loaded++; } } sqlite3_finalize(stmt); + DEBUG_INFO(DEBUG_CATEGORY_CONNECTIVITY, "%s: loaded %d channels from DB", CC_ID, loaded); } } @@ -322,12 +324,6 @@ void chat_core_sync_my_addresses(void) { if (sa->ss_family == AF_INET) { struct sockaddr_in* sin = (struct sockaddr_in*)sa; - uint8_t b0 = (uint8_t)(ntohl(sin->sin_addr.s_addr) >> 24); - if (b0 == 10 || b0 == 127 || - (b0 == 172 && ((ntohl(sin->sin_addr.s_addr) >> 20) & 0xF0) == 16) || - (b0 == 192 && (uint8_t)(ntohl(sin->sin_addr.s_addr) >> 16) == 168) || - (b0 == 169 && (uint8_t)(ntohl(sin->sin_addr.s_addr) >> 16) == 254)) - { sock = sock->next; continue; } sqlite3_bind_int64(ins, 1, (sqlite3_int64)g_cc.my_node_id); sqlite3_bind_int(ins, 2, 4); sqlite3_bind_blob(ins, 3, &sin->sin_addr, 4, SQLITE_STATIC); @@ -335,8 +331,6 @@ void chat_core_sync_my_addresses(void) { sqlite3_step(ins); sqlite3_reset(ins); } else if (sa->ss_family == AF_INET6) { struct sockaddr_in6* sin6 = (struct sockaddr_in6*)sa; - if (sin6->sin6_addr.s6_addr[0] == 0xFE && (sin6->sin6_addr.s6_addr[1] & 0xC0) == 0x80) - { sock = sock->next; continue; } sqlite3_bind_int64(ins, 1, (sqlite3_int64)g_cc.my_node_id); sqlite3_bind_int(ins, 2, 6); sqlite3_bind_blob(ins, 3, &sin6->sin6_addr, 16, SQLITE_STATIC); @@ -982,9 +976,26 @@ void chat_core_create_channel(struct chat_channel_create* req) { } else { memset(join_sig, 0, 64); } + uint8_t my_addrs[256]; int my_addr_cnt = 0; + { struct ETCP_SOCKET* s = g_cc.inst->etcp_sockets; + while (s && my_addr_cnt < 16) { + struct sockaddr_storage* sa = s->interface_addr.ss_family ? &s->interface_addr : NULL; + 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); + 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_addr_cnt++; + } + s = s->next; + } + } int mrc = member_sync_put(g_cc.inst, req->channel_id, myid, g_cc.inst->my_keys.public_key, g_cc.inst->my_ed25519_pubkey, - join_sig, join_ts, NULL, 0, g_cc.inst->name, NULL, 0); + join_sig, join_ts, NULL, 0, g_cc.inst->name, my_addrs, my_addr_cnt); if (mrc != 0) { DEBUG_ERROR(DEBUG_CATEGORY_CONNECTIVITY, "%s: member_sync_put(self) FAILED ch=%s rc=%d", CC_ID, req->channel_id, mrc);