Bind remaining desktop commands atomically and cancel owned attachments
This commit is contained in:
1 parent
d9abb1f025
commit
707938d503
2 files changed
+48
No files matched your search
@@ -93,6 +93,11 @@ void gui_bridge_post_uasync_fn(void (*fn)(void*), void* arg);
|
||||
/* Передать отдельный u_malloc/u_calloc-блок arg: 0 — мост принял владение, callback обязан освободить arg;
|
||||
* отмена до callback освобождает его мостом. -1 — arg остаётся вызывающему. Вложенные ресурсы не освобождаются. */
|
||||
int gui_bridge_post_uasync_owned_fn(void (*fn)(void*), void* arg);
|
||||
/* Один u_malloc-блок команды ядру; binding — адрес её поля inst внутри arg.
|
||||
* Проверка running, запись inst и enqueue выполняются под mutex. GUI не читает instance.
|
||||
* 0 передаёт владение: fn освобождает arg после исполнения, мост — при отмене.
|
||||
* -1 оставляет блок вызывающему для u_free; вложенные ресурсы этим API не поддерживаются. */
|
||||
int gui_bridge_post_bound_fn(void (*fn)(void*), void* arg, struct UTUN_INSTANCE** binding);
|
||||
|
||||
/* Команды обычного звонка: GUI не передаёт instance или heap-аргументы.
|
||||
* Под mutex моста копируют данные, привязываются к живому running-ядру и передают владение очереди.
|
||||
@@ -130,6 +135,10 @@ int gui_bridge_update_name(const char* name);
|
||||
* При -1 результата нет: вызывающий освобождает req и сам сообщает об отказе своему composer. */
|
||||
struct chat_msg_submit;
|
||||
int gui_bridge_submit_message(struct chat_msg_submit* req);
|
||||
/* Подготовка вложения: тот же контракт результата, но отмена также освобождает PCM/compressor/временный source
|
||||
* и сообщает MSG_SUBMITTED(false). При -1 caller вызывает attachment_send_discard(req). */
|
||||
struct attachment_send_req;
|
||||
int gui_bridge_submit_attachment(struct attachment_send_req* req);
|
||||
|
||||
/* Проверить наличие опубликованных uasync и instance. Только подсказка готовности, не резервация их lifetime. */
|
||||
int gui_bridge_is_uasync_ready(void);
|
||||
|
||||
@@ -27,6 +27,7 @@ extern "C" {
|
||||
#include "../../../src/dm/dm_core.h"
|
||||
#include "../../../src/call/call.h"
|
||||
#include "../../../src/radio/radio_call.h"
|
||||
#include "../../../src/media_async/attachment_send.h"
|
||||
}
|
||||
|
||||
/* ── Внутренний объект-приёмник в GUI-потоке ── */
|
||||
@@ -773,6 +774,21 @@ int gui_bridge_post_uasync_owned_fn(void (*fn)(void*), void* arg) {
|
||||
return post_command(fn, arg, true);
|
||||
}
|
||||
|
||||
/* binding указывает на поле inst самой команды; отдельного чтения указателя из GUI нет. */
|
||||
int gui_bridge_post_bound_fn(void (*fn)(void*), void* arg, struct UTUN_INSTANCE** binding) {
|
||||
std::lock_guard<std::mutex> guard(bridge_mutex);
|
||||
if (!fn || !arg || !binding || !g_inst || !g_ua || !uasync_is_running(g_ua)) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_GENERAL, "GUI core command rejected: fn=%p arg=%p binding=%p inst=%p ua=%p running=%d",
|
||||
(void*)fn, arg, (void*)binding, (void*)g_inst.load(), (void*)g_ua, uasync_is_running(g_ua)); return -1;
|
||||
}
|
||||
*binding = g_inst;
|
||||
if (post_command(fn, arg, true) < 0) {
|
||||
*binding = nullptr; DEBUG_ERROR(DEBUG_CATEGORY_GENERAL, "GUI core command queue failed: fn=%p arg=%p", (void*)fn, arg); return -1;
|
||||
}
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_GENERAL, "GUI core command queued: fn=%p inst=%p ua=%p", (void*)fn, (void*)g_inst.load(), (void*)g_ua);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Создание payload и enqueue атомарны относительно detach; GUI не читает заимствованный instance. */
|
||||
int gui_bridge_call_start(const char* channel, uint64_t peer, uint64_t call_id) {
|
||||
const size_t length = channel ? strnlen(channel, sizeof(call_start_arg::ch_id)) : 0;
|
||||
@@ -1022,6 +1038,29 @@ int gui_bridge_submit_message(struct chat_msg_submit* req) {
|
||||
return post_command(chat_core_submit_trampoline, req, true, cancel_message_submit);
|
||||
}
|
||||
|
||||
/* Отмена до native trampoline не требует живого media owner; callback освобождает весь запрос сам. */
|
||||
static void cancel_attachment_submit(void* arg) {
|
||||
auto* request = static_cast<attachment_send_req*>(arg);
|
||||
if (request->request_id) {
|
||||
uint8_t result[9] = {0};
|
||||
memcpy(result, &request->request_id, 8); gui_bridge_post(CHAT_EVT_MSG_SUBMITTED, result, sizeof(result));
|
||||
}
|
||||
attachment_send_discard(request);
|
||||
}
|
||||
|
||||
int gui_bridge_submit_attachment(struct attachment_send_req* req) {
|
||||
std::lock_guard<std::mutex> guard(bridge_mutex);
|
||||
if (!req || !g_inst || !g_ua || !uasync_is_running(g_ua)) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "attachment submission: core/request unavailable"); return -1;
|
||||
}
|
||||
req->inst = g_inst;
|
||||
if (post_command(attachment_send_trampoline, req, false, cancel_attachment_submit) < 0) {
|
||||
req->inst = nullptr; DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "attachment submission: queue allocation failed"); return -1;
|
||||
}
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_MEDIA, "attachment queued: target=%s request=%llu", req->target, (unsigned long long)req->request_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gui_bridge_is_uasync_ready(void) {
|
||||
std::lock_guard<std::mutex> guard(bridge_mutex);
|
||||
return g_ua && g_inst ? 1 : 0;
|
||||
|
||||
Reference in new issue
Block a user