Define join contract and require committed CHAT membership for BGP
This commit is contained in:
1 parent
1a8072e9b2
commit
9745a987ac
7 files changed
+221
-44
No files matched your search
@@ -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 по группам. */
|
||||
|
||||
@@ -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 // запрос полной таблицы
|
||||
|
||||
Reference in new issue
Block a user