Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Address TODOs #383

Open
wants to merge 19 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/aws/http/http.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ enum aws_http_errors {
AWS_ERROR_HTTP_STREAM_MANAGER_SHUTTING_DOWN,
AWS_ERROR_HTTP_STREAM_MANAGER_CONNECTION_ACQUIRE_FAILURE,
AWS_ERROR_HTTP_STREAM_MANAGER_UNEXPECTED_HTTP_VERSION,
AWS_ERROR_HTTP_REQUIRED_PSEUDO_HEADER_MISSING,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see this error used anywhere.
Remove it if you're not using it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it was used here


AWS_ERROR_HTTP_END_RANGE = AWS_ERROR_ENUM_END_RANGE(AWS_C_HTTP_PACKAGE_ID)
};
Expand Down
16 changes: 13 additions & 3 deletions include/aws/http/private/hpack.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,19 @@ struct aws_hpack_decoder {

struct aws_hpack_context context;

/* TODO: check the new (RFC 9113 - 4.3.1) to make sure we did it right */
/* SETTINGS_HEADER_TABLE_SIZE from http2 */
size_t dynamic_table_protocol_max_size_setting;
/* SETTINGS_HEADER_TABLE_SIZE from http2. */
struct {
size_t latest_value; /* The latest setting from http2 */
uint32_t smallest_value_pending; /* The smallest setting during the pending update time. Only valid when
pending_update is true. */
bool pending_update_in_progress; /* True when the settings was received that smaller than the current dynamic
table size but not received a regular entry yet, assume the update is still in
progress. */
bool update_valid; /* True when the update should happen and no *conformant* Dynamic table resize was received
yet, which is at least one resize smaller than the smallest value received during the
time. */
size_t received_resize_num; /* The continuous number of dynamic table resize received during pending. */
} dynamic_table_protocol_max_size_setting;

/* PRO TIP: Don't union progress_integer and progress_string together, since string_decode calls integer_decode */
struct hpack_progress_integer {
Expand Down
24 changes: 10 additions & 14 deletions source/connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -815,9 +815,7 @@ static void s_client_bootstrap_on_channel_setup(
struct aws_crt_statistics_handler *http_connection_monitor =
aws_crt_statistics_handler_new_http_connection_monitor(
http_bootstrap->alloc, &http_bootstrap->monitoring_options);
if (http_connection_monitor == NULL) {
goto error;
}
AWS_ASSERT(http_connection_monitor);

aws_channel_set_statistics_handler(channel, http_connection_monitor);
}
Expand Down Expand Up @@ -1030,17 +1028,15 @@ int aws_http_client_connect_internal(

struct aws_http2_setting *setting_array = NULL;
struct aws_hash_table *alpn_string_map = NULL;
if (!aws_mem_acquire_many(
options.allocator,
3,
&http_bootstrap,
sizeof(struct aws_http_client_bootstrap),
&setting_array,
options.http2_options->num_initial_settings * sizeof(struct aws_http2_setting),
&alpn_string_map,
sizeof(struct aws_hash_table))) {
goto error;
}
aws_mem_acquire_many(
options.allocator,
3,
&http_bootstrap,
sizeof(struct aws_http_client_bootstrap),
&setting_array,
options.http2_options->num_initial_settings * sizeof(struct aws_http2_setting),
&alpn_string_map,
sizeof(struct aws_hash_table));

AWS_ZERO_STRUCT(*http_bootstrap);

Expand Down
11 changes: 4 additions & 7 deletions source/connection_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,17 +124,16 @@ enum aws_http_connection_manager_count_type {
* READY - connections may be acquired and released. When the external ref count for the manager
* drops to zero, the manager moves to:
*
* TODO: Seems like connections can still be release while shutting down.
* SHUTTING_DOWN - connections may no longer be acquired and released (how could they if the external
* ref count was accurate?) but in case of user ref errors, we simply fail attempts to do so rather
* than crash or underflow. While in this state, we wait for a set of tracking counters to all fall to zero:
* ref count was accurate?)
* While in this state, we wait for a set of tracking counters to all fall to zero:
*
* pending_connect_count - the # of unresolved calls to the http layer's connect logic
* open_connection_count - the # of connections for whom the shutdown callback (from http) has not been invoked
* vended_connection_count - the # of connections held by external users that haven't been released. Under correct
* usage this should be zero before SHUTTING_DOWN is entered, but we attempt to handle incorrect usage gracefully.
*
* While all the counter fall to zero and no outlife transition, connection manager will detroy itself.
* While all the counter fall to zero and no outlive transition, connection manager will detroy itself.
*
* While shutting down, as pending connects resolve, we immediately release new incoming (from http) connections
*
Expand Down Expand Up @@ -821,9 +820,6 @@ struct aws_http_connection_manager *aws_http_connection_manager_new(

struct aws_http_connection_manager *manager =
aws_mem_calloc(allocator, 1, sizeof(struct aws_http_connection_manager));
if (manager == NULL) {
return NULL;
}

manager->allocator = allocator;

Expand Down Expand Up @@ -1232,6 +1228,7 @@ int aws_http_connection_manager_release_connection(
(void *)connection);

aws_mutex_lock(&manager->lock);
AWS_FATAL_ASSERT(manager->state == AWS_HCMST_READY);

/* We're probably hosed in this case, but let's not underflow */
if (manager->internal_ref[AWS_HCMCT_VENDED_CONNECTION] == 0) {
Expand Down
16 changes: 7 additions & 9 deletions source/connection_monitor.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,15 +204,13 @@ struct aws_crt_statistics_handler *aws_crt_statistics_handler_new_http_connectio
struct aws_crt_statistics_handler *handler = NULL;
struct aws_statistics_handler_http_connection_monitor_impl *impl = NULL;

if (!aws_mem_acquire_many(
allocator,
2,
&handler,
sizeof(struct aws_crt_statistics_handler),
&impl,
sizeof(struct aws_statistics_handler_http_connection_monitor_impl))) {
return NULL;
}
aws_mem_acquire_many(
allocator,
2,
&handler,
sizeof(struct aws_crt_statistics_handler),
&impl,
sizeof(struct aws_statistics_handler_http_connection_monitor_impl));

AWS_ZERO_STRUCT(*handler);
AWS_ZERO_STRUCT(*impl);
Expand Down
9 changes: 1 addition & 8 deletions source/h1_decoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,6 @@ static int s_cat(struct aws_h1_decoder *decoder, struct aws_byte_cursor to_appen
} while (new_size < (buffer->len + to_append.len));

uint8_t *new_data = aws_mem_acquire(buffer->allocator, new_size);
if (!new_data) {
return AWS_OP_ERR;
}

if (buffer->buffer != NULL) {
memcpy(new_data, buffer->buffer, buffer->len);
Expand Down Expand Up @@ -726,11 +723,7 @@ static int s_linestate_response(struct aws_h1_decoder *decoder, struct aws_byte_
struct aws_h1_decoder *aws_h1_decoder_new(struct aws_h1_decoder_params *params) {
AWS_ASSERT(params);

struct aws_h1_decoder *decoder = aws_mem_acquire(params->alloc, sizeof(struct aws_h1_decoder));
if (!decoder) {
return NULL;
}
AWS_ZERO_STRUCT(*decoder);
struct aws_h1_decoder *decoder = aws_mem_calloc(params->alloc, 1, sizeof(struct aws_h1_decoder));

decoder->alloc = params->alloc;
decoder->user_data = params->user_data;
Expand Down
5 changes: 1 addition & 4 deletions source/h1_encoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -542,10 +542,7 @@ struct aws_h1_chunk *aws_h1_chunk_new(struct aws_allocator *allocator, const str
struct aws_h1_chunk *chunk;
size_t chunk_line_size = s_calculate_chunk_line_size(options);
void *chunk_line_storage;
if (!aws_mem_acquire_many(
allocator, 2, &chunk, sizeof(struct aws_h1_chunk), &chunk_line_storage, chunk_line_size)) {
return NULL;
}
aws_mem_acquire_many(allocator, 2, &chunk, sizeof(struct aws_h1_chunk), &chunk_line_storage, chunk_line_size);

chunk->allocator = allocator;
chunk->data = aws_input_stream_acquire(options->chunk_data);
Expand Down
72 changes: 41 additions & 31 deletions source/h2_connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -304,9 +304,6 @@ static struct aws_h2_connection *s_connection_new(
AWS_PRECONDITION(http2_options);

struct aws_h2_connection *connection = aws_mem_calloc(alloc, 1, sizeof(struct aws_h2_connection));
if (!connection) {
return NULL;
}
connection->base.vtable = &s_h2_connection_vtable;
connection->base.alloc = alloc;
connection->base.channel_handler.vtable = &s_h2_connection_vtable.channel_handler_vtable;
Expand Down Expand Up @@ -420,9 +417,7 @@ static struct aws_h2_connection *s_connection_new(
http2_options->num_initial_settings,
http2_options->on_initial_settings_completed,
NULL /* user_data is set later... */);
if (!connection->thread_data.init_pending_settings) {
goto error;
}
AWS_ASSERT(connection->thread_data.init_pending_settings);
/* We enqueue the inital settings when handler get installed */
return connection;

Expand Down Expand Up @@ -511,15 +506,13 @@ static struct aws_h2_pending_settings *s_new_pending_settings(
size_t settings_storage_size = sizeof(struct aws_http2_setting) * num_settings;
struct aws_h2_pending_settings *pending_settings;
void *settings_storage;
if (!aws_mem_acquire_many(
allocator,
2,
&pending_settings,
sizeof(struct aws_h2_pending_settings),
&settings_storage,
settings_storage_size)) {
return NULL;
}
aws_mem_acquire_many(
allocator,
2,
&pending_settings,
sizeof(struct aws_h2_pending_settings),
&settings_storage,
settings_storage_size);

AWS_ZERO_STRUCT(*pending_settings);
/* We buffer the settings up, incase the caller has freed them when the ACK arrives */
Expand All @@ -542,9 +535,7 @@ static struct aws_h2_pending_ping *s_new_pending_ping(
aws_http2_on_ping_complete_fn *on_completed) {

struct aws_h2_pending_ping *pending_ping = aws_mem_calloc(allocator, 1, sizeof(struct aws_h2_pending_ping));
if (!pending_ping) {
return NULL;
}

if (optional_opaque_data) {
memcpy(pending_ping->opaque_data, optional_opaque_data->ptr, AWS_HTTP2_PING_DATA_SIZE);
}
Expand Down Expand Up @@ -1410,9 +1401,6 @@ static struct aws_h2err s_decoder_on_settings(
struct aws_http2_setting *callback_array = NULL;
if (num_settings) {
callback_array = aws_mem_acquire(connection->base.alloc, num_settings * sizeof(struct aws_http2_setting));
if (!callback_array) {
return aws_h2err_from_last_error();
}
}
size_t callback_array_num = 0;

Expand Down Expand Up @@ -2082,9 +2070,6 @@ static struct aws_http_stream *s_connection_make_request(

struct aws_h2_connection *connection = AWS_CONTAINER_OF(client_connection, struct aws_h2_connection, base);

/* #TODO: http/2-ify the request (ex: add ":method" header). Should we mutate a copy or the original? Validate?
* Or just pass pointer to headers struct and let encoder transform it while encoding? */

struct aws_h2_stream *stream = aws_h2_stream_new_request(client_connection, options);
if (!stream) {
CONNECTION_LOGF(
Expand Down Expand Up @@ -2112,8 +2097,28 @@ static struct aws_http_stream *s_connection_make_request(
aws_error_name(aws_last_error()));
goto error;
}
struct aws_byte_cursor method;
AWS_ZERO_STRUCT(method);
struct aws_byte_cursor path;
AWS_ZERO_STRUCT(path);

if (aws_http_message_get_request_method(stream->thread_data.outgoing_message, &method)) {
aws_raise_error(AWS_ERROR_HTTP_REQUIRED_PSEUDO_HEADER_MISSING);
CONNECTION_LOG(ERROR, connection, "Cannot create request stream, the `:method` header is missing.");
goto error;
}
if (aws_http_message_get_request_path(stream->thread_data.outgoing_message, &path)) {
aws_raise_error(AWS_ERROR_HTTP_REQUIRED_PSEUDO_HEADER_MISSING);
CONNECTION_LOG(ERROR, connection, "Cannot create request stream, the `:path` header is missing.");
goto error;
}

AWS_H2_STREAM_LOG(DEBUG, stream, "Created HTTP/2 request stream"); /* #TODO: print method & path */
AWS_H2_STREAM_LOGF(
DEBUG,
stream,
"Created HTTP/2 request stream, method: " PRInSTR ". path: " PRInSTR "",
AWS_BYTE_CURSOR_PRI(method),
AWS_BYTE_CURSOR_PRI(path));
return &stream->base;

error:
Expand Down Expand Up @@ -2263,9 +2268,7 @@ static int s_connection_change_settings(

struct aws_h2_pending_settings *pending_settings =
s_new_pending_settings(connection->base.alloc, settings_array, num_settings, on_completed, user_data);
if (!pending_settings) {
return AWS_OP_ERR;
}
AWS_ASSERT(pending_settings);
struct aws_h2_frame *settings_frame =
aws_h2_frame_new_settings(connection->base.alloc, settings_array, num_settings, false /*ACK*/);
if (!settings_frame) {
Expand Down Expand Up @@ -2818,22 +2821,26 @@ static void s_gather_statistics(struct aws_channel_handler *handler, struct aws_
struct aws_h2_connection *connection = handler->impl;
AWS_PRECONDITION(aws_channel_thread_is_callers_thread(connection->base.channel_slot->channel));

/* TODO: Need update the way we calculate statistics, to account for user-controlled pauses.
* If user is adding chunks 1 by 1, there can naturally be a gap in the upload.
* If the user lets the stream-window go to zero, there can naturally be a gap in the download. */
uint64_t now_ns = 0;
if (aws_channel_current_clock_time(connection->base.channel_slot->channel, &now_ns)) {
return;
}

if (!aws_linked_list_empty(&connection->thread_data.outgoing_streams_list)) {
/**
* For stream flow control stall and writing to stream over time, the stream will be removed from the
* outgoing_streams_list.
* For connection level flow control, as there could be streams waiting for response, we cannot mark the
* connection is inactive.
*/
s_add_time_measurement_to_stats(
connection->thread_data.outgoing_timestamp_ns,
now_ns,
&connection->thread_data.stats.pending_outgoing_stream_ms);

connection->thread_data.outgoing_timestamp_ns = now_ns;
}

if (aws_hash_table_get_entry_count(&connection->thread_data.active_streams_map) != 0) {
s_add_time_measurement_to_stats(
connection->thread_data.incoming_timestamp_ns,
Expand All @@ -2842,6 +2849,9 @@ static void s_gather_statistics(struct aws_channel_handler *handler, struct aws_

connection->thread_data.incoming_timestamp_ns = now_ns;
} else {
TingDaoK marked this conversation as resolved.
Show resolved Hide resolved
/**
* was inactive as no stream has data to write or waiting for data from the other side.
*/
connection->thread_data.stats.was_inactive = true;
}

Expand Down
Loading