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; 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", 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); 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) {
} }
} }
/* ─── создание канала ─── */ /* ─── подготовка инфраструктуры канала (msg-таблица + db_sync instance) ─── */
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", void chat_core_ensure_channel_ready(const char* ch_id) {
CC_ID, req->channel_id, req->name); 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];
/* создаём таблицу сообщений */ snprintf(sql, sizeof(sql),
char sql[512]; snprintf(sql, sizeof(sql),
"CREATE TABLE IF NOT EXISTS \"%s\" (" "CREATE TABLE IF NOT EXISTS \"%s\" ("
" id INTEGER PRIMARY KEY AUTOINCREMENT," " id INTEGER PRIMARY KEY AUTOINCREMENT,"
" node_id INTEGER NOT NULL," " node_id INTEGER NOT NULL,"
@ -879,26 +886,39 @@ void chat_core_create_channel(struct chat_channel_create* req) {
" sync_flags INTEGER DEFAULT 0," " sync_flags INTEGER DEFAULT 0,"
" UNIQUE(timestamp, datahash))", tbl_msg); " UNIQUE(timestamp, datahash))", tbl_msg);
db_exec(sql); db_exec(sql);
snprintf(sql, sizeof(sql), snprintf(sql, sizeof(sql),
"CREATE INDEX IF NOT EXISTS \"idx_%s_ts_dh\" ON \"%s\"(timestamp, datahash)", "CREATE INDEX IF NOT EXISTS \"idx_%s_ts_dh\" ON \"%s\"(timestamp, datahash)",
tbl_msg, tbl_msg); tbl_msg, tbl_msg);
db_exec(sql); db_exec(sql);
/* Register with db_sync for message sync */ 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); }
/* Compute a deterministic hash from channel_id for db_sync instance id */ struct DB_SYNC_INSTANCE* si = db_sync_instance_add(g_cc.inst, "chats", ch_hash);
uint64_t ch_hash = 0; if (si) {
{ 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); } si_register(si, ch_id);
struct DB_SYNC_INSTANCE* si = db_sync_instance_add(g_cc.inst, "chats", ch_hash); db_sync_set_insert_cb(si, on_db_sync_insert, u_strdup(ch_id));
if (si) { DEBUG_INFO(DEBUG_CATEGORY_CONNECTIVITY, "%s: channel ready ch=%s hash=0x%016llx",
si_register(si, req->channel_id); CC_ID, ch_id, (unsigned long long)ch_hash);
db_sync_set_insert_cb(si, on_db_sync_insert, u_strdup(req->channel_id)); } else {
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); DEBUG_ERROR(DEBUG_CATEGORY_CONNECTIVITY, "%s: db_sync_instance_add failed for ch=%s",
} else { CC_ID, ch_id);
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTIVITY, "%s: db_sync_instance_add failed for ch=%s", CC_ID, req->channel_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, 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]; 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(struct chat_channel_create* req);
void chat_core_create_channel_trampoline(void* arg); 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 */ /* save channel to local DB */
topo_node_sqlite_channel_put(cs->inst->topo_groups->topo_sqlite_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); 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 */ /* verify inviter's join_sig */
{ sqlite3* vdb = cs->inst->topo_groups->topo_sqlite_db; { sqlite3* vdb = cs->inst->topo_groups->topo_sqlite_db;

Loading…
Cancel
Save