Acknowledge PM media submissions after local commit or preparation failure
This commit is contained in:
1 parent
dae19c06d7
commit
4fd5ebf57a
3 files changed
+13
-4
No files matched your search
+7
-2
@@ -52,6 +52,7 @@ struct dm_file_job {
|
||||
char input[1024], cipher[1024], plain[1024], temp[1024], output[1024];
|
||||
int error;
|
||||
uint64_t generation;
|
||||
uint64_t request_id;
|
||||
unsigned held;
|
||||
};
|
||||
|
||||
@@ -567,6 +568,7 @@ static void dm_file_done(void* arg, int error) {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_DM, "dm_media: prepared conv=%s bytes=%llu name=%s", job->conv,
|
||||
(unsigned long long)job->size, job->info.name);
|
||||
chat_event_attachment(inst, 1, job->conv, job->id, 1);
|
||||
chat_event_submitted(inst, job->request_id, 1);
|
||||
dm_job_free(job);
|
||||
return;
|
||||
}
|
||||
@@ -627,6 +629,7 @@ fail:
|
||||
DEBUG_WARN(DEBUG_CATEGORY_DM, "dm_media: file task failed/cancelled work=%d error=%d worker=%d closing=%d",
|
||||
job->work, error, job->error, media->closing);
|
||||
if (job->work == DM_FILE_PREPARE) {
|
||||
chat_event_submitted(inst, job->request_id, 0);
|
||||
chat_event_attachment(inst, 1, job->conv, job->id, 2);
|
||||
dm_file_remove(job->plain); dm_file_remove(job->cipher);
|
||||
if (job->remove_source) dm_file_remove(job->input);
|
||||
@@ -718,7 +721,7 @@ static int dm_file_lookup(void* arg, uint64_t group, uint64_t peer, const uint8_
|
||||
|
||||
/* Путь исходника копируется; caller может освободить строку после возврата. */
|
||||
int dm_send_file(struct UTUN_INSTANCE* inst, const char* conv, const char* path, const struct attachment_info* info,
|
||||
int remove_source) {
|
||||
int remove_source, uint64_t request_id) {
|
||||
struct dm_media_state* media = inst ? inst->dm_media : NULL;
|
||||
if (!media || media->closing || !inst->media_async || !conv || !path || attachment_validate(info) || strlen(path) >= 1024) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_DM, "dm_media: invalid file send arguments/state");
|
||||
@@ -731,6 +734,7 @@ int dm_send_file(struct UTUN_INSTANCE* inst, const char* conv, const char* path,
|
||||
if (!job) { DEBUG_ERROR(DEBUG_CATEGORY_DM, "dm_media: preparation allocation failed"); return -1; }
|
||||
job->media = media; job->work = DM_FILE_PREPARE; job->author = inst->node_id;
|
||||
job->generation = dm_history_generation(inst, conv);
|
||||
job->request_id = request_id;
|
||||
if (!dm_history_current(inst, conv, job->generation)) { u_free(job); return -1; }
|
||||
snprintf(job->conv, sizeof(job->conv), "%s", conv); job->info = *info; job->remove_source = remove_source;
|
||||
snprintf(job->input, sizeof(job->input), "%s", path);
|
||||
@@ -775,8 +779,9 @@ void dm_send_file_trampoline(void* arg) {
|
||||
if (!req) return;
|
||||
uint64_t generation = req->generation ? req->generation : dm_history_generation(req->inst, req->conv);
|
||||
int current = dm_history_current(req->inst, req->conv, generation);
|
||||
if (!current || dm_send_file(req->inst, req->conv, req->path, &req->info, req->remove_source)) {
|
||||
if (!current || dm_send_file(req->inst, req->conv, req->path, &req->info, req->remove_source, req->request_id)) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_DM, "DM files: send rejected conv=%s generation=%llu", req->conv, (unsigned long long)generation);
|
||||
chat_event_submitted(req->inst, req->request_id, 0);
|
||||
const uint8_t rejected[16] = {0};
|
||||
if (current) chat_event_attachment(req->inst, 1, req->conv, rejected, 2);
|
||||
if (req->remove_source) {
|
||||
|
||||
+4
-2
@@ -56,13 +56,15 @@ void dm_media_destroy(struct UTUN_INSTANCE* inst);
|
||||
* готовность/ошибка подготовки сообщается CHAT_EVT_ATTACHMENT_PREPARATION, включая до возврата 0.
|
||||
* Беседа должна быть видимой; до 4 одновременных подготовок, plaintext до DM_MEDIA_MAX_SIZE.
|
||||
* remove_source=1 передаёт worker собственный временный файл приложения для удаления; при -1 его убирает caller.
|
||||
* Успех подготовки означает commit file-сообщения, не доставку. Пользовательский исходник: remove_source=0. */
|
||||
* Успех подготовки означает commit file-сообщения, не доставку. Пользовательский исходник: remove_source=0.
|
||||
* request_id!=0 получает CHAT_EVT_MSG_SUBMITTED после commit/ошибки; при возврате -1 событие посылает caller. */
|
||||
int dm_send_file(struct UTUN_INSTANCE* inst, const char* conv, const char* path, const struct attachment_info* info,
|
||||
int remove_source);
|
||||
int remove_source, uint64_t request_id);
|
||||
struct dm_file_req {
|
||||
struct UTUN_INSTANCE* inst; /* Заимствованное ядро до callback. */
|
||||
char conv[64]; /* Десятичный ID беседы с NUL. */
|
||||
uint64_t generation; /* Ожидаемое поколение; 0=захватить при входе в uasync. */
|
||||
uint64_t request_id; /* Корреляция результата локального commit, 0=без подтверждения. */
|
||||
char path[1024]; /* Путь исходника с NUL; копируется при принятии. */
|
||||
struct attachment_info info; /* Проверенные метаданные вложения. */
|
||||
int remove_source; /* Только принадлежащий приложению временный файл. */
|
||||
|
||||
@@ -108,11 +108,13 @@ static void attachment_publish(struct attachment_send_req* req, int error) {
|
||||
if (file) {
|
||||
file->inst = req->inst; file->info = req->info; file->remove_source = 1;
|
||||
file->generation = req->dm_generation;
|
||||
file->request_id = req->request_id;
|
||||
snprintf(file->conv, sizeof(file->conv), "%s", req->target);
|
||||
snprintf(file->path, sizeof(file->path), "%s", req->output);
|
||||
dm_send_file_trampoline(file);
|
||||
} else {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "attachment: PM dispatch allocation failed");
|
||||
chat_event_submitted(req->inst, req->request_id, 0);
|
||||
chat_event_attachment(req->inst, req->is_dm, req->target, req->id, 2);
|
||||
if (remove(req->output)) DEBUG_WARN(DEBUG_CATEGORY_MEDIA, "attachment: rejected output cleanup failed");
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user