Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package aws-c-http for openSUSE:Factory 
checked in at 2025-04-04 17:34:15
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/aws-c-http (Old)
 and      /work/SRC/openSUSE:Factory/.aws-c-http.new.1907 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "aws-c-http"

Fri Apr  4 17:34:15 2025 rev:15 rq:1267109 version:0.9.6

Changes:
--------
--- /work/SRC/openSUSE:Factory/aws-c-http/aws-c-http.changes    2025-03-26 
21:25:17.871180417 +0100
+++ /work/SRC/openSUSE:Factory/.aws-c-http.new.1907/aws-c-http.changes  
2025-04-04 17:34:19.401041944 +0200
@@ -1,0 +2,8 @@
+Wed Apr  2 14:55:22 UTC 2025 - John Paul Adrian Glaubitz 
<adrian.glaub...@suse.com>
+
+- Update to 0.9.6
+  * Fix Error Handling For Connection Manager by @waahm7 in (#507)
+  * h1_decoder error on multiple content-length headers by @quinnj in (#509)
+  * Apple Network Framework Support by @xiazhvera in (#502)
+
+-------------------------------------------------------------------

Old:
----
  v0.9.5.tar.gz

New:
----
  v0.9.6.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ aws-c-http.spec ++++++
--- /var/tmp/diff_new_pack.FYzwoX/_old  2025-04-04 17:34:20.821101255 +0200
+++ /var/tmp/diff_new_pack.FYzwoX/_new  2025-04-04 17:34:20.821101255 +0200
@@ -19,7 +19,7 @@
 %define library_version 1.0.0
 %define library_soversion 1_0_0
 Name:           aws-c-http
-Version:        0.9.5
+Version:        0.9.6
 Release:        0
 Summary:        C99 implementation of the HTTP/1.1 and HTTP/2 specifications
 License:        Apache-2.0

++++++ v0.9.5.tar.gz -> v0.9.6.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aws-c-http-0.9.5/.github/workflows/ci.yml 
new/aws-c-http-0.9.6/.github/workflows/ci.yml
--- old/aws-c-http-0.9.5/.github/workflows/ci.yml       2025-03-14 
21:12:18.000000000 +0100
+++ new/aws-c-http-0.9.6/.github/workflows/ci.yml       2025-03-28 
22:24:03.000000000 +0100
@@ -204,7 +204,11 @@
         python 
.\aws-c-http\build\deps\aws-c-common\scripts\appverifier_ctest.py 
--build_directory .\aws-c-http\build\aws-c-http
 
   macos:
-    runs-on: macos-14 # latest
+    runs-on: macos-14
+    strategy:
+      fail-fast: false
+      matrix:
+        eventloop: ["kqueue", "dispatch_queue"]
     steps:
     - uses: aws-actions/configure-aws-credentials@v4
       with:
@@ -214,10 +218,10 @@
       run: |
         python3 -c "from urllib.request import urlretrieve; urlretrieve('${{ 
env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION 
}}/builder.pyz?run=${{ env.RUN }}', 'builder')"
         chmod a+x builder
-        ./builder build -p ${{ env.PACKAGE_NAME }}
+        ./builder build -p ${{ env.PACKAGE_NAME }} 
--cmake-extra=-DAWS_USE_APPLE_NETWORK_FRAMEWORK=${{ matrix.eventloop == 
'dispatch_queue' && 'ON' || 'OFF' }}
 
   macos-x64:
-    runs-on: macos-14-large # latest
+    runs-on: macos-14-large
     steps:
     - uses: aws-actions/configure-aws-credentials@v4
       with:
@@ -244,7 +248,11 @@
         python3 builder.pyz build -p aws-c-http 
--cmake-extra=-DENABLE_LOCALHOST_INTEGRATION_TESTS=ON --config Debug
 
   localhost-test-macos:
-    runs-on: macos-14 # latest
+    runs-on: macos-14
+    strategy:
+      fail-fast: false
+      matrix:
+        eventloop: ["kqueue", "dispatch_queue"]
     steps:
     - uses: aws-actions/configure-aws-credentials@v4
       with:
@@ -257,7 +265,7 @@
         python3 -m venv .venv
         source .venv/bin/activate
         python3 -c "from urllib.request import urlretrieve; urlretrieve('${{ 
env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION 
}}/builder.pyz?run=${{ env.RUN }}', 'builder.pyz')"
-        python3 builder.pyz build -p aws-c-http 
--cmake-extra=-DENABLE_LOCALHOST_INTEGRATION_TESTS=ON --config Debug
+        python3 builder.pyz build -p aws-c-http 
--cmake-extra=-DENABLE_LOCALHOST_INTEGRATION_TESTS=ON 
--cmake-extra=-DAWS_USE_APPLE_NETWORK_FRAMEWORK=${{ matrix.eventloop == 
'dispatch_queue' && 'ON' || 'OFF' }} --config Debug
 
   localhost-test-win:
     runs-on: windows-2022 # latest
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aws-c-http-0.9.5/source/connection.c 
new/aws-c-http-0.9.6/source/connection.c
--- old/aws-c-http-0.9.5/source/connection.c    2025-03-14 21:12:18.000000000 
+0100
+++ new/aws-c-http-0.9.6/source/connection.c    2025-03-28 22:24:03.000000000 
+0100
@@ -16,6 +16,7 @@
 #include <aws/common/string.h>
 #include <aws/http/request_response.h>
 #include <aws/io/channel_bootstrap.h>
