blob: cb428f8e3c9c53e91cd0a26708a26e8d7de06d71 [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 Tillerd20efd22015-06-12 16:17:09 -0700217} grpc_chttp2_transport_writing;
218
219struct grpc_chttp2_transport_parsing {
220 /** is this transport a client? (boolean) */
221 gpr_uint8 is_client;
222
223 /** were settings updated? */
224 gpr_uint8 settings_updated;
225 /** was a settings ack received? */
226 gpr_uint8 settings_ack_received;
227 /** was a goaway frame received? */
228 gpr_uint8 goaway_received;
229
Craig Tiller3719f072015-06-12 17:19:51 -0700230 /** initial window change */
231 gpr_int64 initial_window_update;
232
Craig Tillerd20efd22015-06-12 16:17:09 -0700233 /** data to write later - after parsing */
234 gpr_slice_buffer qbuf;
235 /* metadata object cache */
236 grpc_mdstr *str_grpc_timeout;
237 /** parser for headers */
238 grpc_chttp2_hpack_parser hpack_parser;
239 /** simple one shot parsers */
240 union {
241 grpc_chttp2_window_update_parser window_update;
242 grpc_chttp2_settings_parser settings;
243 grpc_chttp2_ping_parser ping;
244 grpc_chttp2_rst_stream_parser rst_stream;
245 } simple;
246 /** parser for goaway frames */
247 grpc_chttp2_goaway_parser goaway_parser;
248
249 /** window available for peer to send to us */
250 gpr_uint32 incoming_window;
Craig Tiller285b8822015-06-17 15:58:13 -0700251 gpr_uint32 incoming_window_delta;
Craig Tillerd20efd22015-06-12 16:17:09 -0700252
253 /** next stream id available at the time of beginning parsing */
254 gpr_uint32 next_stream_id;
255 gpr_uint32 last_incoming_stream_id;
256
257 /* deframing */
258 grpc_chttp2_deframe_transport_state deframe_state;
259 gpr_uint8 incoming_frame_type;
260 gpr_uint8 incoming_frame_flags;
261 gpr_uint8 header_eof;
262 gpr_uint32 expect_continuation_stream_id;
263 gpr_uint32 incoming_frame_size;
264 gpr_uint32 incoming_stream_id;
265
266 /* active parser */
267 void *parser_data;
268 grpc_chttp2_stream_parsing *incoming_stream;
Craig Tiller4aa71a12015-06-15 13:00:55 -0700269 grpc_chttp2_parse_error (*parser)(
270 void *parser_user_data, grpc_chttp2_transport_parsing *transport_parsing,
271 grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
Craig Tillerd20efd22015-06-12 16:17:09 -0700272
273 /* received settings */
274 gpr_uint32 settings[GRPC_CHTTP2_NUM_SETTINGS];
275
276 /* goaway data */
277 grpc_status_code goaway_error;
278 gpr_uint32 goaway_last_stream_index;
279 gpr_slice goaway_text;
Craig Tiller3719f072015-06-12 17:19:51 -0700280
281 gpr_uint64 outgoing_window_update;
282
283 /** pings awaiting responses */
284 grpc_chttp2_outstanding_ping pings;
Craig Tillerd20efd22015-06-12 16:17:09 -0700285};
286
Craig Tillerb084d902015-06-12 07:50:02 -0700287struct grpc_chttp2_transport {
Craig Tiller9b8671c2015-06-12 07:41:54 -0700288 grpc_transport base; /* must be first */
289 grpc_endpoint *ep;
290 grpc_mdctx *metadata_context;
291 gpr_refcount refs;
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700292 char *peer_string;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700293
294 gpr_mu mu;
Craig Tiller606d8742015-06-15 06:58:50 -0700295
296 /** is the transport destroying itself? */
297 gpr_uint8 destroying;
298 /** has the upper layer closed the transport? */
299 gpr_uint8 closed;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700300
Craig Tillerd20efd22015-06-12 16:17:09 -0700301 /** is a thread currently writing */
302 gpr_uint8 writing_active;
Craig Tiller606d8742015-06-15 06:58:50 -0700303 /** is a thread currently parsing */
304 gpr_uint8 parsing_active;
Craig Tillerd20efd22015-06-12 16:17:09 -0700305
Craig Tiller606d8742015-06-15 06:58:50 -0700306 /** is there a read request to the endpoint outstanding? */
307 gpr_uint8 endpoint_reading;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700308
Craig Tiller606d8742015-06-15 06:58:50 -0700309 /** various lists of streams */
Craig Tillerb084d902015-06-12 07:50:02 -0700310 grpc_chttp2_stream_list lists[STREAM_LIST_COUNT];
Craig Tiller9b8671c2015-06-12 07:41:54 -0700311
Craig Tiller606d8742015-06-15 06:58:50 -0700312 /** global state for reading/writing */
Craig Tillerd20efd22015-06-12 16:17:09 -0700313 grpc_chttp2_transport_global global;
Craig Tiller606d8742015-06-15 06:58:50 -0700314 /** state only accessible by the chain of execution that
315 set writing_active=1 */
Craig Tillerd20efd22015-06-12 16:17:09 -0700316 grpc_chttp2_transport_writing writing;
Craig Tiller606d8742015-06-15 06:58:50 -0700317 /** state only accessible by the chain of execution that
318 set parsing_active=1 */
Craig Tillerd20efd22015-06-12 16:17:09 -0700319 grpc_chttp2_transport_parsing parsing;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700320
Craig Tiller606d8742015-06-15 06:58:50 -0700321 /** maps stream id to grpc_chttp2_stream objects;
322 owned by the parsing thread when parsing */
323 grpc_chttp2_stream_map parsing_stream_map;
324
325 /** streams created by the client (possibly during parsing);
326 merged with parsing_stream_map during unlock when no
327 parsing is occurring */
328 grpc_chttp2_stream_map new_stream_map;
329
Craig Tillerd20efd22015-06-12 16:17:09 -0700330 /** closure to execute writing */
331 grpc_iomgr_closure writing_action;
Craig Tiller8b2f1d72015-06-18 13:38:38 -0700332 /** closure to start reading from the endpoint */
333 grpc_iomgr_closure reading_action;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700334
Craig Tiller4aa71a12015-06-15 13:00:55 -0700335 /** address to place a newly accepted stream - set and unset by
Craig Tiller606d8742015-06-15 06:58:50 -0700336 grpc_chttp2_parsing_accept_stream; used by init_stream to
337 publish the accepted server stream */
338 grpc_chttp2_stream **accepting_stream;
339
Craig Tiller9b8671c2015-06-12 07:41:54 -0700340 struct {
Craig Tiller1064f8b2015-06-25 13:52:57 -0700341 /* accept stream callback */
342 void (*accept_stream)(void *user_data, grpc_transport *transport,
343 const void *server_data);
344 void *accept_stream_user_data;
345
346 /** connectivity tracking */
Craig Tiller08a1cf82015-06-29 09:37:52 -0700347 grpc_connectivity_state_tracker state_tracker;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700348 } channel_callback;
349};
350
Craig Tillerd20efd22015-06-12 16:17:09 -0700351typedef struct {
352 /** HTTP2 stream id for this stream, or zero if one has not been assigned */
Craig Tiller9b8671c2015-06-12 07:41:54 -0700353 gpr_uint32 id;
354
Craig Tillerd20efd22015-06-12 16:17:09 -0700355 grpc_iomgr_closure *send_done_closure;
356 grpc_iomgr_closure *recv_done_closure;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700357
Craig Tillerd20efd22015-06-12 16:17:09 -0700358 /** window available for us to send to peer */
359 gpr_int64 outgoing_window;
Craig Tiller27166a62015-07-05 21:08:33 -0700360 /** The number of bytes the upper layers have offered to receive.
361 As the upper layer offers more bytes, this value increases.
362 As bytes are read, this value decreases. */
363 gpr_uint32 max_recv_bytes;
364 /** The number of bytes the upper layer has offered to read but we have
365 not yet announced to HTTP2 flow control.
366 As the upper layers offer to read more bytes, this value increases.
367 As we advertise incoming flow control window, this value decreases. */
368 gpr_uint32 unannounced_incoming_window;
369 /** The number of bytes of HTTP2 flow control we have advertised.
370 As we advertise incoming flow control window, this value increases.
371 As bytes are read, this value decreases.
372 Updated after parse. */
Craig Tiller3719f072015-06-12 17:19:51 -0700373 gpr_uint32 incoming_window;
Craig Tillerd20efd22015-06-12 16:17:09 -0700374 /** stream ops the transport user would like to send */
375 grpc_stream_op_buffer *outgoing_sopb;
376 /** when the application requests writes be closed, the write_closed is
377 'queued'; when the close is flow controlled into the send path, we are
378 'sending' it; when the write has been performed it is 'sent' */
379 grpc_chttp2_write_state write_state;
380 /** is this stream closed (boolean) */
381 gpr_uint8 read_closed;
Craig Tiller5dc3b302015-06-15 16:06:50 -0700382 /** has this stream been cancelled? (boolean) */
383 gpr_uint8 cancelled;
Craig Tillercec9eb92015-06-17 17:16:48 -0700384 grpc_status_code cancelled_status;
385 /** have we told the upper layer that this stream is cancelled? */
386 gpr_uint8 published_cancelled;
Craig Tiller5dc3b302015-06-15 16:06:50 -0700387 /** is this stream in the stream map? (boolean) */
388 gpr_uint8 in_stream_map;
Craig Tiller0c23f292015-08-03 10:18:05 -0700389 /** bitmask of GRPC_CHTTP2_WRITING_xxx above */
Craig Tiller994c2622015-07-23 14:00:58 -0700390 gpr_uint8 writing_now;
Craig Tiller606d8742015-06-15 06:58:50 -0700391
392 /** stream state already published to the upper layer */
393 grpc_stream_state published_state;
394 /** address to publish next stream state to */
395 grpc_stream_state *publish_state;
396 /** pointer to sop buffer to fill in with new stream ops */
Craig Tiller6905b7c2015-06-16 15:33:33 -0700397 grpc_stream_op_buffer *publish_sopb;
398 grpc_stream_op_buffer incoming_sopb;
Craig Tiller5dc3b302015-06-15 16:06:50 -0700399
400 /** incoming metadata */
401 grpc_chttp2_incoming_metadata_buffer incoming_metadata;
Craig Tillerb787c502015-06-15 16:14:52 -0700402 grpc_chttp2_incoming_metadata_live_op_buffer outstanding_metadata;
Craig Tillerd20efd22015-06-12 16:17:09 -0700403} grpc_chttp2_stream_global;
404
405typedef struct {
406 /** HTTP2 stream id for this stream, or zero if one has not been assigned */
407 gpr_uint32 id;
408 /** sops that have passed flow control to be written */
409 grpc_stream_op_buffer sopb;
410 /** how strongly should we indicate closure with the next write */
411 grpc_chttp2_send_closed send_closed;
Craig Tiller86316522015-07-15 11:35:07 -0700412 /** how much window should we announce? */
413 gpr_uint32 announce_window;
Craig Tillerd20efd22015-06-12 16:17:09 -0700414} grpc_chttp2_stream_writing;
415
416struct grpc_chttp2_stream_parsing {
417 /** HTTP2 stream id for this stream, or zero if one has not been assigned */
418 gpr_uint32 id;
419 /** has this stream received a close */
420 gpr_uint8 received_close;
Craig Tiller3719f072015-06-12 17:19:51 -0700421 /** saw a rst_stream */
422 gpr_uint8 saw_rst_stream;
Craig Tiller606d8742015-06-15 06:58:50 -0700423 /** incoming_window has been reduced by this much during parsing */
424 gpr_uint32 incoming_window_delta;
Craig Tillerd20efd22015-06-12 16:17:09 -0700425 /** window available for peer to send to us */
426 gpr_uint32 incoming_window;
427 /** parsing state for data frames */
428 grpc_chttp2_data_parser data_parser;
Craig Tiller3719f072015-06-12 17:19:51 -0700429 /** reason give to rst_stream */
430 gpr_uint32 rst_stream_reason;
431 /* amount of window given */
432 gpr_uint64 outgoing_window_update;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700433
Craig Tiller5dc3b302015-06-15 16:06:50 -0700434 /** incoming metadata */
435 grpc_chttp2_incoming_metadata_buffer incoming_metadata;
Craig Tillerd20efd22015-06-12 16:17:09 -0700436};
437
438struct grpc_chttp2_stream {
439 grpc_chttp2_stream_global global;
440 grpc_chttp2_stream_writing writing;
Craig Tiller606d8742015-06-15 06:58:50 -0700441 grpc_chttp2_stream_parsing parsing;
Craig Tillerd20efd22015-06-12 16:17:09 -0700442
443 grpc_chttp2_stream_link links[STREAM_LIST_COUNT];
444 gpr_uint8 included[STREAM_LIST_COUNT];
Craig Tiller9b8671c2015-06-12 07:41:54 -0700445};
446
Craig Tillerd20efd22015-06-12 16:17:09 -0700447/** Transport writing call flow:
Craig Tiller4aa71a12015-06-15 13:00:55 -0700448 chttp2_transport.c calls grpc_chttp2_unlocking_check_writes to see if writes
449 are required;
450 if they are, chttp2_transport.c calls grpc_chttp2_perform_writes to do the
451 writes.
452 Once writes have been completed (meaning another write could potentially be
453 started),
454 grpc_chttp2_terminate_writing is called. This will call
455 grpc_chttp2_cleanup_writing, at which
Craig Tillerd20efd22015-06-12 16:17:09 -0700456 point the write phase is complete. */
457
Craig Tiller3208e392015-06-12 08:17:02 -0700458/** Someone is unlocking the transport mutex: check to see if writes
459 are required, and schedule them if so */
Craig Tiller4aa71a12015-06-15 13:00:55 -0700460int grpc_chttp2_unlocking_check_writes(grpc_chttp2_transport_global *global,
461 grpc_chttp2_transport_writing *writing);
462void grpc_chttp2_perform_writes(
463 grpc_chttp2_transport_writing *transport_writing, grpc_endpoint *endpoint);
464void grpc_chttp2_terminate_writing(
465 grpc_chttp2_transport_writing *transport_writing, int success);
466void grpc_chttp2_cleanup_writing(grpc_chttp2_transport_global *global,
467 grpc_chttp2_transport_writing *writing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700468
Craig Tiller4aa71a12015-06-15 13:00:55 -0700469void grpc_chttp2_prepare_to_read(grpc_chttp2_transport_global *global,
470 grpc_chttp2_transport_parsing *parsing);
Craig Tillerab630732015-06-25 11:20:01 -0700471/** Process one slice of incoming data; return 1 if the connection is still
472 viable after reading, or 0 if the connection should be torn down */
Craig Tiller4aa71a12015-06-15 13:00:55 -0700473int grpc_chttp2_perform_read(grpc_chttp2_transport_parsing *transport_parsing,
474 gpr_slice slice);
475void grpc_chttp2_publish_reads(grpc_chttp2_transport_global *global,
476 grpc_chttp2_transport_parsing *parsing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700477
478/** Get a writable stream
Craig Tillerab630732015-06-25 11:20:01 -0700479 returns non-zero if there was a stream available */
Craig Tiller4aa71a12015-06-15 13:00:55 -0700480void grpc_chttp2_list_add_writable_stream(
481 grpc_chttp2_transport_global *transport_global,
482 grpc_chttp2_stream_global *stream_global);
Craig Tiller994c2622015-07-23 14:00:58 -0700483void grpc_chttp2_list_add_first_writable_stream(
484 grpc_chttp2_transport_global *transport_global,
485 grpc_chttp2_stream_global *stream_global);
Craig Tiller4aa71a12015-06-15 13:00:55 -0700486int grpc_chttp2_list_pop_writable_stream(
487 grpc_chttp2_transport_global *transport_global,
488 grpc_chttp2_transport_writing *transport_writing,
489 grpc_chttp2_stream_global **stream_global,
490 grpc_chttp2_stream_writing **stream_writing);
Craig Tiller994c2622015-07-23 14:00:58 -0700491void grpc_chttp2_list_remove_writable_stream(
492 grpc_chttp2_transport_global *transport_global,
493 grpc_chttp2_stream_global *stream_global);
Craig Tillerd20efd22015-06-12 16:17:09 -0700494
Craig Tillercf1e3192015-06-16 14:28:22 -0700495void grpc_chttp2_list_add_incoming_window_updated(
496 grpc_chttp2_transport_global *transport_global,
497 grpc_chttp2_stream_global *stream_global);
498int grpc_chttp2_list_pop_incoming_window_updated(
499 grpc_chttp2_transport_global *transport_global,
500 grpc_chttp2_transport_parsing *transport_parsing,
501 grpc_chttp2_stream_global **stream_global,
502 grpc_chttp2_stream_parsing **stream_parsing);
Craig Tiller759eb322015-06-16 22:41:18 -0700503void grpc_chttp2_list_remove_incoming_window_updated(
504 grpc_chttp2_transport_global *transport_global,
505 grpc_chttp2_stream_global *stream_global);
Craig Tillercf1e3192015-06-16 14:28:22 -0700506
Craig Tiller4aa71a12015-06-15 13:00:55 -0700507void grpc_chttp2_list_add_writing_stream(
508 grpc_chttp2_transport_writing *transport_writing,
509 grpc_chttp2_stream_writing *stream_writing);
510int grpc_chttp2_list_have_writing_streams(
511 grpc_chttp2_transport_writing *transport_writing);
512int grpc_chttp2_list_pop_writing_stream(
513 grpc_chttp2_transport_writing *transport_writing,
514 grpc_chttp2_stream_writing **stream_writing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700515
Craig Tiller4aa71a12015-06-15 13:00:55 -0700516void grpc_chttp2_list_add_written_stream(
517 grpc_chttp2_transport_writing *transport_writing,
518 grpc_chttp2_stream_writing *stream_writing);
519int grpc_chttp2_list_pop_written_stream(
520 grpc_chttp2_transport_global *transport_global,
521 grpc_chttp2_transport_writing *transport_writing,
522 grpc_chttp2_stream_global **stream_global,
523 grpc_chttp2_stream_writing **stream_writing);
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