@ -786,10 +786,9 @@ int etcp_int_send(struct ETCP_CONN* etcp, const void* data, uint16_t len) {
DEBUG_DEBUG ( DEBUG_CATEGORY_ETCP , " [%s] created PACKET %p with data %p (len=%zu) " , etcp - > log_name , pkt , packet_data , len ) ;
DEBUG_DEBUG ( DEBUG_CATEGORY_ETCP , " [%s] created PACKET %p with data %p (len=%zu) " , etcp - > log_name , pkt , packet_data , len ) ;
// Add to input queue - input_queue_cb will process it
// Add to input queue - input_queue_cb will process it
// При провале queue_data_put сам освобождает entry+dgram, повторный free дал бы double-free.
if ( queue_data_put ( etcp - > input_queue , ( struct ll_entry * ) pkt ) ! = 0 ) {
if ( queue_data_put ( etcp - > input_queue , ( struct ll_entry * ) pkt ) ! = 0 ) {
DEBUG_ERROR ( DEBUG_CATEGORY_ETCP , " [%s] failed to add to input queue " , etcp - > log_name ) ;
DEBUG_ERROR ( DEBUG_CATEGORY_ETCP , " [%s] failed to add to input queue " , etcp - > log_name ) ;
queue_dgram_free ( & pkt - > ll ) ;
queue_entry_free ( & pkt - > ll ) ;
return - 1 ;
return - 1 ;
}
}
@ -923,10 +922,9 @@ static void input_queue_cb(struct ll_queue* q, void* arg) {
int len = p - > ll . len ; // сохраним len
int len = p - > ll . len ; // сохраним len
// Add to send queue
// Add to send queue
// При провале queue_data_put_with_index сам освобождает entry+dgram, повторный free дал бы double-free.
if ( queue_data_put_with_index ( etcp - > input_send_q , & p - > ll ) ! = 0 ) {
if ( queue_data_put_with_index ( etcp - > input_send_q , & p - > ll ) ! = 0 ) {
DEBUG_ERROR ( DEBUG_CATEGORY_ETCP , " [%s] failed to add packet seq=%u to input_send_q " , etcp - > log_name , p - > seq ) ;
DEBUG_ERROR ( DEBUG_CATEGORY_ETCP , " [%s] failed to add packet seq=%u to input_send_q " , etcp - > log_name , p - > seq ) ;
queue_dgram_free ( & p - > ll ) ;
queue_entry_free ( & p - > ll ) ;
DEBUG_TRACE ( DEBUG_CATEGORY_ETCP , " [%s] EXIT (queue put failed) " , etcp - > log_name ) ;
DEBUG_TRACE ( DEBUG_CATEGORY_ETCP , " [%s] EXIT (queue put failed) " , etcp - > log_name ) ;
return ;
return ;
}
}
@ -1397,16 +1395,18 @@ void etcp_output_try_assembly(struct ETCP_CONN* etcp) {
DEBUG_TRACE ( DEBUG_CATEGORY_ETCP , " [%s] moving packet id=%u to output_queue (qlen=%d) " , etcp - > log_name ,
DEBUG_TRACE ( DEBUG_CATEGORY_ETCP , " [%s] moving packet id=%u to output_queue (qlen=%d) " , etcp - > log_name ,
next_expected_id , etcp - > output_queue - > count ) ;
next_expected_id , etcp - > output_queue - > count ) ;
uint16_t pkt_len = rx_pkt - > ll . len ;
uint16_t pkt_len = rx_pkt - > ll . len ;
if ( queue_data_put ( etcp - > output_queue , ( struct ll_entry * ) rx_pkt ) = = 0 ) {
// На провале queue_data_put сам освобождает rx_pkt — re-put дал бы double-free.
delivered_bytes + = pkt_len ;
if ( queue_data_put ( etcp - > output_queue , ( struct ll_entry * ) rx_pkt ) ! = 0 ) {
delivered_count + + ;
} else {
DEBUG_ERROR ( DEBUG_CATEGORY_ETCP , " [%s] failed to add packet id=%u to output_queue " , etcp - > log_name ,
DEBUG_ERROR ( DEBUG_CATEGORY_ETCP , " [%s] failed to add packet id=%u to output_queue " , etcp - > log_name ,
next_expected_id ) ;
next_expected_id ) ;
// Put it back in recv_q if we can't add to output_queue
queue_data_put_with_index ( etcp - > recv_q , ( struct ll_entry * ) rx_pkt ) ;
break ;
break ;
}
}
// pn_unpacker_cb (вызывается из put синхронно) мог ре-энтрантно сделать reinit/close:
// при reinit last_delivered_id уже сброшен в 0 и recv_q очищен, при close state==2.
if ( etcp - > state = = 2 | | etcp - > reinit_pending ) break ;
delivered_bytes + = pkt_len ;
delivered_count + + ;
// Update state for next iteration
// Update state for next iteration
etcp - > last_delivered_id = next_expected_id ;
etcp - > last_delivered_id = next_expected_id ;
@ -1506,6 +1506,7 @@ void etcp_ack_recv(struct ETCP_CONN* etcp, uint32_t seq, uint16_t ts, uint16_t d
DEBUG_DEBUG ( DEBUG_CATEGORY_ETCP , " [%s] TX removed packet seq=%u from wait_ack, unacked_bytes now %u total acked=%u " , etcp - > log_name , seq , etcp - > unacked_bytes , etcp - > ack_packets_count ) ;
DEBUG_DEBUG ( DEBUG_CATEGORY_ETCP , " [%s] TX removed packet seq=%u from wait_ack, unacked_bytes now %u total acked=%u " , etcp - > log_name , seq , etcp - > unacked_bytes , etcp - > ack_packets_count ) ;
if ( acked_pkt - > ll . dgram ) {
if ( acked_pkt - > ll . dgram ) {
DEBUG_DEBUG ( DEBUG_CATEGORY_ETCP , " [%s] TX-ACK free dgram=%p seq=%u " , etcp - > log_name , acked_pkt - > ll . dgram , seq ) ;
memory_pool_free ( etcp - > instance - > data_pool , acked_pkt - > ll . dgram ) ;
memory_pool_free ( etcp - > instance - > data_pool , acked_pkt - > ll . dgram ) ;
}
}
memory_pool_free ( etcp - > inflight_pool , acked_pkt ) ;
memory_pool_free ( etcp - > inflight_pool , acked_pkt ) ;
@ -1542,6 +1543,8 @@ void etcp_conn_input(struct ETCP_DGRAM* pkt) {
DEBUG_DEBUG ( DEBUG_CATEGORY_ETCP , " [%s] RX pkt dlen=%d " , etcp - > log_name , len ) ;
DEBUG_DEBUG ( DEBUG_CATEGORY_ETCP , " [%s] RX pkt dlen=%d " , etcp - > log_name , len ) ;
while ( len > = 1 ) {
while ( len > = 1 ) {
// Ре-энтрантный reinit/close (из pn_unpacker_cb/etcp_int_recv) — дальше разбирать пакет нельзя.
if ( etcp - > state = = 2 | | etcp - > reinit_pending ) break ;
uint8_t type = data [ 0 ] ;
uint8_t type = data [ 0 ] ;
// Process sections as per protocol.txt
// Process sections as per protocol.txt
@ -1812,7 +1815,8 @@ void etcp_conn_input(struct ETCP_DGRAM* pkt) {
}
}
if ( memory_pool_is_freed ( pkt - > link - > etcp - > instance - > pkt_pool , pkt ) ) {
// Используем локальный etcp (валиден до phase 2 close): pkt->link мог быть освобождён ре-энтрантным close.
if ( memory_pool_is_freed ( etcp - > instance - > pkt_pool , pkt ) ) {
DEBUG_ERROR ( DEBUG_CATEGORY_ETCP , " pkt=%p ALREADY FREED in pkt_pool — HALTING " , ( void * ) pkt ) ;
DEBUG_ERROR ( DEBUG_CATEGORY_ETCP , " pkt=%p ALREADY FREED in pkt_pool — HALTING " , ( void * ) pkt ) ;
volatile int _halt = 1 ; while ( _halt ) { }
volatile int _halt = 1 ; while ( _halt ) { }
}
}