+#include <aws/io/future.h>
 #include <aws/io/logging.h>
 #include <aws/io/socket.h>
 #include <aws/io/socket_channel_handler.h>
@@ -58,6 +59,7 @@
     aws_http_server_on_incoming_connection_fn *on_incoming_connection;
     aws_http_server_on_destroy_fn *on_destroy_complete;
     struct aws_socket *socket;
+    struct aws_future_void *setup_future;
 
     /* Any thread may touch this data, but the lock must be held */
     struct {
@@ -576,6 +578,7 @@
     }
     aws_hash_table_clean_up(&server->synced_data.channel_to_connection_map);
     aws_mutex_clean_up(&server->synced_data.lock);
+    aws_future_void_release(server->setup_future);
     aws_mem_release(server->alloc, server);
 }
 
@@ -621,6 +624,20 @@
     s_http_server_clean_up(server);
 }
 
+/* the server listener has finished setup. We released the socket if 
error_code is not 0. */
+static void s_server_bootstrap_on_server_listener_setup(
+    struct aws_server_bootstrap *bootstrap,
+    int error_code,
+    void *user_data) {
+    (void)bootstrap;
+    struct aws_http_server *server = user_data;
+    if (error_code) {
+        aws_future_void_set_error(server->setup_future, error_code);
+    } else {
+        aws_future_void_set_result(server->setup_future);
+    }
+}
+
 struct aws_http_server *aws_http_server_new(const struct 
aws_http_server_options *options) {
     aws_http_fatal_assert_library_initialized();
 
@@ -654,7 +671,7 @@
     if (err) {
         AWS_LOGF_ERROR(
             AWS_LS_HTTP_SERVER, "static: Failed to initialize mutex, error %d 
(%s).", err, aws_error_name(err));
-        goto mutex_error;
+        goto server_error;
     }
     err = aws_hash_table_init(
         &server->synced_data.channel_to_connection_map, server->alloc, 16, 
aws_hash_ptr, aws_ptr_eq, NULL, NULL);
@@ -664,7 +681,7 @@
             "static: Cannot create server, error %d (%s).",
             aws_last_error(),
             aws_error_name(aws_last_error()));
-        goto hash_table_error;
+        goto server_error;
     }
     /* Protect against callbacks firing before server->socket is set */
     s_server_lock_synced_data(server);
@@ -672,6 +689,8 @@
         server->is_using_tls = true;
     }
 
+    server->setup_future = aws_future_void_new(options->allocator);
+
     struct aws_server_socket_channel_bootstrap_options bootstrap_options = {
         .enable_read_back_pressure = options->manual_window_management,
         .tls_options = options->tls_options,
@@ -680,23 +699,38 @@
         .incoming_callback = s_server_bootstrap_on_accept_channel_setup,
         .shutdown_callback = s_server_bootstrap_on_accept_channel_shutdown,
         .destroy_callback = s_server_bootstrap_on_server_listener_destroy,
+        .setup_callback = s_server_bootstrap_on_server_listener_setup,
         .host_name = options->endpoint->address,
         .port = options->endpoint->port,
         .user_data = server,
     };
 
-    server->socket = 
aws_server_bootstrap_new_socket_listener(&bootstrap_options);
+    int listen_error = AWS_OP_SUCCESS;
 
+    /*
+     * WARNING & TODO!!!!
+     * aws_server_bootstrap_new_socket_listener has async callback, we would 
block here waiting for
+     * setup complete. aws-c-http library need to be updated with a proper 
async API.
+     */
+    server->socket = 
aws_server_bootstrap_new_socket_listener(&bootstrap_options);
+    // if server setup properly, waiting for setup callback
+    if (server->socket) {
+        aws_future_void_wait(server->setup_future, UINT64_MAX /*timeout*/);
+        listen_error = aws_future_void_get_error(server->setup_future);
+    } else {
+        listen_error = aws_last_error();
+    }
     s_server_unlock_synced_data(server);
 
