blob: a1b773b1cad73283eb946a86e00db936a224ad45 [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,
Craig Tiller6459db42015-06-15 17:11:45 -070063 GRPC_CHTTP2_LIST_PARSING_SEEN,
Craig Tiller83fb0702015-06-16 21:13:07 -070064 GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_PARSING,
Craig Tiller17be5dc2015-07-01 10:36:27 -070065 GRPC_CHTTP2_LIST_CANCELLED_WAITING_FOR_WRITING,
Craig Tillercf1e3192015-06-16 14:28:22 -070066 GRPC_CHTTP2_LIST_INCOMING_WINDOW_UPDATED,
Craig Tiller5dc3b302015-06-15 16:06:50 -070067 /** streams that are waiting to start because there are too many concurrent
68 streams on the connection */
69 GRPC_CHTTP2_LIST_WAITING_FOR_CONCURRENCY,
Craig Tiller9b8671c2015-06-12 07:41:54 -070070 STREAM_LIST_COUNT /* must be last */
Craig Tillerb084d902015-06-12 07:50:02 -070071} grpc_chttp2_stream_list_id;
Craig Tiller9b8671c2015-06-12 07:41:54 -070072
73/* deframer state for the overall http2 stream of bytes */
74typedef enum {
75 /* prefix: one entry per http2 connection prefix byte */
Craig Tillerab630732015-06-25 11:20:01 -070076 GRPC_DTS_CLIENT_PREFIX_0 = 0,
77 GRPC_DTS_CLIENT_PREFIX_1,
78 GRPC_DTS_CLIENT_PREFIX_2,
79 GRPC_DTS_CLIENT_PREFIX_3,
80 GRPC_DTS_CLIENT_PREFIX_4,
81 GRPC_DTS_CLIENT_PREFIX_5,
82 GRPC_DTS_CLIENT_PREFIX_6,
83 GRPC_DTS_CLIENT_PREFIX_7,
84 GRPC_DTS_CLIENT_PREFIX_8,
85 GRPC_DTS_CLIENT_PREFIX_9,
86 GRPC_DTS_CLIENT_PREFIX_10,
87 GRPC_DTS_CLIENT_PREFIX_11,
88 GRPC_DTS_CLIENT_PREFIX_12,
89 GRPC_DTS_CLIENT_PREFIX_13,
90 GRPC_DTS_CLIENT_PREFIX_14,
91 GRPC_DTS_CLIENT_PREFIX_15,
92 GRPC_DTS_CLIENT_PREFIX_16,
93 GRPC_DTS_CLIENT_PREFIX_17,
94 GRPC_DTS_CLIENT_PREFIX_18,
95 GRPC_DTS_CLIENT_PREFIX_19,
96 GRPC_DTS_CLIENT_PREFIX_20,
97 GRPC_DTS_CLIENT_PREFIX_21,
98 GRPC_DTS_CLIENT_PREFIX_22,
99 GRPC_DTS_CLIENT_PREFIX_23,
Craig Tiller9b8671c2015-06-12 07:41:54 -0700100 /* frame header byte 0... */
101 /* must follow from the prefix states */
Craig Tillerab630732015-06-25 11:20:01 -0700102 GRPC_DTS_FH_0,
103 GRPC_DTS_FH_1,
104 GRPC_DTS_FH_2,
105 GRPC_DTS_FH_3,
106 GRPC_DTS_FH_4,
107 GRPC_DTS_FH_5,
108 GRPC_DTS_FH_6,
109 GRPC_DTS_FH_7,
Craig Tiller9b8671c2015-06-12 07:41:54 -0700110 /* ... frame header byte 8 */
Craig Tillerab630732015-06-25 11:20:01 -0700111 GRPC_DTS_FH_8,
Craig Tiller9b8671c2015-06-12 07:41:54 -0700112 /* inside a http2 frame */
Craig Tillerab630732015-06-25 11:20:01 -0700113 GRPC_DTS_FRAME
Craig Tillerb084d902015-06-12 07:50:02 -0700114} grpc_chttp2_deframe_transport_state;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700115
116typedef enum {
Craig Tillerab630732015-06-25 11:20:01 -0700117 GRPC_WRITE_STATE_OPEN,
118 GRPC_WRITE_STATE_QUEUED_CLOSE,
119 GRPC_WRITE_STATE_SENT_CLOSE
Craig Tillerb084d902015-06-12 07:50:02 -0700120} grpc_chttp2_write_state;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700121
Craig Tiller0c23f292015-08-03 10:18:05 -0700122/* flags that can be or'd into stream_global::writing_now */
123#define GRPC_CHTTP2_WRITING_DATA 1
124#define GRPC_CHTTP2_WRITING_WINDOW 2
125
Craig Tiller9b8671c2015-06-12 07:41:54 -0700126typedef enum {
Craig Tillerab630732015-06-25 11:20:01 -0700127 GRPC_DONT_SEND_CLOSED = 0,
128 GRPC_SEND_CLOSED,
129 GRPC_SEND_CLOSED_WITH_RST_STREAM
Craig Tillerb084d902015-06-12 07:50:02 -0700130} grpc_chttp2_send_closed;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700131
132typedef struct {
Craig Tillerb084d902015-06-12 07:50:02 -0700133 grpc_chttp2_stream *head;
134 grpc_chttp2_stream *tail;
135} grpc_chttp2_stream_list;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700136
137typedef struct {
Craig Tillerb084d902015-06-12 07:50:02 -0700138 grpc_chttp2_stream *next;
139 grpc_chttp2_stream *prev;
140} grpc_chttp2_stream_link;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700141
Craig Tiller9b8671c2015-06-12 07:41:54 -0700142/* We keep several sets of connection wide parameters */
143typedef enum {
144 /* The settings our peer has asked for (and we have acked) */
Craig Tillerab630732015-06-25 11:20:01 -0700145 GRPC_PEER_SETTINGS = 0,
Craig Tiller9b8671c2015-06-12 07:41:54 -0700146 /* The settings we'd like to have */
Craig Tillerab630732015-06-25 11:20:01 -0700147 GRPC_LOCAL_SETTINGS,
Craig Tiller9b8671c2015-06-12 07:41:54 -0700148 /* The settings we've published to our peer */
Craig Tillerab630732015-06-25 11:20:01 -0700149 GRPC_SENT_SETTINGS,
Craig Tiller9b8671c2015-06-12 07:41:54 -0700150 /* The settings the peer has acked */
Craig Tillerab630732015-06-25 11:20:01 -0700151 GRPC_ACKED_SETTINGS,
152 GRPC_NUM_SETTING_SETS
Craig Tillerb084d902015-06-12 07:50:02 -0700153} grpc_chttp2_setting_set;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700154
155/* Outstanding ping request data */
Craig Tiller3719f072015-06-12 17:19:51 -0700156typedef struct grpc_chttp2_outstanding_ping {
Craig Tiller9b8671c2015-06-12 07:41:54 -0700157 gpr_uint8 id[8];
Craig Tiller3719f072015-06-12 17:19:51 -0700158 grpc_iomgr_closure *on_recv;
159 struct grpc_chttp2_outstanding_ping *next;
160 struct grpc_chttp2_outstanding_ping *prev;
Craig Tillerb084d902015-06-12 07:50:02 -0700161} grpc_chttp2_outstanding_ping;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700162
163typedef struct {
Craig Tillerd20efd22015-06-12 16:17:09 -0700164 /** data to write next write */
165 gpr_slice_buffer qbuf;
166 /** queued callbacks */
Craig Tillerff3ae682015-06-29 17:44:04 -0700167 grpc_iomgr_closure *pending_closures_head;
168 grpc_iomgr_closure *pending_closures_tail;
Craig Tillerd20efd22015-06-12 16:17:09 -0700169
170 /** window available for us to send to peer */
171 gpr_uint32 outgoing_window;
Craig Tiller3719f072015-06-12 17:19:51 -0700172 /** window available for peer to send to us - updated after parse */
173 gpr_uint32 incoming_window;
Craig Tillerd20efd22015-06-12 16:17:09 -0700174 /** how much window would we like to have for incoming_window */
175 gpr_uint32 connection_window_target;
176
Craig Tiller1064f8b2015-06-25 13:52:57 -0700177 /** have we seen a goaway */
178 gpr_uint8 seen_goaway;
Craig Tiller9188d7a2015-07-05 12:44:37 -0700179 /** have we sent a goaway */
180 gpr_uint8 sent_goaway;
Craig Tiller1064f8b2015-06-25 13:52:57 -0700181
Craig Tiller3719f072015-06-12 17:19:51 -0700182 /** is this transport a client? */
183 gpr_uint8 is_client;
Craig Tillerd20efd22015-06-12 16:17:09 -0700184 /** are the local settings dirty and need to be sent? */
185 gpr_uint8 dirtied_local_settings;
186 /** have local settings been sent? */
187 gpr_uint8 sent_local_settings;
188 /** bitmask of setting indexes to send out */
Craig Tiller4aa71a12015-06-15 13:00:55 -0700189 gpr_uint32 force_send_settings;
Craig Tillerd20efd22015-06-12 16:17:09 -0700190 /** settings values */
Craig Tillerab630732015-06-25 11:20:01 -0700191 gpr_uint32 settings[GRPC_NUM_SETTING_SETS][GRPC_CHTTP2_NUM_SETTINGS];
Craig Tillerd20efd22015-06-12 16:17:09 -0700192
Craig Tiller606d8742015-06-15 06:58:50 -0700193 /** what is the next stream id to be allocated by this peer?
194 copied to next_stream_id in parsing when parsing commences */
195 gpr_uint32 next_stream_id;
196
Craig Tillerd20efd22015-06-12 16:17:09 -0700197 /** last received stream id */
198 gpr_uint32 last_incoming_stream_id;
Craig Tiller3719f072015-06-12 17:19:51 -0700199
200 /** pings awaiting responses */
201 grpc_chttp2_outstanding_ping pings;
Craig Tiller606d8742015-06-15 06:58:50 -0700202 /** next payload for an outgoing ping */
203 gpr_uint64 ping_counter;
204
205 /** concurrent stream count: updated when not parsing,
206 so this is a strict over-estimation on the client */
207 gpr_uint32 concurrent_stream_count;
Craig Tillerd20efd22015-06-12 16:17:09 -0700208} grpc_chttp2_transport_global;
209
210typedef struct {
211 /** data to write now */
212 gpr_slice_buffer outbuf;
213 /** hpack encoding */
214 grpc_chttp2_hpack_compressor hpack_compressor;
Craig Tiller285b8822015-06-17 15:58:13 -0700215 /** is this a client? */
216 gpr_uint8 is_client;
Craig Tillerb0298592015-08-27 07:38:01 -0700217 /** callback for when writing is done */
218 grpc_iomgr_closure done_cb;
Craig Tillerd20efd22015-06-12 16:17:09 -0700219} grpc_chttp2_transport_writing;
220
221struct grpc_chttp2_transport_parsing {
222 /** is this transport a client? (boolean) */
223 gpr_uint8 is_client;
224
225 /** were settings updated? */
226 gpr_uint8 settings_updated;
227 /** was a settings ack received? */
228 gpr_uint8 settings_ack_received;
229 /** was a goaway frame received? */
230 gpr_uint8 goaway_received;
231
Craig Tiller3719f072015-06-12 17:19:51 -0700232 /** initial window change */
233 gpr_int64 initial_window_update;
234
Craig Tillerd20efd22015-06-12 16:17:09 -0700235 /** data to write later - after parsing */
236 gpr_slice_buffer qbuf;
237 /* metadata object cache */
238 grpc_mdstr *str_grpc_timeout;
239 /** parser for headers */
240 grpc_chttp2_hpack_parser hpack_parser;
241 /** simple one shot parsers */
242 union {
243 grpc_chttp2_window_update_parser window_update;
244 grpc_chttp2_settings_parser settings;
245 grpc_chttp2_ping_parser ping;
246 grpc_chttp2_rst_stream_parser rst_stream;
247 } simple;
248 /** parser for goaway frames */
249 grpc_chttp2_goaway_parser goaway_parser;
250
251 /** window available for peer to send to us */
252 gpr_uint32 incoming_window;
Craig Tiller285b8822015-06-17 15:58:13 -0700253 gpr_uint32 incoming_window_delta;
Craig Tillerd20efd22015-06-12 16:17:09 -0700254
255 /** next stream id available at the time of beginning parsing */
256 gpr_uint32 next_stream_id;
257 gpr_uint32 last_incoming_stream_id;
258
259 /* deframing */
260 grpc_chttp2_deframe_transport_state deframe_state;
261 gpr_uint8 incoming_frame_type;
262 gpr_uint8 incoming_frame_flags;
263 gpr_uint8 header_eof;
264 gpr_uint32 expect_continuation_stream_id;
265 gpr_uint32 incoming_frame_size;
266 gpr_uint32 incoming_stream_id;
267
268 /* active parser */
269 void *parser_data;
270 grpc_chttp2_stream_parsing *incoming_stream;
Craig Tiller4aa71a12015-06-15 13:00:55 -0700271 grpc_chttp2_parse_error (*parser)(
272 void *parser_user_data, grpc_chttp2_transport_parsing *transport_parsing,
273 grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
Craig Tillerd20efd22015-06-12 16:17:09 -0700274
275 /* received settings */
276 gpr_uint32 settings[GRPC_CHTTP2_NUM_SETTINGS];
277
278 /* goaway data */
279 grpc_status_code goaway_error;
280 gpr_uint32 goaway_last_stream_index;
281 gpr_slice goaway_text;
Craig Tiller3719f072015-06-12 17:19:51 -0700282
283 gpr_uint64 outgoing_window_update;
284
285 /** pings awaiting responses */
286 grpc_chttp2_outstanding_ping pings;
Craig Tillerd20efd22015-06-12 16:17:09 -0700287};
288
Craig Tillerb084d902015-06-12 07:50:02 -0700289struct grpc_chttp2_transport {
Craig Tiller9b8671c2015-06-12 07:41:54 -0700290 grpc_transport base; /* must be first */
291 grpc_endpoint *ep;
292 grpc_mdctx *metadata_context;
293 gpr_refcount refs;
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700294 char *peer_string;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700295
296 gpr_mu mu;
Craig Tiller606d8742015-06-15 06:58:50 -0700297
298 /** is the transport destroying itself? */
299 gpr_uint8 destroying;
300 /** has the upper layer closed the transport? */
301 gpr_uint8 closed;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700302
Craig Tillerd20efd22015-06-12 16:17:09 -0700303 /** is a thread currently writing */
304 gpr_uint8 writing_active;
Craig Tiller606d8742015-06-15 06:58:50 -0700305 /** is a thread currently parsing */
306 gpr_uint8 parsing_active;
Craig Tillerd20efd22015-06-12 16:17:09 -0700307
Craig Tiller606d8742015-06-15 06:58:50 -0700308 /** is there a read request to the endpoint outstanding? */
309 gpr_uint8 endpoint_reading;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700310
Craig Tiller606d8742015-06-15 06:58:50 -0700311 /** various lists of streams */
Craig Tillerb084d902015-06-12 07:50:02 -0700312 grpc_chttp2_stream_list lists[STREAM_LIST_COUNT];
Craig Tiller9b8671c2015-06-12 07:41:54 -0700313
Craig Tiller606d8742015-06-15 06:58:50 -0700314 /** global state for reading/writing */
Craig Tillerd20efd22015-06-12 16:17:09 -0700315 grpc_chttp2_transport_global global;
Craig Tiller606d8742015-06-15 06:58:50 -0700316 /** state only accessible by the chain of execution that
317 set writing_active=1 */
Craig Tillerd20efd22015-06-12 16:17:09 -0700318 grpc_chttp2_transport_writing writing;
Craig Tiller606d8742015-06-15 06:58:50 -0700319 /** state only accessible by the chain of execution that
320 set parsing_active=1 */
Craig Tillerd20efd22015-06-12 16:17:09 -0700321 grpc_chttp2_transport_parsing parsing;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700322
Craig Tiller606d8742015-06-15 06:58:50 -0700323 /** maps stream id to grpc_chttp2_stream objects;
324 owned by the parsing thread when parsing */
325 grpc_chttp2_stream_map parsing_stream_map;
326
327 /** streams created by the client (possibly during parsing);
328 merged with parsing_stream_map during unlock when no
329 parsing is occurring */
330 grpc_chttp2_stream_map new_stream_map;
331
Craig Tillerd20efd22015-06-12 16:17:09 -0700332 /** closure to execute writing */
333 grpc_iomgr_closure writing_action;
Craig Tillerb0298592015-08-27 07:38:01 -0700334 /** closure to finish reading from the endpoint */
335 grpc_iomgr_closure recv_data;
336
337 /** incoming read bytes */
338 gpr_slice_buffer read_buffer;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700339
Craig Tiller4aa71a12015-06-15 13:00:55 -0700340 /** address to place a newly accepted stream - set and unset by
Craig Tiller606d8742015-06-15 06:58:50 -0700341 grpc_chttp2_parsing_accept_stream; used by init_stream to
342 publish the accepted server stream */
343 grpc_chttp2_stream **accepting_stream;
344
Craig Tiller9b8671c2015-06-12 07:41:54 -0700345 struct {
Craig Tiller1064f8b2015-06-25 13:52:57 -0700346 /* accept stream callback */
347 void (*accept_stream)(void *user_data, grpc_transport *transport,
348 const void *server_data);
349 void *accept_stream_user_data;
350
351 /** connectivity tracking */
Craig Tiller08a1cf82015-06-29 09:37:52 -0700352 grpc_connectivity_state_tracker state_tracker;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700353 } channel_callback;
354};
355
Craig Tillerd20efd22015-06-12 16:17:09 -0700356typedef struct {
357 /** HTTP2 stream id for this stream, or zero if one has not been assigned */
Craig Tiller9b8671c2015-06-12 07:41:54 -0700358 gpr_uint32 id;
359
Craig Tillerd20efd22015-06-12 16:17:09 -0700360 grpc_iomgr_closure *send_done_closure;
361 grpc_iomgr_closure *recv_done_closure;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700362
Craig Tillerd20efd22015-06-12 16:17:09 -0700363 /** window available for us to send to peer */
364 gpr_int64 outgoing_window;
Craig Tiller27166a62015-07-05 21:08:33 -0700365 /** The number of bytes the upper layers have offered to receive.
366 As the upper layer offers more bytes, this value increases.
367 As bytes are read, this value decreases. */
368 gpr_uint32 max_recv_bytes;
369 /** The number of bytes the upper layer has offered to read but we have
370 not yet announced to HTTP2 flow control.
371 As the upper layers offer to read more bytes, this value increases.
372 As we advertise incoming flow control window, this value decreases. */
373 gpr_uint32 unannounced_incoming_window;
374 /** The number of bytes of HTTP2 flow control we have advertised.
375 As we advertise incoming flow control window, this value increases.
376 As bytes are read, this value decreases.
377 Updated after parse. */
Craig Tiller3719f072015-06-12 17:19:51 -0700378 gpr_uint32 incoming_window;
Craig Tillerd20efd22015-06-12 16:17:09 -0700379 /** stream ops the transport user would like to send */
380 grpc_stream_op_buffer *outgoing_sopb;
381 /** when the application requests writes be closed, the write_closed is
382 'queued'; when the close is flow controlled into the send path, we are
383 'sending' it; when the write has been performed it is 'sent' */
384 grpc_chttp2_write_state write_state;
385 /** is this stream closed (boolean) */
386 gpr_uint8 read_closed;
Craig Tiller5dc3b302015-06-15 16:06:50 -0700387 /** has this stream been cancelled? (boolean) */
388 gpr_uint8 cancelled;
Craig Tillercec9eb92015-06-17 17:16:48 -0700389 grpc_status_code cancelled_status;
390 /** have we told the upper layer that this stream is cancelled? */
391 gpr_uint8 published_cancelled;
Craig Tiller5dc3b302015-06-15 16:06:50 -0700392 /** is this stream in the stream map? (boolean) */
393 gpr_uint8 in_stream_map;
Craig Tiller0c23f292015-08-03 10:18:05 -0700394 /** bitmask of GRPC_CHTTP2_WRITING_xxx above */
Craig Tiller994c2622015-07-23 14:00:58 -0700395 gpr_uint8 writing_now;
Craig Tiller45ce9272015-07-31 11:22:35 -0700396 /** has anything been written to this stream? */
397 gpr_uint8 written_anything;
Craig Tiller606d8742015-06-15 06:58:50 -0700398
399 /** stream state already published to the upper layer */
400 grpc_stream_state published_state;
401 /** address to publish next stream state to */
402 grpc_stream_state *publish_state;
403 /** pointer to sop buffer to fill in with new stream ops */
Craig Tiller6905b7c2015-06-16 15:33:33 -0700404 grpc_stream_op_buffer *publish_sopb;
405 grpc_stream_op_buffer incoming_sopb;
Craig Tiller5dc3b302015-06-15 16:06:50 -0700406
407 /** incoming metadata */
408 grpc_chttp2_incoming_metadata_buffer incoming_metadata;
Craig Tillerb787c502015-06-15 16:14:52 -0700409 grpc_chttp2_incoming_metadata_live_op_buffer outstanding_metadata;
Craig Tillerd20efd22015-06-12 16:17:09 -0700410} grpc_chttp2_stream_global;
411
412typedef struct {
413 /** HTTP2 stream id for this stream, or zero if one has not been assigned */
414 gpr_uint32 id;
415 /** sops that have passed flow control to be written */
416 grpc_stream_op_buffer sopb;
417 /** how strongly should we indicate closure with the next write */
418 grpc_chttp2_send_closed send_closed;
Craig Tiller86316522015-07-15 11:35:07 -0700419 /** how much window should we announce? */
420 gpr_uint32 announce_window;
Craig Tillerd20efd22015-06-12 16:17:09 -0700421} grpc_chttp2_stream_writing;
422
423struct grpc_chttp2_stream_parsing {
424 /** HTTP2 stream id for this stream, or zero if one has not been assigned */
425 gpr_uint32 id;
426 /** has this stream received a close */
427 gpr_uint8 received_close;
Craig Tiller3719f072015-06-12 17:19:51 -0700428 /** saw a rst_stream */
429 gpr_uint8 saw_rst_stream;
Craig Tiller606d8742015-06-15 06:58:50 -0700430 /** incoming_window has been reduced by this much during parsing */
431 gpr_uint32 incoming_window_delta;
Craig Tillerd20efd22015-06-12 16:17:09 -0700432 /** window available for peer to send to us */
433 gpr_uint32 incoming_window;
434 /** parsing state for data frames */
435 grpc_chttp2_data_parser data_parser;
Craig Tiller3719f072015-06-12 17:19:51 -0700436 /** reason give to rst_stream */
437 gpr_uint32 rst_stream_reason;
438 /* amount of window given */
439 gpr_uint64 outgoing_window_update;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700440
Craig Tiller5dc3b302015-06-15 16:06:50 -0700441 /** incoming metadata */
442 grpc_chttp2_incoming_metadata_buffer incoming_metadata;
Craig Tillerd20efd22015-06-12 16:17:09 -0700443};
444
445struct grpc_chttp2_stream {
446 grpc_chttp2_stream_global global;
447 grpc_chttp2_stream_writing writing;
Craig Tiller606d8742015-06-15 06:58:50 -0700448 grpc_chttp2_stream_parsing parsing;
Craig Tillerd20efd22015-06-12 16:17:09 -0700449
450 grpc_chttp2_stream_link links[STREAM_LIST_COUNT];
451 gpr_uint8 included[STREAM_LIST_COUNT];
Craig Tiller9b8671c2015-06-12 07:41:54 -0700452};
453
Craig Tillerd20efd22015-06-12 16:17:09 -0700454/** Transport writing call flow:
Craig Tiller4aa71a12015-06-15 13:00:55 -0700455 chttp2_transport.c calls grpc_chttp2_unlocking_check_writes to see if writes
456 are required;
457 if they are, chttp2_transport.c calls grpc_chttp2_perform_writes to do the
458 writes.
459 Once writes have been completed (meaning another write could potentially be
460 started),
461 grpc_chttp2_terminate_writing is called. This will call
462 grpc_chttp2_cleanup_writing, at which
Craig Tillerd20efd22015-06-12 16:17:09 -0700463 point the write phase is complete. */
464
Craig Tiller3208e392015-06-12 08:17:02 -0700465/** Someone is unlocking the transport mutex: check to see if writes
466 are required, and schedule them if so */
Craig Tiller4aa71a12015-06-15 13:00:55 -0700467int grpc_chttp2_unlocking_check_writes(grpc_chttp2_transport_global *global,
468 grpc_chttp2_transport_writing *writing);
469void grpc_chttp2_perform_writes(
470 grpc_chttp2_transport_writing *transport_writing, grpc_endpoint *endpoint);
Craig Tillerb0298592015-08-27 07:38:01 -0700471void grpc_chttp2_terminate_writing(void *transport_writing, int success);
Craig Tiller4aa71a12015-06-15 13:00:55 -0700472void grpc_chttp2_cleanup_writing(grpc_chttp2_transport_global *global,
473 grpc_chttp2_transport_writing *writing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700474
Craig Tiller4aa71a12015-06-15 13:00:55 -0700475void grpc_chttp2_prepare_to_read(grpc_chttp2_transport_global *global,
476 grpc_chttp2_transport_parsing *parsing);
Craig Tillerab630732015-06-25 11:20:01 -0700477/** Process one slice of incoming data; return 1 if the connection is still
478 viable after reading, or 0 if the connection should be torn down */
Craig Tiller4aa71a12015-06-15 13:00:55 -0700479int grpc_chttp2_perform_read(grpc_chttp2_transport_parsing *transport_parsing,
480 gpr_slice slice);
481void grpc_chttp2_publish_reads(grpc_chttp2_transport_global *global,
482 grpc_chttp2_transport_parsing *parsing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700483
484/** Get a writable stream
Craig Tillerab630732015-06-25 11:20:01 -0700485 returns non-zero if there was a stream available */
Craig Tiller4aa71a12015-06-15 13:00:55 -0700486void grpc_chttp2_list_add_writable_stream(
487 grpc_chttp2_transport_global *transport_global,
488 grpc_chttp2_stream_global *stream_global);
Craig Tiller994c2622015-07-23 14:00:58 -0700489void grpc_chttp2_list_add_first_writable_stream(
490 grpc_chttp2_transport_global *transport_global,
491 grpc_chttp2_stream_global *stream_global);
Craig Tiller4aa71a12015-06-15 13:00:55 -0700492int grpc_chttp2_list_pop_writable_stream(
493 grpc_chttp2_transport_global *transport_global,
494 grpc_chttp2_transport_writing *transport_writing,
495 grpc_chttp2_stream_global **stream_global,
496 grpc_chttp2_stream_writing **stream_writing);
Craig Tiller994c2622015-07-23 14:00:58 -0700497void grpc_chttp2_list_remove_writable_stream(
498 grpc_chttp2_transport_global *transport_global,
499 grpc_chttp2_stream_global *stream_global);
Craig Tillerd20efd22015-06-12 16:17:09 -0700500
Craig Tillercf1e3192015-06-16 14:28:22 -0700501void grpc_chttp2_list_add_incoming_window_updated(
502 grpc_chttp2_transport_global *transport_global,
503 grpc_chttp2_stream_global *stream_global);
504int grpc_chttp2_list_pop_incoming_window_updated(
505 grpc_chttp2_transport_global *transport_global,
506 grpc_chttp2_transport_parsing *transport_parsing,
507 grpc_chttp2_stream_global **stream_global,
508 grpc_chttp2_stream_parsing **stream_parsing);
Craig Tiller759eb322015-06-16 22:41:18 -0700509void grpc_chttp2_list_remove_incoming_window_updated(
510 grpc_chttp2_transport_global *transport_global,
511 grpc_chttp2_stream_global *stream_global);
Craig Tillercf1e3192015-06-16 14:28:22 -0700512
Craig Tiller4aa71a12015-06-15 13:00:55 -0700513void grpc_chttp2_list_add_writing_stream(
514 grpc_chttp2_transport_writing *transport_writing,
515 grpc_chttp2_stream_writing *stream_writing);
516int grpc_chttp2_list_have_writing_streams(
517 grpc_chttp2_transport_writing *transport_writing);
518int grpc_chttp2_list_pop_writing_stream(
519 grpc_chttp2_transport_writing *transport_writing,
520 grpc_chttp2_stream_writing **stream_writing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700521
Craig Tiller4aa71a12015-06-15 13:00:55 -0700522void grpc_chttp2_list_add_written_stream(
523 grpc_chttp2_transport_writing *transport_writing,
524 grpc_chttp2_stream_writing *stream_writing);
525int grpc_chttp2_list_pop_written_stream(
526 grpc_chttp2_transport_global *transport_global,
527 grpc_chttp2_transport_writing *transport_writing,
528 grpc_chttp2_stream_global **stream_global,
529 grpc_chttp2_stream_writing **stream_writing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700530
Craig Tiller4aa71a12015-06-15 13:00:55 -0700531void grpc_chttp2_list_add_parsing_seen_stream(
532 grpc_chttp2_transport_parsing *transport_parsing,
533 grpc_chttp2_stream_parsing *stream_parsing);
534int grpc_chttp2_list_pop_parsing_seen_stream(
535 grpc_chttp2_transport_global *transport_global,
536 grpc_chttp2_transport_parsing *transport_parsing,
537 grpc_chttp2_stream_global **stream_global,
538 grpc_chttp2_stream_parsing **stream_parsing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700539
Craig Tiller5dc3b302015-06-15 16:06:50 -0700540void grpc_chttp2_list_add_waiting_for_concurrency(
541 grpc_chttp2_transport_global *transport_global,
542 grpc_chttp2_stream_global *stream_global);
543int grpc_chttp2_list_pop_waiting_for_concurrency(
544 grpc_chttp2_transport_global *transport_global,
545 grpc_chttp2_stream_global **stream_global);
546
Craig Tiller83fb0702015-06-16 21:13:07 -0700547void grpc_chttp2_list_add_closed_waiting_for_parsing(
Craig Tiller5dc3b302015-06-15 16:06:50 -0700548 grpc_chttp2_transport_global *transport_global,
549 grpc_chttp2_stream_global *stream_global);
Craig Tiller83fb0702015-06-16 21:13:07 -0700550int grpc_chttp2_list_pop_closed_waiting_for_parsing(
Craig Tiller5dc3b302015-06-15 16:06:50 -0700551 grpc_chttp2_transport_global *transport_global,
552 grpc_chttp2_stream_global **stream_global);
553
Craig Tiller17be5dc2015-07-01 10:36:27 -0700554void grpc_chttp2_list_add_cancelled_waiting_for_writing(
555 grpc_chttp2_transport_global *transport_global,
556 grpc_chttp2_stream_global *stream_global);
557int grpc_chttp2_list_pop_cancelled_waiting_for_writing(
558 grpc_chttp2_transport_global *transport_global,
559 grpc_chttp2_stream_global **stream_global);
560
Craig Tiller6459db42015-06-15 17:11:45 -0700561void grpc_chttp2_list_add_read_write_state_changed(
562 grpc_chttp2_transport_global *transport_global,
563 grpc_chttp2_stream_global *stream_global);
Craig Tillerf73fcd12015-06-16 16:25:26 -0700564int grpc_chttp2_list_pop_read_write_state_changed(
565 grpc_chttp2_transport_global *transport_global,
566 grpc_chttp2_stream_global **stream_global);
Craig Tiller6459db42015-06-15 17:11:45 -0700567
Craig Tiller1937b062015-06-16 08:47:38 -0700568/** schedule a closure to run without the transport lock taken */
Craig Tiller4aa71a12015-06-15 13:00:55 -0700569void grpc_chttp2_schedule_closure(
570 grpc_chttp2_transport_global *transport_global, grpc_iomgr_closure *closure,
571 int success);
Craig Tillerd20efd22015-06-12 16:17:09 -0700572
Craig Tiller4aa71a12015-06-15 13:00:55 -0700573grpc_chttp2_stream_parsing *grpc_chttp2_parsing_lookup_stream(
574 grpc_chttp2_transport_parsing *transport_parsing, gpr_uint32 id);
575grpc_chttp2_stream_parsing *grpc_chttp2_parsing_accept_stream(
576 grpc_chttp2_transport_parsing *transport_parsing, gpr_uint32 id);
Craig Tillerd20efd22015-06-12 16:17:09 -0700577
Craig Tiller98505102015-06-16 11:33:15 -0700578void grpc_chttp2_add_incoming_goaway(
579 grpc_chttp2_transport_global *transport_global, gpr_uint32 goaway_error,
580 gpr_slice goaway_text);
Craig Tiller4aa71a12015-06-15 13:00:55 -0700581
Craig Tiller98505102015-06-16 11:33:15 -0700582void grpc_chttp2_register_stream(grpc_chttp2_transport *t,
583 grpc_chttp2_stream *s);
Craig Tiller9188d7a2015-07-05 12:44:37 -0700584/* returns 1 if this is the last stream, 0 otherwise */
585int grpc_chttp2_unregister_stream(grpc_chttp2_transport *t,
586 grpc_chttp2_stream *s) GRPC_MUST_USE_RESULT;
587int grpc_chttp2_has_streams(grpc_chttp2_transport *t);
Craig Tiller98505102015-06-16 11:33:15 -0700588void grpc_chttp2_for_all_streams(
589 grpc_chttp2_transport_global *transport_global, void *user_data,
590 void (*cb)(grpc_chttp2_transport_global *transport_global, void *user_data,
591 grpc_chttp2_stream_global *stream_global));
Craig Tiller5dc3b302015-06-15 16:06:50 -0700592
Craig Tiller285b8822015-06-17 15:58:13 -0700593void grpc_chttp2_parsing_become_skip_parser(
594 grpc_chttp2_transport_parsing *transport_parsing);
Craig Tiller66abdaa2015-06-17 08:00:39 -0700595
Craig Tillerd20efd22015-06-12 16:17:09 -0700596#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 -0700597#define GRPC_CHTTP2_CLIENT_CONNECT_STRLEN \
598 (sizeof(GRPC_CHTTP2_CLIENT_CONNECT_STRING) - 1)
Craig Tillerd20efd22015-06-12 16:17:09 -0700599
600extern int grpc_http_trace;
Craig Tiller285b8822015-06-17 15:58:13 -0700601extern int grpc_flowctl_trace;
Craig Tillerd20efd22015-06-12 16:17:09 -0700602
Craig Tillerab630732015-06-25 11:20:01 -0700603#define GRPC_CHTTP2_IF_TRACING(stmt) \
604 if (!(grpc_http_trace)) \
605 ; \
606 else \
Craig Tillerd20efd22015-06-12 16:17:09 -0700607 stmt
Craig Tiller3208e392015-06-12 08:17:02 -0700608
Craig Tiller285b8822015-06-17 15:58:13 -0700609#define GRPC_CHTTP2_FLOWCTL_TRACE_STREAM(reason, transport, context, var, \
610 delta) \
611 if (!(grpc_flowctl_trace)) { \
612 } else { \
613 grpc_chttp2_flowctl_trace(__FILE__, __LINE__, reason, #context, #var, \
614 transport->is_client, context->id, context->var, \
615 delta); \
616 }
617
618#define GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT(reason, context, var, delta) \
619 if (!(grpc_flowctl_trace)) { \
620 } else { \
621 grpc_chttp2_flowctl_trace(__FILE__, __LINE__, reason, #context, #var, \
622 context->is_client, 0, context->var, delta); \
623 }
624
625void grpc_chttp2_flowctl_trace(const char *file, int line, const char *reason,
626 const char *context, const char *var,
627 int is_client, gpr_uint32 stream_id,
628 gpr_int64 current_value, gpr_int64 delta);
629
Craig Tiller9b8671c2015-06-12 07:41:54 -0700630#endif