blob: 386f2dd315644906399b08fcf6c332f0d1a8cf05 [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 Tiller33825112015-09-18 07:44:19 -0700158 grpc_closure *on_recv;
Craig Tiller3719f072015-06-12 17:19:51 -0700159 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 Tiller33825112015-09-18 07:44:19 -0700167 grpc_call_list run_at_unlock;
Craig Tillerd20efd22015-06-12 16:17:09 -0700168
169 /** window available for us to send to peer */
Craig Tiller6a6b36c2015-09-10 16:00:22 -0700170 gpr_int64 outgoing_window;
Craig Tiller3719f072015-06-12 17:19:51 -0700171 /** window available for peer to send to us - updated after parse */
172 gpr_uint32 incoming_window;
Craig Tillerd20efd22015-06-12 16:17:09 -0700173 /** how much window would we like to have for incoming_window */
174 gpr_uint32 connection_window_target;
175
Craig Tiller1064f8b2015-06-25 13:52:57 -0700176 /** have we seen a goaway */
177 gpr_uint8 seen_goaway;
Craig Tiller9188d7a2015-07-05 12:44:37 -0700178 /** have we sent a goaway */
179 gpr_uint8 sent_goaway;
Craig Tiller1064f8b2015-06-25 13:52:57 -0700180
Craig Tiller3719f072015-06-12 17:19:51 -0700181 /** is this transport a client? */
182 gpr_uint8 is_client;
Craig Tillerd20efd22015-06-12 16:17:09 -0700183 /** are the local settings dirty and need to be sent? */
184 gpr_uint8 dirtied_local_settings;
185 /** have local settings been sent? */
186 gpr_uint8 sent_local_settings;
187 /** bitmask of setting indexes to send out */
Craig Tiller4aa71a12015-06-15 13:00:55 -0700188 gpr_uint32 force_send_settings;
Craig Tillerd20efd22015-06-12 16:17:09 -0700189 /** settings values */
Craig Tillerab630732015-06-25 11:20:01 -0700190 gpr_uint32 settings[GRPC_NUM_SETTING_SETS][GRPC_CHTTP2_NUM_SETTINGS];
Craig Tillerd20efd22015-06-12 16:17:09 -0700191
Craig Tiller606d8742015-06-15 06:58:50 -0700192 /** what is the next stream id to be allocated by this peer?
193 copied to next_stream_id in parsing when parsing commences */
194 gpr_uint32 next_stream_id;
195
Craig Tillerd20efd22015-06-12 16:17:09 -0700196 /** last received stream id */
197 gpr_uint32 last_incoming_stream_id;
Craig Tiller3719f072015-06-12 17:19:51 -0700198
199 /** pings awaiting responses */
200 grpc_chttp2_outstanding_ping pings;
Craig Tiller606d8742015-06-15 06:58:50 -0700201 /** next payload for an outgoing ping */
202 gpr_uint64 ping_counter;
203
204 /** concurrent stream count: updated when not parsing,
205 so this is a strict over-estimation on the client */
206 gpr_uint32 concurrent_stream_count;
Craig Tillerd20efd22015-06-12 16:17:09 -0700207} grpc_chttp2_transport_global;
208
209typedef struct {
210 /** data to write now */
211 gpr_slice_buffer outbuf;
212 /** hpack encoding */
213 grpc_chttp2_hpack_compressor hpack_compressor;
Craig Tiller285b8822015-06-17 15:58:13 -0700214 /** is this a client? */
215 gpr_uint8 is_client;
Craig Tillerb0298592015-08-27 07:38:01 -0700216 /** callback for when writing is done */
Craig Tiller33825112015-09-18 07:44:19 -0700217 grpc_closure done_cb;
Craig Tillerd20efd22015-06-12 16:17:09 -0700218} grpc_chttp2_transport_writing;
219
220struct grpc_chttp2_transport_parsing {
221 /** is this transport a client? (boolean) */
222 gpr_uint8 is_client;
223
224 /** were settings updated? */
225 gpr_uint8 settings_updated;
226 /** was a settings ack received? */
227 gpr_uint8 settings_ack_received;
228 /** was a goaway frame received? */
229 gpr_uint8 goaway_received;
230
Craig Tiller3719f072015-06-12 17:19:51 -0700231 /** initial window change */
232 gpr_int64 initial_window_update;
233
Craig Tillerd20efd22015-06-12 16:17:09 -0700234 /** data to write later - after parsing */
235 gpr_slice_buffer qbuf;
236 /* metadata object cache */
237 grpc_mdstr *str_grpc_timeout;
238 /** parser for headers */
239 grpc_chttp2_hpack_parser hpack_parser;
240 /** simple one shot parsers */
241 union {
242 grpc_chttp2_window_update_parser window_update;
243 grpc_chttp2_settings_parser settings;
244 grpc_chttp2_ping_parser ping;
245 grpc_chttp2_rst_stream_parser rst_stream;
246 } simple;
247 /** parser for goaway frames */
248 grpc_chttp2_goaway_parser goaway_parser;
249
250 /** window available for peer to send to us */
251 gpr_uint32 incoming_window;
Craig Tiller285b8822015-06-17 15:58:13 -0700252 gpr_uint32 incoming_window_delta;
Craig Tillerd20efd22015-06-12 16:17:09 -0700253
254 /** next stream id available at the time of beginning parsing */
255 gpr_uint32 next_stream_id;
256 gpr_uint32 last_incoming_stream_id;
257
258 /* deframing */
259 grpc_chttp2_deframe_transport_state deframe_state;
260 gpr_uint8 incoming_frame_type;
261 gpr_uint8 incoming_frame_flags;
262 gpr_uint8 header_eof;
263 gpr_uint32 expect_continuation_stream_id;
264 gpr_uint32 incoming_frame_size;
265 gpr_uint32 incoming_stream_id;
266
267 /* active parser */
268 void *parser_data;
269 grpc_chttp2_stream_parsing *incoming_stream;
Craig Tiller4aa71a12015-06-15 13:00:55 -0700270 grpc_chttp2_parse_error (*parser)(
271 void *parser_user_data, grpc_chttp2_transport_parsing *transport_parsing,
272 grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
Craig Tillerd20efd22015-06-12 16:17:09 -0700273
274 /* received settings */
275 gpr_uint32 settings[GRPC_CHTTP2_NUM_SETTINGS];
276
277 /* goaway data */
278 grpc_status_code goaway_error;
279 gpr_uint32 goaway_last_stream_index;
280 gpr_slice goaway_text;
Craig Tiller3719f072015-06-12 17:19:51 -0700281
Craig Tiller6a6b36c2015-09-10 16:00:22 -0700282 gpr_int64 outgoing_window_update;
Craig Tiller3719f072015-06-12 17:19:51 -0700283
284 /** pings awaiting responses */
285 grpc_chttp2_outstanding_ping pings;
Craig Tillerd20efd22015-06-12 16:17:09 -0700286};
287
Craig Tillerb084d902015-06-12 07:50:02 -0700288struct grpc_chttp2_transport {
Craig Tiller9b8671c2015-06-12 07:41:54 -0700289 grpc_transport base; /* must be first */
290 grpc_endpoint *ep;
291 grpc_mdctx *metadata_context;
292 gpr_refcount refs;
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700293 char *peer_string;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700294
Craig Tiller9f80fcf2015-08-28 08:22:48 -0700295 /** when this drops to zero it's safe to shutdown the endpoint */
296 gpr_refcount shutdown_ep_refs;
297
Craig Tiller9b8671c2015-06-12 07:41:54 -0700298 gpr_mu mu;
Craig Tiller606d8742015-06-15 06:58:50 -0700299
300 /** is the transport destroying itself? */
301 gpr_uint8 destroying;
302 /** has the upper layer closed the transport? */
303 gpr_uint8 closed;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700304
Craig Tillerd20efd22015-06-12 16:17:09 -0700305 /** is a thread currently writing */
306 gpr_uint8 writing_active;
Craig Tiller606d8742015-06-15 06:58:50 -0700307 /** is a thread currently parsing */
308 gpr_uint8 parsing_active;
Craig Tillerd20efd22015-06-12 16:17:09 -0700309
Craig Tiller606d8742015-06-15 06:58:50 -0700310 /** is there a read request to the endpoint outstanding? */
311 gpr_uint8 endpoint_reading;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700312
Craig Tiller606d8742015-06-15 06:58:50 -0700313 /** various lists of streams */
Craig Tillerb084d902015-06-12 07:50:02 -0700314 grpc_chttp2_stream_list lists[STREAM_LIST_COUNT];
Craig Tiller9b8671c2015-06-12 07:41:54 -0700315
Craig Tiller606d8742015-06-15 06:58:50 -0700316 /** global state for reading/writing */
Craig Tillerd20efd22015-06-12 16:17:09 -0700317 grpc_chttp2_transport_global global;
Craig Tiller606d8742015-06-15 06:58:50 -0700318 /** state only accessible by the chain of execution that
319 set writing_active=1 */
Craig Tillerd20efd22015-06-12 16:17:09 -0700320 grpc_chttp2_transport_writing writing;
Craig Tiller606d8742015-06-15 06:58:50 -0700321 /** state only accessible by the chain of execution that
322 set parsing_active=1 */
Craig Tillerd20efd22015-06-12 16:17:09 -0700323 grpc_chttp2_transport_parsing parsing;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700324
Craig Tiller606d8742015-06-15 06:58:50 -0700325 /** maps stream id to grpc_chttp2_stream objects;
326 owned by the parsing thread when parsing */
327 grpc_chttp2_stream_map parsing_stream_map;
328
329 /** streams created by the client (possibly during parsing);
330 merged with parsing_stream_map during unlock when no
331 parsing is occurring */
332 grpc_chttp2_stream_map new_stream_map;
333
Craig Tillerd20efd22015-06-12 16:17:09 -0700334 /** closure to execute writing */
Craig Tiller33825112015-09-18 07:44:19 -0700335 grpc_closure writing_action;
Craig Tillerb0298592015-08-27 07:38:01 -0700336 /** closure to finish reading from the endpoint */
Craig Tiller33825112015-09-18 07:44:19 -0700337 grpc_closure recv_data;
Craig Tillerb0298592015-08-27 07:38:01 -0700338
339 /** incoming read bytes */
340 gpr_slice_buffer read_buffer;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700341
Craig Tiller4aa71a12015-06-15 13:00:55 -0700342 /** address to place a newly accepted stream - set and unset by
Craig Tiller606d8742015-06-15 06:58:50 -0700343 grpc_chttp2_parsing_accept_stream; used by init_stream to
344 publish the accepted server stream */
345 grpc_chttp2_stream **accepting_stream;
346
Craig Tiller9b8671c2015-06-12 07:41:54 -0700347 struct {
Craig Tiller1064f8b2015-06-25 13:52:57 -0700348 /* accept stream callback */
349 void (*accept_stream)(void *user_data, grpc_transport *transport,
350 const void *server_data);
351 void *accept_stream_user_data;
352
353 /** connectivity tracking */
Craig Tiller08a1cf82015-06-29 09:37:52 -0700354 grpc_connectivity_state_tracker state_tracker;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700355 } channel_callback;
356};
357
Craig Tillerd20efd22015-06-12 16:17:09 -0700358typedef struct {
359 /** HTTP2 stream id for this stream, or zero if one has not been assigned */
Craig Tiller9b8671c2015-06-12 07:41:54 -0700360 gpr_uint32 id;
361
Craig Tiller33825112015-09-18 07:44:19 -0700362 grpc_closure *send_done_closure;
363 grpc_closure *recv_done_closure;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700364
Craig Tillerd20efd22015-06-12 16:17:09 -0700365 /** window available for us to send to peer */
366 gpr_int64 outgoing_window;
Craig Tiller27166a62015-07-05 21:08:33 -0700367 /** The number of bytes the upper layers have offered to receive.
368 As the upper layer offers more bytes, this value increases.
369 As bytes are read, this value decreases. */
370 gpr_uint32 max_recv_bytes;
371 /** The number of bytes the upper layer has offered to read but we have
372 not yet announced to HTTP2 flow control.
373 As the upper layers offer to read more bytes, this value increases.
374 As we advertise incoming flow control window, this value decreases. */
375 gpr_uint32 unannounced_incoming_window;
376 /** The number of bytes of HTTP2 flow control we have advertised.
377 As we advertise incoming flow control window, this value increases.
378 As bytes are read, this value decreases.
379 Updated after parse. */
Craig Tiller3719f072015-06-12 17:19:51 -0700380 gpr_uint32 incoming_window;
Craig Tillerd20efd22015-06-12 16:17:09 -0700381 /** stream ops the transport user would like to send */
382 grpc_stream_op_buffer *outgoing_sopb;
383 /** when the application requests writes be closed, the write_closed is
384 'queued'; when the close is flow controlled into the send path, we are
385 'sending' it; when the write has been performed it is 'sent' */
386 grpc_chttp2_write_state write_state;
387 /** is this stream closed (boolean) */
388 gpr_uint8 read_closed;
Craig Tiller5dc3b302015-06-15 16:06:50 -0700389 /** has this stream been cancelled? (boolean) */
390 gpr_uint8 cancelled;
Craig Tillercec9eb92015-06-17 17:16:48 -0700391 grpc_status_code cancelled_status;
392 /** have we told the upper layer that this stream is cancelled? */
393 gpr_uint8 published_cancelled;
Craig Tiller5dc3b302015-06-15 16:06:50 -0700394 /** is this stream in the stream map? (boolean) */
395 gpr_uint8 in_stream_map;
Craig Tiller0c23f292015-08-03 10:18:05 -0700396 /** bitmask of GRPC_CHTTP2_WRITING_xxx above */
Craig Tiller994c2622015-07-23 14:00:58 -0700397 gpr_uint8 writing_now;
Craig Tiller45ce9272015-07-31 11:22:35 -0700398 /** has anything been written to this stream? */
399 gpr_uint8 written_anything;
Craig Tiller606d8742015-06-15 06:58:50 -0700400
401 /** stream state already published to the upper layer */
402 grpc_stream_state published_state;
403 /** address to publish next stream state to */
404 grpc_stream_state *publish_state;
405 /** pointer to sop buffer to fill in with new stream ops */
Craig Tiller6905b7c2015-06-16 15:33:33 -0700406 grpc_stream_op_buffer *publish_sopb;
407 grpc_stream_op_buffer incoming_sopb;
Craig Tiller5dc3b302015-06-15 16:06:50 -0700408
409 /** incoming metadata */
410 grpc_chttp2_incoming_metadata_buffer incoming_metadata;
Craig Tillerb787c502015-06-15 16:14:52 -0700411 grpc_chttp2_incoming_metadata_live_op_buffer outstanding_metadata;
Craig Tillerd20efd22015-06-12 16:17:09 -0700412} grpc_chttp2_stream_global;
413
414typedef struct {
415 /** HTTP2 stream id for this stream, or zero if one has not been assigned */
416 gpr_uint32 id;
417 /** sops that have passed flow control to be written */
418 grpc_stream_op_buffer sopb;
419 /** how strongly should we indicate closure with the next write */
420 grpc_chttp2_send_closed send_closed;
Craig Tiller86316522015-07-15 11:35:07 -0700421 /** how much window should we announce? */
422 gpr_uint32 announce_window;
Craig Tillerd20efd22015-06-12 16:17:09 -0700423} grpc_chttp2_stream_writing;
424
425struct grpc_chttp2_stream_parsing {
426 /** HTTP2 stream id for this stream, or zero if one has not been assigned */
427 gpr_uint32 id;
428 /** has this stream received a close */
429 gpr_uint8 received_close;
Craig Tiller3719f072015-06-12 17:19:51 -0700430 /** saw a rst_stream */
431 gpr_uint8 saw_rst_stream;
Craig Tiller606d8742015-06-15 06:58:50 -0700432 /** incoming_window has been reduced by this much during parsing */
433 gpr_uint32 incoming_window_delta;
Craig Tillerd20efd22015-06-12 16:17:09 -0700434 /** window available for peer to send to us */
435 gpr_uint32 incoming_window;
436 /** parsing state for data frames */
437 grpc_chttp2_data_parser data_parser;
Craig Tiller3719f072015-06-12 17:19:51 -0700438 /** reason give to rst_stream */
439 gpr_uint32 rst_stream_reason;
440 /* amount of window given */
441 gpr_uint64 outgoing_window_update;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700442
Craig Tiller5dc3b302015-06-15 16:06:50 -0700443 /** incoming metadata */
444 grpc_chttp2_incoming_metadata_buffer incoming_metadata;
Craig Tillerd20efd22015-06-12 16:17:09 -0700445};
446
447struct grpc_chttp2_stream {
448 grpc_chttp2_stream_global global;
449 grpc_chttp2_stream_writing writing;
Craig Tiller606d8742015-06-15 06:58:50 -0700450 grpc_chttp2_stream_parsing parsing;
Craig Tillerd20efd22015-06-12 16:17:09 -0700451
452 grpc_chttp2_stream_link links[STREAM_LIST_COUNT];
453 gpr_uint8 included[STREAM_LIST_COUNT];
Craig Tiller9b8671c2015-06-12 07:41:54 -0700454};
455
Craig Tillerd20efd22015-06-12 16:17:09 -0700456/** Transport writing call flow:
Craig Tiller4aa71a12015-06-15 13:00:55 -0700457 chttp2_transport.c calls grpc_chttp2_unlocking_check_writes to see if writes
458 are required;
459 if they are, chttp2_transport.c calls grpc_chttp2_perform_writes to do the
460 writes.
461 Once writes have been completed (meaning another write could potentially be
462 started),
463 grpc_chttp2_terminate_writing is called. This will call
464 grpc_chttp2_cleanup_writing, at which
Craig Tillerd20efd22015-06-12 16:17:09 -0700465 point the write phase is complete. */
466
Craig Tiller3208e392015-06-12 08:17:02 -0700467/** Someone is unlocking the transport mutex: check to see if writes
468 are required, and schedule them if so */
Craig Tiller4aa71a12015-06-15 13:00:55 -0700469int grpc_chttp2_unlocking_check_writes(grpc_chttp2_transport_global *global,
470 grpc_chttp2_transport_writing *writing);
471void grpc_chttp2_perform_writes(
472 grpc_chttp2_transport_writing *transport_writing, grpc_endpoint *endpoint);
Craig Tillerb0298592015-08-27 07:38:01 -0700473void grpc_chttp2_terminate_writing(void *transport_writing, int success);
Craig Tiller4aa71a12015-06-15 13:00:55 -0700474void grpc_chttp2_cleanup_writing(grpc_chttp2_transport_global *global,
475 grpc_chttp2_transport_writing *writing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700476
Craig Tiller4aa71a12015-06-15 13:00:55 -0700477void grpc_chttp2_prepare_to_read(grpc_chttp2_transport_global *global,
478 grpc_chttp2_transport_parsing *parsing);
Craig Tillerab630732015-06-25 11:20:01 -0700479/** Process one slice of incoming data; return 1 if the connection is still
480 viable after reading, or 0 if the connection should be torn down */
Craig Tiller4aa71a12015-06-15 13:00:55 -0700481int grpc_chttp2_perform_read(grpc_chttp2_transport_parsing *transport_parsing,
482 gpr_slice slice);
483void grpc_chttp2_publish_reads(grpc_chttp2_transport_global *global,
484 grpc_chttp2_transport_parsing *parsing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700485
486/** Get a writable stream
Craig Tillerab630732015-06-25 11:20:01 -0700487 returns non-zero if there was a stream available */
Craig Tiller4aa71a12015-06-15 13:00:55 -0700488void grpc_chttp2_list_add_writable_stream(
489 grpc_chttp2_transport_global *transport_global,
490 grpc_chttp2_stream_global *stream_global);
Craig Tiller994c2622015-07-23 14:00:58 -0700491void grpc_chttp2_list_add_first_writable_stream(
492 grpc_chttp2_transport_global *transport_global,
493 grpc_chttp2_stream_global *stream_global);
Craig Tiller4aa71a12015-06-15 13:00:55 -0700494int grpc_chttp2_list_pop_writable_stream(
495 grpc_chttp2_transport_global *transport_global,
496 grpc_chttp2_transport_writing *transport_writing,
497 grpc_chttp2_stream_global **stream_global,
498 grpc_chttp2_stream_writing **stream_writing);
Craig Tiller994c2622015-07-23 14:00:58 -0700499void grpc_chttp2_list_remove_writable_stream(
500 grpc_chttp2_transport_global *transport_global,
501 grpc_chttp2_stream_global *stream_global);
Craig Tillerd20efd22015-06-12 16:17:09 -0700502
Craig Tillercf1e3192015-06-16 14:28:22 -0700503void grpc_chttp2_list_add_incoming_window_updated(
504 grpc_chttp2_transport_global *transport_global,
505 grpc_chttp2_stream_global *stream_global);
506int grpc_chttp2_list_pop_incoming_window_updated(
507 grpc_chttp2_transport_global *transport_global,
508 grpc_chttp2_transport_parsing *transport_parsing,
509 grpc_chttp2_stream_global **stream_global,
510 grpc_chttp2_stream_parsing **stream_parsing);
Craig Tiller759eb322015-06-16 22:41:18 -0700511void grpc_chttp2_list_remove_incoming_window_updated(
512 grpc_chttp2_transport_global *transport_global,
513 grpc_chttp2_stream_global *stream_global);
Craig Tillercf1e3192015-06-16 14:28:22 -0700514
Craig Tiller4aa71a12015-06-15 13:00:55 -0700515void grpc_chttp2_list_add_writing_stream(
516 grpc_chttp2_transport_writing *transport_writing,
517 grpc_chttp2_stream_writing *stream_writing);
518int grpc_chttp2_list_have_writing_streams(
519 grpc_chttp2_transport_writing *transport_writing);
520int grpc_chttp2_list_pop_writing_stream(
521 grpc_chttp2_transport_writing *transport_writing,
522 grpc_chttp2_stream_writing **stream_writing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700523
Craig Tiller4aa71a12015-06-15 13:00:55 -0700524void grpc_chttp2_list_add_written_stream(
525 grpc_chttp2_transport_writing *transport_writing,
526 grpc_chttp2_stream_writing *stream_writing);
527int grpc_chttp2_list_pop_written_stream(
528 grpc_chttp2_transport_global *transport_global,
529 grpc_chttp2_transport_writing *transport_writing,
530 grpc_chttp2_stream_global **stream_global,
531 grpc_chttp2_stream_writing **stream_writing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700532
Craig Tiller4aa71a12015-06-15 13:00:55 -0700533void grpc_chttp2_list_add_parsing_seen_stream(
534 grpc_chttp2_transport_parsing *transport_parsing,
535 grpc_chttp2_stream_parsing *stream_parsing);
536int grpc_chttp2_list_pop_parsing_seen_stream(
537 grpc_chttp2_transport_global *transport_global,
538 grpc_chttp2_transport_parsing *transport_parsing,
539 grpc_chttp2_stream_global **stream_global,
540 grpc_chttp2_stream_parsing **stream_parsing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700541
Craig Tiller5dc3b302015-06-15 16:06:50 -0700542void grpc_chttp2_list_add_waiting_for_concurrency(
543 grpc_chttp2_transport_global *transport_global,
544 grpc_chttp2_stream_global *stream_global);
545int grpc_chttp2_list_pop_waiting_for_concurrency(
546 grpc_chttp2_transport_global *transport_global,
547 grpc_chttp2_stream_global **stream_global);
548
Craig Tiller83fb0702015-06-16 21:13:07 -0700549void grpc_chttp2_list_add_closed_waiting_for_parsing(
Craig Tiller5dc3b302015-06-15 16:06:50 -0700550 grpc_chttp2_transport_global *transport_global,
551 grpc_chttp2_stream_global *stream_global);
Craig Tiller83fb0702015-06-16 21:13:07 -0700552int grpc_chttp2_list_pop_closed_waiting_for_parsing(
Craig Tiller5dc3b302015-06-15 16:06:50 -0700553 grpc_chttp2_transport_global *transport_global,
554 grpc_chttp2_stream_global **stream_global);
555
Craig Tiller17be5dc2015-07-01 10:36:27 -0700556void grpc_chttp2_list_add_cancelled_waiting_for_writing(
557 grpc_chttp2_transport_global *transport_global,
558 grpc_chttp2_stream_global *stream_global);
559int grpc_chttp2_list_pop_cancelled_waiting_for_writing(
560 grpc_chttp2_transport_global *transport_global,
561 grpc_chttp2_stream_global **stream_global);
562
Craig Tiller6459db42015-06-15 17:11:45 -0700563void grpc_chttp2_list_add_read_write_state_changed(
564 grpc_chttp2_transport_global *transport_global,
565 grpc_chttp2_stream_global *stream_global);
Craig Tillerf73fcd12015-06-16 16:25:26 -0700566int grpc_chttp2_list_pop_read_write_state_changed(
567 grpc_chttp2_transport_global *transport_global,
568 grpc_chttp2_stream_global **stream_global);
Craig Tiller6459db42015-06-15 17:11:45 -0700569
Craig Tiller4aa71a12015-06-15 13:00:55 -0700570grpc_chttp2_stream_parsing *grpc_chttp2_parsing_lookup_stream(
571 grpc_chttp2_transport_parsing *transport_parsing, gpr_uint32 id);
572grpc_chttp2_stream_parsing *grpc_chttp2_parsing_accept_stream(
573 grpc_chttp2_transport_parsing *transport_parsing, gpr_uint32 id);
Craig Tillerd20efd22015-06-12 16:17:09 -0700574
Craig Tiller98505102015-06-16 11:33:15 -0700575void grpc_chttp2_add_incoming_goaway(
576 grpc_chttp2_transport_global *transport_global, gpr_uint32 goaway_error,
577 gpr_slice goaway_text);
Craig Tiller4aa71a12015-06-15 13:00:55 -0700578
Craig Tiller98505102015-06-16 11:33:15 -0700579void grpc_chttp2_register_stream(grpc_chttp2_transport *t,
580 grpc_chttp2_stream *s);
Craig Tiller9188d7a2015-07-05 12:44:37 -0700581/* returns 1 if this is the last stream, 0 otherwise */
582int grpc_chttp2_unregister_stream(grpc_chttp2_transport *t,
583 grpc_chttp2_stream *s) GRPC_MUST_USE_RESULT;
584int grpc_chttp2_has_streams(grpc_chttp2_transport *t);
Craig Tiller98505102015-06-16 11:33:15 -0700585void grpc_chttp2_for_all_streams(
586 grpc_chttp2_transport_global *transport_global, void *user_data,
587 void (*cb)(grpc_chttp2_transport_global *transport_global, void *user_data,
588 grpc_chttp2_stream_global *stream_global));
Craig Tiller5dc3b302015-06-15 16:06:50 -0700589
Craig Tiller285b8822015-06-17 15:58:13 -0700590void grpc_chttp2_parsing_become_skip_parser(
591 grpc_chttp2_transport_parsing *transport_parsing);
Craig Tiller66abdaa2015-06-17 08:00:39 -0700592
Craig Tillerd20efd22015-06-12 16:17:09 -0700593#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 -0700594#define GRPC_CHTTP2_CLIENT_CONNECT_STRLEN \
595 (sizeof(GRPC_CHTTP2_CLIENT_CONNECT_STRING) - 1)
Craig Tillerd20efd22015-06-12 16:17:09 -0700596
597extern int grpc_http_trace;
Craig Tiller285b8822015-06-17 15:58:13 -0700598extern int grpc_flowctl_trace;
Craig Tillerd20efd22015-06-12 16:17:09 -0700599
Craig Tillerab630732015-06-25 11:20:01 -0700600#define GRPC_CHTTP2_IF_TRACING(stmt) \
601 if (!(grpc_http_trace)) \
602 ; \
603 else \
Craig Tillerd20efd22015-06-12 16:17:09 -0700604 stmt
Craig Tiller3208e392015-06-12 08:17:02 -0700605
Craig Tiller32ca48c2015-09-10 11:47:15 -0700606#define GRPC_CHTTP2_FLOWCTL_TRACE_STREAM(reason, transport, context, var, \
607 delta) \
608 if (!(grpc_flowctl_trace)) { \
609 } else { \
610 grpc_chttp2_flowctl_trace(__FILE__, __LINE__, reason, #context, #var, \
611 transport->is_client, context->id, \
612 (gpr_int64)(context->var), (gpr_int64)(delta)); \
Craig Tiller285b8822015-06-17 15:58:13 -0700613 }
614
Craig Tiller32ca48c2015-09-10 11:47:15 -0700615#define GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT(reason, context, var, delta) \
616 if (!(grpc_flowctl_trace)) { \
617 } else { \
618 grpc_chttp2_flowctl_trace(__FILE__, __LINE__, reason, #context, #var, \
619 context->is_client, 0, \
620 (gpr_int64)(context->var), (gpr_int64)(delta)); \
Craig Tiller285b8822015-06-17 15:58:13 -0700621 }
622
623void grpc_chttp2_flowctl_trace(const char *file, int line, const char *reason,
624 const char *context, const char *var,
625 int is_client, gpr_uint32 stream_id,
626 gpr_int64 current_value, gpr_int64 delta);
627
Craig Tiller9b8671c2015-06-12 07:41:54 -0700628#endif