Browse Source

Prioritize supernodes in invites and update chat background and ringtone

master
evgeny 1 day ago
parent
commit
7ebc282eb2
  1. 11
      src/chat/invite_build.c
  2. 4
      src/chat/invite_build.h
  3. 42
      tests/test_chat_join_e2e.c
  4. BIN
      tools/chatgui/resources/bg.png
  5. BIN
      tools/chatgui/resources/sounds/call_incoming.mp3

11
src/chat/invite_build.c

@ -65,7 +65,7 @@ static int node_has_both_public(struct UTUN_INSTANCE* inst, uint64_t node_id) {
static uint64_t pick_best_node(struct UTUN_INSTANCE* inst, uint64_t channel_id, int* out_has_both_public, int* out_priority) {
struct chat_core_ctx* cc = CC(inst);
uint64_t best_nid = 0;
int best_priority = 4; /* 1=regular, 2=self, 3=super, 4=invalid */
int best_priority = 4; /* 1=super, 2=regular, 3=self, 4=invalid */
int best_has_both = 0;
struct TOPO_GROUP* grp = resolve_chat_group(inst, channel_id);
@ -99,9 +99,9 @@ static uint64_t pick_best_node(struct UTUN_INSTANCE* inst, uint64_t channel_id,
int has_both = node_has_both_public(inst, nid);
int priority;
if (nid == cc->my_node_id) priority = 2; /* self */
else if (ntype == 4) priority = 3; /* supernode */
else priority = 1; /* regular */
if (ntype == 4) priority = 1; /* supernode, включая self */
else if (nid == cc->my_node_id) priority = 3;
else priority = 2;
if (priority <= best_priority) {
best_nid = nid;
@ -122,6 +122,9 @@ static uint64_t resolve_auto_node(struct UTUN_INSTANCE* inst, uint64_t channel_i
int has_both = 0, prio = 4;
uint64_t best = pick_best_node(inst, channel_id, &has_both, &prio);
if (best == 0) best = cc->my_node_id;
DEBUG_INFO(DEBUG_CATEGORY_CHAT_SYNC, "invite_build: auto selection ch=%llu node=0x%016llx role=%s self=%d",
(unsigned long long)channel_id, (unsigned long long)best,
prio == 1 ? "supernode" : prio == 2 ? "regular" : "self", best == cc->my_node_id);
if (out_has_both) *out_has_both = has_both;
if (out_priority) *out_priority = prio;
return best;

4
src/chat/invite_build.h

@ -20,7 +20,7 @@ struct chat_invite_build;
typedef void (*chat_invite_ready_fn)(void* arg, int result, const char* link);
/* Собрать invite-ссылку для канала.
* target_node_id = 0 → auto (лучший достижимый мембер, иначе self).
* target_node_id = 0 → auto (достижимый суперузел → обычный узел → self).
* target_node_id != 0 → конкретный узел (должен быть достижимым мембером канала).
* password = NULL → без пароля.
* NULL=ошибка запуска, callback не вызывается. Иначе callback после возврата,
@ -35,7 +35,7 @@ void chat_invite_build_cancel(struct chat_invite_build* request);
* Возвращает количество (0..max_ids), либо -1. */
int chat_invite_candidate_nodes(struct UTUN_INSTANCE* inst, uint64_t channel_id, uint64_t* out_ids, int max_ids);
/* Авто-узел: лучший достижимый мембер, иначе self. Возвращает 0 и заполняет out_node_id, либо -1. */
/* Авто-узел: достижимый суперузел → обычный узел → self. Возвращает 0 и заполняет out_node_id, либо -1. */
int chat_invite_best_node(struct UTUN_INSTANCE* inst, uint64_t channel_id, uint64_t* out_node_id);
/* Трамплин для gui_bridge (arg = u_malloc(struct chat_invite_build_req)).

42
tests/test_chat_join_e2e.c

@ -12,6 +12,7 @@
// invalid неверный ключ: J отклонён, мембера J нет.
#include "chat_core.h"
#include "chat_core_priv.h"
#include "chat_sync.h"
#include "chat_join.h"
#include "chat_headless_control.h"
@ -432,6 +433,46 @@ out:
/* ── child_main ── */
/* Проверяем выбор на реальных мемберах канала; изменения производных полей откатываем до следующего poll. */
static int check_invite_priority(struct UTUN_INSTANCE* inst) {
uint64_t channel_id = strtoull(g_sh.ch_id, NULL, 10), selected = 0;
struct TOPO_GROUP* group = topo_groups_find(inst->topo_groups, channel_id);
struct TOPO_GROUP_NODE* peer = topo_node_find_by_id(group, g_sh.nid[IDX_C]);
if (!peer) { DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "test invite priority: missing peer"); return 0; }
uint64_t deadline = get_time_tb() + 10000;
while (!peer->conn_presence && get_time_tb() < deadline) poll_checked(inst);
if (!peer->conn_presence) { DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "test invite priority: peer unreachable"); return 0; }
char table[80], sql[256];
peers_table_name(g_sh.ch_id, table, sizeof(table));
sqlite3* db = inst->topo_sqlite_db;
if (sqlite3_exec(db, "SAVEPOINT invite_priority", NULL, NULL, NULL) != SQLITE_OK) {
DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "test invite priority: savepoint failed: %s", sqlite3_errmsg(db)); return 0;
}
int ok = 0;
uint8_t presence = peer->conn_presence;
snprintf(sql, sizeof(sql), "UPDATE \"%s\" SET node_type=1", table);
if (sqlite3_exec(db, sql, NULL, NULL, NULL) != SQLITE_OK) goto out;
if (chat_invite_best_node(inst, channel_id, &selected) || selected != g_sh.nid[IDX_C]) goto out;
snprintf(sql, sizeof(sql), "UPDATE \"%s\" SET node_type=4 WHERE node_id=%lld", table, (long long)inst->node_id);
if (sqlite3_exec(db, sql, NULL, NULL, NULL) != SQLITE_OK) goto out;
if (chat_invite_best_node(inst, channel_id, &selected) || selected != inst->node_id) goto out;
snprintf(sql, sizeof(sql), "UPDATE \"%s\" SET node_type=1 WHERE node_id=%lld", table, (long long)inst->node_id);
if (sqlite3_exec(db, sql, NULL, NULL, NULL) != SQLITE_OK) goto out;
snprintf(sql, sizeof(sql), "UPDATE \"%s\" SET node_type=4 WHERE node_id=%lld", table, (long long)g_sh.nid[IDX_C]);
if (sqlite3_exec(db, sql, NULL, NULL, NULL) != SQLITE_OK) goto out;
if (chat_invite_best_node(inst, channel_id, &selected) || selected != g_sh.nid[IDX_C]) goto out;
peer->conn_presence = 0;
if (chat_invite_best_node(inst, channel_id, &selected) || selected != inst->node_id) goto out;
ok = 1;
out:
peer->conn_presence = presence;
if (sqlite3_exec(db, "ROLLBACK TO invite_priority; RELEASE invite_priority", NULL, NULL, NULL) != SQLITE_OK) ok = 0;
if (!ok) DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "test invite priority failed: selected=%016llx err=%s",
(unsigned long long)selected, sqlite3_errmsg(db));
else DEBUG_INFO(DEBUG_CATEGORY_CHAT_SYNC, "test invite priority: regular, self-supernode, supernode, unreachable PASS");
return ok;
}
static int child_main(const char* role, const char* dir, int invalid_key) {
struct UASYNC* ua = uasync_create();
if (!ua) { fprintf(stderr, "%s: uasync_create failed\n", role); return 1; }
@ -477,6 +518,7 @@ static int child_main(const char* role, const char* dir, int invalid_key) {
if (!g_sh.degraded && !wait_bgp(inst, g_sh.nid[IDX_C], 8000)) {
fprintf(stderr, "A: no BGP to C\n"); goto out;
}
if (!g_sh.degraded && !check_invite_priority(inst)) goto out;
uint64_t target = g_sh.degraded ? g_sh.nid[IDX_A] : g_sh.nid[IDX_C];
struct invite_result result = {0};

BIN
tools/chatgui/resources/bg.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 MiB

After

Width:  |  Height:  |  Size: 1.3 MiB

BIN
tools/chatgui/resources/sounds/call_incoming.mp3

Binary file not shown.
Loading…
Cancel
Save