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.
Files changed (322) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/VERSION +1 -1
  4. data/aws-crt-ffi/CMakeLists.txt +49 -41
  5. data/aws-crt-ffi/crt/aws-c-auth/CMakeLists.txt +0 -10
  6. data/aws-crt-ffi/crt/aws-c-auth/include/aws/auth/credentials.h +3 -2
  7. data/aws-crt-ffi/crt/aws-c-auth/include/aws/auth/private/credentials_utils.h +4 -4
  8. data/aws-crt-ffi/crt/aws-c-auth/source/auth.c +1 -14
  9. data/aws-crt-ffi/crt/aws-c-auth/source/aws_imds_client.c +206 -68
  10. data/aws-crt-ffi/crt/aws-c-auth/source/aws_signing.c +5 -0
  11. data/aws-crt-ffi/crt/aws-c-auth/source/credentials_provider_cached.c +6 -6
  12. data/aws-crt-ffi/crt/aws-c-auth/source/credentials_provider_default_chain.c +16 -1
  13. data/aws-crt-ffi/crt/aws-c-auth/source/credentials_provider_ecs.c +0 -1
  14. data/aws-crt-ffi/crt/aws-c-auth/source/credentials_provider_process.c +0 -1
  15. data/aws-crt-ffi/crt/aws-c-auth/source/credentials_provider_sts_web_identity.c +0 -1
  16. data/aws-crt-ffi/crt/aws-c-auth/source/credentials_provider_x509.c +10 -7
  17. data/aws-crt-ffi/crt/aws-c-auth/source/credentials_utils.c +35 -26
  18. data/aws-crt-ffi/crt/aws-c-auth/source/signable_chunk.c +3 -2
  19. data/aws-crt-ffi/crt/aws-c-auth/tests/CMakeLists.txt +3 -2
  20. data/aws-crt-ffi/crt/aws-c-auth/tests/aws_imds_client_test.c +1 -0
  21. data/aws-crt-ffi/crt/aws-c-auth/tests/credentials_provider_ecs_tests.c +3 -0
  22. data/aws-crt-ffi/crt/aws-c-auth/tests/credentials_provider_process_tests.c +65 -16
  23. data/aws-crt-ffi/crt/aws-c-auth/tests/credentials_tests.c +125 -0
  24. data/aws-crt-ffi/crt/aws-c-auth/tests/sigv4_signing_tests.c +68 -46
  25. data/aws-crt-ffi/crt/aws-c-cal/CMakeLists.txt +8 -3
  26. data/aws-crt-ffi/crt/aws-c-cal/bin/run_x_platform_fuzz_corpus/main.c +9 -0
  27. data/aws-crt-ffi/crt/aws-c-cal/builder.json +11 -3
  28. data/aws-crt-ffi/crt/aws-c-cal/cmake/aws-c-cal-config.cmake +14 -5
  29. data/aws-crt-ffi/crt/aws-c-cal/source/darwin/securityframework_ecc.c +6 -6
  30. data/aws-crt-ffi/crt/aws-c-cal/source/windows/bcrypt_ecc.c +12 -12
  31. data/aws-crt-ffi/crt/aws-c-cal/tests/test_case_helper.h +14 -14
  32. data/aws-crt-ffi/crt/aws-c-common/CMakeLists.txt +21 -1
  33. data/aws-crt-ffi/crt/aws-c-common/README.md +8 -0
  34. data/aws-crt-ffi/crt/aws-c-common/cmake/AwsCFlags.cmake +20 -5
  35. data/aws-crt-ffi/crt/aws-c-common/cmake/AwsFeatureTests.cmake +7 -1
  36. data/aws-crt-ffi/crt/aws-c-common/format-check.sh +1 -1
  37. data/aws-crt-ffi/crt/aws-c-common/include/aws/common/byte_buf.h +14 -0
  38. data/aws-crt-ffi/crt/aws-c-common/include/aws/common/config.h.in +1 -0
  39. data/aws-crt-ffi/crt/{aws-c-auth/include/aws/auth → aws-c-common/include/aws/common}/external/cJSON.h +82 -74
  40. data/aws-crt-ffi/crt/aws-c-common/include/aws/common/json.h +335 -0
  41. data/aws-crt-ffi/crt/aws-c-common/include/aws/common/logging.h +1 -0
  42. data/aws-crt-ffi/crt/aws-c-common/include/aws/common/math.inl +2 -2
  43. data/aws-crt-ffi/crt/aws-c-common/include/aws/common/private/json_impl.h +22 -0
  44. data/aws-crt-ffi/crt/aws-c-common/include/aws/testing/aws_test_harness.h +2 -0
  45. data/aws-crt-ffi/crt/aws-c-common/source/byte_buf.c +36 -0
  46. data/aws-crt-ffi/crt/aws-c-common/source/common.c +5 -2
  47. data/aws-crt-ffi/crt/aws-c-common/source/external/cJSON.c +3113 -0
  48. data/aws-crt-ffi/crt/aws-c-common/source/file.c +9 -0
  49. data/aws-crt-ffi/crt/aws-c-common/source/json.c +348 -0
  50. data/aws-crt-ffi/crt/aws-c-common/source/logging.c +7 -2
  51. data/aws-crt-ffi/crt/aws-c-common/source/posix/system_info.c +8 -0
  52. data/aws-crt-ffi/crt/aws-c-common/source/ref_count.c +3 -1
  53. data/aws-crt-ffi/crt/aws-c-common/source/windows/file.c +47 -0
  54. data/aws-crt-ffi/crt/aws-c-common/source/windows/system_info.c +2 -1
  55. data/aws-crt-ffi/crt/aws-c-common/tests/CMakeLists.txt +5 -0
  56. data/aws-crt-ffi/crt/aws-c-common/tests/byte_buf_test.c +69 -0
  57. data/aws-crt-ffi/crt/aws-c-common/tests/json_test.c +134 -0
  58. data/aws-crt-ffi/crt/aws-c-common/tests/memtrace_test.c +6 -2
  59. data/aws-crt-ffi/crt/aws-c-event-stream/README.md +18 -35
  60. data/aws-crt-ffi/crt/aws-c-event-stream/include/aws/event-stream/event_stream.h +21 -2
  61. data/aws-crt-ffi/crt/aws-c-event-stream/include/aws/event-stream/event_stream_rpc_client.h +14 -2
  62. data/aws-crt-ffi/crt/aws-c-event-stream/include/aws/event-stream/event_stream_rpc_server.h +13 -0
  63. data/aws-crt-ffi/crt/aws-c-event-stream/include/aws/event-stream/private/event_stream_rpc_priv.h +7 -7
  64. data/aws-crt-ffi/crt/aws-c-event-stream/source/event_stream.c +257 -141
  65. data/aws-crt-ffi/crt/aws-c-event-stream/source/event_stream_channel_handler.c +1 -1
  66. data/aws-crt-ffi/crt/aws-c-event-stream/source/event_stream_rpc_client.c +31 -8
  67. data/aws-crt-ffi/crt/aws-c-event-stream/source/event_stream_rpc_server.c +63 -10
  68. data/aws-crt-ffi/crt/aws-c-event-stream/tests/CMakeLists.txt +2 -0
  69. data/aws-crt-ffi/crt/aws-c-event-stream/tests/event_stream_rpc_client_connection_test.c +157 -106
  70. data/aws-crt-ffi/crt/aws-c-event-stream/tests/event_stream_rpc_server_connection_test.c +168 -1
  71. data/aws-crt-ffi/crt/aws-c-event-stream/tests/message_deserializer_test.c +4 -2
  72. data/aws-crt-ffi/crt/aws-c-http/CMakeLists.txt +1 -0
  73. data/aws-crt-ffi/crt/aws-c-http/README.md +8 -0
  74. data/aws-crt-ffi/crt/aws-c-http/bin/elasticurl/main.c +1 -1
  75. data/aws-crt-ffi/crt/aws-c-http/builder.json +4 -3
  76. data/aws-crt-ffi/crt/aws-c-http/include/aws/http/connection.h +8 -1
  77. data/aws-crt-ffi/crt/aws-c-http/include/aws/http/connection_manager.h +45 -1
  78. data/aws-crt-ffi/crt/aws-c-http/include/aws/http/http2_stream_manager.h +63 -12
  79. data/aws-crt-ffi/crt/aws-c-http/include/aws/http/private/connection_impl.h +2 -1
  80. data/aws-crt-ffi/crt/aws-c-http/include/aws/http/private/h2_connection.h +20 -2
  81. data/aws-crt-ffi/crt/aws-c-http/include/aws/http/private/h2_frames.h +1 -0
  82. data/aws-crt-ffi/crt/aws-c-http/include/aws/http/private/h2_stream.h +42 -13
  83. data/aws-crt-ffi/crt/aws-c-http/include/aws/http/private/http2_stream_manager_impl.h +17 -0
  84. data/aws-crt-ffi/crt/aws-c-http/include/aws/http/private/http_impl.h +3 -0
  85. data/aws-crt-ffi/crt/aws-c-http/include/aws/http/private/random_access_set.h +10 -3
  86. data/aws-crt-ffi/crt/aws-c-http/include/aws/http/private/request_response_impl.h +3 -17
  87. data/aws-crt-ffi/crt/aws-c-http/include/aws/http/request_response.h +108 -4
  88. data/aws-crt-ffi/crt/aws-c-http/include/aws/http/statistics.h +22 -0
  89. data/aws-crt-ffi/crt/aws-c-http/source/connection.c +8 -3
  90. data/aws-crt-ffi/crt/aws-c-http/source/connection_manager.c +22 -3
  91. data/aws-crt-ffi/crt/aws-c-http/source/connection_monitor.c +32 -14
  92. data/aws-crt-ffi/crt/aws-c-http/source/h1_connection.c +14 -0
  93. data/aws-crt-ffi/crt/aws-c-http/source/h1_encoder.c +7 -4
  94. data/aws-crt-ffi/crt/aws-c-http/source/h2_connection.c +161 -45
  95. data/aws-crt-ffi/crt/aws-c-http/source/h2_decoder.c +37 -8
  96. data/aws-crt-ffi/crt/aws-c-http/source/h2_frames.c +13 -1
  97. data/aws-crt-ffi/crt/aws-c-http/source/h2_stream.c +345 -87
  98. data/aws-crt-ffi/crt/aws-c-http/source/hpack.c +3 -0
  99. data/aws-crt-ffi/crt/aws-c-http/source/http.c +3 -0
  100. data/aws-crt-ffi/crt/aws-c-http/source/http2_stream_manager.c +266 -39
  101. data/aws-crt-ffi/crt/aws-c-http/source/random_access_set.c +9 -3
  102. data/aws-crt-ffi/crt/aws-c-http/source/request_response.c +80 -20
  103. data/aws-crt-ffi/crt/aws-c-http/source/statistics.c +11 -0
  104. data/aws-crt-ffi/crt/aws-c-http/tests/CMakeLists.txt +28 -1
  105. data/aws-crt-ffi/crt/aws-c-http/tests/fuzz/fuzz_h2_decoder_correct.c +5 -3
  106. data/aws-crt-ffi/crt/aws-c-http/tests/h2_test_helper.c +133 -29
  107. data/aws-crt-ffi/crt/aws-c-http/tests/h2_test_helper.h +6 -0
  108. data/aws-crt-ffi/crt/aws-c-http/tests/py_localhost/README.md +40 -0
  109. data/aws-crt-ffi/crt/aws-c-http/tests/py_localhost/non_tls_server.py +56 -0
  110. data/aws-crt-ffi/crt/aws-c-http/tests/py_localhost/server.py +329 -0
  111. data/aws-crt-ffi/crt/aws-c-http/tests/test_connection_manager.c +1 -1
  112. data/aws-crt-ffi/crt/aws-c-http/tests/test_connection_monitor.c +2 -2
  113. data/aws-crt-ffi/crt/aws-c-http/tests/test_h1_client.c +47 -34
  114. data/aws-crt-ffi/crt/aws-c-http/tests/test_h1_encoder.c +4 -4
  115. data/aws-crt-ffi/crt/aws-c-http/tests/test_h1_server.c +15 -12
  116. data/aws-crt-ffi/crt/aws-c-http/tests/test_h2_client.c +582 -25
  117. data/aws-crt-ffi/crt/aws-c-http/tests/test_h2_encoder.c +3 -3
  118. data/aws-crt-ffi/crt/aws-c-http/tests/test_localhost_integ.c +530 -0
  119. data/aws-crt-ffi/crt/aws-c-http/tests/test_stream_manager.c +459 -67
  120. data/aws-crt-ffi/crt/aws-c-io/CMakeLists.txt +4 -0
  121. data/aws-crt-ffi/crt/aws-c-io/builder.json +3 -2
  122. data/aws-crt-ffi/crt/aws-c-io/include/aws/io/channel.h +21 -0
  123. data/aws-crt-ffi/crt/aws-c-io/include/aws/io/io.h +3 -0
  124. data/aws-crt-ffi/crt/aws-c-io/include/aws/io/socket.h +6 -0
  125. data/aws-crt-ffi/crt/aws-c-io/include/aws/io/stream.h +35 -5
  126. data/aws-crt-ffi/crt/aws-c-io/include/aws/io/tls_channel_handler.h +211 -15
  127. data/aws-crt-ffi/crt/aws-c-io/source/channel.c +56 -30
  128. data/aws-crt-ffi/crt/aws-c-io/source/darwin/secure_transport_tls_channel_handler.c +0 -24
  129. data/aws-crt-ffi/crt/aws-c-io/source/io.c +9 -0
  130. data/aws-crt-ffi/crt/aws-c-io/source/{pkcs11.c → pkcs11_lib.c} +162 -22
  131. data/aws-crt-ffi/crt/aws-c-io/source/pkcs11_private.h +18 -20
  132. data/aws-crt-ffi/crt/aws-c-io/source/pkcs11_tls_op_handler.c +221 -0
  133. data/aws-crt-ffi/crt/aws-c-io/source/posix/socket.c +135 -81
  134. data/aws-crt-ffi/crt/aws-c-io/source/retry_strategy.c +12 -8
  135. data/aws-crt-ffi/crt/aws-c-io/source/s2n/s2n_tls_channel_handler.c +252 -215
  136. data/aws-crt-ffi/crt/aws-c-io/source/stream.c +65 -82
  137. data/aws-crt-ffi/crt/aws-c-io/source/tls_channel_handler.c +188 -57
  138. data/aws-crt-ffi/crt/aws-c-io/source/windows/iocp/socket.c +271 -256
  139. data/aws-crt-ffi/crt/aws-c-io/tests/CMakeLists.txt +21 -12
  140. data/aws-crt-ffi/crt/aws-c-io/tests/channel_test.c +32 -4
  141. data/aws-crt-ffi/crt/aws-c-io/tests/io_lib_test.c +37 -0
  142. data/aws-crt-ffi/crt/aws-c-io/tests/pkcs11_test.c +412 -93
  143. data/aws-crt-ffi/crt/aws-c-io/tests/resources/ec_unittests.crt +15 -0
  144. data/aws-crt-ffi/crt/aws-c-io/tests/resources/ec_unittests.key +5 -0
  145. data/aws-crt-ffi/crt/aws-c-io/tests/resources/ec_unittests.p12 +0 -0
  146. data/aws-crt-ffi/crt/aws-c-io/tests/resources/ec_unittests.p8 +5 -0
  147. data/aws-crt-ffi/crt/aws-c-io/tests/resources/generateCerts.sh +24 -15
  148. data/aws-crt-ffi/crt/aws-c-io/tests/socket_test.c +72 -1
  149. data/aws-crt-ffi/crt/s2n/CMakeLists.txt +6 -1
  150. data/aws-crt-ffi/crt/s2n/bindings/rust/Cargo.toml +1 -0
  151. data/aws-crt-ffi/crt/s2n/bindings/rust/generate/src/main.rs +105 -82
  152. data/aws-crt-ffi/crt/s2n/bindings/rust/generate.sh +1 -0
  153. data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls/Cargo.toml +2 -2
  154. data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls/src/raw/config.rs +1 -1
  155. data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls-sys/Cargo.toml +1 -1
  156. data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls-sys/build.rs +84 -30
  157. data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls-sys/src/lib.rs +4 -0
  158. data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls-tokio/Cargo.toml +21 -0
  159. data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls-tokio/examples/certs/cert.pem +14 -0
  160. data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls-tokio/examples/certs/key.pem +8 -0
  161. data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls-tokio/examples/client.rs +45 -0
  162. data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls-tokio/examples/server.rs +60 -0
  163. data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls-tokio/src/lib.rs +150 -0
  164. data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls-tokio/tests/handshake.rs +51 -0
  165. data/aws-crt-ffi/crt/s2n/crypto/s2n_drbg.c +98 -77
  166. data/aws-crt-ffi/crt/s2n/crypto/s2n_drbg.h +10 -7
  167. data/aws-crt-ffi/crt/s2n/crypto/s2n_openssl.h +2 -0
  168. data/aws-crt-ffi/crt/s2n/error/s2n_errno.c +1 -1
  169. data/aws-crt-ffi/crt/s2n/error/s2n_errno.h +1 -0
  170. data/aws-crt-ffi/crt/s2n/s2n.mk +7 -0
  171. data/aws-crt-ffi/crt/s2n/tests/cbmc/templates/scripts/repository.py +233 -0
  172. data/aws-crt-ffi/crt/s2n/tests/cbmc/templates/scripts/setup-proof.py +8 -7
  173. data/aws-crt-ffi/crt/s2n/tests/cbmc/templates/scripts/setup.py +17 -18
  174. data/aws-crt-ffi/crt/s2n/tests/cbmc/templates/scripts/util.py +41 -23
  175. data/aws-crt-ffi/crt/s2n/tests/fuzz/LD_PRELOAD/global_overrides.c +3 -3
  176. data/aws-crt-ffi/crt/s2n/tests/integration/s2n_client_endpoint_handshake_test.py +2 -2
  177. data/aws-crt-ffi/crt/s2n/tests/integrationv2/Makefile +13 -42
  178. data/aws-crt-ffi/crt/s2n/tests/integrationv2/README.md +6 -1
  179. data/aws-crt-ffi/crt/s2n/tests/integrationv2/common.py +118 -53
  180. data/aws-crt-ffi/crt/s2n/tests/integrationv2/configuration.py +108 -88
  181. data/aws-crt-ffi/crt/s2n/tests/integrationv2/conftest.py +6 -3
  182. data/aws-crt-ffi/crt/s2n/tests/integrationv2/constants.py +6 -4
  183. data/aws-crt-ffi/crt/s2n/tests/integrationv2/fixtures.py +21 -12
  184. data/aws-crt-ffi/crt/s2n/tests/integrationv2/global_flags.py +1 -0
  185. data/aws-crt-ffi/crt/s2n/tests/integrationv2/processes.py +62 -19
  186. data/aws-crt-ffi/crt/s2n/tests/integrationv2/providers.py +304 -48
  187. data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_client_authentication.py +20 -11
  188. data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_cross_compatibility.py +41 -17
  189. data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_dynamic_record_sizes.py +6 -3
  190. data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_early_data.py +105 -48
  191. data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_external_psk.py +160 -76
  192. data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_fragmentation.py +59 -26
  193. data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_happy_path.py +42 -28
  194. data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_hello_retry_requests.py +33 -13
  195. data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_key_update.py +29 -11
  196. data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_ocsp.py +138 -0
  197. data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_pq_handshake.py +103 -36
  198. data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_session_resumption.py +52 -25
  199. data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_signature_algorithms.py +47 -21
  200. data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_sni_match.py +13 -9
  201. data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_sslyze.py +88 -17
  202. data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_version_negotiation.py +71 -22
  203. data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_well_known_endpoints.py +4 -3
  204. data/aws-crt-ffi/crt/s2n/tests/integrationv2/tox.ini +1 -0
  205. data/aws-crt-ffi/crt/s2n/tests/integrationv2/utils.py +50 -15
  206. data/aws-crt-ffi/crt/s2n/tests/litani/CHANGELOG +131 -0
  207. data/aws-crt-ffi/crt/s2n/tests/litani/CONTRIBUTING.md +16 -0
  208. data/aws-crt-ffi/crt/s2n/tests/litani/README.md +36 -14
  209. data/aws-crt-ffi/crt/s2n/tests/litani/THIRD-PARTY +205 -41
  210. data/aws-crt-ffi/crt/s2n/tests/litani/doc/bin/build-html-doc +7 -7
  211. data/aws-crt-ffi/crt/s2n/tests/litani/doc/configure +27 -23
  212. data/aws-crt-ffi/crt/s2n/tests/litani/doc/src/man/litani-add-job.scdoc +7 -0
  213. data/aws-crt-ffi/crt/s2n/tests/litani/doc/src/man/litani-dump-run.scdoc +7 -5
  214. data/aws-crt-ffi/crt/s2n/tests/litani/doc/src/man/litani-transform-jobs.scdoc +248 -0
  215. data/aws-crt-ffi/crt/s2n/tests/litani/doc/src/man/litani.scdoc +2 -2
  216. data/aws-crt-ffi/crt/s2n/tests/litani/doc/templates/index.jinja.html +4 -0
  217. data/aws-crt-ffi/crt/s2n/tests/litani/examples/add-root-node/README +12 -0
  218. data/aws-crt-ffi/crt/s2n/tests/litani/examples/add-root-node/original-run.sh +52 -0
  219. data/aws-crt-ffi/crt/s2n/tests/litani/examples/add-root-node/run-all.py +71 -0
  220. data/aws-crt-ffi/crt/s2n/tests/litani/examples/no-standalone-transform/README +13 -0
  221. data/aws-crt-ffi/crt/s2n/tests/litani/examples/no-standalone-transform/run-1.sh +34 -0
  222. data/aws-crt-ffi/crt/s2n/tests/litani/examples/no-standalone-transform/run-2.sh +35 -0
  223. data/aws-crt-ffi/crt/s2n/tests/litani/examples/no-standalone-transform/run-3.sh +34 -0
  224. data/aws-crt-ffi/crt/s2n/tests/litani/examples/no-standalone-transform/run-all.py +60 -0
  225. data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/README.md +10 -0
  226. data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/assumptions.html +42 -0
  227. data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/file.dat +7 -0
  228. data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/histogram.dat +7 -0
  229. data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/run-1.sh +41 -0
  230. data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/run-2.sh +47 -0
  231. data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/run-3.sh +41 -0
  232. data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/run-all.py +34 -0
  233. data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/scripts/fib-table.py +40 -0
  234. data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/scripts/fib.plt +5 -0
  235. data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/scripts/fib.py +32 -0
  236. data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/scripts/sin-output.py +40 -0
  237. data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/scripts/sin.plt +5 -0
  238. data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/scripts/sin.py +30 -0
  239. data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/templates/fib-table.jinja.html +45 -0
  240. data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/templates/sin-output.jinja.html +30 -0
  241. data/aws-crt-ffi/crt/s2n/tests/litani/lib/add_job.py +55 -0
  242. data/aws-crt-ffi/crt/s2n/tests/litani/lib/graph.py +2 -2
  243. data/aws-crt-ffi/crt/s2n/tests/litani/lib/litani.py +6 -1
  244. data/aws-crt-ffi/crt/s2n/tests/litani/lib/litani_report.py +18 -21
  245. data/aws-crt-ffi/crt/s2n/tests/litani/lib/ninja.py +2 -0
  246. data/aws-crt-ffi/crt/s2n/tests/litani/lib/run_printer.py +26 -7
  247. data/aws-crt-ffi/crt/s2n/tests/litani/lib/transform_jobs.py +84 -0
  248. data/aws-crt-ffi/crt/s2n/tests/litani/litani +28 -33
  249. data/aws-crt-ffi/crt/s2n/tests/litani/script/release +220 -0
  250. data/aws-crt-ffi/crt/s2n/tests/litani/templates/dashboard.jinja.html +78 -15
  251. data/aws-crt-ffi/crt/s2n/tests/litani/templates/pipeline.jinja.html +21 -5
  252. data/aws-crt-ffi/crt/s2n/tests/litani/test/README +15 -0
  253. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/run +56 -33
  254. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/custom_stages.py +1 -0
  255. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/cwd.py +1 -0
  256. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/dump_run.py +1 -0
  257. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/graph_line_break.py +1 -0
  258. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/html_node.py +1 -0
  259. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/job_id_env.py +1 -0
  260. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/multiproc_dump_run.py +1 -0
  261. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/no_pool_serialize.py +1 -0
  262. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/no_pool_serialize_graph.py +1 -0
  263. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/no_timed_out.py +1 -0
  264. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/no_timed_out_timeout_ignored.py +1 -0
  265. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/no_timed_out_timeout_ok.py +1 -0
  266. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/pipeline_order.py +53 -0
  267. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/pool_serialize.py +1 -0
  268. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/pool_serialize_graph.py +1 -0
  269. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/single_pool.py +1 -0
  270. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/timed_out.py +1 -0
  271. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/timed_out_subprocess.py +1 -0
  272. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/timed_out_subprocess_multi_shell.py +1 -0
  273. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/timed_out_subprocess_shell.py +1 -0
  274. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/timed_out_timeout_ignored.py +1 -0
  275. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/timed_out_timeout_ok.py +1 -0
  276. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/transform_delete_job.py +54 -0
  277. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/transform_modify_job.py +46 -0
  278. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/transform_no_change_job.py +44 -0
  279. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/zero_pool.py +1 -0
  280. data/aws-crt-ffi/crt/s2n/tests/litani/test/run +82 -12
  281. data/aws-crt-ffi/crt/s2n/tests/s2n_test.h +58 -33
  282. data/aws-crt-ffi/crt/s2n/tests/testlib/s2n_key_schedule_testlib.c +18 -6
  283. data/aws-crt-ffi/crt/s2n/tests/testlib/s2n_pq_kat_test_utils.c +4 -4
  284. data/aws-crt-ffi/crt/s2n/tests/testlib/s2n_testlib.h +2 -0
  285. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_client_hello_retry_test.c +66 -2
  286. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_connection_test.c +1 -1
  287. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_drbg_test.c +34 -14
  288. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_fork_generation_number_test.c +28 -5
  289. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_mem_usage_test.c +6 -0
  290. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_override_openssl_random_test.c +1 -1
  291. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_random_test.c +60 -41
  292. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_self_talk_broken_pipe_test.c +2 -2
  293. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_tls13_handshake_early_data_test.c +3 -1
  294. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_tls13_hybrid_shared_secret_test.c +9 -1
  295. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_tls13_key_schedule_rfc8448_test.c +31 -130
  296. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_tls13_key_schedule_test.c +2 -4
  297. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_tls13_pq_handshake_test.c +11 -6
  298. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_tls13_secrets_rfc8448_test.c +19 -21
  299. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_tls13_secrets_test.c +109 -60
  300. data/aws-crt-ffi/crt/s2n/tls/s2n_config.c +1 -0
  301. data/aws-crt-ffi/crt/s2n/tls/s2n_config.h +1 -1
  302. data/aws-crt-ffi/crt/s2n/tls/s2n_connection.c +29 -24
  303. data/aws-crt-ffi/crt/s2n/tls/s2n_connection.h +5 -5
  304. data/aws-crt-ffi/crt/s2n/tls/s2n_handshake_hashes.h +1 -7
  305. data/aws-crt-ffi/crt/s2n/tls/s2n_handshake_io.c +2 -0
  306. data/aws-crt-ffi/crt/s2n/tls/s2n_handshake_transcript.c +0 -44
  307. data/aws-crt-ffi/crt/s2n/tls/s2n_internal.h +0 -1
  308. data/aws-crt-ffi/crt/s2n/tls/s2n_quic_support.h +1 -1
  309. data/aws-crt-ffi/crt/s2n/tls/s2n_tls13_key_schedule.c +1 -2
  310. data/aws-crt-ffi/crt/s2n/tls/s2n_tls13_secrets.c +84 -44
  311. data/aws-crt-ffi/crt/s2n/tls/s2n_tls13_secrets.h +3 -9
  312. data/aws-crt-ffi/crt/s2n/utils/s2n_blob.h +15 -8
  313. data/aws-crt-ffi/crt/s2n/utils/s2n_fork_detection.c +2 -6
  314. data/aws-crt-ffi/crt/s2n/utils/s2n_random.c +9 -9
  315. data/aws-crt-ffi/src/input_stream.c +32 -15
  316. data/ext/compile.rb +13 -5
  317. data/lib/aws-crt/platforms.rb +14 -5
  318. data/lib/aws-crt/string_blob.rb +3 -3
  319. metadata +61 -7
  320. data/aws-crt-ffi/crt/aws-c-auth/source/external/cJSON.c +0 -2987
  321. data/aws-crt-ffi/crt/aws-c-auth/tests/external/cJSON.c +0 -2986
  322. 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(options->request, stream->base.alloc);
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
- if (!rst_stream_frame) {
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
- int aws_h2_stream_on_activated(struct aws_h2_stream *stream, bool *out_has_outgoing_data) {
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
- bool has_body_stream = aws_http_message_get_body_stream(msg) != NULL;
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
- !has_body_stream /* end_stream */,
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 (has_body_stream) {
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
- *out_has_outgoing_data = has_body_stream;
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 *body = aws_http_message_get_body_stream(stream->thread_data.outgoing_message);
633
- AWS_ASSERT(body);
762
+ struct aws_input_stream *input_stream = s_h2_stream_get_data_stream(stream);
763
+ AWS_ASSERT(input_stream);
634
764
 
635
- bool body_complete;
636
- bool body_stalled;
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
- body,
641
- true /*body_ends_stream*/,
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
- &body_complete,
647
- &body_stalled)) {
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
- if (body_complete) {
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 (body_stalled) {
682
- *data_encode_status = AWS_H2_DATA_ENCODE_ONGOING_BODY_STALLED;
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 from
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
- if (name_enum == AWS_HTTP_HEADER_STATUS) {
753
- uint64_t status_code;
754
- int err = aws_byte_cursor_utf8_parse_u64(header->value, &status_code);
755
- AWS_ASSERT(!err && "Invalid :status value. Decoder should have already validated this");
756
- (void)err;
757
-
758
- stream->base.client_data->response_status = (int)status_code;
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
- if (total_padding_bytes != 0 && !end_stream && stream->base.owning_connection->stream_manual_window_management) {
892
- /**
893
- * Automatically update the flow-window to account for padding, even if "manual window management"
894
- * is enabled. We do this because the current API doesn't have any way to inform the user about padding,
895
- * so we can't expect them to manage it themselves.
896
- */
897
- if (s_stream_send_update_window(stream, total_padding_bytes)) {
898
- return aws_h2err_from_last_error();
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
- AWS_H2_STREAM_LOGF(
901
- DEBUG,
902
- stream,
903
- "DATA with %" PRIu32
904
- " padding. Updating the window for padding and one byte for padding length automatically for stream.",
905
- total_padding_bytes - 1 /* one byte for padding length */);
906
- }
907
- /* send a stream window_update frame to automatically maintain the stream self window size, if
908
- * manual_window_management is not set */
909
- if (payload_len != 0 && !end_stream && !stream->base.owning_connection->stream_manual_window_management) {
910
- if (s_stream_send_update_window(stream, payload_len)) {
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
+ }