@ -62,6 +62,19 @@ static void topo_group_send_join_group(struct TOPO_GROUP* group, struct ETCP_CON
if ( etcp_send ( conn , e ) ! = 0 ) { u_free ( req ) ; queue_entry_free ( e ) ; }
}
static void topo_group_send_resync ( struct ETCP_CONN * conn ) {
if ( ! conn ) return ;
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " Sending RESYNC to %s " , conn - > log_name ) ;
struct TOPOMSG_RESYNC * req = u_calloc ( 1 , sizeof ( struct TOPOMSG_RESYNC ) ) ;
if ( ! req ) return ;
req - > cmd = ETCP_ID_TOPO_ENTRY ;
req - > subcmd = TOPO_SUBCMD_RESYNC ;
struct ll_entry * e = queue_entry_new ( 0 ) ;
if ( ! e ) { u_free ( req ) ; return ; }
e - > dgram = ( uint8_t * ) req ; e - > len = sizeof ( struct TOPOMSG_RESYNC ) ;
if ( etcp_send ( conn , e ) ! = 0 ) { u_free ( req ) ; queue_entry_free ( e ) ; }
}
static void topo_group_send_table_complete ( struct TOPO_GROUP * group , struct ETCP_CONN * conn ) {
if ( ! group | | ! conn ) return ;
struct TOPOMSG_TABLE_REQ * req = u_calloc ( 1 , sizeof ( struct TOPOMSG_TABLE_REQ ) ) ;
@ -80,6 +93,8 @@ static bool topo_group_should_send_to(const struct TOPO_GROUP_NODE* nq, uint64_t
static void topo_group_send_full_table ( struct TOPO_GROUP * group , struct ETCP_CONN * conn ) ;
static void topo_group_handle_request_table ( struct TOPO_GROUP * group , struct ETCP_CONN * conn ) ;
static void topo_group_handle_join_group ( struct TOPO_GROUP * group , struct ETCP_CONN * conn ) ;
static void topo_group_send_resync ( struct ETCP_CONN * conn ) ;
static void topo_group_handle_resync ( struct UTUN_INSTANCE * instance , struct ETCP_CONN * conn ) ;
static void nodeinfo_dump_log ( const uint8_t * data , size_t len ) {
if ( ! data | | len < sizeof ( struct TOPOMSG_NODEINFO_PKT ) ) return ;
@ -130,6 +145,7 @@ static const char* group_subcmd_name(uint8_t subcmd) {
case TOPO_SUBCMD_TABLE_COMPLETE : return " TABLE_COMPLETE " ;
case TOPO_SUBCMD_ERR_GROUP_MISMATCH : return " ERR_GROUP_MISMATCH " ;
case TOPO_SUBCMD_JOIN_GROUP : return " JOIN_GROUP " ;
case TOPO_SUBCMD_RESYNC : return " RESYNC " ;
default : return " ? " ;
}
}
@ -169,6 +185,12 @@ static void topo_group_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry*
uint8_t * data = entry - > dgram ; uint8_t cmd = data [ 0 ] ; uint8_t subcmd = data [ 1 ] ;
if ( cmd ! = ETCP_ID_TOPO_ENTRY ) { queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; return ; }
/* RESYNC — общий сигнал без group_id, обрабатывается до поиска группы */
if ( subcmd = = TOPO_SUBCMD_RESYNC ) {
topo_group_handle_resync ( instance , from_conn ) ;
queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; return ;
}
uint64_t pkt_group_id = 0 ;
if ( subcmd = = TOPO_SUBCMD_NODEINFO & & entry - > len > = 3 ) {
pkt_group_id = ( ( struct TOPOMSG_NODEINFO_PKT * ) data ) - > node . group_id ;
@ -218,13 +240,18 @@ static void topo_group_conn_status(struct ETCP_CONN* conn, int status, void* arg
if ( ! conn | | ! groups ) return ;
if ( status = = ETCP_CONN_STATUS_UP & & conn - > peer_node_id ) {
/* non-CHAT (UTUN): узлы из конфига (clients) + явные подключения (etcp_connect). */
int is_client = conn - > instance - > config & & config_peer_in_clients ( conn - > instance - > config , conn - > crypto_ctx . peer_public_key ) ;
int explicit_conn = conn - > bgp_ready_cbk ! = NULL ;
/* пассивная сторона: просим пира заново анонсировать свои группы (после флэпа/переподключения) */
if ( ! is_client & & ! explicit_conn )
topo_group_send_resync ( conn ) ;
/* non-CHAT (UTUN): узлы из конфига (clients) + явные подключения (etcp_connect). */
struct ll_entry * fe = groups - > group_list - > head ;
while ( fe ) {
struct TOPO_GROUP * g = ( struct TOPO_GROUP * ) fe ; fe = fe - > next ;
if ( g - > group_type ! = TOPO_GROUP_TYPE_CHAT ) {
int is_client = conn - > instance - > config & & config_peer_in_clients ( conn - > instance - > config , conn - > crypto_ctx . peer_public_key ) ;
if ( is_client | | explicit_conn ) {
topo_group_new_conn ( g , conn ) ; /* добавить + инициировать BGP */
topo_group_send_join_group ( g , conn ) ; /* запросить членство у пира */
@ -1006,6 +1033,20 @@ static void topo_group_handle_join_group(struct TOPO_GROUP* group, struct ETCP_C
topo_group_new_conn ( group , conn ) ;
}
static void topo_group_handle_resync ( struct UTUN_INSTANCE * instance , struct ETCP_CONN * conn ) {
if ( ! instance | | ! conn | | ! conn - > instance | | ! instance - > topo_groups ) return ;
/* общий сигнал от пассивной стороны: рестартуем обмен, если мы для этого пира VPN-клиент */
int is_client = conn - > instance - > config & & config_peer_in_clients ( conn - > instance - > config , conn - > crypto_ctx . peer_public_key ) ;
if ( ! is_client & & conn - > bgp_ready_cbk = = NULL ) return ;
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " handle_resync: from %s — re-announce groups " , conn - > log_name ) ;
struct ll_entry * fe = instance - > topo_groups - > group_list - > head ;
while ( fe ) {
struct TOPO_GROUP * g = ( struct TOPO_GROUP * ) fe ; fe = fe - > next ;
if ( g - > group_type ! = TOPO_GROUP_TYPE_CHAT )
topo_group_send_join_group ( g , conn ) ;
}
}
/* ── BGP node event callbacks ── */
void topo_group_add_node_cbk ( struct TOPO_GROUP * group , topo_node_event_fn fn , void * arg ) {