summaryrefslogtreecommitdiffstats
path: root/contrib/restricted/aws/aws-c-http
diff options
context:
space:
mode:
authorthegeorg <[email protected]>2025-05-12 15:51:24 +0300
committerthegeorg <[email protected]>2025-05-12 16:06:27 +0300
commitd629bb70c8773d2c0c43f5088ddbb5a86d8c37ea (patch)
tree4f678e0d65ad08c800db21c657d3b0f71fafed06 /contrib/restricted/aws/aws-c-http
parent92c4b696d7a1c03d54e13aff7a7c20a078d90dd7 (diff)
Update contrib/restricted/aws libraries to nixpkgs 24.05
commit_hash:f8083acb039e6005e820cdee77b84e0a6b6c6d6d
Diffstat (limited to 'contrib/restricted/aws/aws-c-http')
-rw-r--r--contrib/restricted/aws/aws-c-http/.yandex_meta/override.nix4
-rw-r--r--contrib/restricted/aws/aws-c-http/include/aws/http/connection.h27
-rw-r--r--contrib/restricted/aws/aws-c-http/include/aws/http/connection_manager.h5
-rw-r--r--contrib/restricted/aws/aws-c-http/include/aws/http/http.h4
-rw-r--r--contrib/restricted/aws/aws-c-http/include/aws/http/http2_stream_manager.h6
-rw-r--r--contrib/restricted/aws/aws-c-http/include/aws/http/private/connection_impl.h9
-rw-r--r--contrib/restricted/aws/aws-c-http/include/aws/http/private/connection_manager_system_vtable.h28
-rw-r--r--contrib/restricted/aws/aws-c-http/include/aws/http/private/h1_stream.h1
-rw-r--r--contrib/restricted/aws/aws-c-http/include/aws/http/private/h2_connection.h1
-rw-r--r--contrib/restricted/aws/aws-c-http/include/aws/http/private/proxy_impl.h12
-rw-r--r--contrib/restricted/aws/aws-c-http/include/aws/http/private/request_response_impl.h8
-rw-r--r--contrib/restricted/aws/aws-c-http/include/aws/http/proxy.h5
-rw-r--r--contrib/restricted/aws/aws-c-http/include/aws/http/request_response.h104
-rw-r--r--contrib/restricted/aws/aws-c-http/include/aws/http/server.h9
-rw-r--r--contrib/restricted/aws/aws-c-http/include/aws/http/statistics.h3
-rw-r--r--contrib/restricted/aws/aws-c-http/include/aws/http/websocket.h11
-rw-r--r--contrib/restricted/aws/aws-c-http/source/connection.c37
-rw-r--r--contrib/restricted/aws/aws-c-http/source/connection_manager.c45
-rw-r--r--contrib/restricted/aws/aws-c-http/source/h1_connection.c153
-rw-r--r--contrib/restricted/aws/aws-c-http/source/h1_decoder.c2
-rw-r--r--contrib/restricted/aws/aws-c-http/source/h1_encoder.c9
-rw-r--r--contrib/restricted/aws/aws-c-http/source/h1_stream.c9
-rw-r--r--contrib/restricted/aws/aws-c-http/source/h2_connection.c3
-rw-r--r--contrib/restricted/aws/aws-c-http/source/h2_stream.c72
-rw-r--r--contrib/restricted/aws/aws-c-http/source/hpack.c2
-rw-r--r--contrib/restricted/aws/aws-c-http/source/http.c5
-rw-r--r--contrib/restricted/aws/aws-c-http/source/proxy_connection.c55
-rw-r--r--contrib/restricted/aws/aws-c-http/source/request_response.c25
-rw-r--r--contrib/restricted/aws/aws-c-http/source/websocket_bootstrap.c3
-rw-r--r--contrib/restricted/aws/aws-c-http/ya.make4
30 files changed, 544 insertions, 117 deletions
diff --git a/contrib/restricted/aws/aws-c-http/.yandex_meta/override.nix b/contrib/restricted/aws/aws-c-http/.yandex_meta/override.nix
index e3d0ccc4c91..5088ed27063 100644
--- a/contrib/restricted/aws/aws-c-http/.yandex_meta/override.nix
+++ b/contrib/restricted/aws/aws-c-http/.yandex_meta/override.nix
@@ -1,10 +1,10 @@
pkgs: attrs: with pkgs; with attrs; rec {
- version = "0.7.6";
+ version = "0.8.1";
src = fetchFromGitHub {
owner = "awslabs";
repo = "aws-c-http";
rev = "v${version}";
- hash = "sha256-pJGzGbIuz8UJkfmTQEZgXSOMuYixMezNZmgaRlcnmfg=";
+ hash = "sha256-S5ETVkdGTndt2GJBNL4DU5SycHAufsmN06xBDRMFVKo=";
};
}
diff --git a/contrib/restricted/aws/aws-c-http/include/aws/http/connection.h b/contrib/restricted/aws/aws-c-http/include/aws/http/connection.h
index e6362c1439e..031957ef0f1 100644
--- a/contrib/restricted/aws/aws-c-http/include/aws/http/connection.h
+++ b/contrib/restricted/aws/aws-c-http/include/aws/http/connection.h
@@ -8,8 +8,11 @@
#include <aws/http/http.h>
+AWS_PUSH_SANE_WARNING_LEVEL
+
struct aws_client_bootstrap;
struct aws_socket_options;
+struct aws_socket_endpoint;
struct aws_tls_connection_options;
struct aws_http2_setting;
struct proxy_env_var_settings;
@@ -269,7 +272,7 @@ struct aws_http_client_connection_options {
/**
* Required.
*/
- uint16_t port;
+ uint32_t port;
/**
* Required.
@@ -305,6 +308,15 @@ struct aws_http_client_connection_options {
const struct aws_http_connection_monitoring_options *monitoring_options;
/**
+ * Optional (ignored if 0).
+ * After a request is fully sent, if the server does not begin responding within N milliseconds,
+ * then fail with AWS_ERROR_HTTP_RESPONSE_FIRST_BYTE_TIMEOUT.
+ * This can be overridden per-request by aws_http_make_request_options.response_first_byte_timeout_ms.
+ * TODO: Only supported in HTTP/1.1 now, support it in HTTP/2
+ */
+ uint64_t response_first_byte_timeout_ms;
+
+ /**
* Set to true to manually manage the flow-control window of each stream.
*
* If false, the connection will maintain its flow-control windows such that
@@ -398,6 +410,12 @@ struct aws_http_client_connection_options {
* event loop group associated with the client bootstrap.
*/
struct aws_event_loop *requested_event_loop;
+
+ /**
+ * Optional
+ * Host resolution override that allows the user to override DNS behavior for this particular connection.
+ */
+ const struct aws_host_resolution_config *host_resolution_config;
};
/* Predefined settings identifiers (RFC-7540 6.5.2) */
@@ -507,6 +525,12 @@ AWS_HTTP_API
struct aws_channel *aws_http_connection_get_channel(struct aws_http_connection *connection);
/**
+ * Returns the remote endpoint of the HTTP connection.
+ */
+AWS_HTTP_API
+const struct aws_socket_endpoint *aws_http_connection_get_remote_endpoint(const struct aws_http_connection *connection);
+
+/**
* Initialize an map copied from the *src map, which maps `struct aws_string *` to `enum aws_http_version`.
*/
AWS_HTTP_API
@@ -675,5 +699,6 @@ AWS_HTTP_API
void aws_http2_connection_update_window(struct aws_http_connection *http2_connection, uint32_t increment_size);
AWS_EXTERN_C_END
+AWS_POP_SANE_WARNING_LEVEL
#endif /* AWS_HTTP_CONNECTION_H */
diff --git a/contrib/restricted/aws/aws-c-http/include/aws/http/connection_manager.h b/contrib/restricted/aws/aws-c-http/include/aws/http/connection_manager.h
index 4c02df9382a..70b1e77b82d 100644
--- a/contrib/restricted/aws/aws-c-http/include/aws/http/connection_manager.h
+++ b/contrib/restricted/aws/aws-c-http/include/aws/http/connection_manager.h
@@ -10,6 +10,8 @@
#include <aws/common/byte_buf.h>
+AWS_PUSH_SANE_WARNING_LEVEL
+
struct aws_client_bootstrap;
struct aws_http_connection;
struct aws_http_connection_manager;
@@ -78,7 +80,7 @@ struct aws_http_connection_manager_options {
const struct aws_http_connection_monitoring_options *monitoring_options;
struct aws_byte_cursor host;
- uint16_t port;
+ uint32_t port;
/**
* Optional.
@@ -190,5 +192,6 @@ void aws_http_connection_manager_fetch_metrics(
struct aws_http_manager_metrics *out_metrics);
AWS_EXTERN_C_END
+AWS_POP_SANE_WARNING_LEVEL
#endif /* AWS_HTTP_CONNECTION_MANAGER_H */
diff --git a/contrib/restricted/aws/aws-c-http/include/aws/http/http.h b/contrib/restricted/aws/aws-c-http/include/aws/http/http.h
index f02f09dc3e6..7532537d2f8 100644
--- a/contrib/restricted/aws/aws-c-http/include/aws/http/http.h
+++ b/contrib/restricted/aws/aws-c-http/include/aws/http/http.h
@@ -10,6 +10,8 @@
#include <aws/http/exports.h>
#include <aws/io/io.h>
+AWS_PUSH_SANE_WARNING_LEVEL
+
#define AWS_C_HTTP_PACKAGE_ID 2
enum aws_http_errors {
@@ -57,6 +59,7 @@ enum aws_http_errors {
AWS_ERROR_HTTP_WEBSOCKET_PROTOCOL_ERROR,
AWS_ERROR_HTTP_MANUAL_WRITE_NOT_ENABLED,
AWS_ERROR_HTTP_MANUAL_WRITE_HAS_COMPLETED,
+ AWS_ERROR_HTTP_RESPONSE_FIRST_BYTE_TIMEOUT,
AWS_ERROR_HTTP_END_RANGE = AWS_ERROR_ENUM_END_RANGE(AWS_C_HTTP_PACKAGE_ID)
};
@@ -154,5 +157,6 @@ AWS_HTTP_API extern const struct aws_byte_cursor aws_http_scheme_http;
AWS_HTTP_API extern const struct aws_byte_cursor aws_http_scheme_https;
AWS_EXTERN_C_END
+AWS_POP_SANE_WARNING_LEVEL
#endif /* AWS_HTTP_H */
diff --git a/contrib/restricted/aws/aws-c-http/include/aws/http/http2_stream_manager.h b/contrib/restricted/aws/aws-c-http/include/aws/http/http2_stream_manager.h
index c37da489aa6..bd78677598b 100644
--- a/contrib/restricted/aws/aws-c-http/include/aws/http/http2_stream_manager.h
+++ b/contrib/restricted/aws/aws-c-http/include/aws/http/http2_stream_manager.h
@@ -8,6 +8,8 @@
#include <aws/http/http.h>
+AWS_PUSH_SANE_WARNING_LEVEL
+
struct aws_http2_stream_manager;
struct aws_client_bootstrap;
struct aws_http_connection;
@@ -66,7 +68,7 @@ struct aws_http2_stream_manager_options {
bool http2_prior_knowledge;
struct aws_byte_cursor host;
- uint16_t port;
+ uint32_t port;
/**
* Optional.
@@ -212,4 +214,6 @@ void aws_http2_stream_manager_fetch_metrics(
struct aws_http_manager_metrics *out_metrics);
AWS_EXTERN_C_END
+AWS_POP_SANE_WARNING_LEVEL
+
#endif /* AWS_HTTP2_STREAM_MANAGER_H */
diff --git a/contrib/restricted/aws/aws-c-http/include/aws/http/private/connection_impl.h b/contrib/restricted/aws/aws-c-http/include/aws/http/private/connection_impl.h
index a97ab0daba9..fd9c915ab29 100644
--- a/contrib/restricted/aws/aws-c-http/include/aws/http/private/connection_impl.h
+++ b/contrib/restricted/aws/aws-c-http/include/aws/http/private/connection_impl.h
@@ -20,10 +20,10 @@ struct aws_http_make_request_options;
struct aws_http_request_handler_options;
struct aws_http_stream;
-typedef int aws_client_bootstrap_new_socket_channel_fn(struct aws_socket_channel_bootstrap_options *options);
-
+/* vtable of functions that aws_http_connection uses to interact with external systems.
+ * tests override the vtable to mock those systems */
struct aws_http_connection_system_vtable {
- aws_client_bootstrap_new_socket_channel_fn *new_socket_channel;
+ int (*aws_client_bootstrap_new_socket_channel)(struct aws_socket_channel_bootstrap_options *options);
};
struct aws_http_connection_vtable {
@@ -103,7 +103,7 @@ struct aws_http_connection {
union {
struct aws_http_connection_client_data {
- uint8_t delete_me; /* exists to prevent "empty struct" errors */
+ uint64_t response_first_byte_timeout_ms;
} client;
struct aws_http_connection_server_data {
@@ -133,6 +133,7 @@ struct aws_http_client_bootstrap {
aws_http_on_client_connection_setup_fn *on_setup;
aws_http_on_client_connection_shutdown_fn *on_shutdown;
aws_http_proxy_request_transform_fn *proxy_request_transform;
+ uint64_t response_first_byte_timeout_ms;
struct aws_http1_connection_options http1_options;
struct aws_http2_connection_options http2_options; /* allocated with bootstrap */
diff --git a/contrib/restricted/aws/aws-c-http/include/aws/http/private/connection_manager_system_vtable.h b/contrib/restricted/aws/aws-c-http/include/aws/http/private/connection_manager_system_vtable.h
index 115ba661364..d5d183b82ed 100644
--- a/contrib/restricted/aws/aws-c-http/include/aws/http/private/connection_manager_system_vtable.h
+++ b/contrib/restricted/aws/aws-c-http/include/aws/http/private/connection_manager_system_vtable.h
@@ -12,28 +12,20 @@
struct aws_http_connection_manager;
-typedef int(aws_http_connection_manager_create_connection_fn)(const struct aws_http_client_connection_options *options);
-typedef void(aws_http_connection_manager_close_connection_fn)(struct aws_http_connection *connection);
-typedef void(aws_http_connection_release_connection_fn)(struct aws_http_connection *connection);
-typedef bool(aws_http_connection_is_connection_available_fn)(const struct aws_http_connection *connection);
-typedef bool(aws_http_connection_manager_is_callers_thread_fn)(struct aws_channel *channel);
-typedef struct aws_channel *(aws_http_connection_manager_connection_get_channel_fn)(
- struct aws_http_connection *connection);
-typedef enum aws_http_version(aws_http_connection_manager_connection_get_version_fn)(
- const struct aws_http_connection *connection);
-
+/* vtable of functions that aws_http_connection_manager uses to interact with external systems.
+ * tests override the vtable to mock those systems */
struct aws_http_connection_manager_system_vtable {
/*
* Downstream http functions
*/
- aws_http_connection_manager_create_connection_fn *create_connection;
- aws_http_connection_manager_close_connection_fn *close_connection;
- aws_http_connection_release_connection_fn *release_connection;
- aws_http_connection_is_connection_available_fn *is_connection_available;
- aws_io_clock_fn *get_monotonic_time;
- aws_http_connection_manager_is_callers_thread_fn *is_callers_thread;
- aws_http_connection_manager_connection_get_channel_fn *connection_get_channel;
- aws_http_connection_manager_connection_get_version_fn *connection_get_version;
+ int (*aws_http_client_connect)(const struct aws_http_client_connection_options *options);
+ void (*aws_http_connection_close)(struct aws_http_connection *connection);
+ void (*aws_http_connection_release)(struct aws_http_connection *connection);
+ bool (*aws_http_connection_new_requests_allowed)(const struct aws_http_connection *connection);
+ int (*aws_high_res_clock_get_ticks)(uint64_t *timestamp);
+ bool (*aws_channel_thread_is_callers_thread)(struct aws_channel *channel);
+ struct aws_channel *(*aws_http_connection_get_channel)(struct aws_http_connection *connection);
+ enum aws_http_version (*aws_http_connection_get_version)(const struct aws_http_connection *connection);
};
AWS_HTTP_API
diff --git a/contrib/restricted/aws/aws-c-http/include/aws/http/private/h1_stream.h b/contrib/restricted/aws/aws-c-http/include/aws/http/private/h1_stream.h
index df1446ec9b3..8b210c8b1dd 100644
--- a/contrib/restricted/aws/aws-c-http/include/aws/http/private/h1_stream.h
+++ b/contrib/restricted/aws/aws-c-http/include/aws/http/private/h1_stream.h
@@ -117,6 +117,7 @@ struct aws_h1_stream *aws_h1_stream_new_request(
struct aws_h1_stream *aws_h1_stream_new_request_handler(const struct aws_http_request_handler_options *options);
int aws_h1_stream_activate(struct aws_http_stream *stream);
+void aws_h1_stream_cancel(struct aws_http_stream *stream, int error_code);
int aws_h1_stream_send_response(struct aws_h1_stream *stream, struct aws_http_message *response);
diff --git a/contrib/restricted/aws/aws-c-http/include/aws/http/private/h2_connection.h b/contrib/restricted/aws/aws-c-http/include/aws/http/private/h2_connection.h
index 6d42b831602..f2754ab754d 100644
--- a/contrib/restricted/aws/aws-c-http/include/aws/http/private/h2_connection.h
+++ b/contrib/restricted/aws/aws-c-http/include/aws/http/private/h2_connection.h
@@ -125,6 +125,7 @@ struct aws_h2_connection {
uint64_t outgoing_timestamp_ns;
/* Timestamp when connection has data to receive, which is when there is an active stream */
uint64_t incoming_timestamp_ns;
+
} thread_data;
/* Any thread may touch this data, but the lock must be held (unless it's an atomic) */
diff --git a/contrib/restricted/aws/aws-c-http/include/aws/http/private/proxy_impl.h b/contrib/restricted/aws/aws-c-http/include/aws/http/private/proxy_impl.h
index c47305b251e..946fece72b3 100644
--- a/contrib/restricted/aws/aws-c-http/include/aws/http/private/proxy_impl.h
+++ b/contrib/restricted/aws/aws-c-http/include/aws/http/private/proxy_impl.h
@@ -52,7 +52,7 @@ struct aws_http_proxy_config {
struct aws_byte_buf host;
- uint16_t port;
+ uint32_t port;
struct aws_tls_connection_options *tls_options;
@@ -97,7 +97,7 @@ struct aws_http_proxy_user_data {
* Cached original connect options
*/
struct aws_string *original_host;
- uint16_t original_port;
+ uint32_t original_port;
void *original_user_data;
struct aws_tls_connection_options *original_tls_options;
struct aws_client_bootstrap *original_bootstrap;
@@ -126,10 +126,16 @@ struct aws_http_proxy_user_data {
struct aws_http_proxy_config *proxy_config;
struct aws_event_loop *requested_event_loop;
+
+ const struct aws_host_resolution_config *host_resolution_config;
};
+/* vtable of functions that proxy uses to interact with external systems.
+ * tests override the vtable to mock those systems */
struct aws_http_proxy_system_vtable {
- int (*setup_client_tls)(struct aws_channel_slot *right_of_slot, struct aws_tls_connection_options *tls_options);
+ int (*aws_channel_setup_client_tls)(
+ struct aws_channel_slot *right_of_slot,
+ struct aws_tls_connection_options *tls_options);
};
AWS_EXTERN_C_BEGIN
diff --git a/contrib/restricted/aws/aws-c-http/include/aws/http/private/request_response_impl.h b/contrib/restricted/aws/aws-c-http/include/aws/http/private/request_response_impl.h
index 9cd06e01c24..acc5d9dd7db 100644
--- a/contrib/restricted/aws/aws-c-http/include/aws/http/private/request_response_impl.h
+++ b/contrib/restricted/aws/aws-c-http/include/aws/http/private/request_response_impl.h
@@ -6,6 +6,7 @@
* SPDX-License-Identifier: Apache-2.0.
*/
+#include <aws/common/task_scheduler.h>
#include <aws/http/request_response.h>
#include <aws/http/private/http_impl.h>
@@ -16,6 +17,7 @@ struct aws_http_stream_vtable {
void (*destroy)(struct aws_http_stream *stream);
void (*update_window)(struct aws_http_stream *stream, size_t increment_size);
int (*activate)(struct aws_http_stream *stream);
+ void (*cancel)(struct aws_http_stream *stream, int error_code);
int (*http1_write_chunk)(struct aws_http_stream *http1_stream, const struct aws_http1_chunk_options *options);
int (*http1_add_trailer)(struct aws_http_stream *http1_stream, const struct aws_http_headers *trailing_headers);
@@ -43,15 +45,21 @@ struct aws_http_stream {
aws_http_on_incoming_headers_fn *on_incoming_headers;
aws_http_on_incoming_header_block_done_fn *on_incoming_header_block_done;
aws_http_on_incoming_body_fn *on_incoming_body;
+ aws_http_on_stream_metrics_fn *on_metrics;
aws_http_on_stream_complete_fn *on_complete;
aws_http_on_stream_destroy_fn *on_destroy;
struct aws_atomic_var refcount;
enum aws_http_method request_method;
+ struct aws_http_stream_metrics metrics;
union {
struct aws_http_stream_client_data {
int response_status;
+ uint64_t response_first_byte_timeout_ms;
+ /* Using aws_task instead of aws_channel_task because, currently, channel-tasks can't be canceled.
+ * We only touch this from the connection's thread */
+ struct aws_task response_first_byte_timeout_task;
} client;
struct aws_http_stream_server_data {
struct aws_byte_cursor request_method_str;
diff --git a/contrib/restricted/aws/aws-c-http/include/aws/http/proxy.h b/contrib/restricted/aws/aws-c-http/include/aws/http/proxy.h
index cd4c92107df..28fdfb045b5 100644
--- a/contrib/restricted/aws/aws-c-http/include/aws/http/proxy.h
+++ b/contrib/restricted/aws/aws-c-http/include/aws/http/proxy.h
@@ -11,6 +11,8 @@
#include <aws/http/request_response.h>
#include <aws/http/status_code.h>
+AWS_PUSH_SANE_WARNING_LEVEL
+
struct aws_http_client_connection_options;
struct aws_http_connection_manager_options;
@@ -112,7 +114,7 @@ struct aws_http_proxy_options {
/**
* Port to make the proxy connection to
*/
- uint16_t port;
+ uint32_t port;
/**
* Optional.
@@ -566,5 +568,6 @@ AWS_HTTP_API int aws_http_proxy_new_socket_channel(
const struct aws_http_proxy_options *proxy_options);
AWS_EXTERN_C_END
+AWS_POP_SANE_WARNING_LEVEL
#endif /* AWS_PROXY_STRATEGY_H */
diff --git a/contrib/restricted/aws/aws-c-http/include/aws/http/request_response.h b/contrib/restricted/aws/aws-c-http/include/aws/http/request_response.h
index a4ff6da9477..73c1900508f 100644
--- a/contrib/restricted/aws/aws-c-http/include/aws/http/request_response.h
+++ b/contrib/restricted/aws/aws-c-http/include/aws/http/request_response.h
@@ -8,6 +8,10 @@
#include <aws/http/http.h>
+#include <aws/io/future.h>
+
+AWS_PUSH_SANE_WARNING_LEVEL
+
struct aws_http_connection;
struct aws_input_stream;
@@ -135,7 +139,8 @@ typedef void(aws_http_message_transform_fn)(
* This is always invoked on the HTTP connection's event-loop thread.
*
* Return AWS_OP_SUCCESS to continue processing the stream.
- * Return AWS_OP_ERR to indicate failure and cancel the stream.
+ * Return aws_raise_error(E) to indicate failure and cancel the stream.
+ * The error you raise will be reflected in the error_code passed to the on_complete callback.
*/
typedef int(aws_http_on_incoming_headers_fn)(
struct aws_http_stream *stream,
@@ -149,7 +154,8 @@ typedef int(aws_http_on_incoming_headers_fn)(
* This is always invoked on the HTTP connection's event-loop thread.
*
* Return AWS_OP_SUCCESS to continue processing the stream.
- * Return AWS_OP_ERR to indicate failure and cancel the stream.
+ * Return aws_raise_error(E) to indicate failure and cancel the stream.
+ * The error you raise will be reflected in the error_code passed to the on_complete callback.
*/
typedef int(aws_http_on_incoming_header_block_done_fn)(
struct aws_http_stream *stream,
@@ -167,7 +173,8 @@ typedef int(aws_http_on_incoming_header_block_done_fn)(
* aws_http_stream_update_window().
*
* Return AWS_OP_SUCCESS to continue processing the stream.
- * Return AWS_OP_ERR to indicate failure and cancel the stream.
+ * Return aws_raise_error(E) to indicate failure and cancel the stream.
+ * The error you raise will be reflected in the error_code passed to the on_complete callback.
*/
typedef int(
aws_http_on_incoming_body_fn)(struct aws_http_stream *stream, const struct aws_byte_cursor *data, void *user_data);
@@ -177,24 +184,66 @@ typedef int(
* This is always invoked on the HTTP connection's event-loop thread.
*
* Return AWS_OP_SUCCESS to continue processing the stream.
- * Return AWS_OP_ERR to indicate failure and cancel the stream.
+ * Return aws_raise_error(E) to indicate failure and cancel the stream.
+ * The error you raise will be reflected in the error_code passed to the on_complete callback.
*/
typedef int(aws_http_on_incoming_request_done_fn)(struct aws_http_stream *stream, void *user_data);
/**
- * Invoked when request/response stream is completely destroyed.
- * This may be invoked synchronously when aws_http_stream_release() is called.
- * This is invoked even if the stream is never activated.
+ * Invoked when a request/response stream is complete, whether successful or unsuccessful
+ * This is always invoked on the HTTP connection's event-loop thread.
+ * This will not be invoked if the stream is never activated.
*/
typedef void(aws_http_on_stream_complete_fn)(struct aws_http_stream *stream, int error_code, void *user_data);
/**
* Invoked when request/response stream destroy completely.
* This can be invoked within the same thead who release the refcount on http stream.
+ * This is invoked even if the stream is never activated.
*/
typedef void(aws_http_on_stream_destroy_fn)(void *user_data);
/**
+ * Tracing metrics for aws_http_stream.
+ * Data maybe not be available if the data of stream was never sent/received before it completes.
+ */
+struct aws_http_stream_metrics {
+ /* The time stamp when the request started to be encoded. -1 means data not available. Timestamp
+ * are from `aws_high_res_clock_get_ticks` */
+ int64_t send_start_timestamp_ns;
+ /* The time stamp when the request finished to be encoded. -1 means data not available.
+ * Timestamp are from `aws_high_res_clock_get_ticks` */
+ int64_t send_end_timestamp_ns;
+ /* The time duration for the request from start encoding to finish encoding (send_end_timestamp_ns -
+ * send_start_timestamp_ns). -1 means data not available. */
+ int64_t sending_duration_ns;
+
+ /* The time stamp when the response started to be received from the network channel. -1 means data not available.
+ * Timestamp are from `aws_high_res_clock_get_ticks` */
+ int64_t receive_start_timestamp_ns;
+ /* The time stamp when the response finished to be received from the network channel. -1 means data not available.
+ * Timestamp are from `aws_high_res_clock_get_ticks` */
+ int64_t receive_end_timestamp_ns;
+ /* The time duration for the request from start receiving to finish receiving. receive_end_timestamp_ns -
+ * receive_start_timestamp_ns. -1 means data not available. */
+ int64_t receiving_duration_ns;
+
+ /* The stream-id on the connection when this stream was activated. */
+ uint32_t stream_id;
+};
+
+/**
+ * Invoked right before request/response stream is complete to report the tracing metrics for aws_http_stream.
+ * This may be invoked synchronously when aws_http_stream_release() is called.
+ * This is invoked even if the stream is never activated.
+ * See `aws_http_stream_metrics` for details.
+ */
+typedef void(aws_http_on_stream_metrics_fn)(
+ struct aws_http_stream *stream,
+ const struct aws_http_stream_metrics *metrics,
+ void *user_data);
+
+/**
* Options for creating a stream which sends a request from the client and receives a response from the server.
*/
struct aws_http_make_request_options {
@@ -235,6 +284,13 @@ struct aws_http_make_request_options {
aws_http_on_incoming_body_fn *on_response_body;
/**
+ * Invoked right before stream is complete, whether successful or unsuccessful
+ * Optional.
+ * See `aws_http_on_stream_metrics_fn`
+ */
+ aws_http_on_stream_metrics_fn *on_metrics;
+
+ /**
* Invoked when request/response stream is complete, whether successful or unsuccessful
* Optional.
* See `aws_http_on_stream_complete_fn`.
@@ -249,6 +305,16 @@ struct aws_http_make_request_options {
* when data has been supplied via `aws_http2_stream_write_data`
*/
bool http2_use_manual_data_writes;
+
+ /**
+ * Optional (ignored if 0).
+ * After a request is fully sent, if the server does not begin responding within N milliseconds, then fail with
+ * AWS_ERROR_HTTP_RESPONSE_FIRST_BYTE_TIMEOUT.
+ * It override the connection level settings, when the request completes, the
+ * original monitoring options will be applied back to the connection.
+ * TODO: Only supported in HTTP/1.1 now, support it in HTTP/2
+ */
+ uint64_t response_first_byte_timeout_ms;
};
struct aws_http_request_handler_options {
@@ -807,6 +873,11 @@ AWS_HTTP_API
void aws_http_message_set_body_stream(struct aws_http_message *message, struct aws_input_stream *body_stream);
/**
+ * aws_future<aws_http_message*>
+ */
+AWS_FUTURE_T_POINTER_WITH_RELEASE_DECLARATION(aws_future_http_message, struct aws_http_message, AWS_HTTP_API)
+
+/**
* Submit a chunk of data to be sent on an HTTP/1.1 stream.
* The stream must have specified "chunked" in a "transfer-encoding" header.
* For client streams, activate() must be called before any chunks are submitted.
@@ -973,6 +1044,12 @@ struct aws_http_stream *aws_http_stream_new_server_request_handler(
const struct aws_http_request_handler_options *options);
/**
+ * Acquire refcount on the stream to prevent it from being cleaned up until it is released.
+ */
+AWS_HTTP_API
+struct aws_http_stream *aws_http_stream_acquire(struct aws_http_stream *stream);
+
+/**
* Users must release the stream when they are done with it, or its memory will never be cleaned up.
* This will not cancel the stream, its callbacks will still fire if the stream is still in progress.
*
@@ -1038,6 +1115,18 @@ AWS_HTTP_API
uint32_t aws_http_stream_get_id(const struct aws_http_stream *stream);
/**
+ * Cancel the stream in flight.
+ * For HTTP/1.1 streams, it's equivalent to closing the connection.
+ * For HTTP/2 streams, it's equivalent to calling reset on the stream with `AWS_HTTP2_ERR_CANCEL`.
+ *
+ * the stream will complete with the error code provided, unless the stream is
+ * already completing for other reasons, or the stream is not activated,
+ * in which case this call will have no impact.
+ */
+AWS_HTTP_API
+void aws_http_stream_cancel(struct aws_http_stream *stream, int error_code);
+
+/**
* Reset the HTTP/2 stream (HTTP/2 only).
* Note that if the stream closes before this async call is fully processed, the RST_STREAM frame will not be sent.
*
@@ -1068,5 +1157,6 @@ AWS_HTTP_API
int aws_http2_stream_get_sent_reset_error_code(struct aws_http_stream *http2_stream, uint32_t *out_http2_error);
AWS_EXTERN_C_END
+AWS_POP_SANE_WARNING_LEVEL
#endif /* AWS_HTTP_REQUEST_RESPONSE_H */
diff --git a/contrib/restricted/aws/aws-c-http/include/aws/http/server.h b/contrib/restricted/aws/aws-c-http/include/aws/http/server.h
index 0e1be3d8c01..03893355d8a 100644
--- a/contrib/restricted/aws/aws-c-http/include/aws/http/server.h
+++ b/contrib/restricted/aws/aws-c-http/include/aws/http/server.h
@@ -8,6 +8,8 @@
#include <aws/http/http.h>
+AWS_PUSH_SANE_WARNING_LEVEL
+
struct aws_http_connection;
struct aws_server_bootstrap;
struct aws_socket_options;
@@ -193,6 +195,13 @@ int aws_http_connection_configure_server(
AWS_HTTP_API
bool aws_http_connection_is_server(const struct aws_http_connection *connection);
+/**
+ * Returns the local listener endpoint of the HTTP server. Only valid as long as the server remains valid.
+ */
+AWS_HTTP_API
+const struct aws_socket_endpoint *aws_http_server_get_listener_endpoint(const struct aws_http_server *server);
+
AWS_EXTERN_C_END
+AWS_POP_SANE_WARNING_LEVEL
#endif /* AWS_HTTP_SERVER_H */
diff --git a/contrib/restricted/aws/aws-c-http/include/aws/http/statistics.h b/contrib/restricted/aws/aws-c-http/include/aws/http/statistics.h
index ecc8c2700ab..7f3790242e0 100644
--- a/contrib/restricted/aws/aws-c-http/include/aws/http/statistics.h
+++ b/contrib/restricted/aws/aws-c-http/include/aws/http/statistics.h
@@ -10,6 +10,8 @@
#include <aws/common/statistics.h>
+AWS_PUSH_SANE_WARNING_LEVEL
+
enum aws_crt_http_statistics_category {
AWSCRT_STAT_CAT_HTTP1_CHANNEL = AWS_CRT_STATISTICS_CATEGORY_BEGIN_RANGE(AWS_C_HTTP_PACKAGE_ID),
AWSCRT_STAT_CAT_HTTP2_CHANNEL,
@@ -71,5 +73,6 @@ AWS_HTTP_API
void aws_crt_statistics_http2_channel_reset(struct aws_crt_statistics_http2_channel *stats);
AWS_EXTERN_C_END
+AWS_POP_SANE_WARNING_LEVEL
#endif /* AWS_HTTP_STATISTICS_H */
diff --git a/contrib/restricted/aws/aws-c-http/include/aws/http/websocket.h b/contrib/restricted/aws/aws-c-http/include/aws/http/websocket.h
index 6f85cafa810..39703b4e2bb 100644
--- a/contrib/restricted/aws/aws-c-http/include/aws/http/websocket.h
+++ b/contrib/restricted/aws/aws-c-http/include/aws/http/websocket.h
@@ -7,6 +7,8 @@
#include <aws/http/http.h>
+AWS_PUSH_SANE_WARNING_LEVEL
+
struct aws_http_header;
struct aws_http_message;
@@ -183,7 +185,7 @@ struct aws_websocket_client_connection_options {
* Optional.
* Defaults to 443 if tls_options is present, 80 if it is not.
*/
- uint16_t port;
+ uint32_t port;
/**
* Required.
@@ -280,6 +282,12 @@ struct aws_websocket_client_connection_options {
* a single thread.
*/
struct aws_event_loop *requested_event_loop;
+
+ /**
+ * Optional
+ * Host resolution override that allows the user to override DNS behavior for this particular connection.
+ */
+ const struct aws_host_resolution_config *host_resolution_config;
};
/**
@@ -479,5 +487,6 @@ struct aws_http_message *aws_http_message_new_websocket_handshake_request(
struct aws_byte_cursor host);
AWS_EXTERN_C_END
+AWS_POP_SANE_WARNING_LEVEL
#endif /* AWS_HTTP_WEBSOCKET_H */
diff --git a/contrib/restricted/aws/aws-c-http/source/connection.c b/contrib/restricted/aws/aws-c-http/source/connection.c
index f020823dcf1..a53aebe1912 100644
--- a/contrib/restricted/aws/aws-c-http/source/connection.c
+++ b/contrib/restricted/aws/aws-c-http/source/connection.c
@@ -18,6 +18,7 @@
#include <aws/io/channel_bootstrap.h>
#include <aws/io/logging.h>
#include <aws/io/socket.h>
+#include <aws/io/socket_channel_handler.h>
#include <aws/io/tls_channel_handler.h>
#ifdef _MSC_VER
@@ -26,7 +27,7 @@
#endif
static struct aws_http_connection_system_vtable s_default_system_vtable = {
- .new_socket_channel = aws_client_bootstrap_new_socket_channel,
+ .aws_client_bootstrap_new_socket_channel = aws_client_bootstrap_new_socket_channel,
};
static const struct aws_http_connection_system_vtable *s_system_vtable_ptr = &s_default_system_vtable;
@@ -366,6 +367,16 @@ struct aws_channel *aws_http_connection_get_channel(struct aws_http_connection *
return connection->channel_slot->channel;
}
+const struct aws_socket_endpoint *aws_http_connection_get_remote_endpoint(
+ const struct aws_http_connection *connection) {
+ AWS_ASSERT(connection);
+ struct aws_channel *channel = connection->channel_slot->channel;
+ /* The first slot for an HTTP connection is always socket */
+ struct aws_channel_slot *socket_slot = aws_channel_get_first_slot(channel);
+ const struct aws_socket *socket = aws_socket_handler_get_socket(socket_slot->handler);
+ return &socket->remote_endpoint;
+}
+
int aws_http_alpn_map_init(struct aws_allocator *allocator, struct aws_hash_table *map) {
AWS_ASSERT(allocator);
AWS_ASSERT(map);
@@ -495,7 +506,7 @@ static void s_server_bootstrap_on_accept_channel_setup(
if (put_err) {
AWS_LOGF_ERROR(
AWS_LS_HTTP_SERVER,
- "%p: %s:%d: Failed to store connection object, error %d (%s).",
+ "%p: %s:%u: Failed to store connection object, error %d (%s).",
(void *)server,
server->socket->local_endpoint.address,
server->socket->local_endpoint.port,
@@ -508,7 +519,7 @@ static void s_server_bootstrap_on_accept_channel_setup(
/* Tell user of successful connection. */
AWS_LOGF_INFO(
AWS_LS_HTTP_CONNECTION,
- "id=%p: " PRInSTR " server connection established at %p %s:%d.",
+ "id=%p: " PRInSTR " server connection established at %p %s:%u.",
(void *)connection,
AWS_BYTE_CURSOR_PRI(aws_http_version_to_str(connection->http_version)),
(void *)server,
@@ -690,7 +701,7 @@ struct aws_http_server *aws_http_server_new(const struct aws_http_server_options
AWS_LOGF_INFO(
AWS_LS_HTTP_SERVER,
- "%p %s:%d: Server setup complete, listening for incoming connections.",
+ "%p %s:%u: Server setup complete, listening for incoming connections.",
(void *)server,
server->socket->local_endpoint.address,
server->socket->local_endpoint.port);
@@ -740,7 +751,7 @@ void aws_http_server_release(struct aws_http_server *server) {
* s_server_bootstrap_on_server_listener_destroy will be invoked, clean up of the server will be there */
AWS_LOGF_INFO(
AWS_LS_HTTP_SERVER,
- "%p %s:%d: Shutting down the server.",
+ "%p %s:%u: Shutting down the server.",
(void *)server,
server->socket->local_endpoint.address,
server->socket->local_endpoint.port);
@@ -751,6 +762,12 @@ void aws_http_server_release(struct aws_http_server *server) {
* clean up will be called from eventloop */
}
+const struct aws_socket_endpoint *aws_http_server_get_listener_endpoint(const struct aws_http_server *server) {
+ AWS_FATAL_ASSERT(server);
+
+ return &server->socket->local_endpoint;
+}
+
/* At this point, the channel bootstrapper has established a connection to the server and set up a channel.
* Now we need to create the aws_http_connection and insert it into the channel as a channel-handler. */
static void s_client_bootstrap_on_channel_setup(
@@ -823,6 +840,8 @@ static void s_client_bootstrap_on_channel_setup(
}
http_bootstrap->connection->proxy_request_transform = http_bootstrap->proxy_request_transform;
+ http_bootstrap->connection->client_data->response_first_byte_timeout_ms =
+ http_bootstrap->response_first_byte_timeout_ms;
AWS_LOGF_INFO(
AWS_LS_HTTP_CONNECTION,
@@ -1062,6 +1081,7 @@ int aws_http_client_connect_internal(
http_bootstrap->proxy_request_transform = proxy_request_transform;
http_bootstrap->http1_options = *options.http1_options;
http_bootstrap->http2_options = *options.http2_options;
+ http_bootstrap->response_first_byte_timeout_ms = options.response_first_byte_timeout_ms;
/* keep a copy of the settings array if it's not NULL */
if (options.http2_options->num_initial_settings > 0) {
@@ -1085,9 +1105,9 @@ int aws_http_client_connect_internal(
AWS_LOGF_TRACE(
AWS_LS_HTTP_CONNECTION,
- "static: attempting to initialize a new client channel to %s:%d",
+ "static: attempting to initialize a new client channel to %s:%u",
aws_string_c_str(host_name),
- (int)options.port);
+ options.port);
struct aws_socket_channel_bootstrap_options channel_options = {
.bootstrap = options.bootstrap,
@@ -1100,9 +1120,10 @@ int aws_http_client_connect_internal(
.enable_read_back_pressure = options.manual_window_management,
.user_data = http_bootstrap,
.requested_event_loop = options.requested_event_loop,
+ .host_resolution_override_config = options.host_resolution_config,
};
- err = s_system_vtable_ptr->new_socket_channel(&channel_options);
+ err = s_system_vtable_ptr->aws_client_bootstrap_new_socket_channel(&channel_options);
if (err) {
AWS_LOGF_ERROR(
diff --git a/contrib/restricted/aws/aws-c-http/source/connection_manager.c b/contrib/restricted/aws/aws-c-http/source/connection_manager.c
index 30eda61778f..195a7d6caf6 100644
--- a/contrib/restricted/aws/aws-c-http/source/connection_manager.c
+++ b/contrib/restricted/aws/aws-c-http/source/connection_manager.c
@@ -43,22 +43,22 @@ struct aws_idle_connection {
* System vtable to use under normal circumstances
*/
static struct aws_http_connection_manager_system_vtable s_default_system_vtable = {
- .create_connection = aws_http_client_connect,
- .release_connection = aws_http_connection_release,
- .close_connection = aws_http_connection_close,
- .is_connection_available = aws_http_connection_new_requests_allowed,
- .get_monotonic_time = aws_high_res_clock_get_ticks,
- .is_callers_thread = aws_channel_thread_is_callers_thread,
- .connection_get_channel = aws_http_connection_get_channel,
- .connection_get_version = aws_http_connection_get_version,
+ .aws_http_client_connect = aws_http_client_connect,
+ .aws_http_connection_release = aws_http_connection_release,
+ .aws_http_connection_close = aws_http_connection_close,
+ .aws_http_connection_new_requests_allowed = aws_http_connection_new_requests_allowed,
+ .aws_high_res_clock_get_ticks = aws_high_res_clock_get_ticks,
+ .aws_channel_thread_is_callers_thread = aws_channel_thread_is_callers_thread,
+ .aws_http_connection_get_channel = aws_http_connection_get_channel,
+ .aws_http_connection_get_version = aws_http_connection_get_version,
};
const struct aws_http_connection_manager_system_vtable *g_aws_http_connection_manager_default_system_vtable_ptr =
&s_default_system_vtable;
bool aws_http_connection_manager_system_vtable_is_valid(const struct aws_http_connection_manager_system_vtable *table) {
- return table->create_connection && table->close_connection && table->release_connection &&
- table->is_connection_available;
+ return table->aws_http_client_connect && table->aws_http_connection_close && table->aws_http_connection_release &&
+ table->aws_http_connection_new_requests_allowed;
}
enum aws_http_connection_manager_state_type { AWS_HCMST_UNINITIALIZED, AWS_HCMST_READY, AWS_HCMST_SHUTTING_DOWN };
@@ -236,7 +236,7 @@ struct aws_http_connection_manager {
struct aws_string *host;
struct proxy_env_var_settings proxy_ev_settings;
struct aws_tls_connection_options *proxy_ev_tls_options;
- uint16_t port;
+ uint32_t port;
/*
* HTTP/2 specific.
*/
@@ -433,13 +433,13 @@ static void s_aws_http_connection_manager_complete_acquisitions(
if (pending_acquisition->error_code == AWS_OP_SUCCESS) {
- struct aws_channel *channel =
- pending_acquisition->manager->system_vtable->connection_get_channel(pending_acquisition->connection);
+ struct aws_channel *channel = pending_acquisition->manager->system_vtable->aws_http_connection_get_channel(
+ pending_acquisition->connection);
AWS_PRECONDITION(channel);
/* For some workloads, going ahead and moving the connection callback to the connection's thread is a
* substantial performance improvement so let's do that */
- if (!pending_acquisition->manager->system_vtable->is_callers_thread(channel)) {
+ if (!pending_acquisition->manager->system_vtable->aws_channel_thread_is_callers_thread(channel)) {
aws_channel_task_init(
&pending_acquisition->acquisition_task,
s_connection_acquisition_task,
@@ -776,7 +776,7 @@ static void s_schedule_connection_culling(struct aws_http_connection_manager *ma
* culling interval from now.
*/
uint64_t now = 0;
- manager->system_vtable->get_monotonic_time(&now);
+ manager->system_vtable->aws_high_res_clock_get_ticks(&now);
cull_task_time =
now + aws_timestamp_convert(
manager->max_connection_idle_in_milliseconds, AWS_TIMESTAMP_MILLIS, AWS_TIMESTAMP_NANOS, NULL);
@@ -1024,7 +1024,7 @@ static int s_aws_http_connection_manager_new_connection(struct aws_http_connecti
options.proxy_options = &proxy_options;
}
- if (manager->system_vtable->create_connection(&options)) {
+ if (manager->system_vtable->aws_http_client_connect(&options)) {
AWS_LOGF_ERROR(
AWS_LS_HTTP_CONNECTION_MANAGER,
"id=%p: http connection creation failed with error code %d(%s)",
@@ -1061,7 +1061,7 @@ static void s_aws_http_connection_manager_execute_transaction(struct aws_connect
"id=%p: Releasing connection (id=%p)",
(void *)manager,
(void *)idle_connection->connection);
- manager->system_vtable->release_connection(idle_connection->connection);
+ manager->system_vtable->aws_http_connection_release(idle_connection->connection);
aws_mem_release(idle_connection->allocator, idle_connection);
}
@@ -1071,7 +1071,7 @@ static void s_aws_http_connection_manager_execute_transaction(struct aws_connect
"id=%p: Releasing connection (id=%p)",
(void *)manager,
(void *)work->connection_to_release);
- manager->system_vtable->release_connection(work->connection_to_release);
+ manager->system_vtable->aws_http_connection_release(work->connection_to_release);
}
/*
@@ -1194,7 +1194,7 @@ static int s_idle_connection(struct aws_http_connection_manager *manager, struct
idle_connection->connection = connection;
uint64_t idle_start_timestamp = 0;
- if (manager->system_vtable->get_monotonic_time(&idle_start_timestamp)) {
+ if (manager->system_vtable->aws_high_res_clock_get_ticks(&idle_start_timestamp)) {
goto on_error;
}
@@ -1223,7 +1223,7 @@ int aws_http_connection_manager_release_connection(
s_aws_connection_management_transaction_init(&work, manager);
int result = AWS_OP_ERR;
- bool should_release_connection = !manager->system_vtable->is_connection_available(connection);
+ bool should_release_connection = !manager->system_vtable->aws_http_connection_new_requests_allowed(connection);
AWS_LOGF_DEBUG(
AWS_LS_HTTP_CONNECTION_MANAGER,
@@ -1413,7 +1413,8 @@ static void s_aws_http_connection_manager_on_connection_setup(
s_connection_manager_internal_ref_increase(manager, AWS_HCMCT_OPEN_CONNECTION, 1);
}
- if (connection != NULL && manager->system_vtable->connection_get_version(connection) == AWS_HTTP_VERSION_2) {
+ if (connection != NULL &&
+ manager->system_vtable->aws_http_connection_get_version(connection) == AWS_HTTP_VERSION_2) {
/* If the manager is shutting down, we will still wait for the settings, since we don't have map for connections
*/
++manager->pending_settings_count;
@@ -1492,7 +1493,7 @@ static void s_cull_idle_connections(struct aws_http_connection_manager *manager)
}
uint64_t now = 0;
- if (manager->system_vtable->get_monotonic_time(&now)) {
+ if (manager->system_vtable->aws_high_res_clock_get_ticks(&now)) {
return;
}
diff --git a/contrib/restricted/aws/aws-c-http/source/h1_connection.c b/contrib/restricted/aws/aws-c-http/source/h1_connection.c
index 3532bb80d94..903cf038144 100644
--- a/contrib/restricted/aws/aws-c-http/source/h1_connection.c
+++ b/contrib/restricted/aws/aws-c-http/source/h1_connection.c
@@ -11,6 +11,7 @@
#include <aws/http/private/h1_stream.h>
#include <aws/http/private/request_response_impl.h>
#include <aws/http/status_code.h>
+#include <aws/io/event_loop.h>
#include <aws/io/logging.h>
#include <inttypes.h>
@@ -371,6 +372,7 @@ int aws_h1_stream_activate(struct aws_http_stream *stream) {
/* connection keeps activated stream alive until stream completes */
aws_atomic_fetch_add(&stream->refcount, 1);
+ stream->metrics.stream_id = stream->id;
if (should_schedule_task) {
AWS_LOGF_TRACE(
@@ -386,6 +388,34 @@ int aws_h1_stream_activate(struct aws_http_stream *stream) {
return AWS_OP_SUCCESS;
}
+void aws_h1_stream_cancel(struct aws_http_stream *stream, int error_code) {
+ struct aws_h1_stream *h1_stream = AWS_CONTAINER_OF(stream, struct aws_h1_stream, base);
+ struct aws_http_connection *base_connection = stream->owning_connection;
+ struct aws_h1_connection *connection = AWS_CONTAINER_OF(base_connection, struct aws_h1_connection, base);
+
+ { /* BEGIN CRITICAL SECTION */
+ aws_h1_connection_lock_synced_data(connection);
+ if (h1_stream->synced_data.api_state != AWS_H1_STREAM_API_STATE_ACTIVE ||
+ connection->synced_data.is_open == false) {
+ /* Not active, nothing to cancel. */
+ aws_h1_connection_unlock_synced_data(connection);
+ AWS_LOGF_DEBUG(AWS_LS_HTTP_STREAM, "id=%p: Stream not active, nothing to cancel.", (void *)stream);
+ return;
+ }
+
+ aws_h1_connection_unlock_synced_data(connection);
+ } /* END CRITICAL SECTION */
+ AWS_LOGF_INFO(
+ AWS_LS_HTTP_CONNECTION,
+ "id=%p: Connection shutting down due to stream=%p cancelled with error code %d (%s).",
+ (void *)&connection->base,
+ (void *)stream,
+ error_code,
+ aws_error_name(error_code));
+
+ s_stop(connection, false /*stop_reading*/, false /*stop_writing*/, true /*schedule_shutdown*/, error_code);
+}
+
struct aws_http_stream *s_make_request(
struct aws_http_connection *client_connection,
const struct aws_http_make_request_options *options) {
@@ -534,6 +564,7 @@ static int s_aws_http1_switch_protocols(struct aws_h1_connection *connection) {
static void s_stream_complete(struct aws_h1_stream *stream, int error_code) {
struct aws_h1_connection *connection =
AWS_CONTAINER_OF(stream->base.owning_connection, struct aws_h1_connection, base);
+ AWS_ASSERT(aws_channel_thread_is_callers_thread(connection->base.channel_slot->channel));
/*
* If this is the end of a successful CONNECT request, mark ourselves as pass-through since the proxy layer
@@ -546,6 +577,14 @@ static void s_stream_complete(struct aws_h1_stream *stream, int error_code) {
}
}
+ if (stream->base.client_data && stream->base.client_data->response_first_byte_timeout_task.fn != NULL) {
+ /* There is an outstanding response timeout task, but stream completed, we can cancel it now. We are
+ * safe to do it as we always on connection thread to schedule the task or cancel it */
+ struct aws_event_loop *connection_loop = aws_channel_get_event_loop(connection->base.channel_slot->channel);
+ /* The task will be zeroed out within the call */
+ aws_event_loop_cancel_task(connection_loop, &stream->base.client_data->response_first_byte_timeout_task);
+ }
+
if (error_code != AWS_ERROR_SUCCESS) {
if (stream->base.client_data && stream->is_incoming_message_done) {
/* As a request that finished receiving the response, we ignore error and
@@ -633,6 +672,10 @@ static void s_stream_complete(struct aws_h1_stream *stream, int error_code) {
aws_h1_chunk_complete_and_destroy(chunk, &stream->base, AWS_ERROR_HTTP_STREAM_HAS_COMPLETED);
}
+ if (stream->base.on_metrics) {
+ stream->base.on_metrics(&stream->base, &stream->base.metrics, stream->base.user_data);
+ }
+
/* Invoke callback and clean up stream. */
if (stream->base.on_complete) {
stream->base.on_complete(&stream->base, error_code, stream->base.user_data);
@@ -716,6 +759,87 @@ static void s_client_update_incoming_stream_ptr(struct aws_h1_connection *connec
s_set_incoming_stream_ptr(connection, desired);
}
+static void s_http_stream_response_first_byte_timeout_task(
+ struct aws_task *task,
+ void *arg,
+ enum aws_task_status status) {
+ (void)task;
+ struct aws_h1_stream *stream = arg;
+ struct aws_http_connection *connection_base = stream->base.owning_connection;
+ /* zero-out task to indicate that it's no longer scheduled */
+ AWS_ZERO_STRUCT(stream->base.client_data->response_first_byte_timeout_task);
+
+ if (status == AWS_TASK_STATUS_CANCELED) {
+ return;
+ }
+
+ struct aws_h1_connection *connection = AWS_CONTAINER_OF(connection_base, struct aws_h1_connection, base);
+ /* Timeout happened, close the connection */
+ uint64_t response_first_byte_timeout_ms = stream->base.client_data->response_first_byte_timeout_ms == 0
+ ? connection_base->client_data->response_first_byte_timeout_ms
+ : stream->base.client_data->response_first_byte_timeout_ms;
+ AWS_LOGF_INFO(
+ AWS_LS_HTTP_CONNECTION,
+ "id=%p: Closing connection as timeout after request sent to the first byte received happened. "
+ "response_first_byte_timeout_ms is %" PRIu64 ".",
+ (void *)connection_base,
+ response_first_byte_timeout_ms);
+
+ /* Don't stop reading/writing immediately, let that happen naturally during the channel shutdown process. */
+ s_stop(
+ connection,
+ false /*stop_reading*/,
+ false /*stop_writing*/,
+ true /*schedule_shutdown*/,
+ AWS_ERROR_HTTP_RESPONSE_FIRST_BYTE_TIMEOUT);
+}
+
+static void s_set_outgoing_message_done(struct aws_h1_stream *stream) {
+ struct aws_http_connection *connection = stream->base.owning_connection;
+ struct aws_channel *channel = aws_http_connection_get_channel(connection);
+ AWS_ASSERT(aws_channel_thread_is_callers_thread(channel));
+
+ if (stream->is_outgoing_message_done) {
+ /* Already did the job */
+ return;
+ }
+
+ stream->is_outgoing_message_done = true;
+ AWS_ASSERT(stream->base.metrics.send_end_timestamp_ns == -1);
+ aws_high_res_clock_get_ticks((uint64_t *)&stream->base.metrics.send_end_timestamp_ns);
+ AWS_ASSERT(stream->base.metrics.send_start_timestamp_ns != -1);
+ AWS_ASSERT(stream->base.metrics.send_end_timestamp_ns >= stream->base.metrics.send_start_timestamp_ns);
+ stream->base.metrics.sending_duration_ns =
+ stream->base.metrics.send_end_timestamp_ns - stream->base.metrics.send_start_timestamp_ns;
+ if (stream->base.metrics.receive_start_timestamp_ns == -1) {
+ /* We haven't receive any message, schedule the response timeout task */
+
+ uint64_t response_first_byte_timeout_ms = 0;
+ if (stream->base.client_data != NULL && connection->client_data != NULL) {
+ response_first_byte_timeout_ms = stream->base.client_data->response_first_byte_timeout_ms == 0
+ ? connection->client_data->response_first_byte_timeout_ms
+ : stream->base.client_data->response_first_byte_timeout_ms;
+ }
+ if (response_first_byte_timeout_ms != 0) {
+ /* The task should not be initialized before. */
+ AWS_ASSERT(stream->base.client_data->response_first_byte_timeout_task.fn == NULL);
+ aws_task_init(
+ &stream->base.client_data->response_first_byte_timeout_task,
+ s_http_stream_response_first_byte_timeout_task,
+ stream,
+ "http_stream_response_first_byte_timeout_task");
+ uint64_t now_ns = 0;
+ aws_channel_current_clock_time(channel, &now_ns);
+ struct aws_event_loop *connection_loop = aws_channel_get_event_loop(channel);
+ aws_event_loop_schedule_task_future(
+ connection_loop,
+ &stream->base.client_data->response_first_byte_timeout_task,
+ now_ns + aws_timestamp_convert(
+ response_first_byte_timeout_ms, AWS_TIMESTAMP_MILLIS, AWS_TIMESTAMP_NANOS, NULL));
+ }
+ }
+}
+
/**
* If necessary, update `outgoing_stream` so it is pointing at a stream
* with data to send, or NULL if all streams are done sending data.
@@ -730,7 +854,7 @@ static struct aws_h1_stream *s_update_outgoing_stream_ptr(struct aws_h1_connecti
/* If current stream is done sending data... */
if (current && !aws_h1_encoder_is_message_in_progress(&connection->thread_data.encoder)) {
- current->is_outgoing_message_done = true;
+ s_set_outgoing_message_done(current);
/* RFC-7230 section 6.6: Tear-down.
* If this was the final stream, don't allows any further streams to be sent */
@@ -801,9 +925,13 @@ static struct aws_h1_stream *s_update_outgoing_stream_ptr(struct aws_h1_connecti
s_set_outgoing_stream_ptr(connection, current);
if (current) {
+ AWS_ASSERT(current->base.metrics.send_start_timestamp_ns == -1);
+ aws_high_res_clock_get_ticks((uint64_t *)&current->base.metrics.send_start_timestamp_ns);
+
err = aws_h1_encoder_start_message(
&connection->thread_data.encoder, &current->encoder_message, &current->base);
(void)err;
+ AWS_ASSERT(connection->thread_data.encoder.state == AWS_H1_ENCODER_STATE_INIT);
AWS_ASSERT(!err);
}
@@ -1109,7 +1237,7 @@ static int s_decoder_on_header(const struct aws_h1_decoded_header *header, void
AWS_LS_HTTP_STREAM,
"id=%p: Received 'Connection: close' header, no more request data will be sent.",
(void *)&incoming_stream->base);
- incoming_stream->is_outgoing_message_done = true;
+ s_set_outgoing_message_done(incoming_stream);
}
/* Stop writing right now.
* Shutdown will be scheduled after we finishing parsing the response */
@@ -1270,6 +1398,13 @@ static int s_decoder_on_done(void *user_data) {
/* Otherwise the incoming stream is finished decoding and we will update it if needed */
incoming_stream->is_incoming_message_done = true;
+ aws_high_res_clock_get_ticks((uint64_t *)&incoming_stream->base.metrics.receive_end_timestamp_ns);
+ AWS_ASSERT(incoming_stream->base.metrics.receive_start_timestamp_ns != -1);
+ AWS_ASSERT(
+ incoming_stream->base.metrics.receive_end_timestamp_ns >=
+ incoming_stream->base.metrics.receive_start_timestamp_ns);
+ incoming_stream->base.metrics.receiving_duration_ns = incoming_stream->base.metrics.receive_end_timestamp_ns -
+ incoming_stream->base.metrics.receive_start_timestamp_ns;
/* RFC-7230 section 6.6
* After reading the final message, the connection must not read any more */
@@ -1822,6 +1957,20 @@ static int s_try_process_next_stream_read_message(struct aws_h1_connection *conn
bool body_headers_ignored = incoming_stream->base.request_method == AWS_HTTP_METHOD_HEAD;
aws_h1_decoder_set_body_headers_ignored(connection->thread_data.incoming_stream_decoder, body_headers_ignored);
+ if (incoming_stream->base.metrics.receive_start_timestamp_ns == -1) {
+ /* That's the first time for the stream receives any message */
+ aws_high_res_clock_get_ticks((uint64_t *)&incoming_stream->base.metrics.receive_start_timestamp_ns);
+ if (incoming_stream->base.client_data &&
+ incoming_stream->base.client_data->response_first_byte_timeout_task.fn != NULL) {
+ /* There is an outstanding response timeout task, as we already received the data, we can cancel it now. We
+ * are safe to do it as we always on connection thread to schedule the task or cancel it */
+ struct aws_event_loop *connection_loop = aws_channel_get_event_loop(connection->base.channel_slot->channel);
+ /* The task will be zeroed out within the call */
+ aws_event_loop_cancel_task(
+ connection_loop, &incoming_stream->base.client_data->response_first_byte_timeout_task);
+ }
+ }
+
/* As decoder runs, it invokes the internal s_decoder_X callbacks, which in turn invoke user callbacks.
* The decoder will stop once it hits the end of the request/response OR the end of the message data. */
if (aws_h1_decode(connection->thread_data.incoming_stream_decoder, &message_cursor)) {
diff --git a/contrib/restricted/aws/aws-c-http/source/h1_decoder.c b/contrib/restricted/aws/aws-c-http/source/h1_decoder.c
index 68e5aa224ae..c615d09a658 100644
--- a/contrib/restricted/aws/aws-c-http/source/h1_decoder.c
+++ b/contrib/restricted/aws/aws-c-http/source/h1_decoder.c
@@ -301,7 +301,7 @@ static int s_linestate_chunk_size(struct aws_h1_decoder *decoder, struct aws_byt
decoder->logging_id,
AWS_BYTE_CURSOR_PRI(input));
- return AWS_OP_ERR;
+ return aws_raise_error(AWS_ERROR_HTTP_PROTOCOL_ERROR);
}
int err = aws_byte_cursor_utf8_parse_u64_hex(size, &decoder->chunk_size);
diff --git a/contrib/restricted/aws/aws-c-http/source/h1_encoder.c b/contrib/restricted/aws/aws-c-http/source/h1_encoder.c
index 1899d2f4025..277dce94633 100644
--- a/contrib/restricted/aws/aws-c-http/source/h1_encoder.c
+++ b/contrib/restricted/aws/aws-c-http/source/h1_encoder.c
@@ -403,10 +403,7 @@ int aws_h1_encoder_message_init_from_response(
goto error;
}
- err = aws_byte_buf_init(&message->outgoing_head_buf, allocator, head_total_len);
- if (err) {
- return AWS_OP_ERR;
- }
+ aws_byte_buf_init(&message->outgoing_head_buf, allocator, head_total_len);
bool wrote_all = true;
@@ -489,9 +486,9 @@ static size_t s_calculate_chunk_line_size(const struct aws_http1_chunk_options *
size_t chunk_line_size = MAX_ASCII_HEX_CHUNK_STR_SIZE + CRLF_SIZE;
for (size_t i = 0; i < options->num_extensions; ++i) {
struct aws_http1_chunk_extension *chunk_extension = options->extensions + i;
- chunk_line_size += sizeof(';');
+ chunk_line_size += 1 /* ; */;
chunk_line_size += chunk_extension->key.len;
- chunk_line_size += sizeof('=');
+ chunk_line_size += 1 /* = */;
chunk_line_size += chunk_extension->value.len;
}
return chunk_line_size;
diff --git a/contrib/restricted/aws/aws-c-http/source/h1_stream.c b/contrib/restricted/aws/aws-c-http/source/h1_stream.c
index a5d2f4782b4..ef8f086bfca 100644
--- a/contrib/restricted/aws/aws-c-http/source/h1_stream.c
+++ b/contrib/restricted/aws/aws-c-http/source/h1_stream.c
@@ -329,6 +329,7 @@ static const struct aws_http_stream_vtable s_stream_vtable = {
.destroy = s_stream_destroy,
.update_window = s_stream_update_window,
.activate = aws_h1_stream_activate,
+ .cancel = aws_h1_stream_cancel,
.http1_write_chunk = s_stream_write_chunk,
.http1_add_trailer = s_stream_add_trailer,
.http2_reset_stream = NULL,
@@ -361,6 +362,12 @@ static struct aws_h1_stream *s_stream_new_common(
stream->base.on_incoming_body = on_incoming_body;
stream->base.on_complete = on_complete;
stream->base.on_destroy = on_destroy;
+ stream->base.metrics.send_start_timestamp_ns = -1;
+ stream->base.metrics.send_end_timestamp_ns = -1;
+ stream->base.metrics.sending_duration_ns = -1;
+ stream->base.metrics.receive_start_timestamp_ns = -1;
+ stream->base.metrics.receive_end_timestamp_ns = -1;
+ stream->base.metrics.receiving_duration_ns = -1;
aws_channel_task_init(
&stream->cross_thread_work_task, s_stream_cross_thread_work_task, stream, "http1_stream_cross_thread_work");
@@ -401,6 +408,8 @@ struct aws_h1_stream *aws_h1_stream_new_request(
stream->base.client_data = &stream->base.client_or_server_data.client;
stream->base.client_data->response_status = AWS_HTTP_STATUS_CODE_UNKNOWN;
+ stream->base.client_data->response_first_byte_timeout_ms = options->response_first_byte_timeout_ms;
+ stream->base.on_metrics = options->on_metrics;
/* Validate request and cache info that the encoder will eventually need */
if (aws_h1_encoder_message_init_from_request(
diff --git a/contrib/restricted/aws/aws-c-http/source/h2_connection.c b/contrib/restricted/aws/aws-c-http/source/h2_connection.c
index 15ea192f8ab..f27c005f38f 100644
--- a/contrib/restricted/aws/aws-c-http/source/h2_connection.c
+++ b/contrib/restricted/aws/aws-c-http/source/h2_connection.c
@@ -1531,7 +1531,7 @@ static struct aws_h2err s_decoder_on_settings_ack(void *userdata) {
}
connection->thread_data.settings_self[settings_array[i].id] = settings_array[i].value;
}
- /* invoke the change settings compeleted user callback */
+ /* invoke the change settings completed user callback */
if (pending_settings->on_completed) {
pending_settings->on_completed(&connection->base, AWS_ERROR_SUCCESS, pending_settings->user_data);
}
@@ -2057,6 +2057,7 @@ int aws_h2_stream_activate(struct aws_http_stream *stream) {
/* connection keeps activated stream alive until stream completes */
aws_atomic_fetch_add(&stream->refcount, 1);
+ stream->metrics.stream_id = stream->id;
if (!was_cross_thread_work_scheduled) {
CONNECTION_LOG(TRACE, connection, "Scheduling cross-thread work task");
diff --git a/contrib/restricted/aws/aws-c-http/source/h2_stream.c b/contrib/restricted/aws/aws-c-http/source/h2_stream.c
index 85232db0066..6d8336bfd3d 100644
--- a/contrib/restricted/aws/aws-c-http/source/h2_stream.c
+++ b/contrib/restricted/aws/aws-c-http/source/h2_stream.c
@@ -5,6 +5,7 @@
#include <aws/http/private/h2_stream.h>
+#include <aws/common/clock.h>
#include <aws/http/private/h2_connection.h>
#include <aws/http/private/strutil.h>
#include <aws/http/status_code.h>
@@ -26,12 +27,17 @@ static int s_stream_write_data(
static void s_stream_cross_thread_work_task(struct aws_channel_task *task, void *arg, enum aws_task_status status);
static struct aws_h2err s_send_rst_and_close_stream(struct aws_h2_stream *stream, struct aws_h2err stream_error);
-static int s_stream_reset_stream_internal(struct aws_http_stream *stream_base, struct aws_h2err stream_error);
+static int s_stream_reset_stream_internal(
+ struct aws_http_stream *stream_base,
+ struct aws_h2err stream_error,
+ bool cancelling);
+static void s_stream_cancel(struct aws_http_stream *stream, int error_code);
struct aws_http_stream_vtable s_h2_stream_vtable = {
.destroy = s_stream_destroy,
.update_window = s_stream_update_window,
.activate = aws_h2_stream_activate,
+ .cancel = s_stream_cancel,
.http1_write_chunk = NULL,
.http2_reset_stream = s_stream_reset_stream,
.http2_get_received_error_code = s_stream_get_received_error_code,
@@ -240,10 +246,17 @@ struct aws_h2_stream *aws_h2_stream_new_request(
stream->base.on_incoming_headers = options->on_response_headers;
stream->base.on_incoming_header_block_done = options->on_response_header_block_done;
stream->base.on_incoming_body = options->on_response_body;
+ stream->base.on_metrics = options->on_metrics;
stream->base.on_complete = options->on_complete;
stream->base.on_destroy = options->on_destroy;
stream->base.client_data = &stream->base.client_or_server_data.client;
stream->base.client_data->response_status = AWS_HTTP_STATUS_CODE_UNKNOWN;
+ stream->base.metrics.send_start_timestamp_ns = -1;
+ stream->base.metrics.send_end_timestamp_ns = -1;
+ stream->base.metrics.sending_duration_ns = -1;
+ stream->base.metrics.receive_start_timestamp_ns = -1;
+ stream->base.metrics.receive_end_timestamp_ns = -1;
+ stream->base.metrics.receiving_duration_ns = -1;
aws_linked_list_init(&stream->thread_data.outgoing_writes);
aws_linked_list_init(&stream->synced_data.pending_write_list);
@@ -446,6 +459,9 @@ void aws_h2_stream_complete(struct aws_h2_stream *stream, int error_code) {
s_h2_stream_destroy_pending_writes(stream);
/* Invoke callback */
+ if (stream->base.on_metrics) {
+ stream->base.on_metrics(&stream->base, &stream->base.metrics, stream->base.user_data);
+ }
if (stream->base.on_complete) {
stream->base.on_complete(&stream->base, error_code, stream->base.user_data);
}
@@ -515,12 +531,16 @@ static void s_stream_update_window(struct aws_http_stream *stream_base, size_t i
.h2_code = AWS_HTTP2_ERR_INTERNAL_ERROR,
};
/* Only when stream is not initialized reset will fail. So, we can assert it to be succeed. */
- AWS_FATAL_ASSERT(s_stream_reset_stream_internal(stream_base, stream_error) == AWS_OP_SUCCESS);
+ AWS_FATAL_ASSERT(
+ s_stream_reset_stream_internal(stream_base, stream_error, false /*cancelling*/) == AWS_OP_SUCCESS);
}
return;
}
-static int s_stream_reset_stream_internal(struct aws_http_stream *stream_base, struct aws_h2err stream_error) {
+static int s_stream_reset_stream_internal(
+ struct aws_http_stream *stream_base,
+ struct aws_h2err stream_error,
+ bool cancelling) {
struct aws_h2_stream *stream = AWS_CONTAINER_OF(stream_base, struct aws_h2_stream, base);
struct aws_h2_connection *connection = s_get_h2_connection(stream);
@@ -542,21 +562,25 @@ static int s_stream_reset_stream_internal(struct aws_http_stream *stream_base, s
} /* END CRITICAL SECTION */
if (stream_is_init) {
+ if (cancelling) {
+ /* Not an error if we are just cancelling. */
+ AWS_LOGF_DEBUG(AWS_LS_HTTP_STREAM, "id=%p: Stream not in process, nothing to cancel.", (void *)stream);
+ return AWS_OP_SUCCESS;
+ }
AWS_H2_STREAM_LOG(
ERROR, stream, "Reset stream failed. Stream is in initialized state, please activate the stream first.");
return aws_raise_error(AWS_ERROR_INVALID_STATE);
}
+ if (reset_called) {
+ AWS_H2_STREAM_LOG(DEBUG, stream, "Reset stream ignored. Reset stream has been called already.");
+ }
+
if (cross_thread_work_should_schedule) {
AWS_H2_STREAM_LOG(TRACE, stream, "Scheduling stream cross-thread work task");
/* increment the refcount of stream to keep it alive until the task runs */
aws_atomic_fetch_add(&stream->base.refcount, 1);
aws_channel_schedule_task_now(connection->base.channel_slot->channel, &stream->cross_thread_work_task);
- return AWS_OP_SUCCESS;
}
- if (reset_called) {
- AWS_H2_STREAM_LOG(DEBUG, stream, "Reset stream ignored. Reset stream has been called already.");
- }
-
return AWS_OP_SUCCESS;
}
@@ -572,7 +596,16 @@ static int s_stream_reset_stream(struct aws_http_stream *stream_base, uint32_t h
(void *)stream_base,
aws_http2_error_code_to_str(http2_error),
http2_error);
- return s_stream_reset_stream_internal(stream_base, stream_error);
+ return s_stream_reset_stream_internal(stream_base, stream_error, false /*cancelling*/);
+}
+
+void s_stream_cancel(struct aws_http_stream *stream_base, int error_code) {
+ struct aws_h2err stream_error = {
+ .aws_code = error_code,
+ .h2_code = AWS_HTTP2_ERR_CANCEL,
+ };
+ s_stream_reset_stream_internal(stream_base, stream_error, true /*cancelling*/);
+ return;
}
static int s_stream_get_received_error_code(struct aws_http_stream *stream_base, uint32_t *out_http2_error) {
@@ -706,7 +739,8 @@ int aws_h2_stream_on_activated(struct aws_h2_stream *stream, enum aws_h2_stream_
AWS_H2_STREAM_LOGF(ERROR, stream, "Failed to create HEADERS frame: %s", aws_error_name(aws_last_error()));
goto error;
}
-
+ AWS_ASSERT(stream->base.metrics.send_start_timestamp_ns == -1);
+ aws_high_res_clock_get_ticks((uint64_t *)&stream->base.metrics.send_start_timestamp_ns);
/* Initialize the flow-control window size */
stream->thread_data.window_size_peer =
connection->thread_data.settings_peer[AWS_HTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
@@ -721,6 +755,11 @@ int aws_h2_stream_on_activated(struct aws_h2_stream *stream, enum aws_h2_stream_
/* If stream has no body, then HEADERS frame marks the end of outgoing data */
stream->thread_data.state = AWS_H2_STREAM_STATE_HALF_CLOSED_LOCAL;
AWS_H2_STREAM_LOG(TRACE, stream, "Sending HEADERS with END_STREAM. State -> HALF_CLOSED_LOCAL");
+ /* There is no further frames to be sent, now is the end timestamp of sending. */
+ AWS_ASSERT(stream->base.metrics.send_end_timestamp_ns == -1);
+ aws_high_res_clock_get_ticks((uint64_t *)&stream->base.metrics.send_end_timestamp_ns);
+ stream->base.metrics.sending_duration_ns =
+ stream->base.metrics.send_end_timestamp_ns - stream->base.metrics.send_start_timestamp_ns;
}
if (s_h2_stream_has_outgoing_writes(stream)) {
@@ -798,6 +837,11 @@ int aws_h2_stream_encode_data_frame(
*/
if (input_stream_complete && ends_stream) {
/* Done sending data. No more data will be sent. */
+ AWS_ASSERT(stream->base.metrics.send_end_timestamp_ns == -1);
+ aws_high_res_clock_get_ticks((uint64_t *)&stream->base.metrics.send_end_timestamp_ns);
+ stream->base.metrics.sending_duration_ns =
+ stream->base.metrics.send_end_timestamp_ns - stream->base.metrics.send_start_timestamp_ns;
+
if (stream->thread_data.state == AWS_H2_STREAM_STATE_HALF_CLOSED_REMOTE) {
/* Both sides have sent END_STREAM */
stream->thread_data.state = AWS_H2_STREAM_STATE_CLOSED;
@@ -841,6 +885,7 @@ struct aws_h2err aws_h2_stream_on_decoder_headers_begin(struct aws_h2_stream *st
if (aws_h2err_failed(stream_err)) {
return s_send_rst_and_close_stream(stream, stream_err);
}
+ aws_high_res_clock_get_ticks((uint64_t *)&stream->base.metrics.receive_start_timestamp_ns);
return AWS_H2ERR_SUCCESS;
}
@@ -1150,6 +1195,13 @@ struct aws_h2err aws_h2_stream_on_decoder_end_stream(struct aws_h2_stream *strea
* an actual frame type. It's a flag on DATA or HEADERS frames, and we
* already checked the legality of those frames in their respective callbacks. */
+ AWS_ASSERT(stream->base.metrics.receive_start_timestamp_ns != -1);
+ AWS_ASSERT(stream->base.metrics.receive_end_timestamp_ns == -1);
+ aws_high_res_clock_get_ticks((uint64_t *)&stream->base.metrics.receive_end_timestamp_ns);
+ AWS_ASSERT(stream->base.metrics.receive_end_timestamp_ns >= stream->base.metrics.receive_start_timestamp_ns);
+ stream->base.metrics.receiving_duration_ns =
+ stream->base.metrics.receive_end_timestamp_ns - stream->base.metrics.receive_start_timestamp_ns;
+
if (stream->thread_data.content_length_received) {
if (stream->base.request_method != AWS_HTTP_METHOD_HEAD &&
stream->base.client_data->response_status != AWS_HTTP_STATUS_CODE_304_NOT_MODIFIED) {
diff --git a/contrib/restricted/aws/aws-c-http/source/hpack.c b/contrib/restricted/aws/aws-c-http/source/hpack.c
index ef3d0b3dcfa..83aee646782 100644
--- a/contrib/restricted/aws/aws-c-http/source/hpack.c
+++ b/contrib/restricted/aws/aws-c-http/source/hpack.c
@@ -103,7 +103,7 @@ void aws_hpack_static_table_init(struct aws_allocator *allocator) {
}
}
-void aws_hpack_static_table_clean_up() {
+void aws_hpack_static_table_clean_up(void) {
aws_hash_table_clean_up(&s_static_header_reverse_lookup);
aws_hash_table_clean_up(&s_static_header_reverse_lookup_name_only);
}
diff --git a/contrib/restricted/aws/aws-c-http/source/http.c b/contrib/restricted/aws/aws-c-http/source/http.c
index 8a8fe92bd19..af61c51517a 100644
--- a/contrib/restricted/aws/aws-c-http/source/http.c
+++ b/contrib/restricted/aws/aws-c-http/source/http.c
@@ -148,6 +148,9 @@ static struct aws_error_info s_errors[] = {
AWS_DEFINE_ERROR_INFO_HTTP(
AWS_ERROR_HTTP_MANUAL_WRITE_HAS_COMPLETED,
"Manual write failed because manual writes are already completed."),
+ AWS_DEFINE_ERROR_INFO_HTTP(
+ AWS_ERROR_HTTP_RESPONSE_FIRST_BYTE_TIMEOUT,
+ "The server does not begin responding within the configuration after a request is fully sent."),
};
/* clang-format on */
@@ -537,7 +540,7 @@ void aws_http_library_clean_up(void) {
aws_io_library_clean_up();
}
-void aws_http_fatal_assert_library_initialized() {
+void aws_http_fatal_assert_library_initialized(void) {
if (!s_library_initialized) {
AWS_LOGF_FATAL(
AWS_LS_HTTP_GENERAL,
diff --git a/contrib/restricted/aws/aws-c-http/source/proxy_connection.c b/contrib/restricted/aws/aws-c-http/source/proxy_connection.c
index e6cdb8a2460..3706c2fd543 100644
--- a/contrib/restricted/aws/aws-c-http/source/proxy_connection.c
+++ b/contrib/restricted/aws/aws-c-http/source/proxy_connection.c
@@ -39,7 +39,7 @@ AWS_STATIC_STRING_FROM_LITERAL(s_proxy_no_verify_peer_env_var, "AWS_PROXY_NO_VER
#endif
static struct aws_http_proxy_system_vtable s_default_vtable = {
- .setup_client_tls = &aws_channel_setup_client_tls,
+ .aws_channel_setup_client_tls = &aws_channel_setup_client_tls,
};
static struct aws_http_proxy_system_vtable *s_vtable = &s_default_vtable;
@@ -162,6 +162,7 @@ struct aws_http_proxy_user_data *aws_http_proxy_user_data_new(
user_data->original_channel_on_setup = on_channel_setup;
user_data->original_channel_on_shutdown = on_channel_shutdown;
user_data->requested_event_loop = options.requested_event_loop;
+ user_data->host_resolution_config = options.host_resolution_config;
user_data->prior_knowledge_http2 = options.prior_knowledge_http2;
/* one and only one setup callback must be valid */
@@ -465,7 +466,7 @@ static struct aws_http_message *s_build_h1_proxy_connect_request(struct aws_http
}
char port_str[20] = "\0";
- snprintf(port_str, sizeof(port_str), "%d", (int)user_data->original_port);
+ snprintf(port_str, sizeof(port_str), "%u", user_data->original_port);
struct aws_byte_cursor port_cursor = aws_byte_cursor_from_c_str(port_str);
if (aws_byte_buf_append(&path_buffer, &port_cursor)) {
goto on_error;
@@ -771,7 +772,7 @@ static void s_aws_http_on_stream_complete_tunnel_proxy(
last_slot = last_slot->adj_right;
}
- if (s_vtable->setup_client_tls(last_slot, context->original_tls_options)) {
+ if (s_vtable->aws_channel_setup_client_tls(last_slot, context->original_tls_options)) {
AWS_LOGF_ERROR(
AWS_LS_HTTP_CONNECTION,
"(%p) Proxy connection failed to start TLS negotiation with error %d(%s)",
@@ -1048,6 +1049,7 @@ static int s_aws_http_client_connect_via_forwarding_proxy(const struct aws_http_
options_copy.on_shutdown = s_aws_http_on_client_connection_http_proxy_shutdown_fn;
options_copy.tls_options = options->proxy_options->tls_options;
options_copy.requested_event_loop = options->requested_event_loop;
+ options_copy.host_resolution_config = options->host_resolution_config;
options_copy.prior_knowledge_http2 = false; /* ToDo, expose the protocol specific config for proxy connection. */
int result = aws_http_client_connect_internal(&options_copy, s_proxy_http_request_transform);
@@ -1084,6 +1086,7 @@ static int s_create_tunneling_connection(struct aws_http_proxy_user_data *user_d
connect_options.http1_options = NULL; /* ToDo, expose the protocol specific config for proxy connection. */
connect_options.http2_options = NULL; /* ToDo */
connect_options.requested_event_loop = user_data->requested_event_loop;
+ connect_options.host_resolution_config = user_data->host_resolution_config;
int result = aws_http_client_connect(&connect_options);
if (result == AWS_OP_ERR) {
@@ -1137,6 +1140,23 @@ static enum aws_http_proxy_connection_type s_determine_proxy_connection_type(
}
}
+static struct aws_string *s_get_proxy_environment_value(
+ struct aws_allocator *allocator,
+ const struct aws_string *env_name) {
+ struct aws_string *out_string = NULL;
+ if (aws_get_environment_value(allocator, env_name, &out_string) == AWS_OP_SUCCESS && out_string != NULL &&
+ out_string->len > 0) {
+ AWS_LOGF_DEBUG(
+ AWS_LS_HTTP_CONNECTION,
+ "%s environment found, %s",
+ aws_string_c_str(env_name),
+ aws_string_c_str(out_string));
+ return out_string;
+ }
+ aws_string_destroy(out_string);
+ return NULL;
+}
+
static int s_proxy_uri_init_from_env_variable(
struct aws_allocator *allocator,
const struct aws_http_client_connection_options *options,
@@ -1145,25 +1165,19 @@ static int s_proxy_uri_init_from_env_variable(
struct aws_string *proxy_uri_string = NULL;
*found = false;
if (options->tls_options) {
- if (aws_get_environment_value(allocator, s_https_proxy_env_var_low, &proxy_uri_string) == AWS_OP_SUCCESS &&
- proxy_uri_string != NULL) {
- AWS_LOGF_DEBUG(AWS_LS_HTTP_CONNECTION, "https_proxy environment found");
- } else if (
- aws_get_environment_value(allocator, s_https_proxy_env_var, &proxy_uri_string) == AWS_OP_SUCCESS &&
- proxy_uri_string != NULL) {
- AWS_LOGF_DEBUG(AWS_LS_HTTP_CONNECTION, "HTTPS_PROXY environment found");
- } else {
+ proxy_uri_string = s_get_proxy_environment_value(allocator, s_https_proxy_env_var_low);
+ if (proxy_uri_string == NULL) {
+ proxy_uri_string = s_get_proxy_environment_value(allocator, s_https_proxy_env_var);
+ }
+ if (proxy_uri_string == NULL) {
return AWS_OP_SUCCESS;
}
} else {
- if (aws_get_environment_value(allocator, s_http_proxy_env_var_low, &proxy_uri_string) == AWS_OP_SUCCESS &&
- proxy_uri_string != NULL) {
- AWS_LOGF_DEBUG(AWS_LS_HTTP_CONNECTION, "http_proxy environment found");
- } else if (
- aws_get_environment_value(allocator, s_http_proxy_env_var, &proxy_uri_string) == AWS_OP_SUCCESS &&
- proxy_uri_string != NULL) {
- AWS_LOGF_DEBUG(AWS_LS_HTTP_CONNECTION, "HTTP_PROXY environment found");
- } else {
+ proxy_uri_string = s_get_proxy_environment_value(allocator, s_http_proxy_env_var_low);
+ if (proxy_uri_string == NULL) {
+ proxy_uri_string = s_get_proxy_environment_value(allocator, s_http_proxy_env_var);
+ }
+ if (proxy_uri_string == NULL) {
return AWS_OP_SUCCESS;
}
}
@@ -1213,7 +1227,7 @@ static int s_setup_proxy_tls_env_variable(
AWS_LS_HTTP_CONNECTION,
"Failed making default TLS context because of BYO_CRYPTO, set up the tls_options for proxy_env_settings to "
"make it work.");
- return AWS_OP_ERR;
+ return aws_raise_error(AWS_ERROR_UNIMPLEMENTED);
#else
struct aws_tls_ctx *tls_ctx = NULL;
struct aws_tls_ctx_options tls_ctx_options;
@@ -1642,6 +1656,7 @@ int aws_http_proxy_new_socket_channel(
http_connection_options.on_setup = NULL; /* use channel callbacks, not http callbacks */
http_connection_options.on_shutdown = NULL; /* use channel callbacks, not http callbacks */
http_connection_options.requested_event_loop = channel_options->requested_event_loop;
+ http_connection_options.host_resolution_config = channel_options->host_resolution_override_config;
if (s_aws_http_client_connect_via_tunneling_proxy(
&http_connection_options, s_http_proxied_socket_channel_setup, s_http_proxied_socket_channel_shutdown)) {
diff --git a/contrib/restricted/aws/aws-c-http/source/request_response.c b/contrib/restricted/aws/aws-c-http/source/request_response.c
index c382a3a4d0e..dbd5214e762 100644
--- a/contrib/restricted/aws/aws-c-http/source/request_response.c
+++ b/contrib/restricted/aws/aws-c-http/source/request_response.c
@@ -867,6 +867,11 @@ int aws_http_message_get_header(
return aws_http_headers_get_index(message->headers, index, out_header);
}
+AWS_FUTURE_T_POINTER_WITH_RELEASE_IMPLEMENTATION(
+ aws_future_http_message,
+ struct aws_http_message,
+ aws_http_message_release)
+
struct aws_http_stream *aws_http_connection_make_request(
struct aws_http_connection *client_connection,
const struct aws_http_make_request_options *options) {
@@ -952,8 +957,8 @@ struct aws_http_message *aws_http2_message_new_from_http1(
scheme_cursor.ptr);
/**
- * An intermediary that forwards a request over HTTP/2 MUST construct an ":authority" pseudo-header field using
- * the authority information from the control data of the original request. (RFC=9113 8.3.1)
+ * An intermediary that forwards a request over HTTP/2 MUST construct an ":authority" pseudo-header field
+ * using the authority information from the control data of the original request. (RFC=9113 8.3.1)
*/
struct aws_byte_cursor host_value;
AWS_ZERO_STRUCT(host_value);
@@ -970,7 +975,8 @@ struct aws_http_message *aws_http2_message_new_from_http1(
(int)host_value.len,
host_value.ptr);
}
- /* TODO: If the host headers is missing, the target URI could be the other source of the authority information
+ /* TODO: If the host headers is missing, the target URI could be the other source of the authority
+ * information
*/
struct aws_byte_cursor path_cursor;
@@ -1107,6 +1113,15 @@ int aws_http_stream_send_response(struct aws_http_stream *stream, struct aws_htt
return stream->owning_connection->vtable->stream_send_response(stream, response);
}
+struct aws_http_stream *aws_http_stream_acquire(struct aws_http_stream *stream) {
+ AWS_PRECONDITION(stream);
+
+ size_t prev_refcount = aws_atomic_fetch_add(&stream->refcount, 1);
+ AWS_LOGF_TRACE(
+ AWS_LS_HTTP_STREAM, "id=%p: Stream refcount acquired, %zu remaining.", (void *)stream, prev_refcount + 1);
+ return stream;
+}
+
void aws_http_stream_release(struct aws_http_stream *stream) {
if (!stream) {
return;
@@ -1186,6 +1201,10 @@ uint32_t aws_http_stream_get_id(const struct aws_http_stream *stream) {
return stream->id;
}
+void aws_http_stream_cancel(struct aws_http_stream *stream, int error_code) {
+ stream->vtable->cancel(stream, error_code);
+}
+
int aws_http2_stream_reset(struct aws_http_stream *http2_stream, uint32_t http2_error) {
AWS_PRECONDITION(http2_stream);
AWS_PRECONDITION(http2_stream->vtable);
diff --git a/contrib/restricted/aws/aws-c-http/source/websocket_bootstrap.c b/contrib/restricted/aws/aws-c-http/source/websocket_bootstrap.c
index b5225873059..6c66c8515c5 100644
--- a/contrib/restricted/aws/aws-c-http/source/websocket_bootstrap.c
+++ b/contrib/restricted/aws/aws-c-http/source/websocket_bootstrap.c
@@ -215,6 +215,7 @@ int aws_websocket_client_connect(const struct aws_websocket_client_connection_op
http_options.on_setup = s_ws_bootstrap_on_http_setup;
http_options.on_shutdown = s_ws_bootstrap_on_http_shutdown;
http_options.requested_event_loop = options->requested_event_loop;
+ http_options.host_resolution_config = options->host_resolution_config;
/* Infer port, if not explicitly specified in URI */
http_options.port = options->port;
@@ -234,7 +235,7 @@ int aws_websocket_client_connect(const struct aws_websocket_client_connection_op
/* Success! (so far) */
AWS_LOGF_TRACE(
AWS_LS_HTTP_WEBSOCKET_SETUP,
- "id=%p: Websocket setup begun, connecting to " PRInSTR ":%" PRIu16 PRInSTR,
+ "id=%p: Websocket setup begun, connecting to " PRInSTR ":%" PRIu32 PRInSTR,
(void *)ws_bootstrap,
AWS_BYTE_CURSOR_PRI(options->host),
options->port,
diff --git a/contrib/restricted/aws/aws-c-http/ya.make b/contrib/restricted/aws/aws-c-http/ya.make
index 641db7b8269..25cf51985e2 100644
--- a/contrib/restricted/aws/aws-c-http/ya.make
+++ b/contrib/restricted/aws/aws-c-http/ya.make
@@ -6,9 +6,9 @@ LICENSE(Apache-2.0)
LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
-VERSION(0.7.6)
+VERSION(0.8.1)
-ORIGINAL_SOURCE(https://github.com/awslabs/aws-c-http/archive/v0.7.6.tar.gz)
+ORIGINAL_SOURCE(https://github.com/awslabs/aws-c-http/archive/v0.8.1.tar.gz)
PEERDIR(
contrib/restricted/aws/aws-c-cal