|
|
|
|
@ -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, |
|
|
|
|
|