@ -36,6 +36,8 @@ static void packet_dump(const char* prefix, const uint8_t* data, size_t len, str
static void etcp_link_send_init ( struct ETCP_LINK * link ) ;
static int etcp_link_send_reset ( struct ETCP_LINK * link ) ;
static void etcp_link_init_timer_cbk ( void * arg ) ;
static void etcp_link_send_keepalive ( struct ETCP_LINK * link ) ;
static void keepalive_timer_cb ( void * arg ) ;
# define INIT_TIMEOUT_INITIAL 500
# define INIT_TIMEOUT_MAX 50000
@ -112,11 +114,69 @@ static void etcp_link_init_timer_cbk(void* arg) {
DEBUG_TRACE ( DEBUG_CATEGORY_CONNECTION , " " ) ;
struct ETCP_LINK * link = ( struct ETCP_LINK * ) arg ;
if ( ! link | | link - > initialized | | link - > is_server ! = 0 ) return ;
link - > init_timer = NULL ;
etcp_link_send_init ( link ) ;
}
// Send empty keepalive packet (only timestamp, no sections)
static void etcp_link_send_keepalive ( struct ETCP_LINK * link ) {
DEBUG_TRACE ( DEBUG_CATEGORY_CONNECTION , " " ) ;
if ( ! link | | ! link - > etcp | | ! link - > etcp - > instance ) return ;
struct ETCP_DGRAM * dgram = malloc ( sizeof ( struct ETCP_DGRAM ) + 2 ) ;
if ( ! dgram ) {
DEBUG_ERROR ( DEBUG_CATEGORY_CONNECTION , " etcp_link_send_keepalive: malloc failed " ) ;
return ;
}
dgram - > link = link ;
dgram - > data_len = 0 ; // Empty packet - only timestamp in header
dgram - > noencrypt_len = 0 ;
dgram - > timestamp = get_current_timestamp ( ) ;
DEBUG_DEBUG ( DEBUG_CATEGORY_CONNECTION , " [%s] Sending keepalive on link %p (local_id=%d) " ,
link - > etcp - > log_name , link , link - > local_link_id ) ;
etcp_encrypt_send ( dgram ) ;
free ( dgram ) ;
}
// Keepalive timer callback
static void keepalive_timer_cb ( void * arg ) {
DEBUG_TRACE ( DEBUG_CATEGORY_CONNECTION , " " ) ;
struct ETCP_LINK * link = ( struct ETCP_LINK * ) arg ;
if ( ! link | | ! link - > etcp | | ! link - > etcp - > instance ) return ;
link - > keepalive_timer = NULL ;
// Skip if link is not initialized
if ( ! link - > initialized ) {
DEBUG_DEBUG ( DEBUG_CATEGORY_CONNECTION , " [%s] Keepalive skipped - link not initialized " ,
link - > etcp - > log_name ) ;
goto restart_timer ;
}
// Send keepalive only if no packets were sent since last tick
if ( ! link - > pkt_sent_since_keepalive ) {
etcp_link_send_keepalive ( link ) ;
} else {
DEBUG_DEBUG ( DEBUG_CATEGORY_CONNECTION , " [%s] Keepalive skipped - packet sent since last tick " ,
link - > etcp - > log_name ) ;
}
// Reset flag for next interval
link - > pkt_sent_since_keepalive = 0 ;
restart_timer :
// Restart timer
if ( link - > keepalive_interval > 0 ) {
link - > keepalive_timer = uasync_set_timeout ( link - > etcp - > instance - > ua ,
link - > keepalive_interval * 10 ,
link , keepalive_timer_cb ) ;
}
}
static int etcp_link_send_reset ( struct ETCP_LINK * link ) {
DEBUG_TRACE ( DEBUG_CATEGORY_CONNECTION , " " ) ;
if ( ! link ) return - 1 ;
@ -462,6 +522,12 @@ void etcp_link_close(struct ETCP_LINK* link) {
link - > shaper_timer = NULL ;
}
// Cancel keepalive timer if active
if ( link - > keepalive_timer ) {
uasync_cancel_timeout ( link - > etcp - > instance - > ua , link - > keepalive_timer ) ;
link - > keepalive_timer = NULL ;
}
// универсальное удаление из односвязного списка
struct ETCP_LINK * * pp = & link - > etcp - > links ;
while ( * pp ) {
@ -482,6 +548,11 @@ int etcp_encrypt_send(struct ETCP_DGRAM* dgram) {
// DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "etcp_encrypt_send called, link=%p", dgram ? dgram->link : NULL);
// printf("[ETCP DEBUG] etcp_encrypt_send: ENTERING FUNCTION\n");
if ( ! dgram | | ! dgram - > link ) return - 1 ;
// Mark that packet was sent (for keepalive logic)
dgram - > link - > pkt_sent_since_keepalive = 1 ;
int errcode = 0 ;
sc_context_t * sc = & dgram - > link - > etcp - > crypto_ctx ;
int len = dgram - > data_len - dgram - > noencrypt_len ; // не забываем добавить timestamp (2 bytes)
@ -702,6 +773,16 @@ static void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
memory_pool_free ( e_sock - > instance - > pkt_pool , pkt ) ;
link - > initialized = 1 ; // получен init request (server), считаем линк уже готовым к работе
// Start keepalive timer
if ( ! link - > keepalive_timer & & link - > keepalive_interval > 0 ) {
link - > keepalive_timer = uasync_set_timeout ( link - > etcp - > instance - > ua ,
link - > keepalive_interval * 10 ,
link , keepalive_timer_cb ) ;
DEBUG_DEBUG ( DEBUG_CATEGORY_CONNECTION , " [%s] Keepalive timer started on link %p (interval=%d ms) " ,
link - > etcp - > log_name , link , link - > keepalive_interval ) ;
}
loadbalancer_link_ready ( link ) ;
// Notify BGP about new connection to send routing table
@ -792,6 +873,16 @@ process_decrypted:
// Mark link as initialized
// DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "Setting link->initialized=1, link=%p, is_server=%d", link, link->is_server);
link - > initialized = 1 ; // получен init response (client)
// Start keepalive timer
if ( ! link - > keepalive_timer & & link - > keepalive_interval > 0 ) {
link - > keepalive_timer = uasync_set_timeout ( link - > etcp - > instance - > ua ,
link - > keepalive_interval * 10 ,
link , keepalive_timer_cb ) ;
DEBUG_DEBUG ( DEBUG_CATEGORY_CONNECTION , " [%s] Keepalive timer started on link %p (interval=%d ms) " ,
link - > etcp - > log_name , link , link - > keepalive_interval ) ;
}
loadbalancer_link_ready ( link ) ;
// Notify BGP about new connection to send routing table