Preserve durable publication and restore evicted decrypted files
This commit is contained in:
1 parent
3c395dfe5d
commit
feb327afc7
2 files changed
+25
-6
No files matched your search
@@ -123,12 +123,10 @@ static void ak_file_work(void* arg) {
|
||||
if (ak_parent(job->plain) || ak_parent(job->cipher)) return;
|
||||
snprintf(job->temporary, sizeof(job->temporary), "%s.part", job->encrypt ? job->cipher : job->plain);
|
||||
if (job->encrypt) {
|
||||
if (ma_copy_file(job->source, job->plain) || encrypted_file_sync(job->plain) ||
|
||||
if (ma_copy_file(job->source, job->plain) || encrypted_file_sync(job->plain) || encrypted_file_sync_directory(job->plain) ||
|
||||
encrypted_file_write(job->plain, job->temporary, job->key, job->author, job->id, &job->info, job->type)) return;
|
||||
} else if (encrypted_file_read(job->cipher, job->temporary, job->key, job->author, job->id, job->hash, &job->info, job->type)) return;
|
||||
if (rename(job->temporary, job->encrypt ? job->cipher : job->plain)) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "attachment keys: publish failed: %s", strerror(errno)); return;
|
||||
}
|
||||
if (encrypted_file_publish(job->temporary, job->encrypt ? job->cipher : job->plain)) return;
|
||||
job->error = 0;
|
||||
}
|
||||
|
||||
@@ -182,7 +180,10 @@ static void ak_file_done(void* arg, int error) {
|
||||
if (remove(job->plain) && errno != ENOENT) DEBUG_WARN(DEBUG_CATEGORY_MEDIA, "attachment keys: deleted channel plaintext cleanup failed");
|
||||
if (job->encrypt && remove(job->cipher) && errno != ENOENT) DEBUG_WARN(DEBUG_CATEGORY_MEDIA, "attachment keys: deleted channel ciphertext cleanup failed");
|
||||
}
|
||||
if (valid) ak_changed(inst, job->channel);
|
||||
if (valid) {
|
||||
if (success && !job->encrypt) chat_media_cache_enforce(inst);
|
||||
ak_changed(inst, job->channel);
|
||||
}
|
||||
OPENSSL_cleanse(job->key, 32); u_free(job);
|
||||
}
|
||||
|
||||
@@ -440,6 +441,19 @@ void chat_attachment_decision_trampoline(void* arg) {
|
||||
|
||||
/* Пользовательский интерес хранится отдельно от фоновой storage-копии. */
|
||||
void chat_attachment_want(struct UTUN_INSTANCE* inst, const char* channel, const uint8_t message[32]) {
|
||||
sqlite3_stmt* check = ak_prepare(inst, "SELECT plain_path FROM attachment_keys WHERE channel=? AND message_id=? AND ready=1");
|
||||
if (!check) return;
|
||||
sqlite3_bind_text(check, 1, channel, -1, SQLITE_STATIC); sqlite3_bind_blob(check, 2, message, 32, SQLITE_STATIC);
|
||||
int result = sqlite3_step(check), missing = result == SQLITE_ROW && ma_file_size((const char*)sqlite3_column_text(check, 0)) < 0;
|
||||
sqlite3_finalize(check);
|
||||
if (result != SQLITE_ROW && result != SQLITE_DONE) { DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "attachment keys: cache lookup failed rc=%d", result); return; }
|
||||
if (missing) {
|
||||
sqlite3_stmt* reset = ak_prepare(inst, "UPDATE attachment_keys SET ready=0 WHERE channel=? AND message_id=? AND decrypting=0");
|
||||
if (!reset) return;
|
||||
sqlite3_bind_text(reset, 1, channel, -1, SQLITE_STATIC); sqlite3_bind_blob(reset, 2, message, 32, SQLITE_STATIC);
|
||||
if (ak_step(inst, reset)) return;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_MEDIA, "attachment keys: decrypted cache missing, restoring from retained key channel=%s", channel);
|
||||
}
|
||||
sqlite3_stmt* st = ak_prepare(inst, "UPDATE attachment_keys SET wanted=1,error=0 WHERE channel=? AND message_id=?");
|
||||
if (!st) return;
|
||||
sqlite3_bind_text(st, 1, channel, -1, SQLITE_STATIC); sqlite3_bind_blob(st, 2, message, 32, SQLITE_STATIC); ak_step(inst, st);
|
||||
@@ -545,6 +559,7 @@ int chat_attachment_init(struct UTUN_INSTANCE* inst) {
|
||||
"command INTEGER NOT NULL,retry_at INTEGER NOT NULL DEFAULT 0,PRIMARY KEY(channel,message_id,peer));"
|
||||
"UPDATE attachment_keys SET decrypting=0; UPDATE attachment_key_outbox SET retry_at=0;")) return -1;
|
||||
CC(inst)->attachment_closing = 0;
|
||||
CC(inst)->attachment_initialized = 1;
|
||||
if (etcp_router_bind(inst, ETCP_RT_ID_ATTACHMENT_KEYS, ak_receive)) return -1;
|
||||
CC(inst)->attachment_timer = uasync_set_timeout(inst->ua, 10000, inst, ak_tick, "attachment keys");
|
||||
if (!CC(inst)->attachment_timer) { DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "attachment keys: initial timer allocation failed"); return -1; }
|
||||
@@ -553,7 +568,7 @@ int chat_attachment_init(struct UTUN_INSTANCE* inst) {
|
||||
|
||||
/* Сначала снять сеть/таймер, потом дождаться workers с живым chat_core. */
|
||||
void chat_attachment_quiesce(struct UTUN_INSTANCE* inst) {
|
||||
if (!CC(inst)) return;
|
||||
if (!CC(inst) || !CC(inst)->attachment_initialized || CC(inst)->attachment_closing) return;
|
||||
CC(inst)->attachment_closing = 1;
|
||||
if (CC(inst)->attachment_timer) uasync_cancel_timeout(inst->ua, CC(inst)->attachment_timer);
|
||||
CC(inst)->attachment_timer = NULL;
|
||||
@@ -567,6 +582,7 @@ void chat_attachment_destroy(struct UTUN_INSTANCE* inst) {
|
||||
|
||||
/* Удаление ключей отменяет completion активных workers; они удалят свои результаты. */
|
||||
void chat_attachment_delete_channel(struct UTUN_INSTANCE* inst, const char* channel) {
|
||||
if (!CC(inst) || !CC(inst)->attachment_initialized) return;
|
||||
sqlite3_stmt* st = ak_prepare(inst, "SELECT plain_path FROM attachment_keys WHERE channel=?");
|
||||
if (st) {
|
||||
sqlite3_bind_text(st, 1, channel, -1, SQLITE_STATIC); int rc;
|
||||
|
||||
@@ -100,6 +100,7 @@ struct chat_core_ctx {
|
||||
int media_channel_backfill_pending;
|
||||
void* attachment_timer;
|
||||
int attachment_closing;
|
||||
int attachment_initialized;
|
||||
};
|
||||
|
||||
/* Per-instance chat context. inst->chat_core обязателен после chat_core_init. */
|
||||
@@ -122,6 +123,8 @@ void on_msg_inserted(struct DB_SYNC_INSTANCE* si, const uint8_t message_id[32],
|
||||
const char* data, size_t len, uint64_t author, int initial_sync, void* arg);
|
||||
/* Разобрать подписанный manifest канального медиа; result освобождается media_index_result_free. */
|
||||
int chat_msg_parse_media_body(const char* body, struct media_index_result* result);
|
||||
/* Учесть также расшифрованные производные файлы и применить общую квоту кеша. */
|
||||
void chat_media_cache_enforce(struct UTUN_INSTANCE* inst);
|
||||
|
||||
/* ── применить настройку group_autoconnect ко всем CHAT-группам (chat_channel.c) ── */
|
||||
|
||||
|
||||
Reference in new issue
Block a user