|
|
|
|
@ -45,56 +45,51 @@ static void etcp_update_window(struct ETCP_CONN* etcp) {
|
|
|
|
|
etcp->retrans_timer_period = 20; // Default retransmit period
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Creating ETCP instance
|
|
|
|
|
// после создания надо добавить peer bublic key.
|
|
|
|
|
struct ETCP_CONN* etcp_connection_create(struct UTUN_INSTANCE* instance) { |
|
|
|
|
if (!instance) return NULL; |
|
|
|
|
|
|
|
|
|
struct ETCP_CONN* etcp = calloc(1, sizeof(struct ETCP_CONN)); |
|
|
|
|
if (!etcp) return NULL; |
|
|
|
|
// Reset connection (adapted from etcp_reset in master, without packet sending)
|
|
|
|
|
void etcp_conn_reset(struct ETCP_CONN* etcp) { |
|
|
|
|
if (!etcp) return; |
|
|
|
|
|
|
|
|
|
etcp->mtu = 1500; // Default MTU
|
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "etcp_conn_reset: resetting instance"); |
|
|
|
|
|
|
|
|
|
etcp->instance = instance; |
|
|
|
|
etcp->state = 0; |
|
|
|
|
|
|
|
|
|
// Initialize crypto context
|
|
|
|
|
if (sc_init_ctx(&etcp->crypto_ctx, &etcp->instance->my_keys) != SC_OK) { |
|
|
|
|
free(etcp); |
|
|
|
|
return NULL; |
|
|
|
|
// Cancel timers
|
|
|
|
|
if (etcp->next_tx_timer) { |
|
|
|
|
uasync_cancel_timeout(etcp->instance->ua, etcp->next_tx_timer); |
|
|
|
|
etcp->next_tx_timer = NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Initialize queues (tx_queue is input_queue)
|
|
|
|
|
etcp->input_queue = queue_new(instance->ua,NULL); |
|
|
|
|
etcp->output_queue = queue_new(instance->ua,NULL); |
|
|
|
|
if (!etcp->input_queue || !etcp->output_queue) { |
|
|
|
|
if (etcp->input_queue) queue_free(etcp->input_queue); |
|
|
|
|
if (etcp->output_queue) queue_free(etcp->output_queue); |
|
|
|
|
free(etcp); |
|
|
|
|
return NULL; |
|
|
|
|
if (etcp->retransmit_timer) { |
|
|
|
|
uasync_cancel_timeout(etcp->instance->ua, etcp->retransmit_timer); |
|
|
|
|
etcp->retransmit_timer = NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Set callback for input_queue (tx_queue)
|
|
|
|
|
queue_set_callback(etcp->input_queue, tx_queue_callback, etcp); |
|
|
|
|
|
|
|
|
|
// Initialize state (from master)
|
|
|
|
|
etcp->bandwidth = 10000; // Default: 10000 bytes per timebase (0.1us)
|
|
|
|
|
etcp->last_sent_timestamp = get_current_timestamp(); |
|
|
|
|
etcp->bytes_allowed = 0; |
|
|
|
|
etcp_update_window(etcp); // Initialize window size and retrans timer
|
|
|
|
|
// Clear queues (but keep them)
|
|
|
|
|
queue_clear(etcp->input_queue); |
|
|
|
|
queue_clear(etcp->output_queue); |
|
|
|
|
|
|
|
|
|
// Initialize lists
|
|
|
|
|
// Clear lists
|
|
|
|
|
rx_packet_t* rx = etcp->rx_list; |
|
|
|
|
while (rx) { |
|
|
|
|
rx_packet_t* next = rx->next; |
|
|
|
|
if (rx->data) free(rx->data); |
|
|
|
|
free(rx); |
|
|
|
|
rx = next; |
|
|
|
|
} |
|
|
|
|
etcp->rx_list = NULL; |
|
|
|
|
|
|
|
|
|
sent_packet_t* sent = etcp->sent_list; |
|
|
|
|
while (sent) { |
|
|
|
|
sent_packet_t* next = sent->next; |
|
|
|
|
if (sent->data) free(sent->data); |
|
|
|
|
free(sent); |
|
|
|
|
sent = next; |
|
|
|
|
} |
|
|
|
|
etcp->sent_list = NULL; |
|
|
|
|
|
|
|
|
|
// Initialize metrics
|
|
|
|
|
// Reset metrics and stats
|
|
|
|
|
etcp->rtt_last = 0; |
|
|
|
|
etcp->rtt_avg_10 = 0; |
|
|
|
|
etcp->rtt_avg_100 = 0; |
|
|
|
|
etcp->jitter = 0; |
|
|
|
|
etcp->bytes_sent_total = 0; |
|
|
|
|
|
|
|
|
|
// Initialize statistics
|
|
|
|
|
etcp->retransmissions_count = 0; |
|
|
|
|
etcp->ack_packets_count = 0; |
|
|
|
|
etcp->control_packets_count = 0; |
|
|
|
|
@ -102,37 +97,74 @@ struct ETCP_CONN* etcp_connection_create(struct UTUN_INSTANCE* instance) {
|
|
|
|
|
etcp->unique_packets_sent = 0; |
|
|
|
|
etcp->bytes_received_total = 0; |
|
|
|
|
|
|
|
|
|
// Initialize IDs
|
|
|
|
|
// Reset IDs
|
|
|
|
|
etcp->next_tx_id = 1; |
|
|
|
|
etcp->last_sent_id = 0; |
|
|
|
|
etcp->last_rx_id = 0; |
|
|
|
|
etcp->last_delivered_id = 0; |
|
|
|
|
|
|
|
|
|
// Initialize history
|
|
|
|
|
// Reset history
|
|
|
|
|
etcp->rtt_history_idx = 0; |
|
|
|
|
etcp->rtt_history_count = 0; |
|
|
|
|
|
|
|
|
|
// Initialize pending arrays
|
|
|
|
|
// Reset pending
|
|
|
|
|
etcp->pending_ack_count = 0; |
|
|
|
|
etcp->pending_retransmit_count = 0; |
|
|
|
|
|
|
|
|
|
// Initialize window management
|
|
|
|
|
// Reset window
|
|
|
|
|
etcp->unacked_bytes = 0; |
|
|
|
|
etcp->last_acked_id = 0; |
|
|
|
|
etcp->last_rx_ack_id = 0; |
|
|
|
|
etcp->retrans_timer_period = 20; // Default 2ms (20 timebase units)
|
|
|
|
|
etcp->next_retrans_time = 0; |
|
|
|
|
etcp->window_blocked = 0; |
|
|
|
|
|
|
|
|
|
// Forward progress tracking
|
|
|
|
|
// Reset forward progress
|
|
|
|
|
etcp->oldest_missing_id = 0; |
|
|
|
|
etcp->missing_since_time = 0; |
|
|
|
|
|
|
|
|
|
// No timers yet
|
|
|
|
|
etcp->next_tx_timer = NULL; |
|
|
|
|
etcp->retransmit_timer = NULL; |
|
|
|
|
etcp_update_window(etcp); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "etcp_create: created instance with node_id=%llu, mtu=%d",
|
|
|
|
|
// Creating ETCP instance
|
|
|
|
|
// после создания надо добавить peer bublic key.
|
|
|
|
|
struct ETCP_CONN* etcp_connection_create(struct UTUN_INSTANCE* instance) { |
|
|
|
|
if (!instance) return NULL; |
|
|
|
|
|
|
|
|
|
struct ETCP_CONN* etcp = calloc(1, sizeof(struct ETCP_CONN)); |
|
|
|
|
if (!etcp) return NULL; |
|
|
|
|
|
|
|
|
|
etcp->mtu = 1500; // Default MTU
|
|
|
|
|
|
|
|
|
|
etcp->instance = instance; |
|
|
|
|
|
|
|
|
|
// Initialize crypto context
|
|
|
|
|
if (sc_init_ctx(&etcp->crypto_ctx, &etcp->instance->my_keys) != SC_OK) { |
|
|
|
|
free(etcp); |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Initialize queues (tx_queue is input_queue)
|
|
|
|
|
etcp->input_queue = queue_new(instance->ua,NULL); |
|
|
|
|
etcp->output_queue = queue_new(instance->ua,NULL); |
|
|
|
|
if (!etcp->input_queue || !etcp->output_queue) { |
|
|
|
|
if (etcp->input_queue) queue_free(etcp->input_queue); |
|
|
|
|
if (etcp->output_queue) queue_free(etcp->output_queue); |
|
|
|
|
free(etcp); |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Set callback for input_queue (tx_queue)
|
|
|
|
|
queue_set_callback(etcp->input_queue, tx_queue_callback, etcp); |
|
|
|
|
|
|
|
|
|
// Initialize state (from master)
|
|
|
|
|
etcp->bandwidth = 10000; // Default: 10000 bytes per timebase (0.1us)
|
|
|
|
|
etcp->last_sent_timestamp = get_current_timestamp(); |
|
|
|
|
etcp->bytes_allowed = 0; |
|
|
|
|
|
|
|
|
|
// Reset all other fields to initial state
|
|
|
|
|
etcp_conn_reset(etcp); |
|
|
|
|
|
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "etcp_connection_create: created instance with node_id=%llu, mtu=%d",
|
|
|
|
|
(unsigned long long)etcp->instance->node_id, etcp->mtu); |
|
|
|
|
|
|
|
|
|
etcp->next=instance->connections; |
|
|
|
|
@ -144,10 +176,10 @@ struct ETCP_CONN* etcp_connection_create(struct UTUN_INSTANCE* instance) {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Destroying ETCP instance
|
|
|
|
|
void etcp_destroy(struct ETCP_CONN* etcp) { |
|
|
|
|
void etcp_connection_close(struct ETCP_CONN* etcp) { |
|
|
|
|
if (!etcp) return; |
|
|
|
|
|
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "etcp_destroy: destroying instance"); |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "etcp_connection_close: destroying instance"); |
|
|
|
|
|
|
|
|
|
// Cancel timers
|
|
|
|
|
if (etcp->next_tx_timer) { |
|
|
|
|
@ -185,8 +217,10 @@ void etcp_destroy(struct ETCP_CONN* etcp) {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Process incoming packet (partial, truncated in original)
|
|
|
|
|
void etcp_conn_input(struct ETCP_CONN* etcp, struct ETCP_DGRAM* pkt) { |
|
|
|
|
if (!etcp || !pkt) return; |
|
|
|
|
void etcp_conn_input(struct ETCP_DGRAM* pkt) { |
|
|
|
|
if (!pkt) return; |
|
|
|
|
struct ETCP_CONN* etcp=pkt->link->etcp; |
|
|
|
|
if (!etcp) return; |
|
|
|
|
|
|
|
|
|
uint8_t* data = pkt->data; |
|
|
|
|
size_t len = pkt->data_len; |
|
|
|
|
@ -327,88 +361,6 @@ void etcp_conn_input(struct ETCP_CONN* etcp, struct ETCP_DGRAM* pkt) {
|
|
|
|
|
schedule_ack_timer(etcp); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Reset connection (adapted from etcp_reset in master, without packet sending)
|
|
|
|
|
void etcp_conn_reset(struct ETCP_CONN* etcp) { |
|
|
|
|
if (!etcp) return; |
|
|
|
|
|
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "etcp_conn_reset: resetting instance"); |
|
|
|
|
|
|
|
|
|
// Reset state
|
|
|
|
|
etcp->state = 0; |
|
|
|
|
|
|
|
|
|
// Cancel timers
|
|
|
|
|
if (etcp->next_tx_timer) { |
|
|
|
|
uasync_cancel_timeout(etcp->instance->ua, etcp->next_tx_timer); |
|
|
|
|
etcp->next_tx_timer = NULL; |
|
|
|
|
} |
|
|
|
|
if (etcp->retransmit_timer) { |
|
|
|
|
uasync_cancel_timeout(etcp->instance->ua, etcp->retransmit_timer); |
|
|
|
|
etcp->retransmit_timer = NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Clear queues (but keep them)
|
|
|
|
|
queue_clear(etcp->input_queue); |
|
|
|
|
queue_clear(etcp->output_queue); |
|
|
|
|
|
|
|
|
|
// Clear lists
|
|
|
|
|
rx_packet_t* rx = etcp->rx_list; |
|
|
|
|
while (rx) { |
|
|
|
|
rx_packet_t* next = rx->next; |
|
|
|
|
if (rx->data) free(rx->data); |
|
|
|
|
free(rx); |
|
|
|
|
rx = next; |
|
|
|
|
} |
|
|
|
|
etcp->rx_list = NULL; |
|
|
|
|
|
|
|
|
|
sent_packet_t* sent = etcp->sent_list; |
|
|
|
|
while (sent) { |
|
|
|
|
sent_packet_t* next = sent->next; |
|
|
|
|
if (sent->data) free(sent->data); |
|
|
|
|
free(sent); |
|
|
|
|
sent = next; |
|
|
|
|
} |
|
|
|
|
etcp->sent_list = NULL; |
|
|
|
|
|
|
|
|
|
// Reset metrics and stats
|
|
|
|
|
etcp->rtt_last = 0; |
|
|
|
|
etcp->rtt_avg_10 = 0; |
|
|
|
|
etcp->rtt_avg_100 = 0; |
|
|
|
|
etcp->jitter = 0; |
|
|
|
|
etcp->bytes_sent_total = 0; |
|
|
|
|
etcp->retransmissions_count = 0; |
|
|
|
|
etcp->ack_packets_count = 0; |
|
|
|
|
etcp->control_packets_count = 0; |
|
|
|
|
etcp->total_packets_sent = 0; |
|
|
|
|
etcp->unique_packets_sent = 0; |
|
|
|
|
etcp->bytes_received_total = 0; |
|
|
|
|
|
|
|
|
|
// Reset IDs
|
|
|
|
|
etcp->next_tx_id = 1; |
|
|
|
|
etcp->last_sent_id = 0; |
|
|
|
|
etcp->last_rx_id = 0; |
|
|
|
|
etcp->last_delivered_id = 0; |
|
|
|
|
|
|
|
|
|
// Reset history
|
|
|
|
|
etcp->rtt_history_idx = 0; |
|
|
|
|
etcp->rtt_history_count = 0; |
|
|
|
|
|
|
|
|
|
// Reset pending
|
|
|
|
|
etcp->pending_ack_count = 0; |
|
|
|
|
etcp->pending_retransmit_count = 0; |
|
|
|
|
|
|
|
|
|
// Reset window
|
|
|
|
|
etcp->unacked_bytes = 0; |
|
|
|
|
etcp->last_acked_id = 0; |
|
|
|
|
etcp->last_rx_ack_id = 0; |
|
|
|
|
etcp->next_retrans_time = 0; |
|
|
|
|
etcp->window_blocked = 0; |
|
|
|
|
|
|
|
|
|
// Reset forward progress
|
|
|
|
|
etcp->oldest_missing_id = 0; |
|
|
|
|
etcp->missing_since_time = 0; |
|
|
|
|
|
|
|
|
|
etcp_update_window(etcp); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Getting statistics (extended with master stats)
|
|
|
|
|
void etcp_get_stats(struct ETCP_CONN* etcp, size_t* packets_sent, size_t* packets_recv, |
|
|
|
|
|