diff --git a/src/routing_layer/topo_group.h b/src/routing_layer/topo_group.h index 47041c49..8920d110 100644 --- a/src/routing_layer/topo_group.h +++ b/src/routing_layer/topo_group.h @@ -3,7 +3,7 @@ * @brief Групповые сессии и обмен маршрутами поверх общего транспорта NCD. * * У каждой группы своя топология; идентичности и адреса узлов общие (topo_node.h). - * UTUN обменивается также подсетями, CHAT допускает только локально известных участников. + * UTUN обменивается также подсетями, CHAT допускает только полных неудалённых участников из локальной БД. * Для подключения используйте peer_open/close: группа владеет NCD с начала попытки. * JOIN/ACCEPT согласует сессию, NODEINFO/WITHDRAW поддерживают её маршруты. * Потерю путей обрабатывает topo_recovery, выбор CHAT-пиров — topo_group_connect. @@ -116,7 +116,7 @@ void topo_fire_nodeinfo_cbk(struct UTUN_INSTANCE* instance, struct TOPO_GROUP* g // ETCP ID для пакетов топологии: ETCP_ID_TOPO_ENTRY (см. etcp_api.h) /* Групповая сессия принадлежит паре (group, peer), транспорт разделяется через NCD. - * JOIN_GROUP не добавляет мембера: CHAT проверяет локальную таблицу участников + * JOIN_GROUP не добавляет мембера: CHAT требует source=0 и deleted=0 в локальной таблице участников * (chat_join.h / member_sync). Поздний commit мембера повторяет JOIN на готовом NCD. * * Каждая сторона создаёт случайный ненулевой local_epoch. JOIN несёт src_epoch, diff --git a/src/routing_layer/topo_group_invite.c b/src/routing_layer/topo_group_invite.c index 21c23608..a7f4c0aa 100644 --- a/src/routing_layer/topo_group_invite.c +++ b/src/routing_layer/topo_group_invite.c @@ -169,7 +169,7 @@ static void tgi_handle_info_resp(struct ETCP_CONN* conn, const uint8_t* data, si DEBUG_INFO(DEBUG_CATEGORY_BGP, "invite: verified channel saved peer=%016llx group=%s name=%s owner=%016llx", (unsigned long long)p->node_id, ch_id, name, (unsigned long long)owner); /* Только существующий мембер может инициировать групповое согласование. */ - if (topo_node_sqlite_member_in_channel(inst->topo_sqlite_db, ch_id, p->node_id)) + if (topo_node_sqlite_member_allowed(inst->topo_sqlite_db, ch_id, p->node_id)) topo_group_connect_node_once(group, p->node_id); tgi_finish(p, TGI_EVENT_JOIN); } diff --git a/tests/test_group_recovery.c b/tests/test_group_recovery.c index ebe40e27..b1a33d1b 100644 --- a/tests/test_group_recovery.c +++ b/tests/test_group_recovery.c @@ -294,8 +294,23 @@ static void manual_planner_cancel(void) { /* The membership table is the only authorization source. */ uint8_t key[32] = {1}, signature[64] = {1}; assert(topo_node_sqlite_channel_put(f.inst->topo_sqlite_db, "42", "test", 0, key, NULL, key, NULL, signature) == 0); + assert(!topo_node_sqlite_member_placeholder_put(f.inst->topo_sqlite_db, "42", f.ids[0], key, key)); + assert(topo_node_sqlite_member_in_channel(f.inst->topo_sqlite_db, "42", f.ids[0])); + assert(!topo_node_sqlite_member_allowed(f.inst->topo_sqlite_db, "42", f.ids[0])); + struct topo_connect_peer* candidates = NULL; size_t count = 0; + assert(!topo_node_sqlite_get_connect_peers(f.inst->topo_sqlite_db, "42", &candidates, &count) && !count && !candidates); + struct TOPO_PEER_REQUEST* denied = NULL; + assert(topo_group_peer_open(f.group, f.ids[0], &denied) == -1 && !denied && !peer(&f, 0)); assert(topo_node_sqlite_member_block_put(f.inst->topo_sqlite_db, "42", f.ids[0], signature, 1, signature, 1, key, key, "{}", NULL, 0, signature) == 0); + assert(topo_node_sqlite_member_allowed(f.inst->topo_sqlite_db, "42", f.ids[0])); + assert(!topo_node_sqlite_get_connect_peers(f.inst->topo_sqlite_db, "42", &candidates, &count) && count == 1); + assert(candidates[0].node_id == f.ids[0]); u_free(candidates); candidates = NULL; + assert(!topo_node_sqlite_member_owner_put(f.inst->topo_sqlite_db, "42", f.ids[0], "{\"deleted\":\"yes\"}", signature, 0)); + assert(!topo_node_sqlite_member_allowed(f.inst->topo_sqlite_db, "42", f.ids[0])); + assert(!topo_node_sqlite_get_connect_peers(f.inst->topo_sqlite_db, "42", &candidates, &count) && !count && !candidates); + assert(topo_group_peer_open(f.group, f.ids[0], &denied) == -1 && !denied && !peer(&f, 0)); + assert(!topo_node_sqlite_member_owner_put(f.inst->topo_sqlite_db, "42", f.ids[0], "{}", signature, 0)); assert(topo_group_connect_node_once(f.group, f.ids[0]) == 0); struct NODE_CONN_DIRECT* ownership = peer(&f, 0)->handle; assert(topo_group_connect_node_once(f.group, f.ids[0]) == 0 && peer(&f, 0)->handle == ownership);