etcp: reset_id эпоха ресета — фикс потери NODEINFO при флапе

Добавлен 64-битный reset_id (эпоха ресета) в INIT-фреймы и STCP-handshake:
- генерится один раз при создании conn, меняется только при фатальном ресете
  (normalizer desync / bad fragment size);
- при приёме чужого id slave принимает эпоху пира и ресетится, master держит свою;
- первый id принимается без ресета (свежие при init);
- «tcp peer clean» реинит гейтится по смене id — нет повторного сброса seq.

Это устраняет коллизию seq=1 (RX dup) из-за двойного реинита нескольких TCP-линков,
из-за которой NODEINFO пира терялся и member не возвращался online.

Также: chat member online теперь из topo_group (без БД/merkle), тест test_etcp_seq_collision.
This commit is contained in:
evgeny committed 2026-09-06 21:50:06 +03:00
1 parent f7c08f8f5e
commit 61c572cae4
29 files changed
+663 -385

No files matched your search

+16 -7
View File
@@ -84,10 +84,18 @@ int topo_node_sqlite_addrs_put(sqlite3* db, uint64_t node_id, struct TOPO_NODE*
sqlite3_exec(db, "BEGIN", NULL, NULL, NULL);
sqlite3_stmt* ds = NULL;
int deleted = 0;
if (sqlite3_prepare_v2(db, "DELETE FROM node_addresses WHERE node_id=?", -1, &ds, NULL) == SQLITE_OK) {
sqlite3_bind_int64(ds, 1, (sqlite3_int64)node_id);
sqlite3_step(ds);
int drc = sqlite3_step(ds);
deleted = sqlite3_changes(db);
if (drc != SQLITE_DONE)
DEBUG_WARN(DEBUG_CATEGORY_BGP, "addrs_put: DELETE rc=%d (not DONE) node=%016llx: %s",
drc, (unsigned long long)node_id, sqlite3_errmsg(db));
sqlite3_finalize(ds);
} else {
DEBUG_WARN(DEBUG_CATEGORY_BGP, "addrs_put: DELETE prepare failed node=%016llx: %s",
(unsigned long long)node_id, sqlite3_errmsg(db));
}
sqlite3_stmt* is = NULL;
@@ -113,8 +121,9 @@ int topo_node_sqlite_addrs_put(sqlite3* db, uint64_t node_id, struct TOPO_NODE*
sqlite3_bind_int(is, 8, (int)nat);
sqlite3_bind_int(is, 9, (int)a->socket_id);
if (sqlite3_step(is) != SQLITE_DONE)
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "addrs_put: INSERT failed node=%016llx fam=4 sock=%d: %s",
(unsigned long long)node_id, a->socket_id, sqlite3_errmsg(db));
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "addrs_put: INSERT failed node=%016llx fam=4 sock=%d at=%d cfg=%d nat=%d addr=%d.%d.%d.%d:%d: %s",
(unsigned long long)node_id, a->socket_id, at, cfg, nat,
a->addr[0], a->addr[1], a->addr[2], a->addr[3], a->port, sqlite3_errmsg(db));
sqlite3_reset(is);
written++;
}
@@ -132,16 +141,16 @@ int topo_node_sqlite_addrs_put(sqlite3* db, uint64_t node_id, struct TOPO_NODE*
sqlite3_bind_int(is, 8, (int)nat);
sqlite3_bind_int(is, 9, (int)a->socket_id);
if (sqlite3_step(is) != SQLITE_DONE)
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "addrs_put: INSERT failed node=%016llx fam=6 sock=%d: %s",
(unsigned long long)node_id, a->socket_id, sqlite3_errmsg(db));
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "addrs_put: INSERT failed node=%016llx fam=6 sock=%d at=%d cfg=%d nat=%d: %s",
(unsigned long long)node_id, a->socket_id, at, cfg, nat, sqlite3_errmsg(db));
sqlite3_reset(is);
written++;
}
sqlite3_finalize(is);
sqlite3_exec(db, "COMMIT", NULL, NULL, NULL);
DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "addrs_put: node=%016llx v4=%d v6=%d total=%d",
(unsigned long long)node_id,
DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "addrs_put: node=%016llx deleted=%d v4=%d v6=%d written=%d",
(unsigned long long)node_id, deleted,
topo_list_count((struct _topo_head*)ni->v4_addrs),
topo_list_count((struct _topo_head*)ni->v6_addrs), written);
return 0;