dm: resolve service roles independently of delivery routes

This commit is contained in:
evgeny committed 2026-11-03 22:11:46 +01:00
1 parent 307ca10733
commit 3c58fc80e3
2 files changed
+41

No files matched your search

+36
View File
@@ -33,6 +33,7 @@
#include "../../lib/debug_config.h"
#include "../../lib/platform_compat.h"
#include "../../lib/strbuf.h"
#include "../../lib/json_flat.h"
#include <string.h>
#include <stdlib.h>
@@ -153,6 +154,41 @@ int dm_route_group(struct UTUN_INSTANCE* inst, uint64_t peer, uint64_t preferred
return dm_find_route_group(inst, peer, preferred, group_id, 0);
}
int dm_peer_role(struct UTUN_INSTANCE* inst, uint64_t peer, const char* role) {
if (!inst || !inst->topo_sqlite_db || !peer || !role || !role[0]) {
DEBUG_ERROR(DEBUG_CATEGORY_DM, "DM role: invalid lookup peer=%llu", (unsigned long long)peer); return 0;
}
uint64_t* groups = NULL;
int count = 0, allowed = 0;
if (topo_node_sqlite_get_member_channels(inst->topo_sqlite_db, inst->node_id, &groups, &count)) {
DEBUG_ERROR(DEBUG_CATEGORY_DM, "DM role: membership lookup failed peer=%llu", (unsigned long long)peer); return 0;
}
for (int i = 0; i < count; i++) {
if (!topo_group_chat_allowed(inst, groups[i], peer)) continue;
char sql[192], value[16];
snprintf(sql, sizeof(sql), "SELECT adm_tags FROM \"peers_%llu\""
" WHERE node_id=? AND source=0 AND deleted=0 AND admitted=1", (unsigned long long)groups[i]);
sqlite3_stmt* st = NULL;
int rc = sqlite3_prepare_v2(inst->topo_sqlite_db, sql, -1, &st, NULL);
if (rc == SQLITE_OK) rc = sqlite3_bind_int64(st, 1, (sqlite3_int64)peer);
if (rc == SQLITE_OK) rc = sqlite3_step(st);
const char* tags = rc == SQLITE_ROW ? (const char*)sqlite3_column_text(st, 0) : NULL;
allowed = tags && !json_flat_get(tags, role, value, sizeof(value)) && !strcmp(value, "yes");
int final = sqlite3_finalize(st);
if ((rc != SQLITE_ROW && rc != SQLITE_DONE) || final != SQLITE_OK) {
DEBUG_ERROR(DEBUG_CATEGORY_DM, "DM role: lookup failed peer=%llu group=%llu role=%s rc=%d final=%d",
(unsigned long long)peer, (unsigned long long)groups[i], role, rc, final);
allowed = 0; break;
}
if (allowed) {
DEBUG_TRACE(DEBUG_CATEGORY_DM, "DM role: admitted peer=%llu role=%s group=%llu",
(unsigned long long)peer, role, (unsigned long long)groups[i]); break;
}
}
u_free(groups);
return allowed;
}
/* Router владеет entry после вызова, в том числе при ошибке. */
static int dm_route_send(struct dm_state* dm, uint64_t group_id, uint64_t dst, uint8_t subcmd,
const uint8_t* body, size_t body_len) {
+5
View File
@@ -62,6 +62,11 @@ static inline int dm_msg_len(const uint8_t* msg, size_t avail, size_t* out_len)
* 1 и *group_id при успехе; 0 при отсутствии пути/ошибке, выход не меняется.
* group_id обязателен; наличие пути не гарантирует успешной последующей отправки. */
int dm_route_group(struct UTUN_INSTANCE* inst, uint64_t peer, uint64_t preferred, uint64_t* group_id);
/* Проверить role=yes у peer в любой живой общей CHAT-группе self/peer.
* Группа объявления роли не ограничивает маршрут личной передачи. peer=self проверяет локальную роль.
* Учитывает только source=0, admitted=1, deleted=0 и действующий канал; путь не требуется.
* 1=роль найдена, 0=нет роли/ошибка с диагностикой. role — непустое имя adm_tags, только uasync. */
int dm_peer_role(struct UTUN_INSTANCE* inst, uint64_t peer, const char* role);
/* Проверить точную длину msg/len, conv/author/recipient/seq, descriptor и подпись автора из nodes.
* 0=корректно, -1=отказ. Нужна SQLite, владелец dm_core не требуется.
* Не расшифровывает тело и не проверяет членство/роль router-отправителя: это обязанность вызывающего. */