From 2dbc45e63def911fd607224c785e508f540e29a3 Mon Sep 17 00:00:00 2001 From: evgeny Date: Thu, 29 Oct 2026 09:35:32 +0100 Subject: [PATCH] Transfer Android ordinary attachment caches to the shared media worker --- .../libutun_lite/attachment_sender.c | 99 +++++-------------- .../libutun_lite/attachment_sender.h | 11 ++- 2 files changed, 29 insertions(+), 81 deletions(-) diff --git a/tools/chatgui-android/libutun_lite/attachment_sender.c b/tools/chatgui-android/libutun_lite/attachment_sender.c index d14bc719..5f2dc5e7 100644 --- a/tools/chatgui-android/libutun_lite/attachment_sender.c +++ b/tools/chatgui-android/libutun_lite/attachment_sender.c @@ -1,93 +1,40 @@ +/* Обычный picker-файл: общий worker владеет cache и подтверждает публикацию. */ +#include +#include #include "attachment_sender.h" #include "instance_lite.h" #include "../../../lib/debug_config.h" #include "../../../lib/mem.h" #include "../../../lib/u_async.h" -#include "../../../src/chat/chat_core.h" -#include -#include -#include -#include -#include -#include -#include +#include "../../../src/media_async/attachment_send.h" int attachment_send(const char* channel_id, const char* src_file_path, const char* db_path, const uint8_t reply_to[32], uint64_t request_id) { - if (!channel_id || !src_file_path || !db_path) { - DEBUG_ERROR(DEBUG_CATEGORY_GENERAL, "attachment_send: invalid args"); - return -1; - } - + (void)db_path; struct UASYNC* ua = instance_lite_get_uasync(); - if (!uasync_is_running(ua)) { DEBUG_ERROR(DEBUG_CATEGORY_GENERAL, "attachment_send: core stopped"); return -1; } - - /* get original basename for display, then make unique filename for storage */ - char path_copy[1024]; - snprintf(path_copy, sizeof(path_copy), "%s", src_file_path); - char* fname = basename(path_copy); - char original_basename[256]; - snprintf(original_basename, sizeof(original_basename), "%s", fname); - char* dot = strrchr(fname, '.'); - char ext[32] = ""; - if (dot) { snprintf(ext, sizeof(ext), "%s", dot + 1); *dot = '\0'; } - - struct stat st; memset(&st, 0, sizeof(st)); - stat(src_file_path, &st); - - /* generate dt/suffix for unique filename */ - time_t t = time(NULL); - struct tm tm_buf; localtime_r(&t, &tm_buf); - char dt[32]; snprintf(dt, sizeof(dt), "%04d%02d%02d-%02d%02d%02d", - tm_buf.tm_year + 1900, tm_buf.tm_mon + 1, tm_buf.tm_mday, - tm_buf.tm_hour, tm_buf.tm_min, tm_buf.tm_sec); - int rnd = rand() & 0xFFFF; - char suffix[8]; snprintf(suffix, sizeof(suffix), "%04x", rnd); - - /* ensure media dir exists */ - char media_dir[1024]; - snprintf(media_dir, sizeof(media_dir), "%s/media/%s", db_path, channel_id); - { - char tmp[1024]; size_t off = 0; - for (size_t i = 0; media_dir[i] && off < sizeof(tmp) - 1; i++) { - tmp[off++] = media_dir[i]; - if (media_dir[i] == '/' && off > 1) { tmp[off] = '\0'; mkdir(tmp, 0755); } - } - tmp[off] = '\0'; - mkdir(tmp, 0755); + if (!channel_id || !src_file_path || !reply_to || strlen(channel_id) >= 64 || strlen(src_file_path) >= 1024 || + !uasync_is_running(ua)) { + DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "attachment_send: invalid arguments/stopped core"); return -1; } - - /* single file path — no splitting */ - char media_file[1280]; - snprintf(media_file, sizeof(media_file), "%s/%s_%s_%s.%s", - media_dir, dt, fname, suffix, ext[0] ? ext : "bin"); - - /* post chat_msg_submit — media_copy=1 so media_index copies src to dest - data = original_basename — becomes first part of message "d" field: "name.ext|size|..." */ - size_t datalen = strlen(original_basename); - struct chat_msg_submit* req = u_calloc(1, sizeof(struct chat_msg_submit) + datalen + 1); + const char* name = strrchr(src_file_path, '/'); name = name ? name + 1 : src_file_path; + struct attachment_send_req* req = u_calloc(1, sizeof(*req)); struct posted_task* post = u_calloc(1, sizeof(*post)); if (!req || !post) { DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "attachment_send: allocation failed"); u_free(req); u_free(post); return -1; } - - req->inst = instance_lite_get_instance(); - memcpy(req->reply_to, reply_to, sizeof(req->reply_to)); - req->request_id = request_id; - snprintf(req->channel_id, sizeof(req->channel_id), "%s", channel_id); - snprintf(req->content_type, sizeof(req->content_type), "application/octet-stream"); - snprintf(req->media_src, sizeof(req->media_src), "%s", src_file_path); - snprintf(req->media_dest, sizeof(req->media_dest), "%s", media_file); - req->media_copy = 1; - req->data = (uint8_t*)(req + 1); - memcpy(req->data, original_basename, datalen); - req->data_len = (uint32_t)datalen; - req->timestamp = 0; - - DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "attachment_send: ch=%s src=%s dst=%s name=%s size=%lld", - channel_id, src_file_path, media_file, original_basename, (long long)st.st_size); - - post->callback = chat_core_submit_trampoline; post->arg = req; + if (strlen(name) >= sizeof(req->info.name)) { + DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "attachment_send: filename too long"); u_free(req); u_free(post); return -1; + } + req->inst = instance_lite_get_instance(); req->info.kind = ATTACHMENT_FILE; + snprintf(req->info.name, sizeof(req->info.name), "%s", name); + if (attachment_validate(&req->info)) { u_free(req); u_free(post); return -1; } + snprintf(req->target, sizeof(req->target), "%s", channel_id); + snprintf(req->source, sizeof(req->source), "%s", src_file_path); + memcpy(req->reply_to, reply_to, sizeof(req->reply_to)); req->request_id = request_id; + req->temporary_source = 1; + DEBUG_INFO(DEBUG_CATEGORY_MEDIA, "attachment_send: accepted channel=%s source=%s request=%llu", + channel_id, src_file_path, (unsigned long long)request_id); + post->callback = attachment_send_trampoline; post->arg = req; uasync_post_reserved(ua, post); return 0; } diff --git a/tools/chatgui-android/libutun_lite/attachment_sender.h b/tools/chatgui-android/libutun_lite/attachment_sender.h index 6943865b..89130f3d 100644 --- a/tools/chatgui-android/libutun_lite/attachment_sender.h +++ b/tools/chatgui-android/libutun_lite/attachment_sender.h @@ -1,7 +1,8 @@ -/* Android-обёртка отправки обычного файла в канал через chat_core_submit_trampoline. - * Строит имя назначения в db_path/media/channel_id, копирование/индексацию выполняет media_index. +/* Android-обёртка отправки обычного cache-файла в канал через общий attachment_send worker. + * Назначение выбирает ядро, копирование/индексация выполняются вне UI. * 0 = запрос поставлен в uasync, -1 = отказ подготовки, результат публикации — CHAT_EVT_MSG_SUBMITTED. - * Вызовы сериализовать со stop/restart ядра; строки копируются, исходный файл нужен неизменным до завершения media-задачи. */ + * При 0 worker забирает собственный временный файл caller и удаляет также при ошибке/отмене. + * При -1 файл остаётся caller. Вызовы сериализовать со stop/restart ядра; строки копируются. */ #ifndef ATTACHMENT_SENDER_H #define ATTACHMENT_SENDER_H #include @@ -10,9 +11,9 @@ extern "C" { #endif -/* channel_id — десятичный ID канала, db_path — каталог БД; пути/строки NUL-терминированы. +/* channel_id — десятичный ID канала, db_path не используется; пути/строки NUL-терминированы. * reply_to обязательно указывает на 32 байта (нули = без ответа), request_id коррелирует результат с UI. - * Источник остаётся у caller и здесь не удаляется; MIME application/octet-stream, имя — basename источника. */ + * MIME application/octet-stream, имя — UTF-8 basename источника. Пользовательский исходник сначала копировать в cache. */ int attachment_send(const char* channel_id, const char* src_file_path, const char* db_path, const uint8_t reply_to[32], uint64_t request_id);