aws-crt 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/VERSION +1 -1
- data/aws-crt-ffi/CMakeLists.txt +49 -41
- data/aws-crt-ffi/crt/aws-c-auth/CMakeLists.txt +0 -10
- data/aws-crt-ffi/crt/aws-c-auth/include/aws/auth/credentials.h +3 -2
- data/aws-crt-ffi/crt/aws-c-auth/include/aws/auth/private/credentials_utils.h +4 -4
- data/aws-crt-ffi/crt/aws-c-auth/source/auth.c +1 -14
- data/aws-crt-ffi/crt/aws-c-auth/source/aws_imds_client.c +206 -68
- data/aws-crt-ffi/crt/aws-c-auth/source/aws_signing.c +5 -0
- data/aws-crt-ffi/crt/aws-c-auth/source/credentials_provider_cached.c +6 -6
- data/aws-crt-ffi/crt/aws-c-auth/source/credentials_provider_default_chain.c +16 -1
- data/aws-crt-ffi/crt/aws-c-auth/source/credentials_provider_ecs.c +0 -1
- data/aws-crt-ffi/crt/aws-c-auth/source/credentials_provider_process.c +0 -1
- data/aws-crt-ffi/crt/aws-c-auth/source/credentials_provider_sts_web_identity.c +0 -1
- data/aws-crt-ffi/crt/aws-c-auth/source/credentials_provider_x509.c +10 -7
- data/aws-crt-ffi/crt/aws-c-auth/source/credentials_utils.c +35 -26
- data/aws-crt-ffi/crt/aws-c-auth/source/signable_chunk.c +3 -2
- data/aws-crt-ffi/crt/aws-c-auth/tests/CMakeLists.txt +3 -2
- data/aws-crt-ffi/crt/aws-c-auth/tests/aws_imds_client_test.c +1 -0
- data/aws-crt-ffi/crt/aws-c-auth/tests/credentials_provider_ecs_tests.c +3 -0
- data/aws-crt-ffi/crt/aws-c-auth/tests/credentials_provider_process_tests.c +65 -16
- data/aws-crt-ffi/crt/aws-c-auth/tests/credentials_tests.c +125 -0
- data/aws-crt-ffi/crt/aws-c-auth/tests/sigv4_signing_tests.c +68 -46
- data/aws-crt-ffi/crt/aws-c-cal/CMakeLists.txt +8 -3
- data/aws-crt-ffi/crt/aws-c-cal/bin/run_x_platform_fuzz_corpus/main.c +9 -0
- data/aws-crt-ffi/crt/aws-c-cal/builder.json +11 -3
- data/aws-crt-ffi/crt/aws-c-cal/cmake/aws-c-cal-config.cmake +14 -5
- data/aws-crt-ffi/crt/aws-c-cal/source/darwin/securityframework_ecc.c +6 -6
- data/aws-crt-ffi/crt/aws-c-cal/source/windows/bcrypt_ecc.c +12 -12
- data/aws-crt-ffi/crt/aws-c-cal/tests/test_case_helper.h +14 -14
- data/aws-crt-ffi/crt/aws-c-common/CMakeLists.txt +21 -1
- data/aws-crt-ffi/crt/aws-c-common/README.md +8 -0
- data/aws-crt-ffi/crt/aws-c-common/cmake/AwsCFlags.cmake +20 -5
- data/aws-crt-ffi/crt/aws-c-common/cmake/AwsFeatureTests.cmake +7 -1
- data/aws-crt-ffi/crt/aws-c-common/format-check.sh +1 -1
- data/aws-crt-ffi/crt/aws-c-common/include/aws/common/byte_buf.h +14 -0
- data/aws-crt-ffi/crt/aws-c-common/include/aws/common/config.h.in +1 -0
- data/aws-crt-ffi/crt/{aws-c-auth/include/aws/auth → aws-c-common/include/aws/common}/external/cJSON.h +82 -74
- data/aws-crt-ffi/crt/aws-c-common/include/aws/common/json.h +335 -0
- data/aws-crt-ffi/crt/aws-c-common/include/aws/common/logging.h +1 -0
- data/aws-crt-ffi/crt/aws-c-common/include/aws/common/math.inl +2 -2
- data/aws-crt-ffi/crt/aws-c-common/include/aws/common/private/json_impl.h +22 -0
- data/aws-crt-ffi/crt/aws-c-common/include/aws/testing/aws_test_harness.h +2 -0
- data/aws-crt-ffi/crt/aws-c-common/source/byte_buf.c +36 -0
- data/aws-crt-ffi/crt/aws-c-common/source/common.c +5 -2
- data/aws-crt-ffi/crt/aws-c-common/source/external/cJSON.c +3113 -0
- data/aws-crt-ffi/crt/aws-c-common/source/file.c +9 -0
- data/aws-crt-ffi/crt/aws-c-common/source/json.c +348 -0
- data/aws-crt-ffi/crt/aws-c-common/source/logging.c +7 -2
- data/aws-crt-ffi/crt/aws-c-common/source/posix/system_info.c +8 -0
- data/aws-crt-ffi/crt/aws-c-common/source/ref_count.c +3 -1
- data/aws-crt-ffi/crt/aws-c-common/source/windows/file.c +47 -0
- data/aws-crt-ffi/crt/aws-c-common/source/windows/system_info.c +2 -1
- data/aws-crt-ffi/crt/aws-c-common/tests/CMakeLists.txt +5 -0
- data/aws-crt-ffi/crt/aws-c-common/tests/byte_buf_test.c +69 -0
- data/aws-crt-ffi/crt/aws-c-common/tests/json_test.c +134 -0
- data/aws-crt-ffi/crt/aws-c-common/tests/memtrace_test.c +6 -2
- data/aws-crt-ffi/crt/aws-c-event-stream/README.md +18 -35
- data/aws-crt-ffi/crt/aws-c-event-stream/include/aws/event-stream/event_stream.h +21 -2
- data/aws-crt-ffi/crt/aws-c-event-stream/include/aws/event-stream/event_stream_rpc_client.h +14 -2
- data/aws-crt-ffi/crt/aws-c-event-stream/include/aws/event-stream/event_stream_rpc_server.h +13 -0
- data/aws-crt-ffi/crt/aws-c-event-stream/include/aws/event-stream/private/event_stream_rpc_priv.h +7 -7
- data/aws-crt-ffi/crt/aws-c-event-stream/source/event_stream.c +257 -141
- data/aws-crt-ffi/crt/aws-c-event-stream/source/event_stream_channel_handler.c +1 -1
- data/aws-crt-ffi/crt/aws-c-event-stream/source/event_stream_rpc_client.c +31 -8
- data/aws-crt-ffi/crt/aws-c-event-stream/source/event_stream_rpc_server.c +63 -10
- data/aws-crt-ffi/crt/aws-c-event-stream/tests/CMakeLists.txt +2 -0
- data/aws-crt-ffi/crt/aws-c-event-stream/tests/event_stream_rpc_client_connection_test.c +157 -106
- data/aws-crt-ffi/crt/aws-c-event-stream/tests/event_stream_rpc_server_connection_test.c +168 -1
- data/aws-crt-ffi/crt/aws-c-event-stream/tests/message_deserializer_test.c +4 -2
- data/aws-crt-ffi/crt/aws-c-http/CMakeLists.txt +1 -0
- data/aws-crt-ffi/crt/aws-c-http/README.md +8 -0
- data/aws-crt-ffi/crt/aws-c-http/bin/elasticurl/main.c +1 -1
- data/aws-crt-ffi/crt/aws-c-http/builder.json +4 -3
- data/aws-crt-ffi/crt/aws-c-http/include/aws/http/connection.h +8 -1
- data/aws-crt-ffi/crt/aws-c-http/include/aws/http/connection_manager.h +45 -1
- data/aws-crt-ffi/crt/aws-c-http/include/aws/http/http2_stream_manager.h +63 -12
- data/aws-crt-ffi/crt/aws-c-http/include/aws/http/private/connection_impl.h +2 -1
- data/aws-crt-ffi/crt/aws-c-http/include/aws/http/private/h2_connection.h +20 -2
- data/aws-crt-ffi/crt/aws-c-http/include/aws/http/private/h2_frames.h +1 -0
- data/aws-crt-ffi/crt/aws-c-http/include/aws/http/private/h2_stream.h +42 -13
- data/aws-crt-ffi/crt/aws-c-http/include/aws/http/private/http2_stream_manager_impl.h +17 -0
- data/aws-crt-ffi/crt/aws-c-http/include/aws/http/private/http_impl.h +3 -0
- data/aws-crt-ffi/crt/aws-c-http/include/aws/http/private/random_access_set.h +10 -3
- data/aws-crt-ffi/crt/aws-c-http/include/aws/http/private/request_response_impl.h +3 -17
- data/aws-crt-ffi/crt/aws-c-http/include/aws/http/request_response.h +108 -4
- data/aws-crt-ffi/crt/aws-c-http/include/aws/http/statistics.h +22 -0
- data/aws-crt-ffi/crt/aws-c-http/source/connection.c +8 -3
- data/aws-crt-ffi/crt/aws-c-http/source/connection_manager.c +22 -3
- data/aws-crt-ffi/crt/aws-c-http/source/connection_monitor.c +32 -14
- data/aws-crt-ffi/crt/aws-c-http/source/h1_connection.c +14 -0
- data/aws-crt-ffi/crt/aws-c-http/source/h1_encoder.c +7 -4
- data/aws-crt-ffi/crt/aws-c-http/source/h2_connection.c +161 -45
- data/aws-crt-ffi/crt/aws-c-http/source/h2_decoder.c +37 -8
- data/aws-crt-ffi/crt/aws-c-http/source/h2_frames.c +13 -1
- data/aws-crt-ffi/crt/aws-c-http/source/h2_stream.c +345 -87
- data/aws-crt-ffi/crt/aws-c-http/source/hpack.c +3 -0
- data/aws-crt-ffi/crt/aws-c-http/source/http.c +3 -0
- data/aws-crt-ffi/crt/aws-c-http/source/http2_stream_manager.c +266 -39
- data/aws-crt-ffi/crt/aws-c-http/source/random_access_set.c +9 -3
- data/aws-crt-ffi/crt/aws-c-http/source/request_response.c +80 -20
- data/aws-crt-ffi/crt/aws-c-http/source/statistics.c +11 -0
- data/aws-crt-ffi/crt/aws-c-http/tests/CMakeLists.txt +28 -1
- data/aws-crt-ffi/crt/aws-c-http/tests/fuzz/fuzz_h2_decoder_correct.c +5 -3
- data/aws-crt-ffi/crt/aws-c-http/tests/h2_test_helper.c +133 -29
- data/aws-crt-ffi/crt/aws-c-http/tests/h2_test_helper.h +6 -0
- data/aws-crt-ffi/crt/aws-c-http/tests/py_localhost/README.md +40 -0
- data/aws-crt-ffi/crt/aws-c-http/tests/py_localhost/non_tls_server.py +56 -0
- data/aws-crt-ffi/crt/aws-c-http/tests/py_localhost/server.py +329 -0
- data/aws-crt-ffi/crt/aws-c-http/tests/test_connection_manager.c +1 -1
- data/aws-crt-ffi/crt/aws-c-http/tests/test_connection_monitor.c +2 -2
- data/aws-crt-ffi/crt/aws-c-http/tests/test_h1_client.c +47 -34
- data/aws-crt-ffi/crt/aws-c-http/tests/test_h1_encoder.c +4 -4
- data/aws-crt-ffi/crt/aws-c-http/tests/test_h1_server.c +15 -12
- data/aws-crt-ffi/crt/aws-c-http/tests/test_h2_client.c +582 -25
- data/aws-crt-ffi/crt/aws-c-http/tests/test_h2_encoder.c +3 -3
- data/aws-crt-ffi/crt/aws-c-http/tests/test_localhost_integ.c +530 -0
- data/aws-crt-ffi/crt/aws-c-http/tests/test_stream_manager.c +459 -67
- data/aws-crt-ffi/crt/aws-c-io/CMakeLists.txt +4 -0
- data/aws-crt-ffi/crt/aws-c-io/builder.json +3 -2
- data/aws-crt-ffi/crt/aws-c-io/include/aws/io/channel.h +21 -0
- data/aws-crt-ffi/crt/aws-c-io/include/aws/io/io.h +3 -0
- data/aws-crt-ffi/crt/aws-c-io/include/aws/io/socket.h +6 -0
- data/aws-crt-ffi/crt/aws-c-io/include/aws/io/stream.h +35 -5
- data/aws-crt-ffi/crt/aws-c-io/include/aws/io/tls_channel_handler.h +211 -15
- data/aws-crt-ffi/crt/aws-c-io/source/channel.c +56 -30
- data/aws-crt-ffi/crt/aws-c-io/source/darwin/secure_transport_tls_channel_handler.c +0 -24
- data/aws-crt-ffi/crt/aws-c-io/source/io.c +9 -0
- data/aws-crt-ffi/crt/aws-c-io/source/{pkcs11.c → pkcs11_lib.c} +162 -22
- data/aws-crt-ffi/crt/aws-c-io/source/pkcs11_private.h +18 -20
- data/aws-crt-ffi/crt/aws-c-io/source/pkcs11_tls_op_handler.c +221 -0
- data/aws-crt-ffi/crt/aws-c-io/source/posix/socket.c +135 -81
- data/aws-crt-ffi/crt/aws-c-io/source/retry_strategy.c +12 -8
- data/aws-crt-ffi/crt/aws-c-io/source/s2n/s2n_tls_channel_handler.c +252 -215
- data/aws-crt-ffi/crt/aws-c-io/source/stream.c +65 -82
- data/aws-crt-ffi/crt/aws-c-io/source/tls_channel_handler.c +188 -57
- data/aws-crt-ffi/crt/aws-c-io/source/windows/iocp/socket.c +271 -256
- data/aws-crt-ffi/crt/aws-c-io/tests/CMakeLists.txt +21 -12
- data/aws-crt-ffi/crt/aws-c-io/tests/channel_test.c +32 -4
- data/aws-crt-ffi/crt/aws-c-io/tests/io_lib_test.c +37 -0
- data/aws-crt-ffi/crt/aws-c-io/tests/pkcs11_test.c +412 -93
- data/aws-crt-ffi/crt/aws-c-io/tests/resources/ec_unittests.crt +15 -0
- data/aws-crt-ffi/crt/aws-c-io/tests/resources/ec_unittests.key +5 -0
- data/aws-crt-ffi/crt/aws-c-io/tests/resources/ec_unittests.p12 +0 -0
- data/aws-crt-ffi/crt/aws-c-io/tests/resources/ec_unittests.p8 +5 -0
- data/aws-crt-ffi/crt/aws-c-io/tests/resources/generateCerts.sh +24 -15
- data/aws-crt-ffi/crt/aws-c-io/tests/socket_test.c +72 -1
- data/aws-crt-ffi/crt/s2n/CMakeLists.txt +6 -1
- data/aws-crt-ffi/crt/s2n/bindings/rust/Cargo.toml +1 -0
- data/aws-crt-ffi/crt/s2n/bindings/rust/generate/src/main.rs +105 -82
- data/aws-crt-ffi/crt/s2n/bindings/rust/generate.sh +1 -0
- data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls/Cargo.toml +2 -2
- data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls/src/raw/config.rs +1 -1
- data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls-sys/Cargo.toml +1 -1
- data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls-sys/build.rs +84 -30
- data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls-sys/src/lib.rs +4 -0
- data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls-tokio/Cargo.toml +21 -0
- data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls-tokio/examples/certs/cert.pem +14 -0
- data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls-tokio/examples/certs/key.pem +8 -0
- data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls-tokio/examples/client.rs +45 -0
- data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls-tokio/examples/server.rs +60 -0
- data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls-tokio/src/lib.rs +150 -0
- data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls-tokio/tests/handshake.rs +51 -0
- data/aws-crt-ffi/crt/s2n/crypto/s2n_drbg.c +98 -77
- data/aws-crt-ffi/crt/s2n/crypto/s2n_drbg.h +10 -7
- data/aws-crt-ffi/crt/s2n/crypto/s2n_openssl.h +2 -0
- data/aws-crt-ffi/crt/s2n/error/s2n_errno.c +1 -1
- data/aws-crt-ffi/crt/s2n/error/s2n_errno.h +1 -0
- data/aws-crt-ffi/crt/s2n/s2n.mk +7 -0
- data/aws-crt-ffi/crt/s2n/tests/cbmc/templates/scripts/repository.py +233 -0
- data/aws-crt-ffi/crt/s2n/tests/cbmc/templates/scripts/setup-proof.py +8 -7
- data/aws-crt-ffi/crt/s2n/tests/cbmc/templates/scripts/setup.py +17 -18
- data/aws-crt-ffi/crt/s2n/tests/cbmc/templates/scripts/util.py +41 -23
- data/aws-crt-ffi/crt/s2n/tests/fuzz/LD_PRELOAD/global_overrides.c +3 -3
- data/aws-crt-ffi/crt/s2n/tests/integration/s2n_client_endpoint_handshake_test.py +2 -2
- data/aws-crt-ffi/crt/s2n/tests/integrationv2/Makefile +13 -42
- data/aws-crt-ffi/crt/s2n/tests/integrationv2/README.md +6 -1
- data/aws-crt-ffi/crt/s2n/tests/integrationv2/common.py +118 -53
- data/aws-crt-ffi/crt/s2n/tests/integrationv2/configuration.py +108 -88
- data/aws-crt-ffi/crt/s2n/tests/integrationv2/conftest.py +6 -3
- data/aws-crt-ffi/crt/s2n/tests/integrationv2/constants.py +6 -4
- data/aws-crt-ffi/crt/s2n/tests/integrationv2/fixtures.py +21 -12
- data/aws-crt-ffi/crt/s2n/tests/integrationv2/global_flags.py +1 -0
- data/aws-crt-ffi/crt/s2n/tests/integrationv2/processes.py +62 -19
- data/aws-crt-ffi/crt/s2n/tests/integrationv2/providers.py +304 -48
- data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_client_authentication.py +20 -11
- data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_cross_compatibility.py +41 -17
- data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_dynamic_record_sizes.py +6 -3
- data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_early_data.py +105 -48
- data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_external_psk.py +160 -76
- data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_fragmentation.py +59 -26
- data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_happy_path.py +42 -28
- data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_hello_retry_requests.py +33 -13
- data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_key_update.py +29 -11
- data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_ocsp.py +138 -0
- data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_pq_handshake.py +103 -36
- data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_session_resumption.py +52 -25
- data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_signature_algorithms.py +47 -21
- data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_sni_match.py +13 -9
- data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_sslyze.py +88 -17
- data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_version_negotiation.py +71 -22
- data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_well_known_endpoints.py +4 -3
- data/aws-crt-ffi/crt/s2n/tests/integrationv2/tox.ini +1 -0
- data/aws-crt-ffi/crt/s2n/tests/integrationv2/utils.py +50 -15
- data/aws-crt-ffi/crt/s2n/tests/litani/CHANGELOG +131 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/CONTRIBUTING.md +16 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/README.md +36 -14
- data/aws-crt-ffi/crt/s2n/tests/litani/THIRD-PARTY +205 -41
- data/aws-crt-ffi/crt/s2n/tests/litani/doc/bin/build-html-doc +7 -7
- data/aws-crt-ffi/crt/s2n/tests/litani/doc/configure +27 -23
- data/aws-crt-ffi/crt/s2n/tests/litani/doc/src/man/litani-add-job.scdoc +7 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/doc/src/man/litani-dump-run.scdoc +7 -5
- data/aws-crt-ffi/crt/s2n/tests/litani/doc/src/man/litani-transform-jobs.scdoc +248 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/doc/src/man/litani.scdoc +2 -2
- data/aws-crt-ffi/crt/s2n/tests/litani/doc/templates/index.jinja.html +4 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/examples/add-root-node/README +12 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/examples/add-root-node/original-run.sh +52 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/examples/add-root-node/run-all.py +71 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/examples/no-standalone-transform/README +13 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/examples/no-standalone-transform/run-1.sh +34 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/examples/no-standalone-transform/run-2.sh +35 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/examples/no-standalone-transform/run-3.sh +34 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/examples/no-standalone-transform/run-all.py +60 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/README.md +10 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/assumptions.html +42 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/file.dat +7 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/histogram.dat +7 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/run-1.sh +41 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/run-2.sh +47 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/run-3.sh +41 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/run-all.py +34 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/scripts/fib-table.py +40 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/scripts/fib.plt +5 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/scripts/fib.py +32 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/scripts/sin-output.py +40 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/scripts/sin.plt +5 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/scripts/sin.py +30 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/templates/fib-table.jinja.html +45 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/templates/sin-output.jinja.html +30 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/lib/add_job.py +55 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/lib/graph.py +2 -2
- data/aws-crt-ffi/crt/s2n/tests/litani/lib/litani.py +6 -1
- data/aws-crt-ffi/crt/s2n/tests/litani/lib/litani_report.py +18 -21
- data/aws-crt-ffi/crt/s2n/tests/litani/lib/ninja.py +2 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/lib/run_printer.py +26 -7
- data/aws-crt-ffi/crt/s2n/tests/litani/lib/transform_jobs.py +84 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/litani +28 -33
- data/aws-crt-ffi/crt/s2n/tests/litani/script/release +220 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/templates/dashboard.jinja.html +78 -15
- data/aws-crt-ffi/crt/s2n/tests/litani/templates/pipeline.jinja.html +21 -5
- data/aws-crt-ffi/crt/s2n/tests/litani/test/README +15 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/run +56 -33
- data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/custom_stages.py +1 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/cwd.py +1 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/dump_run.py +1 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/graph_line_break.py +1 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/html_node.py +1 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/job_id_env.py +1 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/multiproc_dump_run.py +1 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/no_pool_serialize.py +1 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/no_pool_serialize_graph.py +1 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/no_timed_out.py +1 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/no_timed_out_timeout_ignored.py +1 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/no_timed_out_timeout_ok.py +1 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/pipeline_order.py +53 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/pool_serialize.py +1 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/pool_serialize_graph.py +1 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/single_pool.py +1 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/timed_out.py +1 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/timed_out_subprocess.py +1 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/timed_out_subprocess_multi_shell.py +1 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/timed_out_subprocess_shell.py +1 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/timed_out_timeout_ignored.py +1 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/timed_out_timeout_ok.py +1 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/transform_delete_job.py +54 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/transform_modify_job.py +46 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/transform_no_change_job.py +44 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/zero_pool.py +1 -0
- data/aws-crt-ffi/crt/s2n/tests/litani/test/run +82 -12
- data/aws-crt-ffi/crt/s2n/tests/s2n_test.h +58 -33
- data/aws-crt-ffi/crt/s2n/tests/testlib/s2n_key_schedule_testlib.c +18 -6
- data/aws-crt-ffi/crt/s2n/tests/testlib/s2n_pq_kat_test_utils.c +4 -4
- data/aws-crt-ffi/crt/s2n/tests/testlib/s2n_testlib.h +2 -0
- data/aws-crt-ffi/crt/s2n/tests/unit/s2n_client_hello_retry_test.c +66 -2
- data/aws-crt-ffi/crt/s2n/tests/unit/s2n_connection_test.c +1 -1
- data/aws-crt-ffi/crt/s2n/tests/unit/s2n_drbg_test.c +34 -14
- data/aws-crt-ffi/crt/s2n/tests/unit/s2n_fork_generation_number_test.c +28 -5
- data/aws-crt-ffi/crt/s2n/tests/unit/s2n_mem_usage_test.c +6 -0
- data/aws-crt-ffi/crt/s2n/tests/unit/s2n_override_openssl_random_test.c +1 -1
- data/aws-crt-ffi/crt/s2n/tests/unit/s2n_random_test.c +60 -41
- data/aws-crt-ffi/crt/s2n/tests/unit/s2n_self_talk_broken_pipe_test.c +2 -2
- data/aws-crt-ffi/crt/s2n/tests/unit/s2n_tls13_handshake_early_data_test.c +3 -1
- data/aws-crt-ffi/crt/s2n/tests/unit/s2n_tls13_hybrid_shared_secret_test.c +9 -1
- data/aws-crt-ffi/crt/s2n/tests/unit/s2n_tls13_key_schedule_rfc8448_test.c +31 -130
- data/aws-crt-ffi/crt/s2n/tests/unit/s2n_tls13_key_schedule_test.c +2 -4
- data/aws-crt-ffi/crt/s2n/tests/unit/s2n_tls13_pq_handshake_test.c +11 -6
- data/aws-crt-ffi/crt/s2n/tests/unit/s2n_tls13_secrets_rfc8448_test.c +19 -21
- data/aws-crt-ffi/crt/s2n/tests/unit/s2n_tls13_secrets_test.c +109 -60
- data/aws-crt-ffi/crt/s2n/tls/s2n_config.c +1 -0
- data/aws-crt-ffi/crt/s2n/tls/s2n_config.h +1 -1
- data/aws-crt-ffi/crt/s2n/tls/s2n_connection.c +29 -24
- data/aws-crt-ffi/crt/s2n/tls/s2n_connection.h +5 -5
- data/aws-crt-ffi/crt/s2n/tls/s2n_handshake_hashes.h +1 -7
- data/aws-crt-ffi/crt/s2n/tls/s2n_handshake_io.c +2 -0
- data/aws-crt-ffi/crt/s2n/tls/s2n_handshake_transcript.c +0 -44
- data/aws-crt-ffi/crt/s2n/tls/s2n_internal.h +0 -1
- data/aws-crt-ffi/crt/s2n/tls/s2n_quic_support.h +1 -1
- data/aws-crt-ffi/crt/s2n/tls/s2n_tls13_key_schedule.c +1 -2
- data/aws-crt-ffi/crt/s2n/tls/s2n_tls13_secrets.c +84 -44
- data/aws-crt-ffi/crt/s2n/tls/s2n_tls13_secrets.h +3 -9
- data/aws-crt-ffi/crt/s2n/utils/s2n_blob.h +15 -8
- data/aws-crt-ffi/crt/s2n/utils/s2n_fork_detection.c +2 -6
- data/aws-crt-ffi/crt/s2n/utils/s2n_random.c +9 -9
- data/aws-crt-ffi/src/input_stream.c +32 -15
- data/ext/compile.rb +13 -5
- data/lib/aws-crt/platforms.rb +14 -5
- data/lib/aws-crt/string_blob.rb +3 -3
- metadata +61 -7
- data/aws-crt-ffi/crt/aws-c-auth/source/external/cJSON.c +0 -2987
- data/aws-crt-ffi/crt/aws-c-auth/tests/external/cJSON.c +0 -2986
- data/aws-crt-ffi/crt/aws-c-io/tests/error_test.c +0 -20
@@ -10,6 +10,7 @@
|
|
10
10
|
#include <aws/http/status_code.h>
|
11
11
|
#include <aws/io/channel.h>
|
12
12
|
#include <aws/io/logging.h>
|
13
|
+
#include <aws/io/stream.h>
|
13
14
|
|
14
15
|
/* Apple toolchains such as xcode and swiftpm define the DEBUG symbol. undef it here so we can actually use the token */
|
15
16
|
#undef DEBUG
|
@@ -19,6 +20,9 @@ static void s_stream_update_window(struct aws_http_stream *stream_base, size_t i
|
|
19
20
|
static int s_stream_reset_stream(struct aws_http_stream *stream_base, uint32_t http2_error);
|
20
21
|
static int s_stream_get_received_error_code(struct aws_http_stream *stream_base, uint32_t *out_http2_error);
|
21
22
|
static int s_stream_get_sent_error_code(struct aws_http_stream *stream_base, uint32_t *out_http2_error);
|
23
|
+
static int s_stream_write_data(
|
24
|
+
struct aws_http_stream *stream_base,
|
25
|
+
const struct aws_http2_stream_write_data_options *options);
|
22
26
|
|
23
27
|
static void s_stream_cross_thread_work_task(struct aws_channel_task *task, void *arg, enum aws_task_status status);
|
24
28
|
static struct aws_h2err s_send_rst_and_close_stream(struct aws_h2_stream *stream, struct aws_h2err stream_error);
|
@@ -32,6 +36,7 @@ struct aws_http_stream_vtable s_h2_stream_vtable = {
|
|
32
36
|
.http2_reset_stream = s_stream_reset_stream,
|
33
37
|
.http2_get_received_error_code = s_stream_get_received_error_code,
|
34
38
|
.http2_get_sent_error_code = s_stream_get_sent_error_code,
|
39
|
+
.http2_write_data = s_stream_write_data,
|
35
40
|
};
|
36
41
|
|
37
42
|
const char *aws_h2_stream_state_to_str(enum aws_h2_stream_state state) {
|
@@ -238,23 +243,28 @@ struct aws_h2_stream *aws_h2_stream_new_request(
|
|
238
243
|
stream->base.on_complete = options->on_complete;
|
239
244
|
stream->base.client_data = &stream->base.client_or_server_data.client;
|
240
245
|
stream->base.client_data->response_status = AWS_HTTP_STATUS_CODE_UNKNOWN;
|
246
|
+
struct aws_byte_cursor method;
|
247
|
+
AWS_ZERO_STRUCT(method);
|
248
|
+
if (aws_http_message_get_request_method(options->request, &method)) {
|
249
|
+
goto error;
|
250
|
+
}
|
251
|
+
stream->base.request_method = aws_http_str_to_method(method);
|
252
|
+
aws_linked_list_init(&stream->thread_data.outgoing_writes);
|
253
|
+
aws_linked_list_init(&stream->synced_data.pending_write_list);
|
241
254
|
|
242
255
|
/* Stream refcount starts at 1, and gets incremented again for the connection upon a call to activate() */
|
243
256
|
aws_atomic_init_int(&stream->base.refcount, 1);
|
244
257
|
|
245
|
-
/* Init H2 specific stuff */
|
246
|
-
stream->thread_data.state = AWS_H2_STREAM_STATE_IDLE;
|
247
258
|
enum aws_http_version message_version = aws_http_message_get_protocol_version(options->request);
|
248
259
|
switch (message_version) {
|
249
260
|
case AWS_HTTP_VERSION_1_1:
|
261
|
+
/* TODO: don't automatic transform HTTP/1 message. Let user explicitly pass in HTTP/2 request */
|
250
262
|
stream->thread_data.outgoing_message =
|
251
|
-
aws_http2_message_new_from_http1(
|
263
|
+
aws_http2_message_new_from_http1(stream->base.alloc, options->request);
|
252
264
|
if (!stream->thread_data.outgoing_message) {
|
253
265
|
AWS_H2_STREAM_LOG(ERROR, stream, "Stream failed to create the HTTP/2 message from HTTP/1.1 message");
|
254
266
|
goto error;
|
255
267
|
}
|
256
|
-
stream->backup_outgoing_message = options->request;
|
257
|
-
aws_http_message_acquire(stream->backup_outgoing_message);
|
258
268
|
break;
|
259
269
|
case AWS_HTTP_VERSION_2:
|
260
270
|
stream->thread_data.outgoing_message = options->request;
|
@@ -266,9 +276,24 @@ struct aws_h2_stream *aws_h2_stream_new_request(
|
|
266
276
|
goto error;
|
267
277
|
}
|
268
278
|
|
279
|
+
/* Init H2 specific stuff */
|
280
|
+
stream->thread_data.state = AWS_H2_STREAM_STATE_IDLE;
|
281
|
+
/* stream end is implicit if the request isn't using manual data writes */
|
282
|
+
stream->synced_data.manual_write_ended = !options->http2_use_manual_data_writes;
|
283
|
+
stream->manual_write = options->http2_use_manual_data_writes;
|
284
|
+
|
285
|
+
/* if there's a request body to write, add it as the first outgoing write */
|
286
|
+
struct aws_input_stream *body_stream = aws_http_message_get_body_stream(options->request);
|
287
|
+
if (body_stream) {
|
288
|
+
struct aws_h2_stream_data_write *body_write =
|
289
|
+
aws_mem_calloc(stream->base.alloc, 1, sizeof(struct aws_h2_stream_data_write));
|
290
|
+
body_write->data_stream = aws_input_stream_acquire(body_stream);
|
291
|
+
body_write->end_stream = true;
|
292
|
+
aws_linked_list_push_back(&stream->thread_data.outgoing_writes, &body_write->node);
|
293
|
+
}
|
294
|
+
|
269
295
|
stream->sent_reset_error_code = -1;
|
270
296
|
stream->received_reset_error_code = -1;
|
271
|
-
|
272
297
|
stream->synced_data.reset_error.h2_code = AWS_HTTP2_ERR_COUNT;
|
273
298
|
stream->synced_data.api_state = AWS_H2_STREAM_API_STATE_INIT;
|
274
299
|
if (aws_mutex_init(&stream->synced_data.lock)) {
|
@@ -307,6 +332,9 @@ static void s_stream_cross_thread_work_task(struct aws_channel_task *task, void
|
|
307
332
|
size_t window_update_size;
|
308
333
|
struct aws_h2err reset_error;
|
309
334
|
|
335
|
+
struct aws_linked_list pending_writes;
|
336
|
+
aws_linked_list_init(&pending_writes);
|
337
|
+
|
310
338
|
{ /* BEGIN CRITICAL SECTION */
|
311
339
|
s_lock_synced_data(stream);
|
312
340
|
stream->synced_data.is_cross_thread_work_task_scheduled = false;
|
@@ -317,6 +345,9 @@ static void s_stream_cross_thread_work_task(struct aws_channel_task *task, void
|
|
317
345
|
reset_called = stream->synced_data.reset_called;
|
318
346
|
reset_error = stream->synced_data.reset_error;
|
319
347
|
|
348
|
+
/* copy out pending writes */
|
349
|
+
aws_linked_list_swap_contents(&pending_writes, &stream->synced_data.pending_write_list);
|
350
|
+
|
320
351
|
s_unlock_synced_data(stream);
|
321
352
|
} /* END CRITICAL SECTION */
|
322
353
|
|
@@ -338,6 +369,15 @@ static void s_stream_cross_thread_work_task(struct aws_channel_task *task, void
|
|
338
369
|
}
|
339
370
|
}
|
340
371
|
|
372
|
+
if (stream->thread_data.waiting_for_writes && !aws_linked_list_empty(&pending_writes)) {
|
373
|
+
/* Got more to write, move the stream back to outgoing list */
|
374
|
+
aws_linked_list_remove(&stream->node);
|
375
|
+
aws_linked_list_push_back(&connection->thread_data.outgoing_streams_list, &stream->node);
|
376
|
+
stream->thread_data.waiting_for_writes = false;
|
377
|
+
}
|
378
|
+
/* move any pending writes to the outgoing write queue */
|
379
|
+
aws_linked_list_move_all_back(&stream->thread_data.outgoing_writes, &pending_writes);
|
380
|
+
|
341
381
|
/* It's likely that frames were queued while processing cross-thread work.
|
342
382
|
* If so, try writing them now */
|
343
383
|
aws_h2_try_write_outgoing_frames(connection);
|
@@ -346,18 +386,70 @@ end:
|
|
346
386
|
aws_http_stream_release(&stream->base);
|
347
387
|
}
|
348
388
|
|
389
|
+
static void s_stream_data_write_destroy(
|
390
|
+
struct aws_h2_stream *stream,
|
391
|
+
struct aws_h2_stream_data_write *write,
|
392
|
+
int error_code) {
|
393
|
+
|
394
|
+
AWS_PRECONDITION(stream);
|
395
|
+
AWS_PRECONDITION(write);
|
396
|
+
if (write->on_complete) {
|
397
|
+
write->on_complete(&stream->base, error_code, write->user_data);
|
398
|
+
}
|
399
|
+
if (write->data_stream) {
|
400
|
+
aws_input_stream_release(write->data_stream);
|
401
|
+
}
|
402
|
+
aws_mem_release(stream->base.alloc, write);
|
403
|
+
}
|
404
|
+
|
405
|
+
static void s_h2_stream_destroy_pending_writes(struct aws_h2_stream *stream) {
|
406
|
+
/**
|
407
|
+
* Only called when stream is not active and will never be active afterward (destroying).
|
408
|
+
* Under this assumption, we can safely touch `stream->synced_data.pending_write_list` without
|
409
|
+
* lock, as the user can only add write to the list when the stream is ACTIVE
|
410
|
+
*/
|
411
|
+
AWS_ASSERT(stream->synced_data.api_state != AWS_H2_STREAM_API_STATE_ACTIVE);
|
412
|
+
aws_linked_list_move_all_back(
|
413
|
+
&stream->thread_data.outgoing_writes,
|
414
|
+
&stream->synced_data.pending_write_list); /* clean up any outgoing writes */
|
415
|
+
while (!aws_linked_list_empty(&stream->thread_data.outgoing_writes)) {
|
416
|
+
struct aws_linked_list_node *node = aws_linked_list_pop_front(&stream->thread_data.outgoing_writes);
|
417
|
+
struct aws_h2_stream_data_write *write = AWS_CONTAINER_OF(node, struct aws_h2_stream_data_write, node);
|
418
|
+
AWS_LOGF_DEBUG(AWS_LS_HTTP_STREAM, "Stream closing, cancelling write of stream %p", (void *)write->data_stream);
|
419
|
+
s_stream_data_write_destroy(stream, write, AWS_ERROR_HTTP_STREAM_HAS_COMPLETED);
|
420
|
+
}
|
421
|
+
}
|
422
|
+
|
349
423
|
static void s_stream_destroy(struct aws_http_stream *stream_base) {
|
350
424
|
AWS_PRECONDITION(stream_base);
|
351
425
|
struct aws_h2_stream *stream = AWS_CONTAINER_OF(stream_base, struct aws_h2_stream, base);
|
352
426
|
|
427
|
+
s_h2_stream_destroy_pending_writes(stream);
|
428
|
+
|
353
429
|
AWS_H2_STREAM_LOG(DEBUG, stream, "Destroying stream");
|
354
430
|
aws_mutex_clean_up(&stream->synced_data.lock);
|
355
431
|
aws_http_message_release(stream->thread_data.outgoing_message);
|
356
|
-
aws_http_message_release(stream->backup_outgoing_message);
|
357
432
|
|
358
433
|
aws_mem_release(stream->base.alloc, stream);
|
359
434
|
}
|
360
435
|
|
436
|
+
void aws_h2_stream_complete(struct aws_h2_stream *stream, int error_code) {
|
437
|
+
{ /* BEGIN CRITICAL SECTION */
|
438
|
+
/* clean up any pending writes */
|
439
|
+
s_lock_synced_data(stream);
|
440
|
+
/* The stream is complete now, this will prevent further writes from being queued */
|
441
|
+
stream->synced_data.api_state = AWS_H2_STREAM_API_STATE_COMPLETE;
|
442
|
+
s_unlock_synced_data(stream);
|
443
|
+
} /* END CRITICAL SECTION */
|
444
|
+
|
445
|
+
s_h2_stream_destroy_pending_writes(stream);
|
446
|
+
|
447
|
+
/* Invoke callback */
|
448
|
+
if (stream->base.on_complete) {
|
449
|
+
stream->base.on_complete(&stream->base, error_code, stream->base.user_data);
|
450
|
+
}
|
451
|
+
}
|
452
|
+
|
361
453
|
static void s_stream_update_window(struct aws_http_stream *stream_base, size_t increment_size) {
|
362
454
|
AWS_PRECONDITION(stream_base);
|
363
455
|
struct aws_h2_stream *stream = AWS_CONTAINER_OF(stream_base, struct aws_h2_stream, base);
|
@@ -514,11 +606,6 @@ static struct aws_h2err s_send_rst_and_close_stream(struct aws_h2_stream *stream
|
|
514
606
|
struct aws_h2_connection *connection = s_get_h2_connection(stream);
|
515
607
|
|
516
608
|
stream->thread_data.state = AWS_H2_STREAM_STATE_CLOSED;
|
517
|
-
{ /* BEGIN CRITICAL SECTION */
|
518
|
-
s_lock_synced_data(stream);
|
519
|
-
stream->synced_data.api_state = AWS_H2_STREAM_API_STATE_COMPLETE;
|
520
|
-
s_unlock_synced_data(stream);
|
521
|
-
} /* END CRITICAL SECTION */
|
522
609
|
AWS_H2_STREAM_LOGF(
|
523
610
|
DEBUG,
|
524
611
|
stream,
|
@@ -529,10 +616,7 @@ static struct aws_h2err s_send_rst_and_close_stream(struct aws_h2_stream *stream
|
|
529
616
|
/* Send RST_STREAM */
|
530
617
|
struct aws_h2_frame *rst_stream_frame =
|
531
618
|
aws_h2_frame_new_rst_stream(stream->base.alloc, stream->base.id, stream_error.h2_code);
|
532
|
-
|
533
|
-
AWS_H2_STREAM_LOGF(ERROR, stream, "Error creating RST_STREAM frame, %s", aws_error_name(aws_last_error()));
|
534
|
-
return aws_h2err_from_last_error();
|
535
|
-
}
|
619
|
+
AWS_FATAL_ASSERT(rst_stream_frame != NULL);
|
536
620
|
aws_h2_connection_enqueue_outgoing_frame(connection, rst_stream_frame); /* connection takes ownership of frame */
|
537
621
|
stream->sent_reset_error_code = stream_error.h2_code;
|
538
622
|
|
@@ -560,7 +644,42 @@ struct aws_h2err aws_h2_stream_window_size_change(struct aws_h2_stream *stream,
|
|
560
644
|
return AWS_H2ERR_SUCCESS;
|
561
645
|
}
|
562
646
|
|
563
|
-
|
647
|
+
static inline bool s_h2_stream_has_outgoing_writes(struct aws_h2_stream *stream) {
|
648
|
+
return !aws_linked_list_empty(&stream->thread_data.outgoing_writes);
|
649
|
+
}
|
650
|
+
|
651
|
+
static void s_h2_stream_write_data_complete(struct aws_h2_stream *stream, bool *waiting_writes) {
|
652
|
+
AWS_PRECONDITION(waiting_writes);
|
653
|
+
AWS_PRECONDITION(s_h2_stream_has_outgoing_writes(stream));
|
654
|
+
|
655
|
+
/* finish/clean up the current write operation */
|
656
|
+
struct aws_linked_list_node *node = aws_linked_list_pop_front(&stream->thread_data.outgoing_writes);
|
657
|
+
struct aws_h2_stream_data_write *write_op = AWS_CONTAINER_OF(node, struct aws_h2_stream_data_write, node);
|
658
|
+
const bool ending_stream = write_op->end_stream;
|
659
|
+
s_stream_data_write_destroy(stream, write_op, AWS_OP_SUCCESS);
|
660
|
+
|
661
|
+
/* check to see if there are more queued writes or stream_end was called */
|
662
|
+
*waiting_writes = !ending_stream && !s_h2_stream_has_outgoing_writes(stream);
|
663
|
+
}
|
664
|
+
|
665
|
+
static struct aws_h2_stream_data_write *s_h2_stream_get_current_write(struct aws_h2_stream *stream) {
|
666
|
+
AWS_PRECONDITION(s_h2_stream_has_outgoing_writes(stream));
|
667
|
+
struct aws_linked_list_node *node = aws_linked_list_front(&stream->thread_data.outgoing_writes);
|
668
|
+
struct aws_h2_stream_data_write *write = AWS_CONTAINER_OF(node, struct aws_h2_stream_data_write, node);
|
669
|
+
return write;
|
670
|
+
}
|
671
|
+
|
672
|
+
static struct aws_input_stream *s_h2_stream_get_data_stream(struct aws_h2_stream *stream) {
|
673
|
+
struct aws_h2_stream_data_write *write = s_h2_stream_get_current_write(stream);
|
674
|
+
return write->data_stream;
|
675
|
+
}
|
676
|
+
|
677
|
+
static bool s_h2_stream_does_current_write_end_stream(struct aws_h2_stream *stream) {
|
678
|
+
struct aws_h2_stream_data_write *write = s_h2_stream_get_current_write(stream);
|
679
|
+
return write->end_stream;
|
680
|
+
}
|
681
|
+
|
682
|
+
int aws_h2_stream_on_activated(struct aws_h2_stream *stream, enum aws_h2_stream_body_state *body_state) {
|
564
683
|
AWS_PRECONDITION_ON_CHANNEL_THREAD(stream);
|
565
684
|
|
566
685
|
struct aws_h2_connection *connection = s_get_h2_connection(stream);
|
@@ -569,14 +688,16 @@ int aws_h2_stream_on_activated(struct aws_h2_stream *stream, bool *out_has_outgo
|
|
569
688
|
struct aws_http_message *msg = stream->thread_data.outgoing_message;
|
570
689
|
/* Should be ensured when the stream is created */
|
571
690
|
AWS_ASSERT(aws_http_message_get_protocol_version(msg) == AWS_HTTP_VERSION_2);
|
572
|
-
|
691
|
+
/* If manual write, always has data to be sent. */
|
692
|
+
bool with_data = aws_http_message_get_body_stream(msg) != NULL || stream->manual_write;
|
693
|
+
|
573
694
|
struct aws_http_headers *h2_headers = aws_http_message_get_headers(msg);
|
574
695
|
|
575
696
|
struct aws_h2_frame *headers_frame = aws_h2_frame_new_headers(
|
576
697
|
stream->base.alloc,
|
577
698
|
stream->base.id,
|
578
699
|
h2_headers,
|
579
|
-
!
|
700
|
+
!with_data /* end_stream */,
|
580
701
|
0 /* padding - not currently configurable via public API */,
|
581
702
|
NULL /* priority - not currently configurable via public API */);
|
582
703
|
|
@@ -591,7 +712,7 @@ int aws_h2_stream_on_activated(struct aws_h2_stream *stream, bool *out_has_outgo
|
|
591
712
|
stream->thread_data.window_size_self =
|
592
713
|
connection->thread_data.settings_self[AWS_HTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
|
593
714
|
|
594
|
-
if (
|
715
|
+
if (with_data) {
|
595
716
|
/* If stream has DATA to send, put it in the outgoing_streams_list, and we'll send data later */
|
596
717
|
stream->thread_data.state = AWS_H2_STREAM_STATE_OPEN;
|
597
718
|
AWS_H2_STREAM_LOG(TRACE, stream, "Sending HEADERS. State -> OPEN");
|
@@ -601,7 +722,16 @@ int aws_h2_stream_on_activated(struct aws_h2_stream *stream, bool *out_has_outgo
|
|
601
722
|
AWS_H2_STREAM_LOG(TRACE, stream, "Sending HEADERS with END_STREAM. State -> HALF_CLOSED_LOCAL");
|
602
723
|
}
|
603
724
|
|
604
|
-
|
725
|
+
if (s_h2_stream_has_outgoing_writes(stream)) {
|
726
|
+
*body_state = AWS_H2_STREAM_BODY_STATE_ONGOING;
|
727
|
+
} else {
|
728
|
+
if (stream->manual_write) {
|
729
|
+
stream->thread_data.waiting_for_writes = true;
|
730
|
+
*body_state = AWS_H2_STREAM_BODY_STATE_WAITING_WRITES;
|
731
|
+
} else {
|
732
|
+
*body_state = AWS_H2_STREAM_BODY_STATE_NONE;
|
733
|
+
}
|
734
|
+
}
|
605
735
|
aws_h2_connection_enqueue_outgoing_frame(connection, headers_frame);
|
606
736
|
return AWS_OP_SUCCESS;
|
607
737
|
|
@@ -629,22 +759,23 @@ int aws_h2_stream_encode_data_frame(
|
|
629
759
|
}
|
630
760
|
|
631
761
|
*data_encode_status = AWS_H2_DATA_ENCODE_COMPLETE;
|
632
|
-
struct aws_input_stream *
|
633
|
-
AWS_ASSERT(
|
762
|
+
struct aws_input_stream *input_stream = s_h2_stream_get_data_stream(stream);
|
763
|
+
AWS_ASSERT(input_stream);
|
634
764
|
|
635
|
-
bool
|
636
|
-
bool
|
765
|
+
bool input_stream_complete = false;
|
766
|
+
bool input_stream_stalled = false;
|
767
|
+
bool ends_stream = s_h2_stream_does_current_write_end_stream(stream);
|
637
768
|
if (aws_h2_encode_data_frame(
|
638
769
|
encoder,
|
639
770
|
stream->base.id,
|
640
|
-
|
641
|
-
|
771
|
+
input_stream,
|
772
|
+
ends_stream,
|
642
773
|
0 /*pad_length*/,
|
643
774
|
&stream->thread_data.window_size_peer,
|
644
775
|
&connection->thread_data.window_size_peer,
|
645
776
|
output,
|
646
|
-
&
|
647
|
-
&
|
777
|
+
&input_stream_complete,
|
778
|
+
&input_stream_stalled)) {
|
648
779
|
|
649
780
|
/* Failed to write DATA, treat it as a Stream Error */
|
650
781
|
AWS_H2_STREAM_LOGF(ERROR, stream, "Error encoding stream DATA, %s", aws_error_name(aws_last_error()));
|
@@ -655,16 +786,21 @@ int aws_h2_stream_encode_data_frame(
|
|
655
786
|
return AWS_OP_SUCCESS;
|
656
787
|
}
|
657
788
|
|
658
|
-
|
789
|
+
bool waiting_writes = false;
|
790
|
+
if (input_stream_complete) {
|
791
|
+
s_h2_stream_write_data_complete(stream, &waiting_writes);
|
792
|
+
}
|
793
|
+
|
794
|
+
/*
|
795
|
+
* input_stream_complete for manual writes just means the current outgoing_write is complete. The body is not
|
796
|
+
* complete for real until the stream is told to close
|
797
|
+
*/
|
798
|
+
if (input_stream_complete && ends_stream) {
|
799
|
+
/* Done sending data. No more data will be sent. */
|
659
800
|
if (stream->thread_data.state == AWS_H2_STREAM_STATE_HALF_CLOSED_REMOTE) {
|
660
801
|
/* Both sides have sent END_STREAM */
|
661
802
|
stream->thread_data.state = AWS_H2_STREAM_STATE_CLOSED;
|
662
803
|
AWS_H2_STREAM_LOG(TRACE, stream, "Sent END_STREAM. State -> CLOSED");
|
663
|
-
{ /* BEGIN CRITICAL SECTION */
|
664
|
-
s_lock_synced_data(stream);
|
665
|
-
stream->synced_data.api_state = AWS_H2_STREAM_API_STATE_COMPLETE;
|
666
|
-
s_unlock_synced_data(stream);
|
667
|
-
} /* END CRITICAL SECTION */
|
668
804
|
/* Tell connection that stream is now closed */
|
669
805
|
if (aws_h2_connection_on_stream_closed(
|
670
806
|
connection, stream, AWS_H2_STREAM_CLOSED_WHEN_BOTH_SIDES_END_STREAM, AWS_ERROR_SUCCESS)) {
|
@@ -676,16 +812,22 @@ int aws_h2_stream_encode_data_frame(
|
|
676
812
|
AWS_H2_STREAM_LOG(TRACE, stream, "Sent END_STREAM. State -> HALF_CLOSED_LOCAL");
|
677
813
|
}
|
678
814
|
} else {
|
679
|
-
/* Body not complete */
|
680
815
|
*data_encode_status = AWS_H2_DATA_ENCODE_ONGOING;
|
681
|
-
if (
|
682
|
-
|
816
|
+
if (input_stream_stalled) {
|
817
|
+
AWS_ASSERT(!input_stream_complete);
|
818
|
+
*data_encode_status = AWS_H2_DATA_ENCODE_ONGOING_BODY_STREAM_STALLED;
|
683
819
|
}
|
684
820
|
if (stream->thread_data.window_size_peer <= AWS_H2_MIN_WINDOW_SIZE) {
|
685
|
-
/* if body and window both stalled, we take the window stalled status, which will take the stream out
|
686
|
-
* outgoing list */
|
821
|
+
/* if body and window both stalled, we take the window stalled status, which will take the stream out
|
822
|
+
* from outgoing list */
|
687
823
|
*data_encode_status = AWS_H2_DATA_ENCODE_ONGOING_WINDOW_STALLED;
|
688
824
|
}
|
825
|
+
if (waiting_writes) {
|
826
|
+
/* if window stalled and we waiting for manual writes, we take waiting writes status, which will be handled
|
827
|
+
* properly if more writes coming, but windows is still stalled. But not the other way around. */
|
828
|
+
AWS_ASSERT(input_stream_complete);
|
829
|
+
*data_encode_status = AWS_H2_DATA_ENCODE_ONGOING_WAITING_FOR_WRITES;
|
830
|
+
}
|
689
831
|
}
|
690
832
|
|
691
833
|
return AWS_OP_SUCCESS;
|
@@ -749,28 +891,44 @@ struct aws_h2err aws_h2_stream_on_decoder_headers_i(
|
|
749
891
|
|
750
892
|
} else {
|
751
893
|
/* Client */
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
894
|
+
switch (name_enum) {
|
895
|
+
case AWS_HTTP_HEADER_STATUS: {
|
896
|
+
uint64_t status_code = 0;
|
897
|
+
int err = aws_byte_cursor_utf8_parse_u64(header->value, &status_code);
|
898
|
+
AWS_ASSERT(!err && "Invalid :status value. Decoder should have already validated this");
|
899
|
+
(void)err;
|
900
|
+
|
901
|
+
stream->base.client_data->response_status = (int)status_code;
|
902
|
+
} break;
|
903
|
+
case AWS_HTTP_HEADER_CONTENT_LENGTH: {
|
904
|
+
if (stream->thread_data.content_length_received) {
|
905
|
+
AWS_H2_STREAM_LOG(ERROR, stream, "Duplicate content-length value");
|
906
|
+
goto malformed;
|
907
|
+
}
|
908
|
+
if (aws_byte_cursor_utf8_parse_u64(header->value, &stream->thread_data.incoming_content_length)) {
|
909
|
+
AWS_H2_STREAM_LOG(ERROR, stream, "Invalid content-length value");
|
910
|
+
goto malformed;
|
911
|
+
}
|
912
|
+
stream->thread_data.content_length_received = true;
|
913
|
+
} break;
|
914
|
+
default:
|
915
|
+
break;
|
759
916
|
}
|
760
917
|
}
|
761
918
|
|
762
919
|
if (stream->base.on_incoming_headers) {
|
763
920
|
if (stream->base.on_incoming_headers(&stream->base, block_type, header, 1, stream->base.user_data)) {
|
764
|
-
/* #TODO: callback errors should be Stream Errors, not Connection Errors */
|
765
921
|
AWS_H2_STREAM_LOGF(
|
766
922
|
ERROR, stream, "Incoming header callback raised error, %s", aws_error_name(aws_last_error()));
|
767
|
-
return aws_h2err_from_last_error();
|
923
|
+
return s_send_rst_and_close_stream(stream, aws_h2err_from_last_error());
|
768
924
|
}
|
769
925
|
}
|
770
926
|
|
771
927
|
return AWS_H2ERR_SUCCESS;
|
772
928
|
|
773
929
|
malformed:
|
930
|
+
/* RFC-9113 8.1.1 Malformed requests or responses that are detected MUST be treated as a stream error
|
931
|
+
* (Section 5.4.2) of type PROTOCOL_ERROR.*/
|
774
932
|
return s_send_rst_and_close_stream(stream, aws_h2err_from_h2_code(AWS_HTTP2_ERR_PROTOCOL_ERROR));
|
775
933
|
}
|
776
934
|
|
@@ -811,7 +969,7 @@ struct aws_h2err aws_h2_stream_on_decoder_headers_end(
|
|
811
969
|
stream,
|
812
970
|
"Incoming-header-block-done callback raised error, %s",
|
813
971
|
aws_error_name(aws_last_error()));
|
814
|
-
return aws_h2err_from_last_error();
|
972
|
+
return s_send_rst_and_close_stream(stream, aws_h2err_from_last_error());
|
815
973
|
}
|
816
974
|
}
|
817
975
|
|
@@ -872,6 +1030,25 @@ struct aws_h2err aws_h2_stream_on_decoder_data_begin(
|
|
872
1030
|
return s_send_rst_and_close_stream(stream, aws_h2err_from_h2_code(AWS_HTTP2_ERR_PROTOCOL_ERROR));
|
873
1031
|
}
|
874
1032
|
|
1033
|
+
if (stream->thread_data.content_length_received) {
|
1034
|
+
uint64_t data_len = payload_len - total_padding_bytes;
|
1035
|
+
if (aws_add_u64_checked(
|
1036
|
+
stream->thread_data.incoming_data_length, data_len, &stream->thread_data.incoming_data_length)) {
|
1037
|
+
return s_send_rst_and_close_stream(stream, aws_h2err_from_aws_code(AWS_ERROR_OVERFLOW_DETECTED));
|
1038
|
+
}
|
1039
|
+
|
1040
|
+
if (stream->thread_data.incoming_data_length > stream->thread_data.incoming_content_length) {
|
1041
|
+
AWS_H2_STREAM_LOGF(
|
1042
|
+
ERROR,
|
1043
|
+
stream,
|
1044
|
+
"Total received data payload=%" PRIu64 " has exceed the received content-length header, which=%" PRIi64
|
1045
|
+
". Closing malformed stream",
|
1046
|
+
stream->thread_data.incoming_data_length,
|
1047
|
+
stream->thread_data.incoming_content_length);
|
1048
|
+
return s_send_rst_and_close_stream(stream, aws_h2err_from_h2_code(AWS_HTTP2_ERR_PROTOCOL_ERROR));
|
1049
|
+
}
|
1050
|
+
}
|
1051
|
+
|
875
1052
|
/* RFC-7540 6.9.1:
|
876
1053
|
* The sender MUST NOT send a flow-controlled frame with a length that exceeds
|
877
1054
|
* the space available in either of the flow-control windows advertised by the receiver.
|
@@ -888,34 +1065,30 @@ struct aws_h2err aws_h2_stream_on_decoder_data_begin(
|
|
888
1065
|
}
|
889
1066
|
stream->thread_data.window_size_self -= payload_len;
|
890
1067
|
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
1068
|
+
/* If stream isn't over, we may need to send automatic window updates to keep data flowing */
|
1069
|
+
if (!end_stream) {
|
1070
|
+
uint32_t auto_window_update;
|
1071
|
+
if (stream->base.owning_connection->stream_manual_window_management) {
|
1072
|
+
/* Automatically update the flow-window to account for padding, even though "manual window management"
|
1073
|
+
* is enabled, because the current API doesn't have any way to inform the user about padding,
|
1074
|
+
* so we can't expect them to manage it themselves. */
|
1075
|
+
auto_window_update = total_padding_bytes;
|
1076
|
+
} else {
|
1077
|
+
/* Automatically update the full amount we just received */
|
1078
|
+
auto_window_update = payload_len;
|
899
1079
|
}
|
900
|
-
|
901
|
-
|
902
|
-
stream,
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
return aws_h2err_from_last_error();
|
1080
|
+
|
1081
|
+
if (auto_window_update != 0) {
|
1082
|
+
if (s_stream_send_update_window(stream, auto_window_update)) {
|
1083
|
+
return aws_h2err_from_last_error();
|
1084
|
+
}
|
1085
|
+
AWS_H2_STREAM_LOGF(
|
1086
|
+
TRACE,
|
1087
|
+
stream,
|
1088
|
+
"Automatically updating stream window by %" PRIu32 "(%" PRIu32 " due to padding).",
|
1089
|
+
auto_window_update,
|
1090
|
+
total_padding_bytes);
|
912
1091
|
}
|
913
|
-
AWS_H2_STREAM_LOGF(
|
914
|
-
TRACE,
|
915
|
-
stream,
|
916
|
-
"Connection with no manual window management, updating window with size %" PRIu32
|
917
|
-
" automatically for stream.",
|
918
|
-
payload_len);
|
919
1092
|
}
|
920
1093
|
|
921
1094
|
return AWS_H2ERR_SUCCESS;
|
@@ -931,7 +1104,7 @@ struct aws_h2err aws_h2_stream_on_decoder_data_i(struct aws_h2_stream *stream, s
|
|
931
1104
|
if (stream->base.on_incoming_body(&stream->base, &data, stream->base.user_data)) {
|
932
1105
|
AWS_H2_STREAM_LOGF(
|
933
1106
|
ERROR, stream, "Incoming body callback raised error, %s", aws_error_name(aws_last_error()));
|
934
|
-
return aws_h2err_from_last_error();
|
1107
|
+
return s_send_rst_and_close_stream(stream, aws_h2err_from_last_error());
|
935
1108
|
}
|
936
1109
|
}
|
937
1110
|
|
@@ -976,15 +1149,40 @@ struct aws_h2err aws_h2_stream_on_decoder_end_stream(struct aws_h2_stream *strea
|
|
976
1149
|
* an actual frame type. It's a flag on DATA or HEADERS frames, and we
|
977
1150
|
* already checked the legality of those frames in their respective callbacks. */
|
978
1151
|
|
1152
|
+
if (stream->thread_data.content_length_received) {
|
1153
|
+
if (stream->base.request_method != AWS_HTTP_METHOD_HEAD &&
|
1154
|
+
stream->base.client_data->response_status != AWS_HTTP_STATUS_CODE_304_NOT_MODIFIED) {
|
1155
|
+
/**
|
1156
|
+
* RFC-9110 8.6.
|
1157
|
+
* A server MAY send a Content-Length header field in a response to a HEAD request.
|
1158
|
+
* A server MAY send a Content-Length header field in a 304 (Not Modified) response.
|
1159
|
+
* But both of these condition will have no body receive.
|
1160
|
+
*/
|
1161
|
+
if (stream->thread_data.incoming_data_length != stream->thread_data.incoming_content_length) {
|
1162
|
+
/**
|
1163
|
+
* RFC-9113 8.1.1:
|
1164
|
+
* A request or response is also malformed if the value of a content-length header field does not equal
|
1165
|
+
* the sum of the DATA frame payload lengths that form the content, unless the message is defined as
|
1166
|
+
* having no content.
|
1167
|
+
*
|
1168
|
+
* Clients MUST NOT accept a malformed response.
|
1169
|
+
*/
|
1170
|
+
AWS_H2_STREAM_LOGF(
|
1171
|
+
ERROR,
|
1172
|
+
stream,
|
1173
|
+
"Total received data payload=%" PRIu64
|
1174
|
+
" does not match the received content-length header, which=%" PRIi64 ". Closing malformed stream",
|
1175
|
+
stream->thread_data.incoming_data_length,
|
1176
|
+
stream->thread_data.incoming_content_length);
|
1177
|
+
return s_send_rst_and_close_stream(stream, aws_h2err_from_h2_code(AWS_HTTP2_ERR_PROTOCOL_ERROR));
|
1178
|
+
}
|
1179
|
+
}
|
1180
|
+
}
|
1181
|
+
|
979
1182
|
if (stream->thread_data.state == AWS_H2_STREAM_STATE_HALF_CLOSED_LOCAL) {
|
980
1183
|
/* Both sides have sent END_STREAM */
|
981
1184
|
stream->thread_data.state = AWS_H2_STREAM_STATE_CLOSED;
|
982
1185
|
AWS_H2_STREAM_LOG(TRACE, stream, "Received END_STREAM. State -> CLOSED");
|
983
|
-
{ /* BEGIN CRITICAL SECTION */
|
984
|
-
s_lock_synced_data(stream);
|
985
|
-
stream->synced_data.api_state = AWS_H2_STREAM_API_STATE_COMPLETE;
|
986
|
-
s_unlock_synced_data(stream);
|
987
|
-
} /* END CRITICAL SECTION */
|
988
1186
|
/* Tell connection that stream is now closed */
|
989
1187
|
if (aws_h2_connection_on_stream_closed(
|
990
1188
|
s_get_h2_connection(stream),
|
@@ -1034,11 +1232,6 @@ struct aws_h2err aws_h2_stream_on_decoder_rst_stream(struct aws_h2_stream *strea
|
|
1034
1232
|
}
|
1035
1233
|
|
1036
1234
|
stream->thread_data.state = AWS_H2_STREAM_STATE_CLOSED;
|
1037
|
-
{ /* BEGIN CRITICAL SECTION */
|
1038
|
-
s_lock_synced_data(stream);
|
1039
|
-
stream->synced_data.api_state = AWS_H2_STREAM_API_STATE_COMPLETE;
|
1040
|
-
s_unlock_synced_data(stream);
|
1041
|
-
} /* END CRITICAL SECTION */
|
1042
1235
|
stream->received_reset_error_code = h2_error_code;
|
1043
1236
|
|
1044
1237
|
AWS_H2_STREAM_LOGF(
|
@@ -1055,3 +1248,68 @@ struct aws_h2err aws_h2_stream_on_decoder_rst_stream(struct aws_h2_stream *strea
|
|
1055
1248
|
|
1056
1249
|
return AWS_H2ERR_SUCCESS;
|
1057
1250
|
}
|
1251
|
+
|
1252
|
+
static int s_stream_write_data(
|
1253
|
+
struct aws_http_stream *stream_base,
|
1254
|
+
const struct aws_http2_stream_write_data_options *options) {
|
1255
|
+
struct aws_h2_stream *stream = AWS_CONTAINER_OF(stream_base, struct aws_h2_stream, base);
|
1256
|
+
struct aws_h2_connection *connection = s_get_h2_connection(stream);
|
1257
|
+
|
1258
|
+
/* queue this new write into the pending write list for the stream */
|
1259
|
+
struct aws_h2_stream_data_write *pending_write =
|
1260
|
+
aws_mem_calloc(stream->base.alloc, 1, sizeof(struct aws_h2_stream_data_write));
|
1261
|
+
if (options->data) {
|
1262
|
+
pending_write->data_stream = aws_input_stream_acquire(options->data);
|
1263
|
+
} else {
|
1264
|
+
struct aws_byte_cursor empty_cursor;
|
1265
|
+
AWS_ZERO_STRUCT(empty_cursor);
|
1266
|
+
pending_write->data_stream = aws_input_stream_new_from_cursor(stream->base.alloc, &empty_cursor);
|
1267
|
+
}
|
1268
|
+
bool schedule_cross_thread_work = false;
|
1269
|
+
{ /* BEGIN CRITICAL SECTION */
|
1270
|
+
s_lock_synced_data(stream);
|
1271
|
+
{
|
1272
|
+
if (stream->synced_data.api_state != AWS_H2_STREAM_API_STATE_ACTIVE) {
|
1273
|
+
s_unlock_synced_data(stream);
|
1274
|
+
s_stream_data_write_destroy(stream, pending_write, AWS_ERROR_INVALID_STATE);
|
1275
|
+
AWS_LOGF_ERROR(
|
1276
|
+
AWS_LS_HTTP_STREAM,
|
1277
|
+
"Cannot write DATA frames to an inactive or closed stream, stream=%p",
|
1278
|
+
(void *)stream_base);
|
1279
|
+
return aws_raise_error(AWS_ERROR_INVALID_STATE);
|
1280
|
+
}
|
1281
|
+
|
1282
|
+
if (stream->synced_data.manual_write_ended) {
|
1283
|
+
s_unlock_synced_data(stream);
|
1284
|
+
s_stream_data_write_destroy(stream, pending_write, AWS_ERROR_INVALID_STATE);
|
1285
|
+
AWS_LOGF_ERROR(
|
1286
|
+
AWS_LS_HTTP_STREAM,
|
1287
|
+
"Cannot write DATA frames to a stream after end, stream=%p",
|
1288
|
+
(void *)stream_base);
|
1289
|
+
/* Fail with error, otherwise, people can wait for on_complete callback that will never be invoked. */
|
1290
|
+
return aws_raise_error(AWS_ERROR_INVALID_STATE);
|
1291
|
+
}
|
1292
|
+
/* Not setting this until we're sure we succeeded, so that callback doesn't fire on cleanup if we fail */
|
1293
|
+
if (options->end_stream) {
|
1294
|
+
stream->synced_data.manual_write_ended = true;
|
1295
|
+
}
|
1296
|
+
pending_write->end_stream = options->end_stream;
|
1297
|
+
pending_write->on_complete = options->on_complete;
|
1298
|
+
pending_write->user_data = options->user_data;
|
1299
|
+
|
1300
|
+
aws_linked_list_push_back(&stream->synced_data.pending_write_list, &pending_write->node);
|
1301
|
+
schedule_cross_thread_work = !stream->synced_data.is_cross_thread_work_task_scheduled;
|
1302
|
+
stream->synced_data.is_cross_thread_work_task_scheduled = true;
|
1303
|
+
}
|
1304
|
+
s_unlock_synced_data(stream);
|
1305
|
+
} /* END CRITICAL SECTION */
|
1306
|
+
|
1307
|
+
if (schedule_cross_thread_work) {
|
1308
|
+
AWS_H2_STREAM_LOG(TRACE, stream, "Scheduling stream cross-thread work task");
|
1309
|
+
/* increment the refcount of stream to keep it alive until the task runs */
|
1310
|
+
aws_atomic_fetch_add(&stream->base.refcount, 1);
|
1311
|
+
aws_channel_schedule_task_now(connection->base.channel_slot->channel, &stream->cross_thread_work_task);
|
1312
|
+
}
|
1313
|
+
|
1314
|
+
return AWS_OP_SUCCESS;
|
1315
|
+
}
|