|
|
|
|
@ -5,7 +5,9 @@
|
|
|
|
|
* Таймаут = direct_timeout_ms. По таймауту отменяем незавершённые и помечаем |
|
|
|
|
* connected=0 в БД. Если хоть один подключился → done. |
|
|
|
|
* |
|
|
|
|
* Phase 2: последовательный перебор пиров с публичными адресами до первого успеха. |
|
|
|
|
* Phase 2: последовательный перебор пиров с прямыми/EIM адресами (addr_type=1,2). |
|
|
|
|
* |
|
|
|
|
* Phase 3: последовательный перебор пиров с локальными/strict NAT (addr_type=0,3). |
|
|
|
|
* |
|
|
|
|
* Счётчик active_conn_count — число уникальных peer-узлов с реальными соединениями. |
|
|
|
|
* UP: инкремент только для первого соединения к peer_node_id. |
|
|
|
|
@ -29,7 +31,8 @@
|
|
|
|
|
#define TGC_ID "topo_group_connect" |
|
|
|
|
#define TGC_PHASE_ONE 0 |
|
|
|
|
#define TGC_PHASE_TWO 1 |
|
|
|
|
#define TGC_PHASE_DONE 2 |
|
|
|
|
#define TGC_PHASE_THREE 2 |
|
|
|
|
#define TGC_PHASE_DONE 3 |
|
|
|
|
|
|
|
|
|
struct TOPO_GROUP_CONNECT { |
|
|
|
|
struct TOPO_GROUP* group; |
|
|
|
|
@ -46,6 +49,8 @@ struct TOPO_GROUP_CONNECT {
|
|
|
|
|
|
|
|
|
|
static void tgc_phase2_try_next(struct TOPO_GROUP_CONNECT* gc); |
|
|
|
|
static void tgc_phase2_result(int result, uint64_t node_id, void* arg); |
|
|
|
|
static void tgc_phase3_try_next(struct TOPO_GROUP_CONNECT* gc); |
|
|
|
|
static void tgc_phase3_result(int result, uint64_t node_id, void* arg); |
|
|
|
|
static void tgc_phase1_timeout(void* arg); |
|
|
|
|
static void tgc_phase1_result(int result, uint64_t node_id, void* arg); |
|
|
|
|
|
|
|
|
|
@ -63,6 +68,7 @@ int topo_group_connect_init(struct TOPO_GROUP* group) {
|
|
|
|
|
|
|
|
|
|
uint64_t* ids = NULL; int count = 0; |
|
|
|
|
sqlite3* db = group->instance->topo_sqlite_db; |
|
|
|
|
DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "%s: init ch=%s db=%p", TGC_ID, group->channel_id, (void*)db); |
|
|
|
|
if (!db || topo_node_sqlite_get_connected_peers(db, group->channel_id, &ids, &count) != 0 || count == 0) { |
|
|
|
|
if (ids) { u_free(ids); ids = NULL; } |
|
|
|
|
gc->phase = TGC_PHASE_TWO; |
|
|
|
|
@ -73,8 +79,10 @@ int topo_group_connect_init(struct TOPO_GROUP* group) {
|
|
|
|
|
|
|
|
|
|
gc->phase = TGC_PHASE_ONE; gc->pending = count; |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_BGP, "%s: ch=%s Phase 1 launching %d connects", TGC_ID, group->channel_id, count); |
|
|
|
|
for (int i = 0; i < count; i++) |
|
|
|
|
for (int i = 0; i < count; i++) { |
|
|
|
|
DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "%s: Phase1 connect to 0x%016llx (%d/%d)", TGC_ID, (unsigned long long)ids[i], i + 1, count); |
|
|
|
|
conn_mgr_connect_node(group->conn_mgr, ids[i], 0, tgc_phase1_result, gc); |
|
|
|
|
} |
|
|
|
|
u_free(ids); |
|
|
|
|
|
|
|
|
|
gc->phase_timer = uasync_set_timeout(group->instance->ua, |
|
|
|
|
@ -93,9 +101,9 @@ void topo_group_connect_destroy(struct TOPO_GROUP* group) {
|
|
|
|
|
|
|
|
|
|
void topo_group_connect_restart(struct TOPO_GROUP* group) { |
|
|
|
|
struct TOPO_GROUP_CONNECT* gc = group->connect; |
|
|
|
|
if (!gc) { topo_group_connect_init(group); return; } |
|
|
|
|
if (gc->phase != TGC_PHASE_DONE) return; |
|
|
|
|
if (gc->active_conn_count > 0) return; |
|
|
|
|
if (!gc) { DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "%s: restart ch=%s no gc → init", TGC_ID, group->channel_id); topo_group_connect_init(group); return; } |
|
|
|
|
if (gc->phase != TGC_PHASE_DONE) { DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "%s: restart ch=%s skip phase=%d", TGC_ID, group->channel_id, gc->phase); return; } |
|
|
|
|
if (gc->active_conn_count > 0) { DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "%s: restart ch=%s skip active=%d", TGC_ID, group->channel_id, gc->active_conn_count); return; } |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_BGP, "%s: restart ch=%s", TGC_ID, group->channel_id); |
|
|
|
|
topo_group_connect_destroy(group); |
|
|
|
|
topo_group_connect_init(group); |
|
|
|
|
@ -133,6 +141,8 @@ void topo_group_connect_on_up(struct TOPO_GROUP* group, struct ETCP_CONN* conn)
|
|
|
|
|
if (db) topo_node_sqlite_set_connected(db, group->channel_id, peer, 1); |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_BGP, "%s: UP peer=0x%016llx ch=%s active=%d", |
|
|
|
|
TGC_ID, (unsigned long long)peer, group->channel_id, gc->active_conn_count); |
|
|
|
|
DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "%s: UP phase=%d candidate_count=%d", |
|
|
|
|
TGC_ID, gc->phase, gc->candidate_count); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void topo_group_connect_on_down(struct TOPO_GROUP* group, struct ETCP_CONN* conn) { |
|
|
|
|
@ -173,6 +183,10 @@ void topo_group_connect_on_down(struct TOPO_GROUP* group, struct ETCP_CONN* conn
|
|
|
|
|
if (db) topo_node_sqlite_set_connected(db, group->channel_id, peer, 0); |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_BGP, "%s: DOWN peer=0x%016llx ch=%s active=%d", |
|
|
|
|
TGC_ID, (unsigned long long)peer, group->channel_id, gc->active_conn_count); |
|
|
|
|
if (gc->phase == TGC_PHASE_DONE && gc->active_conn_count == 0) { |
|
|
|
|
DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "%s: DOWN restart eligible ch=%s → restarting", TGC_ID, group->channel_id); |
|
|
|
|
topo_group_connect_restart(group); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* ═══════════════════════════════════════════════════════════════════════
|
|
|
|
|
@ -225,7 +239,8 @@ static void tgc_phase2_try_next(struct TOPO_GROUP_CONNECT* gc) {
|
|
|
|
|
if (gc->phase != TGC_PHASE_TWO) return; |
|
|
|
|
if (gc->candidate_count == 0) { |
|
|
|
|
sqlite3* db = gc->group->instance->topo_sqlite_db; |
|
|
|
|
topo_node_sqlite_get_public_peers(db, gc->group->channel_id, &gc->candidate_ids, &gc->candidate_count); |
|
|
|
|
topo_node_sqlite_get_public_peers(db, gc->group->channel_id, &gc->candidate_ids, &gc->candidate_count, |
|
|
|
|
gc->group->instance->node_id); |
|
|
|
|
gc->cursor = 0; |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_BGP, "%s: Phase2 loaded %d public peers for ch=%s", |
|
|
|
|
TGC_ID, gc->candidate_count, gc->group->channel_id); |
|
|
|
|
@ -244,7 +259,8 @@ static void tgc_phase2_try_next(struct TOPO_GROUP_CONNECT* gc) {
|
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_BGP, "%s: Phase2 exhausted — no connections, ch=%s", TGC_ID, gc->group->channel_id); |
|
|
|
|
gc->phase = TGC_PHASE_DONE; |
|
|
|
|
gc->phase = TGC_PHASE_THREE; gc->candidate_count = 0; |
|
|
|
|
tgc_phase3_try_next(gc); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void tgc_phase2_result(int result, uint64_t node_id, void* arg) { |
|
|
|
|
@ -258,3 +274,46 @@ static void tgc_phase2_result(int result, uint64_t node_id, void* arg) {
|
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_BGP, "%s: Phase2 0x%016llx FAIL — try next", TGC_ID, (unsigned long long)node_id); |
|
|
|
|
tgc_phase2_try_next(gc); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* ═══════════════════════════════════════════════════════════════════════
|
|
|
|
|
* Phase 3 — локальные/strict NAT адреса (addr_type=0,3) |
|
|
|
|
* ══════════════════════════════════════════════════════════════════════ */ |
|
|
|
|
|
|
|
|
|
static void tgc_phase3_try_next(struct TOPO_GROUP_CONNECT* gc) { |
|
|
|
|
if (gc->phase != TGC_PHASE_THREE) return; |
|
|
|
|
if (gc->candidate_count == 0) { |
|
|
|
|
sqlite3* db = gc->group->instance->topo_sqlite_db; |
|
|
|
|
topo_node_sqlite_get_local_peers(db, gc->group->channel_id, &gc->candidate_ids, &gc->candidate_count, |
|
|
|
|
gc->group->instance->node_id); |
|
|
|
|
gc->cursor = 0; |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_BGP, "%s: Phase3 loaded %d local peers for ch=%s", |
|
|
|
|
TGC_ID, gc->candidate_count, gc->group->channel_id); |
|
|
|
|
} |
|
|
|
|
while (gc->cursor < gc->candidate_count) { |
|
|
|
|
uint64_t nid = gc->candidate_ids[gc->cursor++]; |
|
|
|
|
uint8_t status; uint8_t conn_type; |
|
|
|
|
conn_mgr_get_status(gc->group->conn_mgr, nid, &status, &conn_type); |
|
|
|
|
if (status == CONN_MGR_STATE_CONNECTED) { |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_BGP, "%s: Phase3 skip 0x%016llx already connected", TGC_ID, (unsigned long long)nid); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_BGP, "%s: Phase3 trying 0x%016llx (%d/%d)", TGC_ID, |
|
|
|
|
(unsigned long long)nid, gc->cursor, gc->candidate_count); |
|
|
|
|
conn_mgr_connect_node(gc->group->conn_mgr, nid, 0, tgc_phase3_result, gc); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_BGP, "%s: Phase3 exhausted — no connections, ch=%s", TGC_ID, gc->group->channel_id); |
|
|
|
|
gc->phase = TGC_PHASE_DONE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void tgc_phase3_result(int result, uint64_t node_id, void* arg) { |
|
|
|
|
struct TOPO_GROUP_CONNECT* gc = (struct TOPO_GROUP_CONNECT*)arg; |
|
|
|
|
if (gc->phase != TGC_PHASE_THREE) return; |
|
|
|
|
if (result == CONN_MGR_OK) { |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_BGP, "%s: Phase3 connected to 0x%016llx — done", TGC_ID, (unsigned long long)node_id); |
|
|
|
|
gc->phase = TGC_PHASE_DONE; |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_BGP, "%s: Phase3 0x%016llx FAIL — try next", TGC_ID, (unsigned long long)node_id); |
|
|
|
|
tgc_phase3_try_next(gc); |
|
|
|
|
} |
|
|
|
|
|