Tag DM history snapshots with conversation generation

This commit is contained in:
evgeny committed 2026-10-26 22:11:39 +01:00
1 parent 07f63c3047
commit fd82e7bf1b
3 files changed
+18 -6

No files matched your search

+1 -1
View File
@@ -62,7 +62,7 @@ extern "C" {
#define CHAT_EVT_CALL_DECLINED 38 /* [call_id:8][reason:1] */
#define CHAT_EVT_CALL_STATS 39 /* [call_id:8][rtt:2][buffer:2][tempo:2][dropped:2][underruns:2][min:2][max:2][reserve:2] */
#define CHAT_EVT_CALL_ERROR 40 /* [call_id:8][err:1][text:var] */
#define CHAT_EVT_DM_MESSAGES 41 /* [conv_id_len:1][conv_id:var][JSON:utf8] — сообщения беседы и состояния доставки */
#define CHAT_EVT_DM_MESSAGES 41 /* [conv_id_len:1][conv_id:var][generation:8][JSON:utf8] — история указанного поколения */
#define CHAT_EVT_CALL_PATH 42 /* [call_id:8][text:var] — BGP-маршрут до пира звонка */
#define CHAT_EVT_RADIO_TALK 43 /* [group_id:8][src_node_id:8][stream_id:2][on:1] — кто-то начал/закончил говорить */
#define CHAT_EVT_CALL_CONNECTION 44 /* [call_id:8][CONN_TYPE:1][next_hop_node_id:8] — текущий путь отправки звонка */
+14 -4
View File
@@ -1310,19 +1310,29 @@ void dm_call_route_trampoline(void* arg) {
/* Ограниченный JSON-снимок доставляется GUI асинхронно, без доступа UI к instance/SQLite. */
void dm_messages_trampoline(void* arg) {
struct dm_messages_req* req = arg;
if (!req) return;
if (!req) { DEBUG_ERROR(DEBUG_CATEGORY_DM, "%s: missing history request", DM_ID); return; }
struct UTUN_INSTANCE* inst = req->inst;
char conv[64];
snprintf(conv, sizeof(conv), "%s", req->conv_id);
uint64_t generation = req->generation;
u_free(req);
if (!dm_of(inst)) { DEBUG_WARN(DEBUG_CATEGORY_DM, "%s: snapshot after stop", DM_ID); return; }
if (!generation) generation = dm_history_generation(inst, conv);
if (!dm_history_current(inst, conv, generation)) {
DEBUG_INFO(DEBUG_CATEGORY_DM, "%s: skipped stale history conv=%s generation=%llu", DM_ID, conv,
(unsigned long long)generation); return;
}
size_t cl = strlen(conv), cap = 1024 * 1024, len = 0;
uint8_t* evt = u_malloc(1 + cl + cap);
uint8_t* evt = u_malloc(9 + cl + cap);
if (!evt) { DEBUG_ERROR(DEBUG_CATEGORY_DM, "%s: snapshot allocation failed", DM_ID); return; }
evt[0] = (uint8_t)cl;
memcpy(evt + 1, conv, cl);
if (!dm_list_messages_json(inst, conv, 200, 0, (char*)evt + 1 + cl, cap, &len))
chat_event_post(inst, CHAT_EVT_DM_MESSAGES, evt, (int)(1 + cl + len));
memcpy(evt + 1 + cl, &generation, 8);
if (!dm_list_messages_json(inst, conv, 200, 0, (char*)evt + 9 + cl, cap, &len)) {
DEBUG_DEBUG(DEBUG_CATEGORY_DM, "%s: history snapshot conv=%s generation=%llu bytes=%zu", DM_ID, conv,
(unsigned long long)generation, len);
chat_event_post(inst, CHAT_EVT_DM_MESSAGES, evt, (int)(9 + cl + len));
}
u_free(evt);
}
+3 -1
View File
@@ -161,10 +161,12 @@ struct dm_invite_req {
void dm_invite_trampoline(void* arg);
/* Запросить последние 200 сообщений со статусами. CHAT_EVT_DM_MESSAGES:
* [conv_id_len:1][conv_id:var][JSON:utf8]. Все чтения в uasync. */
* [conv_id_len:1][conv_id:var][generation:8][JSON:utf8]. Все чтения в uasync.
* Ненулевое generation проверяется до чтения; 0 захватывает текущее поколение. GUI отбрасывает старый снимок. */
struct dm_messages_req {
struct UTUN_INSTANCE* inst;
char conv_id[64];
uint64_t generation; /* Поколение выбранного PM; для запроса маршрута не используется. */
};
void dm_messages_trampoline(void* arg);
/* Живой BGP-маршрут PM; group_id=0 в снимке означает недоступность. Все вызовы в uasync. */