blob: e5e6f445b7021f121723ebca4f88ee5c7f865bb2 [file] [log] [blame]
Craig Tiller640d3bd2015-06-12 07:51:51 -07001/*
2 *
3 * Copyright 2015, Google Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
Craig Tiller9b8671c2015-06-12 07:41:54 -070034#ifndef GRPC_INTERNAL_CORE_CHTTP2_INTERNAL_H
35#define GRPC_INTERNAL_CORE_CHTTP2_INTERNAL_H
36
Craig Tiller3208e392015-06-12 08:17:02 -070037#include "src/core/iomgr/endpoint.h"
Craig Tillerd20efd22015-06-12 16:17:09 -070038#include "src/core/transport/chttp2/frame.h"
Craig Tiller3208e392015-06-12 08:17:02 -070039#include "src/core/transport/chttp2/frame_data.h"
40#include "src/core/transport/chttp2/frame_goaway.h"
41#include "src/core/transport/chttp2/frame_ping.h"
42#include "src/core/transport/chttp2/frame_rst_stream.h"
43#include "src/core/transport/chttp2/frame_settings.h"
44#include "src/core/transport/chttp2/frame_window_update.h"
Craig Tiller3208e392015-06-12 08:17:02 -070045#include "src/core/transport/chttp2/hpack_parser.h"
Craig Tiller5dc3b302015-06-15 16:06:50 -070046#include "src/core/transport/chttp2/incoming_metadata.h"
Craig Tiller3208e392015-06-12 08:17:02 -070047#include "src/core/transport/chttp2/stream_encoder.h"
Craig Tiller5dc3b302015-06-15 16:06:50 -070048#include "src/core/transport/chttp2/stream_map.h"
Craig Tiller08a1cf82015-06-29 09:37:52 -070049#include "src/core/transport/connectivity_state.h"
50#include "src/core/transport/transport_impl.h"
Craig Tiller9b8671c2015-06-12 07:41:54 -070051
Craig Tillerb084d902015-06-12 07:50:02 -070052typedef struct grpc_chttp2_transport grpc_chttp2_transport;
53typedef struct grpc_chttp2_stream grpc_chttp2_stream;
Craig Tiller9b8671c2015-06-12 07:41:54 -070054
55/* streams are kept in various linked lists depending on what things need to
56 happen to them... this enum labels each list */
57typedef enum {
Craig Tiller5dc3b302015-06-15 16:06:50 -070058 GRPC_CHTTP2_LIST_ALL_STREAMS,
Craig Tiller6459db42015-06-15 17:11:45 -070059 GRPC_CHTTP2_LIST_READ_WRITE_STATE_CHANGED,
Craig Tiller5dc3b302015-06-15 16:06:50 -070060 GRPC_CHTTP2_LIST_WRITABLE,
Craig Tiller6459db42015-06-15 17:11:45 -070061 GRPC_CHTTP2_LIST_WRITING,
62 GRPC_CHTTP2_LIST_WRITTEN,
63 GRPC_CHTTP2_LIST_WRITABLE_WINDOW_UPDATE,
64 GRPC_CHTTP2_LIST_PARSING_SEEN,
Craig Tiller83fb0702015-06-16 21:13:07 -070065 GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_PARSING,
Craig Tiller17be5dc2015-07-01 10:36:27 -070066 GRPC_CHTTP2_LIST_CANCELLED_WAITING_FOR_WRITING,
Craig Tillercf1e3192015-06-16 14:28:22 -070067 GRPC_CHTTP2_LIST_INCOMING_WINDOW_UPDATED,
Craig Tiller5dc3b302015-06-15 16:06:50 -070068 /** streams that are waiting to start because there are too many concurrent
69 streams on the connection */
70 GRPC_CHTTP2_LIST_WAITING_FOR_CONCURRENCY,
Craig Tiller9b8671c2015-06-12 07:41:54 -070071 STREAM_LIST_COUNT /* must be last */
Craig Tillerb084d902015-06-12 07:50:02 -070072} grpc_chttp2_stream_list_id;
Craig Tiller9b8671c2015-06-12 07:41:54 -070073
74/* deframer state for the overall http2 stream of bytes */
75typedef enum {
76 /* prefix: one entry per http2 connection prefix byte */
Craig Tillerab630732015-06-25 11:20:01 -070077 GRPC_DTS_CLIENT_PREFIX_0 = 0,
78 GRPC_DTS_CLIENT_PREFIX_1,
79 GRPC_DTS_CLIENT_PREFIX_2,
80 GRPC_DTS_CLIENT_PREFIX_3,
81 GRPC_DTS_CLIENT_PREFIX_4,
82 GRPC_DTS_CLIENT_PREFIX_5,
83 GRPC_DTS_CLIENT_PREFIX_6,
84 GRPC_DTS_CLIENT_PREFIX_7,
85 GRPC_DTS_CLIENT_PREFIX_8,
86 GRPC_DTS_CLIENT_PREFIX_9,
87 GRPC_DTS_CLIENT_PREFIX_10,
88 GRPC_DTS_CLIENT_PREFIX_11,
89 GRPC_DTS_CLIENT_PREFIX_12,
90 GRPC_DTS_CLIENT_PREFIX_13,
91 GRPC_DTS_CLIENT_PREFIX_14,
92 GRPC_DTS_CLIENT_PREFIX_15,
93 GRPC_DTS_CLIENT_PREFIX_16,
94 GRPC_DTS_CLIENT_PREFIX_17,
95 GRPC_DTS_CLIENT_PREFIX_18,
96 GRPC_DTS_CLIENT_PREFIX_19,
97 GRPC_DTS_CLIENT_PREFIX_20,
98 GRPC_DTS_CLIENT_PREFIX_21,
99 GRPC_DTS_CLIENT_PREFIX_22,
100 GRPC_DTS_CLIENT_PREFIX_23,
Craig Tiller9b8671c2015-06-12 07:41:54 -0700101 /* frame header byte 0... */
102 /* must follow from the prefix states */
Craig Tillerab630732015-06-25 11:20:01 -0700103 GRPC_DTS_FH_0,
104 GRPC_DTS_FH_1,
105 GRPC_DTS_FH_2,
106 GRPC_DTS_FH_3,
107 GRPC_DTS_FH_4,
108 GRPC_DTS_FH_5,
109 GRPC_DTS_FH_6,
110 GRPC_DTS_FH_7,
Craig Tiller9b8671c2015-06-12 07:41:54 -0700111 /* ... frame header byte 8 */
Craig Tillerab630732015-06-25 11:20:01 -0700112 GRPC_DTS_FH_8,
Craig Tiller9b8671c2015-06-12 07:41:54 -0700113 /* inside a http2 frame */
Craig Tillerab630732015-06-25 11:20:01 -0700114 GRPC_DTS_FRAME
Craig Tillerb084d902015-06-12 07:50:02 -0700115} grpc_chttp2_deframe_transport_state;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700116
117typedef enum {
Craig Tillerab630732015-06-25 11:20:01 -0700118 GRPC_WRITE_STATE_OPEN,
119 GRPC_WRITE_STATE_QUEUED_CLOSE,
120 GRPC_WRITE_STATE_SENT_CLOSE
Craig Tillerb084d902015-06-12 07:50:02 -0700121} grpc_chttp2_write_state;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700122
123typedef enum {
Craig Tillerab630732015-06-25 11:20:01 -0700124 GRPC_DONT_SEND_CLOSED = 0,
125 GRPC_SEND_CLOSED,
126 GRPC_SEND_CLOSED_WITH_RST_STREAM
Craig Tillerb084d902015-06-12 07:50:02 -0700127} grpc_chttp2_send_closed;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700128
129typedef struct {
Craig Tillerb084d902015-06-12 07:50:02 -0700130 grpc_chttp2_stream *head;
131 grpc_chttp2_stream *tail;
132} grpc_chttp2_stream_list;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700133
134typedef struct {
Craig Tillerb084d902015-06-12 07:50:02 -0700135 grpc_chttp2_stream *next;
136 grpc_chttp2_stream *prev;
137} grpc_chttp2_stream_link;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700138
Craig Tiller9b8671c2015-06-12 07:41:54 -0700139/* We keep several sets of connection wide parameters */
140typedef enum {
141 /* The settings our peer has asked for (and we have acked) */
Craig Tillerab630732015-06-25 11:20:01 -0700142 GRPC_PEER_SETTINGS = 0,
Craig Tiller9b8671c2015-06-12 07:41:54 -0700143 /* The settings we'd like to have */
Craig Tillerab630732015-06-25 11:20:01 -0700144 GRPC_LOCAL_SETTINGS,
Craig Tiller9b8671c2015-06-12 07:41:54 -0700145 /* The settings we've published to our peer */
Craig Tillerab630732015-06-25 11:20:01 -0700146 GRPC_SENT_SETTINGS,
Craig Tiller9b8671c2015-06-12 07:41:54 -0700147 /* The settings the peer has acked */
Craig Tillerab630732015-06-25 11:20:01 -0700148 GRPC_ACKED_SETTINGS,
149 GRPC_NUM_SETTING_SETS
Craig Tillerb084d902015-06-12 07:50:02 -0700150} grpc_chttp2_setting_set;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700151
152/* Outstanding ping request data */
Craig Tiller3719f072015-06-12 17:19:51 -0700153typedef struct grpc_chttp2_outstanding_ping {
Craig Tiller9b8671c2015-06-12 07:41:54 -0700154 gpr_uint8 id[8];
Craig Tiller3719f072015-06-12 17:19:51 -0700155 grpc_iomgr_closure *on_recv;
156 struct grpc_chttp2_outstanding_ping *next;
157 struct grpc_chttp2_outstanding_ping *prev;
Craig Tillerb084d902015-06-12 07:50:02 -0700158} grpc_chttp2_outstanding_ping;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700159
160typedef struct {
Craig Tillerd20efd22015-06-12 16:17:09 -0700161 /** data to write next write */
162 gpr_slice_buffer qbuf;
163 /** queued callbacks */
Craig Tillerff3ae682015-06-29 17:44:04 -0700164 grpc_iomgr_closure *pending_closures_head;
165 grpc_iomgr_closure *pending_closures_tail;
Craig Tillerd20efd22015-06-12 16:17:09 -0700166
167 /** window available for us to send to peer */
168 gpr_uint32 outgoing_window;
Craig Tiller3719f072015-06-12 17:19:51 -0700169 /** window available for peer to send to us - updated after parse */
170 gpr_uint32 incoming_window;
Craig Tillerd20efd22015-06-12 16:17:09 -0700171 /** how much window would we like to have for incoming_window */
172 gpr_uint32 connection_window_target;
173
Craig Tiller1064f8b2015-06-25 13:52:57 -0700174 /** have we seen a goaway */
175 gpr_uint8 seen_goaway;
Craig Tiller9188d7a2015-07-05 12:44:37 -0700176 /** have we sent a goaway */
177 gpr_uint8 sent_goaway;
Craig Tiller1064f8b2015-06-25 13:52:57 -0700178
Craig Tiller3719f072015-06-12 17:19:51 -0700179 /** is this transport a client? */
180 gpr_uint8 is_client;
Craig Tillerd20efd22015-06-12 16:17:09 -0700181 /** are the local settings dirty and need to be sent? */
182 gpr_uint8 dirtied_local_settings;
183 /** have local settings been sent? */
184 gpr_uint8 sent_local_settings;
185 /** bitmask of setting indexes to send out */
Craig Tiller4aa71a12015-06-15 13:00:55 -0700186 gpr_uint32 force_send_settings;
Craig Tillerd20efd22015-06-12 16:17:09 -0700187 /** settings values */
Craig Tillerab630732015-06-25 11:20:01 -0700188 gpr_uint32 settings[GRPC_NUM_SETTING_SETS][GRPC_CHTTP2_NUM_SETTINGS];
Craig Tillerd20efd22015-06-12 16:17:09 -0700189
Craig Tiller606d8742015-06-15 06:58:50 -0700190 /** what is the next stream id to be allocated by this peer?
191 copied to next_stream_id in parsing when parsing commences */
192 gpr_uint32 next_stream_id;
193
Craig Tillerd20efd22015-06-12 16:17:09 -0700194 /** last received stream id */
195 gpr_uint32 last_incoming_stream_id;
Craig Tiller3719f072015-06-12 17:19:51 -0700196
197 /** pings awaiting responses */
198 grpc_chttp2_outstanding_ping pings;
Craig Tiller606d8742015-06-15 06:58:50 -0700199 /** next payload for an outgoing ping */
200 gpr_uint64 ping_counter;
201
202 /** concurrent stream count: updated when not parsing,
203 so this is a strict over-estimation on the client */
204 gpr_uint32 concurrent_stream_count;
Craig Tillerd20efd22015-06-12 16:17:09 -0700205} grpc_chttp2_transport_global;
206
207typedef struct {
208 /** data to write now */
209 gpr_slice_buffer outbuf;
210 /** hpack encoding */
211 grpc_chttp2_hpack_compressor hpack_compressor;
Craig Tiller285b8822015-06-17 15:58:13 -0700212 /** is this a client? */
213 gpr_uint8 is_client;
Craig Tillerd20efd22015-06-12 16:17:09 -0700214} grpc_chttp2_transport_writing;
215
216struct grpc_chttp2_transport_parsing {
217 /** is this transport a client? (boolean) */
218 gpr_uint8 is_client;
219
220 /** were settings updated? */
221 gpr_uint8 settings_updated;
222 /** was a settings ack received? */
223 gpr_uint8 settings_ack_received;
224 /** was a goaway frame received? */
225 gpr_uint8 goaway_received;
226
Craig Tiller3719f072015-06-12 17:19:51 -0700227 /** initial window change */
228 gpr_int64 initial_window_update;
229
Craig Tillerd20efd22015-06-12 16:17:09 -0700230 /** data to write later - after parsing */
231 gpr_slice_buffer qbuf;
232 /* metadata object cache */
233 grpc_mdstr *str_grpc_timeout;
234 /** parser for headers */
235 grpc_chttp2_hpack_parser hpack_parser;
236 /** simple one shot parsers */
237 union {
238 grpc_chttp2_window_update_parser window_update;
239 grpc_chttp2_settings_parser settings;
240 grpc_chttp2_ping_parser ping;
241 grpc_chttp2_rst_stream_parser rst_stream;
242 } simple;
243 /** parser for goaway frames */
244 grpc_chttp2_goaway_parser goaway_parser;
245
246 /** window available for peer to send to us */
247 gpr_uint32 incoming_window;
Craig Tiller285b8822015-06-17 15:58:13 -0700248 gpr_uint32 incoming_window_delta;
Craig Tillerd20efd22015-06-12 16:17:09 -0700249
250 /** next stream id available at the time of beginning parsing */
251 gpr_uint32 next_stream_id;
252 gpr_uint32 last_incoming_stream_id;
253
254 /* deframing */
255 grpc_chttp2_deframe_transport_state deframe_state;
256 gpr_uint8 incoming_frame_type;
257 gpr_uint8 incoming_frame_flags;
258 gpr_uint8 header_eof;
259 gpr_uint32 expect_continuation_stream_id;
260 gpr_uint32 incoming_frame_size;
261 gpr_uint32 incoming_stream_id;
262
263 /* active parser */
264 void *parser_data;
265 grpc_chttp2_stream_parsing *incoming_stream;
Craig Tiller4aa71a12015-06-15 13:00:55 -0700266 grpc_chttp2_parse_error (*parser)(
267 void *parser_user_data, grpc_chttp2_transport_parsing *transport_parsing,
268 grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
Craig Tillerd20efd22015-06-12 16:17:09 -0700269
270 /* received settings */
271 gpr_uint32 settings[GRPC_CHTTP2_NUM_SETTINGS];
272
273 /* goaway data */
274 grpc_status_code goaway_error;
275 gpr_uint32 goaway_last_stream_index;
276 gpr_slice goaway_text;
Craig Tiller3719f072015-06-12 17:19:51 -0700277
278 gpr_uint64 outgoing_window_update;
279
280 /** pings awaiting responses */
281 grpc_chttp2_outstanding_ping pings;
Craig Tillerd20efd22015-06-12 16:17:09 -0700282};
283
Craig Tillerb084d902015-06-12 07:50:02 -0700284struct grpc_chttp2_transport {
Craig Tiller9b8671c2015-06-12 07:41:54 -0700285 grpc_transport base; /* must be first */
286 grpc_endpoint *ep;
287 grpc_mdctx *metadata_context;
288 gpr_refcount refs;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700289
290 gpr_mu mu;
Craig Tiller606d8742015-06-15 06:58:50 -0700291
292 /** is the transport destroying itself? */
293 gpr_uint8 destroying;
294 /** has the upper layer closed the transport? */
295 gpr_uint8 closed;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700296
Craig Tillerd20efd22015-06-12 16:17:09 -0700297 /** is a thread currently writing */
298 gpr_uint8 writing_active;
Craig Tiller606d8742015-06-15 06:58:50 -0700299 /** is a thread currently parsing */
300 gpr_uint8 parsing_active;
Craig Tillerd20efd22015-06-12 16:17:09 -0700301
Craig Tiller606d8742015-06-15 06:58:50 -0700302 /** is there a read request to the endpoint outstanding? */
303 gpr_uint8 endpoint_reading;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700304
Craig Tiller606d8742015-06-15 06:58:50 -0700305 /** various lists of streams */
Craig Tillerb084d902015-06-12 07:50:02 -0700306 grpc_chttp2_stream_list lists[STREAM_LIST_COUNT];
Craig Tiller9b8671c2015-06-12 07:41:54 -0700307
Craig Tiller606d8742015-06-15 06:58:50 -0700308 /** global state for reading/writing */
Craig Tillerd20efd22015-06-12 16:17:09 -0700309 grpc_chttp2_transport_global global;
Craig Tiller606d8742015-06-15 06:58:50 -0700310 /** state only accessible by the chain of execution that
311 set writing_active=1 */
Craig Tillerd20efd22015-06-12 16:17:09 -0700312 grpc_chttp2_transport_writing writing;
Craig Tiller606d8742015-06-15 06:58:50 -0700313 /** state only accessible by the chain of execution that
314 set parsing_active=1 */
Craig Tillerd20efd22015-06-12 16:17:09 -0700315 grpc_chttp2_transport_parsing parsing;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700316
Craig Tiller606d8742015-06-15 06:58:50 -0700317 /** maps stream id to grpc_chttp2_stream objects;
318 owned by the parsing thread when parsing */
319 grpc_chttp2_stream_map parsing_stream_map;
320
321 /** streams created by the client (possibly during parsing);
322 merged with parsing_stream_map during unlock when no
323 parsing is occurring */
324 grpc_chttp2_stream_map new_stream_map;
325
Craig Tillerd20efd22015-06-12 16:17:09 -0700326 /** closure to execute writing */
327 grpc_iomgr_closure writing_action;
Craig Tiller8b2f1d72015-06-18 13:38:38 -0700328 /** closure to start reading from the endpoint */
329 grpc_iomgr_closure reading_action;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700330
Craig Tiller4aa71a12015-06-15 13:00:55 -0700331 /** address to place a newly accepted stream - set and unset by
Craig Tiller606d8742015-06-15 06:58:50 -0700332 grpc_chttp2_parsing_accept_stream; used by init_stream to
333 publish the accepted server stream */
334 grpc_chttp2_stream **accepting_stream;
335
Craig Tiller9b8671c2015-06-12 07:41:54 -0700336 struct {
Craig Tiller1064f8b2015-06-25 13:52:57 -0700337 /* accept stream callback */
338 void (*accept_stream)(void *user_data, grpc_transport *transport,
339 const void *server_data);
340 void *accept_stream_user_data;
341
342 /** connectivity tracking */
Craig Tiller08a1cf82015-06-29 09:37:52 -0700343 grpc_connectivity_state_tracker state_tracker;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700344 } channel_callback;
345};
346
Craig Tillerd20efd22015-06-12 16:17:09 -0700347typedef struct {
348 /** HTTP2 stream id for this stream, or zero if one has not been assigned */
Craig Tiller9b8671c2015-06-12 07:41:54 -0700349 gpr_uint32 id;
350
Craig Tillerd20efd22015-06-12 16:17:09 -0700351 grpc_iomgr_closure *send_done_closure;
352 grpc_iomgr_closure *recv_done_closure;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700353
Craig Tillerd20efd22015-06-12 16:17:09 -0700354 /** window available for us to send to peer */
355 gpr_int64 outgoing_window;
Craig Tiller27166a62015-07-05 21:08:33 -0700356 /** The number of bytes the upper layers have offered to receive.
357 As the upper layer offers more bytes, this value increases.
358 As bytes are read, this value decreases. */
359 gpr_uint32 max_recv_bytes;
360 /** The number of bytes the upper layer has offered to read but we have
361 not yet announced to HTTP2 flow control.
362 As the upper layers offer to read more bytes, this value increases.
363 As we advertise incoming flow control window, this value decreases. */
364 gpr_uint32 unannounced_incoming_window;
365 /** The number of bytes of HTTP2 flow control we have advertised.
366 As we advertise incoming flow control window, this value increases.
367 As bytes are read, this value decreases.
368 Updated after parse. */
Craig Tiller3719f072015-06-12 17:19:51 -0700369 gpr_uint32 incoming_window;
Craig Tillerd20efd22015-06-12 16:17:09 -0700370 /** stream ops the transport user would like to send */
371 grpc_stream_op_buffer *outgoing_sopb;
372 /** when the application requests writes be closed, the write_closed is
373 'queued'; when the close is flow controlled into the send path, we are
374 'sending' it; when the write has been performed it is 'sent' */
375 grpc_chttp2_write_state write_state;
376 /** is this stream closed (boolean) */
377 gpr_uint8 read_closed;
Craig Tiller5dc3b302015-06-15 16:06:50 -0700378 /** has this stream been cancelled? (boolean) */
379 gpr_uint8 cancelled;
Craig Tillercec9eb92015-06-17 17:16:48 -0700380 grpc_status_code cancelled_status;
381 /** have we told the upper layer that this stream is cancelled? */
382 gpr_uint8 published_cancelled;
Craig Tiller5dc3b302015-06-15 16:06:50 -0700383 /** is this stream in the stream map? (boolean) */
384 gpr_uint8 in_stream_map;
Craig Tiller606d8742015-06-15 06:58:50 -0700385
386 /** stream state already published to the upper layer */
387 grpc_stream_state published_state;
388 /** address to publish next stream state to */
389 grpc_stream_state *publish_state;
390 /** pointer to sop buffer to fill in with new stream ops */
Craig Tiller6905b7c2015-06-16 15:33:33 -0700391 grpc_stream_op_buffer *publish_sopb;
392 grpc_stream_op_buffer incoming_sopb;
Craig Tiller5dc3b302015-06-15 16:06:50 -0700393
394 /** incoming metadata */
395 grpc_chttp2_incoming_metadata_buffer incoming_metadata;
Craig Tillerb787c502015-06-15 16:14:52 -0700396 grpc_chttp2_incoming_metadata_live_op_buffer outstanding_metadata;
Craig Tillerd20efd22015-06-12 16:17:09 -0700397} grpc_chttp2_stream_global;
398
399typedef struct {
400 /** HTTP2 stream id for this stream, or zero if one has not been assigned */
401 gpr_uint32 id;
402 /** sops that have passed flow control to be written */
403 grpc_stream_op_buffer sopb;
404 /** how strongly should we indicate closure with the next write */
405 grpc_chttp2_send_closed send_closed;
Craig Tiller86316522015-07-15 11:35:07 -0700406 /** how much window should we announce? */
407 gpr_uint32 announce_window;
Craig Tillerd20efd22015-06-12 16:17:09 -0700408} grpc_chttp2_stream_writing;
409
410struct grpc_chttp2_stream_parsing {
411 /** HTTP2 stream id for this stream, or zero if one has not been assigned */
412 gpr_uint32 id;
413 /** has this stream received a close */
414 gpr_uint8 received_close;
Craig Tiller3719f072015-06-12 17:19:51 -0700415 /** saw a rst_stream */
416 gpr_uint8 saw_rst_stream;
Craig Tiller606d8742015-06-15 06:58:50 -0700417 /** incoming_window has been reduced by this much during parsing */
418 gpr_uint32 incoming_window_delta;
Craig Tillerd20efd22015-06-12 16:17:09 -0700419 /** window available for peer to send to us */
420 gpr_uint32 incoming_window;
421 /** parsing state for data frames */
422 grpc_chttp2_data_parser data_parser;
Craig Tiller3719f072015-06-12 17:19:51 -0700423 /** reason give to rst_stream */
424 gpr_uint32 rst_stream_reason;
425 /* amount of window given */
426 gpr_uint64 outgoing_window_update;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700427
Craig Tiller5dc3b302015-06-15 16:06:50 -0700428 /** incoming metadata */
429 grpc_chttp2_incoming_metadata_buffer incoming_metadata;
Craig Tillerd20efd22015-06-12 16:17:09 -0700430};
431
432struct grpc_chttp2_stream {
433 grpc_chttp2_stream_global global;
434 grpc_chttp2_stream_writing writing;
Craig Tiller606d8742015-06-15 06:58:50 -0700435 grpc_chttp2_stream_parsing parsing;
Craig Tillerd20efd22015-06-12 16:17:09 -0700436
437 grpc_chttp2_stream_link links[STREAM_LIST_COUNT];
438 gpr_uint8 included[STREAM_LIST_COUNT];
Craig Tiller9b8671c2015-06-12 07:41:54 -0700439};
440
Craig Tillerd20efd22015-06-12 16:17:09 -0700441/** Transport writing call flow:
Craig Tiller4aa71a12015-06-15 13:00:55 -0700442 chttp2_transport.c calls grpc_chttp2_unlocking_check_writes to see if writes
443 are required;
444 if they are, chttp2_transport.c calls grpc_chttp2_perform_writes to do the
445 writes.
446 Once writes have been completed (meaning another write could potentially be
447 started),
448 grpc_chttp2_terminate_writing is called. This will call
449 grpc_chttp2_cleanup_writing, at which
Craig Tillerd20efd22015-06-12 16:17:09 -0700450 point the write phase is complete. */
451
Craig Tiller3208e392015-06-12 08:17:02 -0700452/** Someone is unlocking the transport mutex: check to see if writes
453 are required, and schedule them if so */
Craig Tiller4aa71a12015-06-15 13:00:55 -0700454int grpc_chttp2_unlocking_check_writes(grpc_chttp2_transport_global *global,
455 grpc_chttp2_transport_writing *writing);
456void grpc_chttp2_perform_writes(
457 grpc_chttp2_transport_writing *transport_writing, grpc_endpoint *endpoint);
458void grpc_chttp2_terminate_writing(
459 grpc_chttp2_transport_writing *transport_writing, int success);
460void grpc_chttp2_cleanup_writing(grpc_chttp2_transport_global *global,
461 grpc_chttp2_transport_writing *writing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700462
Craig Tiller4aa71a12015-06-15 13:00:55 -0700463void grpc_chttp2_prepare_to_read(grpc_chttp2_transport_global *global,
464 grpc_chttp2_transport_parsing *parsing);
Craig Tillerab630732015-06-25 11:20:01 -0700465/** Process one slice of incoming data; return 1 if the connection is still
466 viable after reading, or 0 if the connection should be torn down */
Craig Tiller4aa71a12015-06-15 13:00:55 -0700467int grpc_chttp2_perform_read(grpc_chttp2_transport_parsing *transport_parsing,
468 gpr_slice slice);
469void grpc_chttp2_publish_reads(grpc_chttp2_transport_global *global,
470 grpc_chttp2_transport_parsing *parsing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700471
472/** Get a writable stream
Craig Tillerab630732015-06-25 11:20:01 -0700473 returns non-zero if there was a stream available */
Craig Tiller4aa71a12015-06-15 13:00:55 -0700474void grpc_chttp2_list_add_writable_stream(
475 grpc_chttp2_transport_global *transport_global,
476 grpc_chttp2_stream_global *stream_global);
477int grpc_chttp2_list_pop_writable_stream(
478 grpc_chttp2_transport_global *transport_global,
479 grpc_chttp2_transport_writing *transport_writing,
480 grpc_chttp2_stream_global **stream_global,
481 grpc_chttp2_stream_writing **stream_writing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700482
Craig Tillercf1e3192015-06-16 14:28:22 -0700483void grpc_chttp2_list_add_incoming_window_updated(
484 grpc_chttp2_transport_global *transport_global,
485 grpc_chttp2_stream_global *stream_global);
486int grpc_chttp2_list_pop_incoming_window_updated(
487 grpc_chttp2_transport_global *transport_global,
488 grpc_chttp2_transport_parsing *transport_parsing,
489 grpc_chttp2_stream_global **stream_global,
490 grpc_chttp2_stream_parsing **stream_parsing);
Craig Tiller759eb322015-06-16 22:41:18 -0700491void grpc_chttp2_list_remove_incoming_window_updated(
492 grpc_chttp2_transport_global *transport_global,
493 grpc_chttp2_stream_global *stream_global);
Craig Tillercf1e3192015-06-16 14:28:22 -0700494
Craig Tiller4aa71a12015-06-15 13:00:55 -0700495void grpc_chttp2_list_add_writing_stream(
496 grpc_chttp2_transport_writing *transport_writing,
497 grpc_chttp2_stream_writing *stream_writing);
498int grpc_chttp2_list_have_writing_streams(
499 grpc_chttp2_transport_writing *transport_writing);
500int grpc_chttp2_list_pop_writing_stream(
501 grpc_chttp2_transport_writing *transport_writing,
502 grpc_chttp2_stream_writing **stream_writing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700503
Craig Tiller4aa71a12015-06-15 13:00:55 -0700504void grpc_chttp2_list_add_written_stream(
505 grpc_chttp2_transport_writing *transport_writing,
506 grpc_chttp2_stream_writing *stream_writing);
507int grpc_chttp2_list_pop_written_stream(
508 grpc_chttp2_transport_global *transport_global,
509 grpc_chttp2_transport_writing *transport_writing,
510 grpc_chttp2_stream_global **stream_global,
511 grpc_chttp2_stream_writing **stream_writing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700512
Craig Tiller4aa71a12015-06-15 13:00:55 -0700513void grpc_chttp2_list_add_writable_window_update_stream(
514 grpc_chttp2_transport_global *transport_global,
515 grpc_chttp2_stream_global *stream_global);
516int grpc_chttp2_list_pop_writable_window_update_stream(
517 grpc_chttp2_transport_global *transport_global,
Craig Tiller86316522015-07-15 11:35:07 -0700518 grpc_chttp2_transport_writing *transport_writing,
519 grpc_chttp2_stream_global **stream_global,
520 grpc_chttp2_stream_writing **stream_writing);
Craig Tillerb951df12015-06-18 15:46:58 -0700521void grpc_chttp2_list_remove_writable_window_update_stream(
522 grpc_chttp2_transport_global *transport_global,
523 grpc_chttp2_stream_global *stream_global);
Craig Tillerd20efd22015-06-12 16:17:09 -0700524
Craig Tiller4aa71a12015-06-15 13:00:55 -0700525void grpc_chttp2_list_add_parsing_seen_stream(
526 grpc_chttp2_transport_parsing *transport_parsing,
527 grpc_chttp2_stream_parsing *stream_parsing);
528int grpc_chttp2_list_pop_parsing_seen_stream(
529 grpc_chttp2_transport_global *transport_global,
530 grpc_chttp2_transport_parsing *transport_parsing,
531 grpc_chttp2_stream_global **stream_global,
532 grpc_chttp2_stream_parsing **stream_parsing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700533
Craig Tiller5dc3b302015-06-15 16:06:50 -0700534void grpc_chttp2_list_add_waiting_for_concurrency(
535 grpc_chttp2_transport_global *transport_global,
536 grpc_chttp2_stream_global *stream_global);
537int grpc_chttp2_list_pop_waiting_for_concurrency(
538 grpc_chttp2_transport_global *transport_global,
539 grpc_chttp2_stream_global **stream_global);
540
Craig Tiller83fb0702015-06-16 21:13:07 -0700541void grpc_chttp2_list_add_closed_waiting_for_parsing(
Craig Tiller5dc3b302015-06-15 16:06:50 -0700542 grpc_chttp2_transport_global *transport_global,
543 grpc_chttp2_stream_global *stream_global);
Craig Tiller83fb0702015-06-16 21:13:07 -0700544int grpc_chttp2_list_pop_closed_waiting_for_parsing(
Craig Tiller5dc3b302015-06-15 16:06:50 -0700545 grpc_chttp2_transport_global *transport_global,
546 grpc_chttp2_stream_global **stream_global);
547
Craig Tiller17be5dc2015-07-01 10:36:27 -0700548void grpc_chttp2_list_add_cancelled_waiting_for_writing(
549 grpc_chttp2_transport_global *transport_global,
550 grpc_chttp2_stream_global *stream_global);
551int grpc_chttp2_list_pop_cancelled_waiting_for_writing(
552 grpc_chttp2_transport_global *transport_global,
553 grpc_chttp2_stream_global **stream_global);
554
Craig Tiller6459db42015-06-15 17:11:45 -0700555void grpc_chttp2_list_add_read_write_state_changed(
556 grpc_chttp2_transport_global *transport_global,
557 grpc_chttp2_stream_global *stream_global);
Craig Tillerf73fcd12015-06-16 16:25:26 -0700558int grpc_chttp2_list_pop_read_write_state_changed(
559 grpc_chttp2_transport_global *transport_global,
560 grpc_chttp2_stream_global **stream_global);
Craig Tiller6459db42015-06-15 17:11:45 -0700561
Craig Tiller1937b062015-06-16 08:47:38 -0700562/** schedule a closure to run without the transport lock taken */
Craig Tiller4aa71a12015-06-15 13:00:55 -0700563void grpc_chttp2_schedule_closure(
564 grpc_chttp2_transport_global *transport_global, grpc_iomgr_closure *closure,
565 int success);
Craig Tillerd20efd22015-06-12 16:17:09 -0700566
Craig Tiller4aa71a12015-06-15 13:00:55 -0700567grpc_chttp2_stream_parsing *grpc_chttp2_parsing_lookup_stream(
568 grpc_chttp2_transport_parsing *transport_parsing, gpr_uint32 id);
569grpc_chttp2_stream_parsing *grpc_chttp2_parsing_accept_stream(
570 grpc_chttp2_transport_parsing *transport_parsing, gpr_uint32 id);
Craig Tillerd20efd22015-06-12 16:17:09 -0700571
Craig Tiller98505102015-06-16 11:33:15 -0700572void grpc_chttp2_add_incoming_goaway(
573 grpc_chttp2_transport_global *transport_global, gpr_uint32 goaway_error,
574 gpr_slice goaway_text);
Craig Tiller4aa71a12015-06-15 13:00:55 -0700575
Craig Tiller98505102015-06-16 11:33:15 -0700576void grpc_chttp2_register_stream(grpc_chttp2_transport *t,
577 grpc_chttp2_stream *s);
Craig Tiller9188d7a2015-07-05 12:44:37 -0700578/* returns 1 if this is the last stream, 0 otherwise */
579int grpc_chttp2_unregister_stream(grpc_chttp2_transport *t,
580 grpc_chttp2_stream *s) GRPC_MUST_USE_RESULT;
581int grpc_chttp2_has_streams(grpc_chttp2_transport *t);
Craig Tiller98505102015-06-16 11:33:15 -0700582void grpc_chttp2_for_all_streams(
583 grpc_chttp2_transport_global *transport_global, void *user_data,
584 void (*cb)(grpc_chttp2_transport_global *transport_global, void *user_data,
585 grpc_chttp2_stream_global *stream_global));
Craig Tiller5dc3b302015-06-15 16:06:50 -0700586
Craig Tiller285b8822015-06-17 15:58:13 -0700587void grpc_chttp2_parsing_become_skip_parser(
588 grpc_chttp2_transport_parsing *transport_parsing);
Craig Tiller66abdaa2015-06-17 08:00:39 -0700589
Craig Tillerd20efd22015-06-12 16:17:09 -0700590#define GRPC_CHTTP2_CLIENT_CONNECT_STRING "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
Craig Tiller4aa71a12015-06-15 13:00:55 -0700591#define GRPC_CHTTP2_CLIENT_CONNECT_STRLEN \
592 (sizeof(GRPC_CHTTP2_CLIENT_CONNECT_STRING) - 1)
Craig Tillerd20efd22015-06-12 16:17:09 -0700593
594extern int grpc_http_trace;
Craig Tiller285b8822015-06-17 15:58:13 -0700595extern int grpc_flowctl_trace;
Craig Tillerd20efd22015-06-12 16:17:09 -0700596
Craig Tillerab630732015-06-25 11:20:01 -0700597#define GRPC_CHTTP2_IF_TRACING(stmt) \
598 if (!(grpc_http_trace)) \
599 ; \
600 else \
Craig Tillerd20efd22015-06-12 16:17:09 -0700601 stmt
Craig Tiller3208e392015-06-12 08:17:02 -0700602
Craig Tiller285b8822015-06-17 15:58:13 -0700603#define GRPC_CHTTP2_FLOWCTL_TRACE_STREAM(reason, transport, context, var, \
604 delta) \
605 if (!(grpc_flowctl_trace)) { \
606 } else { \
607 grpc_chttp2_flowctl_trace(__FILE__, __LINE__, reason, #context, #var, \
608 transport->is_client, context->id, context->var, \
609 delta); \
610 }
611
612#define GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT(reason, context, var, delta) \
613 if (!(grpc_flowctl_trace)) { \
614 } else { \
615 grpc_chttp2_flowctl_trace(__FILE__, __LINE__, reason, #context, #var, \
616 context->is_client, 0, context->var, delta); \
617 }
618
619void grpc_chttp2_flowctl_trace(const char *file, int line, const char *reason,
620 const char *context, const char *var,
621 int is_client, gpr_uint32 stream_id,
622 gpr_int64 current_value, gpr_int64 delta);
623
Craig Tiller9b8671c2015-06-12 07:41:54 -0700624#endif