blob: f0eeb6de505317e196ab5d976c520dd21410b3b8 [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
122typedef enum {
Craig Tillerab630732015-06-25 11:20:01 -0700123 GRPC_DONT_SEND_CLOSED = 0,
124 GRPC_SEND_CLOSED,
125 GRPC_SEND_CLOSED_WITH_RST_STREAM
Craig Tillerb084d902015-06-12 07:50:02 -0700126} grpc_chttp2_send_closed;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700127
128typedef struct {
Craig Tillerb084d902015-06-12 07:50:02 -0700129 grpc_chttp2_stream *head;
130 grpc_chttp2_stream *tail;
131} grpc_chttp2_stream_list;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700132
133typedef struct {
Craig Tillerb084d902015-06-12 07:50:02 -0700134 grpc_chttp2_stream *next;
135 grpc_chttp2_stream *prev;
136} grpc_chttp2_stream_link;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700137
Craig Tiller9b8671c2015-06-12 07:41:54 -0700138/* We keep several sets of connection wide parameters */
139typedef enum {
140 /* The settings our peer has asked for (and we have acked) */
Craig Tillerab630732015-06-25 11:20:01 -0700141 GRPC_PEER_SETTINGS = 0,
Craig Tiller9b8671c2015-06-12 07:41:54 -0700142 /* The settings we'd like to have */
Craig Tillerab630732015-06-25 11:20:01 -0700143 GRPC_LOCAL_SETTINGS,
Craig Tiller9b8671c2015-06-12 07:41:54 -0700144 /* The settings we've published to our peer */
Craig Tillerab630732015-06-25 11:20:01 -0700145 GRPC_SENT_SETTINGS,
Craig Tiller9b8671c2015-06-12 07:41:54 -0700146 /* The settings the peer has acked */
Craig Tillerab630732015-06-25 11:20:01 -0700147 GRPC_ACKED_SETTINGS,
148 GRPC_NUM_SETTING_SETS
Craig Tillerb084d902015-06-12 07:50:02 -0700149} grpc_chttp2_setting_set;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700150
151/* Outstanding ping request data */
Craig Tiller3719f072015-06-12 17:19:51 -0700152typedef struct grpc_chttp2_outstanding_ping {
Craig Tiller9b8671c2015-06-12 07:41:54 -0700153 gpr_uint8 id[8];
Craig Tiller3719f072015-06-12 17:19:51 -0700154 grpc_iomgr_closure *on_recv;
155 struct grpc_chttp2_outstanding_ping *next;
156 struct grpc_chttp2_outstanding_ping *prev;
Craig Tillerb084d902015-06-12 07:50:02 -0700157} grpc_chttp2_outstanding_ping;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700158
159typedef struct {
Craig Tillerd20efd22015-06-12 16:17:09 -0700160 /** data to write next write */
161 gpr_slice_buffer qbuf;
162 /** queued callbacks */
Craig Tillerff3ae682015-06-29 17:44:04 -0700163 grpc_iomgr_closure *pending_closures_head;
164 grpc_iomgr_closure *pending_closures_tail;
Craig Tillerd20efd22015-06-12 16:17:09 -0700165
166 /** window available for us to send to peer */
167 gpr_uint32 outgoing_window;
Craig Tiller3719f072015-06-12 17:19:51 -0700168 /** window available for peer to send to us - updated after parse */
169 gpr_uint32 incoming_window;
Craig Tillerd20efd22015-06-12 16:17:09 -0700170 /** how much window would we like to have for incoming_window */
171 gpr_uint32 connection_window_target;
172
Craig Tiller1064f8b2015-06-25 13:52:57 -0700173 /** have we seen a goaway */
174 gpr_uint8 seen_goaway;
Craig Tiller9188d7a2015-07-05 12:44:37 -0700175 /** have we sent a goaway */
176 gpr_uint8 sent_goaway;
Craig Tiller1064f8b2015-06-25 13:52:57 -0700177
Craig Tiller3719f072015-06-12 17:19:51 -0700178 /** is this transport a client? */
179 gpr_uint8 is_client;
Craig Tillerd20efd22015-06-12 16:17:09 -0700180 /** are the local settings dirty and need to be sent? */
181 gpr_uint8 dirtied_local_settings;
182 /** have local settings been sent? */
183 gpr_uint8 sent_local_settings;
184 /** bitmask of setting indexes to send out */
Craig Tiller4aa71a12015-06-15 13:00:55 -0700185 gpr_uint32 force_send_settings;
Craig Tillerd20efd22015-06-12 16:17:09 -0700186 /** settings values */
Craig Tillerab630732015-06-25 11:20:01 -0700187 gpr_uint32 settings[GRPC_NUM_SETTING_SETS][GRPC_CHTTP2_NUM_SETTINGS];
Craig Tillerd20efd22015-06-12 16:17:09 -0700188
Craig Tiller606d8742015-06-15 06:58:50 -0700189 /** what is the next stream id to be allocated by this peer?
190 copied to next_stream_id in parsing when parsing commences */
191 gpr_uint32 next_stream_id;
192
Craig Tillerd20efd22015-06-12 16:17:09 -0700193 /** last received stream id */
194 gpr_uint32 last_incoming_stream_id;
Craig Tiller3719f072015-06-12 17:19:51 -0700195
196 /** pings awaiting responses */
197 grpc_chttp2_outstanding_ping pings;
Craig Tiller606d8742015-06-15 06:58:50 -0700198 /** next payload for an outgoing ping */
199 gpr_uint64 ping_counter;
200
201 /** concurrent stream count: updated when not parsing,
202 so this is a strict over-estimation on the client */
203 gpr_uint32 concurrent_stream_count;
Craig Tillerd20efd22015-06-12 16:17:09 -0700204} grpc_chttp2_transport_global;
205
206typedef struct {
207 /** data to write now */
208 gpr_slice_buffer outbuf;
209 /** hpack encoding */
210 grpc_chttp2_hpack_compressor hpack_compressor;
Craig Tiller285b8822015-06-17 15:58:13 -0700211 /** is this a client? */
212 gpr_uint8 is_client;
Craig Tillerd20efd22015-06-12 16:17:09 -0700213} grpc_chttp2_transport_writing;
214
215struct grpc_chttp2_transport_parsing {
216 /** is this transport a client? (boolean) */
217 gpr_uint8 is_client;
218
219 /** were settings updated? */
220 gpr_uint8 settings_updated;
221 /** was a settings ack received? */
222 gpr_uint8 settings_ack_received;
223 /** was a goaway frame received? */
224 gpr_uint8 goaway_received;
225
Craig Tiller3719f072015-06-12 17:19:51 -0700226 /** initial window change */
227 gpr_int64 initial_window_update;
228
Craig Tillerd20efd22015-06-12 16:17:09 -0700229 /** data to write later - after parsing */
230 gpr_slice_buffer qbuf;
231 /* metadata object cache */
232 grpc_mdstr *str_grpc_timeout;
233 /** parser for headers */
234 grpc_chttp2_hpack_parser hpack_parser;
235 /** simple one shot parsers */
236 union {
237 grpc_chttp2_window_update_parser window_update;
238 grpc_chttp2_settings_parser settings;
239 grpc_chttp2_ping_parser ping;
240 grpc_chttp2_rst_stream_parser rst_stream;
241 } simple;
242 /** parser for goaway frames */
243 grpc_chttp2_goaway_parser goaway_parser;
244
245 /** window available for peer to send to us */
246 gpr_uint32 incoming_window;
Craig Tiller285b8822015-06-17 15:58:13 -0700247 gpr_uint32 incoming_window_delta;
Craig Tillerd20efd22015-06-12 16:17:09 -0700248
249 /** next stream id available at the time of beginning parsing */
250 gpr_uint32 next_stream_id;
251 gpr_uint32 last_incoming_stream_id;
252
253 /* deframing */
254 grpc_chttp2_deframe_transport_state deframe_state;
255 gpr_uint8 incoming_frame_type;
256 gpr_uint8 incoming_frame_flags;
257 gpr_uint8 header_eof;
258 gpr_uint32 expect_continuation_stream_id;
259 gpr_uint32 incoming_frame_size;
260 gpr_uint32 incoming_stream_id;
261
262 /* active parser */
263 void *parser_data;
264 grpc_chttp2_stream_parsing *incoming_stream;
Craig Tiller4aa71a12015-06-15 13:00:55 -0700265 grpc_chttp2_parse_error (*parser)(
266 void *parser_user_data, grpc_chttp2_transport_parsing *transport_parsing,
267 grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
Craig Tillerd20efd22015-06-12 16:17:09 -0700268
269 /* received settings */
270 gpr_uint32 settings[GRPC_CHTTP2_NUM_SETTINGS];
271
272 /* goaway data */
273 grpc_status_code goaway_error;
274 gpr_uint32 goaway_last_stream_index;
275 gpr_slice goaway_text;
Craig Tiller3719f072015-06-12 17:19:51 -0700276
277 gpr_uint64 outgoing_window_update;
278
279 /** pings awaiting responses */
280 grpc_chttp2_outstanding_ping pings;
Craig Tillerd20efd22015-06-12 16:17:09 -0700281};
282
Craig Tillerb084d902015-06-12 07:50:02 -0700283struct grpc_chttp2_transport {
Craig Tiller9b8671c2015-06-12 07:41:54 -0700284 grpc_transport base; /* must be first */
285 grpc_endpoint *ep;
286 grpc_mdctx *metadata_context;
287 gpr_refcount refs;
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700288 char *peer_string;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700289
290 gpr_mu mu;
Craig Tiller606d8742015-06-15 06:58:50 -0700291
292 /** is the transport destroying itself? */
293 gpr_uint8 destroying;
294 /** has the upper layer closed the transport? */
295 gpr_uint8 closed;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700296
Craig Tillerd20efd22015-06-12 16:17:09 -0700297 /** is a thread currently writing */
298 gpr_uint8 writing_active;
Craig Tiller606d8742015-06-15 06:58:50 -0700299 /** is a thread currently parsing */
300 gpr_uint8 parsing_active;
Craig Tillerd20efd22015-06-12 16:17:09 -0700301
Craig Tiller606d8742015-06-15 06:58:50 -0700302 /** is there a read request to the endpoint outstanding? */
303 gpr_uint8 endpoint_reading;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700304
Craig Tiller606d8742015-06-15 06:58:50 -0700305 /** various lists of streams */
Craig Tillerb084d902015-06-12 07:50:02 -0700306 grpc_chttp2_stream_list lists[STREAM_LIST_COUNT];
Craig Tiller9b8671c2015-06-12 07:41:54 -0700307
Craig Tiller606d8742015-06-15 06:58:50 -0700308 /** global state for reading/writing */
Craig Tillerd20efd22015-06-12 16:17:09 -0700309 grpc_chttp2_transport_global global;
Craig Tiller606d8742015-06-15 06:58:50 -0700310 /** state only accessible by the chain of execution that
311 set writing_active=1 */
Craig Tillerd20efd22015-06-12 16:17:09 -0700312 grpc_chttp2_transport_writing writing;
Craig Tiller606d8742015-06-15 06:58:50 -0700313 /** state only accessible by the chain of execution that
314 set parsing_active=1 */
Craig Tillerd20efd22015-06-12 16:17:09 -0700315 grpc_chttp2_transport_parsing parsing;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700316
Craig Tiller606d8742015-06-15 06:58:50 -0700317 /** maps stream id to grpc_chttp2_stream objects;
318 owned by the parsing thread when parsing */
319 grpc_chttp2_stream_map parsing_stream_map;
320
321 /** streams created by the client (possibly during parsing);
322 merged with parsing_stream_map during unlock when no
323 parsing is occurring */
324 grpc_chttp2_stream_map new_stream_map;
325
Craig Tillerd20efd22015-06-12 16:17:09 -0700326 /** closure to execute writing */
327 grpc_iomgr_closure writing_action;
Craig Tiller8b2f1d72015-06-18 13:38:38 -0700328 /** closure to start reading from the endpoint */
329 grpc_iomgr_closure reading_action;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700330
Craig Tiller4aa71a12015-06-15 13:00:55 -0700331 /** address to place a newly accepted stream - set and unset by
Craig Tiller606d8742015-06-15 06:58:50 -0700332 grpc_chttp2_parsing_accept_stream; used by init_stream to
333 publish the accepted server stream */
334 grpc_chttp2_stream **accepting_stream;
335
Craig Tiller9b8671c2015-06-12 07:41:54 -0700336 struct {
Craig Tiller1064f8b2015-06-25 13:52:57 -0700337 /* accept stream callback */
338 void (*accept_stream)(void *user_data, grpc_transport *transport,
339 const void *server_data);
340 void *accept_stream_user_data;
341
342 /** connectivity tracking */
Craig Tiller08a1cf82015-06-29 09:37:52 -0700343 grpc_connectivity_state_tracker state_tracker;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700344 } channel_callback;
345};
346
Craig Tillerd20efd22015-06-12 16:17:09 -0700347typedef struct {
348 /** HTTP2 stream id for this stream, or zero if one has not been assigned */
Craig Tiller9b8671c2015-06-12 07:41:54 -0700349 gpr_uint32 id;
350
Craig Tillerd20efd22015-06-12 16:17:09 -0700351 grpc_iomgr_closure *send_done_closure;
352 grpc_iomgr_closure *recv_done_closure;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700353
Craig Tillerd20efd22015-06-12 16:17:09 -0700354 /** window available for us to send to peer */
355 gpr_int64 outgoing_window;
Craig Tiller27166a62015-07-05 21:08:33 -0700356 /** The number of bytes the upper layers have offered to receive.
357 As the upper layer offers more bytes, this value increases.
358 As bytes are read, this value decreases. */
359 gpr_uint32 max_recv_bytes;
360 /** The number of bytes the upper layer has offered to read but we have
361 not yet announced to HTTP2 flow control.
362 As the upper layers offer to read more bytes, this value increases.
363 As we advertise incoming flow control window, this value decreases. */
364 gpr_uint32 unannounced_incoming_window;
365 /** The number of bytes of HTTP2 flow control we have advertised.
366 As we advertise incoming flow control window, this value increases.
367 As bytes are read, this value decreases.
368 Updated after parse. */
Craig Tiller3719f072015-06-12 17:19:51 -0700369 gpr_uint32 incoming_window;
Craig Tillerd20efd22015-06-12 16:17:09 -0700370 /** stream ops the transport user would like to send */
371 grpc_stream_op_buffer *outgoing_sopb;
372 /** when the application requests writes be closed, the write_closed is
373 'queued'; when the close is flow controlled into the send path, we are
374 'sending' it; when the write has been performed it is 'sent' */
375 grpc_chttp2_write_state write_state;
376 /** is this stream closed (boolean) */
377 gpr_uint8 read_closed;
Craig Tiller5dc3b302015-06-15 16:06:50 -0700378 /** has this stream been cancelled? (boolean) */
379 gpr_uint8 cancelled;
Craig Tillercec9eb92015-06-17 17:16:48 -0700380 grpc_status_code cancelled_status;
381 /** have we told the upper layer that this stream is cancelled? */
382 gpr_uint8 published_cancelled;
Craig Tiller5dc3b302015-06-15 16:06:50 -0700383 /** is this stream in the stream map? (boolean) */
384 gpr_uint8 in_stream_map;
Craig Tiller994c2622015-07-23 14:00:58 -0700385 /** is this stream actively being written? */
386 gpr_uint8 writing_now;
Craig Tiller606d8742015-06-15 06:58:50 -0700387
388 /** stream state already published to the upper layer */
389 grpc_stream_state published_state;
390 /** address to publish next stream state to */
391 grpc_stream_state *publish_state;
392 /** pointer to sop buffer to fill in with new stream ops */
Craig Tiller6905b7c2015-06-16 15:33:33 -0700393 grpc_stream_op_buffer *publish_sopb;
394 grpc_stream_op_buffer incoming_sopb;
Craig Tiller5dc3b302015-06-15 16:06:50 -0700395
396 /** incoming metadata */
397 grpc_chttp2_incoming_metadata_buffer incoming_metadata;
Craig Tillerb787c502015-06-15 16:14:52 -0700398 grpc_chttp2_incoming_metadata_live_op_buffer outstanding_metadata;
Craig Tillerd20efd22015-06-12 16:17:09 -0700399} grpc_chttp2_stream_global;
400
401typedef struct {
402 /** HTTP2 stream id for this stream, or zero if one has not been assigned */
403 gpr_uint32 id;
404 /** sops that have passed flow control to be written */
405 grpc_stream_op_buffer sopb;
406 /** how strongly should we indicate closure with the next write */
407 grpc_chttp2_send_closed send_closed;
Craig Tiller86316522015-07-15 11:35:07 -0700408 /** how much window should we announce? */
409 gpr_uint32 announce_window;
Craig Tillerd20efd22015-06-12 16:17:09 -0700410} grpc_chttp2_stream_writing;
411
412struct grpc_chttp2_stream_parsing {
413 /** HTTP2 stream id for this stream, or zero if one has not been assigned */
414 gpr_uint32 id;
415 /** has this stream received a close */
416 gpr_uint8 received_close;
Craig Tiller3719f072015-06-12 17:19:51 -0700417 /** saw a rst_stream */
418 gpr_uint8 saw_rst_stream;
Craig Tiller606d8742015-06-15 06:58:50 -0700419 /** incoming_window has been reduced by this much during parsing */
420 gpr_uint32 incoming_window_delta;
Craig Tillerd20efd22015-06-12 16:17:09 -0700421 /** window available for peer to send to us */
422 gpr_uint32 incoming_window;
423 /** parsing state for data frames */
424 grpc_chttp2_data_parser data_parser;
Craig Tiller3719f072015-06-12 17:19:51 -0700425 /** reason give to rst_stream */
426 gpr_uint32 rst_stream_reason;
427 /* amount of window given */
428 gpr_uint64 outgoing_window_update;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700429
Craig Tiller5dc3b302015-06-15 16:06:50 -0700430 /** incoming metadata */
431 grpc_chttp2_incoming_metadata_buffer incoming_metadata;
Craig Tillerd20efd22015-06-12 16:17:09 -0700432};
433
434struct grpc_chttp2_stream {
435 grpc_chttp2_stream_global global;
436 grpc_chttp2_stream_writing writing;
Craig Tiller606d8742015-06-15 06:58:50 -0700437 grpc_chttp2_stream_parsing parsing;
Craig Tillerd20efd22015-06-12 16:17:09 -0700438
439 grpc_chttp2_stream_link links[STREAM_LIST_COUNT];
440 gpr_uint8 included[STREAM_LIST_COUNT];
Craig Tiller9b8671c2015-06-12 07:41:54 -0700441};
442
Craig Tillerd20efd22015-06-12 16:17:09 -0700443/** Transport writing call flow:
Craig Tiller4aa71a12015-06-15 13:00:55 -0700444 chttp2_transport.c calls grpc_chttp2_unlocking_check_writes to see if writes
445 are required;
446 if they are, chttp2_transport.c calls grpc_chttp2_perform_writes to do the
447 writes.
448 Once writes have been completed (meaning another write could potentially be
449 started),
450 grpc_chttp2_terminate_writing is called. This will call
451 grpc_chttp2_cleanup_writing, at which
Craig Tillerd20efd22015-06-12 16:17:09 -0700452 point the write phase is complete. */
453
Craig Tiller3208e392015-06-12 08:17:02 -0700454/** Someone is unlocking the transport mutex: check to see if writes
455 are required, and schedule them if so */
Craig Tiller4aa71a12015-06-15 13:00:55 -0700456int grpc_chttp2_unlocking_check_writes(grpc_chttp2_transport_global *global,
457 grpc_chttp2_transport_writing *writing);
458void grpc_chttp2_perform_writes(
459 grpc_chttp2_transport_writing *transport_writing, grpc_endpoint *endpoint);
460void grpc_chttp2_terminate_writing(
461 grpc_chttp2_transport_writing *transport_writing, int success);
462void grpc_chttp2_cleanup_writing(grpc_chttp2_transport_global *global,
463 grpc_chttp2_transport_writing *writing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700464
Craig Tiller4aa71a12015-06-15 13:00:55 -0700465void grpc_chttp2_prepare_to_read(grpc_chttp2_transport_global *global,
466 grpc_chttp2_transport_parsing *parsing);
Craig Tillerab630732015-06-25 11:20:01 -0700467/** Process one slice of incoming data; return 1 if the connection is still
468 viable after reading, or 0 if the connection should be torn down */
Craig Tiller4aa71a12015-06-15 13:00:55 -0700469int grpc_chttp2_perform_read(grpc_chttp2_transport_parsing *transport_parsing,
470 gpr_slice slice);
471void grpc_chttp2_publish_reads(grpc_chttp2_transport_global *global,
472 grpc_chttp2_transport_parsing *parsing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700473
474/** Get a writable stream
Craig Tillerab630732015-06-25 11:20:01 -0700475 returns non-zero if there was a stream available */
Craig Tiller4aa71a12015-06-15 13:00:55 -0700476void grpc_chttp2_list_add_writable_stream(
477 grpc_chttp2_transport_global *transport_global,
478 grpc_chttp2_stream_global *stream_global);
Craig Tiller994c2622015-07-23 14:00:58 -0700479void grpc_chttp2_list_add_first_writable_stream(
480 grpc_chttp2_transport_global *transport_global,
481 grpc_chttp2_stream_global *stream_global);
Craig Tiller4aa71a12015-06-15 13:00:55 -0700482int grpc_chttp2_list_pop_writable_stream(
483 grpc_chttp2_transport_global *transport_global,
484 grpc_chttp2_transport_writing *transport_writing,
485 grpc_chttp2_stream_global **stream_global,
486 grpc_chttp2_stream_writing **stream_writing);
Craig Tiller994c2622015-07-23 14:00:58 -0700487void grpc_chttp2_list_remove_writable_stream(
488 grpc_chttp2_transport_global *transport_global,
489 grpc_chttp2_stream_global *stream_global);
Craig Tillerd20efd22015-06-12 16:17:09 -0700490
Craig Tillercf1e3192015-06-16 14:28:22 -0700491void grpc_chttp2_list_add_incoming_window_updated(
492 grpc_chttp2_transport_global *transport_global,
493 grpc_chttp2_stream_global *stream_global);
494int grpc_chttp2_list_pop_incoming_window_updated(
495 grpc_chttp2_transport_global *transport_global,
496 grpc_chttp2_transport_parsing *transport_parsing,
497 grpc_chttp2_stream_global **stream_global,
498 grpc_chttp2_stream_parsing **stream_parsing);
Craig Tiller759eb322015-06-16 22:41:18 -0700499void grpc_chttp2_list_remove_incoming_window_updated(
500 grpc_chttp2_transport_global *transport_global,
501 grpc_chttp2_stream_global *stream_global);
Craig Tillercf1e3192015-06-16 14:28:22 -0700502
Craig Tiller4aa71a12015-06-15 13:00:55 -0700503void grpc_chttp2_list_add_writing_stream(
504 grpc_chttp2_transport_writing *transport_writing,
505 grpc_chttp2_stream_writing *stream_writing);
506int grpc_chttp2_list_have_writing_streams(
507 grpc_chttp2_transport_writing *transport_writing);
508int grpc_chttp2_list_pop_writing_stream(
509 grpc_chttp2_transport_writing *transport_writing,
510 grpc_chttp2_stream_writing **stream_writing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700511
Craig Tiller4aa71a12015-06-15 13:00:55 -0700512void grpc_chttp2_list_add_written_stream(
513 grpc_chttp2_transport_writing *transport_writing,
514 grpc_chttp2_stream_writing *stream_writing);
515int grpc_chttp2_list_pop_written_stream(
516 grpc_chttp2_transport_global *transport_global,
517 grpc_chttp2_transport_writing *transport_writing,
518 grpc_chttp2_stream_global **stream_global,
519 grpc_chttp2_stream_writing **stream_writing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700520
Craig Tiller4aa71a12015-06-15 13:00:55 -0700521void grpc_chttp2_list_add_parsing_seen_stream(
522 grpc_chttp2_transport_parsing *transport_parsing,
523 grpc_chttp2_stream_parsing *stream_parsing);
524int grpc_chttp2_list_pop_parsing_seen_stream(
525 grpc_chttp2_transport_global *transport_global,
526 grpc_chttp2_transport_parsing *transport_parsing,
527 grpc_chttp2_stream_global **stream_global,
528 grpc_chttp2_stream_parsing **stream_parsing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700529
Craig Tiller5dc3b302015-06-15 16:06:50 -0700530void grpc_chttp2_list_add_waiting_for_concurrency(
531 grpc_chttp2_transport_global *transport_global,
532 grpc_chttp2_stream_global *stream_global);
533int grpc_chttp2_list_pop_waiting_for_concurrency(
534 grpc_chttp2_transport_global *transport_global,
535 grpc_chttp2_stream_global **stream_global);
536
Craig Tiller83fb0702015-06-16 21:13:07 -0700537void grpc_chttp2_list_add_closed_waiting_for_parsing(
Craig Tiller5dc3b302015-06-15 16:06:50 -0700538 grpc_chttp2_transport_global *transport_global,
539 grpc_chttp2_stream_global *stream_global);
Craig Tiller83fb0702015-06-16 21:13:07 -0700540int grpc_chttp2_list_pop_closed_waiting_for_parsing(
Craig Tiller5dc3b302015-06-15 16:06:50 -0700541 grpc_chttp2_transport_global *transport_global,
542 grpc_chttp2_stream_global **stream_global);
543
Craig Tiller17be5dc2015-07-01 10:36:27 -0700544void grpc_chttp2_list_add_cancelled_waiting_for_writing(
545 grpc_chttp2_transport_global *transport_global,
546 grpc_chttp2_stream_global *stream_global);
547int grpc_chttp2_list_pop_cancelled_waiting_for_writing(
548 grpc_chttp2_transport_global *transport_global,
549 grpc_chttp2_stream_global **stream_global);
550
Craig Tiller6459db42015-06-15 17:11:45 -0700551void grpc_chttp2_list_add_read_write_state_changed(
552 grpc_chttp2_transport_global *transport_global,
553 grpc_chttp2_stream_global *stream_global);
Craig Tillerf73fcd12015-06-16 16:25:26 -0700554int grpc_chttp2_list_pop_read_write_state_changed(
555 grpc_chttp2_transport_global *transport_global,
556 grpc_chttp2_stream_global **stream_global);
Craig Tiller6459db42015-06-15 17:11:45 -0700557
Craig Tiller1937b062015-06-16 08:47:38 -0700558/** schedule a closure to run without the transport lock taken */
Craig Tiller4aa71a12015-06-15 13:00:55 -0700559void grpc_chttp2_schedule_closure(
560 grpc_chttp2_transport_global *transport_global, grpc_iomgr_closure *closure,
561 int success);
Craig Tillerd20efd22015-06-12 16:17:09 -0700562
Craig Tiller4aa71a12015-06-15 13:00:55 -0700563grpc_chttp2_stream_parsing *grpc_chttp2_parsing_lookup_stream(
564 grpc_chttp2_transport_parsing *transport_parsing, gpr_uint32 id);
565grpc_chttp2_stream_parsing *grpc_chttp2_parsing_accept_stream(
566 grpc_chttp2_transport_parsing *transport_parsing, gpr_uint32 id);
Craig Tillerd20efd22015-06-12 16:17:09 -0700567
Craig Tiller98505102015-06-16 11:33:15 -0700568void grpc_chttp2_add_incoming_goaway(
569 grpc_chttp2_transport_global *transport_global, gpr_uint32 goaway_error,
570 gpr_slice goaway_text);
Craig Tiller4aa71a12015-06-15 13:00:55 -0700571
Craig Tiller98505102015-06-16 11:33:15 -0700572void grpc_chttp2_register_stream(grpc_chttp2_transport *t,
573 grpc_chttp2_stream *s);
Craig Tiller9188d7a2015-07-05 12:44:37 -0700574/* returns 1 if this is the last stream, 0 otherwise */
575int grpc_chttp2_unregister_stream(grpc_chttp2_transport *t,
576 grpc_chttp2_stream *s) GRPC_MUST_USE_RESULT;
577int grpc_chttp2_has_streams(grpc_chttp2_transport *t);
Craig Tiller98505102015-06-16 11:33:15 -0700578void grpc_chttp2_for_all_streams(
579 grpc_chttp2_transport_global *transport_global, void *user_data,
580 void (*cb)(grpc_chttp2_transport_global *transport_global, void *user_data,
581 grpc_chttp2_stream_global *stream_global));
Craig Tiller5dc3b302015-06-15 16:06:50 -0700582
Craig Tiller285b8822015-06-17 15:58:13 -0700583void grpc_chttp2_parsing_become_skip_parser(
584 grpc_chttp2_transport_parsing *transport_parsing);
Craig Tiller66abdaa2015-06-17 08:00:39 -0700585
Craig Tillerd20efd22015-06-12 16:17:09 -0700586#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 -0700587#define GRPC_CHTTP2_CLIENT_CONNECT_STRLEN \
588 (sizeof(GRPC_CHTTP2_CLIENT_CONNECT_STRING) - 1)
Craig Tillerd20efd22015-06-12 16:17:09 -0700589
590extern int grpc_http_trace;
Craig Tiller285b8822015-06-17 15:58:13 -0700591extern int grpc_flowctl_trace;
Craig Tillerd20efd22015-06-12 16:17:09 -0700592
Craig Tillerab630732015-06-25 11:20:01 -0700593#define GRPC_CHTTP2_IF_TRACING(stmt) \
594 if (!(grpc_http_trace)) \
595 ; \
596 else \
Craig Tillerd20efd22015-06-12 16:17:09 -0700597 stmt
Craig Tiller3208e392015-06-12 08:17:02 -0700598
Craig Tiller285b8822015-06-17 15:58:13 -0700599#define GRPC_CHTTP2_FLOWCTL_TRACE_STREAM(reason, transport, context, var, \
600 delta) \
601 if (!(grpc_flowctl_trace)) { \
602 } else { \
603 grpc_chttp2_flowctl_trace(__FILE__, __LINE__, reason, #context, #var, \
604 transport->is_client, context->id, context->var, \
605 delta); \
606 }
607
608#define GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT(reason, context, var, delta) \
609 if (!(grpc_flowctl_trace)) { \
610 } else { \
611 grpc_chttp2_flowctl_trace(__FILE__, __LINE__, reason, #context, #var, \
612 context->is_client, 0, context->var, delta); \
613 }
614
615void grpc_chttp2_flowctl_trace(const char *file, int line, const char *reason,
616 const char *context, const char *var,
617 int is_client, gpr_uint32 stream_id,
618 gpr_int64 current_value, gpr_int64 delta);
619
Craig Tiller9b8671c2015-06-12 07:41:54 -0700620#endif