Browse Source

fix chatgui: ensure msg table + db_sync instance on join and restart

- chat_core_ensure_channel_ready(ch_id): idempotent — creates
  msg_<id> table + registers db_sync instance if missing
- chat_core_create_channel: refactored to use ensure_channel_ready
- cs_handle_channel_info_resp: call ensure_channel_ready on join
- chat_core_init: iterate existing channels on restart
- Fixes 'no such table: msg_<id>' after invite join
- Fixes 'no db_sync instance for ch=<id>' after restart
topo_upd
Evgeny 3 months ago
parent
commit
c4751557b1
  1. 76
      tools/chatgui/transport/chat_core.c
  2. 1
      tools/chatgui/transport/chat_core.h
  3. 1
      tools/chatgui/transport/chat_sync.c

76
tools/chatgui/transport/chat_core.c

@ -200,6 +200,20 @@ int chat_core_init(struct UTUN_INSTANCE* inst, const char* db_path) {
);
g_cc.initialized = 1;
/* ensure infrastructure for all existing channels (survives restart) */
{
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) {
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);
}
sqlite3_finalize(stmt);
}
}
DEBUG_INFO(DEBUG_CATEGORY_CONNECTIVITY, "%s: initialized, db=%s node_id=0x%016llx",
CC_ID, db_path, (unsigned long long)g_cc.my_node_id);
@ -848,23 +862,16 @@ void chat_core_connect_from_invite(struct chat_invite* inv) {
}
}
/* ─── создание канала ─── */
void chat_core_create_channel(struct chat_channel_create* req) {
if (!g_cc.initialized) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTIVITY, "%s: create_channel NOT INITIALIZED ch=%s",
CC_ID, req ? req->channel_id : "(null)");
return;
}
if (!req) { DEBUG_ERROR(DEBUG_CATEGORY_CONNECTIVITY, "%s: create_channel req=NULL", CC_ID); return; }
/* ─── подготовка инфраструктуры канала (msg-таблица + db_sync instance) ─── */
DEBUG_INFO(DEBUG_CATEGORY_CONNECTIVITY, "%s: create_channel BEGIN ch=%s name=%s",
CC_ID, req->channel_id, req->name);
void chat_core_ensure_channel_ready(const char* ch_id) {
if (!g_cc.initialized || !ch_id || !ch_id[0]) return;
if (si_find(ch_id)) return;
char tbl_msg[80]; msg_table_name(req->channel_id, tbl_msg, sizeof(tbl_msg));
char tbl_msg[80]; msg_table_name(ch_id, tbl_msg, sizeof(tbl_msg));
char sql[512];
/* создаём таблицу сообщений */
char sql[512]; snprintf(sql, sizeof(sql),
snprintf(sql, sizeof(sql),
"CREATE TABLE IF NOT EXISTS \"%s\" ("
" id INTEGER PRIMARY KEY AUTOINCREMENT,"
" node_id INTEGER NOT NULL,"
@ -879,26 +886,39 @@ void chat_core_create_channel(struct chat_channel_create* req) {
" sync_flags INTEGER DEFAULT 0,"
" UNIQUE(timestamp, datahash))", tbl_msg);
db_exec(sql);
snprintf(sql, sizeof(sql),
"CREATE INDEX IF NOT EXISTS \"idx_%s_ts_dh\" ON \"%s\"(timestamp, datahash)",
tbl_msg, tbl_msg);
db_exec(sql);
/* Register with db_sync for message sync */
{
/* Compute a deterministic hash from channel_id for db_sync instance id */
uint64_t ch_hash = 0;
{ const uint8_t* chd = (const uint8_t*)req->channel_id; size_t chl = strlen(req->channel_id); uint8_t sh[32]; SHA256(chd, chl, sh); memcpy(&ch_hash, sh, 8); }
struct DB_SYNC_INSTANCE* si = db_sync_instance_add(g_cc.inst, "chats", ch_hash);
if (si) {
si_register(si, req->channel_id);
db_sync_set_insert_cb(si, on_db_sync_insert, u_strdup(req->channel_id));
DEBUG_INFO(DEBUG_CATEGORY_CONNECTIVITY, "%s: db_sync instance added for ch=%s hash=0x%016llx", CC_ID, req->channel_id, (unsigned long long)ch_hash);
} else {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTIVITY, "%s: db_sync_instance_add failed for ch=%s", CC_ID, req->channel_id);
}
uint64_t ch_hash = 0;
{ const uint8_t* chd = (const uint8_t*)ch_id; size_t chl = strlen(ch_id); uint8_t sh[32]; SHA256(chd, chl, sh); memcpy(&ch_hash, sh, 8); }
struct DB_SYNC_INSTANCE* si = db_sync_instance_add(g_cc.inst, "chats", ch_hash);
if (si) {
si_register(si, ch_id);
db_sync_set_insert_cb(si, on_db_sync_insert, u_strdup(ch_id));
DEBUG_INFO(DEBUG_CATEGORY_CONNECTIVITY, "%s: channel ready ch=%s hash=0x%016llx",
CC_ID, ch_id, (unsigned long long)ch_hash);
} else {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTIVITY, "%s: db_sync_instance_add failed for ch=%s",
CC_ID, ch_id);
}
}
/* ─── создание канала ─── */
void chat_core_create_channel(struct chat_channel_create* req) {
if (!g_cc.initialized) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTIVITY, "%s: create_channel NOT INITIALIZED ch=%s",
CC_ID, req ? req->channel_id : "(null)");
return;
}
if (!req) { DEBUG_ERROR(DEBUG_CATEGORY_CONNECTIVITY, "%s: create_channel req=NULL", CC_ID); return; }
DEBUG_INFO(DEBUG_CATEGORY_CONNECTIVITY, "%s: create_channel BEGIN ch=%s name=%s",
CC_ID, req->channel_id, req->name);
chat_core_ensure_channel_ready(req->channel_id);
/* записываем канал в БД */
int rc = topo_node_sqlite_channel_put(g_cc.db,

1
tools/chatgui/transport/chat_core.h

@ -68,6 +68,7 @@ struct chat_channel_create {
uint8_t signature[64];
};
void chat_core_ensure_channel_ready(const char* ch_id);
void chat_core_create_channel(struct chat_channel_create* req);
void chat_core_create_channel_trampoline(void* arg);

1
tools/chatgui/transport/chat_sync.c

@ -774,6 +774,7 @@ static void cs_handle_channel_info_resp(struct chat_sync* cs, uint64_t peer,
/* save channel to local DB */
topo_node_sqlite_channel_put(cs->inst->topo_groups->topo_sqlite_db,
ch_id, name, (int)is_dm, owner, x25519, NULL, ed_pub, NULL, ch_sig);
chat_core_ensure_channel_ready(ch_id);
/* verify inviter's join_sig */
{ sqlite3* vdb = cs->inst->topo_groups->topo_sqlite_db;

Loading…
Cancel
Save