Expose live radio subscriptions in member updates
This commit is contained in:
1 parent
81d71690c2
commit
9dd2dffc80
3 files changed
+33
-8
No files matched your search
+21
-4
@@ -2,7 +2,7 @@
|
||||
* chat_member.c — единый код запроса мемберов для GUI
|
||||
*
|
||||
* Используется: chatgui (desktop), headless CLI, Android.
|
||||
* Все три потребителя получают данные через chat_core_get_member_list().
|
||||
* Live-состояние участников читается только в uasync-потоке.
|
||||
*/
|
||||
|
||||
#include "chat_core_priv.h"
|
||||
@@ -32,6 +32,16 @@ int chat_core_member_online(struct UTUN_INSTANCE* inst, const char* ch_id, uint6
|
||||
return topo_node_find_by_id(g, node_id) != NULL;
|
||||
}
|
||||
|
||||
/* Рация — живая подписка на конкретную CHAT-группу; у self нет записи в group->nodes. */
|
||||
static uint8_t member_radio_flag(struct UTUN_INSTANCE* inst, const char* ch_id, uint64_t node_id) {
|
||||
if (!inst || !inst->topo_groups || !ch_id || !ch_id[0]) return 0;
|
||||
struct TOPO_GROUP* group = topo_groups_find(inst->topo_groups, strtoull(ch_id, NULL, 10));
|
||||
if (!group || group->group_type != TOPO_GROUP_TYPE_CHAT) return 0;
|
||||
if (node_id == inst->node_id) return group->radio_active ? CHAT_MEMBER_FLAG_RADIO : 0;
|
||||
struct TOPO_GROUP_NODE* node = topo_node_find_by_id(group, node_id);
|
||||
return node && node->radio ? CHAT_MEMBER_FLAG_RADIO : 0;
|
||||
}
|
||||
|
||||
/* ─── парсинг adm_tags в flags ─── */
|
||||
|
||||
static uint8_t parse_adm_tags_flags(const char* adm_tags) {
|
||||
@@ -138,7 +148,7 @@ int chat_core_get_member_list(struct UTUN_INSTANCE* inst, const char* ch_id, uin
|
||||
const char* adm_tags = (const char*)sqlite3_column_text(st, 3);
|
||||
m->storage = (uint8_t)sqlite3_column_int(st, 4);
|
||||
m->is_self = (uint8_t)(m->node_id == my_id ? 1 : 0);
|
||||
m->flags = parse_adm_tags_flags(adm_tags);
|
||||
m->flags = parse_adm_tags_flags(adm_tags) | member_radio_flag(inst, ch_id, m->node_id);
|
||||
if (sqlite3_column_int(st, 5)) m->flags |= CHAT_MEMBER_FLAG_DELETED;
|
||||
m->rtt = 0xFFFF;
|
||||
m->nat_type = 0xFF;
|
||||
@@ -253,7 +263,7 @@ int chat_core_get_single_member(struct UTUN_INSTANCE* inst, const char* ch_id, u
|
||||
const char* adm_tags = (const char*)sqlite3_column_text(st, 2);
|
||||
m.storage = (uint8_t)sqlite3_column_int(st, 3);
|
||||
m.is_self = (uint8_t)(node_id == my_id ? 1 : 0);
|
||||
m.flags = parse_adm_tags_flags(adm_tags);
|
||||
m.flags = parse_adm_tags_flags(adm_tags) | member_radio_flag(inst, ch_id, node_id);
|
||||
if (sqlite3_column_int(st, 4)) m.flags |= CHAT_MEMBER_FLAG_DELETED;
|
||||
m.rtt = 0xFFFF;
|
||||
m.nat_type = 0xFF;
|
||||
@@ -374,8 +384,15 @@ static void on_member_props_changed(uint64_t node_id, const char* adm_tags, cons
|
||||
evt[0] = (uint8_t)cl;
|
||||
memcpy(evt + 1, channel_id, cl);
|
||||
evt[1 + cl] = 1;
|
||||
if (chat_core_get_single_member(inst, channel_id, node_id, evt + 1 + cl + 1) == 0)
|
||||
if (chat_core_get_single_member(inst, channel_id, node_id, evt + 1 + cl + 1) == 0) {
|
||||
const uint8_t* member = evt + 1 + cl + 1;
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_CHAT_SYNC, "chat_member: update ch=%s node=%016llx online=%u self=%u radio=%u",
|
||||
channel_id, (unsigned long long)node_id, member[8], member[9], !!(member[10] & CHAT_MEMBER_FLAG_RADIO));
|
||||
chat_event_post(inst, CHAT_EVT_MEMBER_UPDATED, evt, 1 + (int)cl + 1 + CHAT_MEMBER_DISPLAY_SIZE);
|
||||
} else {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "chat_member: cannot build update ch=%s node=%016llx",
|
||||
channel_id, (unsigned long long)node_id);
|
||||
}
|
||||
return;
|
||||
}
|
||||
sqlite3_finalize(st);
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
* chat_member.h — единая структура мембера для отображения в GUI
|
||||
*
|
||||
* Используется chatgui (desktop), headless CLI, Android.
|
||||
* Все три потребителя получают данные через chat_core_get_member_list(),
|
||||
* а не прямыми SQL-запросами.
|
||||
* Live-снимки для всех потребителей формирует chat_core_get_member_list() в uasync-потоке.
|
||||
* Android дополняет ими свой JSON-список с расширенными свойствами участников.
|
||||
*
|
||||
* Формат на проводе (ручная сериализация, фиксированный размер 79 байт):
|
||||
* [0-7] node_id uint64_t LE
|
||||
* [8] online uint8_t
|
||||
* [9] is_self uint8_t
|
||||
* [10] flags uint8_t 0x01=supernode 0x02=admin 0x04=moder
|
||||
* [10] flags uint8_t 0x01=supernode 0x02=admin 0x04=moder 0x08=deleted 0x10=radio
|
||||
* [11-12] rtt uint16_t LE (ms, 0xFFFF=нет данных)
|
||||
* [13] nat_type uint8_t ADDR_TYPE_*
|
||||
* [14] storage uint8_t
|
||||
@@ -30,6 +30,7 @@ extern "C" {
|
||||
#define CHAT_MEMBER_FLAG_ADMIN 0x02
|
||||
#define CHAT_MEMBER_FLAG_MODER 0x04
|
||||
#define CHAT_MEMBER_FLAG_DELETED 0x08
|
||||
#define CHAT_MEMBER_FLAG_RADIO 0x10
|
||||
|
||||
#define CHAT_MEMBER_DISPLAY_SIZE 79
|
||||
|
||||
|
||||
@@ -896,7 +896,14 @@ void topo_group_set_radio(struct TOPO_GROUP* group, int on) {
|
||||
group->radio_active = v;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_BGP, "set_radio: %s grp=%016llx ch=%s",
|
||||
v ? "ON" : "OFF", (unsigned long long)group->group_id, group->channel_id);
|
||||
topo_group_update_my_nodeinfo(group->instance, group);
|
||||
if (topo_group_update_my_nodeinfo(group->instance, group) < 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "set_radio: cannot update local NODEINFO grp=%016llx ch=%s radio=%u",
|
||||
(unsigned long long)group->group_id, group->channel_id, v);
|
||||
return;
|
||||
}
|
||||
/* Свой мембер обновляется через те же подписки, что и удалённые BGP-узлы. */
|
||||
for (struct topo_node_cbk_entry* cb = group->node_cbks; cb; cb = cb->next)
|
||||
cb->fn(group, group->instance->node_id, TOPO_NODE_EVENT_UPDATE, cb->arg);
|
||||
if (group->senders_list) {
|
||||
struct ll_entry* se = group->senders_list->head;
|
||||
while (se) {
|
||||
|
||||
Reference in new issue
Block a user