-    if (!server->socket) {
+    if (listen_error) {
         AWS_LOGF_ERROR(
             AWS_LS_HTTP_SERVER,
             "static: Failed creating new socket listener, error %d (%s). 
Cannot create server.",
-            aws_last_error(),
-            aws_error_name(aws_last_error()));
+            listen_error,
+            aws_error_name(listen_error));
 
-        goto socket_error;
+        aws_raise_error(listen_error);
+        goto server_error;
     }
 
     AWS_LOGF_INFO(
@@ -708,12 +742,8 @@
 
     return server;
 
-socket_error:
-    aws_hash_table_clean_up(&server->synced_data.channel_to_connection_map);
-hash_table_error:
-    aws_mutex_clean_up(&server->synced_data.lock);
-mutex_error:
-    aws_mem_release(server->alloc, server);
+server_error:
+    s_http_server_clean_up(server);
     return NULL;
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aws-c-http-0.9.5/source/connection_manager.c 
new/aws-c-http-0.9.6/source/connection_manager.c
--- old/aws-c-http-0.9.5/source/connection_manager.c    2025-03-14 
21:12:18.000000000 +0100
+++ new/aws-c-http-0.9.6/source/connection_manager.c    2025-03-28 
22:24:03.000000000 +0100
@@ -1164,7 +1164,6 @@
 
     struct aws_http_connection_manager *manager = work->manager;
 
-    int representative_error = 0;
     size_t new_connection_failures = 0;
 
     /*
@@ -1202,8 +1201,6 @@
      */
     struct aws_array_list errors;
     AWS_ZERO_STRUCT(errors);
-    /* Even if we can't init this array, we still need to invoke error 
callbacks properly */
-    bool push_errors = false;
 
     if (work->new_connections > 0) {
         AWS_LOGF_INFO(
@@ -1211,20 +1208,21 @@
             "id=%p: Requesting %zu new connections from http",
             (void *)manager,
             work->new_connections);
-        push_errors = aws_array_list_init_dynamic(&errors, work->allocator, 
work->new_connections, sizeof(int)) ==
-                      AWS_ERROR_SUCCESS;
+        AWS_FATAL_ASSERT(
+            aws_array_list_init_dynamic(&errors, work->allocator, 
work->new_connections, sizeof(int)) ==
+            AWS_OP_SUCCESS);
     }
 
     for (size_t i = 0; i < work->new_connections; ++i) {
         if (s_aws_http_connection_manager_new_connection(manager)) {
             ++new_connection_failures;
-            representative_error = aws_last_error();
-            if (push_errors) {
-                AWS_FATAL_ASSERT(aws_array_list_push_back(&errors, 
&representative_error) == AWS_OP_SUCCESS);
-            }
+            int error = aws_last_error();
+            AWS_FATAL_ASSERT(aws_array_list_push_back(&errors, &error) == 
AWS_OP_SUCCESS);
         }
     }
 
+    bool has_pending_acquisitions = false;
+    struct aws_connection_management_transaction pending_acquisitions_work;
     if (new_connection_failures > 0) {
         /*
          * We failed and aren't going to receive a callback, but the current 
state assumes we will receive
@@ -1235,30 +1233,24 @@
         AWS_FATAL_ASSERT(manager->internal_ref[AWS_HCMCT_PENDING_CONNECTIONS] 
>= new_connection_failures);
         s_connection_manager_internal_ref_decrease(manager, 
AWS_HCMCT_PENDING_CONNECTIONS, new_connection_failures);
 
-        /*
-         * Rather than failing one acquisition for each connection failure, if 
there's at least one
-         * connection failure, we instead fail all excess acquisitions, since 
there's no pending
-         * connect that will necessarily resolve them.
-         *
-         * Try to correspond an error with the acquisition failure, but as a 
fallback just use the
-         * representative error.
-         */
-        size_t i = 0;
-        while (manager->pending_acquisition_count > 
manager->internal_ref[AWS_HCMCT_PENDING_CONNECTIONS]) {
-            int error = representative_error;
-            if (i < aws_array_list_length(&errors)) {
-                aws_array_list_get_at(&errors, &error, i);
-            }
-
+        for (size_t i = 0; i < new_connection_failures && 
manager->pending_acquisition_count > 0; i++) {
+            int error;
+            aws_array_list_get_at(&errors, &error, i);
             AWS_LOGF_DEBUG(
                 AWS_LS_HTTP_CONNECTION_MANAGER,
-                "id=%p: Failing excess connection acquisition with error code 
%d",
+                "id=%p: Failing connection acquisition with error code %d",
                 (void *)manager,
                 (int)error);
             s_aws_http_connection_manager_move_front_acquisition(manager, 
NULL, error, &work->completions);
-            ++i;
         }
-
+        has_pending_acquisitions =
+            manager->internal_ref[AWS_HCMCT_PENDING_CONNECTIONS] + 
manager->pending_settings_count <
+            manager->pending_acquisition_count;
+        if (has_pending_acquisitions) {
+            /* If there are pending acquisitions, schedule work again to try 
acquiring them */
+            
s_aws_connection_management_transaction_init(&pending_acquisitions_work, 
manager);
+            
s_aws_http_connection_manager_build_transaction(&pending_acquisitions_work);
+        }
         aws_mutex_unlock(&manager->lock);
     }
 
@@ -1266,13 +1258,20 @@
      * Step 4 - Perform acquisition callbacks
      */
     s_aws_http_connection_manager_complete_acquisitions(&work->completions, 
work->allocator);
-
     aws_array_list_clean_up(&errors);
 
     /*
      * Step 5 - Clean up work.  Do this here rather than at the end of every 
caller. Destroy the manager if necessary
      */
     s_aws_connection_management_transaction_clean_up(work);
+
+    /*
+     * Step 6 - If some connection acquisition requests failed and we still 
have more pending acquisitions, try to
+     * acquire them.
+     */
+    if (has_pending_acquisitions) {
+        
s_aws_http_connection_manager_execute_transaction(&pending_acquisitions_work);
+    }
 }
 
 void aws_http_connection_manager_acquire_connection(
@@ -1479,12 +1478,11 @@
             work->connection_to_release = connection;
         }
     } else {
-        /* fail acquisition as one connection cannot be used any more */
-        while (manager->pending_acquisition_count >
-               manager->internal_ref[AWS_HCMCT_PENDING_CONNECTIONS] + 
manager->pending_settings_count) {
+        if (manager->pending_acquisition_count > 0) {
+            /* fail acquisition as connection acquire failed */
             AWS_LOGF_DEBUG(
                 AWS_LS_HTTP_CONNECTION_MANAGER,
-                "id=%p: Failing excess connection acquisition with error code 
%d",
+                "id=%p: Failing connection acquisition with error code %d",
                 (void *)manager,
                 (int)error_code);
             s_aws_http_connection_manager_move_front_acquisition(manager, 
NULL, error_code, &work->completions);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aws-c-http-0.9.5/source/h1_decoder.c 
new/aws-c-http-0.9.6/source/h1_decoder.c
--- old/aws-c-http-0.9.5/source/h1_decoder.c    2025-03-14 21:12:18.000000000 
+0100
+++ new/aws-c-http-0.9.6/source/h1_decoder.c    2025-03-28 22:24:03.000000000 
+0100
@@ -39,6 +39,8 @@
     bool is_done;
     bool body_headers_ignored;
     bool body_headers_forbidden;
+    bool content_length_received;
+
     enum aws_http_header_block header_block;
     const void *logging_id;
 
@@ -214,6 +216,7 @@
     decoder->is_done = false;
     decoder->body_headers_ignored = false;
     decoder->body_headers_forbidden = false;
+    decoder->content_length_received = false;
     /* set to normal by default */
     decoder->header_block = AWS_HTTP_HEADER_BLOCK_MAIN;
 }
@@ -411,6 +414,14 @@
 
     switch (header.name) {
         case AWS_HTTP_HEADER_CONTENT_LENGTH:
+            if (decoder->content_length_received) {
+                AWS_LOGF_ERROR(
+                    AWS_LS_HTTP_STREAM,
+                    "id=%p: Multiple incoming headers for content-length 
received. This is illegal.",
+                    decoder->logging_id);
+                return aws_raise_error(AWS_ERROR_HTTP_PROTOCOL_ERROR);
+            }
+
             if (decoder->transfer_encoding) {
                 AWS_LOGF_ERROR(
                     AWS_LS_HTTP_STREAM,
@@ -441,10 +452,11 @@
                 return aws_raise_error(AWS_ERROR_HTTP_PROTOCOL_ERROR);
             }
 
+            decoder->content_length_received = true;
             break;
 
         case AWS_HTTP_HEADER_TRANSFER_ENCODING: {
-            if (decoder->content_length) {
+            if (decoder->content_length_received) {
                 AWS_LOGF_ERROR(
                     AWS_LS_HTTP_STREAM,
                     "id=%p: Incoming headers for both content-length and 
transfer-encoding received. This is illegal.",
@@ -469,7 +481,23 @@
             AWS_ZERO_STRUCT(split);
             while (aws_byte_cursor_next_split(&header.value_data, ',', 
&split)) {
                 struct aws_byte_cursor coding = 
aws_strutil_trim_http_whitespace(split);
-                int prev_flags = decoder->transfer_encoding;
+
+                /* A sender MUST NOT apply chunked more than once to a message 
body.
+                 * If any transfer coding other than chunked is applied to a 
request payload body, the sender MUST
+                 * apply chunked as the final transfer coding to ensure that 
the message is properly framed.
+                 * RFC-7230 3.3.1 */
+                if (decoder->transfer_encoding & 
AWS_HTTP_TRANSFER_ENCODING_CHUNKED) {
+                    AWS_LOGF_ERROR(
+                        AWS_LS_HTTP_STREAM,
+                        "id=%p: Incoming transfer-encoding header lists a 
coding after 'chunked', this is illegal.",
+                        decoder->logging_id);
+                    AWS_LOGF_DEBUG(
+                        AWS_LS_HTTP_STREAM,
+                        "id=%p: Misplaced coding is '" PRInSTR "'",
+                        decoder->logging_id,
+                        AWS_BYTE_CURSOR_PRI(coding));
+                    return aws_raise_error(AWS_ERROR_HTTP_PROTOCOL_ERROR);
+                }
 
                 if 
(aws_string_eq_byte_cursor_ignore_case(s_transfer_coding_chunked, &coding)) {
                     decoder->transfer_encoding |= 
AWS_HTTP_TRANSFER_ENCODING_CHUNKED;
@@ -500,21 +528,11 @@
                         decoder->logging_id,
                         AWS_BYTE_CURSOR_PRI(coding));
                     return aws_raise_error(AWS_ERROR_HTTP_PROTOCOL_ERROR);
-                }
-
-                /* If any transfer coding other than chunked is applied to a 
request payload body, the sender MUST
-                 * apply chunked as the final transfer coding to ensure that 
the message is properly framed.
-                 * RFC-7230 3.3.1 */
-                if ((prev_flags & AWS_HTTP_TRANSFER_ENCODING_CHUNKED) && 
(decoder->transfer_encoding != prev_flags)) {
+                } else {
                     AWS_LOGF_ERROR(
                         AWS_LS_HTTP_STREAM,
-                        "id=%p: Incoming transfer-encoding header lists a 
coding after 'chunked', this is illegal.",
+                        "id=%p: Incoming transfer-encoding header has invalid 
blank entry.",
                         decoder->logging_id);
-                    AWS_LOGF_DEBUG(
-                        AWS_LS_HTTP_STREAM,
-                        "id=%p: Misplaced coding is '" PRInSTR "'",
-                        decoder->logging_id,
-                        AWS_BYTE_CURSOR_PRI(coding));
                     return aws_raise_error(AWS_ERROR_HTTP_PROTOCOL_ERROR);
                 }
             }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aws-c-http-0.9.5/tests/CMakeLists.txt 
new/aws-c-http-0.9.6/tests/CMakeLists.txt
--- old/aws-c-http-0.9.5/tests/CMakeLists.txt   2025-03-14 21:12:18.000000000 
+0100
+++ new/aws-c-http-0.9.6/tests/CMakeLists.txt   2025-03-28 22:24:03.000000000 
+0100
@@ -529,6 +529,8 @@
 add_net_test_case(connection_manager_acquire_release_mix_synchronous)
 add_net_test_case(connection_manager_acquisition_timeout)
 add_net_test_case(connection_manager_connect_callback_failure)
+add_net_test_case(test_connection_manager_connect_callback_async_failure)
+add_net_test_case(test_connection_manager_connect_callback_async_with_immediate_failure)
 add_net_test_case(connection_manager_connect_immediate_failure)
 add_net_test_case(connection_manager_proxy_setup_shutdown)
 add_net_test_case(connection_manager_idle_culling_single)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aws-c-http-0.9.5/tests/test_connection_manager.c 
new/aws-c-http-0.9.6/tests/test_connection_manager.c
--- old/aws-c-http-0.9.5/tests/test_connection_manager.c        2025-03-14 
21:12:18.000000000 +0100
+++ new/aws-c-http-0.9.6/tests/test_connection_manager.c        2025-03-28 
22:24:03.000000000 +0100
@@ -819,7 +819,7 @@
     connection_manager_max_pending_acquisitions_with_vended_connections,
     
s_test_connection_manager_max_pending_acquisitions_with_vended_connections);
 
-static int s_aws_http_connection_manager_create_connection_sync_mock(
+static int s_aws_http_connection_manager_create_connection_validate(
     const struct aws_http_client_connection_options *options) {
     struct cm_tester *tester = &s_tester;
 
@@ -830,8 +830,6 @@
         ASSERT_TRUE(aws_byte_cursor_eq_c_str(&interface_name, 
options->socket_options->network_interface_name));
     }
 
-    size_t next_connection_id = 
aws_atomic_fetch_add(&tester->next_connection_id, 1);
-
     ASSERT_SUCCESS(aws_mutex_lock(&tester->lock));
     tester->release_connection_fn = options->on_shutdown;
     ASSERT_SUCCESS(aws_mutex_unlock(&tester->lock));
@@ -847,7 +845,15 @@
         ASSERT_UINT_EQUALS(options->proxy_options->connection_type, 
tester->verify_proxy_options->connection_type);
     }
 
+    return AWS_OP_SUCCESS;
+}
+static int s_aws_http_connection_manager_create_connection_sync_mock(
+    const struct aws_http_client_connection_options *options) {
+    s_aws_http_connection_manager_create_connection_validate(options);
+    struct cm_tester *tester = &s_tester;
+
     struct mock_connection *connection = NULL;
+    size_t next_connection_id = 
aws_atomic_fetch_add(&tester->next_connection_id, 1);
 
     if (next_connection_id < aws_array_list_length(&tester->mock_connections)) 
{
         aws_array_list_get_at(&tester->mock_connections, &connection, 
next_connection_id);
@@ -868,6 +874,63 @@
     return aws_raise_error(AWS_ERROR_HTTP_UNKNOWN);
 }
 
+struct connect_task_args {
+    void *user_data;
+    struct mock_connection *connection;
+    aws_http_on_client_connection_setup_fn *on_setup;
+};
+
+static void s_aws_http_connection_manager_connect_task(
+    struct aws_task *task,
+    void *user_data,
+    enum aws_task_status status) {
+    (void)status;
+    struct cm_tester *tester = &s_tester;
+
+    struct connect_task_args *task_args = user_data;
+    struct mock_connection *connection = task_args->connection;
+    if (connection) {
+        if (connection->result == AWS_NCRT_SUCCESS) {
+            task_args->on_setup((struct aws_http_connection *)connection, 
AWS_ERROR_SUCCESS, task_args->user_data);
+        } else if (connection->result == AWS_NCRT_ERROR_VIA_CALLBACK) {
+            task_args->on_setup(NULL, AWS_ERROR_HTTP_UNKNOWN, 
task_args->user_data);
+        } else {
+            AWS_FATAL_ASSERT(0 && "Unexpected connection->result");
+        }
+    }
+
+    aws_mem_release(tester->allocator, task);
+    aws_mem_release(tester->allocator, task_args);
+}
+
+static int s_aws_http_connection_manager_connect_async_mock(const struct 
aws_http_client_connection_options *options) {
+    s_aws_http_connection_manager_create_connection_validate(options);
+    struct cm_tester *tester = &s_tester;
+
+    struct mock_connection *connection = NULL;
+    size_t next_connection_id = 
aws_atomic_fetch_add(&tester->next_connection_id, 1);
+    if (next_connection_id < aws_array_list_length(&tester->mock_connections)) 
{
+        aws_array_list_get_at(&tester->mock_connections, &connection, 
next_connection_id);
+    }
+
+    if (connection->result == AWS_NCRT_ERROR_FROM_CREATE) {
+        return aws_raise_error(AWS_ERROR_HTTP_UNKNOWN);
+    }
+
+    struct aws_task *task = aws_mem_calloc(options->allocator, 1, 
sizeof(struct aws_task));
+    struct connect_task_args *task_args = aws_mem_calloc(options->allocator, 
1, sizeof(struct connect_task_args));
+    task_args->connection = connection;
+    task_args->user_data = options->user_data;
+    task_args->on_setup = options->on_setup;
+    aws_task_init(task, s_aws_http_connection_manager_connect_task, task_args, 
"create_connection_task");
+
+    struct aws_event_loop *event_loop = 
aws_event_loop_group_get_next_loop(tester->event_loop_group);
+    uint64_t now;
+    ASSERT_SUCCESS(aws_event_loop_current_clock_time(event_loop, &now));
+    aws_event_loop_schedule_task_future(event_loop, task, now + 1000000000);
+    return AWS_OP_SUCCESS;
+}
+
 static void s_aws_http_connection_manager_release_connection_sync_mock(struct 
aws_http_connection *connection) {
     (void)connection;
 
@@ -920,6 +983,17 @@
     .aws_http_connection_get_version = 
s_aws_http_connection_manager_connection_get_version_sync_mock,
 };
 
+static struct aws_http_connection_manager_system_vtable s_async_connect_mock = 
{
+    .aws_http_client_connect = 
s_aws_http_connection_manager_connect_async_mock,
+    .aws_http_connection_release = 
s_aws_http_connection_manager_release_connection_sync_mock,
+    .aws_http_connection_close = 
s_aws_http_connection_manager_close_connection_sync_mock,
+    .aws_http_connection_new_requests_allowed = 
s_aws_http_connection_manager_is_connection_available_sync_mock,
+    .aws_high_res_clock_get_ticks = aws_high_res_clock_get_ticks,
+    .aws_http_connection_get_channel = 
s_aws_http_connection_manager_connection_get_channel_sync_mock,
+    .aws_channel_thread_is_callers_thread = 
s_aws_http_connection_manager_is_callers_thread_sync_mock,
+    .aws_http_connection_get_version = 
s_aws_http_connection_manager_connection_get_version_sync_mock,
+};
+
 static int s_test_connection_manager_with_network_interface_list(struct 
aws_allocator *allocator, void *ctx) {
     (void)ctx;
     struct aws_byte_cursor *interface_names_array = aws_mem_calloc(allocator, 
3, sizeof(struct aws_byte_cursor));
@@ -1055,6 +1129,68 @@
 }
 AWS_TEST_CASE(connection_manager_connect_callback_failure, 
s_test_connection_manager_connect_callback_failure);
 
+static int s_test_connection_manager_connect_callback_async_failure(struct 
aws_allocator *allocator, void *ctx) {
+    (void)ctx;
+    int error_connections = 5;
+    int success_connections = 5;
+    struct cm_tester_options options = {
+        .allocator = allocator,
+        .max_connections = error_connections,
+        .mock_table = &s_async_connect_mock,
+    };
+
+    ASSERT_SUCCESS(s_cm_tester_init(&options));
+
+    s_add_mock_connections(error_connections, AWS_NCRT_ERROR_VIA_CALLBACK, 
false);
+    s_add_mock_connections(success_connections, AWS_NCRT_SUCCESS, true);
+
+    s_acquire_connections(error_connections + success_connections);
+
+    ASSERT_SUCCESS(s_wait_on_connection_reply_count(error_connections + 
success_connections));
+
+    ASSERT_UINT_EQUALS(s_tester.connection_errors, error_connections);
+    ASSERT_SUCCESS(s_release_connections(success_connections, false));
+
+    ASSERT_SUCCESS(s_cm_tester_clean_up());
+
+    return AWS_OP_SUCCESS;
+}
+AWS_TEST_CASE(
+    test_connection_manager_connect_callback_async_failure,
+    s_test_connection_manager_connect_callback_async_failure);
+
+static int 
s_test_connection_manager_connect_callback_async_with_immediate_failure(
+    struct aws_allocator *allocator,
+    void *ctx) {
+    (void)ctx;
+    int error_connections = 5;
+    int success_connections = 5;
+    struct cm_tester_options options = {
+        .allocator = allocator,
+        .max_connections = error_connections + success_connections,
+        .mock_table = &s_async_connect_mock,
+    };
+
+    ASSERT_SUCCESS(s_cm_tester_init(&options));
+
+    s_add_mock_connections(success_connections, AWS_NCRT_SUCCESS, true);
+    s_add_mock_connections(error_connections, AWS_NCRT_ERROR_VIA_CALLBACK, 
false);
+
+    s_acquire_connections(error_connections + success_connections);
+
+    ASSERT_SUCCESS(s_wait_on_connection_reply_count(error_connections + 
success_connections));
+
+    ASSERT_UINT_EQUALS(s_tester.connection_errors, error_connections);
+    ASSERT_SUCCESS(s_release_connections(success_connections, false));
+
+    ASSERT_SUCCESS(s_cm_tester_clean_up());
+
+    return AWS_OP_SUCCESS;
+}
+AWS_TEST_CASE(
+    test_connection_manager_connect_callback_async_with_immediate_failure,
+    s_test_connection_manager_connect_callback_async_with_immediate_failure);
+
 static int s_test_connection_manager_connect_immediate_failure(struct 
aws_allocator *allocator, void *ctx) {
     (void)ctx;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aws-c-http-0.9.5/tests/test_h1_decoder.c 
new/aws-c-http-0.9.6/tests/test_h1_decoder.c
--- old/aws-c-http-0.9.5/tests/test_h1_decoder.c        2025-03-14 
21:12:18.000000000 +0100
+++ new/aws-c-http-0.9.6/tests/test_h1_decoder.c        2025-03-28 
22:24:03.000000000 +0100
@@ -340,18 +340,13 @@
     struct aws_byte_cursor msg = 
AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("HTTP/1.1 200 OK\r\n"
                                                                        
"Server: some-server\r\n"
                                                                        
"Transfer-Encoding: compress\r\n"
-                                                                       
"Transfer-Encoding: gzip, ,deflate\r\n"
+                                                                       
"Transfer-Encoding: gzip,deflate\r\n"
                                                                        
"Transfer-Encoding: chunked\r\n"
-                                                                       
"Transfer-Encoding:\r\n"
-                                                                       "\r\n"
-                                                                       "Hello 
noob.");
+                                                                       "\r\n");
     struct aws_h1_decoder_params params;
     s_common_decoder_setup(allocator, 1024, &params, s_response, NULL);
     struct aws_h1_decoder *decoder = aws_h1_decoder_new(&params);
 
-    /* Not a valid HTTP1.1 message, but not the job of decoder to return error 
here. */
-    /* Instead, the user should know their buffer has been processed without 
returning any body data, and
-     * report the error in user-space. */
     ASSERT_SUCCESS(aws_h1_decode(decoder, &msg));
     int flags = aws_h1_decoder_get_encoding_flags(decoder);
     ASSERT_INT_EQUALS(
@@ -614,6 +609,17 @@
                                               "Transfer-Encoding: gzip\r\n"
                                               "\r\n"),
 
+        /* A sender MUST NOT apply chunked more than once to a message body */
+        AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("GET / HTTP/1.1\r\n"
+                                              "Transfer-Encoding: chunked, 
chunked\r\n"
+                                              "\r\n"),
+
+        /* A sender MUST NOT apply chunked more than once to a message body, 
p2 */
+        AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("GET / HTTP/1.1\r\n"
+                                              "Transfer-Encoding: chunked,\r\n"
+                                              "Transfer-Encoding: chunked\r\n"
+                                              "\r\n"),
+
         /* Invalid hex-int as chunk size. */
         AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("GET / HTTP/1.1\r\n"
                                               "Transfer-Encoding: chunked\r\n"
@@ -651,6 +657,28 @@
         AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("GET / HTTP/1.1\r\n"
                                               "Transfer-Encoding: 
shrinkydinky, chunked\r\n"),
 
+        /* Transfer coding cannot be blank (empty header value) */
+        AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("GET / HTTP/1.1\r\n"
+                                              "Transfer-Encoding: \r\n"
+                                              "Transfer-Encoding: 
chunked\r\n"),
+
+        /* Transfer coding cannot be blank (empty item in list) */
+        AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("GET / HTTP/1.1\r\n"
+                                              "Transfer-Encoding: gzip, 
,chunked\r\n"),
+
+        /* Transfer coding cannot be blank (empty item at start of list) */
+        AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("GET / HTTP/1.1\r\n"
+                                              "Transfer-Encoding: 
,chunked\r\n"),
+
+        /* Transfer coding cannot be blank (empty item at end of list) */
+        AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("GET / HTTP/1.1\r\n"
+                                              "Transfer-Encoding: 
chunked,\r\n"),
+
+        /* Transfer coding cannot be blank (empty header value) */
+        AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("GET / HTTP/1.1\r\n"
+                                              "Transfer-Encoding: \r\n"
+                                              "Transfer-Encoding: 
chunked\r\n"),
+
         /* My chunk size is too big */
         AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("GET / HTTP/1.1\r\n"
                                               "Transfer-Encoding: chunked\r\n"
@@ -665,11 +693,21 @@
         AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("POST / HTTP/1.1\r\n"
                                               "Content-Length:\r\n"),
 
-        /* Has both content-Length and transfer-encoding */
+        /* Has both content-length and transfer-encoding */
         AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("POST / HTTP/1.1\r\n"
-                                              "Content-Length: 999\r\n"
+                                              "Content-Length: 0\r\n"
                                               "Transfer-Encoding: 
chunked\r\n"),
 
+        /* Has both transfer-encoding and content-length (but with 
transfer-encoding first this time) */
+        AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("POST / HTTP/1.1\r\n"
+                                              "Transfer-Encoding: chunked\r\n"
+                                              "Content-Length: 0\r\n"),
+
+        /* Multiple content-length headers */
+        AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("POST / HTTP/1.1\r\n"
+                                              "Content-Length: 0\r\n"
+                                              "Content-Length: 0\r\n"
+                                              "\r\n"),
         /* Header is missing colon */
         AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("GET / HTTP/1.1\r\n"
                                               "Header-Missing-Colon yes it 
is\r\n"
@@ -744,12 +782,16 @@
         s_common_decoder_setup(allocator, 1024, &params, s_request, NULL);
         struct aws_h1_decoder *decoder = aws_h1_decoder_new(&params);
 
+        aws_reset_error();
+
         ASSERT_FAILS(
             aws_h1_decode(decoder, &request),
             "Entry [%zu] should have failed, but it passed:\n------\n" PRInSTR 
"\n------\n",
             iter,
             AWS_BYTE_CURSOR_PRI(requests[iter]));
 
+        ASSERT_INT_EQUALS(AWS_ERROR_HTTP_PROTOCOL_ERROR, aws_last_error());
+
         aws_h1_decoder_destroy(decoder);
     }
 

Reply via email to