Skip to content

Commit 96883a3

Browse files
committed
Almost everything debugged, except for multipath
1 parent 7ae96cf commit 96883a3

21 files changed

+891
-987
lines changed

picoquic/frames.c

Lines changed: 74 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -705,9 +705,9 @@ const uint8_t* picoquic_decode_retire_connection_id_frame(picoquic_cnx_t* cnx, c
705705
picoquic_connection_error(cnx, PICOQUIC_TRANSPORT_FRAME_FORMAT_ERROR,
706706
(is_mp)?picoquic_frame_type_path_retire_connection_id:picoquic_frame_type_retire_connection_id);
707707
}
708-
else if (path_x->p_local_cnxid != NULL &&
708+
else if (path_x->first_tuple->p_local_cnxid != NULL &&
709709
(!is_mp || path_x->unique_path_id == unique_path_id) &&
710-
sequence == path_x->p_local_cnxid->sequence) {
710+
sequence == path_x->first_tuple->p_local_cnxid->sequence) {
711711
/* Cannot delete the path through which it arrives */
712712
picoquic_connection_error(cnx, PICOQUIC_TRANSPORT_PROTOCOL_VIOLATION,
713713
(is_mp) ? picoquic_frame_type_path_retire_connection_id : picoquic_frame_type_retire_connection_id);
@@ -3822,17 +3822,13 @@ uint8_t* picoquic_format_ack_frame_in_context(picoquic_cnx_t* cnx, uint8_t* byte
38223822
(((is_ecn) ? picoquic_frame_type_path_ack_ecn : picoquic_frame_type_path_ack));
38233823

38243824
/* Check that there something to acknowledge */
3825-
#if 1
38263825
int not_needed = picoquic_sack_list_is_empty(&ack_ctx->sack_list);
38273826
if (!not_needed && !ack_ctx->act[is_opportunistic].ack_needed &&
38283827
ack_ctx->sack_list.ack_tree.size == 1) {
38293828
picoquic_sack_item_t* last_sack = picoquic_sack_last_item(&ack_ctx->sack_list);
38303829
not_needed = (last_sack->nb_times_sent[is_opportunistic] >= PICOQUIC_MAX_ACK_RANGE_REPEAT);
38313830
}
38323831
if (!not_needed){
3833-
#else
3834-
if (!picoquic_sack_list_is_empty(&ack_ctx->sack_list)) {
3835-
#endif
38363832
uint8_t* num_block_byte = NULL;
38373833
picoquic_sack_item_t* last_sack = picoquic_sack_last_item(&ack_ctx->sack_list);
38383834

@@ -4031,9 +4027,9 @@ uint64_t picoquic_ack_gap_override_if_needed(picoquic_cnx_t* cnx, int path_index
40314027
uint64_t ack_gap = cnx->ack_gap_remote;
40324028
if (cnx->is_multipath_enabled) {
40334029
if (!cnx->path[path_index]->path_is_demoted &&
4034-
!cnx->path[path_index]->challenge_failed &&
4035-
!cnx->path[path_index]->response_required &&
4036-
cnx->path[path_index]->challenge_verified &&
4030+
!cnx->path[path_index]->first_tuple->challenge_failed &&
4031+
!cnx->path[path_index]->first_tuple->response_required &&
4032+
cnx->path[path_index]->first_tuple->challenge_verified &&
40374033
cnx->path[path_index]->received < 100 * PICOQUIC_MAX_PACKET_SIZE) {
40384034
ack_gap = 2;
40394035
}
@@ -4652,26 +4648,30 @@ const uint8_t* picoquic_decode_path_challenge_frame(picoquic_cnx_t* cnx, const u
46524648
if (!is_valid) {
46534649
/* If multipath is not enabled, we must verify that the addresses
46544650
* source (addr_from) matches the peer address if known. */
4655-
if (addr_from == NULL ||
4656-
picoquic_compare_addr(addr_from, (struct sockaddr*)&path_x->first_tuple->peer_addr) == 0) {
4657-
/* If the source address matches, we must verify that the destination
4658-
* address also matches. Given how the socket code works there will be cases
4659-
* when the local port is now yet known. In that case, we only compare
4660-
* the IP address component . Otherwise, we compare the whole address.
4661-
*/
4662-
if (addr_to == NULL ||
4663-
(picoquic_get_addr_port((struct sockaddr*)&path_x->first_tuple->local_addr) == 0 &&
4664-
picoquic_compare_ip_addr(addr_to, (struct sockaddr*)&path_x->first_tuple->local_addr) == 0) ||
4665-
picoquic_compare_addr(addr_to, (struct sockaddr*)&path_x->first_tuple->local_addr) == 0) {
4666-
is_valid = 1;
4651+
picoquic_tuple_t* tuple = path_x->first_tuple;
4652+
while (tuple != NULL) {
4653+
4654+
if (addr_from == NULL ||
4655+
picoquic_compare_addr(addr_from, (struct sockaddr*)&tuple->peer_addr) == 0) {
4656+
/* If the source address matches, we must verify that the destination
4657+
* address also matches. Given how the socket code works there will be cases
4658+
* when the local port is now yet known. In that case, we only compare
4659+
* the IP address component . Otherwise, we compare the whole address.
4660+
*/
4661+
if (addr_to == NULL ||
4662+
(picoquic_get_addr_port((struct sockaddr*)&tuple->local_addr) == 0 &&
4663+
picoquic_compare_ip_addr(addr_to, (struct sockaddr*)&tuple->local_addr) == 0) ||
4664+
picoquic_compare_addr(addr_to, (struct sockaddr*)&tuple->local_addr) == 0) {
4665+
is_valid = 1;
4666+
tuple->challenge_response = challenge_response;
4667+
tuple->response_required = 1;
4668+
break;
4669+
}
46674670
}
4671+
tuple = tuple->next_tuple;
46684672
}
46694673
}
4670-
if (is_valid) {
4671-
path_x->first_tuple->challenge_response = challenge_response;
4672-
path_x->response_required = 1;
4673-
}
4674-
else {
4674+
if (!is_valid) {
46754675
char buf1[128], buf2[128], buf3[128], buf4[128];
46764676
picoquic_log_app_message(cnx,
46774677
"Path challenge[%" PRIu64 "] from %s to %s ignored, wrong addresses, expected %s - %s.\n",
@@ -4714,54 +4714,45 @@ const uint8_t* picoquic_decode_path_response_frame(picoquic_cnx_t* cnx, const ui
47144714
/* Per QUIC V1, path responses must come on the same path. Ignore them if this cannot be verified. */
47154715
if (path_x != NULL) {
47164716
int found_challenge = 0;
4717-
int found_nat_challenge = 0;
4717+
picoquic_tuple_t* tuple = path_x->first_tuple;
4718+
picoquic_tuple_t* previous_tuple = NULL;
47184719

4719-
for (int ichal = 0; ichal < PICOQUIC_CHALLENGE_REPEAT_MAX; ichal++) {
4720-
if (response == path_x->first_tuple->challenge[ichal]) {
4721-
found_challenge = 1;
4722-
break;
4723-
}
4724-
}
4725-
if (!found_challenge && path_x->nat_peer_addr.ss_family != AF_UNSPEC) {
4720+
while (tuple != NULL) {
47264721
for (int ichal = 0; ichal < PICOQUIC_CHALLENGE_REPEAT_MAX; ichal++) {
4727-
if (response == path_x->nat_challenge[ichal]) {
4728-
found_nat_challenge = 1;
4722+
if (response == tuple->challenge[ichal]) {
4723+
found_challenge = 1;
47294724
break;
47304725
}
47314726
}
4732-
}
4733-
if (found_nat_challenge && !path_x->challenge_verified) {
4734-
/* while probing NAT, the NAT response arrived before the normal path response */
4735-
/* Update the addresses */
4736-
picoquic_store_addr(&path_x->first_tuple->local_addr, (struct sockaddr*)&path_x->nat_local_addr);
4737-
picoquic_update_peer_addr(path_x, (struct sockaddr*)&path_x->nat_peer_addr);
4738-
path_x->first_tuple->if_index_dest = path_x->if_index_nat_dest;
4739-
/* if useful, update the CID */
4740-
if (path_x->p_remote_nat_cnxid != NULL) {
4741-
picoquic_dereference_stashed_cnxid(cnx, path_x, 0);
4742-
path_x->p_remote_cnxid = path_x->p_remote_nat_cnxid;
4743-
path_x->p_remote_nat_cnxid = NULL;
4727+
if (found_challenge) {
4728+
break;
47444729
}
4745-
/* Consider this a successful challenge */
4746-
found_challenge = 1;
4730+
previous_tuple = tuple;
4731+
tuple = tuple->next_tuple;
47474732
}
47484733

4749-
if (found_challenge && !path_x->challenge_verified){
4750-
/* TODO: update the RTT if using initial value */
4751-
path_x->challenge_verified = 1;
4752-
4734+
if (found_challenge && !tuple->challenge_verified) {
4735+
tuple->challenge_verified = 1;
47534736
/* Provide a qualified time estimate from challenge time */
4754-
picoquic_update_path_rtt(cnx, path_x, path_x, -1, path_x->first_tuple->challenge_time_first, current_time, 0, 0);
4755-
4756-
if (cnx->are_path_callbacks_enabled &&
4757-
cnx->callback_fn(cnx, path_x->unique_path_id, NULL, 0, picoquic_callback_path_available,
4758-
cnx->callback_ctx, path_x->app_path_ctx) != 0) {
4759-
picoquic_connection_error_ex(cnx, PICOQUIC_TRANSPORT_INTERNAL_ERROR,
4760-
picoquic_frame_type_path_response, "path available callback");
4761-
bytes = NULL;
4737+
picoquic_update_path_rtt(cnx, path_x, path_x, -1, tuple->challenge_time_first, current_time, 0, 0);
4738+
/* This challenge is verified.
4739+
* If this is a client, the path should replace the current path.
4740+
* If this is a server, the replacement should happen if we have a NAT, maybe,
4741+
* or if qualifying data is received, which will happen later.
4742+
*/
4743+
if (previous_tuple != NULL /* && cnx->client_mode */) {
4744+
previous_tuple->next_tuple = tuple->next_tuple;
4745+
tuple->next_tuple = path_x->first_tuple;
4746+
path_x->first_tuple = tuple;
4747+
4748+
if (cnx->are_path_callbacks_enabled &&
4749+
cnx->callback_fn(cnx, path_x->unique_path_id, NULL, 0, picoquic_callback_path_available,
4750+
cnx->callback_ctx, path_x->app_path_ctx) != 0) {
4751+
picoquic_connection_error_ex(cnx, PICOQUIC_TRANSPORT_INTERNAL_ERROR,
4752+
picoquic_frame_type_path_response, "path available callback");
4753+
bytes = NULL;
4754+
}
47624755
}
4763-
/* Erase the NAT address, to avoid continuing the NAT challenge */
4764-
path_x->nat_peer_addr.ss_family = AF_UNSPEC;
47654756
}
47664757
}
47674758
}
@@ -4795,8 +4786,8 @@ int picoquic_should_repeat_path_response_frame(picoquic_cnx_t* cnx, const uint8_
47954786
}
47964787

47974788
if (path_index >= 0 &&
4798-
(cnx->path[path_index]->challenge_verified ||
4799-
(cnx->client_mode && !cnx->path[path_index]->challenge_failed))) {
4789+
(cnx->path[path_index]->first_tuple->challenge_verified ||
4790+
(cnx->client_mode && !cnx->path[path_index]->first_tuple->challenge_failed))) {
48004791
should_repeat = 1;
48014792
}
48024793
else {
@@ -5549,7 +5540,7 @@ int picoquic_queue_path_available_or_backup_frame(
55495540
{
55505541
int ret = 0;
55515542

5552-
if (path_x->p_remote_cnxid == NULL) {
5543+
if (path_x->first_tuple->p_remote_cnxid == NULL) {
55535544
ret = -1;
55545545
}
55555546
else {
@@ -5560,7 +5551,7 @@ int picoquic_queue_path_available_or_backup_frame(
55605551
uint64_t sequence = cnx->status_sequence_to_send_next++;
55615552
uint64_t path_id = (cnx->is_multipath_enabled)?
55625553
path_x->unique_path_id :
5563-
path_x->p_remote_cnxid->sequence;
5554+
path_x->first_tuple->p_remote_cnxid->sequence;
55645555
int is_pure_ack = 0;
55655556
int more_data = 0;
55665557
uint8_t* bytes_next = picoquic_format_path_available_or_backup_frame(
@@ -6071,21 +6062,24 @@ uint8_t* picoquic_format_observed_address_frame(
60716062
return bytes;
60726063
}
60736064

6065+
6066+
60746067
uint8_t* picoquic_prepare_observed_address_frame(uint8_t* bytes, const uint8_t* bytes_max,
6075-
picoquic_path_t* path_x, uint64_t current_time, uint64_t * next_wake_time,
6068+
picoquic_path_t* path_x, picoquic_tuple_t * tuple,
6069+
uint64_t current_time, uint64_t * next_wake_time,
60766070
int * more_data, int* is_pure_ack)
60776071
{
6078-
if (!path_x->observed_addr_acked &&
6079-
path_x->nb_observed_repeat < 4 &&
6080-
path_x->first_tuple->peer_addr.ss_family != AF_UNSPEC) {
6072+
if (!path_x->observed_addr_acked &&
6073+
tuple->nb_observed_repeat < 4 &&
6074+
tuple->peer_addr.ss_family != AF_UNSPEC) {
60816075
int is_needed = 0;
60826076

6083-
if (path_x->nb_observed_repeat == 0) {
6077+
if (tuple->nb_observed_repeat == 0) {
60846078
is_needed = 1;
60856079
path_x->observed_sequence_sent = path_x->cnx->observed_number++;
60866080
}
60876081
else {
6088-
uint64_t repeat_time = path_x->observed_time + path_x->retransmit_timer;
6082+
uint64_t repeat_time = tuple->observed_time + path_x->retransmit_timer;
60896083

60906084
if (repeat_time <= current_time) {
60916085
is_needed = 1;
@@ -6100,14 +6094,14 @@ uint8_t* picoquic_prepare_observed_address_frame(uint8_t* bytes, const uint8_t*
61006094
uint8_t* ip_addr = NULL;
61016095
uint16_t port = 0;
61026096

6103-
if (path_x->first_tuple->peer_addr.ss_family == AF_INET6) {
6104-
struct sockaddr_in6* addr = (struct sockaddr_in6*)&path_x->first_tuple->peer_addr;
6097+
if (tuple->peer_addr.ss_family == AF_INET6) {
6098+
struct sockaddr_in6* addr = (struct sockaddr_in6*)&tuple->peer_addr;
61056099
ftype = picoquic_frame_type_observed_address_v6;
61066100
ip_addr = (uint8_t*)&addr->sin6_addr;
61076101
port = ntohs(addr->sin6_port);
61086102
}
61096103
else {
6110-
struct sockaddr_in* addr = (struct sockaddr_in*)&path_x->first_tuple->peer_addr;
6104+
struct sockaddr_in* addr = (struct sockaddr_in*)&tuple->peer_addr;
61116105
ftype = picoquic_frame_type_observed_address_v4;
61126106
ip_addr = (uint8_t*)&addr->sin_addr;
61136107
port = ntohs(addr->sin_port);
@@ -6119,8 +6113,8 @@ uint8_t* picoquic_prepare_observed_address_frame(uint8_t* bytes, const uint8_t*
61196113
if (bytes_next > bytes) {
61206114
*is_pure_ack = 0;
61216115
bytes = bytes_next;
6122-
path_x->nb_observed_repeat += 1;
6123-
path_x->observed_time = current_time;
6116+
tuple->nb_observed_repeat += 1;
6117+
tuple->observed_time = current_time;
61246118
}
61256119
}
61266120
}
@@ -6208,6 +6202,7 @@ int picoquic_process_ack_of_observed_address_frame(picoquic_cnx_t* cnx, picoquic
62086202
ret = -1;
62096203
}
62106204
else {
6205+
/* TODO: tie this to a specific address and port */
62116206
path_x->observed_addr_acked = 1;
62126207
*consumed = bytes_next - bytes;
62136208
}

picoquic/logwriter.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1059,7 +1059,7 @@ void binlog_new_connection(picoquic_cnx_t * cnx)
10591059

10601060
bytewrite_int8(msg, cnx->client_mode != 0);
10611061
bytewrite_int32(msg, cnx->proposed_version);
1062-
bytewrite_cid(msg, &cnx->path[0]->p_remote_cnxid->cnx_id);
1062+
bytewrite_cid(msg, &cnx->path[0]->first_tuple->p_remote_cnxid->cnx_id);
10631063

10641064
/* Algorithms used */
10651065
bytewrite_cstr(msg, cnx->congestion_alg->congestion_algorithm_id);

picoquic/loss_recovery.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -468,12 +468,12 @@ static size_t picoquic_retransmit_needed_packet(picoquic_cnx_t* cnx, picoquic_pa
468468
}
469469
}
470470
if (!all_paths_dubious) {
471-
old_path->challenge_failed = 1;
471+
old_path->first_tuple->challenge_failed = 1;
472472
cnx->path_demotion_needed = 1;
473473
}
474474
}
475475
else {
476-
old_path->challenge_failed = 1;
476+
old_path->first_tuple->challenge_failed = 1;
477477
cnx->path_demotion_needed = 1;
478478
}
479479
}
@@ -899,7 +899,7 @@ static void picoquic_count_and_notify_loss(
899899
if (timer_based_retransmit < 2) {
900900
picoquic_log_packet_lost(cnx, old_p->send_path, old_p->ptype, old_p->sequence_number,
901901
(timer_based_retransmit) ? "timer" : "repeat",
902-
(old_p->send_path == NULL || old_p->send_path->p_remote_cnxid == NULL) ? NULL : &old_p->send_path->p_remote_cnxid->cnx_id,
902+
(old_p->send_path == NULL || old_p->send_path->first_tuple->p_remote_cnxid == NULL) ? NULL : &old_p->send_path->first_tuple->p_remote_cnxid->cnx_id,
903903
old_p->length, current_time);
904904

905905
if (!old_p->is_preemptive_repeat) {

0 commit comments

Comments
 (0)