Define join contract and require committed CHAT membership for BGP

This commit is contained in:
evgeny committed 2026-09-27 20:34:24 +03:00
1 parent 1a8072e9b2
commit 9745a987ac
7 files changed
+221 -44

No files matched your search

+34 -3
View File
@@ -225,6 +225,19 @@ static void topo_group_broadcast_withdraw(struct TOPO_GROUP* group, uint64_t nod
// Приём пакетов
// ============================================================================
static int topo_group_has_sender(struct TOPO_GROUP* group, struct ETCP_CONN* conn) {
for (struct ll_entry* e = group->senders_list ? group->senders_list->head : NULL; e; e = e->next)
if (((struct TOPO_GROUP_CONN_ITEM*)e->data)->conn == conn) return 1;
return 0;
}
/* Транспорт не даёт членства: CHAT сверяет локальную таблицу участников. */
static int topo_group_peer_allowed(struct TOPO_GROUP* group, uint64_t node_id) {
if (group->group_type != TOPO_GROUP_TYPE_CHAT) return 1;
sqlite3* db = group->instance->topo_sqlite_db;
return db && group->channel_id[0] && topo_node_sqlite_member_in_channel(db, group->channel_id, node_id);
}
/* Приёмник BGP-пакетов от ETCP: диспетчер по subcmd (NODEINFO/WITHDRAW/...). */
static void topo_group_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry* entry) {
if (!from_conn || !entry || entry->len < 2) { if (entry) { queue_dgram_free(entry); queue_entry_free(entry); } return; }
@@ -265,6 +278,12 @@ static void topo_group_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry*
DEBUG_DEBUG(DEBUG_CATEGORY_BGP,"BGP recv %s from=%s group=%016llx len=%u",group_subcmd_name(subcmd),
from_conn->log_name,(unsigned long long)pkt_group_id,entry->len);
if (!topo_group_peer_allowed(group, from_conn->peer_node_id)) {
DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP deferred: member unknown peer=%016llx group=%016llx cmd=%u",
(unsigned long long)from_conn->peer_node_id, (unsigned long long)group->group_id, subcmd);
queue_dgram_free(entry); queue_entry_free(entry); return;
}
if (subcmd == TOPO_SUBCMD_NODEINFO) { nodeinfo_dump_log(data, entry->len); topo_group_process_nodeinfo(group, from_conn, data, entry->len); }
else if (subcmd == TOPO_SUBCMD_WITHDRAW) topo_group_process_withdraw(group, from_conn, data, entry->len);
else if (subcmd == TOPO_SUBCMD_REQUEST_TABLE) topo_group_handle_request_table(group, from_conn);
@@ -701,6 +720,11 @@ int topo_group_new_conn(struct TOPO_GROUP* group, struct ETCP_CONN* conn) {
if (!group || !conn) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "invalid args"); return -1; }
if (!conn->instance) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "conn->instance is NULL"); return -1; }
if (!conn->instance->rt) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "conn->instance->rt is NULL"); return -1; }
if (!topo_group_peer_allowed(group, conn->peer_node_id)) {
DEBUG_INFO(DEBUG_CATEGORY_BGP, "group connect deferred: member unknown peer=%016llx group=%016llx",
(unsigned long long)conn->peer_node_id, (unsigned long long)group->group_id);
return -1;
}
/* дедуп: тот же conn стреляет ETCP_CONN_STATUS_UP дважды (UDP-линк, затем TCP-линк).
* Если conn уже в senders_list — повторно не обрабатываем, иначе active_conn_count
@@ -731,6 +755,7 @@ int topo_group_new_conn(struct TOPO_GROUP* group, struct ETCP_CONN* conn) {
DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "topo_group_new_conn: peer=%016llx group=%016llx type=%d ch=%s", (unsigned long long)conn->peer_node_id, (unsigned long long)group->group_id, group->group_type, group->channel_id);
topo_group_send_join_group(group, conn);
topo_group_send_table_request(group, conn);
topo_group_connect_on_up(group, conn);
return 0;
@@ -1211,6 +1236,11 @@ static void topo_group_send_full_table(struct TOPO_GROUP* group, struct ETCP_CON
/* Обрабатывает REQUEST_TABLE: шлёт свой nodeinfo + полную таблицу + TABLE_COMPLETE. */
static void topo_group_handle_request_table(struct TOPO_GROUP* group, struct ETCP_CONN* conn) {
if (!group || !conn) return;
if (!topo_group_peer_allowed(group, conn->peer_node_id)) {
DEBUG_INFO(DEBUG_CATEGORY_BGP, "table request deferred: member unknown peer=%016llx group=%016llx",
(unsigned long long)conn->peer_node_id, (unsigned long long)group->group_id);
return;
}
topo_group_send_nodeinfo(group, group->local_node, conn, 0);
topo_group_send_full_table(group, conn);
/* senders_list заполняется только через topo_group_new_conn (add + BGP);
@@ -1222,9 +1252,10 @@ static void topo_group_handle_request_table(struct TOPO_GROUP* group, struct ETC
static void topo_group_handle_join_group(struct TOPO_GROUP* group, struct ETCP_CONN* conn) {
if (!group || !conn) return;
DEBUG_INFO(DEBUG_CATEGORY_BGP, "handle_join_group: from %s grp=%016llx type=%d", conn->log_name, (unsigned long long)group->group_id, group->group_type);
/* входящий запросил членство: для non-CHAT (UTUN) — добавить запросившего узла + инициировать BGP обратно */
if (group->group_type != TOPO_GROUP_TYPE_CHAT)
topo_group_new_conn(group, conn);
/* Проверка таблицы участников общая для входящих и локальных запросов. */
int existing = topo_group_has_sender(group, conn);
if (topo_group_new_conn(group, conn) == 0 && existing)
topo_group_send_table_request(group, conn);
}
/* Обрабатывает RESYNC: если мы VPN-клиент пира — заново шлём JOIN_GROUP по группам. */
+10
View File
@@ -90,6 +90,16 @@ void topo_fire_nodeinfo_cbk(struct UTUN_INSTANCE* instance, struct TOPO_GROUP* g
// ETCP ID для пакетов топологии: ETCP_ID_TOPO_ENTRY (см. etcp_api.h)
/* JOIN_GROUP восстанавливает BGP-связь с группой, не добавляет мембера.
* Для CHAT источник членства — локальная таблица участников канала.
* Запись приходит по протоколу из chat_join.h / member_sync; до её сохранения
* транспорт может обслуживать приглашение, но не даёт доступа к топологии канала.
* Поздний commit мембера повторно инициирует согласование на готовом NCD.
* JOIN_READY из chat_sync.h — результат добавления участника, а TABLE_COMPLETE —
* результат обмена топологией одной группы; ни один не означает готовности других групп.
* Конфиг, auto-connect и recovery обязаны использовать общую проверку членства.
*/
// Sub-команды
#define TOPO_SUBCMD_NODEINFO 0x04 // полная информация об узле + подсети
#define TOPO_SUBCMD_REQUEST_TABLE 0x05 // запрос полной таблицы