1 #ifndef AWS_HTTP_H2_STREAM_H 2 #define AWS_HTTP_H2_STREAM_H 3 4 /** 5 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 6 * SPDX-License-Identifier: Apache-2.0. 7 */ 8 9 #include <aws/http/private/h2_frames.h> 10 #include <aws/http/private/request_response_impl.h> 11 12 #include <aws/common/mutex.h> 13 #include <aws/io/channel.h> 14 15 #include <inttypes.h> 16 17 #define AWS_H2_STREAM_LOGF(level, stream, text, ...) \ 18 AWS_LOGF_##level( \ 19 AWS_LS_HTTP_STREAM, \ 20 "id=%" PRIu32 " connection=%p state=%s: " text, \ 21 (stream)->base.id, \ 22 (void *)(stream)->base.owning_connection, \ 23 aws_h2_stream_state_to_str((stream)->thread_data.state), \ 24 __VA_ARGS__) 25 #define AWS_H2_STREAM_LOG(level, stream, text) AWS_H2_STREAM_LOGF(level, (stream), "%s", (text)) 26 27 enum aws_h2_stream_state { 28 /* Initial state, before anything sent or received. */ 29 AWS_H2_STREAM_STATE_IDLE, 30 /* (server-only) stream-id was reserved via PUSH_PROMISE on another stream, 31 * but HEADERS for this stream have not been sent yet */ 32 AWS_H2_STREAM_STATE_RESERVED_LOCAL, 33 /* (client-only) stream-id was reserved via PUSH_PROMISE on another stream, 34 * but HEADERS for this stream have not been received yet */ 35 AWS_H2_STREAM_STATE_RESERVED_REMOTE, 36 /* Neither side is done sending their message. */ 37 AWS_H2_STREAM_STATE_OPEN, 38 /* This side is done sending message (END_STREAM), but peer is not done. */ 39 AWS_H2_STREAM_STATE_HALF_CLOSED_LOCAL, 40 /* Peer is done sending message (END_STREAM), but this side is not done */ 41 AWS_H2_STREAM_STATE_HALF_CLOSED_REMOTE, 42 /* Both sides done sending message (END_STREAM), 43 * or either side has sent RST_STREAM */ 44 AWS_H2_STREAM_STATE_CLOSED, 45 46 AWS_H2_STREAM_STATE_COUNT, 47 }; 48 49 /* simplified stream state for API implementation */ 50 enum aws_h2_stream_api_state { 51 AWS_H2_STREAM_API_STATE_INIT, 52 AWS_H2_STREAM_API_STATE_ACTIVE, 53 AWS_H2_STREAM_API_STATE_COMPLETE, 54 }; 55 56 struct aws_h2_stream { 57 struct aws_http_stream base; 58 59 struct aws_linked_list_node node; 60 struct aws_channel_task cross_thread_work_task; 61 62 /* Only the event-loop thread may touch this data */ 63 struct { 64 enum aws_h2_stream_state state; 65 int32_t window_size_peer; 66 /* The local window size. 67 * We allow this value exceed the max window size (int64 can hold much more than 0x7FFFFFFF), 68 * We leave it up to the remote peer to detect whether the max window size has been exceeded. */ 69 int64_t window_size_self; 70 struct aws_http_message *outgoing_message; 71 bool received_main_headers; 72 } thread_data; 73 74 /* Any thread may touch this data, but the lock must be held (unless it's an atomic) */ 75 struct { 76 struct aws_mutex lock; 77 78 bool is_cross_thread_work_task_scheduled; 79 80 /* The window_update value for `thread_data.window_size_self` that haven't applied yet */ 81 size_t window_update_size; 82 83 /* The combined aws_http2_error_code user wanted to send to remote peer via rst_stream and internal aws error 84 * code we want to inform user about. */ 85 struct aws_h2err reset_error; 86 bool reset_called; 87 88 /* Simplified stream state. */ 89 enum aws_h2_stream_api_state api_state; 90 } synced_data; 91 92 /* Store the sent reset HTTP/2 error code, set to -1, if none has sent so far */ 93 int64_t sent_reset_error_code; 94 95 /* Store the received reset HTTP/2 error code, set to -1, if none has received so far */ 96 int64_t received_reset_error_code; 97 }; 98 99 const char *aws_h2_stream_state_to_str(enum aws_h2_stream_state state); 100 101 struct aws_h2_stream *aws_h2_stream_new_request( 102 struct aws_http_connection *client_connection, 103 const struct aws_http_make_request_options *options); 104 105 enum aws_h2_stream_state aws_h2_stream_get_state(const struct aws_h2_stream *stream); 106 107 struct aws_h2err aws_h2_stream_window_size_change(struct aws_h2_stream *stream, int32_t size_changed, bool self); 108 109 /* Connection is ready to send frames from stream now */ 110 int aws_h2_stream_on_activated(struct aws_h2_stream *stream, bool *out_has_outgoing_data); 111 112 /* Connection is ready to send data from stream now. 113 * Stream may complete itself during this call. 114 * data_encode_status: 115 * AWS_H2_DATA_ENCODE_COMPLETE: Finished encoding data for the stream 116 * AWS_H2_DATA_ENCODE_ONGOING: Stream has more data to send. 117 * AWS_H2_DATA_ENCODE_ONGOING_BODY_STALLED: Stream has more data to send, but it's not ready right now 118 * AWS_H2_DATA_ENCODE_ONGOING_WINDOW_STALLED: Stream has more data to send but its window size is too small, and stream 119 * will be moved to stalled_window_stream_list */ 120 int aws_h2_stream_encode_data_frame( 121 struct aws_h2_stream *stream, 122 struct aws_h2_frame_encoder *encoder, 123 struct aws_byte_buf *output, 124 int *data_encode_status); 125 126 struct aws_h2err aws_h2_stream_on_decoder_headers_begin(struct aws_h2_stream *stream); 127 128 struct aws_h2err aws_h2_stream_on_decoder_headers_i( 129 struct aws_h2_stream *stream, 130 const struct aws_http_header *header, 131 enum aws_http_header_name name_enum, 132 enum aws_http_header_block block_type); 133 134 struct aws_h2err aws_h2_stream_on_decoder_headers_end( 135 struct aws_h2_stream *stream, 136 bool malformed, 137 enum aws_http_header_block block_type); 138 139 struct aws_h2err aws_h2_stream_on_decoder_push_promise(struct aws_h2_stream *stream, uint32_t promised_stream_id); 140 struct aws_h2err aws_h2_stream_on_decoder_data_begin( 141 struct aws_h2_stream *stream, 142 uint32_t payload_len, 143 bool end_stream); 144 struct aws_h2err aws_h2_stream_on_decoder_data_i(struct aws_h2_stream *stream, struct aws_byte_cursor data); 145 struct aws_h2err aws_h2_stream_on_decoder_window_update( 146 struct aws_h2_stream *stream, 147 uint32_t window_size_increment, 148 bool *window_resume); 149 struct aws_h2err aws_h2_stream_on_decoder_end_stream(struct aws_h2_stream *stream); 150 struct aws_h2err aws_h2_stream_on_decoder_rst_stream(struct aws_h2_stream *stream, uint32_t h2_error_code); 151 152 int aws_h2_stream_activate(struct aws_http_stream *stream); 153 154 #endif /* AWS_HTTP_H2_STREAM_H */ 155