Retry failed decryption after a newly verified download
This commit is contained in:
1 parent
b31f974a44
commit
78d0e3f54f
3 files changed
+19
-14
No files matched your search
@@ -988,7 +988,7 @@ fail:
|
||||
}
|
||||
|
||||
/* Автозагрузка обычного участника запрашивает доступ; storage-реплика хранит только ciphertext. */
|
||||
int chat_attachment_downloaded(struct UTUN_INSTANCE* inst, const char* channel, const uint8_t message[32]) {
|
||||
int chat_attachment_downloaded(struct UTUN_INSTANCE* inst, const char* channel, const uint8_t message[32], int verified_download) {
|
||||
if (!inst || !CC(inst) || CC(inst)->attachment_closing || !ak_channel(channel) || !message) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "attachment keys: invalid downloaded state/arguments"); return -1;
|
||||
}
|
||||
@@ -999,7 +999,7 @@ int chat_attachment_downloaded(struct UTUN_INSTANCE* inst, const char* channel,
|
||||
const char* stage = "begin downloaded";
|
||||
int rc = sqlite3_exec(db, "BEGIN IMMEDIATE /* attachment downloaded */", NULL, NULL, NULL);
|
||||
if (rc != SQLITE_OK) goto fail;
|
||||
char sql[512]; snprintf(sql, sizeof(sql), "SELECT downloaded,wanted,NOT EXISTS(SELECT 1 FROM peers_%s"
|
||||
char sql[512]; snprintf(sql, sizeof(sql), "SELECT downloaded,wanted,error,NOT EXISTS(SELECT 1 FROM peers_%s"
|
||||
" WHERE node_id=? AND source=0 AND deleted=0 AND length(adm_tags_sig)=64 AND json_extract(adm_tags,'$.storage')='yes')"
|
||||
" FROM attachment_keys WHERE channel=? AND message_id=?", channel);
|
||||
stage = "prepare download state"; rc = sqlite3_prepare_v2(db, sql, -1, &st, NULL);
|
||||
@@ -1012,20 +1012,23 @@ int chat_attachment_downloaded(struct UTUN_INSTANCE* inst, const char* channel,
|
||||
if (rc != SQLITE_OK) goto fail;
|
||||
stage = "read download state"; rc = sqlite3_step(st);
|
||||
if (rc != SQLITE_ROW) goto fail;
|
||||
int downloaded = sqlite3_column_int(st, 0), wanted = sqlite3_column_int(st, 1), automatic = sqlite3_column_int(st, 2);
|
||||
int downloaded = sqlite3_column_int(st, 0), wanted = sqlite3_column_int(st, 1), error = sqlite3_column_int(st, 2);
|
||||
int automatic = sqlite3_column_int(st, 3), desired_error = verified_download ? 0 : error;
|
||||
if ((downloaded != 0 && downloaded != 1) || (wanted != 0 && wanted != 1)) { stage = "download state"; rc = SQLITE_MISMATCH; goto fail; }
|
||||
int desired = wanted || automatic, changed_state = !downloaded || wanted != desired;
|
||||
int desired = wanted || automatic, changed_state = !downloaded || wanted != desired || error != desired_error;
|
||||
stage = "finalize download state"; rc = sqlite3_finalize(st); st = NULL;
|
||||
if (rc != SQLITE_OK) goto fail;
|
||||
if (changed_state) {
|
||||
stage = "prepare downloaded";
|
||||
rc = sqlite3_prepare_v2(db, "UPDATE attachment_keys SET downloaded=1,wanted=? WHERE channel=? AND message_id=?", -1, &st, NULL);
|
||||
rc = sqlite3_prepare_v2(db, "UPDATE attachment_keys SET downloaded=1,wanted=?,error=? WHERE channel=? AND message_id=?", -1, &st, NULL);
|
||||
if (rc != SQLITE_OK) goto fail;
|
||||
stage = "bind wanted"; rc = sqlite3_bind_int(st, 1, desired);
|
||||
if (rc != SQLITE_OK) goto fail;
|
||||
stage = "bind channel"; rc = sqlite3_bind_text(st, 2, channel, -1, SQLITE_STATIC);
|
||||
stage = "bind error"; rc = sqlite3_bind_int(st, 2, desired_error);
|
||||
if (rc != SQLITE_OK) goto fail;
|
||||
stage = "bind message"; rc = sqlite3_bind_blob(st, 3, message, 32, SQLITE_STATIC);
|
||||
stage = "bind channel"; rc = sqlite3_bind_text(st, 3, channel, -1, SQLITE_STATIC);
|
||||
if (rc != SQLITE_OK) goto fail;
|
||||
stage = "bind message"; rc = sqlite3_bind_blob(st, 4, message, 32, SQLITE_STATIC);
|
||||
if (rc != SQLITE_OK) goto fail;
|
||||
stage = "write downloaded"; rc = sqlite3_step(st);
|
||||
if (rc != SQLITE_DONE) goto fail;
|
||||
@@ -1037,7 +1040,8 @@ int chat_attachment_downloaded(struct UTUN_INSTANCE* inst, const char* channel,
|
||||
stage = "commit downloaded"; rc = sqlite3_exec(db, "COMMIT /* attachment downloaded */", NULL, NULL, NULL);
|
||||
if (rc != SQLITE_OK) goto fail;
|
||||
if (changed_state) {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_MEDIA, "attachment keys: download state committed channel=%s wanted=%d automatic=%d", channel, desired, automatic);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_MEDIA, "attachment keys: download state committed channel=%s wanted=%d automatic=%d verified=%d error=%d",
|
||||
channel, desired, automatic, verified_download != 0, desired_error);
|
||||
ak_changed(inst, channel);
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -66,10 +66,11 @@ int chat_attachment_observe(struct UTUN_INSTANCE* inst, const char* channel, con
|
||||
|
||||
// ── Получение файла и выдача доступа ──
|
||||
|
||||
/* После проверенной загрузки/наличия сохранённого контейнера: своей транзакцией сохранить downloaded и policy wanted.
|
||||
/* После загрузки/наличия сохранённого контейнера: своей транзакцией сохранить downloaded и policy wanted.
|
||||
* 0/-1; запись observe обязательна. Повтор неизменного состояния не даёт события. Криптографию проверит worker.
|
||||
* verified_download!=0 — новая проверенная передача, также сбрасывает прежний error; 0 — найденный cache, error сохраняется.
|
||||
* Внешняя транзакция запрещена, SQL-отказ сохраняет прежние поля, событие — после commit. */
|
||||
int chat_attachment_downloaded(struct UTUN_INSTANCE* inst, const char* channel, const uint8_t message[32]);
|
||||
int chat_attachment_downloaded(struct UTUN_INSTANCE* inst, const char* channel, const uint8_t message[32], int verified_download);
|
||||
|
||||
/* Ручная загрузка, включая storage: одной транзакцией установить wanted, сбросить error и ready отсутствующего cache.
|
||||
* 0/-1; запись observe обязательна. Внешняя транзакция запрещена, отказ сохраняет прежние поля. */
|
||||
|
||||
+4
-4
@@ -778,7 +778,7 @@ static void md_download_done_cb(void* arg, int err) {
|
||||
struct chat_core_ctx* cc = CC(ctx->inst);
|
||||
if (!err) {
|
||||
if (!strcmp(ctx->content_type, ENCRYPTED_ATTACHMENT_TYPE)) {
|
||||
if (chat_attachment_downloaded(ctx->inst, ctx->channel_id, ctx->message_id))
|
||||
if (chat_attachment_downloaded(ctx->inst, ctx->channel_id, ctx->message_id, 1))
|
||||
media_queue_channel_backfill(ctx->inst, ctx->channel_id);
|
||||
}
|
||||
char attrs[1024];
|
||||
@@ -1187,7 +1187,7 @@ void chat_core_attachment_download(struct UTUN_INSTANCE* inst, const char* chann
|
||||
channel_id, rc, finish, sqlite3_errmsg(cc->db)); u_free(body); return;
|
||||
}
|
||||
if (present) {
|
||||
if (chat_attachment_downloaded(inst, channel_id, message)) media_queue_channel_backfill(inst, channel_id);
|
||||
if (chat_attachment_downloaded(inst, channel_id, message, 0)) media_queue_channel_backfill(inst, channel_id);
|
||||
u_free(body); return;
|
||||
}
|
||||
}
|
||||
@@ -1297,7 +1297,7 @@ 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))
|
||||
if (encrypted_attachment && !registered && chat_attachment_downloaded(inst, ch_id, message, 0))
|
||||
media_queue_channel_backfill(inst, ch_id);
|
||||
|
||||
u_free(body);
|
||||
@@ -1416,7 +1416,7 @@ static void bf_collect(struct chat_core_ctx* cc, const char* media_base, const c
|
||||
snprintf(full_path, sizeof(full_path), "%s/media/%s/%s", media_base, ch_id, final_name);
|
||||
int64_t actual = ma_file_size(full_path);
|
||||
if (actual < 0) actual = 0;
|
||||
if (encrypted_attachment && actual > 0 && chat_attachment_downloaded(cc->inst, ch_id, message))
|
||||
if (encrypted_attachment && actual > 0 && chat_attachment_downloaded(cc->inst, ch_id, message, 0))
|
||||
media_queue_channel_backfill(cc->inst, ch_id);
|
||||
|
||||
if (l->count == l->cap) {
|
||||
|
||||
Reference in new issue
Block a user