From 39db7b15451c25ae1d5629e4015ae38a361c02d5 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Tue, 15 Aug 2023 14:17:31 -0700 Subject: [PATCH 01/52] Add protocol version check for outgoing DATA messages --- source/secure_tunneling.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/source/secure_tunneling.c b/source/secure_tunneling.c index da9b6405..7313937f 100644 --- a/source/secure_tunneling.c +++ b/source/secure_tunneling.c @@ -2547,6 +2547,16 @@ int aws_secure_tunnel_send_message( message_op->options_storage.storage_view.connection_id = 0; } + if (!s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, &message_op->options_storage.storage_view)) { + AWS_LOGF_WARN( + AWS_LS_IOTDEVICE_SECURE_TUNNELING, + "id=%p: Protocol Version missmatch between previously established Protocol Version " + "and Protocol Version used by outgoing DATA message.", + (void *)secure_tunnel); + aws_raise_error(AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH); + goto error; + } + AWS_LOGF_DEBUG( AWS_LS_IOTDEVICE_SECURE_TUNNELING, "id=%p: Submitting MESSAGE operation (%p)", From cf9b7878fda435a97e1ad6377d6c5fec450dcba8 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Tue, 15 Aug 2023 15:46:09 -0700 Subject: [PATCH 02/52] Fix logging when protocols mismatch --- source/secure_tunneling.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/source/secure_tunneling.c b/source/secure_tunneling.c index 7313937f..826c3eb2 100644 --- a/source/secure_tunneling.c +++ b/source/secure_tunneling.c @@ -206,14 +206,17 @@ static uint8_t s_aws_secure_tunnel_message_min_protocol_check(const struct aws_s static bool s_aws_secure_tunnel_protocol_version_match_check( struct aws_secure_tunnel *secure_tunnel, - const struct aws_secure_tunnel_message_view *message) { + const struct aws_secure_tunnel_message_view *message, + bool is_inbound_message) { uint8_t message_protocol_version = s_aws_secure_tunnel_message_min_protocol_check(message); if (secure_tunnel->connections->protocol_version != message_protocol_version) { AWS_LOGF_WARN( AWS_LS_IOTDEVICE_SECURE_TUNNELING, - "id=%p: Secure Tunnel is currently using Protocol V%d and received a message using Protocol V%d", + "id=%p: Protocol Version mismatch: Secure Tunnel is currently using Protocol V%d and an %s message " + "is using Protocol V%d", (void *)secure_tunnel, (int)secure_tunnel->connections->protocol_version, + (is_inbound_message ? "inbound" : "outbound"), message_protocol_version); return false; } @@ -508,7 +511,7 @@ static void s_aws_secure_tunnel_on_data_received( struct aws_secure_tunnel *secure_tunnel, struct aws_secure_tunnel_message_view *message_view) { - if (!s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, message_view)) { + if (!s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, message_view, /*is_inbound_message=*/true)) { /* * Protocol missmatch results in a full disconnect/reconnect to the Secure Tunnel Service followed by * initializing the stream that caused the missmatch @@ -570,7 +573,8 @@ static void s_aws_secure_tunnel_on_stream_start_received( "id=%p: Secure tunnel client Protocol set to V%d based on received STREAM START", (void *)secure_tunnel, secure_tunnel->connections->protocol_version); - } else if (!s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, message_view)) { + } else if (!s_aws_secure_tunnel_protocol_version_match_check( + secure_tunnel, message_view, /*is_inbound_message=*/true)) { /* * Protocol missmatch results in a full disconnect/reconnect to the Secure Tunnel Service followed by * initializing the stream that caused the missmatch @@ -612,7 +616,7 @@ static void s_aws_secure_tunnel_on_stream_reset_received( struct aws_secure_tunnel_message_view *message_view) { if (secure_tunnel->connections->protocol_version != 0 && - !s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, message_view)) { + !s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, message_view, /*is_inbound_message=*/true)) { AWS_LOGF_INFO( AWS_LS_IOTDEVICE_SECURE_TUNNELING, "id=%p: Secure Tunnel will be reset due to Protocol Version missmatch between previously established " @@ -2547,11 +2551,12 @@ int aws_secure_tunnel_send_message( message_op->options_storage.storage_view.connection_id = 0; } - if (!s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, &message_op->options_storage.storage_view)) { + if (!s_aws_secure_tunnel_protocol_version_match_check( + secure_tunnel, &message_op->options_storage.storage_view, /*is_inbound_message=*/false)) { AWS_LOGF_WARN( AWS_LS_IOTDEVICE_SECURE_TUNNELING, - "id=%p: Protocol Version missmatch between previously established Protocol Version " - "and Protocol Version used by outgoing DATA message.", + "id=%p: Ignore outbound DATA message due to Protocol Version mismatch between previously established " + "Protocol Version and Protocol Version used by the message.", (void *)secure_tunnel); aws_raise_error(AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH); goto error; From 8f07b40e006d74badf4a6283c7ddce16037bada7 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Tue, 15 Aug 2023 15:48:19 -0700 Subject: [PATCH 03/52] Use s_aws_secure_tunnel_protocol_version_match_check in aws_secure_tunnel_stream_start --- source/secure_tunneling.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/source/secure_tunneling.c b/source/secure_tunneling.c index 826c3eb2..6a39a810 100644 --- a/source/secure_tunneling.c +++ b/source/secure_tunneling.c @@ -2590,9 +2590,8 @@ int aws_secure_tunnel_stream_start( return AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INCORRECT_MODE; } - uint8_t message_protocol_version = s_aws_secure_tunnel_message_min_protocol_check(message_options); - if (secure_tunnel->connections->protocol_version != 0 && - message_protocol_version != secure_tunnel->connections->protocol_version) { + if (!s_aws_secure_tunnel_protocol_version_match_check( + secure_tunnel, message_options, /*is_inbound_message=*/false)) { /* * Protocol missmatch results in a full disconnect/reconnect to the Secure Tunnel Service followed by * sending the STREAM START request that caused the missmatch. @@ -2600,15 +2599,13 @@ int aws_secure_tunnel_stream_start( AWS_LOGF_INFO( AWS_LS_IOTDEVICE_SECURE_TUNNELING, "id=%p: Secure Tunnel will be reset due to Protocol Version missmatch between previously established " - "Protocol Version (%d) and Protocol Version used by outbound STREAM START message (%d).", - (void *)secure_tunnel, - (int)secure_tunnel->connections->protocol_version, - (int)message_protocol_version); + "Protocol Version and Protocol Version used by outbound STREAM START message.", + (void *)secure_tunnel); reset_secure_tunnel_connection(secure_tunnel); } if (secure_tunnel->connections->protocol_version == 0) { - secure_tunnel->connections->protocol_version = message_protocol_version; + secure_tunnel->connections->protocol_version = s_aws_secure_tunnel_message_min_protocol_check(message_options); AWS_LOGF_INFO( AWS_LS_IOTDEVICE_SECURE_TUNNELING, "id=%p: Secure tunnel client Protocol set to V%d based on outbound STREAM START", From 7bd8829be49408bb43c19ca444dad146ff528480 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Wed, 16 Aug 2023 17:04:54 -0700 Subject: [PATCH 04/52] Add protocol match tests for outbound message --- source/secure_tunneling.c | 37 +++-- tests/CMakeLists.txt | 6 + tests/secure_tunnel_tests.c | 279 +++++++++++++++++++++++++++++++++++- 3 files changed, 306 insertions(+), 16 deletions(-) diff --git a/source/secure_tunneling.c b/source/secure_tunneling.c index 6a39a810..96a5ae34 100644 --- a/source/secure_tunneling.c +++ b/source/secure_tunneling.c @@ -206,17 +206,15 @@ static uint8_t s_aws_secure_tunnel_message_min_protocol_check(const struct aws_s static bool s_aws_secure_tunnel_protocol_version_match_check( struct aws_secure_tunnel *secure_tunnel, - const struct aws_secure_tunnel_message_view *message, - bool is_inbound_message) { + const struct aws_secure_tunnel_message_view *message) { uint8_t message_protocol_version = s_aws_secure_tunnel_message_min_protocol_check(message); if (secure_tunnel->connections->protocol_version != message_protocol_version) { AWS_LOGF_WARN( AWS_LS_IOTDEVICE_SECURE_TUNNELING, - "id=%p: Protocol Version mismatch: Secure Tunnel is currently using Protocol V%d and an %s message " + "id=%p: Protocol Version mismatch: Secure Tunnel is currently using Protocol V%d and a message " "is using Protocol V%d", (void *)secure_tunnel, (int)secure_tunnel->connections->protocol_version, - (is_inbound_message ? "inbound" : "outbound"), message_protocol_version); return false; } @@ -224,7 +222,7 @@ static bool s_aws_secure_tunnel_protocol_version_match_check( } static bool s_aws_secure_tunnel_stream_id_match_check( - struct aws_secure_tunnel *secure_tunnel, + const struct aws_secure_tunnel *secure_tunnel, const struct aws_byte_cursor *service_id, int32_t stream_id) { /* @@ -245,7 +243,7 @@ static bool s_aws_secure_tunnel_stream_id_match_check( } static bool s_aws_secure_tunnel_active_stream_check( - struct aws_secure_tunnel *secure_tunnel, + const struct aws_secure_tunnel *secure_tunnel, const struct aws_secure_tunnel_message_view *message_view) { /* * No service id means either V1 protocol is being used or V3 protocol is being used on a tunnel without service ids @@ -302,6 +300,18 @@ static bool s_aws_secure_tunnel_active_stream_check( return true; } +static bool s_aws_secure_tunnel_is_message_viable_for_connection( + struct aws_secure_tunnel *secure_tunnel, + const struct aws_secure_tunnel_message_view *message) { + if (!s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, message)) { + return false; + } + if (!s_aws_secure_tunnel_active_stream_check(secure_tunnel, message)) { + return false; + } + return true; +} + static int s_aws_secure_tunnel_set_stream( struct aws_secure_tunnel *secure_tunnel, const struct aws_byte_cursor *service_id, @@ -511,7 +521,7 @@ static void s_aws_secure_tunnel_on_data_received( struct aws_secure_tunnel *secure_tunnel, struct aws_secure_tunnel_message_view *message_view) { - if (!s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, message_view, /*is_inbound_message=*/true)) { + if (!s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, message_view)) { /* * Protocol missmatch results in a full disconnect/reconnect to the Secure Tunnel Service followed by * initializing the stream that caused the missmatch @@ -573,8 +583,7 @@ static void s_aws_secure_tunnel_on_stream_start_received( "id=%p: Secure tunnel client Protocol set to V%d based on received STREAM START", (void *)secure_tunnel, secure_tunnel->connections->protocol_version); - } else if (!s_aws_secure_tunnel_protocol_version_match_check( - secure_tunnel, message_view, /*is_inbound_message=*/true)) { + } else if (!s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, message_view)) { /* * Protocol missmatch results in a full disconnect/reconnect to the Secure Tunnel Service followed by * initializing the stream that caused the missmatch @@ -616,7 +625,7 @@ static void s_aws_secure_tunnel_on_stream_reset_received( struct aws_secure_tunnel_message_view *message_view) { if (secure_tunnel->connections->protocol_version != 0 && - !s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, message_view, /*is_inbound_message=*/true)) { + !s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, message_view)) { AWS_LOGF_INFO( AWS_LS_IOTDEVICE_SECURE_TUNNELING, "id=%p: Secure Tunnel will be reset due to Protocol Version missmatch between previously established " @@ -2551,11 +2560,10 @@ int aws_secure_tunnel_send_message( message_op->options_storage.storage_view.connection_id = 0; } - if (!s_aws_secure_tunnel_protocol_version_match_check( - secure_tunnel, &message_op->options_storage.storage_view, /*is_inbound_message=*/false)) { + if (!s_aws_secure_tunnel_is_message_viable_for_connection(secure_tunnel, &message_op->options_storage.storage_view)) { AWS_LOGF_WARN( AWS_LS_IOTDEVICE_SECURE_TUNNELING, - "id=%p: Ignore outbound DATA message due to Protocol Version mismatch between previously established " + "id=%p: Ignore outbound DATA message due to " "Protocol Version and Protocol Version used by the message.", (void *)secure_tunnel); aws_raise_error(AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH); @@ -2590,8 +2598,7 @@ int aws_secure_tunnel_stream_start( return AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INCORRECT_MODE; } - if (!s_aws_secure_tunnel_protocol_version_match_check( - secure_tunnel, message_options, /*is_inbound_message=*/false)) { + if (!s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, message_options)) { /* * Protocol missmatch results in a full disconnect/reconnect to the Secure Tunnel Service followed by * sending the STREAM START request that caused the missmatch. diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 36db970e..36ccf19b 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -44,6 +44,12 @@ add_net_test_case(secure_tunneling_v2_stream_start_connection_start_reset_test) add_net_test_case(secure_tunneling_ignore_outbound_inactive_connection_id_message_sending_test) add_net_test_case(secure_tunneling_close_stream_on_connection_reset_test) add_net_test_case(secure_tunneling_existing_connection_start_send_reset_test) +add_net_test_case(secure_tunneling_send_v2_message_on_v1_connection) +add_net_test_case(secure_tunneling_send_v3_message_on_v1_connection) +add_net_test_case(secure_tunneling_send_v3_message_on_v2_connection) +add_net_test_case(secure_tunneling_send_v1_message_on_v2_connection) +add_net_test_case(secure_tunneling_send_v1_message_on_v3_connection) +add_net_test_case(secure_tunneling_send_v2_message_on_v3_connection) generate_test_driver(${PROJECT_NAME}-tests) diff --git a/tests/secure_tunnel_tests.c b/tests/secure_tunnel_tests.c index 18776a7e..b90b8cb4 100644 --- a/tests/secure_tunnel_tests.c +++ b/tests/secure_tunnel_tests.c @@ -1811,7 +1811,8 @@ static int s_secure_tunneling_ignore_outbound_inactive_connection_id_message_sen .payload = &payload_cur, .connection_id = 3, }; - aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); + int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); + ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_OPTIONS_VALIDATION); /* Confirm that no messages have gone out from the client */ aws_thread_current_sleep(aws_timestamp_convert(1, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_NANOS, NULL)); @@ -1947,3 +1948,279 @@ static int s_secure_tunneling_existing_connection_start_send_reset_test_fn(struc AWS_TEST_CASE( secure_tunneling_existing_connection_start_send_reset_test, s_secure_tunneling_existing_connection_start_send_reset_test_fn) + +static int s_secure_tunneling_send_v2_message_on_v1_connection_fn(struct aws_allocator *allocator, void *ctx) { + (void)ctx; + struct secure_tunnel_test_options test_options; + struct aws_secure_tunnel_mock_test_fixture test_fixture; + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; + + ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); + s_wait_for_connected_successfully(&test_fixture); + + /* Create and send a V1 StreamStart message from the server to the destination client */ + struct aws_secure_tunnel_message_view stream_start_message_view = { + .type = AWS_SECURE_TUNNEL_MT_STREAM_START, + .stream_id = 1, + }; + aws_secure_tunnel_send_mock_message(&test_fixture, &stream_start_message_view); + + /* Wait and confirm that a stream has been started */ + s_wait_for_stream_started(&test_fixture); + ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, NULL, 1)); + + struct aws_byte_cursor service_1 = aws_byte_cursor_from_string(s_service_id_1); + struct aws_secure_tunnel_message_view data_message_view = { + .type = AWS_SECURE_TUNNEL_MT_DATA, + .stream_id = 0, + .service_id = &service_1, + .payload = &s_payload_cursor_max_size, + }; + + int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); + ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH); + + /* Ensure that the established stream was not affected by the message */ + ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, NULL, 1)); + + ASSERT_SUCCESS(aws_secure_tunnel_stop(secure_tunnel)); + s_wait_for_connection_shutdown(&test_fixture); + + aws_secure_tunnel_mock_test_clean_up(&test_fixture); + + return AWS_OP_SUCCESS; +} + +AWS_TEST_CASE(secure_tunneling_send_v2_message_on_v1_connection, s_secure_tunneling_send_v2_message_on_v1_connection_fn) + +static int s_secure_tunneling_send_v3_message_on_v1_connection_fn(struct aws_allocator *allocator, void *ctx) { + (void)ctx; + struct secure_tunnel_test_options test_options; + struct aws_secure_tunnel_mock_test_fixture test_fixture; + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; + + ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); + s_wait_for_connected_successfully(&test_fixture); + + /* Create and send a V1 StreamStart message from the server to the destination client */ + struct aws_secure_tunnel_message_view stream_start_message_view = { + .type = AWS_SECURE_TUNNEL_MT_STREAM_START, + .stream_id = 1, + }; + aws_secure_tunnel_send_mock_message(&test_fixture, &stream_start_message_view); + + /* Wait and confirm that a stream has been started */ + s_wait_for_stream_started(&test_fixture); + ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, NULL, 1)); + + struct aws_byte_cursor service_1 = aws_byte_cursor_from_string(s_service_id_1); + struct aws_secure_tunnel_message_view data_message_view = { + .type = AWS_SECURE_TUNNEL_MT_DATA, + .stream_id = 0, + .service_id = &service_1, + .connection_id = 3, + .payload = &s_payload_cursor_max_size, + }; + + int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); + ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH); + + /* Ensure that the established stream was not affected by the message */ + ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, NULL, 1)); + + ASSERT_SUCCESS(aws_secure_tunnel_stop(secure_tunnel)); + s_wait_for_connection_shutdown(&test_fixture); + + aws_secure_tunnel_mock_test_clean_up(&test_fixture); + + return AWS_OP_SUCCESS; +} + +AWS_TEST_CASE(secure_tunneling_send_v3_message_on_v1_connection, s_secure_tunneling_send_v3_message_on_v1_connection_fn) + +static int s_secure_tunneling_send_v3_message_on_v2_connection_fn(struct aws_allocator *allocator, void *ctx) { + (void)ctx; + struct secure_tunnel_test_options test_options; + struct aws_secure_tunnel_mock_test_fixture test_fixture; + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; + + ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); + s_wait_for_connected_successfully(&test_fixture); + + /* Create and send a V2 StreamStart message from the server to the destination client */ + struct aws_byte_cursor service_1 = aws_byte_cursor_from_string(s_service_id_1); + struct aws_secure_tunnel_message_view stream_start_message_view = { + .type = AWS_SECURE_TUNNEL_MT_STREAM_START, + .service_id = &service_1, + .stream_id = 1, + }; + aws_secure_tunnel_send_mock_message(&test_fixture, &stream_start_message_view); + + /* Wait and confirm that a stream has been started */ + s_wait_for_stream_started(&test_fixture); + ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); + + struct aws_secure_tunnel_message_view data_message_view = { + .type = AWS_SECURE_TUNNEL_MT_DATA, + .stream_id = 0, + .service_id = &service_1, + .connection_id = 3, + .payload = &s_payload_cursor_max_size, + }; + + int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); + ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH); + + /* Ensure that the established stream was not affected by the message */ + ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); + + ASSERT_SUCCESS(aws_secure_tunnel_stop(secure_tunnel)); + s_wait_for_connection_shutdown(&test_fixture); + + aws_secure_tunnel_mock_test_clean_up(&test_fixture); + + return AWS_OP_SUCCESS; +} + +AWS_TEST_CASE(secure_tunneling_send_v3_message_on_v2_connection, s_secure_tunneling_send_v3_message_on_v2_connection_fn) + +static int s_secure_tunneling_send_v1_message_on_v2_connection_fn(struct aws_allocator *allocator, void *ctx) { + (void)ctx; + struct secure_tunnel_test_options test_options; + struct aws_secure_tunnel_mock_test_fixture test_fixture; + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; + + ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); + s_wait_for_connected_successfully(&test_fixture); + + /* Create and send a V1 StreamStart message from the server to the destination client */ + struct aws_byte_cursor service_1 = aws_byte_cursor_from_string(s_service_id_1); + struct aws_secure_tunnel_message_view stream_start_message_view = { + .type = AWS_SECURE_TUNNEL_MT_STREAM_START, + .service_id = &service_1, + .stream_id = 1, + }; + aws_secure_tunnel_send_mock_message(&test_fixture, &stream_start_message_view); + + /* Wait and confirm that a stream has been started */ + s_wait_for_stream_started(&test_fixture); + ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); + + struct aws_secure_tunnel_message_view data_message_view = { + .type = AWS_SECURE_TUNNEL_MT_DATA, + .stream_id = 0, + .payload = &s_payload_cursor_max_size, + }; + + int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); + ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH); + + /* Ensure that the established stream was not affected by the message */ + ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); + + ASSERT_SUCCESS(aws_secure_tunnel_stop(secure_tunnel)); + s_wait_for_connection_shutdown(&test_fixture); + + aws_secure_tunnel_mock_test_clean_up(&test_fixture); + + return AWS_OP_SUCCESS; +} + +AWS_TEST_CASE(secure_tunneling_send_v1_message_on_v2_connection, s_secure_tunneling_send_v1_message_on_v2_connection_fn) + +static int s_secure_tunneling_send_v1_message_on_v3_connection_fn(struct aws_allocator *allocator, void *ctx) { + (void)ctx; + struct secure_tunnel_test_options test_options; + struct aws_secure_tunnel_mock_test_fixture test_fixture; + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; + + ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); + s_wait_for_connected_successfully(&test_fixture); + + /* Create and send a V1 StreamStart message from the server to the destination client */ + struct aws_byte_cursor service_1 = aws_byte_cursor_from_string(s_service_id_1); + struct aws_secure_tunnel_message_view stream_start_message_view = { + .type = AWS_SECURE_TUNNEL_MT_STREAM_START, + .service_id = &service_1, + .stream_id = 1, + .connection_id = 3 + }; + aws_secure_tunnel_send_mock_message(&test_fixture, &stream_start_message_view); + + /* Wait and confirm that a stream has been started */ + s_wait_for_stream_started(&test_fixture); + ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); + + struct aws_secure_tunnel_message_view data_message_view = { + .type = AWS_SECURE_TUNNEL_MT_DATA, + .stream_id = 0, + .payload = &s_payload_cursor_max_size, + }; + + int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); + ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH); + + /* Ensure that the established stream was not affected by the message */ + ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); + + ASSERT_SUCCESS(aws_secure_tunnel_stop(secure_tunnel)); + s_wait_for_connection_shutdown(&test_fixture); + + aws_secure_tunnel_mock_test_clean_up(&test_fixture); + + return AWS_OP_SUCCESS; +} + +AWS_TEST_CASE(secure_tunneling_send_v1_message_on_v3_connection, s_secure_tunneling_send_v1_message_on_v3_connection_fn) + +static int s_secure_tunneling_send_v2_message_on_v3_connection_fn(struct aws_allocator *allocator, void *ctx) { + (void)ctx; + struct secure_tunnel_test_options test_options; + struct aws_secure_tunnel_mock_test_fixture test_fixture; + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; + + ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); + s_wait_for_connected_successfully(&test_fixture); + + /* Create and send a V1 StreamStart message from the server to the destination client */ + struct aws_byte_cursor service_1 = aws_byte_cursor_from_string(s_service_id_1); + struct aws_secure_tunnel_message_view stream_start_message_view = { + .type = AWS_SECURE_TUNNEL_MT_STREAM_START, + .service_id = &service_1, + .stream_id = 1, + .connection_id = 3 + }; + aws_secure_tunnel_send_mock_message(&test_fixture, &stream_start_message_view); + + /* Wait and confirm that a stream has been started */ + s_wait_for_stream_started(&test_fixture); + ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); + + struct aws_secure_tunnel_message_view data_message_view = { + .type = AWS_SECURE_TUNNEL_MT_DATA, + .stream_id = 0, + .service_id = &service_1, + .payload = &s_payload_cursor_max_size, + }; + + int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); + ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH); + + /* Ensure that the established stream was not affected by the message */ + ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); + + ASSERT_SUCCESS(aws_secure_tunnel_stop(secure_tunnel)); + s_wait_for_connection_shutdown(&test_fixture); + + aws_secure_tunnel_mock_test_clean_up(&test_fixture); + + return AWS_OP_SUCCESS; +} + +AWS_TEST_CASE(secure_tunneling_send_v2_message_on_v3_connection, s_secure_tunneling_send_v2_message_on_v3_connection_fn) From 423ff369a984aef990b3fd6514e3aadc6821f44a Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Thu, 17 Aug 2023 09:07:33 -0700 Subject: [PATCH 05/52] Fix constness and formatting --- source/secure_tunneling.c | 7 ++++--- tests/secure_tunnel_tests.c | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/source/secure_tunneling.c b/source/secure_tunneling.c index 96a5ae34..0a145243 100644 --- a/source/secure_tunneling.c +++ b/source/secure_tunneling.c @@ -205,7 +205,7 @@ static uint8_t s_aws_secure_tunnel_message_min_protocol_check(const struct aws_s } static bool s_aws_secure_tunnel_protocol_version_match_check( - struct aws_secure_tunnel *secure_tunnel, + const struct aws_secure_tunnel *secure_tunnel, const struct aws_secure_tunnel_message_view *message) { uint8_t message_protocol_version = s_aws_secure_tunnel_message_min_protocol_check(message); if (secure_tunnel->connections->protocol_version != message_protocol_version) { @@ -301,7 +301,7 @@ static bool s_aws_secure_tunnel_active_stream_check( } static bool s_aws_secure_tunnel_is_message_viable_for_connection( - struct aws_secure_tunnel *secure_tunnel, + const struct aws_secure_tunnel *secure_tunnel, const struct aws_secure_tunnel_message_view *message) { if (!s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, message)) { return false; @@ -2560,7 +2560,8 @@ int aws_secure_tunnel_send_message( message_op->options_storage.storage_view.connection_id = 0; } - if (!s_aws_secure_tunnel_is_message_viable_for_connection(secure_tunnel, &message_op->options_storage.storage_view)) { + if (!s_aws_secure_tunnel_is_message_viable_for_connection( + secure_tunnel, &message_op->options_storage.storage_view)) { AWS_LOGF_WARN( AWS_LS_IOTDEVICE_SECURE_TUNNELING, "id=%p: Ignore outbound DATA message due to " diff --git a/tests/secure_tunnel_tests.c b/tests/secure_tunnel_tests.c index b90b8cb4..e585b725 100644 --- a/tests/secure_tunnel_tests.c +++ b/tests/secure_tunnel_tests.c @@ -2148,7 +2148,7 @@ static int s_secure_tunneling_send_v1_message_on_v3_connection_fn(struct aws_all .type = AWS_SECURE_TUNNEL_MT_STREAM_START, .service_id = &service_1, .stream_id = 1, - .connection_id = 3 + .connection_id = 3, }; aws_secure_tunnel_send_mock_message(&test_fixture, &stream_start_message_view); @@ -2194,7 +2194,7 @@ static int s_secure_tunneling_send_v2_message_on_v3_connection_fn(struct aws_all .type = AWS_SECURE_TUNNEL_MT_STREAM_START, .service_id = &service_1, .stream_id = 1, - .connection_id = 3 + .connection_id = 3, }; aws_secure_tunnel_send_mock_message(&test_fixture, &stream_start_message_view); From 31cf647e987ca7120354d91a1dc2f67fb33e082e Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Thu, 17 Aug 2023 09:17:16 -0700 Subject: [PATCH 06/52] Add comments to the tests --- tests/secure_tunnel_tests.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/secure_tunnel_tests.c b/tests/secure_tunnel_tests.c index e585b725..a6e74078 100644 --- a/tests/secure_tunnel_tests.c +++ b/tests/secure_tunnel_tests.c @@ -1970,6 +1970,7 @@ static int s_secure_tunneling_send_v2_message_on_v1_connection_fn(struct aws_all s_wait_for_stream_started(&test_fixture); ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, NULL, 1)); + /* Create and send a V2 DATA message, this should fail with PROTOCOL VERSION MISMATCH error */ struct aws_byte_cursor service_1 = aws_byte_cursor_from_string(s_service_id_1); struct aws_secure_tunnel_message_view data_message_view = { .type = AWS_SECURE_TUNNEL_MT_DATA, @@ -1977,7 +1978,6 @@ static int s_secure_tunneling_send_v2_message_on_v1_connection_fn(struct aws_all .service_id = &service_1, .payload = &s_payload_cursor_max_size, }; - int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH); @@ -2015,6 +2015,7 @@ static int s_secure_tunneling_send_v3_message_on_v1_connection_fn(struct aws_all s_wait_for_stream_started(&test_fixture); ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, NULL, 1)); + /* Create and send a V3 DATA message, this should fail with PROTOCOL VERSION MISMATCH error */ struct aws_byte_cursor service_1 = aws_byte_cursor_from_string(s_service_id_1); struct aws_secure_tunnel_message_view data_message_view = { .type = AWS_SECURE_TUNNEL_MT_DATA, @@ -2023,7 +2024,6 @@ static int s_secure_tunneling_send_v3_message_on_v1_connection_fn(struct aws_all .connection_id = 3, .payload = &s_payload_cursor_max_size, }; - int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH); @@ -2063,6 +2063,7 @@ static int s_secure_tunneling_send_v3_message_on_v2_connection_fn(struct aws_all s_wait_for_stream_started(&test_fixture); ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); + /* Create and send a V3 DATA message, this should fail with PROTOCOL VERSION MISMATCH error */ struct aws_secure_tunnel_message_view data_message_view = { .type = AWS_SECURE_TUNNEL_MT_DATA, .stream_id = 0, @@ -2070,7 +2071,6 @@ static int s_secure_tunneling_send_v3_message_on_v2_connection_fn(struct aws_all .connection_id = 3, .payload = &s_payload_cursor_max_size, }; - int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH); @@ -2097,7 +2097,7 @@ static int s_secure_tunneling_send_v1_message_on_v2_connection_fn(struct aws_all ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); s_wait_for_connected_successfully(&test_fixture); - /* Create and send a V1 StreamStart message from the server to the destination client */ + /* Create and send a V2 StreamStart message from the server to the destination client */ struct aws_byte_cursor service_1 = aws_byte_cursor_from_string(s_service_id_1); struct aws_secure_tunnel_message_view stream_start_message_view = { .type = AWS_SECURE_TUNNEL_MT_STREAM_START, @@ -2110,12 +2110,12 @@ static int s_secure_tunneling_send_v1_message_on_v2_connection_fn(struct aws_all s_wait_for_stream_started(&test_fixture); ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); + /* Create and send a V1 DATA message, this should fail with PROTOCOL VERSION MISMATCH error */ struct aws_secure_tunnel_message_view data_message_view = { .type = AWS_SECURE_TUNNEL_MT_DATA, .stream_id = 0, .payload = &s_payload_cursor_max_size, }; - int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH); @@ -2142,7 +2142,7 @@ static int s_secure_tunneling_send_v1_message_on_v3_connection_fn(struct aws_all ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); s_wait_for_connected_successfully(&test_fixture); - /* Create and send a V1 StreamStart message from the server to the destination client */ + /* Create and send a V3 StreamStart message from the server to the destination client */ struct aws_byte_cursor service_1 = aws_byte_cursor_from_string(s_service_id_1); struct aws_secure_tunnel_message_view stream_start_message_view = { .type = AWS_SECURE_TUNNEL_MT_STREAM_START, @@ -2156,12 +2156,12 @@ static int s_secure_tunneling_send_v1_message_on_v3_connection_fn(struct aws_all s_wait_for_stream_started(&test_fixture); ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); + /* Create and send a V1 DATA message, this should fail with PROTOCOL VERSION MISMATCH error */ struct aws_secure_tunnel_message_view data_message_view = { .type = AWS_SECURE_TUNNEL_MT_DATA, .stream_id = 0, .payload = &s_payload_cursor_max_size, }; - int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH); @@ -2188,7 +2188,7 @@ static int s_secure_tunneling_send_v2_message_on_v3_connection_fn(struct aws_all ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); s_wait_for_connected_successfully(&test_fixture); - /* Create and send a V1 StreamStart message from the server to the destination client */ + /* Create and send a V3 StreamStart message from the server to the destination client */ struct aws_byte_cursor service_1 = aws_byte_cursor_from_string(s_service_id_1); struct aws_secure_tunnel_message_view stream_start_message_view = { .type = AWS_SECURE_TUNNEL_MT_STREAM_START, @@ -2202,13 +2202,13 @@ static int s_secure_tunneling_send_v2_message_on_v3_connection_fn(struct aws_all s_wait_for_stream_started(&test_fixture); ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); + /* Create and send a V2 DATA message, this should fail with PROTOCOL VERSION MISMATCH error */ struct aws_secure_tunnel_message_view data_message_view = { .type = AWS_SECURE_TUNNEL_MT_DATA, .stream_id = 0, .service_id = &service_1, .payload = &s_payload_cursor_max_size, }; - int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH); From 9c11ea43c62712679597b33bf6662a29427b82e4 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Thu, 17 Aug 2023 12:41:24 -0700 Subject: [PATCH 07/52] Add more validations for outgoing DATA messages --- .../iotdevice/private/secure_tunneling_impl.h | 1 + source/secure_tunneling.c | 38 ++++++++++++++++--- tests/secure_tunnel_tests.c | 2 +- 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/include/aws/iotdevice/private/secure_tunneling_impl.h b/include/aws/iotdevice/private/secure_tunneling_impl.h index d416848b..211355db 100644 --- a/include/aws/iotdevice/private/secure_tunneling_impl.h +++ b/include/aws/iotdevice/private/secure_tunneling_impl.h @@ -158,6 +158,7 @@ struct aws_secure_tunnel_connections { /* Used for streams not using multiplexing (service ids) */ int32_t stream_id; + /* TODO This field should be removed. */ struct aws_hash_table connection_ids; /* Table containing streams using multiplexing (service ids) */ diff --git a/source/secure_tunneling.c b/source/secure_tunneling.c index 0a145243..88036053 100644 --- a/source/secure_tunneling.c +++ b/source/secure_tunneling.c @@ -163,6 +163,7 @@ static void s_on_secure_tunnel_zero_ref_count(void *user_data) { * STREAM HANDLING *****************************************************************************************************************/ +/* TODO Remove the message parameter */ static void s_set_absent_connection_id_to_one(struct aws_secure_tunnel_message_view *message, uint32_t *connection_id) { if (message->connection_id == 0) { *connection_id = 1; @@ -300,15 +301,40 @@ static bool s_aws_secure_tunnel_active_stream_check( return true; } -static bool s_aws_secure_tunnel_is_message_viable_for_connection( +static bool s_aws_secure_tunnel_is_data_message_viable_for_connection( const struct aws_secure_tunnel *secure_tunnel, - const struct aws_secure_tunnel_message_view *message) { - if (!s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, message)) { + const struct aws_secure_tunnel_message_view *message_view) { + + /* Verify that the message uses the same protocol version as the secure tunnel current connection. */ + if (!s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, message_view)) { + aws_raise_error(AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH); return false; } - if (!s_aws_secure_tunnel_active_stream_check(secure_tunnel, message)) { + + /* The V1 message will be assigned a stream ID that is currently in use. */ + if (secure_tunnel->connections->protocol_version == 1) { + return true; + } + + /* Check if the requested service ID is opened in the secure tunnel. */ + struct aws_hash_element *elem = NULL; + aws_hash_table_find(&secure_tunnel->connections->service_ids, message_view->service_id, &elem); + if (elem == NULL) { + aws_raise_error(AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INVALID_SERVICE_ID); return false; } + + /* The message uses V3 protocol. */ + if (message_view->connection_id != 0) { + struct aws_service_id_element *service_id_elem = elem->value; + struct aws_hash_element *connection_id_elem = NULL; + aws_hash_table_find(&service_id_elem->connection_ids, &message_view->connection_id, &connection_id_elem); + if (connection_id_elem == NULL) { + aws_raise_error(AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INVALID_CONNECTION_ID); + return false; + } + } + return true; } @@ -321,6 +347,7 @@ static int s_aws_secure_tunnel_set_stream( if (service_id == NULL || service_id->len == 0) { secure_tunnel->connections->stream_id = stream_id; aws_hash_table_clear(&secure_tunnel->connections->connection_ids); + /* TODO This case should be treated as error. */ if (connection_id > 0) { struct aws_connection_id_element *connection_id_elem = aws_connection_id_element_new(secure_tunnel->allocator, connection_id); @@ -2560,14 +2587,13 @@ int aws_secure_tunnel_send_message( message_op->options_storage.storage_view.connection_id = 0; } - if (!s_aws_secure_tunnel_is_message_viable_for_connection( + if (!s_aws_secure_tunnel_is_data_message_viable_for_connection( secure_tunnel, &message_op->options_storage.storage_view)) { AWS_LOGF_WARN( AWS_LS_IOTDEVICE_SECURE_TUNNELING, "id=%p: Ignore outbound DATA message due to " "Protocol Version and Protocol Version used by the message.", (void *)secure_tunnel); - aws_raise_error(AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH); goto error; } diff --git a/tests/secure_tunnel_tests.c b/tests/secure_tunnel_tests.c index a6e74078..f3078875 100644 --- a/tests/secure_tunnel_tests.c +++ b/tests/secure_tunnel_tests.c @@ -1812,7 +1812,7 @@ static int s_secure_tunneling_ignore_outbound_inactive_connection_id_message_sen .connection_id = 3, }; int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); - ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_OPTIONS_VALIDATION); + ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INVALID_CONNECTION_ID); /* Confirm that no messages have gone out from the client */ aws_thread_current_sleep(aws_timestamp_convert(1, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_NANOS, NULL)); From 2f0046c621eaa577b44ebae874b37a3be72c7d67 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Thu, 17 Aug 2023 12:43:26 -0700 Subject: [PATCH 08/52] Fix naming --- source/secure_tunneling.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/secure_tunneling.c b/source/secure_tunneling.c index 88036053..60054c13 100644 --- a/source/secure_tunneling.c +++ b/source/secure_tunneling.c @@ -301,7 +301,7 @@ static bool s_aws_secure_tunnel_active_stream_check( return true; } -static bool s_aws_secure_tunnel_is_data_message_viable_for_connection( +static bool s_aws_secure_tunnel_is_data_message_valid_for_connection( const struct aws_secure_tunnel *secure_tunnel, const struct aws_secure_tunnel_message_view *message_view) { @@ -2587,7 +2587,7 @@ int aws_secure_tunnel_send_message( message_op->options_storage.storage_view.connection_id = 0; } - if (!s_aws_secure_tunnel_is_data_message_viable_for_connection( + if (!s_aws_secure_tunnel_is_data_message_valid_for_connection( secure_tunnel, &message_op->options_storage.storage_view)) { AWS_LOGF_WARN( AWS_LS_IOTDEVICE_SECURE_TUNNELING, From c21052d45cc4c27f9b17d72acd53c69fa63cfa95 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Fri, 18 Aug 2023 11:39:47 -0700 Subject: [PATCH 09/52] Return error on sending DATA message with incorrect parameters --- source/secure_tunneling.c | 21 ++++--- tests/CMakeLists.txt | 2 + tests/secure_tunnel_tests.c | 111 ++++++++++++++++++++++++++++++++++++ 3 files changed, 127 insertions(+), 7 deletions(-) diff --git a/source/secure_tunneling.c b/source/secure_tunneling.c index 60054c13..cdd80105 100644 --- a/source/secure_tunneling.c +++ b/source/secure_tunneling.c @@ -316,7 +316,7 @@ static bool s_aws_secure_tunnel_is_data_message_valid_for_connection( return true; } - /* Check if the requested service ID is opened in the secure tunnel. */ + /* Check if the requested service ID is available in the secure tunnel. */ struct aws_hash_element *elem = NULL; aws_hash_table_find(&secure_tunnel->connections->service_ids, message_view->service_id, &elem); if (elem == NULL) { @@ -324,6 +324,13 @@ static bool s_aws_secure_tunnel_is_data_message_valid_for_connection( return false; } + /* Check if the requested service ID is active. */ + struct aws_service_id_element *service_id_elem = elem->value; + if (service_id_elem->stream_id == INVALID_STREAM_ID) { + aws_raise_error(AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INVALID_SERVICE_ID); + return false; + } + /* The message uses V3 protocol. */ if (message_view->connection_id != 0) { struct aws_service_id_element *service_id_elem = elem->value; @@ -2575,7 +2582,7 @@ int aws_secure_tunnel_send_message( secure_tunnel->allocator, secure_tunnel, message_options, AWS_STOT_MESSAGE); if (message_op == NULL) { - return aws_last_error(); + goto error; } /* @@ -2591,10 +2598,9 @@ int aws_secure_tunnel_send_message( secure_tunnel, &message_op->options_storage.storage_view)) { AWS_LOGF_WARN( AWS_LS_IOTDEVICE_SECURE_TUNNELING, - "id=%p: Ignore outbound DATA message due to " - "Protocol Version and Protocol Version used by the message.", + "id=%p: Failed to send outbound DATA message", (void *)secure_tunnel); - goto error; + goto destroy_message_op; } AWS_LOGF_DEBUG( @@ -2604,13 +2610,14 @@ int aws_secure_tunnel_send_message( (void *)message_op); if (s_submit_operation(secure_tunnel, &message_op->base)) { - goto error; + goto destroy_message_op; } return AWS_OP_SUCCESS; -error: +destroy_message_op: aws_secure_tunnel_operation_release(&message_op->base); +error: return aws_last_error(); } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 36ccf19b..910aaa6f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -50,6 +50,8 @@ add_net_test_case(secure_tunneling_send_v3_message_on_v2_connection) add_net_test_case(secure_tunneling_send_v1_message_on_v2_connection) add_net_test_case(secure_tunneling_send_v1_message_on_v3_connection) add_net_test_case(secure_tunneling_send_v2_message_on_v3_connection) +add_net_test_case(secure_tunneling_send_v2_message_on_incorrect_v2_connection) +add_net_test_case(secure_tunneling_send_v3_message_on_incorrect_v3_connection) generate_test_driver(${PROJECT_NAME}-tests) diff --git a/tests/secure_tunnel_tests.c b/tests/secure_tunnel_tests.c index f3078875..a4203d49 100644 --- a/tests/secure_tunnel_tests.c +++ b/tests/secure_tunnel_tests.c @@ -2224,3 +2224,114 @@ static int s_secure_tunneling_send_v2_message_on_v3_connection_fn(struct aws_all } AWS_TEST_CASE(secure_tunneling_send_v2_message_on_v3_connection, s_secure_tunneling_send_v2_message_on_v3_connection_fn) + +static int s_secure_tunneling_send_v2_message_on_incorrect_v2_connection_fn( + struct aws_allocator *allocator, + void *ctx) { + + (void)ctx; + + struct secure_tunnel_test_options test_options; + struct aws_secure_tunnel_mock_test_fixture test_fixture; + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; + + ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); + s_wait_for_connected_successfully(&test_fixture); + + /* Create and send a V2 StreamStart message from the server to the destination client */ + struct aws_byte_cursor service_1 = aws_byte_cursor_from_string(s_service_id_1); + struct aws_secure_tunnel_message_view stream_start_message_view = { + .type = AWS_SECURE_TUNNEL_MT_STREAM_START, + .service_id = &service_1, + .stream_id = 1, + }; + aws_secure_tunnel_send_mock_message(&test_fixture, &stream_start_message_view); + + /* Wait and confirm that a stream has been started */ + s_wait_for_stream_started(&test_fixture); + ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); + + /* Create and send a V2 DATA message with incorrect service ID, + * this should fail with INVALID SERVICE ID error */ + struct aws_byte_cursor service_2 = aws_byte_cursor_from_string(s_service_id_2); + struct aws_secure_tunnel_message_view data_message_view = { + .type = AWS_SECURE_TUNNEL_MT_DATA, + .stream_id = 0, + .service_id = &service_2, + .payload = &s_payload_cursor_max_size, + }; + + int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); + ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INVALID_SERVICE_ID); + + /* Ensure that the established stream was not affected by the message */ + ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); + + ASSERT_SUCCESS(aws_secure_tunnel_stop(secure_tunnel)); + s_wait_for_connection_shutdown(&test_fixture); + + aws_secure_tunnel_mock_test_clean_up(&test_fixture); + + return AWS_OP_SUCCESS; +} + +AWS_TEST_CASE( + secure_tunneling_send_v2_message_on_incorrect_v2_connection, + s_secure_tunneling_send_v2_message_on_incorrect_v2_connection_fn) + +static int s_secure_tunneling_send_v3_message_on_incorrect_v3_connection_fn( + struct aws_allocator *allocator, + void *ctx) { + + (void)ctx; + + struct secure_tunnel_test_options test_options; + struct aws_secure_tunnel_mock_test_fixture test_fixture; + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; + + ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); + s_wait_for_connected_successfully(&test_fixture); + + /* Create and send a V3 StreamStart message from the server to the destination client */ + struct aws_byte_cursor service_1 = aws_byte_cursor_from_string(s_service_id_1); + struct aws_secure_tunnel_message_view stream_start_message_view = { + .type = AWS_SECURE_TUNNEL_MT_STREAM_START, + .service_id = &service_1, + .stream_id = 1, + .connection_id = 2, + }; + aws_secure_tunnel_send_mock_message(&test_fixture, &stream_start_message_view); + + /* Wait and confirm that a stream has been started */ + s_wait_for_stream_started(&test_fixture); + ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); + + /* Create and send a V3 DATA message with incorrect service ID, + * this should fail with INVALID CONNECTION ID error */ + struct aws_secure_tunnel_message_view data_message_view = { + .type = AWS_SECURE_TUNNEL_MT_DATA, + .stream_id = 0, + .service_id = &service_1, + .connection_id = 3, + .payload = &s_payload_cursor_max_size, + }; + + int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); + ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INVALID_CONNECTION_ID); + + /* Ensure that the established stream was not affected by the message */ + ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); + + ASSERT_SUCCESS(aws_secure_tunnel_stop(secure_tunnel)); + s_wait_for_connection_shutdown(&test_fixture); + + aws_secure_tunnel_mock_test_clean_up(&test_fixture); + + return AWS_OP_SUCCESS; +} + +AWS_TEST_CASE( + secure_tunneling_send_v3_message_on_incorrect_v3_connection, + s_secure_tunneling_send_v3_message_on_incorrect_v3_connection_fn) From 01244732388ee270a9daecd9bbe85129326dfc0f Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Fri, 18 Aug 2023 11:47:18 -0700 Subject: [PATCH 10/52] Fix comments --- source/secure_tunneling.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/source/secure_tunneling.c b/source/secure_tunneling.c index cdd80105..6f3e1df1 100644 --- a/source/secure_tunneling.c +++ b/source/secure_tunneling.c @@ -163,7 +163,6 @@ static void s_on_secure_tunnel_zero_ref_count(void *user_data) { * STREAM HANDLING *****************************************************************************************************************/ -/* TODO Remove the message parameter */ static void s_set_absent_connection_id_to_one(struct aws_secure_tunnel_message_view *message, uint32_t *connection_id) { if (message->connection_id == 0) { *connection_id = 1; @@ -311,7 +310,7 @@ static bool s_aws_secure_tunnel_is_data_message_valid_for_connection( return false; } - /* The V1 message will be assigned a stream ID that is currently in use. */ + /* The V1 message will be assigned a stream ID that is currently in use, so it's always valid. */ if (secure_tunnel->connections->protocol_version == 1) { return true; } @@ -331,7 +330,7 @@ static bool s_aws_secure_tunnel_is_data_message_valid_for_connection( return false; } - /* The message uses V3 protocol. */ + /* The message uses V3 protocol, check connection ID. */ if (message_view->connection_id != 0) { struct aws_service_id_element *service_id_elem = elem->value; struct aws_hash_element *connection_id_elem = NULL; From 2438ee1139c23e7700c3ec3ab09ef4a08fc7f948 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Fri, 18 Aug 2023 11:51:27 -0700 Subject: [PATCH 11/52] Rearrange tests --- tests/CMakeLists.txt | 2 +- tests/secure_tunnel_tests.c | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 910aaa6f..6a8d82f7 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -46,8 +46,8 @@ add_net_test_case(secure_tunneling_close_stream_on_connection_reset_test) add_net_test_case(secure_tunneling_existing_connection_start_send_reset_test) add_net_test_case(secure_tunneling_send_v2_message_on_v1_connection) add_net_test_case(secure_tunneling_send_v3_message_on_v1_connection) -add_net_test_case(secure_tunneling_send_v3_message_on_v2_connection) add_net_test_case(secure_tunneling_send_v1_message_on_v2_connection) +add_net_test_case(secure_tunneling_send_v3_message_on_v2_connection) add_net_test_case(secure_tunneling_send_v1_message_on_v3_connection) add_net_test_case(secure_tunneling_send_v2_message_on_v3_connection) add_net_test_case(secure_tunneling_send_v2_message_on_incorrect_v2_connection) diff --git a/tests/secure_tunnel_tests.c b/tests/secure_tunnel_tests.c index a4203d49..ef0ed13b 100644 --- a/tests/secure_tunnel_tests.c +++ b/tests/secure_tunnel_tests.c @@ -2040,7 +2040,7 @@ static int s_secure_tunneling_send_v3_message_on_v1_connection_fn(struct aws_all AWS_TEST_CASE(secure_tunneling_send_v3_message_on_v1_connection, s_secure_tunneling_send_v3_message_on_v1_connection_fn) -static int s_secure_tunneling_send_v3_message_on_v2_connection_fn(struct aws_allocator *allocator, void *ctx) { +static int s_secure_tunneling_send_v1_message_on_v2_connection_fn(struct aws_allocator *allocator, void *ctx) { (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; @@ -2063,12 +2063,10 @@ static int s_secure_tunneling_send_v3_message_on_v2_connection_fn(struct aws_all s_wait_for_stream_started(&test_fixture); ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); - /* Create and send a V3 DATA message, this should fail with PROTOCOL VERSION MISMATCH error */ + /* Create and send a V1 DATA message, this should fail with PROTOCOL VERSION MISMATCH error */ struct aws_secure_tunnel_message_view data_message_view = { .type = AWS_SECURE_TUNNEL_MT_DATA, .stream_id = 0, - .service_id = &service_1, - .connection_id = 3, .payload = &s_payload_cursor_max_size, }; int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); @@ -2085,9 +2083,9 @@ static int s_secure_tunneling_send_v3_message_on_v2_connection_fn(struct aws_all return AWS_OP_SUCCESS; } -AWS_TEST_CASE(secure_tunneling_send_v3_message_on_v2_connection, s_secure_tunneling_send_v3_message_on_v2_connection_fn) +AWS_TEST_CASE(secure_tunneling_send_v1_message_on_v2_connection, s_secure_tunneling_send_v1_message_on_v2_connection_fn) -static int s_secure_tunneling_send_v1_message_on_v2_connection_fn(struct aws_allocator *allocator, void *ctx) { +static int s_secure_tunneling_send_v3_message_on_v2_connection_fn(struct aws_allocator *allocator, void *ctx) { (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; @@ -2110,10 +2108,12 @@ static int s_secure_tunneling_send_v1_message_on_v2_connection_fn(struct aws_all s_wait_for_stream_started(&test_fixture); ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); - /* Create and send a V1 DATA message, this should fail with PROTOCOL VERSION MISMATCH error */ + /* Create and send a V3 DATA message, this should fail with PROTOCOL VERSION MISMATCH error */ struct aws_secure_tunnel_message_view data_message_view = { .type = AWS_SECURE_TUNNEL_MT_DATA, .stream_id = 0, + .service_id = &service_1, + .connection_id = 3, .payload = &s_payload_cursor_max_size, }; int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); @@ -2130,7 +2130,7 @@ static int s_secure_tunneling_send_v1_message_on_v2_connection_fn(struct aws_all return AWS_OP_SUCCESS; } -AWS_TEST_CASE(secure_tunneling_send_v1_message_on_v2_connection, s_secure_tunneling_send_v1_message_on_v2_connection_fn) +AWS_TEST_CASE(secure_tunneling_send_v3_message_on_v2_connection, s_secure_tunneling_send_v3_message_on_v2_connection_fn) static int s_secure_tunneling_send_v1_message_on_v3_connection_fn(struct aws_allocator *allocator, void *ctx) { (void)ctx; From 38484fee67b1ca73af6bdd18ebade3aa39bc6828 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Fri, 18 Aug 2023 12:04:14 -0700 Subject: [PATCH 12/52] Clean tests --- tests/CMakeLists.txt | 1 - tests/secure_tunnel_tests.c | 85 ++++++++++++++----------------------- 2 files changed, 32 insertions(+), 54 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 6a8d82f7..ebd5522c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -41,7 +41,6 @@ add_net_test_case(secure_tunneling_v2_to_v1_stream_start_test) add_net_test_case(secure_tunneling_v3_to_v1_stream_start_test) add_net_test_case(secure_tunneling_v1_stream_start_v3_message_reset_test) add_net_test_case(secure_tunneling_v2_stream_start_connection_start_reset_test) -add_net_test_case(secure_tunneling_ignore_outbound_inactive_connection_id_message_sending_test) add_net_test_case(secure_tunneling_close_stream_on_connection_reset_test) add_net_test_case(secure_tunneling_existing_connection_start_send_reset_test) add_net_test_case(secure_tunneling_send_v2_message_on_v1_connection) diff --git a/tests/secure_tunnel_tests.c b/tests/secure_tunnel_tests.c index ef0ed13b..8635f1c0 100644 --- a/tests/secure_tunnel_tests.c +++ b/tests/secure_tunnel_tests.c @@ -1777,59 +1777,6 @@ AWS_TEST_CASE( secure_tunneling_v2_stream_start_connection_start_reset_test, s_secure_tunneling_v2_stream_start_connection_start_reset_test_fn) -static int s_secure_tunneling_ignore_outbound_inactive_connection_id_message_sending_test_fn( - struct aws_allocator *allocator, - void *ctx) { - (void)ctx; - struct secure_tunnel_test_options test_options; - struct aws_secure_tunnel_mock_test_fixture test_fixture; - aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); - struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; - - ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); - s_wait_for_connected_successfully(&test_fixture); - - /* Create and send a stream start message from the server to the destination client */ - struct aws_byte_cursor service_1 = aws_byte_cursor_from_string(s_service_id_1); - struct aws_secure_tunnel_message_view stream_start_message_view = { - .type = AWS_SECURE_TUNNEL_MT_STREAM_START, - .service_id = &service_1, - .stream_id = 1, - .connection_id = 2, - }; - aws_secure_tunnel_send_mock_message(&test_fixture, &stream_start_message_view); - - /* Wait and confirm that a stream has been started */ - s_wait_for_stream_started(&test_fixture); - ASSERT_TRUE(s_secure_tunnel_check_active_connection_id(secure_tunnel, &service_1, 1, 2)); - - /* Create and send a data message from the server to the destination client to an inactive connection id */ - struct aws_byte_cursor payload_cur = aws_byte_cursor_from_string(s_payload_text); - struct aws_secure_tunnel_message_view data_message_view = { - .type = AWS_SECURE_TUNNEL_MT_DATA, - .service_id = &service_1, - .payload = &payload_cur, - .connection_id = 3, - }; - int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); - ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INVALID_CONNECTION_ID); - - /* Confirm that no messages have gone out from the client */ - aws_thread_current_sleep(aws_timestamp_convert(1, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_NANOS, NULL)); - ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 0); - - ASSERT_SUCCESS(aws_secure_tunnel_stop(secure_tunnel)); - s_wait_for_connection_shutdown(&test_fixture); - - aws_secure_tunnel_mock_test_clean_up(&test_fixture); - - return AWS_OP_SUCCESS; -} - -AWS_TEST_CASE( - secure_tunneling_ignore_outbound_inactive_connection_id_message_sending_test, - s_secure_tunneling_ignore_outbound_inactive_connection_id_message_sending_test_fn) - static int s_secure_tunneling_close_stream_on_connection_reset_test_fn(struct aws_allocator *allocator, void *ctx) { (void)ctx; struct secure_tunnel_test_options test_options; @@ -1981,6 +1928,10 @@ static int s_secure_tunneling_send_v2_message_on_v1_connection_fn(struct aws_all int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH); + /* Confirm that no messages have gone out from the client */ + aws_thread_current_sleep(aws_timestamp_convert(1, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_NANOS, NULL)); + ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 0); + /* Ensure that the established stream was not affected by the message */ ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, NULL, 1)); @@ -2027,6 +1978,10 @@ static int s_secure_tunneling_send_v3_message_on_v1_connection_fn(struct aws_all int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH); + /* Confirm that no messages have gone out from the client */ + aws_thread_current_sleep(aws_timestamp_convert(1, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_NANOS, NULL)); + ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 0); + /* Ensure that the established stream was not affected by the message */ ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, NULL, 1)); @@ -2072,6 +2027,10 @@ static int s_secure_tunneling_send_v1_message_on_v2_connection_fn(struct aws_all int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH); + /* Confirm that no messages have gone out from the client */ + aws_thread_current_sleep(aws_timestamp_convert(1, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_NANOS, NULL)); + ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 0); + /* Ensure that the established stream was not affected by the message */ ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); @@ -2119,6 +2078,10 @@ static int s_secure_tunneling_send_v3_message_on_v2_connection_fn(struct aws_all int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH); + /* Confirm that no messages have gone out from the client */ + aws_thread_current_sleep(aws_timestamp_convert(1, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_NANOS, NULL)); + ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 0); + /* Ensure that the established stream was not affected by the message */ ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); @@ -2165,6 +2128,10 @@ static int s_secure_tunneling_send_v1_message_on_v3_connection_fn(struct aws_all int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH); + /* Confirm that no messages have gone out from the client */ + aws_thread_current_sleep(aws_timestamp_convert(1, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_NANOS, NULL)); + ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 0); + /* Ensure that the established stream was not affected by the message */ ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); @@ -2212,6 +2179,10 @@ static int s_secure_tunneling_send_v2_message_on_v3_connection_fn(struct aws_all int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH); + /* Confirm that no messages have gone out from the client */ + aws_thread_current_sleep(aws_timestamp_convert(1, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_NANOS, NULL)); + ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 0); + /* Ensure that the established stream was not affected by the message */ ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); @@ -2265,6 +2236,10 @@ static int s_secure_tunneling_send_v2_message_on_incorrect_v2_connection_fn( int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INVALID_SERVICE_ID); + /* Confirm that no messages have gone out from the client */ + aws_thread_current_sleep(aws_timestamp_convert(1, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_NANOS, NULL)); + ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 0); + /* Ensure that the established stream was not affected by the message */ ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); @@ -2321,6 +2296,10 @@ static int s_secure_tunneling_send_v3_message_on_incorrect_v3_connection_fn( int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INVALID_CONNECTION_ID); + /* Confirm that no messages have gone out from the client */ + aws_thread_current_sleep(aws_timestamp_convert(1, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_NANOS, NULL)); + ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 0); + /* Ensure that the established stream was not affected by the message */ ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); From bab563291b6940d8f69272972f4e724381169bc0 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Fri, 18 Aug 2023 12:05:17 -0700 Subject: [PATCH 13/52] Fix formatting --- source/secure_tunneling.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/source/secure_tunneling.c b/source/secure_tunneling.c index 6f3e1df1..086292eb 100644 --- a/source/secure_tunneling.c +++ b/source/secure_tunneling.c @@ -2596,9 +2596,7 @@ int aws_secure_tunnel_send_message( if (!s_aws_secure_tunnel_is_data_message_valid_for_connection( secure_tunnel, &message_op->options_storage.storage_view)) { AWS_LOGF_WARN( - AWS_LS_IOTDEVICE_SECURE_TUNNELING, - "id=%p: Failed to send outbound DATA message", - (void *)secure_tunnel); + AWS_LS_IOTDEVICE_SECURE_TUNNELING, "id=%p: Failed to send outbound DATA message", (void *)secure_tunnel); goto destroy_message_op; } From 4b5b31c21926b5e0221e86da936f3b3042d218ba Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Fri, 18 Aug 2023 13:52:39 -0700 Subject: [PATCH 14/52] Add new errors, add test --- include/aws/iotdevice/iotdevice.h | 4 +++ source/iotdevice.c | 19 ++++++++--- source/secure_tunneling.c | 16 ++++++++-- tests/CMakeLists.txt | 1 + tests/secure_tunnel_tests.c | 53 +++++++++++++++++++++++++++---- 5 files changed, 79 insertions(+), 14 deletions(-) diff --git a/include/aws/iotdevice/iotdevice.h b/include/aws/iotdevice/iotdevice.h index ac386872..e772d9ab 100644 --- a/include/aws/iotdevice/iotdevice.h +++ b/include/aws/iotdevice/iotdevice.h @@ -38,9 +38,13 @@ enum aws_iotdevice_error { AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_OPERATION_FAILED_DUE_TO_OFFLINE_QUEUE_POLICY, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_UNEXPECTED_HANGUP, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_USER_REQUESTED_STOP, + /* NOTE Leave the old name for compatibility */ AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH, + AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISMATCH = AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_TERMINATED, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DECODE_FAILURE, + AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_NO_ACTIVE_CONNECTION, + AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_PROTOCOL_VERSION_MISMATCH, AWS_ERROR_END_IOTDEVICE_RANGE = AWS_ERROR_ENUM_END_RANGE(AWS_C_IOTDEVICE_PACKAGE_ID), }; diff --git a/source/iotdevice.c b/source/iotdevice.c index 3a317275..6a10d68b 100644 --- a/source/iotdevice.c +++ b/source/iotdevice.c @@ -77,22 +77,31 @@ static struct aws_error_info s_errors[] = { "Error while processing secure tunnel operational state."), AWS_DEFINE_ERROR_INFO_IOTDEVICE( AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_OPERATION_FAILED_DUE_TO_OFFLINE_QUEUE_POLICY, - "Error while processing secure tunnel operational state."), + "Secure Tunnel operation failed due to offline queue policy."), AWS_DEFINE_ERROR_INFO_IOTDEVICE( AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_UNEXPECTED_HANGUP, "The connection was closed unexpectedly."), AWS_DEFINE_ERROR_INFO_IOTDEVICE( AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_USER_REQUESTED_STOP, "Secure Tunnel connection interrupted by user request."), + AWS_DEFINE_ERROR_INFO_IOTDEVICE( + AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISMATCH, + "Secure Tunnel connection interrupted due to a protocol version mismatch."), AWS_DEFINE_ERROR_INFO_IOTDEVICE( AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH, - "Secure Tunnel connection interrupted due to a protocol version missmatch."), + "Secure Tunnel connection interrupted due to a protocol version mismatch."), AWS_DEFINE_ERROR_INFO_IOTDEVICE( AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_TERMINATED, "Secure Tunnel terminated by user request."), - AWS_DEFINE_ERROR_INFO_IOTDEVICE( - AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DECODE_FAILURE, - "Error occured while decoding an incoming message." ), + AWS_DEFINE_ERROR_INFO_IOTDEVICE( + AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DECODE_FAILURE, + "Error occured while decoding an incoming message." ), + AWS_DEFINE_ERROR_INFO_IOTDEVICE( + AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_NO_ACTIVE_CONNECTION, + "DATA message processing failed due to no active connection found." ), + AWS_DEFINE_ERROR_INFO_IOTDEVICE( + AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_PROTOCOL_VERSION_MISMATCH, + "DATA message processing failed due to a protocol version mismatch." ), }; /* clang-format on */ #undef AWS_DEFINE_ERROR_INFO_IOTDEVICE diff --git a/source/secure_tunneling.c b/source/secure_tunneling.c index 086292eb..b5ccfa0a 100644 --- a/source/secure_tunneling.c +++ b/source/secure_tunneling.c @@ -300,13 +300,23 @@ static bool s_aws_secure_tunnel_active_stream_check( return true; } -static bool s_aws_secure_tunnel_is_data_message_valid_for_connection( +/** + * \internal + * Check if DATA message can be sent to one of active connections. + * \endinternal + */ +static bool s_aws_secure_tunnel_is_data_message_valid_for_connections( const struct aws_secure_tunnel *secure_tunnel, const struct aws_secure_tunnel_message_view *message_view) { + if (secure_tunnel->connections->protocol_version == 0) { + aws_raise_error(AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_NO_ACTIVE_CONNECTION); + return false; + } + /* Verify that the message uses the same protocol version as the secure tunnel current connection. */ if (!s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, message_view)) { - aws_raise_error(AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH); + aws_raise_error(AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_PROTOCOL_VERSION_MISMATCH); return false; } @@ -2593,7 +2603,7 @@ int aws_secure_tunnel_send_message( message_op->options_storage.storage_view.connection_id = 0; } - if (!s_aws_secure_tunnel_is_data_message_valid_for_connection( + if (!s_aws_secure_tunnel_is_data_message_valid_for_connections( secure_tunnel, &message_op->options_storage.storage_view)) { AWS_LOGF_WARN( AWS_LS_IOTDEVICE_SECURE_TUNNELING, "id=%p: Failed to send outbound DATA message", (void *)secure_tunnel); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index ebd5522c..722537f0 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -51,6 +51,7 @@ add_net_test_case(secure_tunneling_send_v1_message_on_v3_connection) add_net_test_case(secure_tunneling_send_v2_message_on_v3_connection) add_net_test_case(secure_tunneling_send_v2_message_on_incorrect_v2_connection) add_net_test_case(secure_tunneling_send_v3_message_on_incorrect_v3_connection) +add_net_test_case(secure_tunneling_send_v1_data_message_with_no_active_connection) generate_test_driver(${PROJECT_NAME}-tests) diff --git a/tests/secure_tunnel_tests.c b/tests/secure_tunnel_tests.c index 8635f1c0..fff50369 100644 --- a/tests/secure_tunnel_tests.c +++ b/tests/secure_tunnel_tests.c @@ -1926,7 +1926,7 @@ static int s_secure_tunneling_send_v2_message_on_v1_connection_fn(struct aws_all .payload = &s_payload_cursor_max_size, }; int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); - ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH); + ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_PROTOCOL_VERSION_MISMATCH); /* Confirm that no messages have gone out from the client */ aws_thread_current_sleep(aws_timestamp_convert(1, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_NANOS, NULL)); @@ -1976,7 +1976,7 @@ static int s_secure_tunneling_send_v3_message_on_v1_connection_fn(struct aws_all .payload = &s_payload_cursor_max_size, }; int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); - ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH); + ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_PROTOCOL_VERSION_MISMATCH); /* Confirm that no messages have gone out from the client */ aws_thread_current_sleep(aws_timestamp_convert(1, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_NANOS, NULL)); @@ -2025,7 +2025,7 @@ static int s_secure_tunneling_send_v1_message_on_v2_connection_fn(struct aws_all .payload = &s_payload_cursor_max_size, }; int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); - ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH); + ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_PROTOCOL_VERSION_MISMATCH); /* Confirm that no messages have gone out from the client */ aws_thread_current_sleep(aws_timestamp_convert(1, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_NANOS, NULL)); @@ -2076,7 +2076,7 @@ static int s_secure_tunneling_send_v3_message_on_v2_connection_fn(struct aws_all .payload = &s_payload_cursor_max_size, }; int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); - ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH); + ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_PROTOCOL_VERSION_MISMATCH); /* Confirm that no messages have gone out from the client */ aws_thread_current_sleep(aws_timestamp_convert(1, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_NANOS, NULL)); @@ -2126,7 +2126,7 @@ static int s_secure_tunneling_send_v1_message_on_v3_connection_fn(struct aws_all .payload = &s_payload_cursor_max_size, }; int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); - ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH); + ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_PROTOCOL_VERSION_MISMATCH); /* Confirm that no messages have gone out from the client */ aws_thread_current_sleep(aws_timestamp_convert(1, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_NANOS, NULL)); @@ -2177,7 +2177,7 @@ static int s_secure_tunneling_send_v2_message_on_v3_connection_fn(struct aws_all .payload = &s_payload_cursor_max_size, }; int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); - ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH); + ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_PROTOCOL_VERSION_MISMATCH); /* Confirm that no messages have gone out from the client */ aws_thread_current_sleep(aws_timestamp_convert(1, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_NANOS, NULL)); @@ -2314,3 +2314,44 @@ static int s_secure_tunneling_send_v3_message_on_incorrect_v3_connection_fn( AWS_TEST_CASE( secure_tunneling_send_v3_message_on_incorrect_v3_connection, s_secure_tunneling_send_v3_message_on_incorrect_v3_connection_fn) + +static int s_secure_tunneling_send_v1_data_message_with_no_active_connection_fn( + struct aws_allocator *allocator, + void *ctx) { + + (void)ctx; + + struct secure_tunnel_test_options test_options; + struct aws_secure_tunnel_mock_test_fixture test_fixture; + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; + + ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); + s_wait_for_connected_successfully(&test_fixture); + + /* Create and send a V1 DATA message, + * this should fail with INVALID CONNECTION ID error */ + struct aws_secure_tunnel_message_view data_message_view = { + .type = AWS_SECURE_TUNNEL_MT_DATA, + .stream_id = 0, + .payload = &s_payload_cursor_max_size, + }; + + int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); + ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_NO_ACTIVE_CONNECTION); + + /* Confirm that no messages have gone out from the client */ + aws_thread_current_sleep(aws_timestamp_convert(1, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_NANOS, NULL)); + ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 0); + + ASSERT_SUCCESS(aws_secure_tunnel_stop(secure_tunnel)); + s_wait_for_connection_shutdown(&test_fixture); + + aws_secure_tunnel_mock_test_clean_up(&test_fixture); + + return AWS_OP_SUCCESS; +} + +AWS_TEST_CASE( + secure_tunneling_send_v1_data_message_with_no_active_connection, + s_secure_tunneling_send_v1_data_message_with_no_active_connection_fn) From 041e9372fa00176d34addc519c2ffa6218fa21a0 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Fri, 18 Aug 2023 13:54:02 -0700 Subject: [PATCH 15/52] Fix formatting --- include/aws/iotdevice/iotdevice.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/aws/iotdevice/iotdevice.h b/include/aws/iotdevice/iotdevice.h index e772d9ab..d6450418 100644 --- a/include/aws/iotdevice/iotdevice.h +++ b/include/aws/iotdevice/iotdevice.h @@ -40,7 +40,8 @@ enum aws_iotdevice_error { AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_USER_REQUESTED_STOP, /* NOTE Leave the old name for compatibility */ AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH, - AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISMATCH = AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH, + AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISMATCH = + AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_TERMINATED, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DECODE_FAILURE, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_NO_ACTIVE_CONNECTION, From 4d8e6e52ebeac6ea6c3c639dfb021a5bce731ebf Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Fri, 18 Aug 2023 13:57:17 -0700 Subject: [PATCH 16/52] Fix typo --- .../iotdevice/private/secure_tunneling_impl.h | 2 +- source/secure_tunneling.c | 28 +++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/include/aws/iotdevice/private/secure_tunneling_impl.h b/include/aws/iotdevice/private/secure_tunneling_impl.h index 211355db..e1f0e4bf 100644 --- a/include/aws/iotdevice/private/secure_tunneling_impl.h +++ b/include/aws/iotdevice/private/secure_tunneling_impl.h @@ -164,7 +164,7 @@ struct aws_secure_tunnel_connections { /* Table containing streams using multiplexing (service ids) */ struct aws_hash_table service_ids; - /* Message used for initializing a stream upon a reconnect due to a protocol version missmatch */ + /* Message used for initializing a stream upon a reconnect due to a protocol version mismatch */ struct aws_secure_tunnel_message_storage *restore_stream_message_view; struct aws_secure_tunnel_message_storage restore_stream_message; }; diff --git a/source/secure_tunneling.c b/source/secure_tunneling.c index b5ccfa0a..a668e459 100644 --- a/source/secure_tunneling.c +++ b/source/secure_tunneling.c @@ -566,12 +566,12 @@ static void s_aws_secure_tunnel_on_data_received( if (!s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, message_view)) { /* - * Protocol missmatch results in a full disconnect/reconnect to the Secure Tunnel Service followed by - * initializing the stream that caused the missmatch + * Protocol mismatch results in a full disconnect/reconnect to the Secure Tunnel Service followed by + * initializing the stream that caused the mismatch */ AWS_LOGF_INFO( AWS_LS_IOTDEVICE_SECURE_TUNNELING, - "id=%p: Secure Tunnel will be reset due to Protocol Version missmatch between previously established " + "id=%p: Secure Tunnel will be reset due to Protocol Version mismatch between previously established " "Protocol Version and Protocol Version used by incoming STREAM START message.", (void *)secure_tunnel); reset_secure_tunnel_connection(secure_tunnel); @@ -628,12 +628,12 @@ static void s_aws_secure_tunnel_on_stream_start_received( secure_tunnel->connections->protocol_version); } else if (!s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, message_view)) { /* - * Protocol missmatch results in a full disconnect/reconnect to the Secure Tunnel Service followed by - * initializing the stream that caused the missmatch + * Protocol mismatch results in a full disconnect/reconnect to the Secure Tunnel Service followed by + * initializing the stream that caused the mismatch */ AWS_LOGF_INFO( AWS_LS_IOTDEVICE_SECURE_TUNNELING, - "id=%p: Secure Tunnel will be reset due to Protocol Version missmatch between previously established " + "id=%p: Secure Tunnel will be reset due to Protocol Version mismatch between previously established " "Protocol Version and Protocol Version used by incoming STREAM START message.", (void *)secure_tunnel); reset_secure_tunnel_connection(secure_tunnel); @@ -671,7 +671,7 @@ static void s_aws_secure_tunnel_on_stream_reset_received( !s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, message_view)) { AWS_LOGF_INFO( AWS_LS_IOTDEVICE_SECURE_TUNNELING, - "id=%p: Secure Tunnel will be reset due to Protocol Version missmatch between previously established " + "id=%p: Secure Tunnel will be reset due to Protocol Version mismatch between previously established " "Protocol Version and Protocol Version used by incoming STREAM RESET message.", (void *)secure_tunnel); reset_secure_tunnel_connection(secure_tunnel); @@ -784,7 +784,7 @@ static void s_aws_secure_tunnel_on_connection_start_received( if (secure_tunnel->connections->protocol_version != 3) { AWS_LOGF_INFO( AWS_LS_IOTDEVICE_SECURE_TUNNELING, - "id=%p: Secure Tunnel will be reset due to Protocol Version missmatch between previously established " + "id=%p: Secure Tunnel will be reset due to Protocol Version mismatch between previously established " "Protocol Version and Protocol Version used by incoming CONNECTION START message.", (void *)secure_tunnel); reset_secure_tunnel_connection(secure_tunnel); @@ -827,7 +827,7 @@ static void s_aws_secure_tunnel_on_connection_reset_received( if (secure_tunnel->connections->protocol_version != 3) { AWS_LOGF_INFO( AWS_LS_IOTDEVICE_SECURE_TUNNELING, - "id=%p: Secure Tunnel will be reset due to Protocol Version missmatch between previously established " + "id=%p: Secure Tunnel will be reset due to Protocol Version mismatch between previously established " "Protocol Version and Protocol Version used by incoming CONNECTION RESET message.", (void *)secure_tunnel); reset_secure_tunnel_connection(secure_tunnel); @@ -2366,7 +2366,7 @@ static void s_service_state_clean_disconnect(struct aws_secure_tunnel *secure_tu if (aws_linked_list_empty(&secure_tunnel->queued_operations)) { s_reset_secure_tunnel_streams(secure_tunnel); s_secure_tunnel_shutdown_websocket( - secure_tunnel, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH); + secure_tunnel, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISMATCH); return; } @@ -2641,12 +2641,12 @@ int aws_secure_tunnel_stream_start( if (!s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, message_options)) { /* - * Protocol missmatch results in a full disconnect/reconnect to the Secure Tunnel Service followed by - * sending the STREAM START request that caused the missmatch. + * Protocol mismatch results in a full disconnect/reconnect to the Secure Tunnel Service followed by + * sending the STREAM START request that caused the mismatch. */ AWS_LOGF_INFO( AWS_LS_IOTDEVICE_SECURE_TUNNELING, - "id=%p: Secure Tunnel will be reset due to Protocol Version missmatch between previously established " + "id=%p: Secure Tunnel will be reset due to Protocol Version mismatch between previously established " "Protocol Version and Protocol Version used by outbound STREAM START message.", (void *)secure_tunnel); reset_secure_tunnel_connection(secure_tunnel); @@ -2699,7 +2699,7 @@ int aws_secure_tunnel_connection_start( if (secure_tunnel->connections->protocol_version != 3) { AWS_LOGF_WARN( AWS_LS_IOTDEVICE_SECURE_TUNNELING, "Connection Start may only be used with a Protocol V3 stream."); - return AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH; + return AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISMATCH; } if (message_options->connection_id == 0) { From a561c40b9289085ddfb5918c22e35d485d2f0464 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Fri, 18 Aug 2023 14:05:10 -0700 Subject: [PATCH 17/52] Fix tests naming --- tests/CMakeLists.txt | 16 ++++++------- tests/secure_tunnel_tests.c | 48 +++++++++++++++++++++++-------------- 2 files changed, 38 insertions(+), 26 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 722537f0..d25357de 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -43,14 +43,14 @@ add_net_test_case(secure_tunneling_v1_stream_start_v3_message_reset_test) add_net_test_case(secure_tunneling_v2_stream_start_connection_start_reset_test) add_net_test_case(secure_tunneling_close_stream_on_connection_reset_test) add_net_test_case(secure_tunneling_existing_connection_start_send_reset_test) -add_net_test_case(secure_tunneling_send_v2_message_on_v1_connection) -add_net_test_case(secure_tunneling_send_v3_message_on_v1_connection) -add_net_test_case(secure_tunneling_send_v1_message_on_v2_connection) -add_net_test_case(secure_tunneling_send_v3_message_on_v2_connection) -add_net_test_case(secure_tunneling_send_v1_message_on_v3_connection) -add_net_test_case(secure_tunneling_send_v2_message_on_v3_connection) -add_net_test_case(secure_tunneling_send_v2_message_on_incorrect_v2_connection) -add_net_test_case(secure_tunneling_send_v3_message_on_incorrect_v3_connection) +add_net_test_case(secure_tunneling_send_v2_data_message_on_v1_connection) +add_net_test_case(secure_tunneling_send_v3_data_message_on_v1_connection) +add_net_test_case(secure_tunneling_send_v1_data_message_on_v2_connection) +add_net_test_case(secure_tunneling_send_v3_data_message_on_v2_connection) +add_net_test_case(secure_tunneling_send_v1_data_message_on_v3_connection) +add_net_test_case(secure_tunneling_send_v2_data_message_on_v3_connection) +add_net_test_case(secure_tunneling_send_v2_data_message_on_incorrect_v2_connection) +add_net_test_case(secure_tunneling_send_v3_data_message_on_incorrect_v3_connection) add_net_test_case(secure_tunneling_send_v1_data_message_with_no_active_connection) generate_test_driver(${PROJECT_NAME}-tests) diff --git a/tests/secure_tunnel_tests.c b/tests/secure_tunnel_tests.c index fff50369..2b4a0f61 100644 --- a/tests/secure_tunnel_tests.c +++ b/tests/secure_tunnel_tests.c @@ -1896,7 +1896,7 @@ AWS_TEST_CASE( secure_tunneling_existing_connection_start_send_reset_test, s_secure_tunneling_existing_connection_start_send_reset_test_fn) -static int s_secure_tunneling_send_v2_message_on_v1_connection_fn(struct aws_allocator *allocator, void *ctx) { +static int s_secure_tunneling_send_v2_data_message_on_v1_connection_fn(struct aws_allocator *allocator, void *ctx) { (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; @@ -1943,9 +1943,11 @@ static int s_secure_tunneling_send_v2_message_on_v1_connection_fn(struct aws_all return AWS_OP_SUCCESS; } -AWS_TEST_CASE(secure_tunneling_send_v2_message_on_v1_connection, s_secure_tunneling_send_v2_message_on_v1_connection_fn) +AWS_TEST_CASE( + secure_tunneling_send_v2_data_message_on_v1_connection, + s_secure_tunneling_send_v2_data_message_on_v1_connection_fn) -static int s_secure_tunneling_send_v3_message_on_v1_connection_fn(struct aws_allocator *allocator, void *ctx) { +static int s_secure_tunneling_send_v3_data_message_on_v1_connection_fn(struct aws_allocator *allocator, void *ctx) { (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; @@ -1993,9 +1995,11 @@ static int s_secure_tunneling_send_v3_message_on_v1_connection_fn(struct aws_all return AWS_OP_SUCCESS; } -AWS_TEST_CASE(secure_tunneling_send_v3_message_on_v1_connection, s_secure_tunneling_send_v3_message_on_v1_connection_fn) +AWS_TEST_CASE( + secure_tunneling_send_v3_data_message_on_v1_connection, + s_secure_tunneling_send_v3_data_message_on_v1_connection_fn) -static int s_secure_tunneling_send_v1_message_on_v2_connection_fn(struct aws_allocator *allocator, void *ctx) { +static int s_secure_tunneling_send_v1_data_message_on_v2_connection_fn(struct aws_allocator *allocator, void *ctx) { (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; @@ -2042,9 +2046,11 @@ static int s_secure_tunneling_send_v1_message_on_v2_connection_fn(struct aws_all return AWS_OP_SUCCESS; } -AWS_TEST_CASE(secure_tunneling_send_v1_message_on_v2_connection, s_secure_tunneling_send_v1_message_on_v2_connection_fn) +AWS_TEST_CASE( + secure_tunneling_send_v1_data_message_on_v2_connection, + s_secure_tunneling_send_v1_data_message_on_v2_connection_fn) -static int s_secure_tunneling_send_v3_message_on_v2_connection_fn(struct aws_allocator *allocator, void *ctx) { +static int s_secure_tunneling_send_v3_data_message_on_v2_connection_fn(struct aws_allocator *allocator, void *ctx) { (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; @@ -2093,9 +2099,11 @@ static int s_secure_tunneling_send_v3_message_on_v2_connection_fn(struct aws_all return AWS_OP_SUCCESS; } -AWS_TEST_CASE(secure_tunneling_send_v3_message_on_v2_connection, s_secure_tunneling_send_v3_message_on_v2_connection_fn) +AWS_TEST_CASE( + secure_tunneling_send_v3_data_message_on_v2_connection, + s_secure_tunneling_send_v3_data_message_on_v2_connection_fn) -static int s_secure_tunneling_send_v1_message_on_v3_connection_fn(struct aws_allocator *allocator, void *ctx) { +static int s_secure_tunneling_send_v1_data_message_on_v3_connection_fn(struct aws_allocator *allocator, void *ctx) { (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; @@ -2143,9 +2151,11 @@ static int s_secure_tunneling_send_v1_message_on_v3_connection_fn(struct aws_all return AWS_OP_SUCCESS; } -AWS_TEST_CASE(secure_tunneling_send_v1_message_on_v3_connection, s_secure_tunneling_send_v1_message_on_v3_connection_fn) +AWS_TEST_CASE( + secure_tunneling_send_v1_data_message_on_v3_connection, + s_secure_tunneling_send_v1_data_message_on_v3_connection_fn) -static int s_secure_tunneling_send_v2_message_on_v3_connection_fn(struct aws_allocator *allocator, void *ctx) { +static int s_secure_tunneling_send_v2_data_message_on_v3_connection_fn(struct aws_allocator *allocator, void *ctx) { (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; @@ -2194,9 +2204,11 @@ static int s_secure_tunneling_send_v2_message_on_v3_connection_fn(struct aws_all return AWS_OP_SUCCESS; } -AWS_TEST_CASE(secure_tunneling_send_v2_message_on_v3_connection, s_secure_tunneling_send_v2_message_on_v3_connection_fn) +AWS_TEST_CASE( + secure_tunneling_send_v2_data_message_on_v3_connection, + s_secure_tunneling_send_v2_data_message_on_v3_connection_fn) -static int s_secure_tunneling_send_v2_message_on_incorrect_v2_connection_fn( +static int s_secure_tunneling_send_v2_data_message_on_incorrect_v2_connection_fn( struct aws_allocator *allocator, void *ctx) { @@ -2252,10 +2264,10 @@ static int s_secure_tunneling_send_v2_message_on_incorrect_v2_connection_fn( } AWS_TEST_CASE( - secure_tunneling_send_v2_message_on_incorrect_v2_connection, - s_secure_tunneling_send_v2_message_on_incorrect_v2_connection_fn) + secure_tunneling_send_v2_data_message_on_incorrect_v2_connection, + s_secure_tunneling_send_v2_data_message_on_incorrect_v2_connection_fn) -static int s_secure_tunneling_send_v3_message_on_incorrect_v3_connection_fn( +static int s_secure_tunneling_send_v3_data_message_on_incorrect_v3_connection_fn( struct aws_allocator *allocator, void *ctx) { @@ -2312,8 +2324,8 @@ static int s_secure_tunneling_send_v3_message_on_incorrect_v3_connection_fn( } AWS_TEST_CASE( - secure_tunneling_send_v3_message_on_incorrect_v3_connection, - s_secure_tunneling_send_v3_message_on_incorrect_v3_connection_fn) + secure_tunneling_send_v3_data_message_on_incorrect_v3_connection, + s_secure_tunneling_send_v3_data_message_on_incorrect_v3_connection_fn) static int s_secure_tunneling_send_v1_data_message_with_no_active_connection_fn( struct aws_allocator *allocator, From 267ab22dc39dc27d310df694415d1ca1863ec57d Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Fri, 18 Aug 2023 14:07:11 -0700 Subject: [PATCH 18/52] Fix order of enum errors --- source/iotdevice.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/iotdevice.c b/source/iotdevice.c index 6a10d68b..5954b5eb 100644 --- a/source/iotdevice.c +++ b/source/iotdevice.c @@ -85,10 +85,10 @@ static struct aws_error_info s_errors[] = { AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_USER_REQUESTED_STOP, "Secure Tunnel connection interrupted by user request."), AWS_DEFINE_ERROR_INFO_IOTDEVICE( - AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISMATCH, + AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH, "Secure Tunnel connection interrupted due to a protocol version mismatch."), AWS_DEFINE_ERROR_INFO_IOTDEVICE( - AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH, + AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISMATCH, "Secure Tunnel connection interrupted due to a protocol version mismatch."), AWS_DEFINE_ERROR_INFO_IOTDEVICE( AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_TERMINATED, From 424b24c02e222eccce1a9c3dba0d77d4dfaad0b5 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Fri, 18 Aug 2023 14:15:38 -0700 Subject: [PATCH 19/52] Fix enum erros --- include/aws/iotdevice/iotdevice.h | 2 +- source/iotdevice.c | 3 --- source/secure_tunneling.c | 3 +-- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/include/aws/iotdevice/iotdevice.h b/include/aws/iotdevice/iotdevice.h index d6450418..9cee8fa9 100644 --- a/include/aws/iotdevice/iotdevice.h +++ b/include/aws/iotdevice/iotdevice.h @@ -38,7 +38,7 @@ enum aws_iotdevice_error { AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_OPERATION_FAILED_DUE_TO_OFFLINE_QUEUE_POLICY, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_UNEXPECTED_HANGUP, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_USER_REQUESTED_STOP, - /* NOTE Leave the old name for compatibility */ + /* NOTE Leave the old name for compatibility. */ AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISMATCH = AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH, diff --git a/source/iotdevice.c b/source/iotdevice.c index 5954b5eb..03dd9d6a 100644 --- a/source/iotdevice.c +++ b/source/iotdevice.c @@ -84,9 +84,6 @@ static struct aws_error_info s_errors[] = { AWS_DEFINE_ERROR_INFO_IOTDEVICE( AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_USER_REQUESTED_STOP, "Secure Tunnel connection interrupted by user request."), - AWS_DEFINE_ERROR_INFO_IOTDEVICE( - AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH, - "Secure Tunnel connection interrupted due to a protocol version mismatch."), AWS_DEFINE_ERROR_INFO_IOTDEVICE( AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISMATCH, "Secure Tunnel connection interrupted due to a protocol version mismatch."), diff --git a/source/secure_tunneling.c b/source/secure_tunneling.c index a668e459..ff7c3d38 100644 --- a/source/secure_tunneling.c +++ b/source/secure_tunneling.c @@ -314,7 +314,6 @@ static bool s_aws_secure_tunnel_is_data_message_valid_for_connections( return false; } - /* Verify that the message uses the same protocol version as the secure tunnel current connection. */ if (!s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, message_view)) { aws_raise_error(AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_PROTOCOL_VERSION_MISMATCH); return false; @@ -325,7 +324,7 @@ static bool s_aws_secure_tunnel_is_data_message_valid_for_connections( return true; } - /* Check if the requested service ID is available in the secure tunnel. */ + /* The message is at least V2 version, check if the requested service ID is available in the secure tunnel. */ struct aws_hash_element *elem = NULL; aws_hash_table_find(&secure_tunnel->connections->service_ids, message_view->service_id, &elem); if (elem == NULL) { From 5061e4a3c7f90e0d3847399891800a1ed461f0ac Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Fri, 18 Aug 2023 14:21:00 -0700 Subject: [PATCH 20/52] Remove extra variable --- source/secure_tunneling.c | 1 - 1 file changed, 1 deletion(-) diff --git a/source/secure_tunneling.c b/source/secure_tunneling.c index ff7c3d38..d5d64eca 100644 --- a/source/secure_tunneling.c +++ b/source/secure_tunneling.c @@ -341,7 +341,6 @@ static bool s_aws_secure_tunnel_is_data_message_valid_for_connections( /* The message uses V3 protocol, check connection ID. */ if (message_view->connection_id != 0) { - struct aws_service_id_element *service_id_elem = elem->value; struct aws_hash_element *connection_id_elem = NULL; aws_hash_table_find(&service_id_elem->connection_ids, &message_view->connection_id, &connection_id_elem); if (connection_id_elem == NULL) { From cdd6d72202dcecb6a21eab48826cc02330b08ec6 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Tue, 22 Aug 2023 10:01:31 -0700 Subject: [PATCH 21/52] Add test with data race --- tests/CMakeLists.txt | 1 + tests/secure_tunnel_tests.c | 68 ++++++++++++++++++++++++++++++++++++- 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d25357de..0b696547 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -52,6 +52,7 @@ add_net_test_case(secure_tunneling_send_v2_data_message_on_v3_connection) add_net_test_case(secure_tunneling_send_v2_data_message_on_incorrect_v2_connection) add_net_test_case(secure_tunneling_send_v3_data_message_on_incorrect_v3_connection) add_net_test_case(secure_tunneling_send_v1_data_message_with_no_active_connection) +add_net_test_case(secure_tunneling_multiple_stream_start_test) generate_test_driver(${PROJECT_NAME}-tests) diff --git a/tests/secure_tunnel_tests.c b/tests/secure_tunnel_tests.c index 2b4a0f61..d21e8828 100644 --- a/tests/secure_tunnel_tests.c +++ b/tests/secure_tunnel_tests.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -79,6 +80,15 @@ static void s_secure_tunnel_test_init_default_options(struct secure_tunnel_test_ test_options->secure_tunnel_options = local_secure_tunnel_options; } +static void s_secure_tunnel_test_init_default_options_source_mode(struct secure_tunnel_test_options *test_options) { + struct aws_secure_tunnel_options local_secure_tunnel_options = { + .endpoint_host = aws_byte_cursor_from_string(s_endpoint_host), + .access_token = aws_byte_cursor_from_string(s_access_token), + .local_proxy_mode = AWS_SECURE_TUNNELING_SOURCE_MODE, + }; + test_options->secure_tunnel_options = local_secure_tunnel_options; +} + typedef int(aws_secure_tunnel_mock_test_fixture_header_check_fn)( const struct aws_http_headers *request_headers, void *user_data); @@ -722,7 +732,7 @@ void aws_secure_tunnel_mock_test_init( aws_http_library_init(allocator); aws_iotdevice_library_init(allocator); - s_secure_tunnel_test_init_default_options(test_options); + s_secure_tunnel_test_init_default_options_source_mode(test_options); test_options->secure_tunnel_options.client_token = aws_byte_cursor_from_string(s_client_token); @@ -792,6 +802,62 @@ static int s_secure_tunneling_functionality_connect_test_fn(struct aws_allocator AWS_TEST_CASE(secure_tunneling_functionality_connect_test, s_secure_tunneling_functionality_connect_test_fn) +void s_event_loop_thread(void *arg) { + struct aws_secure_tunnel_mock_test_fixture *test_fixture = arg; + + s_wait_for_connected_successfully(test_fixture); + + struct aws_byte_cursor service_1 = aws_byte_cursor_from_string(s_service_id_1); + struct aws_secure_tunnel_message_view data_message = { + .type = AWS_SECURE_TUNNEL_MT_DATA, + .service_id = &service_1, + .stream_id = 1, + }; + + aws_secure_tunnel_send_mock_message(test_fixture, &data_message); +} + +static int s_secure_tunneling_multiple_stream_start_test_fn(struct aws_allocator *allocator, void *ctx) { + (void)ctx; + + struct secure_tunnel_test_options test_options; + struct aws_secure_tunnel_mock_test_fixture test_fixture; + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; + + test_fixture.header_check = secure_tunneling_access_token_check; + + struct aws_thread event_loop_thread; + aws_thread_init(&event_loop_thread, allocator); + struct aws_thread_options thread_options = *aws_default_thread_options(); + thread_options.cpu_id = 0; + ASSERT_SUCCESS(aws_thread_launch(&event_loop_thread, s_event_loop_thread, &test_fixture, &thread_options)); + + ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); + s_wait_for_connected_successfully(&test_fixture); + + /* Create and send a stream start message from the server to the destination client */ + struct aws_byte_cursor service_1 = aws_byte_cursor_from_string(s_service_id_1); + struct aws_secure_tunnel_message_view stream_start_message_view = { + .type = AWS_SECURE_TUNNEL_MT_STREAM_START, + .service_id = &service_1, + .stream_id = 1, + }; + + ASSERT_SUCCESS(aws_secure_tunnel_stream_start(secure_tunnel, &stream_start_message_view)); + + aws_thread_join(&event_loop_thread); + + ASSERT_SUCCESS(aws_secure_tunnel_stop(secure_tunnel)); + s_wait_for_connection_shutdown(&test_fixture); + + aws_secure_tunnel_mock_test_clean_up(&test_fixture); + + return AWS_OP_SUCCESS; +} + +AWS_TEST_CASE(secure_tunneling_multiple_stream_start_test, s_secure_tunneling_multiple_stream_start_test_fn) + int secure_tunneling_client_token_check(const struct aws_http_headers *request_headers, void *user_data) { (void)user_data; struct aws_byte_cursor client_token_cur; From 8bdf6e7317ce678f682da5236b6edb02a88bfcb0 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Tue, 22 Aug 2023 13:57:05 -0700 Subject: [PATCH 22/52] Fix --- source/secure_tunneling.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/secure_tunneling.c b/source/secure_tunneling.c index d5d64eca..4640a5b9 100644 --- a/source/secure_tunneling.c +++ b/source/secure_tunneling.c @@ -2589,7 +2589,7 @@ int aws_secure_tunnel_send_message( secure_tunnel->allocator, secure_tunnel, message_options, AWS_STOT_MESSAGE); if (message_op == NULL) { - goto error; + return aws_last_error(); } /* @@ -2622,7 +2622,6 @@ int aws_secure_tunnel_send_message( destroy_message_op: aws_secure_tunnel_operation_release(&message_op->base); -error: return aws_last_error(); } @@ -2637,7 +2636,8 @@ int aws_secure_tunnel_stream_start( return AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INCORRECT_MODE; } - if (!s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, message_options)) { + if (secure_tunnel->connections->protocol_version != 0 && + !s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, message_options)) { /* * Protocol mismatch results in a full disconnect/reconnect to the Secure Tunnel Service followed by * sending the STREAM START request that caused the mismatch. From 39137aaa095f7445800f7302357124e8d484fe88 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Tue, 22 Aug 2023 13:57:27 -0700 Subject: [PATCH 23/52] Reproducible data race --- tests/secure_tunnel_tests.c | 39 ++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/tests/secure_tunnel_tests.c b/tests/secure_tunnel_tests.c index d21e8828..465dee87 100644 --- a/tests/secure_tunnel_tests.c +++ b/tests/secure_tunnel_tests.c @@ -807,14 +807,13 @@ void s_event_loop_thread(void *arg) { s_wait_for_connected_successfully(test_fixture); - struct aws_byte_cursor service_1 = aws_byte_cursor_from_string(s_service_id_1); - struct aws_secure_tunnel_message_view data_message = { - .type = AWS_SECURE_TUNNEL_MT_DATA, - .service_id = &service_1, - .stream_id = 1, + struct aws_secure_tunnel_message_view session_reset_message = { + .type = AWS_SECURE_TUNNEL_MT_SESSION_RESET, }; + for (int i = 0; i < 10; ++i) { + aws_secure_tunnel_send_mock_message(test_fixture, &session_reset_message); + } - aws_secure_tunnel_send_mock_message(test_fixture, &data_message); } static int s_secure_tunneling_multiple_stream_start_test_fn(struct aws_allocator *allocator, void *ctx) { @@ -827,27 +826,39 @@ static int s_secure_tunneling_multiple_stream_start_test_fn(struct aws_allocator test_fixture.header_check = secure_tunneling_access_token_check; - struct aws_thread event_loop_thread; - aws_thread_init(&event_loop_thread, allocator); - struct aws_thread_options thread_options = *aws_default_thread_options(); - thread_options.cpu_id = 0; - ASSERT_SUCCESS(aws_thread_launch(&event_loop_thread, s_event_loop_thread, &test_fixture, &thread_options)); - ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); s_wait_for_connected_successfully(&test_fixture); - /* Create and send a stream start message from the server to the destination client */ + /* Create and send a stream start message to the server. */ struct aws_byte_cursor service_1 = aws_byte_cursor_from_string(s_service_id_1); struct aws_secure_tunnel_message_view stream_start_message_view = { .type = AWS_SECURE_TUNNEL_MT_STREAM_START, .service_id = &service_1, - .stream_id = 1, + /* .stream_id = 1, */ + .connection_id = 2, }; ASSERT_SUCCESS(aws_secure_tunnel_stream_start(secure_tunnel, &stream_start_message_view)); + /* Currently that's the only way to be sure that we're in a CONNECTED state. */ + aws_thread_current_sleep(1000000000); + + struct aws_thread event_loop_thread; + aws_thread_init(&event_loop_thread, allocator); + struct aws_thread_options thread_options = *aws_default_thread_options(); + thread_options.cpu_id = 0; + ASSERT_SUCCESS(aws_thread_launch(&event_loop_thread, s_event_loop_thread, &test_fixture, &thread_options)); + + aws_thread_current_sleep(2000000000); + /* stream_start_message_view.connection_id = 3; */ + for (int i = 0; i < 20; ++i) { + ASSERT_SUCCESS(aws_secure_tunnel_stream_start(secure_tunnel, &stream_start_message_view)); + } + aws_thread_join(&event_loop_thread); + aws_thread_current_sleep(1000000000); + ASSERT_SUCCESS(aws_secure_tunnel_stop(secure_tunnel)); s_wait_for_connection_shutdown(&test_fixture); From 3eefe569e8b378b68274cb44605090c85f52379a Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Tue, 22 Aug 2023 17:10:30 -0700 Subject: [PATCH 24/52] Working tests --- include/aws/iotdevice/iotdevice.h | 1 + source/iotdevice.c | 3 + source/secure_tunneling.c | 159 ++++++++++++++++----------- source/secure_tunneling_operations.c | 11 +- tests/secure_tunnel_tests.c | 139 +++++++++++++++++------ 5 files changed, 212 insertions(+), 101 deletions(-) diff --git a/include/aws/iotdevice/iotdevice.h b/include/aws/iotdevice/iotdevice.h index 9cee8fa9..48faad90 100644 --- a/include/aws/iotdevice/iotdevice.h +++ b/include/aws/iotdevice/iotdevice.h @@ -46,6 +46,7 @@ enum aws_iotdevice_error { AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DECODE_FAILURE, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_NO_ACTIVE_CONNECTION, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_PROTOCOL_VERSION_MISMATCH, + AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INACTIVE_SERVICE_ID, AWS_ERROR_END_IOTDEVICE_RANGE = AWS_ERROR_ENUM_END_RANGE(AWS_C_IOTDEVICE_PACKAGE_ID), }; diff --git a/source/iotdevice.c b/source/iotdevice.c index 03dd9d6a..558624c0 100644 --- a/source/iotdevice.c +++ b/source/iotdevice.c @@ -99,6 +99,9 @@ static struct aws_error_info s_errors[] = { AWS_DEFINE_ERROR_INFO_IOTDEVICE( AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_PROTOCOL_VERSION_MISMATCH, "DATA message processing failed due to a protocol version mismatch." ), + AWS_DEFINE_ERROR_INFO_IOTDEVICE( + AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INACTIVE_SERVICE_ID, + "Secure Tunnel operation failed due to using inactive service id." ), }; /* clang-format on */ #undef AWS_DEFINE_ERROR_INFO_IOTDEVICE diff --git a/source/secure_tunneling.c b/source/secure_tunneling.c index 4640a5b9..20d96109 100644 --- a/source/secure_tunneling.c +++ b/source/secure_tunneling.c @@ -1799,6 +1799,98 @@ static bool s_aws_secure_tunnel_should_service_operational_state( return now == s_aws_secure_tunnel_compute_operational_state_service_time(secure_tunnel, now); } +/** + * \internal + * Validate an outbound DATA message, set required fields (e.g. stream_id) and send it to the corresponding active + * connection. + * Calls on_send_message_complete callback if an error occurs. + * \endinternal + */ +void s_process_outbound_data_message( + struct aws_secure_tunnel *secure_tunnel, + struct aws_secure_tunnel_operation *current_operation) { + + int error_code = AWS_OP_SUCCESS; + + /* + * If message is being sent from DESTINATION MODE, it might be expected that a V2 or V1 connection has + * established a default connection id of 1. This default connection id must be stripped before sending + * a V1 or V2 message out. + */ + /* FIXME */ + struct aws_secure_tunnel_operation_message *message_op = current_operation->impl; + if (secure_tunnel->config->local_proxy_mode == AWS_SECURE_TUNNELING_DESTINATION_MODE && + secure_tunnel->connections->protocol_version < 3 && current_operation->message_view->connection_id == 1) { + message_op->options_storage.storage_view.connection_id = 0; + } + + if (secure_tunnel->connections->protocol_version == 0) { + error_code = AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_NO_ACTIVE_CONNECTION; + goto error; + } + + /* If a data message attempts to be sent on an unopen stream, discard it. */ + if (!s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, current_operation->message_view)) { + error_code = AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_PROTOCOL_VERSION_MISMATCH; + goto error; + } + + /* An outbound message does not have an assigned stream ID, assign an active stream ID to it. */ + if ((*current_operation->vtable->aws_secure_tunnel_operation_assign_stream_id_fn)( + current_operation, secure_tunnel)) { + error_code = aws_last_error(); + goto error; + } + + if (!s_aws_secure_tunnel_active_stream_check(secure_tunnel, current_operation->message_view)) { + error_code = aws_last_error(); + if (current_operation->message_view->service_id && current_operation->message_view->service_id->len > 0) { + AWS_LOGF_DEBUG( + AWS_LS_IOTDEVICE_SECURE_TUNNELING, + "id=%p: failed to send DATA message with service id '" PRInSTR + "' stream id (%d) and connection id (%d) with error %d(%s)", + (void *)secure_tunnel, + AWS_BYTE_CURSOR_PRI(*current_operation->message_view->service_id), + current_operation->message_view->stream_id, + current_operation->message_view->connection_id, + error_code, + aws_error_debug_str(error_code)); + } else { + AWS_LOGF_DEBUG( + AWS_LS_IOTDEVICE_SECURE_TUNNELING, + "id=%p: failed to send DATA message with stream id (%d) and connection id (%d) " + "with " + "error %d(%s)", + (void *)secure_tunnel, + current_operation->message_view->stream_id, + current_operation->message_view->connection_id, + error_code, + aws_error_debug_str(error_code)); + } + goto error; + } + + /* Send the Data message through the WebSocket */ + if (s_secure_tunneling_send(secure_tunnel, current_operation->message_view)) { + error_code = aws_last_error(); + AWS_LOGF_ERROR( + AWS_LS_IOTDEVICE_SECURE_TUNNELING, + "id=%p: failed to send DATA message with error %d(%s)", + (void *)secure_tunnel, + error_code, + aws_error_debug_str(error_code)); + } + aws_secure_tunnel_message_view_log(current_operation->message_view, AWS_LL_DEBUG); + + return; + +error: + if (error_code && secure_tunnel->config->on_send_message_complete) { + secure_tunnel->config->on_send_message_complete( + AWS_SECURE_TUNNEL_MT_DATA, error_code, secure_tunnel->config->user_data); + } +} + int aws_secure_tunnel_service_operational_state(struct aws_secure_tunnel *secure_tunnel) { const struct aws_secure_tunnel_vtable *vtable = secure_tunnel->vtable; uint64_t now = (*vtable->get_current_time_fn)(); @@ -1851,56 +1943,7 @@ int aws_secure_tunnel_service_operational_state(struct aws_secure_tunnel *secure break; case AWS_STOT_MESSAGE: - /* If a data message attempts to be sent on an unopen stream, discard it. */ - if ((*current_operation->vtable->aws_secure_tunnel_operation_assign_stream_id_fn)( - current_operation, secure_tunnel)) { - error_code = aws_last_error(); - } else { - if (s_aws_secure_tunnel_active_stream_check(secure_tunnel, current_operation->message_view)) { - /* Send the Data message through the WebSocket */ - if (s_secure_tunneling_send(secure_tunnel, current_operation->message_view)) { - error_code = aws_last_error(); - AWS_LOGF_ERROR( - AWS_LS_IOTDEVICE_SECURE_TUNNELING, - "id=%p: failed to send DATA message with error %d(%s)", - (void *)secure_tunnel, - error_code, - aws_error_debug_str(error_code)); - } - aws_secure_tunnel_message_view_log(current_operation->message_view, AWS_LL_DEBUG); - } else { - error_code = aws_last_error(); - if (current_operation->message_view->service_id && - current_operation->message_view->service_id->len > 0) { - AWS_LOGF_DEBUG( - AWS_LS_IOTDEVICE_SECURE_TUNNELING, - "id=%p: failed to send DATA message with service id '" PRInSTR - "' stream id (%d) and connection id (%d) with error %d(%s)", - (void *)secure_tunnel, - AWS_BYTE_CURSOR_PRI(*current_operation->message_view->service_id), - current_operation->message_view->stream_id, - current_operation->message_view->connection_id, - error_code, - aws_error_debug_str(error_code)); - } else { - AWS_LOGF_DEBUG( - AWS_LS_IOTDEVICE_SECURE_TUNNELING, - "id=%p: failed to send DATA message with stream id (%d) and connection id (%d) " - "with " - "error %d(%s)", - (void *)secure_tunnel, - current_operation->message_view->stream_id, - current_operation->message_view->connection_id, - error_code, - aws_error_debug_str(error_code)); - } - } - } - if (error_code && secure_tunnel->config->on_send_message_complete) { - secure_tunnel->config->on_send_message_complete( - AWS_SECURE_TUNNEL_MT_DATA, error_code, secure_tunnel->config->user_data); - } - + s_process_outbound_data_message(secure_tunnel, current_operation); break; case AWS_STOT_STREAM_START: @@ -2592,22 +2635,6 @@ int aws_secure_tunnel_send_message( return aws_last_error(); } - /* - * If message is being sent from DESTINATION MODE, it might be expected that a V2 or V1 connection has established a - * default connection id of 1. This default connection id must be stripped before sending a V1 or V2 message out. - */ - if (secure_tunnel->config->local_proxy_mode == AWS_SECURE_TUNNELING_DESTINATION_MODE && - secure_tunnel->connections->protocol_version < 3 && message_options->connection_id == 1) { - message_op->options_storage.storage_view.connection_id = 0; - } - - if (!s_aws_secure_tunnel_is_data_message_valid_for_connections( - secure_tunnel, &message_op->options_storage.storage_view)) { - AWS_LOGF_WARN( - AWS_LS_IOTDEVICE_SECURE_TUNNELING, "id=%p: Failed to send outbound DATA message", (void *)secure_tunnel); - goto destroy_message_op; - } - AWS_LOGF_DEBUG( AWS_LS_IOTDEVICE_SECURE_TUNNELING, "id=%p: Submitting MESSAGE operation (%p)", diff --git a/source/secure_tunneling_operations.c b/source/secure_tunneling_operations.c index 38f65602..7e194d70 100644 --- a/source/secure_tunneling_operations.c +++ b/source/secure_tunneling_operations.c @@ -361,6 +361,8 @@ static int s_aws_secure_tunnel_operation_message_assign_stream_id( struct aws_secure_tunnel_message_view *message_view = &message_op->options_storage.storage_view; + int error_code = AWS_OP_SUCCESS; + if (message_view->service_id == NULL || message_view->service_id->len == 0) { stream_id = secure_tunnel->connections->stream_id; } else { @@ -372,13 +374,20 @@ static int s_aws_secure_tunnel_operation_message_assign_stream_id( "id=%p: invalid service id '" PRInSTR "' attempted to be assigned a stream id on an outbound message", (void *)message_view, AWS_BYTE_CURSOR_PRI(*message_view->service_id)); + error_code = AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INVALID_SERVICE_ID; goto error; } struct aws_service_id_element *service_id_elem = elem->value; stream_id = service_id_elem->stream_id; + + if (stream_id == INVALID_STREAM_ID) { + error_code = AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INACTIVE_SERVICE_ID; + goto error; + } } if (stream_id == INVALID_STREAM_ID) { + error_code = AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INVALID_STREAM_ID; goto error; } @@ -401,7 +410,7 @@ static int s_aws_secure_tunnel_operation_message_assign_stream_id( aws_secure_tunnel_message_type_to_c_string(message_view->type)); } - return aws_raise_error(AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INVALID_STREAM_ID); + return aws_raise_error(error_code); } /* diff --git a/tests/secure_tunnel_tests.c b/tests/secure_tunnel_tests.c index 465dee87..10e0ebbd 100644 --- a/tests/secure_tunnel_tests.c +++ b/tests/secure_tunnel_tests.c @@ -80,15 +80,6 @@ static void s_secure_tunnel_test_init_default_options(struct secure_tunnel_test_ test_options->secure_tunnel_options = local_secure_tunnel_options; } -static void s_secure_tunnel_test_init_default_options_source_mode(struct secure_tunnel_test_options *test_options) { - struct aws_secure_tunnel_options local_secure_tunnel_options = { - .endpoint_host = aws_byte_cursor_from_string(s_endpoint_host), - .access_token = aws_byte_cursor_from_string(s_access_token), - .local_proxy_mode = AWS_SECURE_TUNNELING_SOURCE_MODE, - }; - test_options->secure_tunnel_options = local_secure_tunnel_options; -} - typedef int(aws_secure_tunnel_mock_test_fixture_header_check_fn)( const struct aws_http_headers *request_headers, void *user_data); @@ -138,6 +129,12 @@ struct aws_secure_tunnel_mock_test_fixture { int secure_tunnel_message_sent_count_target; int secure_tunnel_message_sent_connection_reset_count; int secure_tunnel_message_sent_data_count; + + bool on_send_message_fired; + struct { + enum aws_secure_tunnel_message_type type; + int error_code; + } send_message_callback_result; }; static bool s_secure_tunnel_check_active_stream_id( @@ -251,7 +248,14 @@ static void s_on_test_secure_tunnel_send_message_complete( void *user_data) { (void)type; (void)error_code; - (void)user_data; + struct aws_secure_tunnel_mock_test_fixture *test_fixture = user_data; + + aws_mutex_lock(&test_fixture->lock); + test_fixture->on_send_message_fired = true; + test_fixture->send_message_callback_result.type = type; + test_fixture->send_message_callback_result.error_code = error_code; + aws_condition_variable_notify_all(&test_fixture->signal); + aws_mutex_unlock(&test_fixture->lock); } static void s_on_test_secure_tunnel_on_session_reset(void *user_data) { @@ -505,6 +509,18 @@ static void s_wait_for_n_messages_received(struct aws_secure_tunnel_mock_test_fi aws_mutex_unlock(&test_fixture->lock); } +static bool s_has_secure_tunnel_on_send_message_complete_fired(void *arg) { + struct aws_secure_tunnel_mock_test_fixture *test_fixture = arg; + return test_fixture->on_send_message_fired; +} + +static void s_wait_for_on_send_message_complete_fired(struct aws_secure_tunnel_mock_test_fixture *test_fixture) { + aws_mutex_lock(&test_fixture->lock); + aws_condition_variable_wait_pred( + &test_fixture->signal, &test_fixture->lock, s_has_secure_tunnel_on_send_message_complete_fired, test_fixture); + aws_mutex_unlock(&test_fixture->lock); +} + /***************************************************************************************************************** * WEBSOCKET MOCK FUNCTIONS *****************************************************************************************************************/ @@ -560,8 +576,8 @@ int aws_websocket_client_connect_mock_fn(const struct aws_websocket_client_conne test_fixture->websocket_function_table->on_incoming_frame_complete_fn = options->on_incoming_frame_complete; void *pointer = test_fixture; - struct aws_websocket_on_connection_setup_data websocket_setup = {.error_code = AWS_ERROR_SUCCESS, - .websocket = pointer}; + struct aws_websocket_on_connection_setup_data websocket_setup = { + .error_code = AWS_ERROR_SUCCESS, .websocket = pointer}; (test_fixture->websocket_function_table->on_connection_setup_fn)(&websocket_setup, secure_tunnel); secure_tunnel->websocket = pointer; @@ -732,7 +748,7 @@ void aws_secure_tunnel_mock_test_init( aws_http_library_init(allocator); aws_iotdevice_library_init(allocator); - s_secure_tunnel_test_init_default_options_source_mode(test_options); + s_secure_tunnel_test_init_default_options(test_options); test_options->secure_tunnel_options.client_token = aws_byte_cursor_from_string(s_client_token); @@ -813,7 +829,6 @@ void s_event_loop_thread(void *arg) { for (int i = 0; i < 10; ++i) { aws_secure_tunnel_send_mock_message(test_fixture, &session_reset_message); } - } static int s_secure_tunneling_multiple_stream_start_test_fn(struct aws_allocator *allocator, void *ctx) { @@ -933,8 +948,8 @@ int aws_websocket_client_connect_fail_once_fn(const struct aws_websocket_client_ test_fixture->websocket_function_table->on_incoming_frame_complete_fn = options->on_incoming_frame_complete; void *pointer = test_fixture; - struct aws_websocket_on_connection_setup_data websocket_setup = {.error_code = AWS_ERROR_SUCCESS, - .websocket = pointer}; + struct aws_websocket_on_connection_setup_data websocket_setup = { + .error_code = AWS_ERROR_SUCCESS, .websocket = pointer}; (test_fixture->websocket_function_table->on_connection_setup_fn)(&websocket_setup, secure_tunnel); @@ -2003,10 +2018,11 @@ static int s_secure_tunneling_send_v2_data_message_on_v1_connection_fn(struct aw .payload = &s_payload_cursor_max_size, }; int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); - ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_PROTOCOL_VERSION_MISMATCH); + ASSERT_INT_EQUALS(result, AWS_OP_SUCCESS); + + s_wait_for_on_send_message_complete_fired(&test_fixture); /* Confirm that no messages have gone out from the client */ - aws_thread_current_sleep(aws_timestamp_convert(1, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_NANOS, NULL)); ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 0); /* Ensure that the established stream was not affected by the message */ @@ -2055,12 +2071,19 @@ static int s_secure_tunneling_send_v3_data_message_on_v1_connection_fn(struct aw .payload = &s_payload_cursor_max_size, }; int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); - ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_PROTOCOL_VERSION_MISMATCH); + ASSERT_INT_EQUALS(result, AWS_OP_SUCCESS); + + s_wait_for_on_send_message_complete_fired(&test_fixture); /* Confirm that no messages have gone out from the client */ - aws_thread_current_sleep(aws_timestamp_convert(1, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_NANOS, NULL)); ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 0); + /* Confirm that on_send_message_complete callback was fired */ + ASSERT_INT_EQUALS(test_fixture.send_message_callback_result.type, AWS_SECURE_TUNNEL_MT_DATA); + ASSERT_INT_EQUALS( + test_fixture.send_message_callback_result.error_code, + AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_PROTOCOL_VERSION_MISMATCH); + /* Ensure that the established stream was not affected by the message */ ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, NULL, 1)); @@ -2106,12 +2129,19 @@ static int s_secure_tunneling_send_v1_data_message_on_v2_connection_fn(struct aw .payload = &s_payload_cursor_max_size, }; int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); - ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_PROTOCOL_VERSION_MISMATCH); + ASSERT_INT_EQUALS(result, AWS_OP_SUCCESS); + + s_wait_for_on_send_message_complete_fired(&test_fixture); /* Confirm that no messages have gone out from the client */ - aws_thread_current_sleep(aws_timestamp_convert(1, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_NANOS, NULL)); ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 0); + /* Confirm that on_send_message_complete callback was fired */ + ASSERT_INT_EQUALS(test_fixture.send_message_callback_result.type, AWS_SECURE_TUNNEL_MT_DATA); + ASSERT_INT_EQUALS( + test_fixture.send_message_callback_result.error_code, + AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_PROTOCOL_VERSION_MISMATCH); + /* Ensure that the established stream was not affected by the message */ ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); @@ -2159,12 +2189,19 @@ static int s_secure_tunneling_send_v3_data_message_on_v2_connection_fn(struct aw .payload = &s_payload_cursor_max_size, }; int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); - ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_PROTOCOL_VERSION_MISMATCH); + ASSERT_INT_EQUALS(result, AWS_OP_SUCCESS); + + s_wait_for_on_send_message_complete_fired(&test_fixture); /* Confirm that no messages have gone out from the client */ - aws_thread_current_sleep(aws_timestamp_convert(1, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_NANOS, NULL)); ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 0); + /* Confirm that on_send_message_complete callback was fired */ + ASSERT_INT_EQUALS(test_fixture.send_message_callback_result.type, AWS_SECURE_TUNNEL_MT_DATA); + ASSERT_INT_EQUALS( + test_fixture.send_message_callback_result.error_code, + AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_PROTOCOL_VERSION_MISMATCH); + /* Ensure that the established stream was not affected by the message */ ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); @@ -2211,12 +2248,19 @@ static int s_secure_tunneling_send_v1_data_message_on_v3_connection_fn(struct aw .payload = &s_payload_cursor_max_size, }; int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); - ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_PROTOCOL_VERSION_MISMATCH); + ASSERT_INT_EQUALS(result, AWS_OP_SUCCESS); + + s_wait_for_on_send_message_complete_fired(&test_fixture); /* Confirm that no messages have gone out from the client */ - aws_thread_current_sleep(aws_timestamp_convert(1, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_NANOS, NULL)); ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 0); + /* Confirm that on_send_message_complete callback was fired */ + ASSERT_INT_EQUALS(test_fixture.send_message_callback_result.type, AWS_SECURE_TUNNEL_MT_DATA); + ASSERT_INT_EQUALS( + test_fixture.send_message_callback_result.error_code, + AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_PROTOCOL_VERSION_MISMATCH); + /* Ensure that the established stream was not affected by the message */ ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); @@ -2264,12 +2308,19 @@ static int s_secure_tunneling_send_v2_data_message_on_v3_connection_fn(struct aw .payload = &s_payload_cursor_max_size, }; int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); - ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_PROTOCOL_VERSION_MISMATCH); + ASSERT_INT_EQUALS(result, AWS_OP_SUCCESS); + + s_wait_for_on_send_message_complete_fired(&test_fixture); /* Confirm that no messages have gone out from the client */ - aws_thread_current_sleep(aws_timestamp_convert(1, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_NANOS, NULL)); ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 0); + /* Confirm that on_send_message_complete callback was fired */ + ASSERT_INT_EQUALS(test_fixture.send_message_callback_result.type, AWS_SECURE_TUNNEL_MT_DATA); + ASSERT_INT_EQUALS( + test_fixture.send_message_callback_result.error_code, + AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_PROTOCOL_VERSION_MISMATCH); + /* Ensure that the established stream was not affected by the message */ ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); @@ -2323,12 +2374,18 @@ static int s_secure_tunneling_send_v2_data_message_on_incorrect_v2_connection_fn }; int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); - ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INVALID_SERVICE_ID); + ASSERT_INT_EQUALS(result, AWS_OP_SUCCESS); + + s_wait_for_on_send_message_complete_fired(&test_fixture); /* Confirm that no messages have gone out from the client */ - aws_thread_current_sleep(aws_timestamp_convert(1, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_NANOS, NULL)); ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 0); + /* Confirm that on_send_message_complete callback was fired */ + ASSERT_INT_EQUALS(test_fixture.send_message_callback_result.type, AWS_SECURE_TUNNEL_MT_DATA); + ASSERT_INT_EQUALS( + test_fixture.send_message_callback_result.error_code, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INACTIVE_SERVICE_ID); + /* Ensure that the established stream was not affected by the message */ ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); @@ -2383,12 +2440,19 @@ static int s_secure_tunneling_send_v3_data_message_on_incorrect_v3_connection_fn }; int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); - ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INVALID_CONNECTION_ID); + ASSERT_INT_EQUALS(result, AWS_OP_SUCCESS); + + s_wait_for_on_send_message_complete_fired(&test_fixture); /* Confirm that no messages have gone out from the client */ - aws_thread_current_sleep(aws_timestamp_convert(1, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_NANOS, NULL)); ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 0); + /* Confirm that on_send_message_complete callback was fired */ + ASSERT_INT_EQUALS(test_fixture.send_message_callback_result.type, AWS_SECURE_TUNNEL_MT_DATA); + ASSERT_INT_EQUALS( + test_fixture.send_message_callback_result.error_code, + AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INVALID_CONNECTION_ID); + /* Ensure that the established stream was not affected by the message */ ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); @@ -2427,12 +2491,19 @@ static int s_secure_tunneling_send_v1_data_message_with_no_active_connection_fn( }; int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); - ASSERT_INT_EQUALS(result, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_NO_ACTIVE_CONNECTION); + ASSERT_INT_EQUALS(result, AWS_OP_SUCCESS); + + s_wait_for_on_send_message_complete_fired(&test_fixture); /* Confirm that no messages have gone out from the client */ - aws_thread_current_sleep(aws_timestamp_convert(1, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_NANOS, NULL)); ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 0); + /* Confirm that on_send_message_complete callback was fired */ + ASSERT_INT_EQUALS(test_fixture.send_message_callback_result.type, AWS_SECURE_TUNNEL_MT_DATA); + ASSERT_INT_EQUALS( + test_fixture.send_message_callback_result.error_code, + AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_NO_ACTIVE_CONNECTION); + ASSERT_SUCCESS(aws_secure_tunnel_stop(secure_tunnel)); s_wait_for_connection_shutdown(&test_fixture); From 0618b39bfec14c9965df0dafd4d59176e1be4192 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Tue, 22 Aug 2023 17:13:12 -0700 Subject: [PATCH 25/52] Remove todo --- include/aws/iotdevice/private/secure_tunneling_impl.h | 1 - tests/secure_tunnel_tests.c | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/include/aws/iotdevice/private/secure_tunneling_impl.h b/include/aws/iotdevice/private/secure_tunneling_impl.h index e1f0e4bf..9367d632 100644 --- a/include/aws/iotdevice/private/secure_tunneling_impl.h +++ b/include/aws/iotdevice/private/secure_tunneling_impl.h @@ -158,7 +158,6 @@ struct aws_secure_tunnel_connections { /* Used for streams not using multiplexing (service ids) */ int32_t stream_id; - /* TODO This field should be removed. */ struct aws_hash_table connection_ids; /* Table containing streams using multiplexing (service ids) */ diff --git a/tests/secure_tunnel_tests.c b/tests/secure_tunnel_tests.c index 10e0ebbd..eb0903ee 100644 --- a/tests/secure_tunnel_tests.c +++ b/tests/secure_tunnel_tests.c @@ -576,8 +576,8 @@ int aws_websocket_client_connect_mock_fn(const struct aws_websocket_client_conne test_fixture->websocket_function_table->on_incoming_frame_complete_fn = options->on_incoming_frame_complete; void *pointer = test_fixture; - struct aws_websocket_on_connection_setup_data websocket_setup = { - .error_code = AWS_ERROR_SUCCESS, .websocket = pointer}; + struct aws_websocket_on_connection_setup_data websocket_setup = {.error_code = AWS_ERROR_SUCCESS, + .websocket = pointer}; (test_fixture->websocket_function_table->on_connection_setup_fn)(&websocket_setup, secure_tunnel); secure_tunnel->websocket = pointer; @@ -948,8 +948,8 @@ int aws_websocket_client_connect_fail_once_fn(const struct aws_websocket_client_ test_fixture->websocket_function_table->on_incoming_frame_complete_fn = options->on_incoming_frame_complete; void *pointer = test_fixture; - struct aws_websocket_on_connection_setup_data websocket_setup = { - .error_code = AWS_ERROR_SUCCESS, .websocket = pointer}; + struct aws_websocket_on_connection_setup_data websocket_setup = {.error_code = AWS_ERROR_SUCCESS, + .websocket = pointer}; (test_fixture->websocket_function_table->on_connection_setup_fn)(&websocket_setup, secure_tunnel); From b30e584dee68700314260a9bce8e21bed3d86a92 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Tue, 22 Aug 2023 17:16:22 -0700 Subject: [PATCH 26/52] Remove unused function --- source/secure_tunneling.c | 52 --------------------------------------- 1 file changed, 52 deletions(-) diff --git a/source/secure_tunneling.c b/source/secure_tunneling.c index 20d96109..a2ad81c3 100644 --- a/source/secure_tunneling.c +++ b/source/secure_tunneling.c @@ -300,58 +300,6 @@ static bool s_aws_secure_tunnel_active_stream_check( return true; } -/** - * \internal - * Check if DATA message can be sent to one of active connections. - * \endinternal - */ -static bool s_aws_secure_tunnel_is_data_message_valid_for_connections( - const struct aws_secure_tunnel *secure_tunnel, - const struct aws_secure_tunnel_message_view *message_view) { - - if (secure_tunnel->connections->protocol_version == 0) { - aws_raise_error(AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_NO_ACTIVE_CONNECTION); - return false; - } - - if (!s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, message_view)) { - aws_raise_error(AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_PROTOCOL_VERSION_MISMATCH); - return false; - } - - /* The V1 message will be assigned a stream ID that is currently in use, so it's always valid. */ - if (secure_tunnel->connections->protocol_version == 1) { - return true; - } - - /* The message is at least V2 version, check if the requested service ID is available in the secure tunnel. */ - struct aws_hash_element *elem = NULL; - aws_hash_table_find(&secure_tunnel->connections->service_ids, message_view->service_id, &elem); - if (elem == NULL) { - aws_raise_error(AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INVALID_SERVICE_ID); - return false; - } - - /* Check if the requested service ID is active. */ - struct aws_service_id_element *service_id_elem = elem->value; - if (service_id_elem->stream_id == INVALID_STREAM_ID) { - aws_raise_error(AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INVALID_SERVICE_ID); - return false; - } - - /* The message uses V3 protocol, check connection ID. */ - if (message_view->connection_id != 0) { - struct aws_hash_element *connection_id_elem = NULL; - aws_hash_table_find(&service_id_elem->connection_ids, &message_view->connection_id, &connection_id_elem); - if (connection_id_elem == NULL) { - aws_raise_error(AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INVALID_CONNECTION_ID); - return false; - } - } - - return true; -} - static int s_aws_secure_tunnel_set_stream( struct aws_secure_tunnel *secure_tunnel, const struct aws_byte_cursor *service_id, From e6e79f833529de6934d2599532b096c5f0239a76 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Tue, 22 Aug 2023 17:17:27 -0700 Subject: [PATCH 27/52] Remove todo --- source/secure_tunneling.c | 1 - 1 file changed, 1 deletion(-) diff --git a/source/secure_tunneling.c b/source/secure_tunneling.c index a2ad81c3..bda5368b 100644 --- a/source/secure_tunneling.c +++ b/source/secure_tunneling.c @@ -309,7 +309,6 @@ static int s_aws_secure_tunnel_set_stream( if (service_id == NULL || service_id->len == 0) { secure_tunnel->connections->stream_id = stream_id; aws_hash_table_clear(&secure_tunnel->connections->connection_ids); - /* TODO This case should be treated as error. */ if (connection_id > 0) { struct aws_connection_id_element *connection_id_elem = aws_connection_id_element_new(secure_tunnel->allocator, connection_id); From 1ed9483f8a2a5d9a61b621e71df27fb032a2a0cd Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Tue, 22 Aug 2023 17:20:46 -0700 Subject: [PATCH 28/52] Fix logging format --- source/secure_tunneling.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/source/secure_tunneling.c b/source/secure_tunneling.c index bda5368b..f59b3315 100644 --- a/source/secure_tunneling.c +++ b/source/secure_tunneling.c @@ -1805,9 +1805,7 @@ void s_process_outbound_data_message( } else { AWS_LOGF_DEBUG( AWS_LS_IOTDEVICE_SECURE_TUNNELING, - "id=%p: failed to send DATA message with stream id (%d) and connection id (%d) " - "with " - "error %d(%s)", + "id=%p: failed to send DATA message with stream id (%d) and connection id (%d) with error %d(%s)", (void *)secure_tunnel, current_operation->message_view->stream_id, current_operation->message_view->connection_id, From 388ff13f6178fef3d1f236f13f003f18f1b39f58 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Tue, 22 Aug 2023 17:22:37 -0700 Subject: [PATCH 29/52] Rename goto label --- source/secure_tunneling.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/secure_tunneling.c b/source/secure_tunneling.c index f59b3315..8c3a1238 100644 --- a/source/secure_tunneling.c +++ b/source/secure_tunneling.c @@ -2587,12 +2587,12 @@ int aws_secure_tunnel_send_message( (void *)message_op); if (s_submit_operation(secure_tunnel, &message_op->base)) { - goto destroy_message_op; + goto error; } return AWS_OP_SUCCESS; -destroy_message_op: +error: aws_secure_tunnel_operation_release(&message_op->base); return aws_last_error(); } From 04c463a856d31e9673152023d47a89f5597affb7 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Tue, 22 Aug 2023 17:23:37 -0700 Subject: [PATCH 30/52] Remove unused include --- tests/secure_tunnel_tests.c | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/secure_tunnel_tests.c b/tests/secure_tunnel_tests.c index eb0903ee..0086d8ea 100644 --- a/tests/secure_tunnel_tests.c +++ b/tests/secure_tunnel_tests.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include From 59b863f1685621a986f4793d7ffe02450f885ac1 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Tue, 22 Aug 2023 17:25:25 -0700 Subject: [PATCH 31/52] Remove stream start test --- tests/CMakeLists.txt | 1 - tests/secure_tunnel_tests.c | 53 ------------------------------------- 2 files changed, 54 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 0b696547..d25357de 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -52,7 +52,6 @@ add_net_test_case(secure_tunneling_send_v2_data_message_on_v3_connection) add_net_test_case(secure_tunneling_send_v2_data_message_on_incorrect_v2_connection) add_net_test_case(secure_tunneling_send_v3_data_message_on_incorrect_v3_connection) add_net_test_case(secure_tunneling_send_v1_data_message_with_no_active_connection) -add_net_test_case(secure_tunneling_multiple_stream_start_test) generate_test_driver(${PROJECT_NAME}-tests) diff --git a/tests/secure_tunnel_tests.c b/tests/secure_tunnel_tests.c index 0086d8ea..4b56cd74 100644 --- a/tests/secure_tunnel_tests.c +++ b/tests/secure_tunnel_tests.c @@ -830,59 +830,6 @@ void s_event_loop_thread(void *arg) { } } -static int s_secure_tunneling_multiple_stream_start_test_fn(struct aws_allocator *allocator, void *ctx) { - (void)ctx; - - struct secure_tunnel_test_options test_options; - struct aws_secure_tunnel_mock_test_fixture test_fixture; - aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); - struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; - - test_fixture.header_check = secure_tunneling_access_token_check; - - ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); - s_wait_for_connected_successfully(&test_fixture); - - /* Create and send a stream start message to the server. */ - struct aws_byte_cursor service_1 = aws_byte_cursor_from_string(s_service_id_1); - struct aws_secure_tunnel_message_view stream_start_message_view = { - .type = AWS_SECURE_TUNNEL_MT_STREAM_START, - .service_id = &service_1, - /* .stream_id = 1, */ - .connection_id = 2, - }; - - ASSERT_SUCCESS(aws_secure_tunnel_stream_start(secure_tunnel, &stream_start_message_view)); - - /* Currently that's the only way to be sure that we're in a CONNECTED state. */ - aws_thread_current_sleep(1000000000); - - struct aws_thread event_loop_thread; - aws_thread_init(&event_loop_thread, allocator); - struct aws_thread_options thread_options = *aws_default_thread_options(); - thread_options.cpu_id = 0; - ASSERT_SUCCESS(aws_thread_launch(&event_loop_thread, s_event_loop_thread, &test_fixture, &thread_options)); - - aws_thread_current_sleep(2000000000); - /* stream_start_message_view.connection_id = 3; */ - for (int i = 0; i < 20; ++i) { - ASSERT_SUCCESS(aws_secure_tunnel_stream_start(secure_tunnel, &stream_start_message_view)); - } - - aws_thread_join(&event_loop_thread); - - aws_thread_current_sleep(1000000000); - - ASSERT_SUCCESS(aws_secure_tunnel_stop(secure_tunnel)); - s_wait_for_connection_shutdown(&test_fixture); - - aws_secure_tunnel_mock_test_clean_up(&test_fixture); - - return AWS_OP_SUCCESS; -} - -AWS_TEST_CASE(secure_tunneling_multiple_stream_start_test, s_secure_tunneling_multiple_stream_start_test_fn) - int secure_tunneling_client_token_check(const struct aws_http_headers *request_headers, void *user_data) { (void)user_data; struct aws_byte_cursor client_token_cur; From 662e32e8acfd7b6453210ecff5b06c53792c7f03 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Wed, 23 Aug 2023 14:57:04 -0700 Subject: [PATCH 32/52] Fix tests naming --- tests/CMakeLists.txt | 18 +++++----- tests/secure_tunnel_tests.c | 66 ++++++++++++++++++++++--------------- 2 files changed, 48 insertions(+), 36 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d25357de..5b50c2f7 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -43,15 +43,15 @@ add_net_test_case(secure_tunneling_v1_stream_start_v3_message_reset_test) add_net_test_case(secure_tunneling_v2_stream_start_connection_start_reset_test) add_net_test_case(secure_tunneling_close_stream_on_connection_reset_test) add_net_test_case(secure_tunneling_existing_connection_start_send_reset_test) -add_net_test_case(secure_tunneling_send_v2_data_message_on_v1_connection) -add_net_test_case(secure_tunneling_send_v3_data_message_on_v1_connection) -add_net_test_case(secure_tunneling_send_v1_data_message_on_v2_connection) -add_net_test_case(secure_tunneling_send_v3_data_message_on_v2_connection) -add_net_test_case(secure_tunneling_send_v1_data_message_on_v3_connection) -add_net_test_case(secure_tunneling_send_v2_data_message_on_v3_connection) -add_net_test_case(secure_tunneling_send_v2_data_message_on_incorrect_v2_connection) -add_net_test_case(secure_tunneling_send_v3_data_message_on_incorrect_v3_connection) -add_net_test_case(secure_tunneling_send_v1_data_message_with_no_active_connection) +add_net_test_case(secure_tunneling_send_v2_data_message_on_v1_connection_test) +add_net_test_case(secure_tunneling_send_v3_data_message_on_v1_connection_test) +add_net_test_case(secure_tunneling_send_v1_data_message_on_v2_connection_test) +add_net_test_case(secure_tunneling_send_v3_data_message_on_v2_connection_test) +add_net_test_case(secure_tunneling_send_v1_data_message_on_v3_connection_test) +add_net_test_case(secure_tunneling_send_v2_data_message_on_v3_connection_test) +add_net_test_case(secure_tunneling_send_v2_data_message_on_incorrect_v2_connection_test) +add_net_test_case(secure_tunneling_send_v3_data_message_on_incorrect_v3_connection_test) +add_net_test_case(secure_tunneling_send_v1_data_message_with_no_active_connection_test) generate_test_driver(${PROJECT_NAME}-tests) diff --git a/tests/secure_tunnel_tests.c b/tests/secure_tunnel_tests.c index 4b56cd74..0ca0d0bf 100644 --- a/tests/secure_tunnel_tests.c +++ b/tests/secure_tunnel_tests.c @@ -1934,7 +1934,9 @@ AWS_TEST_CASE( secure_tunneling_existing_connection_start_send_reset_test, s_secure_tunneling_existing_connection_start_send_reset_test_fn) -static int s_secure_tunneling_send_v2_data_message_on_v1_connection_fn(struct aws_allocator *allocator, void *ctx) { +static int s_secure_tunneling_send_v2_data_message_on_v1_connection_test_fn( + struct aws_allocator *allocator, + void *ctx) { (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; @@ -1983,10 +1985,12 @@ static int s_secure_tunneling_send_v2_data_message_on_v1_connection_fn(struct aw } AWS_TEST_CASE( - secure_tunneling_send_v2_data_message_on_v1_connection, - s_secure_tunneling_send_v2_data_message_on_v1_connection_fn) + secure_tunneling_send_v2_data_message_on_v1_connection_test, + s_secure_tunneling_send_v2_data_message_on_v1_connection_test_fn) -static int s_secure_tunneling_send_v3_data_message_on_v1_connection_fn(struct aws_allocator *allocator, void *ctx) { +static int s_secure_tunneling_send_v3_data_message_on_v1_connection_test_fn( + struct aws_allocator *allocator, + void *ctx) { (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; @@ -2042,10 +2046,12 @@ static int s_secure_tunneling_send_v3_data_message_on_v1_connection_fn(struct aw } AWS_TEST_CASE( - secure_tunneling_send_v3_data_message_on_v1_connection, - s_secure_tunneling_send_v3_data_message_on_v1_connection_fn) + secure_tunneling_send_v3_data_message_on_v1_connection_test, + s_secure_tunneling_send_v3_data_message_on_v1_connection_test_fn) -static int s_secure_tunneling_send_v1_data_message_on_v2_connection_fn(struct aws_allocator *allocator, void *ctx) { +static int s_secure_tunneling_send_v1_data_message_on_v2_connection_test_fn( + struct aws_allocator *allocator, + void *ctx) { (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; @@ -2100,10 +2106,12 @@ static int s_secure_tunneling_send_v1_data_message_on_v2_connection_fn(struct aw } AWS_TEST_CASE( - secure_tunneling_send_v1_data_message_on_v2_connection, - s_secure_tunneling_send_v1_data_message_on_v2_connection_fn) + secure_tunneling_send_v1_data_message_on_v2_connection_test, + s_secure_tunneling_send_v1_data_message_on_v2_connection_test_fn) -static int s_secure_tunneling_send_v3_data_message_on_v2_connection_fn(struct aws_allocator *allocator, void *ctx) { +static int s_secure_tunneling_send_v3_data_message_on_v2_connection_test_fn( + struct aws_allocator *allocator, + void *ctx) { (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; @@ -2160,10 +2168,12 @@ static int s_secure_tunneling_send_v3_data_message_on_v2_connection_fn(struct aw } AWS_TEST_CASE( - secure_tunneling_send_v3_data_message_on_v2_connection, - s_secure_tunneling_send_v3_data_message_on_v2_connection_fn) + secure_tunneling_send_v3_data_message_on_v2_connection_test, + s_secure_tunneling_send_v3_data_message_on_v2_connection_test_fn) -static int s_secure_tunneling_send_v1_data_message_on_v3_connection_fn(struct aws_allocator *allocator, void *ctx) { +static int s_secure_tunneling_send_v1_data_message_on_v3_connection_test_fn( + struct aws_allocator *allocator, + void *ctx) { (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; @@ -2219,10 +2229,12 @@ static int s_secure_tunneling_send_v1_data_message_on_v3_connection_fn(struct aw } AWS_TEST_CASE( - secure_tunneling_send_v1_data_message_on_v3_connection, - s_secure_tunneling_send_v1_data_message_on_v3_connection_fn) + secure_tunneling_send_v1_data_message_on_v3_connection_test, + s_secure_tunneling_send_v1_data_message_on_v3_connection_test_fn) -static int s_secure_tunneling_send_v2_data_message_on_v3_connection_fn(struct aws_allocator *allocator, void *ctx) { +static int s_secure_tunneling_send_v2_data_message_on_v3_connection_test_fn( + struct aws_allocator *allocator, + void *ctx) { (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; @@ -2279,10 +2291,10 @@ static int s_secure_tunneling_send_v2_data_message_on_v3_connection_fn(struct aw } AWS_TEST_CASE( - secure_tunneling_send_v2_data_message_on_v3_connection, - s_secure_tunneling_send_v2_data_message_on_v3_connection_fn) + secure_tunneling_send_v2_data_message_on_v3_connection_test, + s_secure_tunneling_send_v2_data_message_on_v3_connection_test_fn) -static int s_secure_tunneling_send_v2_data_message_on_incorrect_v2_connection_fn( +static int s_secure_tunneling_send_v2_data_message_on_incorrect_v2_connection_test_fn( struct aws_allocator *allocator, void *ctx) { @@ -2344,10 +2356,10 @@ static int s_secure_tunneling_send_v2_data_message_on_incorrect_v2_connection_fn } AWS_TEST_CASE( - secure_tunneling_send_v2_data_message_on_incorrect_v2_connection, - s_secure_tunneling_send_v2_data_message_on_incorrect_v2_connection_fn) + secure_tunneling_send_v2_data_message_on_incorrect_v2_connection_test, + s_secure_tunneling_send_v2_data_message_on_incorrect_v2_connection_test_fn) -static int s_secure_tunneling_send_v3_data_message_on_incorrect_v3_connection_fn( +static int s_secure_tunneling_send_v3_data_message_on_incorrect_v3_connection_test_fn( struct aws_allocator *allocator, void *ctx) { @@ -2411,10 +2423,10 @@ static int s_secure_tunneling_send_v3_data_message_on_incorrect_v3_connection_fn } AWS_TEST_CASE( - secure_tunneling_send_v3_data_message_on_incorrect_v3_connection, - s_secure_tunneling_send_v3_data_message_on_incorrect_v3_connection_fn) + secure_tunneling_send_v3_data_message_on_incorrect_v3_connection_test, + s_secure_tunneling_send_v3_data_message_on_incorrect_v3_connection_test_fn) -static int s_secure_tunneling_send_v1_data_message_with_no_active_connection_fn( +static int s_secure_tunneling_send_v1_data_message_with_no_active_connection_test_fn( struct aws_allocator *allocator, void *ctx) { @@ -2459,5 +2471,5 @@ static int s_secure_tunneling_send_v1_data_message_with_no_active_connection_fn( } AWS_TEST_CASE( - secure_tunneling_send_v1_data_message_with_no_active_connection, - s_secure_tunneling_send_v1_data_message_with_no_active_connection_fn) + secure_tunneling_send_v1_data_message_with_no_active_connection_test, + s_secure_tunneling_send_v1_data_message_with_no_active_connection_test_fn) From fb2c9f5da926a9c6fce4b8fc2ce6ed8793d80992 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Wed, 23 Aug 2023 15:25:48 -0700 Subject: [PATCH 33/52] Receive messages from mocked server in the event loop --- tests/secure_tunnel_tests.c | 80 +++++++++++++++++++++++++++---------- 1 file changed, 58 insertions(+), 22 deletions(-) diff --git a/tests/secure_tunnel_tests.c b/tests/secure_tunnel_tests.c index 0ca0d0bf..bdf812d3 100644 --- a/tests/secure_tunnel_tests.c +++ b/tests/secure_tunnel_tests.c @@ -524,32 +524,68 @@ static void s_wait_for_on_send_message_complete_fired(struct aws_secure_tunnel_m * WEBSOCKET MOCK FUNCTIONS *****************************************************************************************************************/ -/* Serializes message view and sends as Websocket */ +/* Task that simulates a WebSocket payload receiving. */ +struct aws_secure_tunnel_mock_websocket_receive_frame_payload_task { + struct aws_task task; + struct aws_secure_tunnel_mock_test_fixture *test_fixture; + struct aws_byte_buf data_buf; + struct aws_byte_buf out_buf; +}; + +static void s_secure_tunneling_mock_websocket_receive_frame_payload_task_fn( + struct aws_task *task, + void *arg, + enum aws_task_status status) { + + (void)task; + + struct aws_secure_tunnel_mock_websocket_receive_frame_payload_task *receive_task = arg; + if (status != AWS_TASK_STATUS_RUN_READY) { + return; + } + + struct aws_byte_cursor data_cur = aws_byte_cursor_from_buf(&receive_task->out_buf); + receive_task->test_fixture->websocket_function_table->on_incoming_frame_payload_fn( + NULL, NULL, data_cur, receive_task->test_fixture->secure_tunnel); + + aws_byte_buf_clean_up(&receive_task->out_buf); + aws_byte_buf_clean_up(&receive_task->data_buf); + aws_mem_release(receive_task->test_fixture->allocator, receive_task); +} + +/* Serialize a message view and initialize a task for the event loop. The task then will simulate receiving the + * WebSocket data. + * NOTE In the actual environment, WebSocket operations and the secure tunnel are assigned to the same loop. We can + * reproduce this by "receiving" messages from the mocked WebSocket in the same event loop the secure tunnel uses. This + * way we don't need to worry about race conditions appearing in the tests that are not possible during the actual + * execution. + */ void aws_secure_tunnel_send_mock_message( struct aws_secure_tunnel_mock_test_fixture *test_fixture, const struct aws_secure_tunnel_message_view *message_view) { - /* The actual WebSocket is assigned the same event loop as the secure tunnel but the mock websocket for tests - * requires a short sleep to insure there aren't race conditions related to the incoming websocket data being - * processed. */ - aws_thread_current_sleep(aws_timestamp_convert(350, AWS_TIMESTAMP_MILLIS, AWS_TIMESTAMP_NANOS, NULL)); - struct aws_byte_buf data_buf; + + struct aws_secure_tunnel_mock_websocket_receive_frame_payload_task *receive_task = aws_mem_calloc( + test_fixture->secure_tunnel->allocator, + 1, + sizeof(struct aws_secure_tunnel_mock_websocket_receive_frame_payload_task)); + + aws_task_init( + &receive_task->task, + s_secure_tunneling_mock_websocket_receive_frame_payload_task_fn, + (void *)receive_task, + "MockWebsocketSendMessage"); + + receive_task->test_fixture = test_fixture; + struct aws_byte_cursor data_cur; - struct aws_byte_buf out_buf; - aws_iot_st_msg_serialize_from_view(&data_buf, test_fixture->allocator, message_view); - data_cur = aws_byte_cursor_from_buf(&data_buf); - aws_byte_buf_init(&out_buf, test_fixture->allocator, data_cur.len + PAYLOAD_BYTE_LENGTH_PREFIX); - aws_byte_buf_write_be16(&out_buf, (int16_t)data_buf.len); - aws_byte_buf_write_to_capacity(&out_buf, &data_cur); - data_cur = aws_byte_cursor_from_buf(&out_buf); - test_fixture->websocket_function_table->on_incoming_frame_payload_fn( - NULL, NULL, data_cur, test_fixture->secure_tunnel); - - aws_byte_buf_clean_up(&out_buf); - aws_byte_buf_clean_up(&data_buf); - /* The actual WebSocket is assigned the same event loop as the secure tunnel but the mock websocket for tests - * requires a short sleep to insure there aren't race conditions related to the incoming websocket data being - * processed. */ - aws_thread_current_sleep(aws_timestamp_convert(350, AWS_TIMESTAMP_MILLIS, AWS_TIMESTAMP_NANOS, NULL)); + + aws_iot_st_msg_serialize_from_view(&receive_task->data_buf, test_fixture->allocator, message_view); + data_cur = aws_byte_cursor_from_buf(&receive_task->data_buf); + aws_byte_buf_init(&receive_task->out_buf, test_fixture->allocator, data_cur.len + PAYLOAD_BYTE_LENGTH_PREFIX); + aws_byte_buf_write_be16(&receive_task->out_buf, (uint16_t)receive_task->data_buf.len); + aws_byte_buf_write_to_capacity(&receive_task->out_buf, &data_cur); + + aws_event_loop_schedule_task_now(test_fixture->secure_tunnel->loop, &receive_task->task); } int aws_websocket_client_connect_mock_fn(const struct aws_websocket_client_connection_options *options) { From 7757a8ebff52bb5298df99ca78397ec262de4bc7 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Wed, 23 Aug 2023 15:34:34 -0700 Subject: [PATCH 34/52] Add missing static --- source/secure_tunneling.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/secure_tunneling.c b/source/secure_tunneling.c index 8c3a1238..1fedf68f 100644 --- a/source/secure_tunneling.c +++ b/source/secure_tunneling.c @@ -1753,7 +1753,7 @@ static bool s_aws_secure_tunnel_should_service_operational_state( * Calls on_send_message_complete callback if an error occurs. * \endinternal */ -void s_process_outbound_data_message( +static void s_process_outbound_data_message( struct aws_secure_tunnel *secure_tunnel, struct aws_secure_tunnel_operation *current_operation) { From fc70e8273514fc2da5bac9f5ac921a13a468f07e Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Wed, 23 Aug 2023 15:34:53 -0700 Subject: [PATCH 35/52] Fix naming --- tests/secure_tunnel_tests.c | 45 +++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/tests/secure_tunnel_tests.c b/tests/secure_tunnel_tests.c index bdf812d3..dbeb057d 100644 --- a/tests/secure_tunnel_tests.c +++ b/tests/secure_tunnel_tests.c @@ -129,11 +129,11 @@ struct aws_secure_tunnel_mock_test_fixture { int secure_tunnel_message_sent_connection_reset_count; int secure_tunnel_message_sent_data_count; - bool on_send_message_fired; + bool on_send_message_complete_fired; struct { enum aws_secure_tunnel_message_type type; int error_code; - } send_message_callback_result; + } on_send_message_complete_result; }; static bool s_secure_tunnel_check_active_stream_id( @@ -250,9 +250,9 @@ static void s_on_test_secure_tunnel_send_message_complete( struct aws_secure_tunnel_mock_test_fixture *test_fixture = user_data; aws_mutex_lock(&test_fixture->lock); - test_fixture->on_send_message_fired = true; - test_fixture->send_message_callback_result.type = type; - test_fixture->send_message_callback_result.error_code = error_code; + test_fixture->on_send_message_complete_fired = true; + test_fixture->on_send_message_complete_result.type = type; + test_fixture->on_send_message_complete_result.error_code = error_code; aws_condition_variable_notify_all(&test_fixture->signal); aws_mutex_unlock(&test_fixture->lock); } @@ -510,7 +510,7 @@ static void s_wait_for_n_messages_received(struct aws_secure_tunnel_mock_test_fi static bool s_has_secure_tunnel_on_send_message_complete_fired(void *arg) { struct aws_secure_tunnel_mock_test_fixture *test_fixture = arg; - return test_fixture->on_send_message_fired; + return test_fixture->on_send_message_complete_fired; } static void s_wait_for_on_send_message_complete_fired(struct aws_secure_tunnel_mock_test_fixture *test_fixture) { @@ -2065,9 +2065,9 @@ static int s_secure_tunneling_send_v3_data_message_on_v1_connection_test_fn( ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 0); /* Confirm that on_send_message_complete callback was fired */ - ASSERT_INT_EQUALS(test_fixture.send_message_callback_result.type, AWS_SECURE_TUNNEL_MT_DATA); + ASSERT_INT_EQUALS(test_fixture.on_send_message_complete_result.type, AWS_SECURE_TUNNEL_MT_DATA); ASSERT_INT_EQUALS( - test_fixture.send_message_callback_result.error_code, + test_fixture.on_send_message_complete_result.error_code, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_PROTOCOL_VERSION_MISMATCH); /* Ensure that the established stream was not affected by the message */ @@ -2125,9 +2125,9 @@ static int s_secure_tunneling_send_v1_data_message_on_v2_connection_test_fn( ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 0); /* Confirm that on_send_message_complete callback was fired */ - ASSERT_INT_EQUALS(test_fixture.send_message_callback_result.type, AWS_SECURE_TUNNEL_MT_DATA); + ASSERT_INT_EQUALS(test_fixture.on_send_message_complete_result.type, AWS_SECURE_TUNNEL_MT_DATA); ASSERT_INT_EQUALS( - test_fixture.send_message_callback_result.error_code, + test_fixture.on_send_message_complete_result.error_code, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_PROTOCOL_VERSION_MISMATCH); /* Ensure that the established stream was not affected by the message */ @@ -2187,9 +2187,9 @@ static int s_secure_tunneling_send_v3_data_message_on_v2_connection_test_fn( ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 0); /* Confirm that on_send_message_complete callback was fired */ - ASSERT_INT_EQUALS(test_fixture.send_message_callback_result.type, AWS_SECURE_TUNNEL_MT_DATA); + ASSERT_INT_EQUALS(test_fixture.on_send_message_complete_result.type, AWS_SECURE_TUNNEL_MT_DATA); ASSERT_INT_EQUALS( - test_fixture.send_message_callback_result.error_code, + test_fixture.on_send_message_complete_result.error_code, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_PROTOCOL_VERSION_MISMATCH); /* Ensure that the established stream was not affected by the message */ @@ -2248,9 +2248,9 @@ static int s_secure_tunneling_send_v1_data_message_on_v3_connection_test_fn( ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 0); /* Confirm that on_send_message_complete callback was fired */ - ASSERT_INT_EQUALS(test_fixture.send_message_callback_result.type, AWS_SECURE_TUNNEL_MT_DATA); + ASSERT_INT_EQUALS(test_fixture.on_send_message_complete_result.type, AWS_SECURE_TUNNEL_MT_DATA); ASSERT_INT_EQUALS( - test_fixture.send_message_callback_result.error_code, + test_fixture.on_send_message_complete_result.error_code, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_PROTOCOL_VERSION_MISMATCH); /* Ensure that the established stream was not affected by the message */ @@ -2310,9 +2310,9 @@ static int s_secure_tunneling_send_v2_data_message_on_v3_connection_test_fn( ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 0); /* Confirm that on_send_message_complete callback was fired */ - ASSERT_INT_EQUALS(test_fixture.send_message_callback_result.type, AWS_SECURE_TUNNEL_MT_DATA); + ASSERT_INT_EQUALS(test_fixture.on_send_message_complete_result.type, AWS_SECURE_TUNNEL_MT_DATA); ASSERT_INT_EQUALS( - test_fixture.send_message_callback_result.error_code, + test_fixture.on_send_message_complete_result.error_code, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_PROTOCOL_VERSION_MISMATCH); /* Ensure that the established stream was not affected by the message */ @@ -2376,9 +2376,10 @@ static int s_secure_tunneling_send_v2_data_message_on_incorrect_v2_connection_te ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 0); /* Confirm that on_send_message_complete callback was fired */ - ASSERT_INT_EQUALS(test_fixture.send_message_callback_result.type, AWS_SECURE_TUNNEL_MT_DATA); + ASSERT_INT_EQUALS(test_fixture.on_send_message_complete_result.type, AWS_SECURE_TUNNEL_MT_DATA); ASSERT_INT_EQUALS( - test_fixture.send_message_callback_result.error_code, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INACTIVE_SERVICE_ID); + test_fixture.on_send_message_complete_result.error_code, + AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INACTIVE_SERVICE_ID); /* Ensure that the established stream was not affected by the message */ ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); @@ -2442,9 +2443,9 @@ static int s_secure_tunneling_send_v3_data_message_on_incorrect_v3_connection_te ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 0); /* Confirm that on_send_message_complete callback was fired */ - ASSERT_INT_EQUALS(test_fixture.send_message_callback_result.type, AWS_SECURE_TUNNEL_MT_DATA); + ASSERT_INT_EQUALS(test_fixture.on_send_message_complete_result.type, AWS_SECURE_TUNNEL_MT_DATA); ASSERT_INT_EQUALS( - test_fixture.send_message_callback_result.error_code, + test_fixture.on_send_message_complete_result.error_code, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INVALID_CONNECTION_ID); /* Ensure that the established stream was not affected by the message */ @@ -2493,9 +2494,9 @@ static int s_secure_tunneling_send_v1_data_message_with_no_active_connection_tes ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 0); /* Confirm that on_send_message_complete callback was fired */ - ASSERT_INT_EQUALS(test_fixture.send_message_callback_result.type, AWS_SECURE_TUNNEL_MT_DATA); + ASSERT_INT_EQUALS(test_fixture.on_send_message_complete_result.type, AWS_SECURE_TUNNEL_MT_DATA); ASSERT_INT_EQUALS( - test_fixture.send_message_callback_result.error_code, + test_fixture.on_send_message_complete_result.error_code, AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_NO_ACTIVE_CONNECTION); ASSERT_SUCCESS(aws_secure_tunnel_stop(secure_tunnel)); From 3cdf140a819807d6ba89ef8a3a185ced43470e09 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Wed, 23 Aug 2023 15:36:17 -0700 Subject: [PATCH 36/52] Remove unnecessary unused-casts --- tests/secure_tunnel_tests.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/secure_tunnel_tests.c b/tests/secure_tunnel_tests.c index dbeb057d..b2ae628f 100644 --- a/tests/secure_tunnel_tests.c +++ b/tests/secure_tunnel_tests.c @@ -245,8 +245,6 @@ static void s_on_test_secure_tunnel_send_message_complete( enum aws_secure_tunnel_message_type type, int error_code, void *user_data) { - (void)type; - (void)error_code; struct aws_secure_tunnel_mock_test_fixture *test_fixture = user_data; aws_mutex_lock(&test_fixture->lock); From dbbdbf2b8f19333f7e82a9f8ed5ec0f49a4a1059 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Wed, 23 Aug 2023 15:40:16 -0700 Subject: [PATCH 37/52] Remove unused function --- tests/secure_tunnel_tests.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/tests/secure_tunnel_tests.c b/tests/secure_tunnel_tests.c index b2ae628f..594e2ec4 100644 --- a/tests/secure_tunnel_tests.c +++ b/tests/secure_tunnel_tests.c @@ -851,19 +851,6 @@ static int s_secure_tunneling_functionality_connect_test_fn(struct aws_allocator AWS_TEST_CASE(secure_tunneling_functionality_connect_test, s_secure_tunneling_functionality_connect_test_fn) -void s_event_loop_thread(void *arg) { - struct aws_secure_tunnel_mock_test_fixture *test_fixture = arg; - - s_wait_for_connected_successfully(test_fixture); - - struct aws_secure_tunnel_message_view session_reset_message = { - .type = AWS_SECURE_TUNNEL_MT_SESSION_RESET, - }; - for (int i = 0; i < 10; ++i) { - aws_secure_tunnel_send_mock_message(test_fixture, &session_reset_message); - } -} - int secure_tunneling_client_token_check(const struct aws_http_headers *request_headers, void *user_data) { (void)user_data; struct aws_byte_cursor client_token_cur; From 5eea78952d1ccf829c2927c3b8729a145500ce2a Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Wed, 23 Aug 2023 21:26:10 -0700 Subject: [PATCH 38/52] Use vtable for fixing connection id in outbound message --- .../private/secure_tunneling_operations.h | 5 +++++ source/secure_tunneling.c | 19 ++++++----------- source/secure_tunneling_operations.c | 21 +++++++++++++++++++ 3 files changed, 32 insertions(+), 13 deletions(-) diff --git a/include/aws/iotdevice/private/secure_tunneling_operations.h b/include/aws/iotdevice/private/secure_tunneling_operations.h index 37c17d29..0cb242a0 100644 --- a/include/aws/iotdevice/private/secure_tunneling_operations.h +++ b/include/aws/iotdevice/private/secure_tunneling_operations.h @@ -62,6 +62,11 @@ struct aws_secure_tunnel_operation_vtable { int (*aws_secure_tunnel_operation_set_connection_start_id)( struct aws_secure_tunnel_operation *operation, struct aws_secure_tunnel *secure_tunnel); + + /* Perform actions on outbound message before sending it */ + void (*aws_secure_tunnel_operation_prepare_message_for_send_fn)( + struct aws_secure_tunnel_operation *operation, + struct aws_secure_tunnel *secure_tunnel); }; /** diff --git a/source/secure_tunneling.c b/source/secure_tunneling.c index 1fedf68f..318ca381 100644 --- a/source/secure_tunneling.c +++ b/source/secure_tunneling.c @@ -1759,24 +1759,16 @@ static void s_process_outbound_data_message( int error_code = AWS_OP_SUCCESS; - /* - * If message is being sent from DESTINATION MODE, it might be expected that a V2 or V1 connection has - * established a default connection id of 1. This default connection id must be stripped before sending - * a V1 or V2 message out. - */ - /* FIXME */ - struct aws_secure_tunnel_operation_message *message_op = current_operation->impl; - if (secure_tunnel->config->local_proxy_mode == AWS_SECURE_TUNNELING_DESTINATION_MODE && - secure_tunnel->connections->protocol_version < 3 && current_operation->message_view->connection_id == 1) { - message_op->options_storage.storage_view.connection_id = 0; - } - if (secure_tunnel->connections->protocol_version == 0) { error_code = AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_NO_ACTIVE_CONNECTION; goto error; } - /* If a data message attempts to be sent on an unopen stream, discard it. */ + (*current_operation->vtable->aws_secure_tunnel_operation_prepare_message_for_send_fn)( + current_operation, secure_tunnel); + + /* If the data message's protocol version doesn't match the version of the current session, the message should + * be ignored. */ if (!s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, current_operation->message_view)) { error_code = AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_PROTOCOL_VERSION_MISMATCH; goto error; @@ -1789,6 +1781,7 @@ static void s_process_outbound_data_message( goto error; } + /* If a data message attempts to be sent on an unopen stream, discard it. */ if (!s_aws_secure_tunnel_active_stream_check(secure_tunnel, current_operation->message_view)) { error_code = aws_last_error(); if (current_operation->message_view->service_id && current_operation->message_view->service_id->len > 0) { diff --git a/source/secure_tunneling_operations.c b/source/secure_tunneling_operations.c index 7e194d70..a727c081 100644 --- a/source/secure_tunneling_operations.c +++ b/source/secure_tunneling_operations.c @@ -142,6 +142,7 @@ static struct aws_secure_tunnel_operation_vtable s_empty_operation_vtable = { .aws_secure_tunnel_operation_assign_stream_id_fn = NULL, .aws_secure_tunnel_operation_set_next_stream_id_fn = NULL, .aws_secure_tunnel_operation_set_connection_start_id = NULL, + .aws_secure_tunnel_operation_prepare_message_for_send_fn = NULL, }; /********************************************************************************************************************* @@ -570,10 +571,30 @@ static int s_aws_secure_tunnel_operation_set_connection_start_id( return AWS_OP_SUCCESS; } +static void s_aws_secure_tunnel_operation_prepare_message_for_send_fn( + struct aws_secure_tunnel_operation *operation, + struct aws_secure_tunnel *secure_tunnel) { + + struct aws_secure_tunnel_operation_message *message_op = operation->impl; + struct aws_secure_tunnel_message_view *message_view = &message_op->options_storage.storage_view; + + /* + * If message is being sent from DESTINATION MODE, it might be expected that a V2 or V1 connection has + * established a default connection id of 1. This default connection id must be stripped before sending + * a V1 or V2 message out. + */ + if (secure_tunnel->config->local_proxy_mode == AWS_SECURE_TUNNELING_DESTINATION_MODE && + secure_tunnel->connections->protocol_version < 3 && message_view->connection_id == 1) { + message_op->options_storage.storage_view.connection_id = 0; + } +} + static struct aws_secure_tunnel_operation_vtable s_message_operation_vtable = { .aws_secure_tunnel_operation_assign_stream_id_fn = s_aws_secure_tunnel_operation_message_assign_stream_id, .aws_secure_tunnel_operation_set_next_stream_id_fn = s_aws_secure_tunnel_operation_message_set_next_stream_id, .aws_secure_tunnel_operation_set_connection_start_id = s_aws_secure_tunnel_operation_set_connection_start_id, + .aws_secure_tunnel_operation_prepare_message_for_send_fn = + s_aws_secure_tunnel_operation_prepare_message_for_send_fn, }; static void s_destroy_operation_message(void *object) { From 1c1d97e8214cc74b9f79b49d801a138eed5b12c1 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Wed, 23 Aug 2023 21:58:36 -0700 Subject: [PATCH 39/52] Add doxygen comments --- include/aws/iotdevice/secure_tunneling.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/include/aws/iotdevice/secure_tunneling.h b/include/aws/iotdevice/secure_tunneling.h index 9729f428..10611ec8 100644 --- a/include/aws/iotdevice/secure_tunneling.h +++ b/include/aws/iotdevice/secure_tunneling.h @@ -318,11 +318,25 @@ const char *aws_secure_tunnel_message_type_to_c_string(enum aws_secure_tunnel_me //*********************************************************************************************************************** /* THIS API SHOULD ONLY BE USED FROM SOURCE MODE */ //*********************************************************************************************************************** +/** + * Queue a STREAM_START message in a secure tunnel + * @note This function should only be used from source mode. + * @param secure_tunnel secure tunnel to queue a message for + * @param message_options configuration options for the message operation + * @return success/failure in the synchronous logic that kicks off the message operation + */ AWS_IOTDEVICE_API int aws_secure_tunnel_stream_start( struct aws_secure_tunnel *secure_tunnel, const struct aws_secure_tunnel_message_view *message_options); +/** + * Queue a CONNECTION_START message in a secure tunnel + * @note This function should only be used from source mode. + * @param secure_tunnel secure tunnel to queue a message for + * @param message_options configuration options for the message operation + * @return success/failure in the synchronous logic that kicks off the message operation + */ AWS_IOTDEVICE_API int aws_secure_tunnel_connection_start( struct aws_secure_tunnel *secure_tunnel, @@ -331,6 +345,13 @@ int aws_secure_tunnel_connection_start( //*********************************************************************************************************************** /* THIS API SHOULD NOT BE USED BY THE CUSTOMER AND IS DEPRECATED */ //*********************************************************************************************************************** +/** + * Queue a STREAM_RESET message in a secure tunnel + * @deprecated This function should not be used. + * @param secure_tunnel secure tunnel to queue a message for + * @param message_options configuration options for the message operation + * @return success/failure in the synchronous logic that kicks off the message operation + */ AWS_IOTDEVICE_API int aws_secure_tunnel_stream_reset( struct aws_secure_tunnel *secure_tunnel, From 5a92cd91c5f96d0ea79f5d3c139785defaaf69df Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Wed, 23 Aug 2023 22:15:08 -0700 Subject: [PATCH 40/52] Move STREAM_START validation to event loop --- source/secure_tunneling.c | 50 +++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/source/secure_tunneling.c b/source/secure_tunneling.c index 318ca381..4da856b2 100644 --- a/source/secure_tunneling.c +++ b/source/secure_tunneling.c @@ -1885,6 +1885,33 @@ int aws_secure_tunnel_service_operational_state(struct aws_secure_tunnel *secure break; case AWS_STOT_STREAM_START: + /* TODO Extract into function */ + if (secure_tunnel->connections->protocol_version != 0 && + !s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, current_operation->message_view)) { + /* + * Protocol mismatch results in a full disconnect/reconnect to the Secure Tunnel Service followed by + * sending the STREAM START request that caused the mismatch. + */ + AWS_LOGF_INFO( + AWS_LS_IOTDEVICE_SECURE_TUNNELING, + "id=%p: Secure Tunnel will be reset due to Protocol Version mismatch between previously " + "established " + "Protocol Version and Protocol Version used by outbound STREAM START message.", + (void *)secure_tunnel); + reset_secure_tunnel_connection(secure_tunnel); + aws_secure_tunnel_stream_start(secure_tunnel, current_operation->message_view); + break; + } + + if (secure_tunnel->connections->protocol_version == 0) { + secure_tunnel->connections->protocol_version = + s_aws_secure_tunnel_message_min_protocol_check(current_operation->message_view); + AWS_LOGF_INFO( + AWS_LS_IOTDEVICE_SECURE_TUNNELING, + "id=%p: Secure tunnel client Protocol set to V%d based on outbound STREAM START", + (void *)secure_tunnel, + (int)secure_tunnel->connections->protocol_version); + } if ((*current_operation->vtable->aws_secure_tunnel_operation_set_next_stream_id_fn)( current_operation, secure_tunnel)) { error_code = aws_last_error(); @@ -2601,29 +2628,6 @@ int aws_secure_tunnel_stream_start( return AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INCORRECT_MODE; } - if (secure_tunnel->connections->protocol_version != 0 && - !s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, message_options)) { - /* - * Protocol mismatch results in a full disconnect/reconnect to the Secure Tunnel Service followed by - * sending the STREAM START request that caused the mismatch. - */ - AWS_LOGF_INFO( - AWS_LS_IOTDEVICE_SECURE_TUNNELING, - "id=%p: Secure Tunnel will be reset due to Protocol Version mismatch between previously established " - "Protocol Version and Protocol Version used by outbound STREAM START message.", - (void *)secure_tunnel); - reset_secure_tunnel_connection(secure_tunnel); - } - - if (secure_tunnel->connections->protocol_version == 0) { - secure_tunnel->connections->protocol_version = s_aws_secure_tunnel_message_min_protocol_check(message_options); - AWS_LOGF_INFO( - AWS_LS_IOTDEVICE_SECURE_TUNNELING, - "id=%p: Secure tunnel client Protocol set to V%d based on outbound STREAM START", - (void *)secure_tunnel, - (int)secure_tunnel->connections->protocol_version); - } - struct aws_secure_tunnel_operation_message *message_op = aws_secure_tunnel_operation_message_new( secure_tunnel->allocator, secure_tunnel, message_options, AWS_STOT_STREAM_START); From 1e7af768947256f9a33c60652be8ffc2ce18fb90 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Thu, 24 Aug 2023 09:27:33 -0700 Subject: [PATCH 41/52] Add test for STREM_START in SOURCE mode --- tests/CMakeLists.txt | 1 + tests/secure_tunnel_tests.c | 136 ++++++++++++++++++++++++++---------- 2 files changed, 101 insertions(+), 36 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 5b50c2f7..e0215d58 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -52,6 +52,7 @@ add_net_test_case(secure_tunneling_send_v2_data_message_on_v3_connection_test) add_net_test_case(secure_tunneling_send_v2_data_message_on_incorrect_v2_connection_test) add_net_test_case(secure_tunneling_send_v3_data_message_on_incorrect_v3_connection_test) add_net_test_case(secure_tunneling_send_v1_data_message_with_no_active_connection_test) +add_net_test_case(secure_tunneling_send_v3_stream_start_message_test) generate_test_driver(${PROJECT_NAME}-tests) diff --git a/tests/secure_tunnel_tests.c b/tests/secure_tunnel_tests.c index 594e2ec4..90b66251 100644 --- a/tests/secure_tunnel_tests.c +++ b/tests/secure_tunnel_tests.c @@ -70,11 +70,13 @@ struct secure_tunnel_test_options { struct aws_secure_tunnel_mock_websocket_vtable websocket_function_table; }; -static void s_secure_tunnel_test_init_default_options(struct secure_tunnel_test_options *test_options) { +static void s_secure_tunnel_test_init_default_options( + struct secure_tunnel_test_options *test_options, + enum aws_secure_tunneling_local_proxy_mode local_proxy_mode) { struct aws_secure_tunnel_options local_secure_tunnel_options = { .endpoint_host = aws_byte_cursor_from_string(s_endpoint_host), .access_token = aws_byte_cursor_from_string(s_access_token), - .local_proxy_mode = AWS_SECURE_TUNNELING_DESTINATION_MODE, + .local_proxy_mode = local_proxy_mode, }; test_options->secure_tunnel_options = local_secure_tunnel_options; } @@ -776,12 +778,13 @@ int aws_secure_tunnel_mock_test_fixture_init( void aws_secure_tunnel_mock_test_init( struct aws_allocator *allocator, struct secure_tunnel_test_options *test_options, - struct aws_secure_tunnel_mock_test_fixture *test_fixture) { + struct aws_secure_tunnel_mock_test_fixture *test_fixture, + enum aws_secure_tunneling_local_proxy_mode local_proxy_mode) { aws_http_library_init(allocator); aws_iotdevice_library_init(allocator); - s_secure_tunnel_test_init_default_options(test_options); + s_secure_tunnel_test_init_default_options(test_options, local_proxy_mode); test_options->secure_tunnel_options.client_token = aws_byte_cursor_from_string(s_client_token); @@ -833,7 +836,7 @@ static int s_secure_tunneling_functionality_connect_test_fn(struct aws_allocator struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; - aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture, AWS_SECURE_TUNNELING_DESTINATION_MODE); struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; test_fixture.header_check = secure_tunneling_access_token_check; @@ -868,7 +871,7 @@ static int s_secure_tunneling_functionality_client_token_test_fn(struct aws_allo (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; - aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture, AWS_SECURE_TUNNELING_DESTINATION_MODE); struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; test_fixture.header_check = secure_tunneling_client_token_check; @@ -943,7 +946,7 @@ static int s_secure_tunneling_fail_and_retry_connection_test_fn(struct aws_alloc (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; - aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture, AWS_SECURE_TUNNELING_DESTINATION_MODE); struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; test_fixture.secure_tunnel_vtable = *aws_secure_tunnel_get_default_vtable(); @@ -970,7 +973,7 @@ static int s_secure_tunneling_store_service_ids_test_fn(struct aws_allocator *al (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; - aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture, AWS_SECURE_TUNNELING_DESTINATION_MODE); struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); @@ -1004,7 +1007,7 @@ static int s_secure_tunneling_receive_stream_start_test_fn(struct aws_allocator (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; - aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture, AWS_SECURE_TUNNELING_DESTINATION_MODE); struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); @@ -1040,7 +1043,7 @@ static int s_secure_tunneling_rejected_service_id_stream_start_test_fn(struct aw (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; - aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture, AWS_SECURE_TUNNELING_DESTINATION_MODE); struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); @@ -1074,7 +1077,7 @@ static int s_secure_tunneling_close_stream_on_stream_reset_test_fn(struct aws_al (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; - aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture, AWS_SECURE_TUNNELING_DESTINATION_MODE); struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); @@ -1124,7 +1127,7 @@ static int s_secure_tunneling_ignore_stream_reset_for_inactive_stream_test_fn( (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; - aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture, AWS_SECURE_TUNNELING_DESTINATION_MODE); struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); @@ -1177,7 +1180,7 @@ static int s_secure_tunneling_session_reset_test_fn(struct aws_allocator *alloca (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; - aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture, AWS_SECURE_TUNNELING_DESTINATION_MODE); struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); @@ -1234,7 +1237,7 @@ static int s_secure_tunneling_serializer_data_message_test_fn(struct aws_allocat (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; - aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture, AWS_SECURE_TUNNELING_DESTINATION_MODE); struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); @@ -1286,7 +1289,7 @@ static int s_secure_tunneling_max_payload_test_fn(struct aws_allocator *allocato (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; - aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture, AWS_SECURE_TUNNELING_DESTINATION_MODE); struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); @@ -1328,7 +1331,7 @@ static int s_secure_tunneling_max_payload_exceed_test_fn(struct aws_allocator *a (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; - aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture, AWS_SECURE_TUNNELING_DESTINATION_MODE); struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); @@ -1373,7 +1376,7 @@ static int s_secure_tunneling_receive_connection_start_test_fn(struct aws_alloca (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; - aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture, AWS_SECURE_TUNNELING_DESTINATION_MODE); struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); @@ -1419,7 +1422,7 @@ static int s_secure_tunneling_ignore_inactive_stream_message_test_fn(struct aws_ (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; - aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture, AWS_SECURE_TUNNELING_DESTINATION_MODE); struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); @@ -1472,7 +1475,7 @@ static int s_secure_tunneling_ignore_inactive_connection_id_message_test_fn( (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; - aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture, AWS_SECURE_TUNNELING_DESTINATION_MODE); struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); @@ -1525,7 +1528,7 @@ static int s_secure_tunneling_v1_to_v2_stream_start_test_fn(struct aws_allocator (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; - aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture, AWS_SECURE_TUNNELING_DESTINATION_MODE); struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); @@ -1576,7 +1579,7 @@ static int s_secure_tunneling_v1_to_v3_stream_start_test_fn(struct aws_allocator (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; - aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture, AWS_SECURE_TUNNELING_DESTINATION_MODE); struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); @@ -1628,7 +1631,7 @@ static int s_secure_tunneling_v2_to_v1_stream_start_test_fn(struct aws_allocator (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; - aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture, AWS_SECURE_TUNNELING_DESTINATION_MODE); struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); @@ -1679,7 +1682,7 @@ static int s_secure_tunneling_v3_to_v1_stream_start_test_fn(struct aws_allocator (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; - aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture, AWS_SECURE_TUNNELING_DESTINATION_MODE); struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); @@ -1732,7 +1735,7 @@ static int s_secure_tunneling_v1_stream_start_v3_message_reset_test_fn(struct aw (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; - aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture, AWS_SECURE_TUNNELING_DESTINATION_MODE); struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); @@ -1786,7 +1789,7 @@ static int s_secure_tunneling_v2_stream_start_connection_start_reset_test_fn( (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; - aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture, AWS_SECURE_TUNNELING_DESTINATION_MODE); struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); @@ -1840,7 +1843,7 @@ static int s_secure_tunneling_close_stream_on_connection_reset_test_fn(struct aw (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; - aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture, AWS_SECURE_TUNNELING_DESTINATION_MODE); struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); @@ -1903,7 +1906,7 @@ static int s_secure_tunneling_existing_connection_start_send_reset_test_fn(struc (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; - aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture, AWS_SECURE_TUNNELING_DESTINATION_MODE); struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); @@ -1961,7 +1964,7 @@ static int s_secure_tunneling_send_v2_data_message_on_v1_connection_test_fn( (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; - aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture, AWS_SECURE_TUNNELING_DESTINATION_MODE); struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); @@ -2015,7 +2018,7 @@ static int s_secure_tunneling_send_v3_data_message_on_v1_connection_test_fn( (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; - aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture, AWS_SECURE_TUNNELING_DESTINATION_MODE); struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); @@ -2076,7 +2079,7 @@ static int s_secure_tunneling_send_v1_data_message_on_v2_connection_test_fn( (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; - aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture, AWS_SECURE_TUNNELING_DESTINATION_MODE); struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); @@ -2136,7 +2139,7 @@ static int s_secure_tunneling_send_v3_data_message_on_v2_connection_test_fn( (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; - aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture, AWS_SECURE_TUNNELING_DESTINATION_MODE); struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); @@ -2198,7 +2201,7 @@ static int s_secure_tunneling_send_v1_data_message_on_v3_connection_test_fn( (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; - aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture, AWS_SECURE_TUNNELING_DESTINATION_MODE); struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); @@ -2259,7 +2262,7 @@ static int s_secure_tunneling_send_v2_data_message_on_v3_connection_test_fn( (void)ctx; struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; - aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture, AWS_SECURE_TUNNELING_DESTINATION_MODE); struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); @@ -2323,7 +2326,7 @@ static int s_secure_tunneling_send_v2_data_message_on_incorrect_v2_connection_te struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; - aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture, AWS_SECURE_TUNNELING_DESTINATION_MODE); struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); @@ -2389,7 +2392,7 @@ static int s_secure_tunneling_send_v3_data_message_on_incorrect_v3_connection_te struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; - aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture, AWS_SECURE_TUNNELING_DESTINATION_MODE); struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); @@ -2456,7 +2459,7 @@ static int s_secure_tunneling_send_v1_data_message_with_no_active_connection_tes struct secure_tunnel_test_options test_options; struct aws_secure_tunnel_mock_test_fixture test_fixture; - aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture); + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture, AWS_SECURE_TUNNELING_DESTINATION_MODE); struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); @@ -2495,3 +2498,64 @@ static int s_secure_tunneling_send_v1_data_message_with_no_active_connection_tes AWS_TEST_CASE( secure_tunneling_send_v1_data_message_with_no_active_connection_test, s_secure_tunneling_send_v1_data_message_with_no_active_connection_test_fn) + +static int s_secure_tunneling_send_v3_stream_start_message_test_fn(struct aws_allocator *allocator, void *ctx) { + (void)ctx; + + struct secure_tunnel_test_options test_options; + struct aws_secure_tunnel_mock_test_fixture test_fixture; + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture, AWS_SECURE_TUNNELING_SOURCE_MODE); + struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; + + ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); + s_wait_for_connected_successfully(&test_fixture); + + /* Create and send a V3 StreamStart message to the server */ + struct aws_byte_cursor service_1 = aws_byte_cursor_from_string(s_service_id_1); + struct aws_secure_tunnel_message_view stream_start_message_view = { + .type = AWS_SECURE_TUNNEL_MT_STREAM_START, + .service_id = &service_1, + .stream_id = 0, + .connection_id = 2, + }; + aws_secure_tunnel_stream_start(test_fixture.secure_tunnel, &stream_start_message_view); + + /* Wait and confirm that a stream has been started */ + s_wait_for_stream_started(&test_fixture); + ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); + + /* Create and send a V3 DATA message */ + struct aws_secure_tunnel_message_view data_message_view = { + .type = AWS_SECURE_TUNNEL_MT_DATA, + .stream_id = 0, + .service_id = &service_1, + .connection_id = 2, + .payload = &s_payload_cursor_max_size, + }; + + int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); + ASSERT_INT_EQUALS(result, AWS_OP_SUCCESS); + + /* Confirm that no messages have gone out from the client */ + ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 0); + + /* Confirm that on_send_message_complete callback was fired */ + ASSERT_INT_EQUALS(test_fixture.on_send_message_complete_result.type, AWS_SECURE_TUNNEL_MT_DATA); + ASSERT_INT_EQUALS( + test_fixture.on_send_message_complete_result.error_code, + AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INVALID_CONNECTION_ID); + + /* Ensure that the established stream was not affected by the message */ + ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); + + ASSERT_SUCCESS(aws_secure_tunnel_stop(secure_tunnel)); + s_wait_for_connection_shutdown(&test_fixture); + + aws_secure_tunnel_mock_test_clean_up(&test_fixture); + + return AWS_OP_SUCCESS; +} + +AWS_TEST_CASE( + secure_tunneling_send_v3_stream_start_message_test, + s_secure_tunneling_send_v3_stream_start_message_test_fn) From 3b017c05e62a2e3c15721d380872e8850ddc0ad7 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Thu, 24 Aug 2023 09:27:49 -0700 Subject: [PATCH 42/52] Revert "Move STREAM_START validation to event loop" This reverts commit 5a92cd91c5f96d0ea79f5d3c139785defaaf69df. --- source/secure_tunneling.c | 50 ++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/source/secure_tunneling.c b/source/secure_tunneling.c index 4da856b2..318ca381 100644 --- a/source/secure_tunneling.c +++ b/source/secure_tunneling.c @@ -1885,33 +1885,6 @@ int aws_secure_tunnel_service_operational_state(struct aws_secure_tunnel *secure break; case AWS_STOT_STREAM_START: - /* TODO Extract into function */ - if (secure_tunnel->connections->protocol_version != 0 && - !s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, current_operation->message_view)) { - /* - * Protocol mismatch results in a full disconnect/reconnect to the Secure Tunnel Service followed by - * sending the STREAM START request that caused the mismatch. - */ - AWS_LOGF_INFO( - AWS_LS_IOTDEVICE_SECURE_TUNNELING, - "id=%p: Secure Tunnel will be reset due to Protocol Version mismatch between previously " - "established " - "Protocol Version and Protocol Version used by outbound STREAM START message.", - (void *)secure_tunnel); - reset_secure_tunnel_connection(secure_tunnel); - aws_secure_tunnel_stream_start(secure_tunnel, current_operation->message_view); - break; - } - - if (secure_tunnel->connections->protocol_version == 0) { - secure_tunnel->connections->protocol_version = - s_aws_secure_tunnel_message_min_protocol_check(current_operation->message_view); - AWS_LOGF_INFO( - AWS_LS_IOTDEVICE_SECURE_TUNNELING, - "id=%p: Secure tunnel client Protocol set to V%d based on outbound STREAM START", - (void *)secure_tunnel, - (int)secure_tunnel->connections->protocol_version); - } if ((*current_operation->vtable->aws_secure_tunnel_operation_set_next_stream_id_fn)( current_operation, secure_tunnel)) { error_code = aws_last_error(); @@ -2628,6 +2601,29 @@ int aws_secure_tunnel_stream_start( return AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INCORRECT_MODE; } + if (secure_tunnel->connections->protocol_version != 0 && + !s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, message_options)) { + /* + * Protocol mismatch results in a full disconnect/reconnect to the Secure Tunnel Service followed by + * sending the STREAM START request that caused the mismatch. + */ + AWS_LOGF_INFO( + AWS_LS_IOTDEVICE_SECURE_TUNNELING, + "id=%p: Secure Tunnel will be reset due to Protocol Version mismatch between previously established " + "Protocol Version and Protocol Version used by outbound STREAM START message.", + (void *)secure_tunnel); + reset_secure_tunnel_connection(secure_tunnel); + } + + if (secure_tunnel->connections->protocol_version == 0) { + secure_tunnel->connections->protocol_version = s_aws_secure_tunnel_message_min_protocol_check(message_options); + AWS_LOGF_INFO( + AWS_LS_IOTDEVICE_SECURE_TUNNELING, + "id=%p: Secure tunnel client Protocol set to V%d based on outbound STREAM START", + (void *)secure_tunnel, + (int)secure_tunnel->connections->protocol_version); + } + struct aws_secure_tunnel_operation_message *message_op = aws_secure_tunnel_operation_message_new( secure_tunnel->allocator, secure_tunnel, message_options, AWS_STOT_STREAM_START); From 9a77adea296211cf63088b017965e4b7eac37c80 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Thu, 24 Aug 2023 09:41:53 -0700 Subject: [PATCH 43/52] Fix stream_start test --- tests/secure_tunnel_tests.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/tests/secure_tunnel_tests.c b/tests/secure_tunnel_tests.c index 90b66251..025b0b94 100644 --- a/tests/secure_tunnel_tests.c +++ b/tests/secure_tunnel_tests.c @@ -2521,8 +2521,16 @@ static int s_secure_tunneling_send_v3_stream_start_message_test_fn(struct aws_al aws_secure_tunnel_stream_start(test_fixture.secure_tunnel, &stream_start_message_view); /* Wait and confirm that a stream has been started */ - s_wait_for_stream_started(&test_fixture); - ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); + s_wait_for_on_send_message_complete_fired(&test_fixture); + + /* Confirm that no messages have gone out from the client */ + ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 1); + + /* Confirm that on_send_message_complete callback was fired */ + ASSERT_INT_EQUALS(test_fixture.on_send_message_complete_result.type, AWS_SECURE_TUNNEL_MT_STREAM_START); + ASSERT_INT_EQUALS(test_fixture.on_send_message_complete_result.error_code, AWS_ERROR_SUCCESS); + + ASSERT_TRUE(s_secure_tunnel_check_active_connection_id(secure_tunnel, &service_1, 1, 2)); /* Create and send a V3 DATA message */ struct aws_secure_tunnel_message_view data_message_view = { @@ -2536,17 +2544,14 @@ static int s_secure_tunneling_send_v3_stream_start_message_test_fn(struct aws_al int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); ASSERT_INT_EQUALS(result, AWS_OP_SUCCESS); - /* Confirm that no messages have gone out from the client */ - ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 0); + /* Since there is no feedback on successful sending, simply sleep. */ + aws_thread_current_sleep(aws_timestamp_convert(1, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_NANOS, NULL)); - /* Confirm that on_send_message_complete callback was fired */ - ASSERT_INT_EQUALS(test_fixture.on_send_message_complete_result.type, AWS_SECURE_TUNNEL_MT_DATA); - ASSERT_INT_EQUALS( - test_fixture.on_send_message_complete_result.error_code, - AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INVALID_CONNECTION_ID); + /* Confirm that the message has been sent. */ + ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 2); /* Ensure that the established stream was not affected by the message */ - ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); + ASSERT_TRUE(s_secure_tunnel_check_active_connection_id(secure_tunnel, &service_1, 1, 2)); ASSERT_SUCCESS(aws_secure_tunnel_stop(secure_tunnel)); s_wait_for_connection_shutdown(&test_fixture); From 05878faa69339c40feb2ffdb03f2c43fa473c7ab Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Thu, 24 Aug 2023 09:54:32 -0700 Subject: [PATCH 44/52] Add CONNECTION_START test for source mode --- tests/CMakeLists.txt | 1 + tests/secure_tunnel_tests.c | 106 ++++++++++++++++++++++++++++++++++-- 2 files changed, 103 insertions(+), 4 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index e0215d58..3f244b37 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -53,6 +53,7 @@ add_net_test_case(secure_tunneling_send_v2_data_message_on_incorrect_v2_connecti add_net_test_case(secure_tunneling_send_v3_data_message_on_incorrect_v3_connection_test) add_net_test_case(secure_tunneling_send_v1_data_message_with_no_active_connection_test) add_net_test_case(secure_tunneling_send_v3_stream_start_message_test) +add_net_test_case(secure_tunneling_send_v3_connection_start_message_test) generate_test_driver(${PROJECT_NAME}-tests) diff --git a/tests/secure_tunnel_tests.c b/tests/secure_tunnel_tests.c index 025b0b94..417a647a 100644 --- a/tests/secure_tunnel_tests.c +++ b/tests/secure_tunnel_tests.c @@ -517,6 +517,8 @@ static void s_wait_for_on_send_message_complete_fired(struct aws_secure_tunnel_m aws_mutex_lock(&test_fixture->lock); aws_condition_variable_wait_pred( &test_fixture->signal, &test_fixture->lock, s_has_secure_tunnel_on_send_message_complete_fired, test_fixture); + /* Reset flag for the next message. */ + test_fixture->on_send_message_complete_fired = false; aws_mutex_unlock(&test_fixture->lock); } @@ -2510,7 +2512,7 @@ static int s_secure_tunneling_send_v3_stream_start_message_test_fn(struct aws_al ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); s_wait_for_connected_successfully(&test_fixture); - /* Create and send a V3 StreamStart message to the server */ + /* Create and send a V3 STREAM_START message to the server */ struct aws_byte_cursor service_1 = aws_byte_cursor_from_string(s_service_id_1); struct aws_secure_tunnel_message_view stream_start_message_view = { .type = AWS_SECURE_TUNNEL_MT_STREAM_START, @@ -2523,13 +2525,14 @@ static int s_secure_tunneling_send_v3_stream_start_message_test_fn(struct aws_al /* Wait and confirm that a stream has been started */ s_wait_for_on_send_message_complete_fired(&test_fixture); - /* Confirm that no messages have gone out from the client */ + /* Confirm that the message has been sent */ ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 1); /* Confirm that on_send_message_complete callback was fired */ ASSERT_INT_EQUALS(test_fixture.on_send_message_complete_result.type, AWS_SECURE_TUNNEL_MT_STREAM_START); ASSERT_INT_EQUALS(test_fixture.on_send_message_complete_result.error_code, AWS_ERROR_SUCCESS); + /* Ensure that the established connection is still active */ ASSERT_TRUE(s_secure_tunnel_check_active_connection_id(secure_tunnel, &service_1, 1, 2)); /* Create and send a V3 DATA message */ @@ -2547,10 +2550,10 @@ static int s_secure_tunneling_send_v3_stream_start_message_test_fn(struct aws_al /* Since there is no feedback on successful sending, simply sleep. */ aws_thread_current_sleep(aws_timestamp_convert(1, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_NANOS, NULL)); - /* Confirm that the message has been sent. */ + /* Confirm that the message has been sent */ ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 2); - /* Ensure that the established stream was not affected by the message */ + /* Ensure that the established connection is still active */ ASSERT_TRUE(s_secure_tunnel_check_active_connection_id(secure_tunnel, &service_1, 1, 2)); ASSERT_SUCCESS(aws_secure_tunnel_stop(secure_tunnel)); @@ -2564,3 +2567,98 @@ static int s_secure_tunneling_send_v3_stream_start_message_test_fn(struct aws_al AWS_TEST_CASE( secure_tunneling_send_v3_stream_start_message_test, s_secure_tunneling_send_v3_stream_start_message_test_fn) + +static int s_secure_tunneling_send_v3_connection_start_message_test_fn(struct aws_allocator *allocator, void *ctx) { + (void)ctx; + + struct secure_tunnel_test_options test_options; + struct aws_secure_tunnel_mock_test_fixture test_fixture; + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture, AWS_SECURE_TUNNELING_SOURCE_MODE); + struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; + + ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); + s_wait_for_connected_successfully(&test_fixture); + + /* Create and send a V3 StreamStart message to the server */ + struct aws_byte_cursor service_1 = aws_byte_cursor_from_string(s_service_id_1); + struct aws_secure_tunnel_message_view stream_start_message_view = { + .type = AWS_SECURE_TUNNEL_MT_STREAM_START, + .service_id = &service_1, + .stream_id = 0, + .connection_id = 2, + }; + aws_secure_tunnel_stream_start(test_fixture.secure_tunnel, &stream_start_message_view); + + /* Wait and confirm that a stream has been started */ + s_wait_for_on_send_message_complete_fired(&test_fixture); + + /* Confirm that the message has been sent */ + ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 1); + + /* Confirm that on_send_message_complete callback was fired */ + ASSERT_INT_EQUALS(test_fixture.on_send_message_complete_result.type, AWS_SECURE_TUNNEL_MT_STREAM_START); + ASSERT_INT_EQUALS(test_fixture.on_send_message_complete_result.error_code, AWS_ERROR_SUCCESS); + + ASSERT_TRUE(s_secure_tunnel_check_active_connection_id(secure_tunnel, &service_1, 1, 2)); + + /* Create and send a V3 CONNECTION_START message to the server */ + struct aws_secure_tunnel_message_view connection_start_message_view = { + .type = AWS_SECURE_TUNNEL_MT_CONNECTION_START, + .service_id = &service_1, + .stream_id = 0, + .connection_id = 3, + }; + aws_secure_tunnel_connection_start(test_fixture.secure_tunnel, &connection_start_message_view); + + /* Wait and confirm that a stream has been started */ + s_wait_for_on_send_message_complete_fired(&test_fixture); + + /* Confirm that the message has been sent */ + ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 2); + + /* Confirm that on_send_message_complete callback was fired */ + ASSERT_INT_EQUALS(test_fixture.on_send_message_complete_result.type, AWS_SECURE_TUNNEL_MT_CONNECTION_START); + ASSERT_INT_EQUALS(test_fixture.on_send_message_complete_result.error_code, AWS_ERROR_SUCCESS); + + /* Confirm that the both connections are active */ + ASSERT_TRUE(s_secure_tunnel_check_active_connection_id(secure_tunnel, &service_1, 1, 2)); + ASSERT_TRUE(s_secure_tunnel_check_active_connection_id(secure_tunnel, &service_1, 1, 3)); + + /* Create and send a V3 DATA message to the first connection */ + struct aws_secure_tunnel_message_view data_message_view = { + .type = AWS_SECURE_TUNNEL_MT_DATA, + .stream_id = 0, + .service_id = &service_1, + .connection_id = 2, + .payload = &s_payload_cursor_max_size, + }; + + int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); + ASSERT_INT_EQUALS(result, AWS_OP_SUCCESS); + + /* Send a V3 DATA message to the second connection */ + data_message_view.connection_id = 3; + result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); + ASSERT_INT_EQUALS(result, AWS_OP_SUCCESS); + + /* Since there is no feedback on successful sending, simply sleep. */ + aws_thread_current_sleep(aws_timestamp_convert(1, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_NANOS, NULL)); + + /* Confirm that the messages have been sent */ + ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 4); + + /* Ensure that the established connections are still active */ + ASSERT_TRUE(s_secure_tunnel_check_active_connection_id(secure_tunnel, &service_1, 1, 2)); + ASSERT_TRUE(s_secure_tunnel_check_active_connection_id(secure_tunnel, &service_1, 1, 3)); + + ASSERT_SUCCESS(aws_secure_tunnel_stop(secure_tunnel)); + s_wait_for_connection_shutdown(&test_fixture); + + aws_secure_tunnel_mock_test_clean_up(&test_fixture); + + return AWS_OP_SUCCESS; +} + +AWS_TEST_CASE( + secure_tunneling_send_v3_connection_start_message_test, + s_secure_tunneling_send_v3_connection_start_message_test_fn) From 2cbe3e46523ded6d876ce8fb85abcd5b34342b06 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Thu, 24 Aug 2023 09:56:20 -0700 Subject: [PATCH 45/52] Revert "Revert "Move STREAM_START validation to event loop"" This reverts commit 3b017c05e62a2e3c15721d380872e8850ddc0ad7. --- source/secure_tunneling.c | 50 +++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/source/secure_tunneling.c b/source/secure_tunneling.c index 318ca381..4da856b2 100644 --- a/source/secure_tunneling.c +++ b/source/secure_tunneling.c @@ -1885,6 +1885,33 @@ int aws_secure_tunnel_service_operational_state(struct aws_secure_tunnel *secure break; case AWS_STOT_STREAM_START: + /* TODO Extract into function */ + if (secure_tunnel->connections->protocol_version != 0 && + !s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, current_operation->message_view)) { + /* + * Protocol mismatch results in a full disconnect/reconnect to the Secure Tunnel Service followed by + * sending the STREAM START request that caused the mismatch. + */ + AWS_LOGF_INFO( + AWS_LS_IOTDEVICE_SECURE_TUNNELING, + "id=%p: Secure Tunnel will be reset due to Protocol Version mismatch between previously " + "established " + "Protocol Version and Protocol Version used by outbound STREAM START message.", + (void *)secure_tunnel); + reset_secure_tunnel_connection(secure_tunnel); + aws_secure_tunnel_stream_start(secure_tunnel, current_operation->message_view); + break; + } + + if (secure_tunnel->connections->protocol_version == 0) { + secure_tunnel->connections->protocol_version = + s_aws_secure_tunnel_message_min_protocol_check(current_operation->message_view); + AWS_LOGF_INFO( + AWS_LS_IOTDEVICE_SECURE_TUNNELING, + "id=%p: Secure tunnel client Protocol set to V%d based on outbound STREAM START", + (void *)secure_tunnel, + (int)secure_tunnel->connections->protocol_version); + } if ((*current_operation->vtable->aws_secure_tunnel_operation_set_next_stream_id_fn)( current_operation, secure_tunnel)) { error_code = aws_last_error(); @@ -2601,29 +2628,6 @@ int aws_secure_tunnel_stream_start( return AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INCORRECT_MODE; } - if (secure_tunnel->connections->protocol_version != 0 && - !s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, message_options)) { - /* - * Protocol mismatch results in a full disconnect/reconnect to the Secure Tunnel Service followed by - * sending the STREAM START request that caused the mismatch. - */ - AWS_LOGF_INFO( - AWS_LS_IOTDEVICE_SECURE_TUNNELING, - "id=%p: Secure Tunnel will be reset due to Protocol Version mismatch between previously established " - "Protocol Version and Protocol Version used by outbound STREAM START message.", - (void *)secure_tunnel); - reset_secure_tunnel_connection(secure_tunnel); - } - - if (secure_tunnel->connections->protocol_version == 0) { - secure_tunnel->connections->protocol_version = s_aws_secure_tunnel_message_min_protocol_check(message_options); - AWS_LOGF_INFO( - AWS_LS_IOTDEVICE_SECURE_TUNNELING, - "id=%p: Secure tunnel client Protocol set to V%d based on outbound STREAM START", - (void *)secure_tunnel, - (int)secure_tunnel->connections->protocol_version); - } - struct aws_secure_tunnel_operation_message *message_op = aws_secure_tunnel_operation_message_new( secure_tunnel->allocator, secure_tunnel, message_options, AWS_STOT_STREAM_START); From 85da045fd6324f119f74efa88ce88bcd86521d87 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Thu, 24 Aug 2023 10:06:10 -0700 Subject: [PATCH 46/52] Revert "Move STREAM_START validation to event loop" This reverts commit 5a92cd91c5f96d0ea79f5d3c139785defaaf69df. --- source/secure_tunneling.c | 50 ++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/source/secure_tunneling.c b/source/secure_tunneling.c index 4da856b2..318ca381 100644 --- a/source/secure_tunneling.c +++ b/source/secure_tunneling.c @@ -1885,33 +1885,6 @@ int aws_secure_tunnel_service_operational_state(struct aws_secure_tunnel *secure break; case AWS_STOT_STREAM_START: - /* TODO Extract into function */ - if (secure_tunnel->connections->protocol_version != 0 && - !s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, current_operation->message_view)) { - /* - * Protocol mismatch results in a full disconnect/reconnect to the Secure Tunnel Service followed by - * sending the STREAM START request that caused the mismatch. - */ - AWS_LOGF_INFO( - AWS_LS_IOTDEVICE_SECURE_TUNNELING, - "id=%p: Secure Tunnel will be reset due to Protocol Version mismatch between previously " - "established " - "Protocol Version and Protocol Version used by outbound STREAM START message.", - (void *)secure_tunnel); - reset_secure_tunnel_connection(secure_tunnel); - aws_secure_tunnel_stream_start(secure_tunnel, current_operation->message_view); - break; - } - - if (secure_tunnel->connections->protocol_version == 0) { - secure_tunnel->connections->protocol_version = - s_aws_secure_tunnel_message_min_protocol_check(current_operation->message_view); - AWS_LOGF_INFO( - AWS_LS_IOTDEVICE_SECURE_TUNNELING, - "id=%p: Secure tunnel client Protocol set to V%d based on outbound STREAM START", - (void *)secure_tunnel, - (int)secure_tunnel->connections->protocol_version); - } if ((*current_operation->vtable->aws_secure_tunnel_operation_set_next_stream_id_fn)( current_operation, secure_tunnel)) { error_code = aws_last_error(); @@ -2628,6 +2601,29 @@ int aws_secure_tunnel_stream_start( return AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INCORRECT_MODE; } + if (secure_tunnel->connections->protocol_version != 0 && + !s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, message_options)) { + /* + * Protocol mismatch results in a full disconnect/reconnect to the Secure Tunnel Service followed by + * sending the STREAM START request that caused the mismatch. + */ + AWS_LOGF_INFO( + AWS_LS_IOTDEVICE_SECURE_TUNNELING, + "id=%p: Secure Tunnel will be reset due to Protocol Version mismatch between previously established " + "Protocol Version and Protocol Version used by outbound STREAM START message.", + (void *)secure_tunnel); + reset_secure_tunnel_connection(secure_tunnel); + } + + if (secure_tunnel->connections->protocol_version == 0) { + secure_tunnel->connections->protocol_version = s_aws_secure_tunnel_message_min_protocol_check(message_options); + AWS_LOGF_INFO( + AWS_LS_IOTDEVICE_SECURE_TUNNELING, + "id=%p: Secure tunnel client Protocol set to V%d based on outbound STREAM START", + (void *)secure_tunnel, + (int)secure_tunnel->connections->protocol_version); + } + struct aws_secure_tunnel_operation_message *message_op = aws_secure_tunnel_operation_message_new( secure_tunnel->allocator, secure_tunnel, message_options, AWS_STOT_STREAM_START); From 0ab29978f270e291cef3738c5d86a5981ab140e3 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Thu, 24 Aug 2023 10:55:14 -0700 Subject: [PATCH 47/52] Add test for outbound STREAM_START message causing reset --- source/secure_tunneling.c | 15 +++++- tests/CMakeLists.txt | 1 + tests/secure_tunnel_tests.c | 97 ++++++++++++++++++++++++++++++++++++- 3 files changed, 111 insertions(+), 2 deletions(-) diff --git a/source/secure_tunneling.c b/source/secure_tunneling.c index 318ca381..8c18ebc3 100644 --- a/source/secure_tunneling.c +++ b/source/secure_tunneling.c @@ -1658,7 +1658,14 @@ static void s_complete_operation( struct aws_secure_tunnel_operation *operation, int error_code, const void *view) { - (void)secure_tunnel; + + AWS_LOGF_TRACE( + AWS_LS_IOTDEVICE_SECURE_TUNNELING, + "id=%p: Completing operation %s with error %d (%s)", + (void *)secure_tunnel, + aws_secure_tunnel_operation_type_to_c_string(operation->operation_type), + error_code, + aws_error_str(error_code)); aws_secure_tunnel_operation_complete(operation, error_code, view); aws_secure_tunnel_operation_release(operation); @@ -1865,6 +1872,12 @@ int aws_secure_tunnel_service_operational_state(struct aws_secure_tunnel *secure } int error_code = AWS_OP_SUCCESS; + AWS_LOGF_TRACE( + AWS_LS_IOTDEVICE_SECURE_TUNNELING, + "id=%p: Processing %s message", + (void *)secure_tunnel, + aws_secure_tunnel_operation_type_to_c_string(current_operation->operation_type)); + switch (current_operation->operation_type) { case AWS_STOT_PING:; /* diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 3f244b37..cbac1041 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -53,6 +53,7 @@ add_net_test_case(secure_tunneling_send_v2_data_message_on_incorrect_v2_connecti add_net_test_case(secure_tunneling_send_v3_data_message_on_incorrect_v3_connection_test) add_net_test_case(secure_tunneling_send_v1_data_message_with_no_active_connection_test) add_net_test_case(secure_tunneling_send_v3_stream_start_message_test) +add_net_test_case(secure_tunneling_send_v3_stream_start_message_with_reset_test) add_net_test_case(secure_tunneling_send_v3_connection_start_message_test) generate_test_driver(${PROJECT_NAME}-tests) diff --git a/tests/secure_tunnel_tests.c b/tests/secure_tunnel_tests.c index 417a647a..088da1e1 100644 --- a/tests/secure_tunnel_tests.c +++ b/tests/secure_tunnel_tests.c @@ -2532,7 +2532,7 @@ static int s_secure_tunneling_send_v3_stream_start_message_test_fn(struct aws_al ASSERT_INT_EQUALS(test_fixture.on_send_message_complete_result.type, AWS_SECURE_TUNNEL_MT_STREAM_START); ASSERT_INT_EQUALS(test_fixture.on_send_message_complete_result.error_code, AWS_ERROR_SUCCESS); - /* Ensure that the established connection is still active */ + /* Ensure that the established connection is active */ ASSERT_TRUE(s_secure_tunnel_check_active_connection_id(secure_tunnel, &service_1, 1, 2)); /* Create and send a V3 DATA message */ @@ -2568,6 +2568,101 @@ AWS_TEST_CASE( secure_tunneling_send_v3_stream_start_message_test, s_secure_tunneling_send_v3_stream_start_message_test_fn) +static int s_secure_tunneling_send_v3_stream_start_message_with_reset_test_fn( + struct aws_allocator *allocator, + void *ctx) { + (void)ctx; + + struct secure_tunnel_test_options test_options; + struct aws_secure_tunnel_mock_test_fixture test_fixture; + aws_secure_tunnel_mock_test_init(allocator, &test_options, &test_fixture, AWS_SECURE_TUNNELING_SOURCE_MODE); + struct aws_secure_tunnel *secure_tunnel = test_fixture.secure_tunnel; + + ASSERT_SUCCESS(aws_secure_tunnel_start(secure_tunnel)); + s_wait_for_connected_successfully(&test_fixture); + + /* Create and send a V2 STREAM_START message to the server */ + struct aws_byte_cursor service_1 = aws_byte_cursor_from_string(s_service_id_1); + struct aws_secure_tunnel_message_view stream_start_v2_message_view = { + .type = AWS_SECURE_TUNNEL_MT_STREAM_START, + .service_id = &service_1, + .stream_id = 0, + }; + ASSERT_INT_EQUALS( + aws_secure_tunnel_stream_start(test_fixture.secure_tunnel, &stream_start_v2_message_view), AWS_OP_SUCCESS); + + /* Wait and confirm that a stream has been started */ + s_wait_for_on_send_message_complete_fired(&test_fixture); + + /* Confirm that the message has been sent */ + ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 1); + + /* Confirm that on_send_message_complete callback was fired */ + ASSERT_INT_EQUALS(test_fixture.on_send_message_complete_result.type, AWS_SECURE_TUNNEL_MT_STREAM_START); + ASSERT_INT_EQUALS(test_fixture.on_send_message_complete_result.error_code, AWS_ERROR_SUCCESS); + + /* Ensure that the established stream is active */ + ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); + + /* Create and send a V3 STREAM_START message to the server */ + struct aws_byte_cursor service_2 = aws_byte_cursor_from_string(s_service_id_2); + struct aws_secure_tunnel_message_view stream_start_v3_message_view = { + .type = AWS_SECURE_TUNNEL_MT_STREAM_START, + .service_id = &service_2, + .stream_id = 0, + .connection_id = 2, + }; + ASSERT_INT_EQUALS( + aws_secure_tunnel_stream_start(test_fixture.secure_tunnel, &stream_start_v3_message_view), AWS_OP_SUCCESS); + + /* Wait and confirm that a stream has been started */ + s_wait_for_on_send_message_complete_fired(&test_fixture); + + /* Confirm that the message has been sent */ + ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 2); + + /* Confirm that on_send_message_complete callback was fired */ + ASSERT_INT_EQUALS(test_fixture.on_send_message_complete_result.type, AWS_SECURE_TUNNEL_MT_STREAM_START); + ASSERT_INT_EQUALS(test_fixture.on_send_message_complete_result.error_code, AWS_ERROR_SUCCESS); + + /* Ensure that the old stream is inactive */ + ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 0)); + /* Ensure that the newly established stream is active */ + ASSERT_TRUE(s_secure_tunnel_check_active_connection_id(secure_tunnel, &service_2, 1, 2)); + + /* Create and send a V3 DATA message */ + struct aws_secure_tunnel_message_view data_message_view = { + .type = AWS_SECURE_TUNNEL_MT_DATA, + .stream_id = 0, + .service_id = &service_2, + .connection_id = 2, + .payload = &s_payload_cursor_max_size, + }; + + int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); + ASSERT_INT_EQUALS(result, AWS_OP_SUCCESS); + + /* Since there is no feedback on successful sending, simply sleep. */ + aws_thread_current_sleep(aws_timestamp_convert(1, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_NANOS, NULL)); + + /* Confirm that the message has been sent */ + ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 3); + + /* Ensure that the established connection is still active */ + ASSERT_TRUE(s_secure_tunnel_check_active_connection_id(secure_tunnel, &service_2, 1, 2)); + + ASSERT_SUCCESS(aws_secure_tunnel_stop(secure_tunnel)); + s_wait_for_connection_shutdown(&test_fixture); + + aws_secure_tunnel_mock_test_clean_up(&test_fixture); + + return AWS_OP_SUCCESS; +} + +AWS_TEST_CASE( + secure_tunneling_send_v3_stream_start_message_with_reset_test, + s_secure_tunneling_send_v3_stream_start_message_with_reset_test_fn) + static int s_secure_tunneling_send_v3_connection_start_message_test_fn(struct aws_allocator *allocator, void *ctx) { (void)ctx; From 5d1d18324f943176ff49ebaacfcd8e36717e658d Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Thu, 24 Aug 2023 10:55:30 -0700 Subject: [PATCH 48/52] Revert "Revert "Move STREAM_START validation to event loop"" This reverts commit 85da045fd6324f119f74efa88ce88bcd86521d87. --- source/secure_tunneling.c | 50 +++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/source/secure_tunneling.c b/source/secure_tunneling.c index 8c18ebc3..856d89e1 100644 --- a/source/secure_tunneling.c +++ b/source/secure_tunneling.c @@ -1898,6 +1898,33 @@ int aws_secure_tunnel_service_operational_state(struct aws_secure_tunnel *secure break; case AWS_STOT_STREAM_START: + /* TODO Extract into function */ + if (secure_tunnel->connections->protocol_version != 0 && + !s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, current_operation->message_view)) { + /* + * Protocol mismatch results in a full disconnect/reconnect to the Secure Tunnel Service followed by + * sending the STREAM START request that caused the mismatch. + */ + AWS_LOGF_INFO( + AWS_LS_IOTDEVICE_SECURE_TUNNELING, + "id=%p: Secure Tunnel will be reset due to Protocol Version mismatch between previously " + "established " + "Protocol Version and Protocol Version used by outbound STREAM START message.", + (void *)secure_tunnel); + reset_secure_tunnel_connection(secure_tunnel); + aws_secure_tunnel_stream_start(secure_tunnel, current_operation->message_view); + break; + } + + if (secure_tunnel->connections->protocol_version == 0) { + secure_tunnel->connections->protocol_version = + s_aws_secure_tunnel_message_min_protocol_check(current_operation->message_view); + AWS_LOGF_INFO( + AWS_LS_IOTDEVICE_SECURE_TUNNELING, + "id=%p: Secure tunnel client Protocol set to V%d based on outbound STREAM START", + (void *)secure_tunnel, + (int)secure_tunnel->connections->protocol_version); + } if ((*current_operation->vtable->aws_secure_tunnel_operation_set_next_stream_id_fn)( current_operation, secure_tunnel)) { error_code = aws_last_error(); @@ -2614,29 +2641,6 @@ int aws_secure_tunnel_stream_start( return AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INCORRECT_MODE; } - if (secure_tunnel->connections->protocol_version != 0 && - !s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, message_options)) { - /* - * Protocol mismatch results in a full disconnect/reconnect to the Secure Tunnel Service followed by - * sending the STREAM START request that caused the mismatch. - */ - AWS_LOGF_INFO( - AWS_LS_IOTDEVICE_SECURE_TUNNELING, - "id=%p: Secure Tunnel will be reset due to Protocol Version mismatch between previously established " - "Protocol Version and Protocol Version used by outbound STREAM START message.", - (void *)secure_tunnel); - reset_secure_tunnel_connection(secure_tunnel); - } - - if (secure_tunnel->connections->protocol_version == 0) { - secure_tunnel->connections->protocol_version = s_aws_secure_tunnel_message_min_protocol_check(message_options); - AWS_LOGF_INFO( - AWS_LS_IOTDEVICE_SECURE_TUNNELING, - "id=%p: Secure tunnel client Protocol set to V%d based on outbound STREAM START", - (void *)secure_tunnel, - (int)secure_tunnel->connections->protocol_version); - } - struct aws_secure_tunnel_operation_message *message_op = aws_secure_tunnel_operation_message_new( secure_tunnel->allocator, secure_tunnel, message_options, AWS_STOT_STREAM_START); From 5521fd1ad84d2c4ac8732adae0a3bb1756e8daef Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Thu, 24 Aug 2023 11:06:23 -0700 Subject: [PATCH 49/52] Move validation of CONNECTION_START to event loop --- source/secure_tunneling.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/source/secure_tunneling.c b/source/secure_tunneling.c index 856d89e1..4ef62f5a 100644 --- a/source/secure_tunneling.c +++ b/source/secure_tunneling.c @@ -1911,6 +1911,8 @@ int aws_secure_tunnel_service_operational_state(struct aws_secure_tunnel *secure "established " "Protocol Version and Protocol Version used by outbound STREAM START message.", (void *)secure_tunnel); + /* TODO The following doesn't work as all enqueuing operations are canceled on resetting a tunnel + * connection. */ reset_secure_tunnel_connection(secure_tunnel); aws_secure_tunnel_stream_start(secure_tunnel, current_operation->message_view); break; @@ -1948,7 +1950,6 @@ int aws_secure_tunnel_service_operational_state(struct aws_secure_tunnel *secure break; case AWS_STOT_STREAM_RESET: - if ((*current_operation->vtable->aws_secure_tunnel_operation_assign_stream_id_fn)( current_operation, secure_tunnel) == AWS_OP_SUCCESS) { if (current_operation->message_view->connection_id == 0) { @@ -1974,9 +1975,18 @@ int aws_secure_tunnel_service_operational_state(struct aws_secure_tunnel *secure break; case AWS_STOT_CONNECTION_START: + if (secure_tunnel->connections->protocol_version != 3) { + AWS_LOGF_WARN( + AWS_LS_IOTDEVICE_SECURE_TUNNELING, + "Connection Start may only be used with a Protocol V3 stream."); + error_code = AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISMATCH; + } else if (current_operation->message_view->connection_id == 0) { + AWS_LOGF_WARN(AWS_LS_IOTDEVICE_SECURE_TUNNELING, "Connection Start must include a connection id."); + error_code = AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INVALID_CONNECTION_ID; + } /* If a connection start attempts to be sent on an unopen stream, discard it. */ - if ((*current_operation->vtable->aws_secure_tunnel_operation_assign_stream_id_fn)( - current_operation, secure_tunnel)) { + else if ((*current_operation->vtable->aws_secure_tunnel_operation_assign_stream_id_fn)( + current_operation, secure_tunnel)) { error_code = aws_last_error(); } else if ((*current_operation->vtable->aws_secure_tunnel_operation_set_connection_start_id)( current_operation, secure_tunnel)) { @@ -2676,17 +2686,6 @@ int aws_secure_tunnel_connection_start( return AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INCORRECT_MODE; } - if (secure_tunnel->connections->protocol_version != 3) { - AWS_LOGF_WARN( - AWS_LS_IOTDEVICE_SECURE_TUNNELING, "Connection Start may only be used with a Protocol V3 stream."); - return AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISMATCH; - } - - if (message_options->connection_id == 0) { - AWS_LOGF_WARN(AWS_LS_IOTDEVICE_SECURE_TUNNELING, "Connection Start must include a connection id."); - return AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INVALID_CONNECTION_ID; - } - struct aws_secure_tunnel_operation_message *message_op = aws_secure_tunnel_operation_message_new( secure_tunnel->allocator, secure_tunnel, message_options, AWS_STOT_CONNECTION_START); From 254293a2e4e06b5ea3f1b3b3f918e28f78a91be1 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Thu, 24 Aug 2023 11:09:35 -0700 Subject: [PATCH 50/52] Disable failing test --- tests/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index cbac1041..147e3d71 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -53,7 +53,8 @@ add_net_test_case(secure_tunneling_send_v2_data_message_on_incorrect_v2_connecti add_net_test_case(secure_tunneling_send_v3_data_message_on_incorrect_v3_connection_test) add_net_test_case(secure_tunneling_send_v1_data_message_with_no_active_connection_test) add_net_test_case(secure_tunneling_send_v3_stream_start_message_test) -add_net_test_case(secure_tunneling_send_v3_stream_start_message_with_reset_test) +# TODO This tests fails, enable it when restarting stream is supported in source mode. +# add_net_test_case(secure_tunneling_send_v3_stream_start_message_with_reset_test) add_net_test_case(secure_tunneling_send_v3_connection_start_message_test) generate_test_driver(${PROJECT_NAME}-tests) From 78bc7fa58f534a9d4fcad633acde99702235f3b0 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Thu, 24 Aug 2023 13:16:55 -0700 Subject: [PATCH 51/52] Fix stream_start test with reset --- source/secure_tunneling.c | 138 +++++++++++++++++++++--------------- tests/CMakeLists.txt | 3 +- tests/secure_tunnel_tests.c | 33 ++------- 3 files changed, 88 insertions(+), 86 deletions(-) diff --git a/source/secure_tunneling.c b/source/secure_tunneling.c index 4ef62f5a..4a36b9cb 100644 --- a/source/secure_tunneling.c +++ b/source/secure_tunneling.c @@ -1757,7 +1757,7 @@ static bool s_aws_secure_tunnel_should_service_operational_state( * \internal * Validate an outbound DATA message, set required fields (e.g. stream_id) and send it to the corresponding active * connection. - * Calls on_send_message_complete callback if an error occurs. + * Call on_send_message_complete callback if an error occurs. * \endinternal */ static void s_process_outbound_data_message( @@ -1768,7 +1768,7 @@ static void s_process_outbound_data_message( if (secure_tunnel->connections->protocol_version == 0) { error_code = AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_NO_ACTIVE_CONNECTION; - goto error; + goto done; } (*current_operation->vtable->aws_secure_tunnel_operation_prepare_message_for_send_fn)( @@ -1778,14 +1778,14 @@ static void s_process_outbound_data_message( * be ignored. */ if (!s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, current_operation->message_view)) { error_code = AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_PROTOCOL_VERSION_MISMATCH; - goto error; + goto done; } /* An outbound message does not have an assigned stream ID, assign an active stream ID to it. */ if ((*current_operation->vtable->aws_secure_tunnel_operation_assign_stream_id_fn)( current_operation, secure_tunnel)) { error_code = aws_last_error(); - goto error; + goto done; } /* If a data message attempts to be sent on an unopen stream, discard it. */ @@ -1812,7 +1812,7 @@ static void s_process_outbound_data_message( error_code, aws_error_debug_str(error_code)); } - goto error; + goto done; } /* Send the Data message through the WebSocket */ @@ -1827,15 +1827,87 @@ static void s_process_outbound_data_message( } aws_secure_tunnel_message_view_log(current_operation->message_view, AWS_LL_DEBUG); - return; - -error: +done: if (error_code && secure_tunnel->config->on_send_message_complete) { secure_tunnel->config->on_send_message_complete( AWS_SECURE_TUNNEL_MT_DATA, error_code, secure_tunnel->config->user_data); } } +/** + * \internal + * Send STREAM_START message to the Secure Tunnel Service. + * Call on_send_message_complete callback if an error occurs. + * \endinternal + */ +static void s_process_outbound_stream_start_message( + struct aws_secure_tunnel *secure_tunnel, + struct aws_secure_tunnel_operation *current_operation) { + + int error_code = AWS_OP_SUCCESS; + + if (secure_tunnel->connections->protocol_version != 0 && + !s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, current_operation->message_view)) { + AWS_LOGF_WARN( + AWS_LS_IOTDEVICE_SECURE_TUNNELING, + "id=%p: Secure Tunnel client does not support STREAM_START messages with mismatched protocol version in " + "SOURCE mode", + (void *)secure_tunnel); + + error_code = AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISMATCH; + goto done; + + /* TODO The following doesn't work as all enqueued operations are canceled on resetting a tunnel connection. */ + + /* + * Protocol mismatch results in a full disconnect/reconnect to the Secure Tunnel Service followed by + * sending the STREAM START request that caused the mismatch. + */ + AWS_LOGF_INFO( + AWS_LS_IOTDEVICE_SECURE_TUNNELING, + "id=%p: Secure Tunnel will be reset due to Protocol Version mismatch between previously " + "established " + "Protocol Version and Protocol Version used by outbound STREAM START message.", + (void *)secure_tunnel); + reset_secure_tunnel_connection(secure_tunnel); + aws_secure_tunnel_stream_start(secure_tunnel, current_operation->message_view); + goto done; + } + + if (secure_tunnel->connections->protocol_version == 0) { + secure_tunnel->connections->protocol_version = + s_aws_secure_tunnel_message_min_protocol_check(current_operation->message_view); + AWS_LOGF_INFO( + AWS_LS_IOTDEVICE_SECURE_TUNNELING, + "id=%p: Secure tunnel client Protocol set to V%d based on outbound STREAM START", + (void *)secure_tunnel, + (int)secure_tunnel->connections->protocol_version); + } + + if ((*current_operation->vtable->aws_secure_tunnel_operation_set_next_stream_id_fn)( + current_operation, secure_tunnel)) { + error_code = aws_last_error(); + AWS_LOGF_DEBUG( + AWS_LS_IOTDEVICE_SECURE_TUNNELING, + "id=%p: failed to send STREAM START message with error %d(%s)", + (void *)secure_tunnel, + error_code, + aws_error_debug_str(error_code)); + goto done; + } + + if (s_secure_tunneling_send(secure_tunnel, current_operation->message_view)) { + error_code = aws_last_error(); + } + aws_secure_tunnel_message_view_log(current_operation->message_view, AWS_LL_DEBUG); + +done: + if (error_code && secure_tunnel->config->on_send_message_complete) { + secure_tunnel->config->on_send_message_complete( + AWS_SECURE_TUNNEL_MT_STREAM_START, error_code, secure_tunnel->config->user_data); + } +} + int aws_secure_tunnel_service_operational_state(struct aws_secure_tunnel *secure_tunnel) { const struct aws_secure_tunnel_vtable *vtable = secure_tunnel->vtable; uint64_t now = (*vtable->get_current_time_fn)(); @@ -1898,55 +1970,7 @@ int aws_secure_tunnel_service_operational_state(struct aws_secure_tunnel *secure break; case AWS_STOT_STREAM_START: - /* TODO Extract into function */ - if (secure_tunnel->connections->protocol_version != 0 && - !s_aws_secure_tunnel_protocol_version_match_check(secure_tunnel, current_operation->message_view)) { - /* - * Protocol mismatch results in a full disconnect/reconnect to the Secure Tunnel Service followed by - * sending the STREAM START request that caused the mismatch. - */ - AWS_LOGF_INFO( - AWS_LS_IOTDEVICE_SECURE_TUNNELING, - "id=%p: Secure Tunnel will be reset due to Protocol Version mismatch between previously " - "established " - "Protocol Version and Protocol Version used by outbound STREAM START message.", - (void *)secure_tunnel); - /* TODO The following doesn't work as all enqueuing operations are canceled on resetting a tunnel - * connection. */ - reset_secure_tunnel_connection(secure_tunnel); - aws_secure_tunnel_stream_start(secure_tunnel, current_operation->message_view); - break; - } - - if (secure_tunnel->connections->protocol_version == 0) { - secure_tunnel->connections->protocol_version = - s_aws_secure_tunnel_message_min_protocol_check(current_operation->message_view); - AWS_LOGF_INFO( - AWS_LS_IOTDEVICE_SECURE_TUNNELING, - "id=%p: Secure tunnel client Protocol set to V%d based on outbound STREAM START", - (void *)secure_tunnel, - (int)secure_tunnel->connections->protocol_version); - } - if ((*current_operation->vtable->aws_secure_tunnel_operation_set_next_stream_id_fn)( - current_operation, secure_tunnel)) { - error_code = aws_last_error(); - AWS_LOGF_DEBUG( - AWS_LS_IOTDEVICE_SECURE_TUNNELING, - "id=%p: failed to send STREAM START message with error %d(%s)", - (void *)secure_tunnel, - error_code, - aws_error_debug_str(error_code)); - } else { - if (s_secure_tunneling_send(secure_tunnel, current_operation->message_view)) { - error_code = aws_last_error(); - } - aws_secure_tunnel_message_view_log(current_operation->message_view, AWS_LL_DEBUG); - } - - if (error_code && secure_tunnel->config->on_send_message_complete) { - secure_tunnel->config->on_send_message_complete( - AWS_SECURE_TUNNEL_MT_STREAM_START, error_code, secure_tunnel->config->user_data); - } + s_process_outbound_stream_start_message(secure_tunnel, current_operation); break; case AWS_STOT_STREAM_RESET: diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 147e3d71..cbac1041 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -53,8 +53,7 @@ add_net_test_case(secure_tunneling_send_v2_data_message_on_incorrect_v2_connecti add_net_test_case(secure_tunneling_send_v3_data_message_on_incorrect_v3_connection_test) add_net_test_case(secure_tunneling_send_v1_data_message_with_no_active_connection_test) add_net_test_case(secure_tunneling_send_v3_stream_start_message_test) -# TODO This tests fails, enable it when restarting stream is supported in source mode. -# add_net_test_case(secure_tunneling_send_v3_stream_start_message_with_reset_test) +add_net_test_case(secure_tunneling_send_v3_stream_start_message_with_reset_test) add_net_test_case(secure_tunneling_send_v3_connection_start_message_test) generate_test_driver(${PROJECT_NAME}-tests) diff --git a/tests/secure_tunnel_tests.c b/tests/secure_tunnel_tests.c index 088da1e1..0bc2cecc 100644 --- a/tests/secure_tunnel_tests.c +++ b/tests/secure_tunnel_tests.c @@ -2619,37 +2619,16 @@ static int s_secure_tunneling_send_v3_stream_start_message_with_reset_test_fn( s_wait_for_on_send_message_complete_fired(&test_fixture); /* Confirm that the message has been sent */ - ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 2); + ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 1); /* Confirm that on_send_message_complete callback was fired */ ASSERT_INT_EQUALS(test_fixture.on_send_message_complete_result.type, AWS_SECURE_TUNNEL_MT_STREAM_START); - ASSERT_INT_EQUALS(test_fixture.on_send_message_complete_result.error_code, AWS_ERROR_SUCCESS); - - /* Ensure that the old stream is inactive */ - ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 0)); - /* Ensure that the newly established stream is active */ - ASSERT_TRUE(s_secure_tunnel_check_active_connection_id(secure_tunnel, &service_2, 1, 2)); - - /* Create and send a V3 DATA message */ - struct aws_secure_tunnel_message_view data_message_view = { - .type = AWS_SECURE_TUNNEL_MT_DATA, - .stream_id = 0, - .service_id = &service_2, - .connection_id = 2, - .payload = &s_payload_cursor_max_size, - }; - - int result = aws_secure_tunnel_send_message(secure_tunnel, &data_message_view); - ASSERT_INT_EQUALS(result, AWS_OP_SUCCESS); - - /* Since there is no feedback on successful sending, simply sleep. */ - aws_thread_current_sleep(aws_timestamp_convert(1, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_NANOS, NULL)); - - /* Confirm that the message has been sent */ - ASSERT_INT_EQUALS(test_fixture.secure_tunnel_message_sent_count, 3); + ASSERT_INT_EQUALS( + test_fixture.on_send_message_complete_result.error_code, + AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISMATCH); - /* Ensure that the established connection is still active */ - ASSERT_TRUE(s_secure_tunnel_check_active_connection_id(secure_tunnel, &service_2, 1, 2)); + /* Ensure that the old stream is still active */ + ASSERT_TRUE(s_secure_tunnel_check_active_stream_id(secure_tunnel, &service_1, 1)); ASSERT_SUCCESS(aws_secure_tunnel_stop(secure_tunnel)); s_wait_for_connection_shutdown(&test_fixture); From 1ee3b314ccf534bbe8cbd097040d50b01146a5b2 Mon Sep 17 00:00:00 2001 From: Igor Abdrakhimov Date: Thu, 24 Aug 2023 13:23:16 -0700 Subject: [PATCH 52/52] Fix windows build --- source/secure_tunneling.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/source/secure_tunneling.c b/source/secure_tunneling.c index 4a36b9cb..c14bb0c2 100644 --- a/source/secure_tunneling.c +++ b/source/secure_tunneling.c @@ -1855,22 +1855,23 @@ static void s_process_outbound_stream_start_message( (void *)secure_tunnel); error_code = AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISMATCH; - goto done; /* TODO The following doesn't work as all enqueued operations are canceled on resetting a tunnel connection. */ - - /* - * Protocol mismatch results in a full disconnect/reconnect to the Secure Tunnel Service followed by - * sending the STREAM START request that caused the mismatch. - */ - AWS_LOGF_INFO( - AWS_LS_IOTDEVICE_SECURE_TUNNELING, - "id=%p: Secure Tunnel will be reset due to Protocol Version mismatch between previously " - "established " - "Protocol Version and Protocol Version used by outbound STREAM START message.", - (void *)secure_tunnel); - reset_secure_tunnel_connection(secure_tunnel); - aws_secure_tunnel_stream_start(secure_tunnel, current_operation->message_view); + bool is_reset_supported = false; + if (is_reset_supported) { + /* + * Protocol mismatch results in a full disconnect/reconnect to the Secure Tunnel Service followed by + * sending the STREAM START request that caused the mismatch. + */ + AWS_LOGF_INFO( + AWS_LS_IOTDEVICE_SECURE_TUNNELING, + "id=%p: Secure Tunnel will be reset due to Protocol Version mismatch between previously " + "established " + "Protocol Version and Protocol Version used by outbound STREAM START message.", + (void *)secure_tunnel); + reset_secure_tunnel_connection(secure_tunnel); + aws_secure_tunnel_stream_start(secure_tunnel, current_operation->message_view); + } goto done; }