-
Notifications
You must be signed in to change notification settings - Fork 50
Expand file tree
/
Copy pathh1_stream.h
More file actions
156 lines (118 loc) · 6.03 KB
/
h1_stream.h
File metadata and controls
156 lines (118 loc) · 6.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#ifndef AWS_HTTP_H1_STREAM_H
#define AWS_HTTP_H1_STREAM_H
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
#include <aws/http/private/h1_encoder.h>
#include <aws/http/private/http_impl.h>
#include <aws/http/private/request_response_impl.h>
#include <aws/io/channel.h>
#ifdef _MSC_VER
# pragma warning(disable : 4214) /* nonstandard extension used: bit field types other than int */
#endif
/* Simple view of stream's state.
* Used to determine whether it's safe for a user to call functions that alter state. */
enum aws_h1_stream_api_state {
AWS_H1_STREAM_API_STATE_INIT,
AWS_H1_STREAM_API_STATE_ACTIVE,
AWS_H1_STREAM_API_STATE_COMPLETE,
};
struct aws_h1_data_write {
struct aws_allocator *allocator;
struct aws_input_stream *data;
aws_http_stream_write_complete_fn *on_complete;
void *user_data;
struct aws_linked_list_node node;
bool is_end_stream;
};
struct aws_h1_stream {
struct aws_http_stream base;
struct aws_linked_list_node node;
/* Task that removes items from `synced_data` and does their on-thread work.
* Runs once and wait until it's scheduled again.
* Any function that wants to schedule this task MUST:
* - acquire the synced_data.lock
* - check whether `synced_data.is_cross_thread_work_scheduled` was true or false.
* - set `synced_data.is_cross_thread_work_scheduled = true`
* - release synced_data.lock
* - ONLY IF `synced_data.is_cross_thread_work_scheduled` CHANGED from false to true:
* - increment the stream's refcount, to keep stream alive until task runs
* - schedule the task
*/
struct aws_channel_task cross_thread_work_task;
/* Whether the stream is using manual data writes instead of input_stream */
bool using_manual_data_writes : 1;
struct {
/* Message (derived from outgoing request or response) to be submitted to encoder */
struct aws_h1_encoder_message encoder_message;
bool is_outgoing_message_done;
bool is_incoming_message_done;
bool is_incoming_head_done;
/* If true, this is the last stream the connection should process.
* See RFC-7230 Section 6: Connection Management. */
bool is_final_stream;
/* Buffer for incoming data that needs to stick around. */
struct aws_byte_buf incoming_storage_buf;
/* List of `struct aws_h1_chunk`, used for chunked encoding.
* Encoder completes/frees/pops front chunk when it's done sending. */
struct aws_linked_list pending_chunk_list;
struct aws_h1_encoder_message message;
/* Size of stream's flow-control window.
* Only body data (not headers, etc) counts against the stream's flow-control window. */
uint64_t stream_window;
/* List of `struct aws_h1_data_write` which have been moved from synced_data for processing */
struct aws_linked_list pending_data_write_list;
/* Whether the final data write (with is_end_stream=true) has been received */
bool has_final_data_write : 1;
/* Whether a "request handler" stream has a response to send.
* Has mirror variable in synced_data */
bool has_outgoing_response : 1;
} thread_data;
/* Any thread may touch this data, but the connection's lock must be held.
* Sharing a lock is fine because it's rare for an HTTP/1 connection
* to have more than one stream at a time. */
struct {
/* Outgoing response on "request handler" stream which has been submitted by user,
* but hasn't yet moved to thread_data.encoder_message. */
struct aws_h1_encoder_message pending_outgoing_response;
/* List of `struct aws_h1_chunk` which have been submitted by user,
* but haven't yet moved to thread_data.encoder_message.pending_chunk_list where the encoder will find them. */
struct aws_linked_list pending_chunk_list;
/* List of `struct aws_h1_data_write` which have been submitted by user,
* but haven't yet moved to thread_data.pending_data_write_list where the encoder will find them. */
struct aws_linked_list pending_data_write_list;
/* trailing headers which have been submitted by user,
* but haven't yet moved to thread_data.encoder_message where the encoder will find them. */
struct aws_h1_trailer *pending_trailer;
enum aws_h1_stream_api_state api_state;
/* Sum of all aws_http_stream_update_window() calls that haven't yet moved to thread_data.stream_window */
uint64_t pending_window_update;
/* See `cross_thread_work_task` */
bool is_cross_thread_work_task_scheduled : 1;
/* Whether a "request handler" stream has a response to send.
* Has mirror variable in thread_data */
bool has_outgoing_response : 1;
/* Whether the outgoing message is using chunked encoding */
bool using_chunked_encoding : 1;
/* Whether the final 0 length chunk has already been sent */
bool has_final_chunk : 1;
/* Whether the final data write (with is_end_stream=true) has been received */
bool has_final_data_write : 1;
/* Whether the chunked trailer has already been sent */
bool has_added_trailer : 1;
} synced_data;
};
/* DO NOT export functions below. They're only used by other .c files in this library */
struct aws_h1_stream *aws_h1_stream_new_request(
struct aws_http_connection *client_connection,
const struct aws_http_make_request_options *options);
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);
void aws_h1_data_write_complete_and_destroy(
struct aws_h1_data_write *data_write,
struct aws_http_stream *http_stream,
int error_code);
#endif /* AWS_HTTP_H1_STREAM_H */