diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f8e1c291..642ecf411 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ else() endif() project(picoquic - VERSION 1.1.16.1 + VERSION 1.1.16.2 DESCRIPTION "picoquic library" LANGUAGES C CXX) diff --git a/UnitTest1/unittest1.cpp b/UnitTest1/unittest1.cpp index 04648b242..361cc2a1d 100644 --- a/UnitTest1/unittest1.cpp +++ b/UnitTest1/unittest1.cpp @@ -160,7 +160,7 @@ namespace UnitTest1 Assert::AreEqual(ret, 0); } - TEST_METHOD(test_varints) + TEST_METHOD(varints) { int ret = varint_test(); @@ -1621,6 +1621,59 @@ namespace UnitTest1 Assert::AreEqual(ret, 0); } + TEST_METHOD(reset_ack_max) + { + int ret = reset_ack_max_test(); + + Assert::AreEqual(ret, 0); + } + TEST_METHOD(reset_ack_reset) + { + int ret = reset_ack_reset_test(); + + Assert::AreEqual(ret, 0); + } + + TEST_METHOD(reset_extra_max) + { + int ret = reset_extra_max_test(); + + Assert::AreEqual(ret, 0); + } + + TEST_METHOD(reset_extra_reset) + { + int ret = reset_extra_reset_test(); + + Assert::AreEqual(ret, 0); + } + TEST_METHOD(reset_extra_stop) + { + int ret = reset_extra_stop_test(); + + Assert::AreEqual(ret, 0); + } + + TEST_METHOD(reset_need_max) + { + int ret = reset_need_max_test(); + + Assert::AreEqual(ret, 0); + } + TEST_METHOD(reset_need_reset) + { + int ret = reset_need_reset_test(); + + Assert::AreEqual(ret, 0); + } + + TEST_METHOD(reset_need_stop) + { + int ret = reset_need_stop_test(); + + Assert::AreEqual(ret, 0); + } + TEST_METHOD(ready_to_send) { int ret = ready_to_send_test(); diff --git a/picoquic/frames.c b/picoquic/frames.c index 2c0947998..562bfb2ad 100644 --- a/picoquic/frames.c +++ b/picoquic/frames.c @@ -267,8 +267,15 @@ const uint8_t* picoquic_decode_stream_reset_frame(picoquic_cnx_t* cnx, const uin picoquic_connection_error(cnx, PICOQUIC_TRANSPORT_FRAME_FORMAT_ERROR, picoquic_frame_type_reset_stream); } else if ((stream = picoquic_find_or_create_stream(cnx, stream_id, 1)) == NULL) { - bytes = NULL; // error already signaled - + /* Not finding the stream is only an error if the stream + * was expected to be present, or created on demand. If the + * stream was already created and then deleted, there is no harm. + * If the "return NULL" is in a normal scenario, the connection state + * will remain "ready" or "almost ready" + */ + if (cnx->cnx_state > picoquic_state_ready) { + bytes = NULL; /* error already signaled */ + } } else if ((stream->fin_received || stream->reset_received) && final_offset != stream->fin_offset) { picoquic_connection_error(cnx, PICOQUIC_TRANSPORT_FINAL_OFFSET_ERROR, picoquic_frame_type_reset_stream); @@ -319,8 +326,8 @@ int picoquic_process_ack_of_reset_stream_frame(picoquic_cnx_t * cnx, const uint8 ret = -1; } else { *consumed = bytes - byte_first; - /* Find the stream */ - if ((stream = picoquic_find_or_create_stream(cnx, stream_id, 0)) != NULL) { + /* Find the stream, if it exists. If it was already deleted, do nothing. */ + if ((stream = picoquic_find_stream(cnx, stream_id)) != NULL) { /* mark reset as acked by peer */ stream->reset_acked = 1; /* Delete stream if closed. */ @@ -347,7 +354,7 @@ int picoquic_check_reset_stream_needs_repeat(picoquic_cnx_t* cnx, const uint8_t* /* Internal error -- cannot parse the stored packet */ ret = -1; } - else if ((stream = picoquic_find_or_create_stream(cnx, stream_id, 0)) == NULL || + else if ((stream = picoquic_find_stream(cnx, stream_id)) == NULL || stream->reset_acked) { *no_need_to_repeat = 1; } @@ -837,6 +844,35 @@ const uint8_t* picoquic_skip_stop_sending_frame(const uint8_t* bytes, const uint } +int picoquic_check_stop_sending_needs_repeat(picoquic_cnx_t* cnx, const uint8_t* bytes, size_t bytes_size, int* no_need_to_repeat) +{ + uint64_t stream_id = 0; + uint64_t error_code = 0; + const uint8_t* bytes_max = bytes + bytes_size; + picoquic_stream_head_t* stream; + int ret = 0; + + *no_need_to_repeat = 0; + + if ((bytes = picoquic_frames_varint_decode(bytes+1, bytes_max, &stream_id)) == NULL || + (bytes = picoquic_frames_varint_decode(bytes, bytes_max, &error_code)) == NULL) + { + /* If the frame cannot be decoded, do not repeat it */ + *no_need_to_repeat = 1; + } + else if ((stream = picoquic_find_stream(cnx, stream_id)) == NULL) { + /* If the stream is deleted, no need to repeat this frame. */ + *no_need_to_repeat = 1; + } + else if (stream->fin_received || stream->reset_received) { + /* No point repeating if the stream is closed by the peer */ + *no_need_to_repeat = 1; + } + + return ret; +} + + /* * STREAM frames implicitly create a stream and carry stream data. */ @@ -3123,6 +3159,9 @@ int picoquic_check_frame_needs_repeat(picoquic_cnx_t* cnx, const uint8_t* bytes, case picoquic_frame_type_reset_stream: ret = picoquic_check_reset_stream_needs_repeat(cnx, bytes, bytes_max, no_need_to_repeat); break; + case picoquic_frame_type_stop_sending: + ret = picoquic_check_stop_sending_needs_repeat(cnx, bytes, bytes_max, no_need_to_repeat); + break; default: { uint64_t frame_id64; *no_need_to_repeat = 0; diff --git a/picoquic/picoquic.h b/picoquic/picoquic.h index eb78b665c..a2c61658c 100644 --- a/picoquic/picoquic.h +++ b/picoquic/picoquic.h @@ -40,7 +40,7 @@ extern "C" { #endif -#define PICOQUIC_VERSION "1.1.16.1" +#define PICOQUIC_VERSION "1.1.16.2" #define PICOQUIC_ERROR_CLASS 0x400 #define PICOQUIC_ERROR_DUPLICATE (PICOQUIC_ERROR_CLASS + 1) #define PICOQUIC_ERROR_AEAD_CHECK (PICOQUIC_ERROR_CLASS + 3) diff --git a/picoquic/quicctx.c b/picoquic/quicctx.c index 463398016..e3a310e96 100644 --- a/picoquic/quicctx.c +++ b/picoquic/quicctx.c @@ -539,7 +539,7 @@ static picosplay_node_t* picoquic_registered_token_create(void* value) static void* picoquic_registered_token_value(picosplay_node_t* node) { - return (void*)((char*)node - offsetof(struct st_picoquic_registered_token_t, registered_token_node)); + return (void*)((node == NULL)?NULL:((char*)node - offsetof(struct st_picoquic_registered_token_t, registered_token_node))); } static void picoquic_registered_token_delete(void* tree, picosplay_node_t* node) diff --git a/picoquic/tls_api.h b/picoquic/tls_api.h index efb3b12d9..8bd47b9d9 100644 --- a/picoquic/tls_api.h +++ b/picoquic/tls_api.h @@ -193,6 +193,7 @@ void picoquic_aes128_ecb_free(void* v_aesecb); void picoquic_aes128_ecb_encrypt(void* v_aesecb, uint8_t* output, const uint8_t* input, size_t len); +void picoquic_tls_api_init(); void picoquic_tls_api_unload(); void picoquic_tls_api_reset(uint64_t init_flags); diff --git a/picoquic_t/picoquic_t.c b/picoquic_t/picoquic_t.c index 294acb5b1..6eadd7138 100644 --- a/picoquic_t/picoquic_t.c +++ b/picoquic_t/picoquic_t.c @@ -273,6 +273,14 @@ static const picoquic_test_def_t test_table[] = { { "error_reason", error_reason_test }, { "idle_server", idle_server_test }, { "idle_timeout", idle_timeout_test }, + { "reset_ack_max", reset_ack_max_test }, + { "reset_ack_reset", reset_ack_reset_test }, + { "reset_extra_max", reset_extra_max_test }, + { "reset_extra_reset", reset_extra_reset_test }, + { "reset_extra_stop", reset_extra_stop_test }, + { "reset_need_max", reset_need_max_test }, + { "reset_need_reset", reset_need_reset_test }, + { "reset_need_stop", reset_need_stop_test }, { "ready_to_send", ready_to_send_test }, { "ready_to_skip", ready_to_skip_test }, { "ready_to_zfin", ready_to_zfin_test }, diff --git a/picoquictest/cleartext_aead_test.c b/picoquictest/cleartext_aead_test.c index d95daf73c..a3281b219 100644 --- a/picoquictest/cleartext_aead_test.c +++ b/picoquictest/cleartext_aead_test.c @@ -329,8 +329,11 @@ int pn_ctr_test() uint8_t in_bytes[16]; uint8_t out_bytes[16]; uint8_t decoded[16]; + + picoquic_tls_api_init(); + ptls_aead_algorithm_t* aead = (ptls_aead_algorithm_t*)picoquic_get_aes128gcm_v(0); - ptls_cipher_context_t *pn_enc = ptls_cipher_new(aead->ctr_cipher, 1, key); + ptls_cipher_context_t *pn_enc = (aead == NULL)?NULL:ptls_cipher_new(aead->ctr_cipher, 1, key); if (pn_enc == NULL) { ret = -1; diff --git a/picoquictest/edge_cases.c b/picoquictest/edge_cases.c index 08da8beee..2cf359698 100644 --- a/picoquictest/edge_cases.c +++ b/picoquictest/edge_cases.c @@ -748,7 +748,6 @@ int idle_server_test_one(uint8_t test_id, uint64_t client_timeout, uint64_t hand picoquic_test_tls_api_ctx_t* test_ctx = NULL; uint64_t simulated_time = 0; uint64_t target_timeout; - uint64_t loss_mask = 0; picoquic_connection_id_t initial_cid = { { 0x41, 0x9e, 0xc0, 0x99, 0, 0, 0, 0}, 8 }; uint8_t send_buffer[PICOQUIC_MAX_PACKET_SIZE]; int ret = 0; @@ -857,4 +856,379 @@ int idle_server_test() DBG_PRINTF("%s", "All idle timeout tests pass.\n"); } return ret; +} + +/* +* Testing issues caused by frame events after a stream is reset. +* +* We are concerned with possible errors when copies of "old" +* frames cause processing of a stream after the stream has been +* closed. This includes: +* +* - reset stream frames, +* - stop sending frames, +* - max stream data frames. +* +* We are concerned with three events: +* +* - processing the ACK of a packet that contained the frame, because +* the ACK may be received after the reset after the stream context +* was deleted, +* - receiving extra copies of the frames after the stream is deleted. +* These extra copies shall be ignored with no side effect. +* - processing of frames in packets detected as lost after the +* stream was deleted. The stack whether the packets needs to +* be repeated. +* +* The combination of "ack/extra/need" with three frame types produces +* 9 possible tests. However, there is no acking processing for +* stop sending frames, so we do not implement a test for +* "reset_ack_stop_sending". + */ + +typedef enum { + reset_ack_max_stream = 0, + reset_ack_reset, + reset_ack_stop_sending, + reset_extra_max_stream, + reset_extra_reset, + reset_extra_stop_sending, + reset_need_max_stream, + reset_need_reset, + reset_need_stop_sending +} reset_test_enum; + +static test_api_stream_desc_t test_scenario_edge_reset[] = { + { 4, 0, 1000000, 1000000 } +}; + +int picoquic_process_ack_of_reset_stream_frame(picoquic_cnx_t* cnx, const uint8_t* bytes, size_t bytes_size, size_t* consumed); +int picoquic_process_ack_of_max_stream_data_frame(picoquic_cnx_t* cnx, const uint8_t* bytes, + size_t bytes_size, size_t* consumed); + +int reset_repeat_test_receive_frame(int test_id, picoquic_cnx_t * cnx, const uint8_t * frame, size_t frame_size, + uint64_t simulated_time, uint64_t stream_id, int do_not_create) +{ + picoquic_stream_data_node_t dn; + int ret = picoquic_decode_frames(cnx, cnx->path[0], frame, frame_size, + &dn, picoquic_epoch_1rtt, + (struct sockaddr*)&cnx->path[0]->peer_addr, + (struct sockaddr*)&cnx->path[0]->local_addr, + 123, 0, simulated_time); + + if (ret != 0 || cnx->cnx_state > picoquic_state_ready) { + DBG_PRINTF("Test %d. Error after stop sending, ret = 0x%x.", test_id, ret); + ret = -1; + } + else if (ret == 0 && stream_id != UINT64_MAX && do_not_create && picoquic_find_stream(cnx, stream_id) != NULL) { + DBG_PRINTF("Test %d. Stream %" PRIu64 " was created.", test_id, stream_id); + ret = -1; + } + return ret; +} + +int reset_repeat_test_need_repeat(int test_id, picoquic_cnx_t* cnx, const uint8_t* frame, size_t frame_size, + uint64_t simulated_time, uint64_t stream_id, int do_not_create) +{ + int no_need_to_repeat = 0; + int do_not_detect_spurious = 0; + int is_preemptive_needed = 0; + + int ret = picoquic_check_frame_needs_repeat(cnx, frame, frame_size, picoquic_packet_1rtt_protected, + &no_need_to_repeat, &do_not_detect_spurious, &is_preemptive_needed); + + if (ret != 0 || cnx->cnx_state > picoquic_state_ready || !no_need_to_repeat) { + DBG_PRINTF("Test %d. Error after ack of frame 0x%x, ret = 0x%x.", test_id, frame[0], ret); + ret = -1; + } + return ret; +} + +int reset_loop_check_stream_opened(picoquic_test_tls_api_ctx_t* test_ctx, uint64_t data_stream_id) +{ + int is_opened = 0; + if (test_ctx->cnx_client != NULL && test_ctx->cnx_server != NULL) { + picoquic_stream_head_t* c_stream = picoquic_find_stream(test_ctx->cnx_client, data_stream_id); + if (c_stream != NULL && c_stream->sent_offset > 10000) { + picoquic_stream_head_t* s_stream = picoquic_find_stream(test_ctx->cnx_server, data_stream_id); + if (s_stream != NULL) { + is_opened = 1; + } + } + } + return is_opened; +} + +int reset_loop_wait_stream_opened(picoquic_test_tls_api_ctx_t* test_ctx, + uint64_t* simulated_time, uint64_t data_stream_id, uint64_t loop1_time) +{ + int ret = 0; + int nb_inactive = 0; + uint64_t time_out = *simulated_time + loop1_time; + int was_active = 0; + int is_opened = 0; + + while (ret == 0 && *simulated_time < time_out && + TEST_CLIENT_READY && + TEST_SERVER_READY && + nb_inactive < 64) { + + if (reset_loop_check_stream_opened(test_ctx, data_stream_id)) { + is_opened = 1; + break; + } + + was_active = 0; + + ret = tls_api_one_sim_round(test_ctx, simulated_time, 0, &was_active); + + if (was_active) { + nb_inactive = 0; + } + else { + nb_inactive++; + } + } + if (!is_opened) { + ret = -1; + } + return ret; +} + +int reset_repeat_test_one(uint8_t test_id) +{ + picoquic_test_tls_api_ctx_t* test_ctx = NULL; + uint64_t simulated_time = 0; + uint64_t loss_mask = 0; + uint64_t data_stream_id = 4; + uint64_t loop1_time = 50000; + uint64_t loop2_time = 1000000; + picoquic_connection_id_t initial_cid = { { 0x8e, 0x5e, 0x48, 0xe9, 0, 0, 0, 0}, 8 }; + int ret = 0; + uint8_t stop_sending_frame[3] = { + (uint8_t)picoquic_frame_type_stop_sending, + (uint8_t)data_stream_id, + 0x17 }; + uint8_t max_stream_data_frame[3] = { + (uint8_t)picoquic_frame_type_max_stream_data, + (uint8_t)data_stream_id, + 63 }; + uint8_t reset_frame[4] = { + (uint8_t)picoquic_frame_type_reset_stream, + (uint8_t)data_stream_id, + 1, + 1 }; + + initial_cid.id[4] = test_id; + + /* Create the test context */ + if (ret == 0) { + ret = tls_api_init_ctx_ex(&test_ctx, PICOQUIC_INTERNAL_TEST_VERSION_1, + PICOQUIC_TEST_SNI, PICOQUIC_TEST_ALPN, &simulated_time, NULL, NULL, 0, 1, 0, &initial_cid); + } + + /* Set the binlog */ + if (ret == 0) { + picoquic_set_binlog(test_ctx->qclient, "."); + ret = picoquic_start_client_cnx(test_ctx->cnx_client); + } + + /* set the connection */ + if (ret == 0) { + ret = tls_api_connection_loop(test_ctx, &loss_mask, 0, &simulated_time); + } + + /* Prepare to send data */ + if (ret == 0) { + ret = test_api_init_send_recv_scenario(test_ctx, test_scenario_edge_reset, sizeof(test_scenario_edge_reset)); + + if (ret != 0) + { + DBG_PRINTF("Init send receive scenario returns %d\n", ret); + } + } + + /* Run for a short time, so the stream is created and the transfer started */ + if (ret == 0) { + ret = reset_loop_wait_stream_opened(test_ctx, &simulated_time, data_stream_id, loop1_time); + if (ret != 0) { + DBG_PRINTF("Test #%d. Loop wait stream failed!", test_id); + ret = -1; + } + } + + /* Verify that the stream #4 is present, and the + * transmission has not stopped. + */ + if (ret == 0 && (!(TEST_CLIENT_READY) || !(TEST_SERVER_READY))) { + DBG_PRINTF("%s", "Server or client not ready!"); + ret = -1; + } + if (ret == 0) { + picoquic_stream_head_t* stream = picoquic_find_stream(test_ctx->cnx_client, data_stream_id); + if (stream == NULL || stream->fin_sent) { + DBG_PRINTF("Waited too long, stream is %s\n", (stream == NULL) ? "deleted" : "finished"); + ret = -1; + } + } + /* Reset the stream, then run the connection for a short time. + */ + if (ret == 0) { + ret = picoquic_reset_stream(test_ctx->cnx_client, data_stream_id, 0); + } + if (ret == 0) { + ret = picoquic_reset_stream(test_ctx->cnx_server, data_stream_id, 0); + } + if (ret == 0) { + int was_active = 0; + int nb_inactive = 0; + int client_stream_gone = 0; + uint64_t time_out = simulated_time + loop2_time; + while (ret == 0 && simulated_time < time_out && + TEST_CLIENT_READY && + TEST_SERVER_READY && + nb_inactive < 64) { + was_active = 0; + + ret = tls_api_one_sim_round(test_ctx, &simulated_time, time_out, &was_active); + + if (was_active) { + nb_inactive = 0; + } + else { + nb_inactive++; + } + if (picoquic_find_stream(test_ctx->cnx_client, data_stream_id) == NULL) { + client_stream_gone = 1; + break; + } + } + if (!client_stream_gone) { + DBG_PRINTF("%s", "Did not wait long enough, stream is still there."); + ret = -1; + } + } + /* Perform the specified test. + */ + switch (test_id) { + case reset_ack_max_stream: { + size_t consumed = 0; + ret = picoquic_process_ack_of_max_stream_data_frame(test_ctx->cnx_client, reset_frame, sizeof(reset_frame), &consumed); + + if (ret != 0 || test_ctx->cnx_client->cnx_state > picoquic_state_ready) { + DBG_PRINTF("Test %d. Error after ack of max stream, ret = 0x%x.", test_id, ret); + ret = -1; + } + break; + } + case reset_ack_reset:/* spurious ack of reset frame. */ { + size_t consumed = 0; + ret = picoquic_process_ack_of_reset_stream_frame(test_ctx->cnx_client, reset_frame, sizeof(reset_frame), &consumed); + + if (ret != 0 || test_ctx->cnx_client->cnx_state > picoquic_state_ready) { + DBG_PRINTF("Test %d. Error after ack of reset, ret = 0x%x.", test_id, ret); + ret = -1; + } + break; + } + case reset_ack_stop_sending: + /* TODO: there is no code yet for processing acks of stop sending frame. */ + ret = -1; + break; + case reset_extra_max_stream: + /* arrival of stream related frame on a non existing stream. + * this is a bit more subtle than the ACK test. + * - if this is a remotely created stream: + * - if it is bidir, this could be an out of order request to + * not send response, or it could be an old stream that was + * already deleted. + * - if it is monodir, it does not make sense. + * - if it is locally created: + * - if it is closed, just ignore it. + * - if it is not created yet, this is a protocol error. + */ + ret = reset_repeat_test_receive_frame(test_id, test_ctx->cnx_client, max_stream_data_frame, sizeof(max_stream_data_frame), + simulated_time, data_stream_id, 1); + break; + case reset_extra_reset: + /* arrival of extra reset frame. + * see, arrival of stop sending. + */ + ret = reset_repeat_test_receive_frame(test_id, test_ctx->cnx_client, reset_frame, sizeof(reset_frame), + simulated_time, data_stream_id, 1); + break; + case reset_extra_stop_sending: + ret = reset_repeat_test_receive_frame(test_id, test_ctx->cnx_client, stop_sending_frame, sizeof(stop_sending_frame), + simulated_time, data_stream_id, 1); + break; + case reset_need_max_stream: + /* Check whether a frame needs to be repeated. + * this should never cause an error! If the stream is not + * there any more, this means the original reset was + * successful, there is no need to resend it. + */ + ret = reset_repeat_test_need_repeat(test_id, test_ctx->cnx_client, max_stream_data_frame, sizeof(max_stream_data_frame), + simulated_time, data_stream_id, 1); + break; + case reset_need_reset: + ret = reset_repeat_test_need_repeat(test_id, test_ctx->cnx_client, reset_frame, sizeof(reset_frame), + simulated_time, data_stream_id, 1); + break; + case reset_need_stop_sending: + ret = reset_repeat_test_need_repeat(test_id, test_ctx->cnx_client, stop_sending_frame, sizeof(stop_sending_frame), + simulated_time, data_stream_id, 1); + break; + default: + DBG_PRINTF("What test is that: %d?", test_id); + ret = -1; + break; + } + + /* Clean up */ + if (test_ctx != NULL) { + tls_api_delete_ctx(test_ctx); + test_ctx = NULL; + } + + return ret; +} + +int reset_ack_max_test() +{ + return reset_repeat_test_one(reset_ack_max_stream); +} + +int reset_ack_reset_test() +{ + return reset_repeat_test_one(reset_ack_reset); +} + +int reset_extra_max_test() +{ + return reset_repeat_test_one(reset_extra_max_stream); +} + +int reset_extra_reset_test() +{ + return reset_repeat_test_one(reset_extra_reset); +} + +int reset_extra_stop_test() +{ + return reset_repeat_test_one(reset_extra_stop_sending); +} + +int reset_need_max_test() +{ + return reset_repeat_test_one(reset_need_max_stream); +} + +int reset_need_reset_test() +{ + return reset_repeat_test_one(reset_need_reset); +} + +int reset_need_stop_test() +{ + return reset_repeat_test_one(reset_need_stop_sending); } \ No newline at end of file diff --git a/picoquictest/intformattest.c b/picoquictest/intformattest.c index 460d1d64a..39781ef8f 100644 --- a/picoquictest/intformattest.c +++ b/picoquictest/intformattest.c @@ -249,21 +249,25 @@ static size_t nb_varint_test_cases = sizeof(varint_test_cases) / sizeof(picoquic int varint_test() { int ret = 0; + uint8_t test_buf[16]; const picoquic_varintformat_test_t* max_test = varint_test_cases + nb_varint_test_cases; + memset(test_buf, 0xcc, 16); for (picoquic_varintformat_test_t* test = varint_test_cases; ret == 0 && test < max_test; test++) { for (int is_new_decode = 0; ret == 0 && is_new_decode <= 1; is_new_decode++) { - for (size_t buf_size = 0; ret == 0 && buf_size <= test->length + 2; buf_size++) { + for (size_t buf_size = 0; ret == 0 && buf_size <= test->length + 2 && buf_size < 16; buf_size++) { int test_ret = 0; uint64_t n64 = 0; size_t length; + memcpy(test_buf, test->encoding, test->length); + if (is_new_decode) { - const uint8_t* bytes = picoquic_frames_varint_decode(test->encoding, test->encoding + buf_size, &n64); - length = bytes != NULL ? bytes - test->encoding : 0; + const uint8_t* bytes = picoquic_frames_varint_decode(test_buf, test_buf + buf_size, &n64); + length = bytes != NULL ? bytes - test_buf : 0; } else { - length = picoquic_varint_decode(test->encoding, buf_size, &n64); + length = picoquic_varint_decode(test_buf, buf_size, &n64); } if (length != (buf_size < test->length ? 0 : test->length)) { diff --git a/picoquictest/picoquictest.h b/picoquictest/picoquictest.h index 8a03ce731..ad46a7031 100644 --- a/picoquictest/picoquictest.h +++ b/picoquictest/picoquictest.h @@ -224,6 +224,14 @@ int ec9a_preemptive_amok_test(); int error_reason_test(); int idle_server_test(); int idle_timeout_test(); +int reset_ack_max_test(); +int reset_ack_reset_test(); +int reset_extra_max_test(); +int reset_extra_reset_test(); +int reset_extra_stop_test(); +int reset_need_max_test(); +int reset_need_reset_test(); +int reset_need_stop_test(); int ready_to_send_test(); int ready_to_skip_test(); int ready_to_zero_test();