@ -10,9 +10,11 @@
# include "../utun_instance.h"
# include "../ntp_time.h"
# include "../../lib/ll_queue.h"
# include "../../lib/mem.h"
# include "../../lib/platform_compat.h"
# include "../transport_layer/etcp.h"
# include "../transport_layer/etcp_connections.h"
# include "../transport_layer/pkt_normalizer.h"
static const char * nat_type_str ( uint8_t t ) {
switch ( t ) { case 0 : return " UNKNOWN " ; case 1 : return " EIM " ; case 2 : return " STRICT " ; case 3 : return " DIRECT " ; default : return " ? " ; }
@ -112,7 +114,177 @@ static void chat_core_collect_status(void) {
chat_event_post ( CHAT_EVT_STATUS_REFRESH , ( const uint8_t * ) buf , off ) ;
}
/* ── Бинарный список соединений: [count:2][entry:46B]* ── */
/* entry: peer_node_id:8 flags:1 link_count:1 rtt:2 inflight_kb:2 name:32 */
# define CONN_LIST_ENTRY_SIZE 46
static void collect_conn_list ( void ) {
if ( ! g_cc . initialized | | ! g_cc . inst | | ! g_cc . inst - > connections ) return ;
uint16_t count = 0 ;
struct ll_entry * entry = g_cc . inst - > connections - > head ;
while ( entry ) { count + + ; entry = entry - > next ; }
if ( count > 250 ) count = 250 ;
size_t buf_sz = 2 + ( size_t ) count * CONN_LIST_ENTRY_SIZE ;
uint8_t * buf = ( uint8_t * ) u_malloc ( buf_sz ) ;
if ( ! buf ) return ;
uint16_t * hdr = ( uint16_t * ) buf ;
* hdr = count ;
uint8_t * p = buf + 2 ;
entry = g_cc . inst - > connections - > head ;
for ( uint16_t i = 0 ; i < count & & entry ; i + + , entry = entry - > next ) {
struct conn_queue_entry * ce = ( struct conn_queue_entry * ) entry - > data ;
if ( ! ce | | ! ce - > conn ) { memset ( p , 0 , CONN_LIST_ENTRY_SIZE ) ; p + = CONN_LIST_ENTRY_SIZE ; continue ; }
struct ETCP_CONN * conn = ce - > conn ;
memcpy ( p , & ce - > peer_node_id , 8 ) ; p + = 8 ;
uint8_t flags = 0 ;
if ( conn - > links_up ) flags | = 1 ;
if ( conn - > initialized ) flags | = 2 ;
* p + + = flags ;
uint8_t lc = 0 ;
struct ETCP_LINK * tl = conn - > links ; while ( tl ) { lc + + ; tl = tl - > next ; }
* p + + = lc ;
uint16_t rtt = 0 ;
if ( conn - > links ) rtt = conn - > links - > rtt_last ;
memcpy ( p , & rtt , 2 ) ; p + = 2 ;
uint16_t inflight_kb = ( uint16_t ) ( conn - > unacked_bytes / 1024 ) ;
memcpy ( p , & inflight_kb , 2 ) ; p + = 2 ;
char name [ 32 ] ; memset ( name , 0 , 32 ) ;
get_node_name ( ce - > peer_node_id , name , 31 ) ;
if ( ! name [ 0 ] ) snprintf ( name , 32 , " %016llX " , ( unsigned long long ) ce - > peer_node_id ) ;
memcpy ( p , name , 32 ) ; p + = 32 ;
}
chat_event_post ( CHAT_EVT_CONN_LIST , buf , ( int ) buf_sz ) ;
u_free ( buf ) ;
}
/* ── Полный текстовый дамп одного соединения ── */
static void collect_conn_metrics ( uint64_t peer_node_id ) {
char buf [ 8192 ] ; int off = 0 ;
if ( ! g_cc . initialized | | ! g_cc . inst | | ! g_cc . inst - > connections ) {
off = snprintf ( buf , sizeof ( buf ) , " uTun not initialized \n " ) ;
chat_event_post ( CHAT_EVT_CONN_METRICS , ( const uint8_t * ) buf , off ) ;
return ;
}
struct ll_entry * e = queue_find_data_by_index ( g_cc . inst - > connections , ( const uint8_t * ) & peer_node_id ) ;
if ( ! e ) {
off = snprintf ( buf , sizeof ( buf ) , " Connection %016llX not found \n " , ( unsigned long long ) peer_node_id ) ;
chat_event_post ( CHAT_EVT_CONN_METRICS , ( const uint8_t * ) buf , off ) ;
return ;
}
struct conn_queue_entry * ce = ( struct conn_queue_entry * ) e - > data ;
if ( ! ce | | ! ce - > conn ) {
off = snprintf ( buf , sizeof ( buf ) , " Connection %016llX has null data \n " , ( unsigned long long ) peer_node_id ) ;
chat_event_post ( CHAT_EVT_CONN_METRICS , ( const uint8_t * ) buf , off ) ;
return ;
}
struct ETCP_CONN * conn = ce - > conn ;
uint64_t my_id = g_cc . inst - > node_id ;
char peername [ 64 ] ; get_node_name ( peer_node_id , peername , sizeof ( peername ) ) ;
if ( ! peername [ 0 ] ) snprintf ( peername , sizeof ( peername ) , " %016llX " , ( unsigned long long ) peer_node_id ) ;
/* Count links */
int link_count = 0 , links_up_count = 0 ;
struct ETCP_LINK * tl = conn - > links ; while ( tl ) { if ( tl - > link_status ) links_up_count + + ; link_count + + ; tl = tl - > next ; }
off + = snprintf ( buf + off , sizeof ( buf ) - off ,
" === PEER: %04llX \u2192 %04llX [%s] === \n "
" Status: %s Links: %d/%d Initialized: %s Session: 0x%X MTU: %d \n "
" Reinit: %u Reset: %u Tx_state: %d Routing_exchange: %d \n "
" \n --- ETCP --- \n "
" RTT last/avg10: %.1f/%.1f ms Jitter: %.1f ms \n "
" Bytes sent: %u Retrans: %u ACKs: %u \n "
" Unacked bytes: %u Max inflight: %u \n "
" RX dup: %u TX dup: %u \n "
" IDs: next_tx=%u last_rx=%u last_del=%u rx_ack_till=%u \n "
" \n --- Queues --- \n " ,
( unsigned long long ) ( my_id & 0xFFFF ) , ( unsigned long long ) ( peer_node_id & 0xFFFF ) , peername ,
conn - > links_up ? " UP " : " DOWN " , links_up_count , link_count ,
conn - > initialized ? " yes " : " no " , conn - > session_id , conn - > mtu ,
conn - > reinit_count , conn - > reset_count , conn - > tx_state , conn - > routing_exchange_active ,
conn - > rtt_last / 10.0f , conn - > rtt_avg_10 / 10.0f , conn - > jitter / 10.0f ,
conn - > bytes_sent_total , conn - > retransmissions_count , conn - > ack_packets_count ,
conn - > unacked_bytes , conn - > max_inflight ,
conn - > rx_dup_count , conn - > tx_dup_count ,
conn - > next_tx_id , conn - > last_rx_id , conn - > last_delivered_id , conn - > rx_ack_till ) ;
if ( conn - > input_queue ) off + = snprintf ( buf + off , sizeof ( buf ) - off , " input_q: %uB/%dp " , ( unsigned ) queue_total_bytes ( conn - > input_queue ) , queue_entry_count ( conn - > input_queue ) ) ;
if ( conn - > input_send_q ) off + = snprintf ( buf + off , sizeof ( buf ) - off , " send_q: %uB/%dp " , ( unsigned ) queue_total_bytes ( conn - > input_send_q ) , queue_entry_count ( conn - > input_send_q ) ) ;
if ( conn - > input_wait_ack ) off + = snprintf ( buf + off , sizeof ( buf ) - off , " wait_ack: %uB/%dp \n " , ( unsigned ) queue_total_bytes ( conn - > input_wait_ack ) , queue_entry_count ( conn - > input_wait_ack ) ) ;
if ( conn - > ack_q ) off + = snprintf ( buf + off , sizeof ( buf ) - off , " ack_q: %uB/%dp " , ( unsigned ) queue_total_bytes ( conn - > ack_q ) , queue_entry_count ( conn - > ack_q ) ) ;
if ( conn - > recv_q ) off + = snprintf ( buf + off , sizeof ( buf ) - off , " recv_q: %uB/%dp " , ( unsigned ) queue_total_bytes ( conn - > recv_q ) , queue_entry_count ( conn - > recv_q ) ) ;
if ( conn - > output_queue ) off + = snprintf ( buf + off , sizeof ( buf ) - off , " out_q: %uB/%dp \n " , ( unsigned ) queue_total_bytes ( conn - > output_queue ) , queue_entry_count ( conn - > output_queue ) ) ;
off + = snprintf ( buf + off , sizeof ( buf ) - off , " \n --- ACK Debug --- \n "
" hit_inf=%u hit_sndq=%u miss=%u link_wait=%u \n " ,
conn - > cnt_ack_hit_inf , conn - > cnt_ack_hit_sndq , conn - > cnt_ack_miss , conn - > cnt_link_wait ) ;
/* Normalizer */
if ( conn - > normalizer ) {
struct PKTNORM * pn = conn - > normalizer ;
off + = snprintf ( buf + off , sizeof ( buf ) - off ,
" \n --- Normalizer --- \n "
" in: %llu pkts / %llu B out: %llu pkts / %llu B \n "
" frag_size=%u data_ptr=%u data_size=%u alloc_err=%u logic_err=%u \n " ,
( unsigned long long ) pn - > in_total_pkts , ( unsigned long long ) pn - > in_total_bytes ,
( unsigned long long ) pn - > out_total_pkts , ( unsigned long long ) pn - > out_total_bytes ,
pn - > frag_size , pn - > data_ptr , pn - > data_size , pn - > alloc_errors , pn - > logic_errors ) ;
}
/* Links */
int link_idx = 0 ;
struct ETCP_LINK * link = conn - > links ;
while ( link ) {
const char * is_tcp_str = link - > is_tcp ? " TCP " : " UDP " ;
char local_str [ 54 ] , remote_str [ 54 ] ;
strncpy ( local_str , link - > conn ? sockaddr_storage_to_str ( & link - > conn - > local_addr ) . str : " stcp " , sizeof ( local_str ) - 1 ) ;
strncpy ( remote_str , sockaddr_storage_to_str ( & link - > remote_addr ) . str , sizeof ( remote_str ) - 1 ) ;
off + = snprintf ( buf + off , sizeof ( buf ) - off ,
" \n --- LINK#%d: %s %s NAT=%s --- \n "
" addr: %s -> %s \n "
" RTT: %.1f ms TT: %.1f ms \n "
" Keepalive: sent=%u recv=%u period=%ums \n "
" Inflight: %u / %u B (%u pkts) \n "
" Encrypt: sent=%zu err=%zu Decrypt: rcvd=%zu err=%zu \n " ,
link_idx , link - > link_status ? " UP " : " DOWN " , is_tcp_str , nat_type_str ( link - > nat_type ) ,
local_str , remote_str ,
link - > rtt_last / 10.0f , link - > tt_last / 10.0f ,
link - > keepalive_sent_count , link - > keepalive_recv_count , link - > keepalive_interval ,
link - > inflight_bytes , link - > inflight_lim_bytes , link - > inflight_packets ,
link - > total_encrypted , link - > encrypt_errors , link - > total_decrypted , link - > decrypt_errors ) ;
link = link - > next ; link_idx + + ;
}
chat_event_post ( CHAT_EVT_CONN_METRICS , ( const uint8_t * ) buf , off ) ;
}
void chat_core_collect_status_trampoline ( void * arg ) {
( void ) arg ;
chat_core_collect_status ( ) ;
}
void chat_core_collect_conn_list_trampoline ( void * arg ) {
( void ) arg ;
collect_conn_list ( ) ;
}
void chat_core_collect_conn_metrics_trampoline ( void * arg ) {
uint64_t peer_id ;
memcpy ( & peer_id , arg , sizeof ( peer_id ) ) ;
u_free ( arg ) ;
collect_conn_metrics ( peer_id ) ;
}