diff --git a/picoquic/picoquic_internal.h b/picoquic/picoquic_internal.h index 885b222d48ab680de194680f120edb689e45f9a7..664a120e7b65240df49ca497e21f5e275b965eb4 100644 --- a/picoquic/picoquic_internal.h +++ b/picoquic/picoquic_internal.h @@ -755,7 +755,7 @@ void picoquic_register_path(picoquic_cnx_t* cnx, picoquic_path_t * path_x); void picoquic_delete_path(picoquic_cnx_t* cnx, int path_index); void picoquic_demote_path(picoquic_cnx_t* cnx, int path_index, uint64_t current_time); void picoquic_promote_path_to_default(picoquic_cnx_t* cnx, int path_index, uint64_t current_time); -void picoquic_delete_abandoned_paths(picoquic_cnx_t* cnx, uint64_t current_time); +void picoquic_delete_abandoned_paths(picoquic_cnx_t* cnx, uint64_t current_time, uint64_t * next_wake_time); /* Management of the CNX-ID stash */ picoquic_cnxid_stash_t * picoquic_dequeue_cnxid_stash(picoquic_cnx_t* cnx); diff --git a/picoquic/quicctx.c b/picoquic/quicctx.c index b000d83e3384ca25258cbf34ea7b2dce0406755a..3bd56eb1099760b93950692fe37bf986fd12dbf2 100644 --- a/picoquic/quicctx.c +++ b/picoquic/quicctx.c @@ -864,7 +864,7 @@ void picoquic_delete_path(picoquic_cnx_t* cnx, int path_index) * Path challenges may be abandoned if they are tried too many times without success. */ -void picoquic_delete_abandoned_paths(picoquic_cnx_t* cnx, uint64_t current_time) +void picoquic_delete_abandoned_paths(picoquic_cnx_t* cnx, uint64_t current_time, uint64_t * next_wake_time) { int path_index_good = 1; int path_index_current = 1; @@ -876,6 +876,12 @@ void picoquic_delete_abandoned_paths(picoquic_cnx_t* cnx, uint64_t current_time) /* Only increment the current index */ path_index_current++; } else { + if (cnx->path[path_index_current]->path_is_demoted && + current_time < cnx->path[path_index_current]->demotion_time && + *next_wake_time > cnx->path[path_index_current]->demotion_time) { + *next_wake_time = cnx->path[path_index_current]->demotion_time; + } + if (path_index_current > path_index_good) { /* swap the path indexed good with current */ picoquic_path_t * path_x = cnx->path[path_index_current]; diff --git a/picoquic/sender.c b/picoquic/sender.c index 397e12056f2547dca9d5003b9e18119b8f633bee..d6e891604a7f6f2f34c5a7c707ac88e3a53f0c99 100644 --- a/picoquic/sender.c +++ b/picoquic/sender.c @@ -1148,52 +1148,6 @@ uint32_t picoquic_prepare_mtu_probe(picoquic_cnx_t* cnx, return probe_length - checksum_length; } -static uint64_t picoquic_get_challenge_wake_time(picoquic_cnx_t* cnx, uint64_t current_time, uint64_t next_wake_time) -{ - picoquic_probe_t * probe = cnx->probe_first; - - /* Consider demotions */ - for (int i = 0; next_wake_time > current_time && i < cnx->nb_paths; i++) { - if (cnx->path[i]->path_is_demoted) { - if (cnx->path[i]->demotion_time < next_wake_time) { - next_wake_time = cnx->path[i]->demotion_time; - } - } - else { - if (cnx->path[i]->response_required) { - next_wake_time = current_time; - break; - } - - if (cnx->path[i]->challenge_verified == 0 && cnx->path[i]->path_is_activated) { - uint64_t next_challenge_time = cnx->path[i]->challenge_time + cnx->path[i]->retransmit_timer; - - if (next_challenge_time < next_wake_time) { - next_wake_time = next_challenge_time; - } - } - } - } - - /* Consider probe timers */ - while (probe != NULL && next_wake_time > current_time) { - if (probe->challenge_verified == 0) { - uint64_t next_challenge_time = probe->challenge_time + cnx->path[0]->retransmit_timer; - - if (next_challenge_time <= next_wake_time) { - next_wake_time = next_challenge_time; - } - } - probe = probe->next_probe; - } - - if (next_wake_time < current_time) { - next_wake_time = current_time; - } - - return next_wake_time; -} - /* Prepare the next packet to 0-RTT packet to send in the client initial * state, when 0-RTT is available */ @@ -1378,12 +1332,11 @@ void picoquic_implicit_handshake_ack(picoquic_cnx_t* cnx, picoquic_packet_contex /* Prepare the next packet to send when in one of the client initial states */ int picoquic_prepare_packet_client_init(picoquic_cnx_t* cnx, picoquic_path_t * path_x, picoquic_packet_t* packet, - uint64_t current_time, uint8_t* send_buffer, size_t send_buffer_max, size_t* send_length) + uint64_t current_time, uint8_t* send_buffer, size_t send_buffer_max, size_t* send_length, uint64_t * next_wake_time) { int ret = 0; int tls_ready = 0; picoquic_packet_type_enum packet_type = 0; - uint64_t next_wake_time = cnx->start_time + PICOQUIC_MICROSEC_HANDSHAKE_MAX; uint32_t checksum_overhead = 8; int is_cleartext_mode = 1; size_t data_bytes = 0; @@ -1394,6 +1347,10 @@ int picoquic_prepare_packet_client_init(picoquic_cnx_t* cnx, picoquic_path_t * p int epoch = 0; picoquic_packet_context_enum pc = picoquic_packet_context_initial; + if (*next_wake_time > cnx->start_time + PICOQUIC_MICROSEC_HANDSHAKE_MAX) { + *next_wake_time = cnx->start_time + PICOQUIC_MICROSEC_HANDSHAKE_MAX; + } + if (cnx->tls_stream[0].send_queue == NULL) { if (cnx->crypto_context[1].aead_encrypt != NULL && cnx->tls_stream[1].send_queue != NULL) { @@ -1439,12 +1396,12 @@ int picoquic_prepare_packet_client_init(picoquic_cnx_t* cnx, picoquic_path_t * p * on initial context */ if (ret == 0 && epoch > 0) { length = picoquic_prepare_packet_old_context(cnx, picoquic_packet_context_initial, - path_x, packet, send_buffer_max, current_time, &next_wake_time, &header_length); + path_x, packet, send_buffer_max, current_time, next_wake_time, &header_length); } if (ret == 0 && epoch > 1 && length == 0) { length = picoquic_prepare_packet_old_context(cnx, picoquic_packet_context_application, - path_x, packet, send_buffer_max, current_time, &next_wake_time, &header_length); + path_x, packet, send_buffer_max, current_time, next_wake_time, &header_length); } /* If there is nothing to send in previous context, check this one too */ @@ -1456,7 +1413,7 @@ int picoquic_prepare_packet_client_init(picoquic_cnx_t* cnx, picoquic_path_t * p tls_ready = picoquic_is_tls_stream_ready(cnx); if (ret == 0 && retransmit_possible && - (length = picoquic_retransmit_needed(cnx, pc, path_x, current_time, &next_wake_time, packet, send_buffer_max, &is_cleartext_mode, &header_length)) > 0) { + (length = picoquic_retransmit_needed(cnx, pc, path_x, current_time, next_wake_time, packet, send_buffer_max, &is_cleartext_mode, &header_length)) > 0) { /* Check whether it makes sens to add an ACK at the end of the retransmission */ if (epoch != 1) { ret = picoquic_prepare_ack_frame(cnx, current_time, pc, &bytes[length], @@ -1466,7 +1423,7 @@ int picoquic_prepare_packet_client_init(picoquic_cnx_t* cnx, picoquic_path_t * p } else if (ret == PICOQUIC_ERROR_FRAME_BUFFER_TOO_SMALL) { ret = 0; - next_wake_time = current_time; + *next_wake_time = current_time; } } /* document the send time & overhead */ @@ -1496,7 +1453,7 @@ int picoquic_prepare_packet_client_init(picoquic_cnx_t* cnx, picoquic_path_t * p if ((tls_ready == 0 || path_x->cwin <= path_x->bytes_in_transit) && (cnx->cnx_state == picoquic_state_client_almost_ready - || picoquic_is_ack_needed(cnx, current_time, &next_wake_time, pc) == 0) + || picoquic_is_ack_needed(cnx, current_time, next_wake_time, pc) == 0) && cnx->first_misc_frame == NULL) { length = 0; } @@ -1510,7 +1467,7 @@ int picoquic_prepare_packet_client_init(picoquic_cnx_t* cnx, picoquic_path_t * p } else if (ret == PICOQUIC_ERROR_FRAME_BUFFER_TOO_SMALL) { ret = 0; - next_wake_time = current_time; + *next_wake_time = current_time; } } @@ -1524,7 +1481,7 @@ int picoquic_prepare_packet_client_init(picoquic_cnx_t* cnx, picoquic_path_t * p } else if (ret == PICOQUIC_ERROR_FRAME_BUFFER_TOO_SMALL) { ret = 0; - next_wake_time = current_time; + *next_wake_time = current_time; } } @@ -1539,7 +1496,7 @@ int picoquic_prepare_packet_client_init(picoquic_cnx_t* cnx, picoquic_path_t * p else { if (ret == PICOQUIC_ERROR_FRAME_BUFFER_TOO_SMALL) { ret = 0; - next_wake_time = current_time; + *next_wake_time = current_time; } break; } @@ -1557,7 +1514,7 @@ int picoquic_prepare_packet_client_init(picoquic_cnx_t* cnx, picoquic_path_t * p } else if (ret == PICOQUIC_ERROR_FRAME_BUFFER_TOO_SMALL) { ret = 0; - next_wake_time = current_time; + *next_wake_time = current_time; } } @@ -1612,20 +1569,12 @@ int picoquic_prepare_packet_client_init(picoquic_cnx_t* cnx, picoquic_path_t * p &path_x->remote_cnxid, &path_x->local_cnxid, path_x, current_time); } - if (*send_length > 0) { - next_wake_time = current_time; - } - - if (cnx->cnx_state != picoquic_state_draining) { - picoquic_reinsert_by_wake_time(cnx->quic, cnx, next_wake_time); - } - return ret; } /* Prepare the next packet to send when in one the server initial states */ int picoquic_prepare_packet_server_init(picoquic_cnx_t* cnx, picoquic_path_t * path_x, picoquic_packet_t* packet, - uint64_t current_time, uint8_t* send_buffer, size_t send_buffer_max, size_t* send_length) + uint64_t current_time, uint8_t* send_buffer, size_t send_buffer_max, size_t* send_length, uint64_t * next_wake_time) { int ret = 0; int tls_ready = 0; @@ -1638,7 +1587,10 @@ int picoquic_prepare_packet_server_init(picoquic_cnx_t* cnx, picoquic_path_t * p uint32_t header_length = 0; uint8_t* bytes = packet->bytes; uint32_t length = 0; - uint64_t next_wake_time = current_time + PICOQUIC_MICROSEC_HANDSHAKE_MAX; + + if (*next_wake_time > cnx->start_time + PICOQUIC_MICROSEC_HANDSHAKE_MAX) { + *next_wake_time = cnx->start_time + PICOQUIC_MICROSEC_HANDSHAKE_MAX; + } /* The only purpose of the test below is to appease the static analyzer, so it * wont complain of possible NULL deref. On windows we could use "__assume(path_x != NULL)" @@ -1656,16 +1608,14 @@ int picoquic_prepare_packet_server_init(picoquic_cnx_t* cnx, picoquic_path_t * p send_buffer_max = (send_buffer_max > path_x->send_mtu) ? path_x->send_mtu : send_buffer_max; - /* If context is handshake, verify first that there is no need for retransmit or ack * on initial context */ if (ret == 0 && pc == picoquic_packet_context_handshake) { length = picoquic_prepare_packet_old_context(cnx, picoquic_packet_context_initial, - path_x, packet, send_buffer_max, current_time, &next_wake_time, &header_length); + path_x, packet, send_buffer_max, current_time, next_wake_time, &header_length); } if (length == 0) { - checksum_overhead = picoquic_get_checksum_length(cnx, is_cleartext_mode); tls_ready = picoquic_is_tls_stream_ready(cnx); @@ -1718,8 +1668,8 @@ int picoquic_prepare_packet_server_init(picoquic_cnx_t* cnx, picoquic_path_t * p packet->length = length; } - else if (path_x->challenge_time + path_x->retransmit_timer < next_wake_time) { - next_wake_time = path_x->challenge_time + path_x->retransmit_timer; + else if (path_x->challenge_time + path_x->retransmit_timer < *next_wake_time) { + *next_wake_time = path_x->challenge_time + path_x->retransmit_timer; } } } @@ -1750,7 +1700,7 @@ int picoquic_prepare_packet_server_init(picoquic_cnx_t* cnx, picoquic_path_t * p else if (ret == PICOQUIC_ERROR_FRAME_BUFFER_TOO_SMALL) { /* todo: reset offset to previous position? */ ret = 0; - next_wake_time = current_time; + *next_wake_time = current_time; } /* progress the state if the epoch data is all sent */ @@ -1767,7 +1717,7 @@ int picoquic_prepare_packet_server_init(picoquic_cnx_t* cnx, picoquic_path_t * p packet->length = length; } - else if ((length = picoquic_retransmit_needed(cnx, pc, path_x, current_time, &next_wake_time, packet, send_buffer_max, &is_cleartext_mode, &header_length)) > 0) { + else if ((length = picoquic_retransmit_needed(cnx, pc, path_x, current_time, next_wake_time, packet, send_buffer_max, &is_cleartext_mode, &header_length)) > 0) { /* Set the new checksum length */ checksum_overhead = picoquic_get_checksum_length(cnx, is_cleartext_mode); /* Check whether it makes sens to add an ACK at the end of the retransmission */ @@ -1779,7 +1729,7 @@ int picoquic_prepare_packet_server_init(picoquic_cnx_t* cnx, picoquic_path_t * p } else if (ret == PICOQUIC_ERROR_FRAME_BUFFER_TOO_SMALL) { ret = 0; - next_wake_time = current_time; + *next_wake_time = current_time; } /* document the send time & overhead */ packet->send_time = current_time; @@ -1797,7 +1747,7 @@ int picoquic_prepare_packet_server_init(picoquic_cnx_t* cnx, picoquic_path_t * p } else if (ret == PICOQUIC_ERROR_FRAME_BUFFER_TOO_SMALL) { ret = 0; - next_wake_time = current_time; + *next_wake_time = current_time; } } else { length = 0; @@ -1810,18 +1760,12 @@ int picoquic_prepare_packet_server_init(picoquic_cnx_t* cnx, picoquic_path_t * p send_length, send_buffer, (uint32_t)send_buffer_max, &path_x->remote_cnxid, &path_x->local_cnxid, path_x, current_time); - if (*send_length > 0) { - next_wake_time = current_time; - } - - picoquic_reinsert_by_wake_time(cnx->quic, cnx, next_wake_time); - return ret; } /* Prepare the next packet to send when in one the closing states */ int picoquic_prepare_packet_closing(picoquic_cnx_t* cnx, picoquic_path_t * path_x, picoquic_packet_t* packet, - uint64_t current_time, uint8_t* send_buffer, size_t send_buffer_max, size_t* send_length) + uint64_t current_time, uint8_t* send_buffer, size_t send_buffer_max, size_t* send_length, uint64_t * next_wake_time) { int ret = 0; /* TODO: manage multiple streams. */ @@ -1908,7 +1852,7 @@ int picoquic_prepare_packet_closing(picoquic_cnx_t* cnx, picoquic_path_t * path_ length += (uint32_t)consumed; } cnx->cnx_state = picoquic_state_draining; - picoquic_reinsert_by_wake_time(cnx->quic, cnx, exit_time); + *next_wake_time = exit_time; } else if (ret == 0 && cnx->cnx_state == picoquic_state_closing) { /* if more than 3*RTO is elapsed, move to disconnected */ @@ -1916,6 +1860,7 @@ int picoquic_prepare_packet_closing(picoquic_cnx_t* cnx, picoquic_path_t * path_ if (current_time >= exit_time) { cnx->cnx_state = picoquic_state_disconnected; + *next_wake_time = current_time; } else if (current_time >= cnx->next_wake_time) { uint64_t delta_t = path_x->rtt_min; @@ -1954,7 +1899,8 @@ int picoquic_prepare_packet_closing(picoquic_cnx_t* cnx, picoquic_path_t * path_ if (next_time > exit_time) { next_time = exit_time; } - picoquic_reinsert_by_wake_time(cnx->quic, cnx, next_time); + + *next_wake_time = next_time; } } else if (ret == 0 && cnx->cnx_state == picoquic_state_draining) { @@ -1964,9 +1910,10 @@ int picoquic_prepare_packet_closing(picoquic_cnx_t* cnx, picoquic_path_t * path_ if (current_time >= exit_time) { cnx->cnx_state = picoquic_state_disconnected; + *next_wake_time = current_time; } else { - picoquic_reinsert_by_wake_time(cnx->quic, cnx, exit_time); + *next_wake_time = exit_time; } length = 0; } @@ -2012,12 +1959,13 @@ int picoquic_prepare_packet_closing(picoquic_cnx_t* cnx, picoquic_path_t * path_ if (cnx->cnx_state == picoquic_state_handshake_failure) { cnx->cnx_state = picoquic_state_disconnected; + *next_wake_time = current_time; } else { cnx->cnx_state = picoquic_state_closing; } cnx->latest_progress_time = current_time; - picoquic_reinsert_by_wake_time(cnx->quic, cnx, current_time + delta_t); + *next_wake_time = current_time + delta_t; cnx->pkt_ctx[pc].ack_needed = 0; if (cnx->callback_fn) { @@ -2061,7 +2009,7 @@ int picoquic_prepare_new_path_and_id(picoquic_cnx_t* cnx, uint8_t* bytes, size_t /* Prepare the next packet to send when in one the ready states */ int picoquic_prepare_packet_ready(picoquic_cnx_t* cnx, picoquic_path_t * path_x, picoquic_packet_t* packet, - uint64_t current_time, uint8_t* send_buffer, size_t send_buffer_max, size_t* send_length) + uint64_t current_time, uint8_t* send_buffer, size_t send_buffer_max, size_t* send_length, uint64_t * next_wake_time) { int ret = 0; /* TODO: manage multiple streams. */ @@ -2077,7 +2025,6 @@ int picoquic_prepare_packet_ready(picoquic_cnx_t* cnx, picoquic_path_t * path_x, uint32_t length = 0; uint32_t checksum_overhead = picoquic_get_checksum_length(cnx, is_cleartext_mode); uint32_t send_buffer_min_max = (send_buffer_max > path_x->send_mtu) ? path_x->send_mtu : (uint32_t)send_buffer_max; - uint64_t next_wake_time = cnx->latest_progress_time + PICOQUIC_MICROSEC_SILENCE_MAX * (2 - cnx->client_mode); /* * Manage the end of false start transition. @@ -2102,11 +2049,11 @@ int picoquic_prepare_packet_ready(picoquic_cnx_t* cnx, picoquic_path_t * path_x, if (ret == 0) { length = picoquic_prepare_packet_old_context(cnx, picoquic_packet_context_initial, - path_x, packet, send_buffer_min_max, current_time, &next_wake_time, &header_length); + path_x, packet, send_buffer_min_max, current_time, next_wake_time, &header_length); if (length == 0) { length = picoquic_prepare_packet_old_context(cnx, picoquic_packet_context_handshake, - path_x, packet, send_buffer_min_max, current_time, &next_wake_time, &header_length); + path_x, packet, send_buffer_min_max, current_time, next_wake_time, &header_length); } } @@ -2116,7 +2063,7 @@ int picoquic_prepare_packet_ready(picoquic_cnx_t* cnx, picoquic_path_t * path_x, packet->pc = pc; if (ret == 0 && - (length = picoquic_retransmit_needed(cnx, pc, path_x, current_time, &next_wake_time, packet, send_buffer_min_max, &is_cleartext_mode, &header_length)) > 0) { + (length = picoquic_retransmit_needed(cnx, pc, path_x, current_time, next_wake_time, packet, send_buffer_min_max, &is_cleartext_mode, &header_length)) > 0) { /* Set the new checksum length */ checksum_overhead = picoquic_get_checksum_length(cnx, is_cleartext_mode); /* Check whether it makes sense to add an ACK at the end of the retransmission */ @@ -2162,7 +2109,7 @@ int picoquic_prepare_packet_ready(picoquic_cnx_t* cnx, picoquic_path_t * path_x, } else { if (ret == PICOQUIC_ERROR_FRAME_BUFFER_TOO_SMALL) { - next_wake_time = current_time; + *next_wake_time = current_time; ret = 0; } } @@ -2182,8 +2129,8 @@ int picoquic_prepare_packet_ready(picoquic_cnx_t* cnx, picoquic_path_t * path_x, } } else { - if (path_x->challenge_time + path_x->retransmit_timer < next_wake_time) { - next_wake_time = path_x->challenge_time + path_x->retransmit_timer; + if (path_x->challenge_time + path_x->retransmit_timer < *next_wake_time) { + *next_wake_time = path_x->challenge_time + path_x->retransmit_timer; } } } @@ -2198,7 +2145,7 @@ int picoquic_prepare_packet_ready(picoquic_cnx_t* cnx, picoquic_path_t * path_x, if (cnx->cnx_state != picoquic_state_disconnected && path_x->challenge_verified != 0) { - if (picoquic_is_ack_needed(cnx, current_time, &next_wake_time, pc)) { + if (picoquic_is_ack_needed(cnx, current_time, next_wake_time, pc)) { ret = picoquic_prepare_ack_frame(cnx, current_time, pc, &bytes[length], send_buffer_min_max - checksum_overhead - length, &data_bytes); if (ret == 0) { @@ -2206,7 +2153,7 @@ int picoquic_prepare_packet_ready(picoquic_cnx_t* cnx, picoquic_path_t * path_x, } else { if (ret == PICOQUIC_ERROR_FRAME_BUFFER_TOO_SMALL) { - next_wake_time = current_time; + *next_wake_time = current_time; ret = 0; } } @@ -2215,10 +2162,10 @@ int picoquic_prepare_packet_ready(picoquic_cnx_t* cnx, picoquic_path_t * path_x, if (path_x->cwin < path_x->bytes_in_transit) { uint64_t cwin_time = current_time + path_x->smoothed_rtt; - if (cwin_time < next_wake_time) { - next_wake_time = cwin_time; + if (cwin_time < *next_wake_time) { + *next_wake_time = cwin_time; } - } else if (picoquic_is_sending_authorized_by_pacing(path_x, current_time, &next_wake_time)) { + } else if (picoquic_is_sending_authorized_by_pacing(path_x, current_time, next_wake_time)) { /* if present, send tls data */ if (tls_ready) { ret = picoquic_prepare_crypto_hs_frame(cnx, 3, &bytes[length], @@ -2233,7 +2180,7 @@ int picoquic_prepare_packet_ready(picoquic_cnx_t* cnx, picoquic_path_t * path_x, } else { if (ret == PICOQUIC_ERROR_FRAME_BUFFER_TOO_SMALL) { - next_wake_time = current_time; + *next_wake_time = current_time; ret = 0; } } @@ -2247,7 +2194,7 @@ int picoquic_prepare_packet_ready(picoquic_cnx_t* cnx, picoquic_path_t * path_x, } else { if (ret == PICOQUIC_ERROR_FRAME_BUFFER_TOO_SMALL) { - next_wake_time = current_time; + *next_wake_time = current_time; ret = 0; } break; @@ -2266,7 +2213,7 @@ int picoquic_prepare_packet_ready(picoquic_cnx_t* cnx, picoquic_path_t * path_x, } else { if (ret == PICOQUIC_ERROR_FRAME_BUFFER_TOO_SMALL) { - next_wake_time = current_time; + *next_wake_time = current_time; ret = 0; } break; @@ -2285,7 +2232,7 @@ int picoquic_prepare_packet_ready(picoquic_cnx_t* cnx, picoquic_path_t * path_x, } } else if (ret == PICOQUIC_ERROR_FRAME_BUFFER_TOO_SMALL) { - next_wake_time = current_time; + *next_wake_time = current_time; ret = 0; } } @@ -2303,7 +2250,7 @@ int picoquic_prepare_packet_ready(picoquic_cnx_t* cnx, picoquic_path_t * path_x, } } else if (ret == PICOQUIC_ERROR_FRAME_BUFFER_TOO_SMALL) { - next_wake_time = current_time; + *next_wake_time = current_time; ret = 0; } } @@ -2320,7 +2267,7 @@ int picoquic_prepare_packet_ready(picoquic_cnx_t* cnx, picoquic_path_t * path_x, } } else if (ret == PICOQUIC_ERROR_FRAME_BUFFER_TOO_SMALL) { - next_wake_time = current_time; + *next_wake_time = current_time; ret = 0; } } @@ -2345,7 +2292,7 @@ int picoquic_prepare_packet_ready(picoquic_cnx_t* cnx, picoquic_path_t * path_x, } } else if (ret == PICOQUIC_ERROR_FRAME_BUFFER_TOO_SMALL) { - next_wake_time = current_time; + *next_wake_time = current_time; ret = 0; break; } @@ -2394,8 +2341,8 @@ int picoquic_prepare_packet_ready(picoquic_cnx_t* cnx, picoquic_path_t * path_x, bytes[length++] = 0; cnx->latest_progress_time = current_time; } - else if (cnx->latest_progress_time + cnx->keep_alive_interval < next_wake_time) { - next_wake_time = cnx->latest_progress_time + cnx->keep_alive_interval; + else if (cnx->latest_progress_time + cnx->keep_alive_interval < *next_wake_time) { + *next_wake_time = cnx->latest_progress_time + cnx->keep_alive_interval; } } } @@ -2407,25 +2354,20 @@ int picoquic_prepare_packet_ready(picoquic_cnx_t* cnx, picoquic_path_t * path_x, &path_x->remote_cnxid, &path_x->local_cnxid, path_x, current_time); if (*send_length > 0) { - next_wake_time = current_time; + *next_wake_time = current_time; if (ret == 0 && cnx->cc_log != NULL) { picoquic_cc_dump(cnx, current_time); } } - else { - next_wake_time = picoquic_get_challenge_wake_time(cnx, current_time, next_wake_time); - } - - /* reset the connection at its new logical position */ - picoquic_reinsert_by_wake_time(cnx->quic, cnx, next_wake_time); return ret; } /* Prepare next packet to send, or nothing.. */ int picoquic_prepare_segment(picoquic_cnx_t* cnx, picoquic_path_t * path_x, picoquic_packet_t* packet, - uint64_t current_time, uint8_t* send_buffer, size_t send_buffer_max, size_t* send_length) + uint64_t current_time, uint8_t* send_buffer, size_t send_buffer_max, size_t* send_length, + uint64_t * next_wake_time) { int ret = 0; @@ -2452,24 +2394,24 @@ int picoquic_prepare_segment(picoquic_cnx_t* cnx, picoquic_path_t * path_x, pico case picoquic_state_client_handshake_start: case picoquic_state_client_handshake_progress: case picoquic_state_client_almost_ready: - ret = picoquic_prepare_packet_client_init(cnx, path_x, packet, current_time, send_buffer, send_buffer_max, send_length); + ret = picoquic_prepare_packet_client_init(cnx, path_x, packet, current_time, send_buffer, send_buffer_max, send_length, next_wake_time); break; case picoquic_state_server_almost_ready: case picoquic_state_server_init: case picoquic_state_server_handshake: - ret = picoquic_prepare_packet_server_init(cnx, path_x, packet, current_time, send_buffer, send_buffer_max, send_length); + ret = picoquic_prepare_packet_server_init(cnx, path_x, packet, current_time, send_buffer, send_buffer_max, send_length, next_wake_time); break; case picoquic_state_server_false_start: case picoquic_state_client_ready_start: case picoquic_state_ready: - ret = picoquic_prepare_packet_ready(cnx, path_x, packet, current_time, send_buffer, send_buffer_max, send_length); + ret = picoquic_prepare_packet_ready(cnx, path_x, packet, current_time, send_buffer, send_buffer_max, send_length, next_wake_time); break; case picoquic_state_handshake_failure: case picoquic_state_disconnecting: case picoquic_state_closing_received: case picoquic_state_closing: case picoquic_state_draining: - ret = picoquic_prepare_packet_closing(cnx, path_x, packet, current_time, send_buffer, send_buffer_max, send_length); + ret = picoquic_prepare_packet_closing(cnx, path_x, packet, current_time, send_buffer, send_buffer_max, send_length, next_wake_time); break; case picoquic_state_disconnected: ret = PICOQUIC_ERROR_DISCONNECTED; @@ -2491,7 +2433,8 @@ int picoquic_prepare_segment(picoquic_cnx_t* cnx, picoquic_path_t * path_x, pico /* Prepare next probe if one is needed, returns send_length == 0 if none necessary */ int picoquic_prepare_probe(picoquic_cnx_t* cnx, uint64_t current_time, uint8_t* send_buffer, size_t send_buffer_max, size_t* send_length, - struct sockaddr ** p_addr_to, int * to_len, struct sockaddr ** p_addr_from, int * from_len, struct sockaddr ** addr_to_log) + struct sockaddr ** p_addr_to, int * to_len, struct sockaddr ** p_addr_from, int * from_len, struct sockaddr ** addr_to_log, + uint64_t * next_wake_time) { int ret = 0; @@ -2507,13 +2450,18 @@ int picoquic_prepare_probe(picoquic_cnx_t* cnx, picoquic_packet_t * packet = NULL; while (probe != NULL) { - if (!probe->challenge_failed && !probe->challenge_verified && - (probe->challenge_required || - current_time >= probe->challenge_time + cnx->path[0]->retransmit_timer)) { - if (probe->challenge_repeat_count >= PICOQUIC_CHALLENGE_REPEAT_MAX) { - probe->challenge_failed = 1; - } else { - break; + if (!probe->challenge_failed && !probe->challenge_verified){ + uint64_t next_probe_time = probe->challenge_time + cnx->path[0]->retransmit_timer; + if (probe->challenge_required || current_time >= next_probe_time) { + if (probe->challenge_repeat_count >= PICOQUIC_CHALLENGE_REPEAT_MAX) { + probe->challenge_failed = 1; + } + else { + break; + } + } + else if (next_probe_time < *next_wake_time) { + *next_wake_time = next_probe_time; } } probe = probe->next_probe; @@ -2607,9 +2555,6 @@ int picoquic_prepare_probe(picoquic_cnx_t* cnx, ret, length, header_length, checksum_overhead, send_length, send_buffer, (uint32_t)send_buffer_max, &probe->remote_cnxid, &cnx->path[0]->local_cnxid, cnx->path[0], current_time); - - /* Keep the connection alive */ - picoquic_reinsert_by_wake_time(cnx->quic, cnx, current_time); } } } @@ -2627,18 +2572,19 @@ int picoquic_prepare_packet(picoquic_cnx_t* cnx, picoquic_path_t * path_x = NULL; picoquic_packet_t * packet = NULL; struct sockaddr * addr_to_log = NULL; + uint64_t next_wake_time = cnx->latest_progress_time + PICOQUIC_MICROSEC_SILENCE_MAX * (2 - cnx->client_mode); *send_length = 0; /* Remove delete paths */ - picoquic_delete_abandoned_paths(cnx, current_time); + picoquic_delete_abandoned_paths(cnx, current_time, &next_wake_time); /* Remove failed probes */ picoquic_delete_failed_probes(cnx); /* If probes are in waiting, send the first one */ ret = picoquic_prepare_probe(cnx, current_time, send_buffer, send_buffer_max, send_length, - p_addr_to, to_len, p_addr_from, from_len, &addr_to_log); + p_addr_to, to_len, p_addr_from, from_len, &addr_to_log, &next_wake_time); if (ret == 0 && *send_length == 0) { /* Select the path */ @@ -2653,11 +2599,16 @@ int picoquic_prepare_packet(picoquic_cnx_t* cnx, break; } else if (path_x == NULL && cnx->path[i]->path_is_activated && - (cnx->path[i]->challenge_required && - (cnx->path[i]->challenge_repeat_count == 0 || - current_time >= (cnx->path[i]->challenge_time + cnx->path[i]->retransmit_timer)))) { - /* will try this path, unless a validated path came in */ - path_x = cnx->path[i]; + cnx->path[i]->challenge_required) { + uint64_t next_challenge_time = (cnx->path[i]->challenge_time + cnx->path[i]->retransmit_timer); + if (cnx->path[i]->challenge_repeat_count == 0 || + current_time >= next_challenge_time) { + /* will try this path, unless a validated path came in */ + path_x = cnx->path[i]; + } + else if (next_challenge_time < next_wake_time) { + next_wake_time = next_challenge_time; + } } } @@ -2705,7 +2656,7 @@ int picoquic_prepare_packet(picoquic_cnx_t* cnx, } else { ret = picoquic_prepare_segment(cnx, path_x, packet, current_time, - send_buffer + *send_length, available, &segment_length); + send_buffer + *send_length, available, &segment_length, &next_wake_time); if (ret == 0) { *send_length += segment_length; @@ -2738,6 +2689,13 @@ int picoquic_prepare_packet(picoquic_cnx_t* cnx, cnx, addr_to_log, 0, *send_length, current_time); } + /* Update the wake up time for the connection */ + if (*send_length > 0 || cnx->cnx_state == picoquic_state_disconnected ) { + next_wake_time = current_time; + } + + picoquic_reinsert_by_wake_time(cnx->quic, cnx, next_wake_time); + return ret; } diff --git a/picoquictest/stresstest.c b/picoquictest/stresstest.c index 393a1dbf71eaadc550c42a843f0a11e4c35b454c..5baed9262f244707628ed8e780c22c4b2d608adc 100644 --- a/picoquictest/stresstest.c +++ b/picoquictest/stresstest.c @@ -863,8 +863,12 @@ static int stress_create_client_context(int client_index, picoquic_stress_ctx_t } if (ret == 0) { /* initialize the simulation links from client to server and back. */ - ctx->c_to_s_link = picoquictest_sim_link_create(0.01, 10000, 0, 0, 0); - ctx->s_to_c_link = picoquictest_sim_link_create(0.01, 10000, 0, 0, 0); + const double target_bandwidth[4] = { 0.001, 0.01, 0.03, 0.1 }; + uint64_t random_latency = 1000 + picoquic_test_uniform_random(&stress_random_ctx, 99000); + uint64_t bandwidth_index = picoquic_test_uniform_random(&stress_random_ctx, 4); + double bandwidth = target_bandwidth[bandwidth_index]; + ctx->c_to_s_link = picoquictest_sim_link_create(bandwidth, random_latency, 0, 0, 2 * random_latency); + ctx->s_to_c_link = picoquictest_sim_link_create(bandwidth, random_latency, 0, 0, 2 * random_latency); if (ctx->c_to_s_link == NULL || ctx->s_to_c_link == NULL) { DBG_PRINTF("Cannot create the sim links for client #%d.\n", (int)client_index);