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