diff --git a/src/chat/chat_core_priv.h b/src/chat/chat_core_priv.h index 40b7355a..186fc0be 100644 --- a/src/chat/chat_core_priv.h +++ b/src/chat/chat_core_priv.h @@ -19,6 +19,7 @@ #include #define CC_ID "chat_core" +#define CHAT_MEDIA_BACKFILL_CHANNELS 16 /* ── Base64 encode/decode (URL-safe, used for msg "d" field prefix) ── */ @@ -100,7 +101,7 @@ struct chat_core_ctx { int media_backfill_ran; /* was chat_msg.c g_media_startup_backfill_ran */ struct UTUN_INSTANCE* media_backfill_inst; /* was chat_msg.c g_media_startup_backfill_inst */ void* media_channel_backfill_timer; /* ограниченный batch докачки/восстановления индекса через 2с от первой заявки */ - char media_channel_backfill[16][64]; /* pending ch_id */ + char media_channel_backfill[CHAT_MEDIA_BACKFILL_CHANNELS][64]; /* pending ch_id */ int media_channel_backfill_pending; void* attachment_timer; int attachment_closing; diff --git a/src/chat/chat_msg.c b/src/chat/chat_msg.c index 0291e6c0..b36cbdae 100644 --- a/src/chat/chat_msg.c +++ b/src/chat/chat_msg.c @@ -752,7 +752,11 @@ static int msg_read_id(struct chat_core_ctx* cc, const char* channel, int64_t id const void* key = sqlite3_column_blob(st, 0); if (key) { memcpy(message_id, key, 32); result = 0; } } - sqlite3_finalize(st); + int final_rc = sqlite3_finalize(st); + if (final_rc != SQLITE_OK) { + DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "media identity finalize failed ch=%s id=%lld rc=%d", channel, (long long)id, final_rc); + result = -1; + } if (result) DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "media identity missing ch=%s id=%lld rc=%d: %s", channel, (long long)id, rc, sqlite3_errmsg(cc->db)); return result; @@ -1227,7 +1231,7 @@ void chat_media_backfill(struct UTUN_INSTANCE* inst) { char tbl[80]; msg_table_name(ch_id, tbl, sizeof(tbl)); char sql[256]; - snprintf(sql, sizeof(sql), "SELECT data FROM \"%s\"", tbl); + snprintf(sql, sizeof(sql), "SELECT data,message_id,node_id FROM \"%s\"", tbl); sqlite3_stmt* ms = NULL; if (sqlite3_prepare_v2(cc->db, sql, -1, &ms, NULL) != SQLITE_OK) continue; @@ -1260,6 +1264,22 @@ void chat_media_backfill(struct UTUN_INSTANCE* inst) { content_type[i] = '\0'; } + int encrypted_attachment = !strcmp(content_type, ENCRYPTED_ATTACHMENT_TYPE); + uint8_t message[32]; + if (encrypted_attachment) { + if (sqlite3_column_bytes(ms, 1) != 32 || !sqlite3_column_blob(ms, 1)) { + DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "media startup: missing encrypted message identity ch=%s", ch_id); + media_index_result_free(&result); u_free(body); continue; + } + memcpy(message, sqlite3_column_blob(ms, 1), 32); + int observed = chat_attachment_observe(inst, ch_id, message, (uint64_t)sqlite3_column_int64(ms, 2), jdata, + (size_t)sqlite3_column_bytes(ms, 0)); + if (observed) { + if (observed == -1) media_queue_channel_backfill(inst, ch_id); + media_index_result_free(&result); u_free(body); continue; + } + } + char base_filename[256]; extract_base_filename(body, base_filename, sizeof(base_filename)); char final_name[256]; @@ -1277,6 +1297,8 @@ void chat_media_backfill(struct UTUN_INSTANCE* inst) { int registered = media_index_commit(cc->db, &result, cc->my_node_id, NULL, ch_id, path, media_base); if (!registered) total += result.num_blocks; else DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "media backfill registration failed ch=%s file=%s", ch_id, path); + if (encrypted_attachment && !registered && chat_attachment_downloaded(inst, ch_id, message)) + media_queue_channel_backfill(inst, ch_id); u_free(body); media_index_result_free(&result); @@ -1882,7 +1904,7 @@ static void media_channel_backfill_timer_cb(void* arg) { struct chat_core_ctx* cc = CC(inst); if (!cc) return; cc->media_channel_backfill_timer = NULL; - char channels[16][64]; int count = cc->media_channel_backfill_pending; + char channels[CHAT_MEDIA_BACKFILL_CHANNELS][sizeof(cc->media_channel_backfill[0])]; int count = cc->media_channel_backfill_pending; memcpy(channels, cc->media_channel_backfill, (size_t)count * sizeof(channels[0])); cc->media_channel_backfill_pending = 0; for (int i = 0; i < count; i++) chat_media_autodownload_backfill_channel(inst, channels[i]); diff --git a/src/utun_instance.c b/src/utun_instance.c index cffcd397..dca0afae 100644 --- a/src/utun_instance.c +++ b/src/utun_instance.c @@ -848,8 +848,8 @@ int chat_service_start(struct UTUN_INSTANCE* instance) { if (chat_attachment_init(instance) < 0) goto fail; if (member_files_init(instance) < 0 || dm_mailbox_init(instance) < 0 || dm_core_init(instance) < 0 || dm_media_init(instance) < 0 || call_init(instance) < 0 || radio_call_init(instance) < 0) goto fail; - chat_media_backfill(instance); chat_media_startup_backfill_init(instance); + chat_media_backfill(instance); /* Все headless listeners используют IPv4:port; port=0 выбирает ОС. Ошибка отключает только этот listener. */ const struct { const char* bind;