blob: aaf090cd44e391edee6aaa38af056598558c266a [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 */
Craig Tiller45724b32015-09-22 10:42:19 -070057typedef enum
58{
Craig Tiller5dc3b302015-06-15 16:06:50 -070059 GRPC_CHTTP2_LIST_ALL_STREAMS,
Craig Tiller6459db42015-06-15 17:11:45 -070060 GRPC_CHTTP2_LIST_READ_WRITE_STATE_CHANGED,
Craig Tiller5dc3b302015-06-15 16:06:50 -070061 GRPC_CHTTP2_LIST_WRITABLE,
Craig Tiller6459db42015-06-15 17:11:45 -070062 GRPC_CHTTP2_LIST_WRITING,
63 GRPC_CHTTP2_LIST_WRITTEN,
Craig Tiller6459db42015-06-15 17:11:45 -070064 GRPC_CHTTP2_LIST_PARSING_SEEN,
Craig Tiller83fb0702015-06-16 21:13:07 -070065 GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_PARSING,
Craig Tiller17be5dc2015-07-01 10:36:27 -070066 GRPC_CHTTP2_LIST_CANCELLED_WAITING_FOR_WRITING,
Craig Tillercf1e3192015-06-16 14:28:22 -070067 GRPC_CHTTP2_LIST_INCOMING_WINDOW_UPDATED,
Craig Tiller5dc3b302015-06-15 16:06:50 -070068 /** streams that are waiting to start because there are too many concurrent
69 streams on the connection */
70 GRPC_CHTTP2_LIST_WAITING_FOR_CONCURRENCY,
Craig Tiller45724b32015-09-22 10:42:19 -070071 STREAM_LIST_COUNT /* must be last */
Craig Tillerb084d902015-06-12 07:50:02 -070072} grpc_chttp2_stream_list_id;
Craig Tiller9b8671c2015-06-12 07:41:54 -070073
74/* deframer state for the overall http2 stream of bytes */
Craig Tiller45724b32015-09-22 10:42:19 -070075typedef enum
76{
Craig Tiller9b8671c2015-06-12 07:41:54 -070077 /* prefix: one entry per http2 connection prefix byte */
Craig Tillerab630732015-06-25 11:20:01 -070078 GRPC_DTS_CLIENT_PREFIX_0 = 0,
79 GRPC_DTS_CLIENT_PREFIX_1,
80 GRPC_DTS_CLIENT_PREFIX_2,
81 GRPC_DTS_CLIENT_PREFIX_3,
82 GRPC_DTS_CLIENT_PREFIX_4,
83 GRPC_DTS_CLIENT_PREFIX_5,
84 GRPC_DTS_CLIENT_PREFIX_6,
85 GRPC_DTS_CLIENT_PREFIX_7,
86 GRPC_DTS_CLIENT_PREFIX_8,
87 GRPC_DTS_CLIENT_PREFIX_9,
88 GRPC_DTS_CLIENT_PREFIX_10,
89 GRPC_DTS_CLIENT_PREFIX_11,
90 GRPC_DTS_CLIENT_PREFIX_12,
91 GRPC_DTS_CLIENT_PREFIX_13,
92 GRPC_DTS_CLIENT_PREFIX_14,
93 GRPC_DTS_CLIENT_PREFIX_15,
94 GRPC_DTS_CLIENT_PREFIX_16,
95 GRPC_DTS_CLIENT_PREFIX_17,
96 GRPC_DTS_CLIENT_PREFIX_18,
97 GRPC_DTS_CLIENT_PREFIX_19,
98 GRPC_DTS_CLIENT_PREFIX_20,
99 GRPC_DTS_CLIENT_PREFIX_21,
100 GRPC_DTS_CLIENT_PREFIX_22,
101 GRPC_DTS_CLIENT_PREFIX_23,
Craig Tiller9b8671c2015-06-12 07:41:54 -0700102 /* frame header byte 0... */
103 /* must follow from the prefix states */
Craig Tillerab630732015-06-25 11:20:01 -0700104 GRPC_DTS_FH_0,
105 GRPC_DTS_FH_1,
106 GRPC_DTS_FH_2,
107 GRPC_DTS_FH_3,
108 GRPC_DTS_FH_4,
109 GRPC_DTS_FH_5,
110 GRPC_DTS_FH_6,
111 GRPC_DTS_FH_7,
Craig Tiller9b8671c2015-06-12 07:41:54 -0700112 /* ... frame header byte 8 */
Craig Tillerab630732015-06-25 11:20:01 -0700113 GRPC_DTS_FH_8,
Craig Tiller9b8671c2015-06-12 07:41:54 -0700114 /* inside a http2 frame */
Craig Tillerab630732015-06-25 11:20:01 -0700115 GRPC_DTS_FRAME
Craig Tillerb084d902015-06-12 07:50:02 -0700116} grpc_chttp2_deframe_transport_state;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700117
Craig Tiller45724b32015-09-22 10:42:19 -0700118typedef enum
119{
Craig Tillerab630732015-06-25 11:20:01 -0700120 GRPC_WRITE_STATE_OPEN,
121 GRPC_WRITE_STATE_QUEUED_CLOSE,
122 GRPC_WRITE_STATE_SENT_CLOSE
Craig Tillerb084d902015-06-12 07:50:02 -0700123} grpc_chttp2_write_state;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700124
Craig Tiller0c23f292015-08-03 10:18:05 -0700125/* flags that can be or'd into stream_global::writing_now */
126#define GRPC_CHTTP2_WRITING_DATA 1
127#define GRPC_CHTTP2_WRITING_WINDOW 2
128
Craig Tiller45724b32015-09-22 10:42:19 -0700129typedef enum
130{
Craig Tillerab630732015-06-25 11:20:01 -0700131 GRPC_DONT_SEND_CLOSED = 0,
132 GRPC_SEND_CLOSED,
133 GRPC_SEND_CLOSED_WITH_RST_STREAM
Craig Tillerb084d902015-06-12 07:50:02 -0700134} grpc_chttp2_send_closed;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700135
Craig Tiller45724b32015-09-22 10:42:19 -0700136typedef struct
137{
Craig Tillerb084d902015-06-12 07:50:02 -0700138 grpc_chttp2_stream *head;
139 grpc_chttp2_stream *tail;
140} grpc_chttp2_stream_list;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700141
Craig Tiller45724b32015-09-22 10:42:19 -0700142typedef struct
143{
Craig Tillerb084d902015-06-12 07:50:02 -0700144 grpc_chttp2_stream *next;
145 grpc_chttp2_stream *prev;
146} grpc_chttp2_stream_link;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700147
Craig Tiller9b8671c2015-06-12 07:41:54 -0700148/* We keep several sets of connection wide parameters */
Craig Tiller45724b32015-09-22 10:42:19 -0700149typedef enum
150{
Craig Tiller9b8671c2015-06-12 07:41:54 -0700151 /* The settings our peer has asked for (and we have acked) */
Craig Tillerab630732015-06-25 11:20:01 -0700152 GRPC_PEER_SETTINGS = 0,
Craig Tiller9b8671c2015-06-12 07:41:54 -0700153 /* The settings we'd like to have */
Craig Tillerab630732015-06-25 11:20:01 -0700154 GRPC_LOCAL_SETTINGS,
Craig Tiller9b8671c2015-06-12 07:41:54 -0700155 /* The settings we've published to our peer */
Craig Tillerab630732015-06-25 11:20:01 -0700156 GRPC_SENT_SETTINGS,
Craig Tiller9b8671c2015-06-12 07:41:54 -0700157 /* The settings the peer has acked */
Craig Tillerab630732015-06-25 11:20:01 -0700158 GRPC_ACKED_SETTINGS,
159 GRPC_NUM_SETTING_SETS
Craig Tillerb084d902015-06-12 07:50:02 -0700160} grpc_chttp2_setting_set;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700161
162/* Outstanding ping request data */
Craig Tiller45724b32015-09-22 10:42:19 -0700163typedef struct grpc_chttp2_outstanding_ping
164{
Craig Tiller9b8671c2015-06-12 07:41:54 -0700165 gpr_uint8 id[8];
Craig Tiller33825112015-09-18 07:44:19 -0700166 grpc_closure *on_recv;
Craig Tiller3719f072015-06-12 17:19:51 -0700167 struct grpc_chttp2_outstanding_ping *next;
168 struct grpc_chttp2_outstanding_ping *prev;
Craig Tillerb084d902015-06-12 07:50:02 -0700169} grpc_chttp2_outstanding_ping;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700170
Craig Tiller45724b32015-09-22 10:42:19 -0700171typedef struct
172{
Craig Tillerd20efd22015-06-12 16:17:09 -0700173 /** data to write next write */
174 gpr_slice_buffer qbuf;
Craig Tillerd20efd22015-06-12 16:17:09 -0700175
176 /** window available for us to send to peer */
Craig Tiller6a6b36c2015-09-10 16:00:22 -0700177 gpr_int64 outgoing_window;
Craig Tiller3719f072015-06-12 17:19:51 -0700178 /** window available for peer to send to us - updated after parse */
179 gpr_uint32 incoming_window;
Craig Tillerd20efd22015-06-12 16:17:09 -0700180 /** how much window would we like to have for incoming_window */
181 gpr_uint32 connection_window_target;
182
Craig Tiller1064f8b2015-06-25 13:52:57 -0700183 /** have we seen a goaway */
184 gpr_uint8 seen_goaway;
Craig Tiller9188d7a2015-07-05 12:44:37 -0700185 /** have we sent a goaway */
186 gpr_uint8 sent_goaway;
Craig Tiller1064f8b2015-06-25 13:52:57 -0700187
Craig Tiller3719f072015-06-12 17:19:51 -0700188 /** is this transport a client? */
189 gpr_uint8 is_client;
Craig Tillerd20efd22015-06-12 16:17:09 -0700190 /** are the local settings dirty and need to be sent? */
191 gpr_uint8 dirtied_local_settings;
192 /** have local settings been sent? */
193 gpr_uint8 sent_local_settings;
194 /** bitmask of setting indexes to send out */
Craig Tiller4aa71a12015-06-15 13:00:55 -0700195 gpr_uint32 force_send_settings;
Craig Tillerd20efd22015-06-12 16:17:09 -0700196 /** settings values */
Craig Tillerab630732015-06-25 11:20:01 -0700197 gpr_uint32 settings[GRPC_NUM_SETTING_SETS][GRPC_CHTTP2_NUM_SETTINGS];
Craig Tillerd20efd22015-06-12 16:17:09 -0700198
Craig Tiller606d8742015-06-15 06:58:50 -0700199 /** what is the next stream id to be allocated by this peer?
200 copied to next_stream_id in parsing when parsing commences */
201 gpr_uint32 next_stream_id;
202
Craig Tillerd20efd22015-06-12 16:17:09 -0700203 /** last received stream id */
204 gpr_uint32 last_incoming_stream_id;
Craig Tiller3719f072015-06-12 17:19:51 -0700205
206 /** pings awaiting responses */
207 grpc_chttp2_outstanding_ping pings;
Craig Tiller606d8742015-06-15 06:58:50 -0700208 /** next payload for an outgoing ping */
209 gpr_uint64 ping_counter;
210
211 /** concurrent stream count: updated when not parsing,
212 so this is a strict over-estimation on the client */
213 gpr_uint32 concurrent_stream_count;
Craig Tillerd20efd22015-06-12 16:17:09 -0700214} grpc_chttp2_transport_global;
215
Craig Tiller45724b32015-09-22 10:42:19 -0700216typedef struct
217{
Craig Tillerd20efd22015-06-12 16:17:09 -0700218 /** data to write now */
219 gpr_slice_buffer outbuf;
220 /** hpack encoding */
221 grpc_chttp2_hpack_compressor hpack_compressor;
Craig Tiller285b8822015-06-17 15:58:13 -0700222 /** is this a client? */
223 gpr_uint8 is_client;
Craig Tillerb0298592015-08-27 07:38:01 -0700224 /** callback for when writing is done */
Craig Tiller33825112015-09-18 07:44:19 -0700225 grpc_closure done_cb;
Craig Tillerd20efd22015-06-12 16:17:09 -0700226} grpc_chttp2_transport_writing;
227
Craig Tiller45724b32015-09-22 10:42:19 -0700228struct grpc_chttp2_transport_parsing
229{
Craig Tillerd20efd22015-06-12 16:17:09 -0700230 /** is this transport a client? (boolean) */
231 gpr_uint8 is_client;
232
233 /** were settings updated? */
234 gpr_uint8 settings_updated;
235 /** was a settings ack received? */
236 gpr_uint8 settings_ack_received;
237 /** was a goaway frame received? */
238 gpr_uint8 goaway_received;
239
Craig Tiller3719f072015-06-12 17:19:51 -0700240 /** initial window change */
241 gpr_int64 initial_window_update;
242
Craig Tillerd20efd22015-06-12 16:17:09 -0700243 /** data to write later - after parsing */
244 gpr_slice_buffer qbuf;
245 /* metadata object cache */
246 grpc_mdstr *str_grpc_timeout;
247 /** parser for headers */
248 grpc_chttp2_hpack_parser hpack_parser;
249 /** simple one shot parsers */
Craig Tiller45724b32015-09-22 10:42:19 -0700250 union
251 {
Craig Tillerd20efd22015-06-12 16:17:09 -0700252 grpc_chttp2_window_update_parser window_update;
253 grpc_chttp2_settings_parser settings;
254 grpc_chttp2_ping_parser ping;
255 grpc_chttp2_rst_stream_parser rst_stream;
256 } simple;
257 /** parser for goaway frames */
258 grpc_chttp2_goaway_parser goaway_parser;
259
260 /** window available for peer to send to us */
261 gpr_uint32 incoming_window;
Craig Tiller285b8822015-06-17 15:58:13 -0700262 gpr_uint32 incoming_window_delta;
Craig Tillerd20efd22015-06-12 16:17:09 -0700263
264 /** next stream id available at the time of beginning parsing */
265 gpr_uint32 next_stream_id;
266 gpr_uint32 last_incoming_stream_id;
267
268 /* deframing */
269 grpc_chttp2_deframe_transport_state deframe_state;
270 gpr_uint8 incoming_frame_type;
271 gpr_uint8 incoming_frame_flags;
272 gpr_uint8 header_eof;
273 gpr_uint32 expect_continuation_stream_id;
274 gpr_uint32 incoming_frame_size;
275 gpr_uint32 incoming_stream_id;
276
277 /* active parser */
278 void *parser_data;
279 grpc_chttp2_stream_parsing *incoming_stream;
Craig Tiller1be70cc2015-09-22 10:45:28 -0700280 grpc_chttp2_parse_error (*parser) (grpc_exec_ctx * exec_ctx, void *parser_user_data, grpc_chttp2_transport_parsing * transport_parsing, grpc_chttp2_stream_parsing * stream_parsing, gpr_slice slice, int is_last);
Craig Tillerd20efd22015-06-12 16:17:09 -0700281
282 /* received settings */
283 gpr_uint32 settings[GRPC_CHTTP2_NUM_SETTINGS];
284
285 /* goaway data */
286 grpc_status_code goaway_error;
287 gpr_uint32 goaway_last_stream_index;
288 gpr_slice goaway_text;
Craig Tiller3719f072015-06-12 17:19:51 -0700289
Craig Tiller6a6b36c2015-09-10 16:00:22 -0700290 gpr_int64 outgoing_window_update;
Craig Tiller3719f072015-06-12 17:19:51 -0700291
292 /** pings awaiting responses */
293 grpc_chttp2_outstanding_ping pings;
Craig Tillerd20efd22015-06-12 16:17:09 -0700294};
295
Craig Tiller45724b32015-09-22 10:42:19 -0700296struct grpc_chttp2_transport
297{
298 grpc_transport base; /* must be first */
Craig Tiller9b8671c2015-06-12 07:41:54 -0700299 grpc_endpoint *ep;
300 grpc_mdctx *metadata_context;
301 gpr_refcount refs;
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700302 char *peer_string;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700303
Craig Tiller9f80fcf2015-08-28 08:22:48 -0700304 /** when this drops to zero it's safe to shutdown the endpoint */
305 gpr_refcount shutdown_ep_refs;
306
Craig Tiller9b8671c2015-06-12 07:41:54 -0700307 gpr_mu mu;
Craig Tiller606d8742015-06-15 06:58:50 -0700308
309 /** is the transport destroying itself? */
310 gpr_uint8 destroying;
311 /** has the upper layer closed the transport? */
312 gpr_uint8 closed;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700313
Craig Tillerd20efd22015-06-12 16:17:09 -0700314 /** is a thread currently writing */
315 gpr_uint8 writing_active;
Craig Tiller606d8742015-06-15 06:58:50 -0700316 /** is a thread currently parsing */
317 gpr_uint8 parsing_active;
Craig Tillerd20efd22015-06-12 16:17:09 -0700318
Craig Tiller606d8742015-06-15 06:58:50 -0700319 /** is there a read request to the endpoint outstanding? */
320 gpr_uint8 endpoint_reading;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700321
Craig Tiller606d8742015-06-15 06:58:50 -0700322 /** various lists of streams */
Craig Tillerb084d902015-06-12 07:50:02 -0700323 grpc_chttp2_stream_list lists[STREAM_LIST_COUNT];
Craig Tiller9b8671c2015-06-12 07:41:54 -0700324
Craig Tiller606d8742015-06-15 06:58:50 -0700325 /** global state for reading/writing */
Craig Tillerd20efd22015-06-12 16:17:09 -0700326 grpc_chttp2_transport_global global;
Craig Tiller606d8742015-06-15 06:58:50 -0700327 /** state only accessible by the chain of execution that
328 set writing_active=1 */
Craig Tillerd20efd22015-06-12 16:17:09 -0700329 grpc_chttp2_transport_writing writing;
Craig Tiller606d8742015-06-15 06:58:50 -0700330 /** state only accessible by the chain of execution that
331 set parsing_active=1 */
Craig Tillerd20efd22015-06-12 16:17:09 -0700332 grpc_chttp2_transport_parsing parsing;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700333
Craig Tiller606d8742015-06-15 06:58:50 -0700334 /** maps stream id to grpc_chttp2_stream objects;
335 owned by the parsing thread when parsing */
336 grpc_chttp2_stream_map parsing_stream_map;
337
338 /** streams created by the client (possibly during parsing);
339 merged with parsing_stream_map during unlock when no
340 parsing is occurring */
341 grpc_chttp2_stream_map new_stream_map;
342
Craig Tillerd20efd22015-06-12 16:17:09 -0700343 /** closure to execute writing */
Craig Tiller33825112015-09-18 07:44:19 -0700344 grpc_closure writing_action;
Craig Tillerb0298592015-08-27 07:38:01 -0700345 /** closure to finish reading from the endpoint */
Craig Tiller33825112015-09-18 07:44:19 -0700346 grpc_closure recv_data;
Craig Tillerb0298592015-08-27 07:38:01 -0700347
348 /** incoming read bytes */
349 gpr_slice_buffer read_buffer;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700350
Craig Tiller4aa71a12015-06-15 13:00:55 -0700351 /** address to place a newly accepted stream - set and unset by
Craig Tiller606d8742015-06-15 06:58:50 -0700352 grpc_chttp2_parsing_accept_stream; used by init_stream to
353 publish the accepted server stream */
354 grpc_chttp2_stream **accepting_stream;
355
Craig Tiller45724b32015-09-22 10:42:19 -0700356 struct
357 {
Craig Tiller1064f8b2015-06-25 13:52:57 -0700358 /* accept stream callback */
Craig Tiller45724b32015-09-22 10:42:19 -0700359 void (*accept_stream) (void *user_data, grpc_transport * transport, const void *server_data);
Craig Tiller1064f8b2015-06-25 13:52:57 -0700360 void *accept_stream_user_data;
361
362 /** connectivity tracking */
Craig Tiller08a1cf82015-06-29 09:37:52 -0700363 grpc_connectivity_state_tracker state_tracker;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700364 } channel_callback;
365};
366
Craig Tiller45724b32015-09-22 10:42:19 -0700367typedef struct
368{
Craig Tillerd20efd22015-06-12 16:17:09 -0700369 /** HTTP2 stream id for this stream, or zero if one has not been assigned */
Craig Tiller9b8671c2015-06-12 07:41:54 -0700370 gpr_uint32 id;
371
Craig Tiller33825112015-09-18 07:44:19 -0700372 grpc_closure *send_done_closure;
373 grpc_closure *recv_done_closure;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700374
Craig Tillerd20efd22015-06-12 16:17:09 -0700375 /** window available for us to send to peer */
376 gpr_int64 outgoing_window;
Craig Tiller27166a62015-07-05 21:08:33 -0700377 /** The number of bytes the upper layers have offered to receive.
378 As the upper layer offers more bytes, this value increases.
379 As bytes are read, this value decreases. */
380 gpr_uint32 max_recv_bytes;
381 /** The number of bytes the upper layer has offered to read but we have
382 not yet announced to HTTP2 flow control.
383 As the upper layers offer to read more bytes, this value increases.
384 As we advertise incoming flow control window, this value decreases. */
385 gpr_uint32 unannounced_incoming_window;
386 /** The number of bytes of HTTP2 flow control we have advertised.
387 As we advertise incoming flow control window, this value increases.
388 As bytes are read, this value decreases.
389 Updated after parse. */
Craig Tiller3719f072015-06-12 17:19:51 -0700390 gpr_uint32 incoming_window;
Craig Tillerd20efd22015-06-12 16:17:09 -0700391 /** stream ops the transport user would like to send */
392 grpc_stream_op_buffer *outgoing_sopb;
393 /** when the application requests writes be closed, the write_closed is
394 'queued'; when the close is flow controlled into the send path, we are
395 'sending' it; when the write has been performed it is 'sent' */
396 grpc_chttp2_write_state write_state;
397 /** is this stream closed (boolean) */
398 gpr_uint8 read_closed;
Craig Tiller5dc3b302015-06-15 16:06:50 -0700399 /** has this stream been cancelled? (boolean) */
400 gpr_uint8 cancelled;
Craig Tillercec9eb92015-06-17 17:16:48 -0700401 grpc_status_code cancelled_status;
402 /** have we told the upper layer that this stream is cancelled? */
403 gpr_uint8 published_cancelled;
Craig Tiller5dc3b302015-06-15 16:06:50 -0700404 /** is this stream in the stream map? (boolean) */
405 gpr_uint8 in_stream_map;
Craig Tiller0c23f292015-08-03 10:18:05 -0700406 /** bitmask of GRPC_CHTTP2_WRITING_xxx above */
Craig Tiller994c2622015-07-23 14:00:58 -0700407 gpr_uint8 writing_now;
Craig Tiller45ce9272015-07-31 11:22:35 -0700408 /** has anything been written to this stream? */
409 gpr_uint8 written_anything;
Craig Tiller606d8742015-06-15 06:58:50 -0700410
411 /** stream state already published to the upper layer */
412 grpc_stream_state published_state;
413 /** address to publish next stream state to */
414 grpc_stream_state *publish_state;
415 /** pointer to sop buffer to fill in with new stream ops */
Craig Tiller6905b7c2015-06-16 15:33:33 -0700416 grpc_stream_op_buffer *publish_sopb;
417 grpc_stream_op_buffer incoming_sopb;
Craig Tiller5dc3b302015-06-15 16:06:50 -0700418
419 /** incoming metadata */
420 grpc_chttp2_incoming_metadata_buffer incoming_metadata;
Craig Tillerb787c502015-06-15 16:14:52 -0700421 grpc_chttp2_incoming_metadata_live_op_buffer outstanding_metadata;
Craig Tillerd20efd22015-06-12 16:17:09 -0700422} grpc_chttp2_stream_global;
423
Craig Tiller45724b32015-09-22 10:42:19 -0700424typedef struct
425{
Craig Tillerd20efd22015-06-12 16:17:09 -0700426 /** HTTP2 stream id for this stream, or zero if one has not been assigned */
427 gpr_uint32 id;
428 /** sops that have passed flow control to be written */
429 grpc_stream_op_buffer sopb;
430 /** how strongly should we indicate closure with the next write */
431 grpc_chttp2_send_closed send_closed;
Craig Tiller86316522015-07-15 11:35:07 -0700432 /** how much window should we announce? */
433 gpr_uint32 announce_window;
Craig Tillerd20efd22015-06-12 16:17:09 -0700434} grpc_chttp2_stream_writing;
435
Craig Tiller45724b32015-09-22 10:42:19 -0700436struct grpc_chttp2_stream_parsing
437{
Craig Tillerd20efd22015-06-12 16:17:09 -0700438 /** HTTP2 stream id for this stream, or zero if one has not been assigned */
439 gpr_uint32 id;
440 /** has this stream received a close */
441 gpr_uint8 received_close;
Craig Tiller3719f072015-06-12 17:19:51 -0700442 /** saw a rst_stream */
443 gpr_uint8 saw_rst_stream;
Craig Tiller606d8742015-06-15 06:58:50 -0700444 /** incoming_window has been reduced by this much during parsing */
445 gpr_uint32 incoming_window_delta;
Craig Tillerd20efd22015-06-12 16:17:09 -0700446 /** window available for peer to send to us */
447 gpr_uint32 incoming_window;
448 /** parsing state for data frames */
449 grpc_chttp2_data_parser data_parser;
Craig Tiller3719f072015-06-12 17:19:51 -0700450 /** reason give to rst_stream */
451 gpr_uint32 rst_stream_reason;
452 /* amount of window given */
453 gpr_uint64 outgoing_window_update;
Craig Tiller9b8671c2015-06-12 07:41:54 -0700454
Craig Tiller5dc3b302015-06-15 16:06:50 -0700455 /** incoming metadata */
456 grpc_chttp2_incoming_metadata_buffer incoming_metadata;
Craig Tillerd20efd22015-06-12 16:17:09 -0700457};
458
Craig Tiller45724b32015-09-22 10:42:19 -0700459struct grpc_chttp2_stream
460{
Craig Tillerd20efd22015-06-12 16:17:09 -0700461 grpc_chttp2_stream_global global;
462 grpc_chttp2_stream_writing writing;
Craig Tiller606d8742015-06-15 06:58:50 -0700463 grpc_chttp2_stream_parsing parsing;
Craig Tillerd20efd22015-06-12 16:17:09 -0700464
465 grpc_chttp2_stream_link links[STREAM_LIST_COUNT];
466 gpr_uint8 included[STREAM_LIST_COUNT];
Craig Tiller9b8671c2015-06-12 07:41:54 -0700467};
468
Craig Tillerd20efd22015-06-12 16:17:09 -0700469/** Transport writing call flow:
Craig Tiller4aa71a12015-06-15 13:00:55 -0700470 chttp2_transport.c calls grpc_chttp2_unlocking_check_writes to see if writes
471 are required;
472 if they are, chttp2_transport.c calls grpc_chttp2_perform_writes to do the
473 writes.
474 Once writes have been completed (meaning another write could potentially be
475 started),
476 grpc_chttp2_terminate_writing is called. This will call
477 grpc_chttp2_cleanup_writing, at which
Craig Tillerd20efd22015-06-12 16:17:09 -0700478 point the write phase is complete. */
479
Craig Tiller3208e392015-06-12 08:17:02 -0700480/** Someone is unlocking the transport mutex: check to see if writes
481 are required, and schedule them if so */
Craig Tiller45724b32015-09-22 10:42:19 -0700482int grpc_chttp2_unlocking_check_writes (grpc_chttp2_transport_global * global, grpc_chttp2_transport_writing * writing);
Craig Tiller1be70cc2015-09-22 10:45:28 -0700483void grpc_chttp2_perform_writes (grpc_exec_ctx * exec_ctx, grpc_chttp2_transport_writing * transport_writing, grpc_endpoint * endpoint);
484void grpc_chttp2_terminate_writing (grpc_exec_ctx * exec_ctx, void *transport_writing, int success);
485void grpc_chttp2_cleanup_writing (grpc_exec_ctx * exec_ctx, grpc_chttp2_transport_global * global, grpc_chttp2_transport_writing * writing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700486
Craig Tiller45724b32015-09-22 10:42:19 -0700487void grpc_chttp2_prepare_to_read (grpc_chttp2_transport_global * global, grpc_chttp2_transport_parsing * parsing);
Craig Tillerab630732015-06-25 11:20:01 -0700488/** Process one slice of incoming data; return 1 if the connection is still
489 viable after reading, or 0 if the connection should be torn down */
Craig Tiller1be70cc2015-09-22 10:45:28 -0700490int grpc_chttp2_perform_read (grpc_exec_ctx * exec_ctx, grpc_chttp2_transport_parsing * transport_parsing, gpr_slice slice);
491void grpc_chttp2_publish_reads (grpc_exec_ctx * exec_ctx, grpc_chttp2_transport_global * global, grpc_chttp2_transport_parsing * parsing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700492
493/** Get a writable stream
Craig Tillerab630732015-06-25 11:20:01 -0700494 returns non-zero if there was a stream available */
Craig Tiller45724b32015-09-22 10:42:19 -0700495void grpc_chttp2_list_add_writable_stream (grpc_chttp2_transport_global * transport_global, grpc_chttp2_stream_global * stream_global);
496void grpc_chttp2_list_add_first_writable_stream (grpc_chttp2_transport_global * transport_global, grpc_chttp2_stream_global * stream_global);
497int grpc_chttp2_list_pop_writable_stream (grpc_chttp2_transport_global * transport_global, grpc_chttp2_transport_writing * transport_writing, grpc_chttp2_stream_global ** stream_global, grpc_chttp2_stream_writing ** stream_writing);
498void grpc_chttp2_list_remove_writable_stream (grpc_chttp2_transport_global * transport_global, grpc_chttp2_stream_global * stream_global);
Craig Tillerd20efd22015-06-12 16:17:09 -0700499
Craig Tiller45724b32015-09-22 10:42:19 -0700500void grpc_chttp2_list_add_incoming_window_updated (grpc_chttp2_transport_global * transport_global, grpc_chttp2_stream_global * stream_global);
501int grpc_chttp2_list_pop_incoming_window_updated (grpc_chttp2_transport_global * transport_global, grpc_chttp2_transport_parsing * transport_parsing, grpc_chttp2_stream_global ** stream_global, grpc_chttp2_stream_parsing ** stream_parsing);
502void grpc_chttp2_list_remove_incoming_window_updated (grpc_chttp2_transport_global * transport_global, grpc_chttp2_stream_global * stream_global);
Craig Tillercf1e3192015-06-16 14:28:22 -0700503
Craig Tiller45724b32015-09-22 10:42:19 -0700504void grpc_chttp2_list_add_writing_stream (grpc_chttp2_transport_writing * transport_writing, grpc_chttp2_stream_writing * stream_writing);
505int grpc_chttp2_list_have_writing_streams (grpc_chttp2_transport_writing * transport_writing);
506int grpc_chttp2_list_pop_writing_stream (grpc_chttp2_transport_writing * transport_writing, grpc_chttp2_stream_writing ** stream_writing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700507
Craig Tiller45724b32015-09-22 10:42:19 -0700508void grpc_chttp2_list_add_written_stream (grpc_chttp2_transport_writing * transport_writing, grpc_chttp2_stream_writing * stream_writing);
509int grpc_chttp2_list_pop_written_stream (grpc_chttp2_transport_global * transport_global, grpc_chttp2_transport_writing * transport_writing, grpc_chttp2_stream_global ** stream_global, grpc_chttp2_stream_writing ** stream_writing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700510
Craig Tiller45724b32015-09-22 10:42:19 -0700511void grpc_chttp2_list_add_parsing_seen_stream (grpc_chttp2_transport_parsing * transport_parsing, grpc_chttp2_stream_parsing * stream_parsing);
512int grpc_chttp2_list_pop_parsing_seen_stream (grpc_chttp2_transport_global * transport_global, grpc_chttp2_transport_parsing * transport_parsing, grpc_chttp2_stream_global ** stream_global, grpc_chttp2_stream_parsing ** stream_parsing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700513
Craig Tiller45724b32015-09-22 10:42:19 -0700514void grpc_chttp2_list_add_waiting_for_concurrency (grpc_chttp2_transport_global * transport_global, grpc_chttp2_stream_global * stream_global);
515int grpc_chttp2_list_pop_waiting_for_concurrency (grpc_chttp2_transport_global * transport_global, grpc_chttp2_stream_global ** stream_global);
Craig Tiller5dc3b302015-06-15 16:06:50 -0700516
Craig Tiller45724b32015-09-22 10:42:19 -0700517void grpc_chttp2_list_add_closed_waiting_for_parsing (grpc_chttp2_transport_global * transport_global, grpc_chttp2_stream_global * stream_global);
518int grpc_chttp2_list_pop_closed_waiting_for_parsing (grpc_chttp2_transport_global * transport_global, grpc_chttp2_stream_global ** stream_global);
Craig Tiller5dc3b302015-06-15 16:06:50 -0700519
Craig Tiller45724b32015-09-22 10:42:19 -0700520void grpc_chttp2_list_add_cancelled_waiting_for_writing (grpc_chttp2_transport_global * transport_global, grpc_chttp2_stream_global * stream_global);
521int grpc_chttp2_list_pop_cancelled_waiting_for_writing (grpc_chttp2_transport_global * transport_global, grpc_chttp2_stream_global ** stream_global);
Craig Tiller17be5dc2015-07-01 10:36:27 -0700522
Craig Tiller45724b32015-09-22 10:42:19 -0700523void grpc_chttp2_list_add_read_write_state_changed (grpc_chttp2_transport_global * transport_global, grpc_chttp2_stream_global * stream_global);
524int grpc_chttp2_list_pop_read_write_state_changed (grpc_chttp2_transport_global * transport_global, grpc_chttp2_stream_global ** stream_global);
Craig Tiller6459db42015-06-15 17:11:45 -0700525
Craig Tiller45724b32015-09-22 10:42:19 -0700526grpc_chttp2_stream_parsing *grpc_chttp2_parsing_lookup_stream (grpc_chttp2_transport_parsing * transport_parsing, gpr_uint32 id);
527grpc_chttp2_stream_parsing *grpc_chttp2_parsing_accept_stream (grpc_chttp2_transport_parsing * transport_parsing, gpr_uint32 id);
Craig Tillerd20efd22015-06-12 16:17:09 -0700528
Craig Tiller1be70cc2015-09-22 10:45:28 -0700529void grpc_chttp2_add_incoming_goaway (grpc_exec_ctx * exec_ctx, grpc_chttp2_transport_global * transport_global, gpr_uint32 goaway_error, gpr_slice goaway_text);
Craig Tiller4aa71a12015-06-15 13:00:55 -0700530
Craig Tiller45724b32015-09-22 10:42:19 -0700531void grpc_chttp2_register_stream (grpc_chttp2_transport * t, grpc_chttp2_stream * s);
Craig Tiller9188d7a2015-07-05 12:44:37 -0700532/* returns 1 if this is the last stream, 0 otherwise */
Craig Tiller45724b32015-09-22 10:42:19 -0700533int
534grpc_chttp2_unregister_stream (grpc_chttp2_transport * t, grpc_chttp2_stream * s)
535 GRPC_MUST_USE_RESULT;
536 int grpc_chttp2_has_streams (grpc_chttp2_transport * t);
537 void grpc_chttp2_for_all_streams (grpc_chttp2_transport_global * transport_global, void *user_data, void (*cb) (grpc_chttp2_transport_global * transport_global, void *user_data, grpc_chttp2_stream_global * stream_global));
Craig Tiller5dc3b302015-06-15 16:06:50 -0700538
Craig Tiller45724b32015-09-22 10:42:19 -0700539 void grpc_chttp2_parsing_become_skip_parser (grpc_chttp2_transport_parsing * transport_parsing);
Craig Tiller66abdaa2015-06-17 08:00:39 -0700540
Craig Tillerd20efd22015-06-12 16:17:09 -0700541#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 -0700542#define GRPC_CHTTP2_CLIENT_CONNECT_STRLEN \
543 (sizeof(GRPC_CHTTP2_CLIENT_CONNECT_STRING) - 1)
Craig Tillerd20efd22015-06-12 16:17:09 -0700544
Craig Tiller45724b32015-09-22 10:42:19 -0700545 extern int grpc_http_trace;
546 extern int grpc_flowctl_trace;
Craig Tillerd20efd22015-06-12 16:17:09 -0700547
Craig Tillerab630732015-06-25 11:20:01 -0700548#define GRPC_CHTTP2_IF_TRACING(stmt) \
549 if (!(grpc_http_trace)) \
550 ; \
551 else \
Craig Tillerd20efd22015-06-12 16:17:09 -0700552 stmt
Craig Tiller3208e392015-06-12 08:17:02 -0700553
Craig Tiller32ca48c2015-09-10 11:47:15 -0700554#define GRPC_CHTTP2_FLOWCTL_TRACE_STREAM(reason, transport, context, var, \
555 delta) \
556 if (!(grpc_flowctl_trace)) { \
557 } else { \
558 grpc_chttp2_flowctl_trace(__FILE__, __LINE__, reason, #context, #var, \
559 transport->is_client, context->id, \
560 (gpr_int64)(context->var), (gpr_int64)(delta)); \
Craig Tiller285b8822015-06-17 15:58:13 -0700561 }
562
Craig Tiller32ca48c2015-09-10 11:47:15 -0700563#define GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT(reason, context, var, delta) \
564 if (!(grpc_flowctl_trace)) { \
565 } else { \
566 grpc_chttp2_flowctl_trace(__FILE__, __LINE__, reason, #context, #var, \
567 context->is_client, 0, \
568 (gpr_int64)(context->var), (gpr_int64)(delta)); \
Craig Tiller285b8822015-06-17 15:58:13 -0700569 }
570
Craig Tiller45724b32015-09-22 10:42:19 -0700571 void grpc_chttp2_flowctl_trace (const char *file, int line, const char *reason, const char *context, const char *var, int is_client, gpr_uint32 stream_id, gpr_int64 current_value, gpr_int64 delta);
Craig Tiller285b8822015-06-17 15:58:13 -0700572
Craig Tiller9b8671c2015-06-12 07:41:54 -0700573#endif