Authorize call channels and stop revoked calls immediately

This commit is contained in:
evgeny committed 2026-11-04 01:42:20 +01:00
1 parent 8633b35388
commit d83ab168cb
2 files changed
+41 -2

No files matched your search

+34 -2
View File
@@ -161,7 +161,7 @@ static int call_send_invite(struct call_ctx* ctx, struct call_session* s) {
int call_resolve_targets(struct UTUN_INSTANCE* inst, uint64_t group, uint64_t peer, int devices,
uint64_t* out, unsigned capacity) {
struct TOPO_GROUP* g = inst && inst->topo_groups ? topo_groups_find(inst->topo_groups, group) : NULL;
if (!g || g->group_type != TOPO_GROUP_TYPE_CHAT || !peer || !out || !capacity) {
if (!g || !topo_group_chat_allowed(inst, group, peer) || !peer || !out || !capacity) {
DEBUG_WARN(DEBUG_CATEGORY_CALL, "call target invalid group=%llx peer=%llx", (unsigned long long)group, (unsigned long long)peer);
return -1;
}
@@ -424,6 +424,11 @@ static void call_target_tick(void* arg) {
for (unsigned i = 0; i < s->target_count; ++i) {
struct call_target* t = &s->targets[i];
if (!t->end_subcmd || t->ack) continue;
if (!topo_group_chat_allowed(s->ctx->inst, s->group_id, t->peer)) {
DEBUG_DEBUG(DEBUG_CATEGORY_CALL, "call target retry cancelled after revoke id=%llx peer=%llx",
(unsigned long long)s->call_id, (unsigned long long)t->peer);
t->ack = 1; continue;
}
if (now - t->ended_tb >= CALL_END_TIMEOUT_TB) {
DEBUG_WARN(DEBUG_CATEGORY_CALL, "call target end timeout id=%llx peer=%llx",
(unsigned long long)s->call_id, (unsigned long long)t->peer);
@@ -516,6 +521,30 @@ static void call_end(struct call_ctx* ctx, struct call_session* s, uint8_t reaso
call_session_remove_and_free(ctx, s);
}
void call_revalidate_members(struct UTUN_INSTANCE* inst, uint64_t group) {
struct call_ctx* ctx = call_of(inst);
struct ll_entry* e = ctx && ctx->sessions ? ctx->sessions->head : NULL;
while (e) {
struct call_session* s = (struct call_session*)e->data;
e = e->next;
if (s->group_id != group) continue;
int allowed = topo_group_chat_allowed(inst, group, s->peer_node_id);
for (unsigned i = 0; i < s->target_count; ++i) {
struct call_target* t = &s->targets[i];
if (topo_group_chat_allowed(inst, group, t->peer)) continue;
t->ack = 1;
if (!s->selected && t->state != CALL_ST_ENDED) allowed = 0;
}
if (allowed) continue;
DEBUG_INFO(DEBUG_CATEGORY_CALL, "call access revoked id=%llx group=%llx peer=%llx state=%s; stopping media and retries",
(unsigned long long)s->call_id, (unsigned long long)group,
(unsigned long long)s->peer_node_id, call_state_name(s->state));
if (s->cm_handle) { conn_mgr_close(s->cm_handle); s->cm_handle = NULL; }
s->end_subcmd = 0;
call_end(ctx, s, CALL_REASON_CONNECT_FAIL, 0);
}
}
/* ─────────────────── conn_mgr ─────────────────── */
static void call_traffic_timeout_cb(void* arg);
@@ -1114,8 +1143,10 @@ int call_init(struct UTUN_INSTANCE* inst) {
ctx->initialized = 1;
if (etcp_router_require_crypto(inst, ETCP_RT_ID_CALL, ROUTE_CRYPTO_SIGN | ROUTE_CRYPTO_ENCRYPT)
|| etcp_router_set_authorize(inst, ETCP_RT_ID_CALL, topo_group_chat_allowed)
|| etcp_router_bind(inst, ETCP_RT_ID_CALL_AUDIO, call_etcp_recv)
|| etcp_router_require_crypto(inst, ETCP_RT_ID_CALL_AUDIO, ROUTE_CRYPTO_SIGN | ROUTE_CRYPTO_ENCRYPT)
|| etcp_router_set_authorize(inst, ETCP_RT_ID_CALL_AUDIO, topo_group_chat_allowed)
|| call_video_transport_bind(inst)) {
DEBUG_ERROR(DEBUG_CATEGORY_CALL, "call media channel bind failed");
call_destroy(inst); return -1;
@@ -1165,8 +1196,9 @@ int call_busy(struct UTUN_INSTANCE* inst) {
/* Только uasync: проверка доступности перед созданием сессии; очереди групп не межпоточные. */
static int call_is_online(struct UTUN_INSTANCE* inst, const char* ch_id, uint64_t peer_node_id) {
if (!inst || !ch_id || !ch_id[0] || !inst->topo_groups) return 0;
if (peer_node_id == inst->node_id) return 1;
uint64_t group_id = strtoull(ch_id, NULL, 10);
if (!topo_group_chat_allowed(inst, group_id, peer_node_id)) return 0;
if (peer_node_id == inst->node_id) return 1;
struct TOPO_GROUP* g = topo_groups_find(inst->topo_groups, group_id);
if (!g) return 0;
return topo_node_find_by_id(g, peer_node_id) != NULL;
+7
View File
@@ -7,6 +7,9 @@
// CHAT-группы или из DM (group_id — группа маршрутизации, как в dm_core).
// Сигналинг, аудио и видео идут через etcp_router с обязательными ROUTE_CRYPTO_SIGN|ENCRYPT; соединение
// оптимизируется через параллельные пробы conn_mgr (DIRECT/REVERSE/INDIRECT).
// Оба узла должны оставаться допущенными участниками группы доставки. При отзыве доступа
// или остановке группы звонок завершается, очереди медиа очищаются. Группа активного звонка
// не меняется; новый звонок из DM заново выбирает доступную общую группу через dm_call_route.
//
// Все функции, кроме явно отмеченных, — в uasync-потоке. GUI/headless вызывают через trampoline
// (gui_bridge_post_uasync_fn / uasync_post).
@@ -34,6 +37,10 @@ int call_init(struct UTUN_INSTANCE* inst);
* Регистрация call_audio_ops у ядра сохраняется, DSP и устройства frontend здесь не освобождаются. */
void call_destroy(struct UTUN_INSTANCE* inst);
/* uasync: после изменения участников/остановки CHAT-группы завершить затронутые звонки
* с CONNECT_FAIL, отменить их медиа/CM/повторы отозванным пирам. Остальные группы не затрагивает. */
void call_revalidate_members(struct UTUN_INSTANCE* inst, uint64_t group);
// ── сигналинг (uasync-поток) ──
/* Caller: ch_id — группа либо "dm:<conv_id>" (BGP-группа выбирается при запуске).