1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker * libwebsockets - small server side websockets and web server implementation
3*1c60b9acSAndroid Build Coastguard Worker *
4*1c60b9acSAndroid Build Coastguard Worker * Copyright (C) 2010 - 2019 Andy Green <[email protected]>
5*1c60b9acSAndroid Build Coastguard Worker *
6*1c60b9acSAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a copy
7*1c60b9acSAndroid Build Coastguard Worker * of this software and associated documentation files (the "Software"), to
8*1c60b9acSAndroid Build Coastguard Worker * deal in the Software without restriction, including without limitation the
9*1c60b9acSAndroid Build Coastguard Worker * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10*1c60b9acSAndroid Build Coastguard Worker * sell copies of the Software, and to permit persons to whom the Software is
11*1c60b9acSAndroid Build Coastguard Worker * furnished to do so, subject to the following conditions:
12*1c60b9acSAndroid Build Coastguard Worker *
13*1c60b9acSAndroid Build Coastguard Worker * The above copyright notice and this permission notice shall be included in
14*1c60b9acSAndroid Build Coastguard Worker * all copies or substantial portions of the Software.
15*1c60b9acSAndroid Build Coastguard Worker *
16*1c60b9acSAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*1c60b9acSAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*1c60b9acSAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19*1c60b9acSAndroid Build Coastguard Worker * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*1c60b9acSAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21*1c60b9acSAndroid Build Coastguard Worker * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22*1c60b9acSAndroid Build Coastguard Worker * IN THE SOFTWARE.
23*1c60b9acSAndroid Build Coastguard Worker */
24*1c60b9acSAndroid Build Coastguard Worker
25*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-core.h"
26*1c60b9acSAndroid Build Coastguard Worker
27*1c60b9acSAndroid Build Coastguard Worker /*
28*1c60b9acSAndroid Build Coastguard Worker * bitmap of control messages that are valid to receive for each http2 state
29*1c60b9acSAndroid Build Coastguard Worker */
30*1c60b9acSAndroid Build Coastguard Worker
31*1c60b9acSAndroid Build Coastguard Worker static const uint16_t http2_rx_validity[] = {
32*1c60b9acSAndroid Build Coastguard Worker /* LWS_H2S_IDLE */
33*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_SETTINGS) |
34*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_PRIORITY) |
35*1c60b9acSAndroid Build Coastguard Worker // (1 << LWS_H2_FRAME_TYPE_WINDOW_UPDATE)| /* ignore */
36*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_HEADERS) |
37*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_CONTINUATION),
38*1c60b9acSAndroid Build Coastguard Worker /* LWS_H2S_RESERVED_LOCAL */
39*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_SETTINGS) |
40*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_RST_STREAM) |
41*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_PRIORITY) |
42*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_WINDOW_UPDATE),
43*1c60b9acSAndroid Build Coastguard Worker /* LWS_H2S_RESERVED_REMOTE */
44*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_SETTINGS) |
45*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_HEADERS) |
46*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_CONTINUATION) |
47*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_RST_STREAM) |
48*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_PRIORITY),
49*1c60b9acSAndroid Build Coastguard Worker /* LWS_H2S_OPEN */
50*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_DATA) |
51*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_HEADERS) |
52*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_PRIORITY) |
53*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_RST_STREAM) |
54*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_SETTINGS) |
55*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_PUSH_PROMISE) |
56*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_PING) |
57*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_GOAWAY) |
58*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_WINDOW_UPDATE) |
59*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_CONTINUATION),
60*1c60b9acSAndroid Build Coastguard Worker /* LWS_H2S_HALF_CLOSED_REMOTE */
61*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_SETTINGS) |
62*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_WINDOW_UPDATE) |
63*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_PRIORITY) |
64*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_RST_STREAM),
65*1c60b9acSAndroid Build Coastguard Worker /* LWS_H2S_HALF_CLOSED_LOCAL */
66*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_DATA) |
67*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_HEADERS) |
68*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_PRIORITY) |
69*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_RST_STREAM) |
70*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_SETTINGS) |
71*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_PUSH_PROMISE) |
72*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_PING) |
73*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_GOAWAY) |
74*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_WINDOW_UPDATE) |
75*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_CONTINUATION),
76*1c60b9acSAndroid Build Coastguard Worker /* LWS_H2S_CLOSED */
77*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_SETTINGS) |
78*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_PRIORITY) |
79*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_WINDOW_UPDATE) |
80*1c60b9acSAndroid Build Coastguard Worker (1 << LWS_H2_FRAME_TYPE_RST_STREAM),
81*1c60b9acSAndroid Build Coastguard Worker };
82*1c60b9acSAndroid Build Coastguard Worker
83*1c60b9acSAndroid Build Coastguard Worker static const char *preface = "PRI * HTTP/2.0\x0d\x0a\x0d\x0aSM\x0d\x0a\x0d\x0a";
84*1c60b9acSAndroid Build Coastguard Worker
85*1c60b9acSAndroid Build Coastguard Worker static const char * const h2_state_names[] = {
86*1c60b9acSAndroid Build Coastguard Worker "LWS_H2S_IDLE",
87*1c60b9acSAndroid Build Coastguard Worker "LWS_H2S_RESERVED_LOCAL",
88*1c60b9acSAndroid Build Coastguard Worker "LWS_H2S_RESERVED_REMOTE",
89*1c60b9acSAndroid Build Coastguard Worker "LWS_H2S_OPEN",
90*1c60b9acSAndroid Build Coastguard Worker "LWS_H2S_HALF_CLOSED_REMOTE",
91*1c60b9acSAndroid Build Coastguard Worker "LWS_H2S_HALF_CLOSED_LOCAL",
92*1c60b9acSAndroid Build Coastguard Worker "LWS_H2S_CLOSED",
93*1c60b9acSAndroid Build Coastguard Worker };
94*1c60b9acSAndroid Build Coastguard Worker
95*1c60b9acSAndroid Build Coastguard Worker #if 0
96*1c60b9acSAndroid Build Coastguard Worker static const char * const h2_setting_names[] = {
97*1c60b9acSAndroid Build Coastguard Worker "",
98*1c60b9acSAndroid Build Coastguard Worker "H2SET_HEADER_TABLE_SIZE",
99*1c60b9acSAndroid Build Coastguard Worker "H2SET_ENABLE_PUSH",
100*1c60b9acSAndroid Build Coastguard Worker "H2SET_MAX_CONCURRENT_STREAMS",
101*1c60b9acSAndroid Build Coastguard Worker "H2SET_INITIAL_WINDOW_SIZE",
102*1c60b9acSAndroid Build Coastguard Worker "H2SET_MAX_FRAME_SIZE",
103*1c60b9acSAndroid Build Coastguard Worker "H2SET_MAX_HEADER_LIST_SIZE",
104*1c60b9acSAndroid Build Coastguard Worker "reserved",
105*1c60b9acSAndroid Build Coastguard Worker "H2SET_ENABLE_CONNECT_PROTOCOL"
106*1c60b9acSAndroid Build Coastguard Worker };
107*1c60b9acSAndroid Build Coastguard Worker
108*1c60b9acSAndroid Build Coastguard Worker void
109*1c60b9acSAndroid Build Coastguard Worker lws_h2_dump_settings(struct http2_settings *set)
110*1c60b9acSAndroid Build Coastguard Worker {
111*1c60b9acSAndroid Build Coastguard Worker int n;
112*1c60b9acSAndroid Build Coastguard Worker
113*1c60b9acSAndroid Build Coastguard Worker for (n = 1; n < H2SET_COUNT; n++)
114*1c60b9acSAndroid Build Coastguard Worker lwsl_notice(" %30s: %10d\n", h2_setting_names[n], set->s[n]);
115*1c60b9acSAndroid Build Coastguard Worker }
116*1c60b9acSAndroid Build Coastguard Worker #else
117*1c60b9acSAndroid Build Coastguard Worker void
lws_h2_dump_settings(struct http2_settings * set)118*1c60b9acSAndroid Build Coastguard Worker lws_h2_dump_settings(struct http2_settings *set)
119*1c60b9acSAndroid Build Coastguard Worker {
120*1c60b9acSAndroid Build Coastguard Worker }
121*1c60b9acSAndroid Build Coastguard Worker #endif
122*1c60b9acSAndroid Build Coastguard Worker
123*1c60b9acSAndroid Build Coastguard Worker struct lws_h2_protocol_send *
lws_h2_new_pps(enum lws_h2_protocol_send_type type)124*1c60b9acSAndroid Build Coastguard Worker lws_h2_new_pps(enum lws_h2_protocol_send_type type)
125*1c60b9acSAndroid Build Coastguard Worker {
126*1c60b9acSAndroid Build Coastguard Worker struct lws_h2_protocol_send *pps = lws_malloc(sizeof(*pps), "pps");
127*1c60b9acSAndroid Build Coastguard Worker
128*1c60b9acSAndroid Build Coastguard Worker if (pps)
129*1c60b9acSAndroid Build Coastguard Worker pps->type = type;
130*1c60b9acSAndroid Build Coastguard Worker
131*1c60b9acSAndroid Build Coastguard Worker return pps;
132*1c60b9acSAndroid Build Coastguard Worker }
133*1c60b9acSAndroid Build Coastguard Worker
lws_h2_init(struct lws * wsi)134*1c60b9acSAndroid Build Coastguard Worker void lws_h2_init(struct lws *wsi)
135*1c60b9acSAndroid Build Coastguard Worker {
136*1c60b9acSAndroid Build Coastguard Worker wsi->h2.h2n->our_set = wsi->a.vhost->h2.set;
137*1c60b9acSAndroid Build Coastguard Worker wsi->h2.h2n->peer_set = lws_h2_defaults;
138*1c60b9acSAndroid Build Coastguard Worker }
139*1c60b9acSAndroid Build Coastguard Worker
140*1c60b9acSAndroid Build Coastguard Worker void
lws_h2_state(struct lws * wsi,enum lws_h2_states s)141*1c60b9acSAndroid Build Coastguard Worker lws_h2_state(struct lws *wsi, enum lws_h2_states s)
142*1c60b9acSAndroid Build Coastguard Worker {
143*1c60b9acSAndroid Build Coastguard Worker if (!wsi)
144*1c60b9acSAndroid Build Coastguard Worker return;
145*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: %s: state %s -> %s\n", __func__, lws_wsi_tag(wsi),
146*1c60b9acSAndroid Build Coastguard Worker h2_state_names[wsi->h2.h2_state],
147*1c60b9acSAndroid Build Coastguard Worker h2_state_names[s]);
148*1c60b9acSAndroid Build Coastguard Worker
149*1c60b9acSAndroid Build Coastguard Worker (void)h2_state_names;
150*1c60b9acSAndroid Build Coastguard Worker wsi->h2.h2_state = (uint8_t)s;
151*1c60b9acSAndroid Build Coastguard Worker }
152*1c60b9acSAndroid Build Coastguard Worker
153*1c60b9acSAndroid Build Coastguard Worker int
lws_h2_update_peer_txcredit(struct lws * wsi,unsigned int sid,int bump)154*1c60b9acSAndroid Build Coastguard Worker lws_h2_update_peer_txcredit(struct lws *wsi, unsigned int sid, int bump)
155*1c60b9acSAndroid Build Coastguard Worker {
156*1c60b9acSAndroid Build Coastguard Worker struct lws *nwsi = lws_get_network_wsi(wsi);
157*1c60b9acSAndroid Build Coastguard Worker struct lws_h2_protocol_send *pps;
158*1c60b9acSAndroid Build Coastguard Worker
159*1c60b9acSAndroid Build Coastguard Worker assert(wsi);
160*1c60b9acSAndroid Build Coastguard Worker
161*1c60b9acSAndroid Build Coastguard Worker if (!bump)
162*1c60b9acSAndroid Build Coastguard Worker return 0;
163*1c60b9acSAndroid Build Coastguard Worker
164*1c60b9acSAndroid Build Coastguard Worker if (sid == (unsigned int)-1)
165*1c60b9acSAndroid Build Coastguard Worker sid = wsi->mux.my_sid;
166*1c60b9acSAndroid Build Coastguard Worker
167*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: sid %d: bump %d -> %d\n", __func__, sid, bump,
168*1c60b9acSAndroid Build Coastguard Worker (int)wsi->txc.peer_tx_cr_est + bump);
169*1c60b9acSAndroid Build Coastguard Worker
170*1c60b9acSAndroid Build Coastguard Worker pps = lws_h2_new_pps(LWS_H2_PPS_UPDATE_WINDOW);
171*1c60b9acSAndroid Build Coastguard Worker if (!pps)
172*1c60b9acSAndroid Build Coastguard Worker return 1;
173*1c60b9acSAndroid Build Coastguard Worker
174*1c60b9acSAndroid Build Coastguard Worker pps->u.update_window.sid = (unsigned int)sid;
175*1c60b9acSAndroid Build Coastguard Worker pps->u.update_window.credit = (unsigned int)bump;
176*1c60b9acSAndroid Build Coastguard Worker wsi->txc.peer_tx_cr_est += bump;
177*1c60b9acSAndroid Build Coastguard Worker
178*1c60b9acSAndroid Build Coastguard Worker lws_wsi_txc_describe(&wsi->txc, __func__, wsi->mux.my_sid);
179*1c60b9acSAndroid Build Coastguard Worker
180*1c60b9acSAndroid Build Coastguard Worker lws_pps_schedule(wsi, pps);
181*1c60b9acSAndroid Build Coastguard Worker
182*1c60b9acSAndroid Build Coastguard Worker pps = lws_h2_new_pps(LWS_H2_PPS_UPDATE_WINDOW);
183*1c60b9acSAndroid Build Coastguard Worker if (!pps)
184*1c60b9acSAndroid Build Coastguard Worker return 1;
185*1c60b9acSAndroid Build Coastguard Worker
186*1c60b9acSAndroid Build Coastguard Worker pps->u.update_window.sid = 0;
187*1c60b9acSAndroid Build Coastguard Worker pps->u.update_window.credit = (unsigned int)bump;
188*1c60b9acSAndroid Build Coastguard Worker nwsi->txc.peer_tx_cr_est += bump;
189*1c60b9acSAndroid Build Coastguard Worker
190*1c60b9acSAndroid Build Coastguard Worker lws_wsi_txc_describe(&nwsi->txc, __func__, nwsi->mux.my_sid);
191*1c60b9acSAndroid Build Coastguard Worker
192*1c60b9acSAndroid Build Coastguard Worker lws_pps_schedule(nwsi, pps);
193*1c60b9acSAndroid Build Coastguard Worker
194*1c60b9acSAndroid Build Coastguard Worker return 0;
195*1c60b9acSAndroid Build Coastguard Worker }
196*1c60b9acSAndroid Build Coastguard Worker
197*1c60b9acSAndroid Build Coastguard Worker int
lws_h2_get_peer_txcredit_estimate(struct lws * wsi)198*1c60b9acSAndroid Build Coastguard Worker lws_h2_get_peer_txcredit_estimate(struct lws *wsi)
199*1c60b9acSAndroid Build Coastguard Worker {
200*1c60b9acSAndroid Build Coastguard Worker lws_wsi_txc_describe(&wsi->txc, __func__, wsi->mux.my_sid);
201*1c60b9acSAndroid Build Coastguard Worker return (int)wsi->txc.peer_tx_cr_est;
202*1c60b9acSAndroid Build Coastguard Worker }
203*1c60b9acSAndroid Build Coastguard Worker
204*1c60b9acSAndroid Build Coastguard Worker static int
lws_h2_update_peer_txcredit_thresh(struct lws * wsi,unsigned int sid,int threshold,int bump)205*1c60b9acSAndroid Build Coastguard Worker lws_h2_update_peer_txcredit_thresh(struct lws *wsi, unsigned int sid, int threshold, int bump)
206*1c60b9acSAndroid Build Coastguard Worker {
207*1c60b9acSAndroid Build Coastguard Worker if (wsi->txc.peer_tx_cr_est > threshold)
208*1c60b9acSAndroid Build Coastguard Worker return 0;
209*1c60b9acSAndroid Build Coastguard Worker
210*1c60b9acSAndroid Build Coastguard Worker return lws_h2_update_peer_txcredit(wsi, sid, bump);
211*1c60b9acSAndroid Build Coastguard Worker }
212*1c60b9acSAndroid Build Coastguard Worker
213*1c60b9acSAndroid Build Coastguard Worker /* cx + vh lock */
214*1c60b9acSAndroid Build Coastguard Worker
215*1c60b9acSAndroid Build Coastguard Worker static struct lws *
__lws_wsi_server_new(struct lws_vhost * vh,struct lws * parent_wsi,unsigned int sid)216*1c60b9acSAndroid Build Coastguard Worker __lws_wsi_server_new(struct lws_vhost *vh, struct lws *parent_wsi,
217*1c60b9acSAndroid Build Coastguard Worker unsigned int sid)
218*1c60b9acSAndroid Build Coastguard Worker {
219*1c60b9acSAndroid Build Coastguard Worker struct lws *nwsi = lws_get_network_wsi(parent_wsi);
220*1c60b9acSAndroid Build Coastguard Worker struct lws_h2_netconn *h2n = nwsi->h2.h2n;
221*1c60b9acSAndroid Build Coastguard Worker char tmp[50], tmp1[50];
222*1c60b9acSAndroid Build Coastguard Worker unsigned int n, b = 0;
223*1c60b9acSAndroid Build Coastguard Worker struct lws *wsi;
224*1c60b9acSAndroid Build Coastguard Worker const char *p;
225*1c60b9acSAndroid Build Coastguard Worker
226*1c60b9acSAndroid Build Coastguard Worker lws_context_assert_lock_held(vh->context);
227*1c60b9acSAndroid Build Coastguard Worker lws_vhost_assert_lock_held(vh);
228*1c60b9acSAndroid Build Coastguard Worker
229*1c60b9acSAndroid Build Coastguard Worker /*
230*1c60b9acSAndroid Build Coastguard Worker * The identifier of a newly established stream MUST be numerically
231*1c60b9acSAndroid Build Coastguard Worker * greater than all streams that the initiating endpoint has opened or
232*1c60b9acSAndroid Build Coastguard Worker * reserved. This governs streams that are opened using a HEADERS frame
233*1c60b9acSAndroid Build Coastguard Worker * and streams that are reserved using PUSH_PROMISE. An endpoint that
234*1c60b9acSAndroid Build Coastguard Worker * receives an unexpected stream identifier MUST respond with a
235*1c60b9acSAndroid Build Coastguard Worker * connection error (Section 5.4.1) of type PROTOCOL_ERROR.
236*1c60b9acSAndroid Build Coastguard Worker */
237*1c60b9acSAndroid Build Coastguard Worker if (sid <= h2n->highest_sid_opened) {
238*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: tried to open lower sid %d (%d)\n", __func__,
239*1c60b9acSAndroid Build Coastguard Worker sid, (int)h2n->highest_sid_opened);
240*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(nwsi, H2_ERR_PROTOCOL_ERROR, "Bad sid");
241*1c60b9acSAndroid Build Coastguard Worker return NULL;
242*1c60b9acSAndroid Build Coastguard Worker }
243*1c60b9acSAndroid Build Coastguard Worker
244*1c60b9acSAndroid Build Coastguard Worker /* no more children allowed by parent */
245*1c60b9acSAndroid Build Coastguard Worker if (parent_wsi->mux.child_count + 1 >
246*1c60b9acSAndroid Build Coastguard Worker parent_wsi->h2.h2n->our_set.s[H2SET_MAX_CONCURRENT_STREAMS]) {
247*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("reached concurrent stream limit\n");
248*1c60b9acSAndroid Build Coastguard Worker return NULL;
249*1c60b9acSAndroid Build Coastguard Worker }
250*1c60b9acSAndroid Build Coastguard Worker
251*1c60b9acSAndroid Build Coastguard Worker n = 0;
252*1c60b9acSAndroid Build Coastguard Worker p = &parent_wsi->lc.gutag[1];
253*1c60b9acSAndroid Build Coastguard Worker do {
254*1c60b9acSAndroid Build Coastguard Worker if (*p == '|') {
255*1c60b9acSAndroid Build Coastguard Worker b++;
256*1c60b9acSAndroid Build Coastguard Worker if (b == 3)
257*1c60b9acSAndroid Build Coastguard Worker continue;
258*1c60b9acSAndroid Build Coastguard Worker }
259*1c60b9acSAndroid Build Coastguard Worker tmp1[n++] = *p++;
260*1c60b9acSAndroid Build Coastguard Worker } while (b < 3 && n < sizeof(tmp1) - 2);
261*1c60b9acSAndroid Build Coastguard Worker tmp1[n] = '\0';
262*1c60b9acSAndroid Build Coastguard Worker lws_snprintf(tmp, sizeof(tmp), "h2_sid%u_(%s)", sid, tmp1);
263*1c60b9acSAndroid Build Coastguard Worker wsi = lws_create_new_server_wsi(vh, parent_wsi->tsi, tmp);
264*1c60b9acSAndroid Build Coastguard Worker if (!wsi) {
265*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("new server wsi failed (%s)\n", lws_vh_tag(vh));
266*1c60b9acSAndroid Build Coastguard Worker return NULL;
267*1c60b9acSAndroid Build Coastguard Worker }
268*1c60b9acSAndroid Build Coastguard Worker
269*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SERVER)
270*1c60b9acSAndroid Build Coastguard Worker if (lwsi_role_server(parent_wsi)) {
271*1c60b9acSAndroid Build Coastguard Worker lws_metrics_caliper_bind(wsi->cal_conn, wsi->a.context->mth_srv);
272*1c60b9acSAndroid Build Coastguard Worker }
273*1c60b9acSAndroid Build Coastguard Worker #endif
274*1c60b9acSAndroid Build Coastguard Worker
275*1c60b9acSAndroid Build Coastguard Worker h2n->highest_sid_opened = sid;
276*1c60b9acSAndroid Build Coastguard Worker
277*1c60b9acSAndroid Build Coastguard Worker lws_wsi_mux_insert(wsi, parent_wsi, sid);
278*1c60b9acSAndroid Build Coastguard Worker if (sid >= h2n->highest_sid)
279*1c60b9acSAndroid Build Coastguard Worker h2n->highest_sid = sid + 2;
280*1c60b9acSAndroid Build Coastguard Worker
281*1c60b9acSAndroid Build Coastguard Worker wsi->mux_substream = 1;
282*1c60b9acSAndroid Build Coastguard Worker wsi->seen_nonpseudoheader = 0;
283*1c60b9acSAndroid Build Coastguard Worker
284*1c60b9acSAndroid Build Coastguard Worker wsi->txc.tx_cr = (int32_t)nwsi->h2.h2n->peer_set.s[H2SET_INITIAL_WINDOW_SIZE];
285*1c60b9acSAndroid Build Coastguard Worker wsi->txc.peer_tx_cr_est =
286*1c60b9acSAndroid Build Coastguard Worker (int32_t)nwsi->h2.h2n->our_set.s[H2SET_INITIAL_WINDOW_SIZE];
287*1c60b9acSAndroid Build Coastguard Worker
288*1c60b9acSAndroid Build Coastguard Worker lwsi_set_state(wsi, LRS_ESTABLISHED);
289*1c60b9acSAndroid Build Coastguard Worker lwsi_set_role(wsi, lwsi_role(parent_wsi));
290*1c60b9acSAndroid Build Coastguard Worker
291*1c60b9acSAndroid Build Coastguard Worker wsi->a.protocol = &vh->protocols[0];
292*1c60b9acSAndroid Build Coastguard Worker if (lws_ensure_user_space(wsi))
293*1c60b9acSAndroid Build Coastguard Worker goto bail1;
294*1c60b9acSAndroid Build Coastguard Worker
295*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SERVER) && defined(LWS_WITH_SECURE_STREAMS)
296*1c60b9acSAndroid Build Coastguard Worker if (lws_adopt_ss_server_accept(wsi))
297*1c60b9acSAndroid Build Coastguard Worker goto bail1;
298*1c60b9acSAndroid Build Coastguard Worker #endif
299*1c60b9acSAndroid Build Coastguard Worker
300*1c60b9acSAndroid Build Coastguard Worker /* get the ball rolling */
301*1c60b9acSAndroid Build Coastguard Worker lws_validity_confirmed(wsi);
302*1c60b9acSAndroid Build Coastguard Worker
303*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: %s new ch %s, sid %d, usersp=%p\n", __func__,
304*1c60b9acSAndroid Build Coastguard Worker lws_wsi_tag(parent_wsi), lws_wsi_tag(wsi), sid, wsi->user_space);
305*1c60b9acSAndroid Build Coastguard Worker
306*1c60b9acSAndroid Build Coastguard Worker lws_wsi_txc_describe(&wsi->txc, __func__, wsi->mux.my_sid);
307*1c60b9acSAndroid Build Coastguard Worker lws_wsi_txc_describe(&nwsi->txc, __func__, 0);
308*1c60b9acSAndroid Build Coastguard Worker
309*1c60b9acSAndroid Build Coastguard Worker return wsi;
310*1c60b9acSAndroid Build Coastguard Worker
311*1c60b9acSAndroid Build Coastguard Worker bail1:
312*1c60b9acSAndroid Build Coastguard Worker /* undo the insert */
313*1c60b9acSAndroid Build Coastguard Worker parent_wsi->mux.child_list = wsi->mux.sibling_list;
314*1c60b9acSAndroid Build Coastguard Worker parent_wsi->mux.child_count--;
315*1c60b9acSAndroid Build Coastguard Worker
316*1c60b9acSAndroid Build Coastguard Worker if (wsi->user_space)
317*1c60b9acSAndroid Build Coastguard Worker lws_free_set_NULL(wsi->user_space);
318*1c60b9acSAndroid Build Coastguard Worker vh->protocols[0].callback(wsi, LWS_CALLBACK_WSI_DESTROY, NULL, NULL, 0);
319*1c60b9acSAndroid Build Coastguard Worker __lws_vhost_unbind_wsi(wsi);
320*1c60b9acSAndroid Build Coastguard Worker lws_free(wsi);
321*1c60b9acSAndroid Build Coastguard Worker
322*1c60b9acSAndroid Build Coastguard Worker return NULL;
323*1c60b9acSAndroid Build Coastguard Worker }
324*1c60b9acSAndroid Build Coastguard Worker
325*1c60b9acSAndroid Build Coastguard Worker struct lws *
lws_wsi_h2_adopt(struct lws * parent_wsi,struct lws * wsi)326*1c60b9acSAndroid Build Coastguard Worker lws_wsi_h2_adopt(struct lws *parent_wsi, struct lws *wsi)
327*1c60b9acSAndroid Build Coastguard Worker {
328*1c60b9acSAndroid Build Coastguard Worker struct lws *nwsi = lws_get_network_wsi(parent_wsi);
329*1c60b9acSAndroid Build Coastguard Worker
330*1c60b9acSAndroid Build Coastguard Worker /* no more children allowed by parent */
331*1c60b9acSAndroid Build Coastguard Worker if (parent_wsi->mux.child_count + 1 >
332*1c60b9acSAndroid Build Coastguard Worker parent_wsi->h2.h2n->our_set.s[H2SET_MAX_CONCURRENT_STREAMS]) {
333*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("reached concurrent stream limit\n");
334*1c60b9acSAndroid Build Coastguard Worker return NULL;
335*1c60b9acSAndroid Build Coastguard Worker }
336*1c60b9acSAndroid Build Coastguard Worker
337*1c60b9acSAndroid Build Coastguard Worker /* sid is set just before issuing the headers, ensuring monoticity */
338*1c60b9acSAndroid Build Coastguard Worker
339*1c60b9acSAndroid Build Coastguard Worker wsi->seen_nonpseudoheader = 0;
340*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
341*1c60b9acSAndroid Build Coastguard Worker wsi->client_mux_substream = 1;
342*1c60b9acSAndroid Build Coastguard Worker #endif
343*1c60b9acSAndroid Build Coastguard Worker wsi->h2.initialized = 1;
344*1c60b9acSAndroid Build Coastguard Worker
345*1c60b9acSAndroid Build Coastguard Worker #if 0
346*1c60b9acSAndroid Build Coastguard Worker /* only assign sid at header send time when we know it */
347*1c60b9acSAndroid Build Coastguard Worker if (!wsi->mux.my_sid) {
348*1c60b9acSAndroid Build Coastguard Worker wsi->mux.my_sid = nwsi->h2.h2n->highest_sid;
349*1c60b9acSAndroid Build Coastguard Worker nwsi->h2.h2n->highest_sid += 2;
350*1c60b9acSAndroid Build Coastguard Worker }
351*1c60b9acSAndroid Build Coastguard Worker #endif
352*1c60b9acSAndroid Build Coastguard Worker
353*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: binding wsi %s to sid %d (next %d)\n", __func__,
354*1c60b9acSAndroid Build Coastguard Worker lws_wsi_tag(wsi), (int)wsi->mux.my_sid, (int)nwsi->h2.h2n->highest_sid);
355*1c60b9acSAndroid Build Coastguard Worker
356*1c60b9acSAndroid Build Coastguard Worker lws_wsi_mux_insert(wsi, parent_wsi, wsi->mux.my_sid);
357*1c60b9acSAndroid Build Coastguard Worker
358*1c60b9acSAndroid Build Coastguard Worker wsi->txc.tx_cr = (int32_t)nwsi->h2.h2n->peer_set.s[H2SET_INITIAL_WINDOW_SIZE];
359*1c60b9acSAndroid Build Coastguard Worker wsi->txc.peer_tx_cr_est = (int32_t)
360*1c60b9acSAndroid Build Coastguard Worker nwsi->h2.h2n->our_set.s[H2SET_INITIAL_WINDOW_SIZE];
361*1c60b9acSAndroid Build Coastguard Worker
362*1c60b9acSAndroid Build Coastguard Worker lws_wsi_txc_describe(&wsi->txc, __func__, wsi->mux.my_sid);
363*1c60b9acSAndroid Build Coastguard Worker
364*1c60b9acSAndroid Build Coastguard Worker if (lws_ensure_user_space(wsi))
365*1c60b9acSAndroid Build Coastguard Worker goto bail1;
366*1c60b9acSAndroid Build Coastguard Worker
367*1c60b9acSAndroid Build Coastguard Worker lws_role_transition(wsi, LWSIFR_CLIENT, LRS_H2_WAITING_TO_SEND_HEADERS,
368*1c60b9acSAndroid Build Coastguard Worker &role_ops_h2);
369*1c60b9acSAndroid Build Coastguard Worker
370*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(wsi);
371*1c60b9acSAndroid Build Coastguard Worker
372*1c60b9acSAndroid Build Coastguard Worker return wsi;
373*1c60b9acSAndroid Build Coastguard Worker
374*1c60b9acSAndroid Build Coastguard Worker bail1:
375*1c60b9acSAndroid Build Coastguard Worker /* undo the insert */
376*1c60b9acSAndroid Build Coastguard Worker parent_wsi->mux.child_list = wsi->mux.sibling_list;
377*1c60b9acSAndroid Build Coastguard Worker parent_wsi->mux.child_count--;
378*1c60b9acSAndroid Build Coastguard Worker
379*1c60b9acSAndroid Build Coastguard Worker if (wsi->user_space)
380*1c60b9acSAndroid Build Coastguard Worker lws_free_set_NULL(wsi->user_space);
381*1c60b9acSAndroid Build Coastguard Worker wsi->a.protocol->callback(wsi, LWS_CALLBACK_WSI_DESTROY, NULL, NULL, 0);
382*1c60b9acSAndroid Build Coastguard Worker lws_free(wsi);
383*1c60b9acSAndroid Build Coastguard Worker
384*1c60b9acSAndroid Build Coastguard Worker return NULL;
385*1c60b9acSAndroid Build Coastguard Worker }
386*1c60b9acSAndroid Build Coastguard Worker
387*1c60b9acSAndroid Build Coastguard Worker
388*1c60b9acSAndroid Build Coastguard Worker int
lws_h2_issue_preface(struct lws * wsi)389*1c60b9acSAndroid Build Coastguard Worker lws_h2_issue_preface(struct lws *wsi)
390*1c60b9acSAndroid Build Coastguard Worker {
391*1c60b9acSAndroid Build Coastguard Worker struct lws_h2_netconn *h2n = wsi->h2.h2n;
392*1c60b9acSAndroid Build Coastguard Worker struct lws_h2_protocol_send *pps;
393*1c60b9acSAndroid Build Coastguard Worker
394*1c60b9acSAndroid Build Coastguard Worker if (!h2n) {
395*1c60b9acSAndroid Build Coastguard Worker lwsl_warn("%s: no valid h2n\n", __func__);
396*1c60b9acSAndroid Build Coastguard Worker return 1;
397*1c60b9acSAndroid Build Coastguard Worker }
398*1c60b9acSAndroid Build Coastguard Worker
399*1c60b9acSAndroid Build Coastguard Worker if (h2n->sent_preface)
400*1c60b9acSAndroid Build Coastguard Worker return 1;
401*1c60b9acSAndroid Build Coastguard Worker
402*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: %s: fd %d\n", __func__, lws_wsi_tag(wsi), (int)wsi->desc.sockfd);
403*1c60b9acSAndroid Build Coastguard Worker
404*1c60b9acSAndroid Build Coastguard Worker if (lws_issue_raw(wsi, (uint8_t *)preface, strlen(preface)) !=
405*1c60b9acSAndroid Build Coastguard Worker (int)strlen(preface))
406*1c60b9acSAndroid Build Coastguard Worker return 1;
407*1c60b9acSAndroid Build Coastguard Worker
408*1c60b9acSAndroid Build Coastguard Worker h2n->sent_preface = 1;
409*1c60b9acSAndroid Build Coastguard Worker
410*1c60b9acSAndroid Build Coastguard Worker lws_role_transition(wsi, LWSIFR_CLIENT, LRS_H2_WAITING_TO_SEND_HEADERS,
411*1c60b9acSAndroid Build Coastguard Worker &role_ops_h2);
412*1c60b9acSAndroid Build Coastguard Worker
413*1c60b9acSAndroid Build Coastguard Worker h2n->count = 0;
414*1c60b9acSAndroid Build Coastguard Worker wsi->txc.tx_cr = 65535;
415*1c60b9acSAndroid Build Coastguard Worker
416*1c60b9acSAndroid Build Coastguard Worker /*
417*1c60b9acSAndroid Build Coastguard Worker * we must send a settings frame
418*1c60b9acSAndroid Build Coastguard Worker */
419*1c60b9acSAndroid Build Coastguard Worker pps = lws_h2_new_pps(LWS_H2_PPS_MY_SETTINGS);
420*1c60b9acSAndroid Build Coastguard Worker if (!pps)
421*1c60b9acSAndroid Build Coastguard Worker return 1;
422*1c60b9acSAndroid Build Coastguard Worker lws_pps_schedule(wsi, pps);
423*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: h2 client sending settings\n", __func__);
424*1c60b9acSAndroid Build Coastguard Worker
425*1c60b9acSAndroid Build Coastguard Worker return 0;
426*1c60b9acSAndroid Build Coastguard Worker }
427*1c60b9acSAndroid Build Coastguard Worker
428*1c60b9acSAndroid Build Coastguard Worker void
lws_pps_schedule(struct lws * wsi,struct lws_h2_protocol_send * pps)429*1c60b9acSAndroid Build Coastguard Worker lws_pps_schedule(struct lws *wsi, struct lws_h2_protocol_send *pps)
430*1c60b9acSAndroid Build Coastguard Worker {
431*1c60b9acSAndroid Build Coastguard Worker struct lws *nwsi = lws_get_network_wsi(wsi);
432*1c60b9acSAndroid Build Coastguard Worker struct lws_h2_netconn *h2n = nwsi->h2.h2n;
433*1c60b9acSAndroid Build Coastguard Worker
434*1c60b9acSAndroid Build Coastguard Worker pps->next = h2n->pps;
435*1c60b9acSAndroid Build Coastguard Worker h2n->pps = pps;
436*1c60b9acSAndroid Build Coastguard Worker lws_rx_flow_control(wsi, LWS_RXFLOW_REASON_APPLIES_DISABLE |
437*1c60b9acSAndroid Build Coastguard Worker LWS_RXFLOW_REASON_H2_PPS_PENDING);
438*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(wsi);
439*1c60b9acSAndroid Build Coastguard Worker }
440*1c60b9acSAndroid Build Coastguard Worker
441*1c60b9acSAndroid Build Coastguard Worker int
lws_h2_goaway(struct lws * wsi,uint32_t err,const char * reason)442*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(struct lws *wsi, uint32_t err, const char *reason)
443*1c60b9acSAndroid Build Coastguard Worker {
444*1c60b9acSAndroid Build Coastguard Worker struct lws_h2_netconn *h2n = wsi->h2.h2n;
445*1c60b9acSAndroid Build Coastguard Worker struct lws_h2_protocol_send *pps;
446*1c60b9acSAndroid Build Coastguard Worker
447*1c60b9acSAndroid Build Coastguard Worker if (h2n->type == LWS_H2_FRAME_TYPE_COUNT)
448*1c60b9acSAndroid Build Coastguard Worker return 0;
449*1c60b9acSAndroid Build Coastguard Worker
450*1c60b9acSAndroid Build Coastguard Worker pps = lws_h2_new_pps(LWS_H2_PPS_GOAWAY);
451*1c60b9acSAndroid Build Coastguard Worker if (!pps)
452*1c60b9acSAndroid Build Coastguard Worker return 1;
453*1c60b9acSAndroid Build Coastguard Worker
454*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: %s: ERR 0x%x, '%s'\n", __func__, lws_wsi_tag(wsi), (int)err, reason);
455*1c60b9acSAndroid Build Coastguard Worker
456*1c60b9acSAndroid Build Coastguard Worker pps->u.ga.err = err;
457*1c60b9acSAndroid Build Coastguard Worker pps->u.ga.highest_sid = h2n->highest_sid;
458*1c60b9acSAndroid Build Coastguard Worker lws_strncpy(pps->u.ga.str, reason, sizeof(pps->u.ga.str));
459*1c60b9acSAndroid Build Coastguard Worker lws_pps_schedule(wsi, pps);
460*1c60b9acSAndroid Build Coastguard Worker
461*1c60b9acSAndroid Build Coastguard Worker h2n->type = LWS_H2_FRAME_TYPE_COUNT; /* ie, IGNORE */
462*1c60b9acSAndroid Build Coastguard Worker
463*1c60b9acSAndroid Build Coastguard Worker return 0;
464*1c60b9acSAndroid Build Coastguard Worker }
465*1c60b9acSAndroid Build Coastguard Worker
466*1c60b9acSAndroid Build Coastguard Worker int
lws_h2_rst_stream(struct lws * wsi,uint32_t err,const char * reason)467*1c60b9acSAndroid Build Coastguard Worker lws_h2_rst_stream(struct lws *wsi, uint32_t err, const char *reason)
468*1c60b9acSAndroid Build Coastguard Worker {
469*1c60b9acSAndroid Build Coastguard Worker struct lws *nwsi = lws_get_network_wsi(wsi);
470*1c60b9acSAndroid Build Coastguard Worker struct lws_h2_netconn *h2n = nwsi->h2.h2n;
471*1c60b9acSAndroid Build Coastguard Worker struct lws_h2_protocol_send *pps;
472*1c60b9acSAndroid Build Coastguard Worker
473*1c60b9acSAndroid Build Coastguard Worker if (!h2n)
474*1c60b9acSAndroid Build Coastguard Worker return 0;
475*1c60b9acSAndroid Build Coastguard Worker
476*1c60b9acSAndroid Build Coastguard Worker if (!wsi->h2_stream_carries_ws && h2n->type == LWS_H2_FRAME_TYPE_COUNT)
477*1c60b9acSAndroid Build Coastguard Worker return 0;
478*1c60b9acSAndroid Build Coastguard Worker
479*1c60b9acSAndroid Build Coastguard Worker pps = lws_h2_new_pps(LWS_H2_PPS_RST_STREAM);
480*1c60b9acSAndroid Build Coastguard Worker if (!pps)
481*1c60b9acSAndroid Build Coastguard Worker return 1;
482*1c60b9acSAndroid Build Coastguard Worker
483*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: RST_STREAM 0x%x, sid %d, REASON '%s'\n", __func__,
484*1c60b9acSAndroid Build Coastguard Worker (int)err, wsi->mux.my_sid, reason);
485*1c60b9acSAndroid Build Coastguard Worker
486*1c60b9acSAndroid Build Coastguard Worker pps->u.rs.sid = wsi->mux.my_sid;
487*1c60b9acSAndroid Build Coastguard Worker pps->u.rs.err = err;
488*1c60b9acSAndroid Build Coastguard Worker
489*1c60b9acSAndroid Build Coastguard Worker lws_pps_schedule(wsi, pps);
490*1c60b9acSAndroid Build Coastguard Worker
491*1c60b9acSAndroid Build Coastguard Worker h2n->type = LWS_H2_FRAME_TYPE_COUNT; /* ie, IGNORE */
492*1c60b9acSAndroid Build Coastguard Worker lws_h2_state(wsi, LWS_H2_STATE_CLOSED);
493*1c60b9acSAndroid Build Coastguard Worker
494*1c60b9acSAndroid Build Coastguard Worker return 0;
495*1c60b9acSAndroid Build Coastguard Worker }
496*1c60b9acSAndroid Build Coastguard Worker
497*1c60b9acSAndroid Build Coastguard Worker int
lws_h2_settings(struct lws * wsi,struct http2_settings * settings,unsigned char * buf,int len)498*1c60b9acSAndroid Build Coastguard Worker lws_h2_settings(struct lws *wsi, struct http2_settings *settings,
499*1c60b9acSAndroid Build Coastguard Worker unsigned char *buf, int len)
500*1c60b9acSAndroid Build Coastguard Worker {
501*1c60b9acSAndroid Build Coastguard Worker struct lws *nwsi = lws_get_network_wsi(wsi);
502*1c60b9acSAndroid Build Coastguard Worker unsigned int a, b;
503*1c60b9acSAndroid Build Coastguard Worker
504*1c60b9acSAndroid Build Coastguard Worker if (!len)
505*1c60b9acSAndroid Build Coastguard Worker return 0;
506*1c60b9acSAndroid Build Coastguard Worker
507*1c60b9acSAndroid Build Coastguard Worker if (len < LWS_H2_SETTINGS_LEN)
508*1c60b9acSAndroid Build Coastguard Worker return 1;
509*1c60b9acSAndroid Build Coastguard Worker
510*1c60b9acSAndroid Build Coastguard Worker while (len >= LWS_H2_SETTINGS_LEN) {
511*1c60b9acSAndroid Build Coastguard Worker a = (unsigned int)((buf[0] << 8) | buf[1]);
512*1c60b9acSAndroid Build Coastguard Worker if (!a || a >= H2SET_COUNT)
513*1c60b9acSAndroid Build Coastguard Worker goto skip;
514*1c60b9acSAndroid Build Coastguard Worker b = (unsigned int)(buf[2] << 24 | buf[3] << 16 | buf[4] << 8 | buf[5]);
515*1c60b9acSAndroid Build Coastguard Worker
516*1c60b9acSAndroid Build Coastguard Worker switch (a) {
517*1c60b9acSAndroid Build Coastguard Worker case H2SET_HEADER_TABLE_SIZE:
518*1c60b9acSAndroid Build Coastguard Worker break;
519*1c60b9acSAndroid Build Coastguard Worker case H2SET_ENABLE_PUSH:
520*1c60b9acSAndroid Build Coastguard Worker if (b > 1) {
521*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(nwsi, H2_ERR_PROTOCOL_ERROR,
522*1c60b9acSAndroid Build Coastguard Worker "ENABLE_PUSH invalid arg");
523*1c60b9acSAndroid Build Coastguard Worker return 1;
524*1c60b9acSAndroid Build Coastguard Worker }
525*1c60b9acSAndroid Build Coastguard Worker break;
526*1c60b9acSAndroid Build Coastguard Worker case H2SET_MAX_CONCURRENT_STREAMS:
527*1c60b9acSAndroid Build Coastguard Worker break;
528*1c60b9acSAndroid Build Coastguard Worker case H2SET_INITIAL_WINDOW_SIZE:
529*1c60b9acSAndroid Build Coastguard Worker if (b > 0x7fffffff) {
530*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(nwsi, H2_ERR_FLOW_CONTROL_ERROR,
531*1c60b9acSAndroid Build Coastguard Worker "Inital Window beyond max");
532*1c60b9acSAndroid Build Coastguard Worker return 1;
533*1c60b9acSAndroid Build Coastguard Worker }
534*1c60b9acSAndroid Build Coastguard Worker
535*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
536*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_AMAZON_RTOS) || defined(LWS_AMAZON_LINUX)
537*1c60b9acSAndroid Build Coastguard Worker if (
538*1c60b9acSAndroid Build Coastguard Worker #else
539*1c60b9acSAndroid Build Coastguard Worker if (wsi->flags & LCCSCF_H2_QUIRK_OVERFLOWS_TXCR &&
540*1c60b9acSAndroid Build Coastguard Worker #endif
541*1c60b9acSAndroid Build Coastguard Worker b == 0x7fffffff) {
542*1c60b9acSAndroid Build Coastguard Worker b >>= 4;
543*1c60b9acSAndroid Build Coastguard Worker
544*1c60b9acSAndroid Build Coastguard Worker break;
545*1c60b9acSAndroid Build Coastguard Worker }
546*1c60b9acSAndroid Build Coastguard Worker #endif
547*1c60b9acSAndroid Build Coastguard Worker
548*1c60b9acSAndroid Build Coastguard Worker /*
549*1c60b9acSAndroid Build Coastguard Worker * In addition to changing the flow-control window for
550*1c60b9acSAndroid Build Coastguard Worker * streams that are not yet active, a SETTINGS frame
551*1c60b9acSAndroid Build Coastguard Worker * can alter the initial flow-control window size for
552*1c60b9acSAndroid Build Coastguard Worker * streams with active flow-control windows (that is,
553*1c60b9acSAndroid Build Coastguard Worker * streams in the "open" or "half-closed (remote)"
554*1c60b9acSAndroid Build Coastguard Worker * state). When the value of
555*1c60b9acSAndroid Build Coastguard Worker * SETTINGS_INITIAL_WINDOW_SIZE changes, a receiver
556*1c60b9acSAndroid Build Coastguard Worker * MUST adjust the size of all stream flow-control
557*1c60b9acSAndroid Build Coastguard Worker * windows that it maintains by the difference between
558*1c60b9acSAndroid Build Coastguard Worker * the new value and the old value.
559*1c60b9acSAndroid Build Coastguard Worker */
560*1c60b9acSAndroid Build Coastguard Worker
561*1c60b9acSAndroid Build Coastguard Worker lws_start_foreach_ll(struct lws *, w,
562*1c60b9acSAndroid Build Coastguard Worker nwsi->mux.child_list) {
563*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: adi child tc cr %d +%d -> %d",
564*1c60b9acSAndroid Build Coastguard Worker __func__, (int)w->txc.tx_cr,
565*1c60b9acSAndroid Build Coastguard Worker b - (unsigned int)settings->s[a],
566*1c60b9acSAndroid Build Coastguard Worker (int)(w->txc.tx_cr + (int)b -
567*1c60b9acSAndroid Build Coastguard Worker (int)settings->s[a]));
568*1c60b9acSAndroid Build Coastguard Worker w->txc.tx_cr += (int)b - (int)settings->s[a];
569*1c60b9acSAndroid Build Coastguard Worker if (w->txc.tx_cr > 0 &&
570*1c60b9acSAndroid Build Coastguard Worker w->txc.tx_cr <=
571*1c60b9acSAndroid Build Coastguard Worker (int32_t)(b - settings->s[a]))
572*1c60b9acSAndroid Build Coastguard Worker
573*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(w);
574*1c60b9acSAndroid Build Coastguard Worker } lws_end_foreach_ll(w, mux.sibling_list);
575*1c60b9acSAndroid Build Coastguard Worker
576*1c60b9acSAndroid Build Coastguard Worker break;
577*1c60b9acSAndroid Build Coastguard Worker case H2SET_MAX_FRAME_SIZE:
578*1c60b9acSAndroid Build Coastguard Worker if (b < wsi->a.vhost->h2.set.s[H2SET_MAX_FRAME_SIZE]) {
579*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(nwsi, H2_ERR_PROTOCOL_ERROR,
580*1c60b9acSAndroid Build Coastguard Worker "Frame size < initial");
581*1c60b9acSAndroid Build Coastguard Worker return 1;
582*1c60b9acSAndroid Build Coastguard Worker }
583*1c60b9acSAndroid Build Coastguard Worker if (b > 0x00ffffff) {
584*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(nwsi, H2_ERR_PROTOCOL_ERROR,
585*1c60b9acSAndroid Build Coastguard Worker "Settings Frame size above max");
586*1c60b9acSAndroid Build Coastguard Worker return 1;
587*1c60b9acSAndroid Build Coastguard Worker }
588*1c60b9acSAndroid Build Coastguard Worker break;
589*1c60b9acSAndroid Build Coastguard Worker case H2SET_MAX_HEADER_LIST_SIZE:
590*1c60b9acSAndroid Build Coastguard Worker break;
591*1c60b9acSAndroid Build Coastguard Worker }
592*1c60b9acSAndroid Build Coastguard Worker settings->s[a] = b;
593*1c60b9acSAndroid Build Coastguard Worker lwsl_info("http2 settings %d <- 0x%x\n", a, b);
594*1c60b9acSAndroid Build Coastguard Worker skip:
595*1c60b9acSAndroid Build Coastguard Worker len -= LWS_H2_SETTINGS_LEN;
596*1c60b9acSAndroid Build Coastguard Worker buf += LWS_H2_SETTINGS_LEN;
597*1c60b9acSAndroid Build Coastguard Worker }
598*1c60b9acSAndroid Build Coastguard Worker
599*1c60b9acSAndroid Build Coastguard Worker if (len)
600*1c60b9acSAndroid Build Coastguard Worker return 1;
601*1c60b9acSAndroid Build Coastguard Worker
602*1c60b9acSAndroid Build Coastguard Worker lws_h2_dump_settings(settings);
603*1c60b9acSAndroid Build Coastguard Worker
604*1c60b9acSAndroid Build Coastguard Worker return 0;
605*1c60b9acSAndroid Build Coastguard Worker }
606*1c60b9acSAndroid Build Coastguard Worker
607*1c60b9acSAndroid Build Coastguard Worker /* RFC7640 Sect 6.9
608*1c60b9acSAndroid Build Coastguard Worker *
609*1c60b9acSAndroid Build Coastguard Worker * The WINDOW_UPDATE frame can be specific to a stream or to the entire
610*1c60b9acSAndroid Build Coastguard Worker * connection. In the former case, the frame's stream identifier
611*1c60b9acSAndroid Build Coastguard Worker * indicates the affected stream; in the latter, the value "0" indicates
612*1c60b9acSAndroid Build Coastguard Worker * that the entire connection is the subject of the frame.
613*1c60b9acSAndroid Build Coastguard Worker *
614*1c60b9acSAndroid Build Coastguard Worker * ...
615*1c60b9acSAndroid Build Coastguard Worker *
616*1c60b9acSAndroid Build Coastguard Worker * Two flow-control windows are applicable: the stream flow-control
617*1c60b9acSAndroid Build Coastguard Worker * window and the connection flow-control window. The sender MUST NOT
618*1c60b9acSAndroid Build Coastguard Worker * send a flow-controlled frame with a length that exceeds the space
619*1c60b9acSAndroid Build Coastguard Worker * available in either of the flow-control windows advertised by the
620*1c60b9acSAndroid Build Coastguard Worker * receiver. Frames with zero length with the END_STREAM flag set (that
621*1c60b9acSAndroid Build Coastguard Worker * is, an empty DATA frame) MAY be sent if there is no available space
622*1c60b9acSAndroid Build Coastguard Worker * in either flow-control window.
623*1c60b9acSAndroid Build Coastguard Worker */
624*1c60b9acSAndroid Build Coastguard Worker
625*1c60b9acSAndroid Build Coastguard Worker int
lws_h2_tx_cr_get(struct lws * wsi)626*1c60b9acSAndroid Build Coastguard Worker lws_h2_tx_cr_get(struct lws *wsi)
627*1c60b9acSAndroid Build Coastguard Worker {
628*1c60b9acSAndroid Build Coastguard Worker int c = wsi->txc.tx_cr;
629*1c60b9acSAndroid Build Coastguard Worker struct lws *nwsi = lws_get_network_wsi(wsi);
630*1c60b9acSAndroid Build Coastguard Worker
631*1c60b9acSAndroid Build Coastguard Worker if (!wsi->mux_substream && !nwsi->upgraded_to_http2)
632*1c60b9acSAndroid Build Coastguard Worker return ~0x80000000;
633*1c60b9acSAndroid Build Coastguard Worker
634*1c60b9acSAndroid Build Coastguard Worker lwsl_info ("%s: %s: own tx credit %d: nwsi credit %d\n",
635*1c60b9acSAndroid Build Coastguard Worker __func__, lws_wsi_tag(wsi), c, (int)nwsi->txc.tx_cr);
636*1c60b9acSAndroid Build Coastguard Worker
637*1c60b9acSAndroid Build Coastguard Worker if (nwsi->txc.tx_cr < c)
638*1c60b9acSAndroid Build Coastguard Worker c = nwsi->txc.tx_cr;
639*1c60b9acSAndroid Build Coastguard Worker
640*1c60b9acSAndroid Build Coastguard Worker if (c < 0)
641*1c60b9acSAndroid Build Coastguard Worker return 0;
642*1c60b9acSAndroid Build Coastguard Worker
643*1c60b9acSAndroid Build Coastguard Worker return c;
644*1c60b9acSAndroid Build Coastguard Worker }
645*1c60b9acSAndroid Build Coastguard Worker
646*1c60b9acSAndroid Build Coastguard Worker void
lws_h2_tx_cr_consume(struct lws * wsi,int consumed)647*1c60b9acSAndroid Build Coastguard Worker lws_h2_tx_cr_consume(struct lws *wsi, int consumed)
648*1c60b9acSAndroid Build Coastguard Worker {
649*1c60b9acSAndroid Build Coastguard Worker struct lws *nwsi = lws_get_network_wsi(wsi);
650*1c60b9acSAndroid Build Coastguard Worker
651*1c60b9acSAndroid Build Coastguard Worker wsi->txc.tx_cr -= consumed;
652*1c60b9acSAndroid Build Coastguard Worker
653*1c60b9acSAndroid Build Coastguard Worker if (nwsi != wsi)
654*1c60b9acSAndroid Build Coastguard Worker nwsi->txc.tx_cr -= consumed;
655*1c60b9acSAndroid Build Coastguard Worker }
656*1c60b9acSAndroid Build Coastguard Worker
lws_h2_frame_write(struct lws * wsi,int type,int flags,unsigned int sid,unsigned int len,unsigned char * buf)657*1c60b9acSAndroid Build Coastguard Worker int lws_h2_frame_write(struct lws *wsi, int type, int flags,
658*1c60b9acSAndroid Build Coastguard Worker unsigned int sid, unsigned int len, unsigned char *buf)
659*1c60b9acSAndroid Build Coastguard Worker {
660*1c60b9acSAndroid Build Coastguard Worker struct lws *nwsi = lws_get_network_wsi(wsi);
661*1c60b9acSAndroid Build Coastguard Worker unsigned char *p = &buf[-LWS_H2_FRAME_HEADER_LENGTH];
662*1c60b9acSAndroid Build Coastguard Worker int n;
663*1c60b9acSAndroid Build Coastguard Worker
664*1c60b9acSAndroid Build Coastguard Worker //if (wsi->h2_stream_carries_ws)
665*1c60b9acSAndroid Build Coastguard Worker // lwsl_hexdump_level(LLL_NOTICE, buf, len);
666*1c60b9acSAndroid Build Coastguard Worker
667*1c60b9acSAndroid Build Coastguard Worker *p++ = (uint8_t)(len >> 16);
668*1c60b9acSAndroid Build Coastguard Worker *p++ = (uint8_t)(len >> 8);
669*1c60b9acSAndroid Build Coastguard Worker *p++ = (uint8_t)len;
670*1c60b9acSAndroid Build Coastguard Worker *p++ = (uint8_t)type;
671*1c60b9acSAndroid Build Coastguard Worker *p++ = (uint8_t)flags;
672*1c60b9acSAndroid Build Coastguard Worker *p++ = (uint8_t)(sid >> 24);
673*1c60b9acSAndroid Build Coastguard Worker *p++ = (uint8_t)(sid >> 16);
674*1c60b9acSAndroid Build Coastguard Worker *p++ = (uint8_t)(sid >> 8);
675*1c60b9acSAndroid Build Coastguard Worker *p++ = (uint8_t)sid;
676*1c60b9acSAndroid Build Coastguard Worker
677*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: %s (eff %s). typ %d, fl 0x%x, sid=%d, len=%d, "
678*1c60b9acSAndroid Build Coastguard Worker "txcr=%d, nwsi->txcr=%d\n", __func__, lws_wsi_tag(wsi),
679*1c60b9acSAndroid Build Coastguard Worker lws_wsi_tag(nwsi), type, flags,
680*1c60b9acSAndroid Build Coastguard Worker sid, len, (int)wsi->txc.tx_cr, (int)nwsi->txc.tx_cr);
681*1c60b9acSAndroid Build Coastguard Worker
682*1c60b9acSAndroid Build Coastguard Worker if (type == LWS_H2_FRAME_TYPE_DATA) {
683*1c60b9acSAndroid Build Coastguard Worker if (wsi->txc.tx_cr < (int)len)
684*1c60b9acSAndroid Build Coastguard Worker
685*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: %s: sending payload len %d"
686*1c60b9acSAndroid Build Coastguard Worker " but tx_cr only %d!\n", __func__,
687*1c60b9acSAndroid Build Coastguard Worker lws_wsi_tag(wsi), len, (int)wsi->txc.tx_cr);
688*1c60b9acSAndroid Build Coastguard Worker lws_h2_tx_cr_consume(wsi, (int)len);
689*1c60b9acSAndroid Build Coastguard Worker }
690*1c60b9acSAndroid Build Coastguard Worker
691*1c60b9acSAndroid Build Coastguard Worker n = lws_issue_raw(nwsi, &buf[-LWS_H2_FRAME_HEADER_LENGTH],
692*1c60b9acSAndroid Build Coastguard Worker len + LWS_H2_FRAME_HEADER_LENGTH);
693*1c60b9acSAndroid Build Coastguard Worker if (n < 0)
694*1c60b9acSAndroid Build Coastguard Worker return n;
695*1c60b9acSAndroid Build Coastguard Worker
696*1c60b9acSAndroid Build Coastguard Worker if (n >= LWS_H2_FRAME_HEADER_LENGTH)
697*1c60b9acSAndroid Build Coastguard Worker return n - LWS_H2_FRAME_HEADER_LENGTH;
698*1c60b9acSAndroid Build Coastguard Worker
699*1c60b9acSAndroid Build Coastguard Worker return n;
700*1c60b9acSAndroid Build Coastguard Worker }
701*1c60b9acSAndroid Build Coastguard Worker
lws_h2_set_bin(struct lws * wsi,int n,unsigned char * buf)702*1c60b9acSAndroid Build Coastguard Worker static void lws_h2_set_bin(struct lws *wsi, int n, unsigned char *buf)
703*1c60b9acSAndroid Build Coastguard Worker {
704*1c60b9acSAndroid Build Coastguard Worker *buf++ = (uint8_t)(n >> 8);
705*1c60b9acSAndroid Build Coastguard Worker *buf++ = (uint8_t)n;
706*1c60b9acSAndroid Build Coastguard Worker *buf++ = (uint8_t)(wsi->h2.h2n->our_set.s[n] >> 24);
707*1c60b9acSAndroid Build Coastguard Worker *buf++ = (uint8_t)(wsi->h2.h2n->our_set.s[n] >> 16);
708*1c60b9acSAndroid Build Coastguard Worker *buf++ = (uint8_t)(wsi->h2.h2n->our_set.s[n] >> 8);
709*1c60b9acSAndroid Build Coastguard Worker *buf = (uint8_t)wsi->h2.h2n->our_set.s[n];
710*1c60b9acSAndroid Build Coastguard Worker }
711*1c60b9acSAndroid Build Coastguard Worker
712*1c60b9acSAndroid Build Coastguard Worker /* we get called on the network connection */
713*1c60b9acSAndroid Build Coastguard Worker
lws_h2_do_pps_send(struct lws * wsi)714*1c60b9acSAndroid Build Coastguard Worker int lws_h2_do_pps_send(struct lws *wsi)
715*1c60b9acSAndroid Build Coastguard Worker {
716*1c60b9acSAndroid Build Coastguard Worker struct lws_h2_netconn *h2n = wsi->h2.h2n;
717*1c60b9acSAndroid Build Coastguard Worker struct lws_h2_protocol_send *pps = NULL;
718*1c60b9acSAndroid Build Coastguard Worker struct lws *cwsi;
719*1c60b9acSAndroid Build Coastguard Worker uint8_t set[LWS_PRE + 64], *p = &set[LWS_PRE], *q;
720*1c60b9acSAndroid Build Coastguard Worker int n, m = 0, flags = 0;
721*1c60b9acSAndroid Build Coastguard Worker
722*1c60b9acSAndroid Build Coastguard Worker if (!h2n)
723*1c60b9acSAndroid Build Coastguard Worker return 1;
724*1c60b9acSAndroid Build Coastguard Worker
725*1c60b9acSAndroid Build Coastguard Worker /* get the oldest pps */
726*1c60b9acSAndroid Build Coastguard Worker
727*1c60b9acSAndroid Build Coastguard Worker lws_start_foreach_llp(struct lws_h2_protocol_send **, pps1, h2n->pps) {
728*1c60b9acSAndroid Build Coastguard Worker if ((*pps1)->next == NULL) { /* we are the oldest in the list */
729*1c60b9acSAndroid Build Coastguard Worker pps = *pps1; /* remove us from the list */
730*1c60b9acSAndroid Build Coastguard Worker *pps1 = NULL;
731*1c60b9acSAndroid Build Coastguard Worker continue;
732*1c60b9acSAndroid Build Coastguard Worker }
733*1c60b9acSAndroid Build Coastguard Worker } lws_end_foreach_llp(pps1, next);
734*1c60b9acSAndroid Build Coastguard Worker
735*1c60b9acSAndroid Build Coastguard Worker if (!pps)
736*1c60b9acSAndroid Build Coastguard Worker return 1;
737*1c60b9acSAndroid Build Coastguard Worker
738*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: %s: %d\n", __func__, lws_wsi_tag(wsi), pps->type);
739*1c60b9acSAndroid Build Coastguard Worker
740*1c60b9acSAndroid Build Coastguard Worker switch (pps->type) {
741*1c60b9acSAndroid Build Coastguard Worker
742*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_PPS_MY_SETTINGS:
743*1c60b9acSAndroid Build Coastguard Worker
744*1c60b9acSAndroid Build Coastguard Worker /*
745*1c60b9acSAndroid Build Coastguard Worker * if any of our settings varies from h2 "default defaults"
746*1c60b9acSAndroid Build Coastguard Worker * then we must inform the peer
747*1c60b9acSAndroid Build Coastguard Worker */
748*1c60b9acSAndroid Build Coastguard Worker for (n = 1; n < H2SET_COUNT; n++)
749*1c60b9acSAndroid Build Coastguard Worker if (h2n->our_set.s[n] != lws_h2_defaults.s[n]) {
750*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("sending SETTING %d 0x%x\n", n,
751*1c60b9acSAndroid Build Coastguard Worker (unsigned int)
752*1c60b9acSAndroid Build Coastguard Worker wsi->h2.h2n->our_set.s[n]);
753*1c60b9acSAndroid Build Coastguard Worker
754*1c60b9acSAndroid Build Coastguard Worker lws_h2_set_bin(wsi, n, &set[LWS_PRE + m]);
755*1c60b9acSAndroid Build Coastguard Worker m += (int)sizeof(h2n->one_setting);
756*1c60b9acSAndroid Build Coastguard Worker }
757*1c60b9acSAndroid Build Coastguard Worker n = lws_h2_frame_write(wsi, LWS_H2_FRAME_TYPE_SETTINGS,
758*1c60b9acSAndroid Build Coastguard Worker flags, LWS_H2_STREAM_ID_MASTER, (unsigned int)m,
759*1c60b9acSAndroid Build Coastguard Worker &set[LWS_PRE]);
760*1c60b9acSAndroid Build Coastguard Worker if (n != m) {
761*1c60b9acSAndroid Build Coastguard Worker lwsl_info("send %d %d\n", n, m);
762*1c60b9acSAndroid Build Coastguard Worker goto bail;
763*1c60b9acSAndroid Build Coastguard Worker }
764*1c60b9acSAndroid Build Coastguard Worker break;
765*1c60b9acSAndroid Build Coastguard Worker
766*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_PPS_SETTINGS_INITIAL_UPDATE_WINDOW:
767*1c60b9acSAndroid Build Coastguard Worker q = &set[LWS_PRE];
768*1c60b9acSAndroid Build Coastguard Worker *q++ = (uint8_t)(H2SET_INITIAL_WINDOW_SIZE >> 8);
769*1c60b9acSAndroid Build Coastguard Worker *q++ = (uint8_t)(H2SET_INITIAL_WINDOW_SIZE);
770*1c60b9acSAndroid Build Coastguard Worker *q++ = (uint8_t)(pps->u.update_window.credit >> 24);
771*1c60b9acSAndroid Build Coastguard Worker *q++ = (uint8_t)(pps->u.update_window.credit >> 16);
772*1c60b9acSAndroid Build Coastguard Worker *q++ = (uint8_t)(pps->u.update_window.credit >> 8);
773*1c60b9acSAndroid Build Coastguard Worker *q = (uint8_t)(pps->u.update_window.credit);
774*1c60b9acSAndroid Build Coastguard Worker
775*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: resetting initial window to %d\n", __func__,
776*1c60b9acSAndroid Build Coastguard Worker (int)pps->u.update_window.credit);
777*1c60b9acSAndroid Build Coastguard Worker
778*1c60b9acSAndroid Build Coastguard Worker n = lws_h2_frame_write(wsi, LWS_H2_FRAME_TYPE_SETTINGS,
779*1c60b9acSAndroid Build Coastguard Worker flags, LWS_H2_STREAM_ID_MASTER, 6,
780*1c60b9acSAndroid Build Coastguard Worker &set[LWS_PRE]);
781*1c60b9acSAndroid Build Coastguard Worker if (n != 6) {
782*1c60b9acSAndroid Build Coastguard Worker lwsl_info("send %d %d\n", n, m);
783*1c60b9acSAndroid Build Coastguard Worker goto bail;
784*1c60b9acSAndroid Build Coastguard Worker }
785*1c60b9acSAndroid Build Coastguard Worker break;
786*1c60b9acSAndroid Build Coastguard Worker
787*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_PPS_ACK_SETTINGS:
788*1c60b9acSAndroid Build Coastguard Worker /* send ack ... always empty */
789*1c60b9acSAndroid Build Coastguard Worker n = lws_h2_frame_write(wsi, LWS_H2_FRAME_TYPE_SETTINGS, 1,
790*1c60b9acSAndroid Build Coastguard Worker LWS_H2_STREAM_ID_MASTER, 0,
791*1c60b9acSAndroid Build Coastguard Worker &set[LWS_PRE]);
792*1c60b9acSAndroid Build Coastguard Worker if (n) {
793*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: writing settings ack frame failed %d\n", __func__, n);
794*1c60b9acSAndroid Build Coastguard Worker goto bail;
795*1c60b9acSAndroid Build Coastguard Worker }
796*1c60b9acSAndroid Build Coastguard Worker wsi->h2_acked_settings = 0;
797*1c60b9acSAndroid Build Coastguard Worker /* this is the end of the preface dance then? */
798*1c60b9acSAndroid Build Coastguard Worker if (lwsi_state(wsi) == LRS_H2_AWAIT_SETTINGS) {
799*1c60b9acSAndroid Build Coastguard Worker lwsi_set_state(wsi, LRS_ESTABLISHED);
800*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_FILE_OPS)
801*1c60b9acSAndroid Build Coastguard Worker wsi->http.fop_fd = NULL;
802*1c60b9acSAndroid Build Coastguard Worker #endif
803*1c60b9acSAndroid Build Coastguard Worker if (lws_is_ssl(lws_get_network_wsi(wsi)))
804*1c60b9acSAndroid Build Coastguard Worker break;
805*1c60b9acSAndroid Build Coastguard Worker
806*1c60b9acSAndroid Build Coastguard Worker if (wsi->a.vhost->options &
807*1c60b9acSAndroid Build Coastguard Worker LWS_SERVER_OPTION_H2_PRIOR_KNOWLEDGE)
808*1c60b9acSAndroid Build Coastguard Worker break;
809*1c60b9acSAndroid Build Coastguard Worker
810*1c60b9acSAndroid Build Coastguard Worker /*
811*1c60b9acSAndroid Build Coastguard Worker * we need to treat the headers from the upgrade as the
812*1c60b9acSAndroid Build Coastguard Worker * first job. So these need to get shifted to sid 1.
813*1c60b9acSAndroid Build Coastguard Worker */
814*1c60b9acSAndroid Build Coastguard Worker
815*1c60b9acSAndroid Build Coastguard Worker lws_context_lock(wsi->a.context, "h2 mig");
816*1c60b9acSAndroid Build Coastguard Worker lws_vhost_lock(wsi->a.vhost);
817*1c60b9acSAndroid Build Coastguard Worker
818*1c60b9acSAndroid Build Coastguard Worker h2n->swsi = __lws_wsi_server_new(wsi->a.vhost, wsi, 1);
819*1c60b9acSAndroid Build Coastguard Worker
820*1c60b9acSAndroid Build Coastguard Worker lws_vhost_unlock(wsi->a.vhost);
821*1c60b9acSAndroid Build Coastguard Worker lws_context_unlock(wsi->a.context);
822*1c60b9acSAndroid Build Coastguard Worker
823*1c60b9acSAndroid Build Coastguard Worker if (!h2n->swsi)
824*1c60b9acSAndroid Build Coastguard Worker goto bail;
825*1c60b9acSAndroid Build Coastguard Worker
826*1c60b9acSAndroid Build Coastguard Worker /* pass on the initial headers to SID 1 */
827*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->http.ah = wsi->http.ah;
828*1c60b9acSAndroid Build Coastguard Worker wsi->http.ah = NULL;
829*1c60b9acSAndroid Build Coastguard Worker
830*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: inherited headers %p\n", __func__,
831*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->http.ah);
832*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->txc.tx_cr = (int32_t)
833*1c60b9acSAndroid Build Coastguard Worker h2n->our_set.s[H2SET_INITIAL_WINDOW_SIZE];
834*1c60b9acSAndroid Build Coastguard Worker lwsl_info("initial tx credit on %s: %d\n",
835*1c60b9acSAndroid Build Coastguard Worker lws_wsi_tag(h2n->swsi),
836*1c60b9acSAndroid Build Coastguard Worker (int)h2n->swsi->txc.tx_cr);
837*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->h2.initialized = 1;
838*1c60b9acSAndroid Build Coastguard Worker /* demanded by HTTP2 */
839*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->h2.END_STREAM = 1;
840*1c60b9acSAndroid Build Coastguard Worker lwsl_info("servicing initial http request\n");
841*1c60b9acSAndroid Build Coastguard Worker
842*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SERVER)
843*1c60b9acSAndroid Build Coastguard Worker if (lws_http_action(h2n->swsi))
844*1c60b9acSAndroid Build Coastguard Worker goto bail;
845*1c60b9acSAndroid Build Coastguard Worker #endif
846*1c60b9acSAndroid Build Coastguard Worker break;
847*1c60b9acSAndroid Build Coastguard Worker }
848*1c60b9acSAndroid Build Coastguard Worker break;
849*1c60b9acSAndroid Build Coastguard Worker
850*1c60b9acSAndroid Build Coastguard Worker /*
851*1c60b9acSAndroid Build Coastguard Worker * h2 only has PING... ACK = 0 = ping, ACK = 1 = pong
852*1c60b9acSAndroid Build Coastguard Worker */
853*1c60b9acSAndroid Build Coastguard Worker
854*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_PPS_PING:
855*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_PPS_PONG:
856*1c60b9acSAndroid Build Coastguard Worker if (pps->type == LWS_H2_PPS_PING)
857*1c60b9acSAndroid Build Coastguard Worker lwsl_info("sending PING\n");
858*1c60b9acSAndroid Build Coastguard Worker else {
859*1c60b9acSAndroid Build Coastguard Worker lwsl_info("sending PONG\n");
860*1c60b9acSAndroid Build Coastguard Worker flags = LWS_H2_FLAG_SETTINGS_ACK;
861*1c60b9acSAndroid Build Coastguard Worker }
862*1c60b9acSAndroid Build Coastguard Worker
863*1c60b9acSAndroid Build Coastguard Worker memcpy(&set[LWS_PRE], pps->u.ping.ping_payload, 8);
864*1c60b9acSAndroid Build Coastguard Worker n = lws_h2_frame_write(wsi, LWS_H2_FRAME_TYPE_PING, flags,
865*1c60b9acSAndroid Build Coastguard Worker LWS_H2_STREAM_ID_MASTER, 8,
866*1c60b9acSAndroid Build Coastguard Worker &set[LWS_PRE]);
867*1c60b9acSAndroid Build Coastguard Worker if (n != 8)
868*1c60b9acSAndroid Build Coastguard Worker goto bail;
869*1c60b9acSAndroid Build Coastguard Worker
870*1c60b9acSAndroid Build Coastguard Worker break;
871*1c60b9acSAndroid Build Coastguard Worker
872*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_PPS_GOAWAY:
873*1c60b9acSAndroid Build Coastguard Worker lwsl_info("LWS_H2_PPS_GOAWAY\n");
874*1c60b9acSAndroid Build Coastguard Worker *p++ = (uint8_t)(pps->u.ga.highest_sid >> 24);
875*1c60b9acSAndroid Build Coastguard Worker *p++ = (uint8_t)(pps->u.ga.highest_sid >> 16);
876*1c60b9acSAndroid Build Coastguard Worker *p++ = (uint8_t)(pps->u.ga.highest_sid >> 8);
877*1c60b9acSAndroid Build Coastguard Worker *p++ = (uint8_t)(pps->u.ga.highest_sid);
878*1c60b9acSAndroid Build Coastguard Worker *p++ = (uint8_t)(pps->u.ga.err >> 24);
879*1c60b9acSAndroid Build Coastguard Worker *p++ = (uint8_t)(pps->u.ga.err >> 16);
880*1c60b9acSAndroid Build Coastguard Worker *p++ = (uint8_t)(pps->u.ga.err >> 8);
881*1c60b9acSAndroid Build Coastguard Worker *p++ = (uint8_t)(pps->u.ga.err);
882*1c60b9acSAndroid Build Coastguard Worker q = (unsigned char *)pps->u.ga.str;
883*1c60b9acSAndroid Build Coastguard Worker n = 0;
884*1c60b9acSAndroid Build Coastguard Worker while (*q && n++ < (int)sizeof(pps->u.ga.str))
885*1c60b9acSAndroid Build Coastguard Worker *p++ = *q++;
886*1c60b9acSAndroid Build Coastguard Worker h2n->we_told_goaway = 1;
887*1c60b9acSAndroid Build Coastguard Worker n = lws_h2_frame_write(wsi, LWS_H2_FRAME_TYPE_GOAWAY, 0,
888*1c60b9acSAndroid Build Coastguard Worker LWS_H2_STREAM_ID_MASTER,
889*1c60b9acSAndroid Build Coastguard Worker (unsigned int)lws_ptr_diff(p, &set[LWS_PRE]),
890*1c60b9acSAndroid Build Coastguard Worker &set[LWS_PRE]);
891*1c60b9acSAndroid Build Coastguard Worker if (n != 4) {
892*1c60b9acSAndroid Build Coastguard Worker lwsl_info("send %d %d\n", n, m);
893*1c60b9acSAndroid Build Coastguard Worker goto bail;
894*1c60b9acSAndroid Build Coastguard Worker }
895*1c60b9acSAndroid Build Coastguard Worker goto bail;
896*1c60b9acSAndroid Build Coastguard Worker
897*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_PPS_RST_STREAM:
898*1c60b9acSAndroid Build Coastguard Worker lwsl_info("LWS_H2_PPS_RST_STREAM\n");
899*1c60b9acSAndroid Build Coastguard Worker *p++ = (uint8_t)(pps->u.rs.err >> 24);
900*1c60b9acSAndroid Build Coastguard Worker *p++ = (uint8_t)(pps->u.rs.err >> 16);
901*1c60b9acSAndroid Build Coastguard Worker *p++ = (uint8_t)(pps->u.rs.err >> 8);
902*1c60b9acSAndroid Build Coastguard Worker *p++ = (uint8_t)(pps->u.rs.err);
903*1c60b9acSAndroid Build Coastguard Worker n = lws_h2_frame_write(wsi, LWS_H2_FRAME_TYPE_RST_STREAM,
904*1c60b9acSAndroid Build Coastguard Worker 0, pps->u.rs.sid, 4, &set[LWS_PRE]);
905*1c60b9acSAndroid Build Coastguard Worker if (n != 4) {
906*1c60b9acSAndroid Build Coastguard Worker lwsl_info("send %d %d\n", n, m);
907*1c60b9acSAndroid Build Coastguard Worker goto bail;
908*1c60b9acSAndroid Build Coastguard Worker }
909*1c60b9acSAndroid Build Coastguard Worker cwsi = lws_wsi_mux_from_id(wsi, pps->u.rs.sid);
910*1c60b9acSAndroid Build Coastguard Worker if (cwsi) {
911*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: closing cwsi %s %s %s (wsi %s)\n",
912*1c60b9acSAndroid Build Coastguard Worker __func__, lws_wsi_tag(cwsi),
913*1c60b9acSAndroid Build Coastguard Worker cwsi->role_ops->name,
914*1c60b9acSAndroid Build Coastguard Worker cwsi->a.protocol->name, lws_wsi_tag(wsi));
915*1c60b9acSAndroid Build Coastguard Worker lws_close_free_wsi(cwsi, 0, "reset stream");
916*1c60b9acSAndroid Build Coastguard Worker }
917*1c60b9acSAndroid Build Coastguard Worker break;
918*1c60b9acSAndroid Build Coastguard Worker
919*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_PPS_UPDATE_WINDOW:
920*1c60b9acSAndroid Build Coastguard Worker lwsl_info("Issuing LWS_H2_PPS_UPDATE_WINDOW: sid %d: add %d\n",
921*1c60b9acSAndroid Build Coastguard Worker (int)pps->u.update_window.sid,
922*1c60b9acSAndroid Build Coastguard Worker (int)pps->u.update_window.credit);
923*1c60b9acSAndroid Build Coastguard Worker *p++ = (uint8_t)((pps->u.update_window.credit >> 24) & 0x7f); /* 31b */
924*1c60b9acSAndroid Build Coastguard Worker *p++ = (uint8_t)(pps->u.update_window.credit >> 16);
925*1c60b9acSAndroid Build Coastguard Worker *p++ = (uint8_t)(pps->u.update_window.credit >> 8);
926*1c60b9acSAndroid Build Coastguard Worker *p++ = (uint8_t)(pps->u.update_window.credit);
927*1c60b9acSAndroid Build Coastguard Worker n = lws_h2_frame_write(wsi, LWS_H2_FRAME_TYPE_WINDOW_UPDATE,
928*1c60b9acSAndroid Build Coastguard Worker 0, pps->u.update_window.sid, 4,
929*1c60b9acSAndroid Build Coastguard Worker &set[LWS_PRE]);
930*1c60b9acSAndroid Build Coastguard Worker if (n != 4) {
931*1c60b9acSAndroid Build Coastguard Worker lwsl_info("send %d %d\n", n, m);
932*1c60b9acSAndroid Build Coastguard Worker goto bail;
933*1c60b9acSAndroid Build Coastguard Worker }
934*1c60b9acSAndroid Build Coastguard Worker break;
935*1c60b9acSAndroid Build Coastguard Worker
936*1c60b9acSAndroid Build Coastguard Worker default:
937*1c60b9acSAndroid Build Coastguard Worker break;
938*1c60b9acSAndroid Build Coastguard Worker }
939*1c60b9acSAndroid Build Coastguard Worker
940*1c60b9acSAndroid Build Coastguard Worker lws_free(pps);
941*1c60b9acSAndroid Build Coastguard Worker
942*1c60b9acSAndroid Build Coastguard Worker return 0;
943*1c60b9acSAndroid Build Coastguard Worker
944*1c60b9acSAndroid Build Coastguard Worker bail:
945*1c60b9acSAndroid Build Coastguard Worker lws_free(pps);
946*1c60b9acSAndroid Build Coastguard Worker
947*1c60b9acSAndroid Build Coastguard Worker return 1;
948*1c60b9acSAndroid Build Coastguard Worker }
949*1c60b9acSAndroid Build Coastguard Worker
950*1c60b9acSAndroid Build Coastguard Worker static int
951*1c60b9acSAndroid Build Coastguard Worker lws_h2_parse_end_of_frame(struct lws *wsi);
952*1c60b9acSAndroid Build Coastguard Worker
953*1c60b9acSAndroid Build Coastguard Worker /*
954*1c60b9acSAndroid Build Coastguard Worker * The frame header part has just completely arrived.
955*1c60b9acSAndroid Build Coastguard Worker * Perform actions for header completion.
956*1c60b9acSAndroid Build Coastguard Worker */
957*1c60b9acSAndroid Build Coastguard Worker static int
lws_h2_parse_frame_header(struct lws * wsi)958*1c60b9acSAndroid Build Coastguard Worker lws_h2_parse_frame_header(struct lws *wsi)
959*1c60b9acSAndroid Build Coastguard Worker {
960*1c60b9acSAndroid Build Coastguard Worker struct lws_h2_netconn *h2n = wsi->h2.h2n;
961*1c60b9acSAndroid Build Coastguard Worker struct lws_h2_protocol_send *pps;
962*1c60b9acSAndroid Build Coastguard Worker int n;
963*1c60b9acSAndroid Build Coastguard Worker
964*1c60b9acSAndroid Build Coastguard Worker /*
965*1c60b9acSAndroid Build Coastguard Worker * We just got the frame header
966*1c60b9acSAndroid Build Coastguard Worker */
967*1c60b9acSAndroid Build Coastguard Worker h2n->count = 0;
968*1c60b9acSAndroid Build Coastguard Worker h2n->swsi = wsi;
969*1c60b9acSAndroid Build Coastguard Worker /* b31 is a reserved bit */
970*1c60b9acSAndroid Build Coastguard Worker h2n->sid = h2n->sid & 0x7fffffff;
971*1c60b9acSAndroid Build Coastguard Worker
972*1c60b9acSAndroid Build Coastguard Worker if (h2n->sid && !(h2n->sid & 1)) {
973*1c60b9acSAndroid Build Coastguard Worker char pes[32];
974*1c60b9acSAndroid Build Coastguard Worker lws_snprintf(pes, sizeof(pes), "Even Stream ID 0x%x", (unsigned int)h2n->sid);
975*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR, pes);
976*1c60b9acSAndroid Build Coastguard Worker
977*1c60b9acSAndroid Build Coastguard Worker return 0;
978*1c60b9acSAndroid Build Coastguard Worker }
979*1c60b9acSAndroid Build Coastguard Worker
980*1c60b9acSAndroid Build Coastguard Worker /* let the network wsi live a bit longer if subs are active */
981*1c60b9acSAndroid Build Coastguard Worker
982*1c60b9acSAndroid Build Coastguard Worker if (!wsi->immortal_substream_count)
983*1c60b9acSAndroid Build Coastguard Worker lws_set_timeout(wsi, PENDING_TIMEOUT_HTTP_KEEPALIVE_IDLE,
984*1c60b9acSAndroid Build Coastguard Worker wsi->a.vhost->keepalive_timeout ?
985*1c60b9acSAndroid Build Coastguard Worker wsi->a.vhost->keepalive_timeout : 31);
986*1c60b9acSAndroid Build Coastguard Worker
987*1c60b9acSAndroid Build Coastguard Worker if (h2n->sid)
988*1c60b9acSAndroid Build Coastguard Worker h2n->swsi = lws_wsi_mux_from_id(wsi, h2n->sid);
989*1c60b9acSAndroid Build Coastguard Worker
990*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s (%s): fr hdr: typ 0x%x, fla 0x%x, sid 0x%x, len 0x%x\n",
991*1c60b9acSAndroid Build Coastguard Worker lws_wsi_tag(wsi), lws_wsi_tag(h2n->swsi), h2n->type,
992*1c60b9acSAndroid Build Coastguard Worker h2n->flags, (unsigned int)h2n->sid, (unsigned int)h2n->length);
993*1c60b9acSAndroid Build Coastguard Worker
994*1c60b9acSAndroid Build Coastguard Worker if (h2n->we_told_goaway && h2n->sid > h2n->highest_sid)
995*1c60b9acSAndroid Build Coastguard Worker h2n->type = LWS_H2_FRAME_TYPE_COUNT; /* ie, IGNORE */
996*1c60b9acSAndroid Build Coastguard Worker
997*1c60b9acSAndroid Build Coastguard Worker if (h2n->type >= LWS_H2_FRAME_TYPE_COUNT) {
998*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: ignoring unknown frame type %d (len %d)\n", __func__, h2n->type, (unsigned int)h2n->length);
999*1c60b9acSAndroid Build Coastguard Worker /* we MUST ignore frames we don't understand */
1000*1c60b9acSAndroid Build Coastguard Worker h2n->type = LWS_H2_FRAME_TYPE_COUNT;
1001*1c60b9acSAndroid Build Coastguard Worker }
1002*1c60b9acSAndroid Build Coastguard Worker
1003*1c60b9acSAndroid Build Coastguard Worker /*
1004*1c60b9acSAndroid Build Coastguard Worker * Even if we have decided to logically ignore this frame, we must
1005*1c60b9acSAndroid Build Coastguard Worker * consume the correct "frame length" amount of data to retain sync
1006*1c60b9acSAndroid Build Coastguard Worker */
1007*1c60b9acSAndroid Build Coastguard Worker
1008*1c60b9acSAndroid Build Coastguard Worker if (h2n->length > h2n->our_set.s[H2SET_MAX_FRAME_SIZE]) {
1009*1c60b9acSAndroid Build Coastguard Worker /*
1010*1c60b9acSAndroid Build Coastguard Worker * peer sent us something bigger than we told
1011*1c60b9acSAndroid Build Coastguard Worker * it we would allow
1012*1c60b9acSAndroid Build Coastguard Worker */
1013*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: received oversize frame %d\n", __func__,
1014*1c60b9acSAndroid Build Coastguard Worker (unsigned int)h2n->length);
1015*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, H2_ERR_FRAME_SIZE_ERROR,
1016*1c60b9acSAndroid Build Coastguard Worker "Peer ignored our frame size setting");
1017*1c60b9acSAndroid Build Coastguard Worker return 1;
1018*1c60b9acSAndroid Build Coastguard Worker }
1019*1c60b9acSAndroid Build Coastguard Worker
1020*1c60b9acSAndroid Build Coastguard Worker if (h2n->swsi)
1021*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: %s, State: %s, received cmd %d\n",
1022*1c60b9acSAndroid Build Coastguard Worker __func__, lws_wsi_tag(h2n->swsi),
1023*1c60b9acSAndroid Build Coastguard Worker h2_state_names[h2n->swsi->h2.h2_state], h2n->type);
1024*1c60b9acSAndroid Build Coastguard Worker else {
1025*1c60b9acSAndroid Build Coastguard Worker /* if it's data, either way no swsi means CLOSED state */
1026*1c60b9acSAndroid Build Coastguard Worker if (h2n->type == LWS_H2_FRAME_TYPE_DATA) {
1027*1c60b9acSAndroid Build Coastguard Worker if (h2n->sid <= h2n->highest_sid_opened
1028*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
1029*1c60b9acSAndroid Build Coastguard Worker && wsi->client_h2_alpn
1030*1c60b9acSAndroid Build Coastguard Worker #endif
1031*1c60b9acSAndroid Build Coastguard Worker ) {
1032*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("ignoring straggling data fl 0x%x\n",
1033*1c60b9acSAndroid Build Coastguard Worker h2n->flags);
1034*1c60b9acSAndroid Build Coastguard Worker /* ie, IGNORE */
1035*1c60b9acSAndroid Build Coastguard Worker h2n->type = LWS_H2_FRAME_TYPE_COUNT;
1036*1c60b9acSAndroid Build Coastguard Worker } else {
1037*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: received %d bytes data for unknown sid %d, highest known %d\n",
1038*1c60b9acSAndroid Build Coastguard Worker __func__, (int)h2n->length, (int)h2n->sid, (int)h2n->highest_sid_opened);
1039*1c60b9acSAndroid Build Coastguard Worker
1040*1c60b9acSAndroid Build Coastguard Worker // if (h2n->sid > h2n->highest_sid_opened) {
1041*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, H2_ERR_STREAM_CLOSED,
1042*1c60b9acSAndroid Build Coastguard Worker "Data for nonexistent sid");
1043*1c60b9acSAndroid Build Coastguard Worker return 0;
1044*1c60b9acSAndroid Build Coastguard Worker // }
1045*1c60b9acSAndroid Build Coastguard Worker }
1046*1c60b9acSAndroid Build Coastguard Worker }
1047*1c60b9acSAndroid Build Coastguard Worker /* if the sid is credible, treat as wsi for it closed */
1048*1c60b9acSAndroid Build Coastguard Worker if (h2n->sid > h2n->highest_sid_opened &&
1049*1c60b9acSAndroid Build Coastguard Worker h2n->type != LWS_H2_FRAME_TYPE_HEADERS &&
1050*1c60b9acSAndroid Build Coastguard Worker h2n->type != LWS_H2_FRAME_TYPE_PRIORITY) {
1051*1c60b9acSAndroid Build Coastguard Worker /* if not credible, reject it */
1052*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: %s, No child for sid %d, rxcmd %d\n",
1053*1c60b9acSAndroid Build Coastguard Worker __func__, lws_wsi_tag(h2n->swsi), (unsigned int)h2n->sid, h2n->type);
1054*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, H2_ERR_STREAM_CLOSED,
1055*1c60b9acSAndroid Build Coastguard Worker "Data for nonexistent sid");
1056*1c60b9acSAndroid Build Coastguard Worker return 0;
1057*1c60b9acSAndroid Build Coastguard Worker }
1058*1c60b9acSAndroid Build Coastguard Worker }
1059*1c60b9acSAndroid Build Coastguard Worker
1060*1c60b9acSAndroid Build Coastguard Worker if (h2n->swsi && h2n->sid && h2n->type != LWS_H2_FRAME_TYPE_COUNT &&
1061*1c60b9acSAndroid Build Coastguard Worker !(http2_rx_validity[h2n->swsi->h2.h2_state] & (1 << h2n->type))) {
1062*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: %s, State: %s, ILLEGAL cmdrx %d (OK 0x%x)\n",
1063*1c60b9acSAndroid Build Coastguard Worker __func__, lws_wsi_tag(h2n->swsi),
1064*1c60b9acSAndroid Build Coastguard Worker h2_state_names[h2n->swsi->h2.h2_state], h2n->type,
1065*1c60b9acSAndroid Build Coastguard Worker http2_rx_validity[h2n->swsi->h2.h2_state]);
1066*1c60b9acSAndroid Build Coastguard Worker
1067*1c60b9acSAndroid Build Coastguard Worker if (h2n->swsi->h2.h2_state == LWS_H2_STATE_CLOSED ||
1068*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->h2.h2_state == LWS_H2_STATE_HALF_CLOSED_REMOTE)
1069*1c60b9acSAndroid Build Coastguard Worker n = H2_ERR_STREAM_CLOSED;
1070*1c60b9acSAndroid Build Coastguard Worker else
1071*1c60b9acSAndroid Build Coastguard Worker n = H2_ERR_PROTOCOL_ERROR;
1072*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, (unsigned int)n, "invalid rx for state");
1073*1c60b9acSAndroid Build Coastguard Worker
1074*1c60b9acSAndroid Build Coastguard Worker return 0;
1075*1c60b9acSAndroid Build Coastguard Worker }
1076*1c60b9acSAndroid Build Coastguard Worker
1077*1c60b9acSAndroid Build Coastguard Worker if (h2n->cont_exp && h2n->type != LWS_H2_FRAME_TYPE_COUNT &&
1078*1c60b9acSAndroid Build Coastguard Worker (h2n->cont_exp_sid != h2n->sid ||
1079*1c60b9acSAndroid Build Coastguard Worker h2n->type != LWS_H2_FRAME_TYPE_CONTINUATION)) {
1080*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: expected cont on sid %u (got %d on sid %u)\n",
1081*1c60b9acSAndroid Build Coastguard Worker __func__, (unsigned int)h2n->cont_exp_sid, h2n->type,
1082*1c60b9acSAndroid Build Coastguard Worker (unsigned int)h2n->sid);
1083*1c60b9acSAndroid Build Coastguard Worker h2n->cont_exp = 0;
1084*1c60b9acSAndroid Build Coastguard Worker if (h2n->cont_exp_headers)
1085*1c60b9acSAndroid Build Coastguard Worker n = H2_ERR_COMPRESSION_ERROR;
1086*1c60b9acSAndroid Build Coastguard Worker else
1087*1c60b9acSAndroid Build Coastguard Worker n = H2_ERR_PROTOCOL_ERROR;
1088*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, (unsigned int)n, "Continuation hdrs State");
1089*1c60b9acSAndroid Build Coastguard Worker
1090*1c60b9acSAndroid Build Coastguard Worker return 0;
1091*1c60b9acSAndroid Build Coastguard Worker }
1092*1c60b9acSAndroid Build Coastguard Worker
1093*1c60b9acSAndroid Build Coastguard Worker switch (h2n->type) {
1094*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_FRAME_TYPE_DATA:
1095*1c60b9acSAndroid Build Coastguard Worker lwsl_info("seen incoming LWS_H2_FRAME_TYPE_DATA start\n");
1096*1c60b9acSAndroid Build Coastguard Worker if (!h2n->sid) {
1097*1c60b9acSAndroid Build Coastguard Worker lwsl_info("DATA: 0 sid\n");
1098*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR, "DATA 0 sid");
1099*1c60b9acSAndroid Build Coastguard Worker break;
1100*1c60b9acSAndroid Build Coastguard Worker }
1101*1c60b9acSAndroid Build Coastguard Worker lwsl_info("Frame header DATA: sid %u, flags 0x%x, len %u\n",
1102*1c60b9acSAndroid Build Coastguard Worker (unsigned int)h2n->sid, h2n->flags,
1103*1c60b9acSAndroid Build Coastguard Worker (unsigned int)h2n->length);
1104*1c60b9acSAndroid Build Coastguard Worker
1105*1c60b9acSAndroid Build Coastguard Worker if (!h2n->swsi) {
1106*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("DATA: NULL swsi\n");
1107*1c60b9acSAndroid Build Coastguard Worker break;
1108*1c60b9acSAndroid Build Coastguard Worker }
1109*1c60b9acSAndroid Build Coastguard Worker
1110*1c60b9acSAndroid Build Coastguard Worker lwsl_info("DATA rx on state %d\n", h2n->swsi->h2.h2_state);
1111*1c60b9acSAndroid Build Coastguard Worker
1112*1c60b9acSAndroid Build Coastguard Worker if (
1113*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->h2.h2_state == LWS_H2_STATE_HALF_CLOSED_REMOTE ||
1114*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->h2.h2_state == LWS_H2_STATE_CLOSED) {
1115*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, H2_ERR_STREAM_CLOSED, "conn closed");
1116*1c60b9acSAndroid Build Coastguard Worker break;
1117*1c60b9acSAndroid Build Coastguard Worker }
1118*1c60b9acSAndroid Build Coastguard Worker
1119*1c60b9acSAndroid Build Coastguard Worker if (h2n->length == 0)
1120*1c60b9acSAndroid Build Coastguard Worker lws_h2_parse_end_of_frame(wsi);
1121*1c60b9acSAndroid Build Coastguard Worker
1122*1c60b9acSAndroid Build Coastguard Worker break;
1123*1c60b9acSAndroid Build Coastguard Worker
1124*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_FRAME_TYPE_PRIORITY:
1125*1c60b9acSAndroid Build Coastguard Worker lwsl_info("LWS_H2_FRAME_TYPE_PRIORITY complete frame\n");
1126*1c60b9acSAndroid Build Coastguard Worker if (!h2n->sid) {
1127*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR,
1128*1c60b9acSAndroid Build Coastguard Worker "Priority has 0 sid");
1129*1c60b9acSAndroid Build Coastguard Worker break;
1130*1c60b9acSAndroid Build Coastguard Worker }
1131*1c60b9acSAndroid Build Coastguard Worker if (h2n->length != 5) {
1132*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, H2_ERR_FRAME_SIZE_ERROR,
1133*1c60b9acSAndroid Build Coastguard Worker "Priority has length other than 5");
1134*1c60b9acSAndroid Build Coastguard Worker break;
1135*1c60b9acSAndroid Build Coastguard Worker }
1136*1c60b9acSAndroid Build Coastguard Worker break;
1137*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_FRAME_TYPE_PUSH_PROMISE:
1138*1c60b9acSAndroid Build Coastguard Worker lwsl_info("LWS_H2_FRAME_TYPE_PUSH_PROMISE complete frame\n");
1139*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR, "Server only");
1140*1c60b9acSAndroid Build Coastguard Worker break;
1141*1c60b9acSAndroid Build Coastguard Worker
1142*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_FRAME_TYPE_GOAWAY:
1143*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("LWS_H2_FRAME_TYPE_GOAWAY received\n");
1144*1c60b9acSAndroid Build Coastguard Worker break;
1145*1c60b9acSAndroid Build Coastguard Worker
1146*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_FRAME_TYPE_RST_STREAM:
1147*1c60b9acSAndroid Build Coastguard Worker if (!h2n->sid)
1148*1c60b9acSAndroid Build Coastguard Worker return 1;
1149*1c60b9acSAndroid Build Coastguard Worker if (!h2n->swsi) {
1150*1c60b9acSAndroid Build Coastguard Worker if (h2n->sid <= h2n->highest_sid_opened)
1151*1c60b9acSAndroid Build Coastguard Worker break;
1152*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR,
1153*1c60b9acSAndroid Build Coastguard Worker "crazy sid on RST_STREAM");
1154*1c60b9acSAndroid Build Coastguard Worker return 1;
1155*1c60b9acSAndroid Build Coastguard Worker }
1156*1c60b9acSAndroid Build Coastguard Worker if (h2n->length != 4) {
1157*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, H2_ERR_FRAME_SIZE_ERROR,
1158*1c60b9acSAndroid Build Coastguard Worker "RST_STREAM can only be length 4");
1159*1c60b9acSAndroid Build Coastguard Worker break;
1160*1c60b9acSAndroid Build Coastguard Worker }
1161*1c60b9acSAndroid Build Coastguard Worker lws_h2_state(h2n->swsi, LWS_H2_STATE_CLOSED);
1162*1c60b9acSAndroid Build Coastguard Worker break;
1163*1c60b9acSAndroid Build Coastguard Worker
1164*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_FRAME_TYPE_SETTINGS:
1165*1c60b9acSAndroid Build Coastguard Worker lwsl_info("LWS_H2_FRAME_TYPE_SETTINGS complete frame\n");
1166*1c60b9acSAndroid Build Coastguard Worker /* nonzero sid on settings is illegal */
1167*1c60b9acSAndroid Build Coastguard Worker if (h2n->sid) {
1168*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR,
1169*1c60b9acSAndroid Build Coastguard Worker "Settings has nonzero sid");
1170*1c60b9acSAndroid Build Coastguard Worker break;
1171*1c60b9acSAndroid Build Coastguard Worker }
1172*1c60b9acSAndroid Build Coastguard Worker
1173*1c60b9acSAndroid Build Coastguard Worker if (!(h2n->flags & LWS_H2_FLAG_SETTINGS_ACK)) {
1174*1c60b9acSAndroid Build Coastguard Worker if (h2n->length % 6) {
1175*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, H2_ERR_FRAME_SIZE_ERROR,
1176*1c60b9acSAndroid Build Coastguard Worker "Settings length error");
1177*1c60b9acSAndroid Build Coastguard Worker break;
1178*1c60b9acSAndroid Build Coastguard Worker }
1179*1c60b9acSAndroid Build Coastguard Worker
1180*1c60b9acSAndroid Build Coastguard Worker if (h2n->type == LWS_H2_FRAME_TYPE_COUNT)
1181*1c60b9acSAndroid Build Coastguard Worker return 0;
1182*1c60b9acSAndroid Build Coastguard Worker
1183*1c60b9acSAndroid Build Coastguard Worker if (wsi->upgraded_to_http2 &&
1184*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
1185*1c60b9acSAndroid Build Coastguard Worker (!(wsi->flags & LCCSCF_H2_QUIRK_NGHTTP2_END_STREAM) ||
1186*1c60b9acSAndroid Build Coastguard Worker #else
1187*1c60b9acSAndroid Build Coastguard Worker (
1188*1c60b9acSAndroid Build Coastguard Worker #endif
1189*1c60b9acSAndroid Build Coastguard Worker !wsi->h2_acked_settings)) {
1190*1c60b9acSAndroid Build Coastguard Worker
1191*1c60b9acSAndroid Build Coastguard Worker pps = lws_h2_new_pps(LWS_H2_PPS_ACK_SETTINGS);
1192*1c60b9acSAndroid Build Coastguard Worker if (!pps)
1193*1c60b9acSAndroid Build Coastguard Worker return 1;
1194*1c60b9acSAndroid Build Coastguard Worker lws_pps_schedule(wsi, pps);
1195*1c60b9acSAndroid Build Coastguard Worker wsi->h2_acked_settings = 1;
1196*1c60b9acSAndroid Build Coastguard Worker }
1197*1c60b9acSAndroid Build Coastguard Worker break;
1198*1c60b9acSAndroid Build Coastguard Worker }
1199*1c60b9acSAndroid Build Coastguard Worker /* came to us with ACK set... not allowed to have payload */
1200*1c60b9acSAndroid Build Coastguard Worker
1201*1c60b9acSAndroid Build Coastguard Worker if (h2n->length) {
1202*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, H2_ERR_FRAME_SIZE_ERROR,
1203*1c60b9acSAndroid Build Coastguard Worker "Settings with ACK not allowed payload");
1204*1c60b9acSAndroid Build Coastguard Worker break;
1205*1c60b9acSAndroid Build Coastguard Worker }
1206*1c60b9acSAndroid Build Coastguard Worker break;
1207*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_FRAME_TYPE_PING:
1208*1c60b9acSAndroid Build Coastguard Worker if (h2n->sid) {
1209*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR,
1210*1c60b9acSAndroid Build Coastguard Worker "Ping has nonzero sid");
1211*1c60b9acSAndroid Build Coastguard Worker break;
1212*1c60b9acSAndroid Build Coastguard Worker }
1213*1c60b9acSAndroid Build Coastguard Worker if (h2n->length != 8) {
1214*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, H2_ERR_FRAME_SIZE_ERROR,
1215*1c60b9acSAndroid Build Coastguard Worker "Ping payload can only be 8");
1216*1c60b9acSAndroid Build Coastguard Worker break;
1217*1c60b9acSAndroid Build Coastguard Worker }
1218*1c60b9acSAndroid Build Coastguard Worker break;
1219*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_FRAME_TYPE_CONTINUATION:
1220*1c60b9acSAndroid Build Coastguard Worker lwsl_info("LWS_H2_FRAME_TYPE_CONTINUATION: sid = %u %d %d\n",
1221*1c60b9acSAndroid Build Coastguard Worker (unsigned int)h2n->sid, (int)h2n->cont_exp,
1222*1c60b9acSAndroid Build Coastguard Worker (int)h2n->cont_exp_sid);
1223*1c60b9acSAndroid Build Coastguard Worker
1224*1c60b9acSAndroid Build Coastguard Worker if (!h2n->cont_exp ||
1225*1c60b9acSAndroid Build Coastguard Worker h2n->cont_exp_sid != h2n->sid ||
1226*1c60b9acSAndroid Build Coastguard Worker !h2n->sid ||
1227*1c60b9acSAndroid Build Coastguard Worker !h2n->swsi) {
1228*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR,
1229*1c60b9acSAndroid Build Coastguard Worker "unexpected CONTINUATION");
1230*1c60b9acSAndroid Build Coastguard Worker break;
1231*1c60b9acSAndroid Build Coastguard Worker }
1232*1c60b9acSAndroid Build Coastguard Worker
1233*1c60b9acSAndroid Build Coastguard Worker if (h2n->swsi->h2.END_HEADERS) {
1234*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR,
1235*1c60b9acSAndroid Build Coastguard Worker "END_HEADERS already seen");
1236*1c60b9acSAndroid Build Coastguard Worker break;
1237*1c60b9acSAndroid Build Coastguard Worker }
1238*1c60b9acSAndroid Build Coastguard Worker /* END_STREAM is in HEADERS, skip resetting it */
1239*1c60b9acSAndroid Build Coastguard Worker goto update_end_headers;
1240*1c60b9acSAndroid Build Coastguard Worker
1241*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_FRAME_TYPE_HEADERS:
1242*1c60b9acSAndroid Build Coastguard Worker lwsl_info("HEADERS: frame header: sid = %u\n",
1243*1c60b9acSAndroid Build Coastguard Worker (unsigned int)h2n->sid);
1244*1c60b9acSAndroid Build Coastguard Worker if (!h2n->sid) {
1245*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR, "sid 0");
1246*1c60b9acSAndroid Build Coastguard Worker return 1;
1247*1c60b9acSAndroid Build Coastguard Worker }
1248*1c60b9acSAndroid Build Coastguard Worker
1249*1c60b9acSAndroid Build Coastguard Worker if (h2n->swsi && !h2n->swsi->h2.END_STREAM &&
1250*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->h2.END_HEADERS &&
1251*1c60b9acSAndroid Build Coastguard Worker !(h2n->flags & LWS_H2_FLAG_END_STREAM)) {
1252*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR,
1253*1c60b9acSAndroid Build Coastguard Worker "extra HEADERS together");
1254*1c60b9acSAndroid Build Coastguard Worker return 1;
1255*1c60b9acSAndroid Build Coastguard Worker }
1256*1c60b9acSAndroid Build Coastguard Worker
1257*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
1258*1c60b9acSAndroid Build Coastguard Worker if (wsi->client_h2_alpn) {
1259*1c60b9acSAndroid Build Coastguard Worker if (h2n->sid) {
1260*1c60b9acSAndroid Build Coastguard Worker h2n->swsi = lws_wsi_mux_from_id(wsi, h2n->sid);
1261*1c60b9acSAndroid Build Coastguard Worker lwsl_info("HEADERS: nwsi %s: sid %u mapped "
1262*1c60b9acSAndroid Build Coastguard Worker "to wsi %s\n", lws_wsi_tag(wsi),
1263*1c60b9acSAndroid Build Coastguard Worker (unsigned int)h2n->sid,
1264*1c60b9acSAndroid Build Coastguard Worker lws_wsi_tag(h2n->swsi));
1265*1c60b9acSAndroid Build Coastguard Worker if (!h2n->swsi)
1266*1c60b9acSAndroid Build Coastguard Worker break;
1267*1c60b9acSAndroid Build Coastguard Worker }
1268*1c60b9acSAndroid Build Coastguard Worker goto update_end_headers;
1269*1c60b9acSAndroid Build Coastguard Worker }
1270*1c60b9acSAndroid Build Coastguard Worker #endif
1271*1c60b9acSAndroid Build Coastguard Worker
1272*1c60b9acSAndroid Build Coastguard Worker if (!h2n->swsi) {
1273*1c60b9acSAndroid Build Coastguard Worker /* no more children allowed by parent */
1274*1c60b9acSAndroid Build Coastguard Worker if (wsi->mux.child_count + 1 >
1275*1c60b9acSAndroid Build Coastguard Worker wsi->h2.h2n->our_set.s[H2SET_MAX_CONCURRENT_STREAMS]) {
1276*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR,
1277*1c60b9acSAndroid Build Coastguard Worker "Another stream not allowed");
1278*1c60b9acSAndroid Build Coastguard Worker
1279*1c60b9acSAndroid Build Coastguard Worker return 1;
1280*1c60b9acSAndroid Build Coastguard Worker }
1281*1c60b9acSAndroid Build Coastguard Worker
1282*1c60b9acSAndroid Build Coastguard Worker /*
1283*1c60b9acSAndroid Build Coastguard Worker * The peer has sent us a HEADERS implying the creation
1284*1c60b9acSAndroid Build Coastguard Worker * of a new stream
1285*1c60b9acSAndroid Build Coastguard Worker */
1286*1c60b9acSAndroid Build Coastguard Worker
1287*1c60b9acSAndroid Build Coastguard Worker lws_context_lock(wsi->a.context, "h2 new str");
1288*1c60b9acSAndroid Build Coastguard Worker lws_vhost_lock(wsi->a.vhost);
1289*1c60b9acSAndroid Build Coastguard Worker
1290*1c60b9acSAndroid Build Coastguard Worker h2n->swsi = __lws_wsi_server_new(wsi->a.vhost, wsi,
1291*1c60b9acSAndroid Build Coastguard Worker h2n->sid);
1292*1c60b9acSAndroid Build Coastguard Worker
1293*1c60b9acSAndroid Build Coastguard Worker lws_vhost_unlock(wsi->a.vhost);
1294*1c60b9acSAndroid Build Coastguard Worker lws_context_unlock(wsi->a.context);
1295*1c60b9acSAndroid Build Coastguard Worker
1296*1c60b9acSAndroid Build Coastguard Worker if (!h2n->swsi) {
1297*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR,
1298*1c60b9acSAndroid Build Coastguard Worker "OOM");
1299*1c60b9acSAndroid Build Coastguard Worker
1300*1c60b9acSAndroid Build Coastguard Worker return 1;
1301*1c60b9acSAndroid Build Coastguard Worker }
1302*1c60b9acSAndroid Build Coastguard Worker
1303*1c60b9acSAndroid Build Coastguard Worker if (h2n->sid >= h2n->highest_sid)
1304*1c60b9acSAndroid Build Coastguard Worker h2n->highest_sid = h2n->sid + 2;
1305*1c60b9acSAndroid Build Coastguard Worker
1306*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->h2.initialized = 1;
1307*1c60b9acSAndroid Build Coastguard Worker
1308*1c60b9acSAndroid Build Coastguard Worker if (lws_h2_update_peer_txcredit(h2n->swsi,
1309*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->mux.my_sid, 4 * 65536))
1310*1c60b9acSAndroid Build Coastguard Worker goto cleanup_wsi;
1311*1c60b9acSAndroid Build Coastguard Worker }
1312*1c60b9acSAndroid Build Coastguard Worker
1313*1c60b9acSAndroid Build Coastguard Worker /*
1314*1c60b9acSAndroid Build Coastguard Worker * ah needs attaching to child wsi, even though
1315*1c60b9acSAndroid Build Coastguard Worker * we only fill it from network wsi
1316*1c60b9acSAndroid Build Coastguard Worker */
1317*1c60b9acSAndroid Build Coastguard Worker if (!h2n->swsi->http.ah)
1318*1c60b9acSAndroid Build Coastguard Worker if (lws_header_table_attach(h2n->swsi, 0)) {
1319*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: Failed to get ah\n", __func__);
1320*1c60b9acSAndroid Build Coastguard Worker return 1;
1321*1c60b9acSAndroid Build Coastguard Worker }
1322*1c60b9acSAndroid Build Coastguard Worker
1323*1c60b9acSAndroid Build Coastguard Worker /*
1324*1c60b9acSAndroid Build Coastguard Worker * The first use of a new stream identifier implicitly closes
1325*1c60b9acSAndroid Build Coastguard Worker * all streams in the "idle" state that might have been
1326*1c60b9acSAndroid Build Coastguard Worker * initiated by that peer with a lower-valued stream identifier.
1327*1c60b9acSAndroid Build Coastguard Worker *
1328*1c60b9acSAndroid Build Coastguard Worker * For example, if a client sends a HEADERS frame on stream 7
1329*1c60b9acSAndroid Build Coastguard Worker * without ever sending a frame on stream 5, then stream 5
1330*1c60b9acSAndroid Build Coastguard Worker * transitions to the "closed" state when the first frame for
1331*1c60b9acSAndroid Build Coastguard Worker * stream 7 is sent or received.
1332*1c60b9acSAndroid Build Coastguard Worker */
1333*1c60b9acSAndroid Build Coastguard Worker lws_start_foreach_ll(struct lws *, w, wsi->mux.child_list) {
1334*1c60b9acSAndroid Build Coastguard Worker if (w->mux.my_sid < h2n->sid &&
1335*1c60b9acSAndroid Build Coastguard Worker w->h2.h2_state == LWS_H2_STATE_IDLE)
1336*1c60b9acSAndroid Build Coastguard Worker lws_close_free_wsi(w, 0, "h2 sid close");
1337*1c60b9acSAndroid Build Coastguard Worker assert(w->mux.sibling_list != w);
1338*1c60b9acSAndroid Build Coastguard Worker } lws_end_foreach_ll(w, mux.sibling_list);
1339*1c60b9acSAndroid Build Coastguard Worker
1340*1c60b9acSAndroid Build Coastguard Worker h2n->cont_exp = !(h2n->flags & LWS_H2_FLAG_END_HEADERS);
1341*1c60b9acSAndroid Build Coastguard Worker h2n->cont_exp_sid = h2n->sid;
1342*1c60b9acSAndroid Build Coastguard Worker h2n->cont_exp_headers = 1;
1343*1c60b9acSAndroid Build Coastguard Worker // lws_header_table_reset(h2n->swsi, 0);
1344*1c60b9acSAndroid Build Coastguard Worker
1345*1c60b9acSAndroid Build Coastguard Worker update_end_headers:
1346*1c60b9acSAndroid Build Coastguard Worker if (lws_check_opt(h2n->swsi->a.vhost->options,
1347*1c60b9acSAndroid Build Coastguard Worker LWS_SERVER_OPTION_VH_H2_HALF_CLOSED_LONG_POLL)) {
1348*1c60b9acSAndroid Build Coastguard Worker
1349*1c60b9acSAndroid Build Coastguard Worker /*
1350*1c60b9acSAndroid Build Coastguard Worker * We don't directly timeout streams that enter the
1351*1c60b9acSAndroid Build Coastguard Worker * half-closed remote state, allowing immortal long
1352*1c60b9acSAndroid Build Coastguard Worker * poll
1353*1c60b9acSAndroid Build Coastguard Worker */
1354*1c60b9acSAndroid Build Coastguard Worker lws_mux_mark_immortal(h2n->swsi);
1355*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: %s: h2 stream entering long poll\n",
1356*1c60b9acSAndroid Build Coastguard Worker __func__, lws_wsi_tag(h2n->swsi));
1357*1c60b9acSAndroid Build Coastguard Worker
1358*1c60b9acSAndroid Build Coastguard Worker } else {
1359*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->h2.END_STREAM =
1360*1c60b9acSAndroid Build Coastguard Worker !!(h2n->flags & LWS_H2_FLAG_END_STREAM);
1361*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: hdr END_STREAM = %d\n",__func__,
1362*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->h2.END_STREAM);
1363*1c60b9acSAndroid Build Coastguard Worker }
1364*1c60b9acSAndroid Build Coastguard Worker
1365*1c60b9acSAndroid Build Coastguard Worker /* no END_HEADERS means CONTINUATION must come */
1366*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->h2.END_HEADERS =
1367*1c60b9acSAndroid Build Coastguard Worker !!(h2n->flags & LWS_H2_FLAG_END_HEADERS);
1368*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: %s: END_HEADERS %d\n", __func__, lws_wsi_tag(h2n->swsi),
1369*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->h2.END_HEADERS);
1370*1c60b9acSAndroid Build Coastguard Worker if (h2n->swsi->h2.END_HEADERS)
1371*1c60b9acSAndroid Build Coastguard Worker h2n->cont_exp = 0;
1372*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("END_HEADERS %d\n", h2n->swsi->h2.END_HEADERS);
1373*1c60b9acSAndroid Build Coastguard Worker break;
1374*1c60b9acSAndroid Build Coastguard Worker
1375*1c60b9acSAndroid Build Coastguard Worker cleanup_wsi:
1376*1c60b9acSAndroid Build Coastguard Worker
1377*1c60b9acSAndroid Build Coastguard Worker return 1;
1378*1c60b9acSAndroid Build Coastguard Worker
1379*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_FRAME_TYPE_WINDOW_UPDATE:
1380*1c60b9acSAndroid Build Coastguard Worker if (h2n->length != 4) {
1381*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, H2_ERR_FRAME_SIZE_ERROR,
1382*1c60b9acSAndroid Build Coastguard Worker "window update frame not 4");
1383*1c60b9acSAndroid Build Coastguard Worker break;
1384*1c60b9acSAndroid Build Coastguard Worker }
1385*1c60b9acSAndroid Build Coastguard Worker lwsl_info("LWS_H2_FRAME_TYPE_WINDOW_UPDATE\n");
1386*1c60b9acSAndroid Build Coastguard Worker break;
1387*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_FRAME_TYPE_COUNT:
1388*1c60b9acSAndroid Build Coastguard Worker if (h2n->length == 0)
1389*1c60b9acSAndroid Build Coastguard Worker lws_h2_parse_end_of_frame(wsi);
1390*1c60b9acSAndroid Build Coastguard Worker else
1391*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: going on to deal with unknown frame remaining len %d\n", __func__, (unsigned int)h2n->length);
1392*1c60b9acSAndroid Build Coastguard Worker break;
1393*1c60b9acSAndroid Build Coastguard Worker default:
1394*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: ILLEGAL FRAME TYPE %d\n", __func__, h2n->type);
1395*1c60b9acSAndroid Build Coastguard Worker h2n->type = LWS_H2_FRAME_TYPE_COUNT; /* ie, IGNORE */
1396*1c60b9acSAndroid Build Coastguard Worker break;
1397*1c60b9acSAndroid Build Coastguard Worker }
1398*1c60b9acSAndroid Build Coastguard Worker if (h2n->length == 0)
1399*1c60b9acSAndroid Build Coastguard Worker h2n->frame_state = 0;
1400*1c60b9acSAndroid Build Coastguard Worker
1401*1c60b9acSAndroid Build Coastguard Worker return 0;
1402*1c60b9acSAndroid Build Coastguard Worker }
1403*1c60b9acSAndroid Build Coastguard Worker
1404*1c60b9acSAndroid Build Coastguard Worker static const char * const method_names[] = {
1405*1c60b9acSAndroid Build Coastguard Worker "GET", "POST",
1406*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS)
1407*1c60b9acSAndroid Build Coastguard Worker "OPTIONS", "PUT", "PATCH", "DELETE",
1408*1c60b9acSAndroid Build Coastguard Worker #endif
1409*1c60b9acSAndroid Build Coastguard Worker "CONNECT", "HEAD"
1410*1c60b9acSAndroid Build Coastguard Worker };
1411*1c60b9acSAndroid Build Coastguard Worker static unsigned char method_index[] = {
1412*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_GET_URI,
1413*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_POST_URI,
1414*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS)
1415*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_OPTIONS_URI,
1416*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_PUT_URI,
1417*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_PATCH_URI,
1418*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_DELETE_URI,
1419*1c60b9acSAndroid Build Coastguard Worker #endif
1420*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_CONNECT,
1421*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HEAD_URI,
1422*1c60b9acSAndroid Build Coastguard Worker };
1423*1c60b9acSAndroid Build Coastguard Worker
1424*1c60b9acSAndroid Build Coastguard Worker /*
1425*1c60b9acSAndroid Build Coastguard Worker * The last byte of the whole frame has been handled.
1426*1c60b9acSAndroid Build Coastguard Worker * Perform actions for frame completion.
1427*1c60b9acSAndroid Build Coastguard Worker *
1428*1c60b9acSAndroid Build Coastguard Worker * This is the crunch time for parsing that may have occured on a network
1429*1c60b9acSAndroid Build Coastguard Worker * wsi with a pending partial send... we may call lws_http_action() to send
1430*1c60b9acSAndroid Build Coastguard Worker * a response, conflicting with the partial.
1431*1c60b9acSAndroid Build Coastguard Worker *
1432*1c60b9acSAndroid Build Coastguard Worker * So in that case we change the wsi state and do the lws_http_action() in the
1433*1c60b9acSAndroid Build Coastguard Worker * WRITABLE handler as a priority.
1434*1c60b9acSAndroid Build Coastguard Worker */
1435*1c60b9acSAndroid Build Coastguard Worker static int
lws_h2_parse_end_of_frame(struct lws * wsi)1436*1c60b9acSAndroid Build Coastguard Worker lws_h2_parse_end_of_frame(struct lws *wsi)
1437*1c60b9acSAndroid Build Coastguard Worker {
1438*1c60b9acSAndroid Build Coastguard Worker struct lws_h2_netconn *h2n = wsi->h2.h2n;
1439*1c60b9acSAndroid Build Coastguard Worker struct lws *eff_wsi = wsi;
1440*1c60b9acSAndroid Build Coastguard Worker const char *p;
1441*1c60b9acSAndroid Build Coastguard Worker int n;
1442*1c60b9acSAndroid Build Coastguard Worker
1443*1c60b9acSAndroid Build Coastguard Worker h2n->frame_state = 0;
1444*1c60b9acSAndroid Build Coastguard Worker h2n->count = 0;
1445*1c60b9acSAndroid Build Coastguard Worker
1446*1c60b9acSAndroid Build Coastguard Worker if (h2n->sid)
1447*1c60b9acSAndroid Build Coastguard Worker h2n->swsi = lws_wsi_mux_from_id(wsi, h2n->sid);
1448*1c60b9acSAndroid Build Coastguard Worker
1449*1c60b9acSAndroid Build Coastguard Worker if (h2n->sid > h2n->highest_sid)
1450*1c60b9acSAndroid Build Coastguard Worker h2n->highest_sid = h2n->sid;
1451*1c60b9acSAndroid Build Coastguard Worker
1452*1c60b9acSAndroid Build Coastguard Worker if (h2n->collected_priority && (h2n->dep & ~(1u << 31)) == h2n->sid) {
1453*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR, "depends on own sid");
1454*1c60b9acSAndroid Build Coastguard Worker return 0;
1455*1c60b9acSAndroid Build Coastguard Worker }
1456*1c60b9acSAndroid Build Coastguard Worker
1457*1c60b9acSAndroid Build Coastguard Worker switch (h2n->type) {
1458*1c60b9acSAndroid Build Coastguard Worker
1459*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_FRAME_TYPE_SETTINGS:
1460*1c60b9acSAndroid Build Coastguard Worker
1461*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
1462*1c60b9acSAndroid Build Coastguard Worker if (wsi->client_h2_alpn && !wsi->client_mux_migrated &&
1463*1c60b9acSAndroid Build Coastguard Worker !(h2n->flags & LWS_H2_FLAG_SETTINGS_ACK)) {
1464*1c60b9acSAndroid Build Coastguard Worker struct lws_h2_protocol_send *pps;
1465*1c60b9acSAndroid Build Coastguard Worker
1466*1c60b9acSAndroid Build Coastguard Worker /* migrate original client ask on to substream 1 */
1467*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_FILE_OPS)
1468*1c60b9acSAndroid Build Coastguard Worker wsi->http.fop_fd = NULL;
1469*1c60b9acSAndroid Build Coastguard Worker #endif
1470*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: migrating\n", __func__);
1471*1c60b9acSAndroid Build Coastguard Worker wsi->client_mux_migrated = 1;
1472*1c60b9acSAndroid Build Coastguard Worker /*
1473*1c60b9acSAndroid Build Coastguard Worker * we need to treat the headers from the upgrade as the
1474*1c60b9acSAndroid Build Coastguard Worker * first job. So these need to get shifted to sid 1.
1475*1c60b9acSAndroid Build Coastguard Worker */
1476*1c60b9acSAndroid Build Coastguard Worker lws_context_lock(wsi->a.context, "h2 mig");
1477*1c60b9acSAndroid Build Coastguard Worker lws_vhost_lock(wsi->a.vhost);
1478*1c60b9acSAndroid Build Coastguard Worker
1479*1c60b9acSAndroid Build Coastguard Worker h2n->swsi = __lws_wsi_server_new(wsi->a.vhost, wsi, 1);
1480*1c60b9acSAndroid Build Coastguard Worker
1481*1c60b9acSAndroid Build Coastguard Worker lws_vhost_unlock(wsi->a.vhost);
1482*1c60b9acSAndroid Build Coastguard Worker lws_context_unlock(wsi->a.context);
1483*1c60b9acSAndroid Build Coastguard Worker
1484*1c60b9acSAndroid Build Coastguard Worker if (!h2n->swsi)
1485*1c60b9acSAndroid Build Coastguard Worker return 1;
1486*1c60b9acSAndroid Build Coastguard Worker h2n->sid = 1;
1487*1c60b9acSAndroid Build Coastguard Worker
1488*1c60b9acSAndroid Build Coastguard Worker assert(lws_wsi_mux_from_id(wsi, 1) == h2n->swsi);
1489*1c60b9acSAndroid Build Coastguard Worker
1490*1c60b9acSAndroid Build Coastguard Worker // lws_role_transition(wsi, LWSIFR_CLIENT,
1491*1c60b9acSAndroid Build Coastguard Worker // LRS_H2_WAITING_TO_SEND_HEADERS,
1492*1c60b9acSAndroid Build Coastguard Worker // &role_ops_h2);
1493*1c60b9acSAndroid Build Coastguard Worker
1494*1c60b9acSAndroid Build Coastguard Worker lws_role_transition(h2n->swsi, LWSIFR_CLIENT,
1495*1c60b9acSAndroid Build Coastguard Worker LRS_H2_WAITING_TO_SEND_HEADERS,
1496*1c60b9acSAndroid Build Coastguard Worker &role_ops_h2);
1497*1c60b9acSAndroid Build Coastguard Worker
1498*1c60b9acSAndroid Build Coastguard Worker /* pass on the initial headers to SID 1 */
1499*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->http.ah = wsi->http.ah;
1500*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SYS_FAULT_INJECTION)
1501*1c60b9acSAndroid Build Coastguard Worker lws_fi_import(&h2n->swsi->fic, &wsi->fic);
1502*1c60b9acSAndroid Build Coastguard Worker #endif
1503*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->client_mux_substream = 1;
1504*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->client_h2_alpn = 1;
1505*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
1506*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->flags = wsi->flags;
1507*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CONMON)
1508*1c60b9acSAndroid Build Coastguard Worker /* sid1 needs to represent the connection experience
1509*1c60b9acSAndroid Build Coastguard Worker * ... we take over responsibility for the DNS list
1510*1c60b9acSAndroid Build Coastguard Worker * copy as well
1511*1c60b9acSAndroid Build Coastguard Worker */
1512*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->conmon = wsi->conmon;
1513*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->conmon_datum = wsi->conmon_datum;
1514*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->sa46_peer = wsi->sa46_peer;
1515*1c60b9acSAndroid Build Coastguard Worker wsi->conmon.dns_results_copy = NULL;
1516*1c60b9acSAndroid Build Coastguard Worker #endif
1517*1c60b9acSAndroid Build Coastguard Worker #endif /* CLIENT */
1518*1c60b9acSAndroid Build Coastguard Worker
1519*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SECURE_STREAMS)
1520*1c60b9acSAndroid Build Coastguard Worker if (wsi->for_ss) {
1521*1c60b9acSAndroid Build Coastguard Worker lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi);
1522*1c60b9acSAndroid Build Coastguard Worker
1523*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->for_ss = 1;
1524*1c60b9acSAndroid Build Coastguard Worker wsi->for_ss = 0;
1525*1c60b9acSAndroid Build Coastguard Worker
1526*1c60b9acSAndroid Build Coastguard Worker if (h->wsi == wsi)
1527*1c60b9acSAndroid Build Coastguard Worker h->wsi = h2n->swsi;
1528*1c60b9acSAndroid Build Coastguard Worker }
1529*1c60b9acSAndroid Build Coastguard Worker #endif
1530*1c60b9acSAndroid Build Coastguard Worker
1531*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->a.protocol = wsi->a.protocol;
1532*1c60b9acSAndroid Build Coastguard Worker if (h2n->swsi->user_space &&
1533*1c60b9acSAndroid Build Coastguard Worker !h2n->swsi->user_space_externally_allocated)
1534*1c60b9acSAndroid Build Coastguard Worker lws_free(h2n->swsi->user_space);
1535*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->user_space = wsi->user_space;
1536*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->user_space_externally_allocated =
1537*1c60b9acSAndroid Build Coastguard Worker wsi->user_space_externally_allocated;
1538*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->a.opaque_user_data = wsi->a.opaque_user_data;
1539*1c60b9acSAndroid Build Coastguard Worker wsi->a.opaque_user_data = NULL;
1540*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->txc.manual_initial_tx_credit =
1541*1c60b9acSAndroid Build Coastguard Worker wsi->txc.manual_initial_tx_credit;
1542*1c60b9acSAndroid Build Coastguard Worker
1543*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_TLS)
1544*1c60b9acSAndroid Build Coastguard Worker lws_strncpy(h2n->swsi->alpn, wsi->alpn,
1545*1c60b9acSAndroid Build Coastguard Worker sizeof(wsi->alpn));
1546*1c60b9acSAndroid Build Coastguard Worker #endif
1547*1c60b9acSAndroid Build Coastguard Worker
1548*1c60b9acSAndroid Build Coastguard Worker wsi->user_space = NULL;
1549*1c60b9acSAndroid Build Coastguard Worker
1550*1c60b9acSAndroid Build Coastguard Worker if (h2n->swsi->http.ah)
1551*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->http.ah->wsi = h2n->swsi;
1552*1c60b9acSAndroid Build Coastguard Worker wsi->http.ah = NULL;
1553*1c60b9acSAndroid Build Coastguard Worker
1554*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: MIGRATING nwsi %s -> swsi %s\n", __func__,
1555*1c60b9acSAndroid Build Coastguard Worker lws_wsi_tag(wsi), lws_wsi_tag(h2n->swsi));
1556*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->txc.tx_cr = (int32_t)
1557*1c60b9acSAndroid Build Coastguard Worker h2n->peer_set.s[H2SET_INITIAL_WINDOW_SIZE];
1558*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: initial tx credit on %s: %d\n",
1559*1c60b9acSAndroid Build Coastguard Worker __func__, lws_wsi_tag(h2n->swsi),
1560*1c60b9acSAndroid Build Coastguard Worker (int)h2n->swsi->txc.tx_cr);
1561*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->h2.initialized = 1;
1562*1c60b9acSAndroid Build Coastguard Worker
1563*1c60b9acSAndroid Build Coastguard Worker /* set our initial window size */
1564*1c60b9acSAndroid Build Coastguard Worker if (!wsi->h2.initialized) {
1565*1c60b9acSAndroid Build Coastguard Worker wsi->txc.tx_cr = (int32_t)
1566*1c60b9acSAndroid Build Coastguard Worker h2n->peer_set.s[H2SET_INITIAL_WINDOW_SIZE];
1567*1c60b9acSAndroid Build Coastguard Worker
1568*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: initial tx credit for us to "
1569*1c60b9acSAndroid Build Coastguard Worker "write on nwsi %s: %d\n", __func__,
1570*1c60b9acSAndroid Build Coastguard Worker lws_wsi_tag(wsi), (int)wsi->txc.tx_cr);
1571*1c60b9acSAndroid Build Coastguard Worker wsi->h2.initialized = 1;
1572*1c60b9acSAndroid Build Coastguard Worker }
1573*1c60b9acSAndroid Build Coastguard Worker
1574*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(h2n->swsi);
1575*1c60b9acSAndroid Build Coastguard Worker
1576*1c60b9acSAndroid Build Coastguard Worker if (!wsi->h2_acked_settings ||
1577*1c60b9acSAndroid Build Coastguard Worker !(wsi->flags & LCCSCF_H2_QUIRK_NGHTTP2_END_STREAM)
1578*1c60b9acSAndroid Build Coastguard Worker ) {
1579*1c60b9acSAndroid Build Coastguard Worker pps = lws_h2_new_pps(LWS_H2_PPS_ACK_SETTINGS);
1580*1c60b9acSAndroid Build Coastguard Worker if (!pps)
1581*1c60b9acSAndroid Build Coastguard Worker return 1;
1582*1c60b9acSAndroid Build Coastguard Worker lws_pps_schedule(wsi, pps);
1583*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: SETTINGS ack PPS\n", __func__);
1584*1c60b9acSAndroid Build Coastguard Worker wsi->h2_acked_settings = 1;
1585*1c60b9acSAndroid Build Coastguard Worker }
1586*1c60b9acSAndroid Build Coastguard Worker
1587*1c60b9acSAndroid Build Coastguard Worker /* also attach any queued guys */
1588*1c60b9acSAndroid Build Coastguard Worker
1589*1c60b9acSAndroid Build Coastguard Worker lws_wsi_mux_apply_queue(wsi);
1590*1c60b9acSAndroid Build Coastguard Worker }
1591*1c60b9acSAndroid Build Coastguard Worker #endif
1592*1c60b9acSAndroid Build Coastguard Worker break;
1593*1c60b9acSAndroid Build Coastguard Worker
1594*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_FRAME_TYPE_CONTINUATION:
1595*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_FRAME_TYPE_HEADERS:
1596*1c60b9acSAndroid Build Coastguard Worker
1597*1c60b9acSAndroid Build Coastguard Worker if (!h2n->swsi)
1598*1c60b9acSAndroid Build Coastguard Worker break;
1599*1c60b9acSAndroid Build Coastguard Worker
1600*1c60b9acSAndroid Build Coastguard Worker /* service the http request itself */
1601*1c60b9acSAndroid Build Coastguard Worker
1602*1c60b9acSAndroid Build Coastguard Worker if (h2n->last_action_dyntable_resize) {
1603*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, H2_ERR_COMPRESSION_ERROR,
1604*1c60b9acSAndroid Build Coastguard Worker "dyntable resize last in headers");
1605*1c60b9acSAndroid Build Coastguard Worker break;
1606*1c60b9acSAndroid Build Coastguard Worker }
1607*1c60b9acSAndroid Build Coastguard Worker
1608*1c60b9acSAndroid Build Coastguard Worker if (!h2n->swsi->h2.END_HEADERS) {
1609*1c60b9acSAndroid Build Coastguard Worker /* we are not finished yet */
1610*1c60b9acSAndroid Build Coastguard Worker lwsl_info("witholding http action for continuation\n");
1611*1c60b9acSAndroid Build Coastguard Worker h2n->cont_exp_sid = h2n->sid;
1612*1c60b9acSAndroid Build Coastguard Worker h2n->cont_exp = 1;
1613*1c60b9acSAndroid Build Coastguard Worker break;
1614*1c60b9acSAndroid Build Coastguard Worker }
1615*1c60b9acSAndroid Build Coastguard Worker
1616*1c60b9acSAndroid Build Coastguard Worker /* confirm the hpack stream state is reasonable for finishing */
1617*1c60b9acSAndroid Build Coastguard Worker
1618*1c60b9acSAndroid Build Coastguard Worker if (h2n->hpack != HPKS_TYPE) {
1619*1c60b9acSAndroid Build Coastguard Worker /* hpack incomplete */
1620*1c60b9acSAndroid Build Coastguard Worker lwsl_info("hpack incomplete %d (type %d, len %u)\n",
1621*1c60b9acSAndroid Build Coastguard Worker h2n->hpack, h2n->type,
1622*1c60b9acSAndroid Build Coastguard Worker (unsigned int)h2n->hpack_len);
1623*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, H2_ERR_COMPRESSION_ERROR,
1624*1c60b9acSAndroid Build Coastguard Worker "hpack incomplete");
1625*1c60b9acSAndroid Build Coastguard Worker break;
1626*1c60b9acSAndroid Build Coastguard Worker }
1627*1c60b9acSAndroid Build Coastguard Worker
1628*1c60b9acSAndroid Build Coastguard Worker /* this is the last part of HEADERS */
1629*1c60b9acSAndroid Build Coastguard Worker switch (h2n->swsi->h2.h2_state) {
1630*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_STATE_IDLE:
1631*1c60b9acSAndroid Build Coastguard Worker lws_h2_state(h2n->swsi, LWS_H2_STATE_OPEN);
1632*1c60b9acSAndroid Build Coastguard Worker break;
1633*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_STATE_RESERVED_REMOTE:
1634*1c60b9acSAndroid Build Coastguard Worker lws_h2_state(h2n->swsi, LWS_H2_STATE_HALF_CLOSED_LOCAL);
1635*1c60b9acSAndroid Build Coastguard Worker break;
1636*1c60b9acSAndroid Build Coastguard Worker }
1637*1c60b9acSAndroid Build Coastguard Worker
1638*1c60b9acSAndroid Build Coastguard Worker lwsl_info("http req, %s, h2n->swsi=%s\n", lws_wsi_tag(wsi),
1639*1c60b9acSAndroid Build Coastguard Worker lws_wsi_tag(h2n->swsi));
1640*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->hdr_parsing_completed = 1;
1641*1c60b9acSAndroid Build Coastguard Worker
1642*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
1643*1c60b9acSAndroid Build Coastguard Worker if (h2n->swsi->client_mux_substream &&
1644*1c60b9acSAndroid Build Coastguard Worker lws_client_interpret_server_handshake(h2n->swsi)) {
1645*1c60b9acSAndroid Build Coastguard Worker /*
1646*1c60b9acSAndroid Build Coastguard Worker * This is more complicated than it looks, one exit from
1647*1c60b9acSAndroid Build Coastguard Worker * interpret_server_handshake() is to do a close that
1648*1c60b9acSAndroid Build Coastguard Worker * turns into a redirect.
1649*1c60b9acSAndroid Build Coastguard Worker *
1650*1c60b9acSAndroid Build Coastguard Worker * In that case, the wsi survives having being reset
1651*1c60b9acSAndroid Build Coastguard Worker * and detached from any h2 identity. We need to get
1652*1c60b9acSAndroid Build Coastguard Worker * our parents out from touching it any more
1653*1c60b9acSAndroid Build Coastguard Worker */
1654*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: cli int serv hs closed, or redir\n", __func__);
1655*1c60b9acSAndroid Build Coastguard Worker return 2;
1656*1c60b9acSAndroid Build Coastguard Worker }
1657*1c60b9acSAndroid Build Coastguard Worker #endif
1658*1c60b9acSAndroid Build Coastguard Worker
1659*1c60b9acSAndroid Build Coastguard Worker if (lws_hdr_extant(h2n->swsi, WSI_TOKEN_HTTP_CONTENT_LENGTH)) {
1660*1c60b9acSAndroid Build Coastguard Worker const char *simp = lws_hdr_simple_ptr(h2n->swsi,
1661*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP_CONTENT_LENGTH);
1662*1c60b9acSAndroid Build Coastguard Worker
1663*1c60b9acSAndroid Build Coastguard Worker if (!simp) /* coverity */
1664*1c60b9acSAndroid Build Coastguard Worker return 1;
1665*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->http.rx_content_length = (unsigned long long)atoll(simp);
1666*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->http.rx_content_remain =
1667*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->http.rx_content_length;
1668*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->http.content_length_given = 1;
1669*1c60b9acSAndroid Build Coastguard Worker lwsl_info("setting rx_content_length %lld\n",
1670*1c60b9acSAndroid Build Coastguard Worker (long long)h2n->swsi->http.rx_content_length);
1671*1c60b9acSAndroid Build Coastguard Worker }
1672*1c60b9acSAndroid Build Coastguard Worker
1673*1c60b9acSAndroid Build Coastguard Worker {
1674*1c60b9acSAndroid Build Coastguard Worker int n = 0, len;
1675*1c60b9acSAndroid Build Coastguard Worker char buf[256];
1676*1c60b9acSAndroid Build Coastguard Worker const unsigned char *c;
1677*1c60b9acSAndroid Build Coastguard Worker
1678*1c60b9acSAndroid Build Coastguard Worker do {
1679*1c60b9acSAndroid Build Coastguard Worker c = lws_token_to_string((enum lws_token_indexes)n);
1680*1c60b9acSAndroid Build Coastguard Worker if (!c) {
1681*1c60b9acSAndroid Build Coastguard Worker n++;
1682*1c60b9acSAndroid Build Coastguard Worker continue;
1683*1c60b9acSAndroid Build Coastguard Worker }
1684*1c60b9acSAndroid Build Coastguard Worker
1685*1c60b9acSAndroid Build Coastguard Worker len = lws_hdr_total_length(h2n->swsi, (enum lws_token_indexes)n);
1686*1c60b9acSAndroid Build Coastguard Worker if (!len || len > (int)sizeof(buf) - 1) {
1687*1c60b9acSAndroid Build Coastguard Worker n++;
1688*1c60b9acSAndroid Build Coastguard Worker continue;
1689*1c60b9acSAndroid Build Coastguard Worker }
1690*1c60b9acSAndroid Build Coastguard Worker
1691*1c60b9acSAndroid Build Coastguard Worker if (lws_hdr_copy(h2n->swsi, buf, sizeof buf,
1692*1c60b9acSAndroid Build Coastguard Worker (enum lws_token_indexes)n) < 0) {
1693*1c60b9acSAndroid Build Coastguard Worker lwsl_info(" %s !oversize!\n",
1694*1c60b9acSAndroid Build Coastguard Worker (char *)c);
1695*1c60b9acSAndroid Build Coastguard Worker } else {
1696*1c60b9acSAndroid Build Coastguard Worker buf[sizeof(buf) - 1] = '\0';
1697*1c60b9acSAndroid Build Coastguard Worker
1698*1c60b9acSAndroid Build Coastguard Worker lwsl_info(" %s = %s\n",
1699*1c60b9acSAndroid Build Coastguard Worker (char *)c, buf);
1700*1c60b9acSAndroid Build Coastguard Worker }
1701*1c60b9acSAndroid Build Coastguard Worker n++;
1702*1c60b9acSAndroid Build Coastguard Worker } while (c);
1703*1c60b9acSAndroid Build Coastguard Worker }
1704*1c60b9acSAndroid Build Coastguard Worker
1705*1c60b9acSAndroid Build Coastguard Worker if (h2n->swsi->h2.h2_state == LWS_H2_STATE_HALF_CLOSED_REMOTE ||
1706*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->h2.h2_state == LWS_H2_STATE_CLOSED) {
1707*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, H2_ERR_STREAM_CLOSED,
1708*1c60b9acSAndroid Build Coastguard Worker "Banning service on CLOSED_REMOTE");
1709*1c60b9acSAndroid Build Coastguard Worker break;
1710*1c60b9acSAndroid Build Coastguard Worker }
1711*1c60b9acSAndroid Build Coastguard Worker
1712*1c60b9acSAndroid Build Coastguard Worker switch (h2n->swsi->h2.h2_state) {
1713*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_STATE_IDLE:
1714*1c60b9acSAndroid Build Coastguard Worker lws_h2_state(h2n->swsi, LWS_H2_STATE_OPEN);
1715*1c60b9acSAndroid Build Coastguard Worker break;
1716*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_STATE_OPEN:
1717*1c60b9acSAndroid Build Coastguard Worker if (h2n->swsi->h2.END_STREAM)
1718*1c60b9acSAndroid Build Coastguard Worker lws_h2_state(h2n->swsi,
1719*1c60b9acSAndroid Build Coastguard Worker LWS_H2_STATE_HALF_CLOSED_REMOTE);
1720*1c60b9acSAndroid Build Coastguard Worker break;
1721*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_STATE_HALF_CLOSED_LOCAL:
1722*1c60b9acSAndroid Build Coastguard Worker if (h2n->swsi->h2.END_STREAM)
1723*1c60b9acSAndroid Build Coastguard Worker /*
1724*1c60b9acSAndroid Build Coastguard Worker * action the END_STREAM
1725*1c60b9acSAndroid Build Coastguard Worker */
1726*1c60b9acSAndroid Build Coastguard Worker lws_h2_state(h2n->swsi, LWS_H2_STATE_CLOSED);
1727*1c60b9acSAndroid Build Coastguard Worker break;
1728*1c60b9acSAndroid Build Coastguard Worker }
1729*1c60b9acSAndroid Build Coastguard Worker
1730*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
1731*1c60b9acSAndroid Build Coastguard Worker
1732*1c60b9acSAndroid Build Coastguard Worker /*
1733*1c60b9acSAndroid Build Coastguard Worker * If we already had the END_STREAM along with the END_HEADERS,
1734*1c60b9acSAndroid Build Coastguard Worker * we have already transitioned to STATE_CLOSED and we are not
1735*1c60b9acSAndroid Build Coastguard Worker * going to be doing anything further on this stream.
1736*1c60b9acSAndroid Build Coastguard Worker *
1737*1c60b9acSAndroid Build Coastguard Worker * In that case handle the transaction completion and
1738*1c60b9acSAndroid Build Coastguard Worker * finalize the stream for the peer
1739*1c60b9acSAndroid Build Coastguard Worker */
1740*1c60b9acSAndroid Build Coastguard Worker
1741*1c60b9acSAndroid Build Coastguard Worker if (h2n->swsi->h2.h2_state == LWS_H2_STATE_CLOSED &&
1742*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->client_mux_substream) {
1743*1c60b9acSAndroid Build Coastguard Worker
1744*1c60b9acSAndroid Build Coastguard Worker lws_h2_rst_stream(h2n->swsi, H2_ERR_NO_ERROR,
1745*1c60b9acSAndroid Build Coastguard Worker "client done");
1746*1c60b9acSAndroid Build Coastguard Worker
1747*1c60b9acSAndroid Build Coastguard Worker if (lws_http_transaction_completed_client(h2n->swsi))
1748*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("tx completed returned close\n");
1749*1c60b9acSAndroid Build Coastguard Worker break;
1750*1c60b9acSAndroid Build Coastguard Worker }
1751*1c60b9acSAndroid Build Coastguard Worker
1752*1c60b9acSAndroid Build Coastguard Worker if (h2n->swsi->client_mux_substream) {
1753*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: %s: headers: client path (h2 state %s)\n",
1754*1c60b9acSAndroid Build Coastguard Worker __func__, lws_wsi_tag(wsi),
1755*1c60b9acSAndroid Build Coastguard Worker h2_state_names[h2n->swsi->h2.h2_state]);
1756*1c60b9acSAndroid Build Coastguard Worker break;
1757*1c60b9acSAndroid Build Coastguard Worker }
1758*1c60b9acSAndroid Build Coastguard Worker #endif
1759*1c60b9acSAndroid Build Coastguard Worker
1760*1c60b9acSAndroid Build Coastguard Worker if (!lws_hdr_total_length(h2n->swsi, WSI_TOKEN_HTTP_COLON_PATH) ||
1761*1c60b9acSAndroid Build Coastguard Worker !lws_hdr_total_length(h2n->swsi, WSI_TOKEN_HTTP_COLON_METHOD) ||
1762*1c60b9acSAndroid Build Coastguard Worker !lws_hdr_total_length(h2n->swsi, WSI_TOKEN_HTTP_COLON_SCHEME) ||
1763*1c60b9acSAndroid Build Coastguard Worker lws_hdr_total_length(h2n->swsi, WSI_TOKEN_HTTP_COLON_STATUS) ||
1764*1c60b9acSAndroid Build Coastguard Worker lws_hdr_extant(h2n->swsi, WSI_TOKEN_CONNECTION)) {
1765*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR,
1766*1c60b9acSAndroid Build Coastguard Worker "Pseudoheader checks");
1767*1c60b9acSAndroid Build Coastguard Worker break;
1768*1c60b9acSAndroid Build Coastguard Worker }
1769*1c60b9acSAndroid Build Coastguard Worker
1770*1c60b9acSAndroid Build Coastguard Worker if (lws_hdr_extant(h2n->swsi, WSI_TOKEN_TE)) {
1771*1c60b9acSAndroid Build Coastguard Worker n = lws_hdr_total_length(h2n->swsi, WSI_TOKEN_TE);
1772*1c60b9acSAndroid Build Coastguard Worker
1773*1c60b9acSAndroid Build Coastguard Worker if (n != 8 ||
1774*1c60b9acSAndroid Build Coastguard Worker !lws_hdr_simple_ptr(h2n->swsi, WSI_TOKEN_TE) ||
1775*1c60b9acSAndroid Build Coastguard Worker strncmp(lws_hdr_simple_ptr(h2n->swsi, WSI_TOKEN_TE),
1776*1c60b9acSAndroid Build Coastguard Worker "trailers", (unsigned int)n)) {
1777*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR,
1778*1c60b9acSAndroid Build Coastguard Worker "Illegal transfer-encoding");
1779*1c60b9acSAndroid Build Coastguard Worker break;
1780*1c60b9acSAndroid Build Coastguard Worker }
1781*1c60b9acSAndroid Build Coastguard Worker }
1782*1c60b9acSAndroid Build Coastguard Worker
1783*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
1784*1c60b9acSAndroid Build Coastguard Worker lws_http_compression_validate(h2n->swsi);
1785*1c60b9acSAndroid Build Coastguard Worker #endif
1786*1c60b9acSAndroid Build Coastguard Worker
1787*1c60b9acSAndroid Build Coastguard Worker p = lws_hdr_simple_ptr(h2n->swsi, WSI_TOKEN_HTTP_COLON_METHOD);
1788*1c60b9acSAndroid Build Coastguard Worker /*
1789*1c60b9acSAndroid Build Coastguard Worker * duplicate :path into the individual method uri header
1790*1c60b9acSAndroid Build Coastguard Worker * index, so that it looks the same as h1 in the ah
1791*1c60b9acSAndroid Build Coastguard Worker */
1792*1c60b9acSAndroid Build Coastguard Worker for (n = 0; n < (int)LWS_ARRAY_SIZE(method_names); n++)
1793*1c60b9acSAndroid Build Coastguard Worker if (p && !strcasecmp(p, method_names[n])) {
1794*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->http.ah->frag_index[method_index[n]] =
1795*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->http.ah->frag_index[
1796*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP_COLON_PATH];
1797*1c60b9acSAndroid Build Coastguard Worker break;
1798*1c60b9acSAndroid Build Coastguard Worker }
1799*1c60b9acSAndroid Build Coastguard Worker
1800*1c60b9acSAndroid Build Coastguard Worker {
1801*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: setting DEF_ACT from 0x%x\n", __func__,
1802*1c60b9acSAndroid Build Coastguard Worker (unsigned int)h2n->swsi->wsistate);
1803*1c60b9acSAndroid Build Coastguard Worker lwsi_set_state(h2n->swsi, LRS_DEFERRING_ACTION);
1804*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(h2n->swsi);
1805*1c60b9acSAndroid Build Coastguard Worker }
1806*1c60b9acSAndroid Build Coastguard Worker break;
1807*1c60b9acSAndroid Build Coastguard Worker
1808*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_FRAME_TYPE_DATA:
1809*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: DATA flags 0x%x\n", __func__, h2n->flags);
1810*1c60b9acSAndroid Build Coastguard Worker if (!h2n->swsi)
1811*1c60b9acSAndroid Build Coastguard Worker break;
1812*1c60b9acSAndroid Build Coastguard Worker
1813*1c60b9acSAndroid Build Coastguard Worker if (lws_hdr_total_length(h2n->swsi,
1814*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP_CONTENT_LENGTH) &&
1815*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->h2.END_STREAM &&
1816*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->http.rx_content_length &&
1817*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->http.rx_content_remain) {
1818*1c60b9acSAndroid Build Coastguard Worker lws_h2_rst_stream(h2n->swsi, H2_ERR_PROTOCOL_ERROR,
1819*1c60b9acSAndroid Build Coastguard Worker "Not enough rx content");
1820*1c60b9acSAndroid Build Coastguard Worker break;
1821*1c60b9acSAndroid Build Coastguard Worker }
1822*1c60b9acSAndroid Build Coastguard Worker
1823*1c60b9acSAndroid Build Coastguard Worker if (h2n->swsi->h2.END_STREAM &&
1824*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->h2.h2_state == LWS_H2_STATE_OPEN)
1825*1c60b9acSAndroid Build Coastguard Worker lws_h2_state(h2n->swsi,
1826*1c60b9acSAndroid Build Coastguard Worker LWS_H2_STATE_HALF_CLOSED_REMOTE);
1827*1c60b9acSAndroid Build Coastguard Worker
1828*1c60b9acSAndroid Build Coastguard Worker if (h2n->swsi->h2.END_STREAM &&
1829*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->h2.h2_state == LWS_H2_STATE_HALF_CLOSED_LOCAL)
1830*1c60b9acSAndroid Build Coastguard Worker lws_h2_state(h2n->swsi, LWS_H2_STATE_CLOSED);
1831*1c60b9acSAndroid Build Coastguard Worker
1832*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
1833*1c60b9acSAndroid Build Coastguard Worker /*
1834*1c60b9acSAndroid Build Coastguard Worker * client... remote END_STREAM implies we weren't going to
1835*1c60b9acSAndroid Build Coastguard Worker * send anything else anyway.
1836*1c60b9acSAndroid Build Coastguard Worker */
1837*1c60b9acSAndroid Build Coastguard Worker
1838*1c60b9acSAndroid Build Coastguard Worker if (h2n->swsi->client_mux_substream &&
1839*1c60b9acSAndroid Build Coastguard Worker (h2n->flags & LWS_H2_FLAG_END_STREAM)) {
1840*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: %s: DATA: end stream\n",
1841*1c60b9acSAndroid Build Coastguard Worker __func__, lws_wsi_tag(h2n->swsi));
1842*1c60b9acSAndroid Build Coastguard Worker
1843*1c60b9acSAndroid Build Coastguard Worker if (h2n->swsi->h2.h2_state == LWS_H2_STATE_OPEN) {
1844*1c60b9acSAndroid Build Coastguard Worker lws_h2_state(h2n->swsi,
1845*1c60b9acSAndroid Build Coastguard Worker LWS_H2_STATE_HALF_CLOSED_REMOTE);
1846*1c60b9acSAndroid Build Coastguard Worker // lws_h2_rst_stream(h2n->swsi, H2_ERR_NO_ERROR,
1847*1c60b9acSAndroid Build Coastguard Worker // "client done");
1848*1c60b9acSAndroid Build Coastguard Worker
1849*1c60b9acSAndroid Build Coastguard Worker // if (lws_http_transaction_completed_client(h2n->swsi))
1850*1c60b9acSAndroid Build Coastguard Worker // lwsl_debug("tx completed returned close\n");
1851*1c60b9acSAndroid Build Coastguard Worker }
1852*1c60b9acSAndroid Build Coastguard Worker
1853*1c60b9acSAndroid Build Coastguard Worker //if (h2n->swsi->h2.h2_state == LWS_H2_STATE_HALF_CLOSED_LOCAL)
1854*1c60b9acSAndroid Build Coastguard Worker {
1855*1c60b9acSAndroid Build Coastguard Worker lws_h2_state(h2n->swsi, LWS_H2_STATE_CLOSED);
1856*1c60b9acSAndroid Build Coastguard Worker
1857*1c60b9acSAndroid Build Coastguard Worker lws_h2_rst_stream(h2n->swsi, H2_ERR_NO_ERROR,
1858*1c60b9acSAndroid Build Coastguard Worker "client done");
1859*1c60b9acSAndroid Build Coastguard Worker
1860*1c60b9acSAndroid Build Coastguard Worker if (lws_http_transaction_completed_client(h2n->swsi))
1861*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("tx completed returned close\n");
1862*1c60b9acSAndroid Build Coastguard Worker }
1863*1c60b9acSAndroid Build Coastguard Worker }
1864*1c60b9acSAndroid Build Coastguard Worker #endif
1865*1c60b9acSAndroid Build Coastguard Worker break;
1866*1c60b9acSAndroid Build Coastguard Worker
1867*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_FRAME_TYPE_PING:
1868*1c60b9acSAndroid Build Coastguard Worker if (h2n->flags & LWS_H2_FLAG_SETTINGS_ACK)
1869*1c60b9acSAndroid Build Coastguard Worker lws_validity_confirmed(wsi);
1870*1c60b9acSAndroid Build Coastguard Worker else {
1871*1c60b9acSAndroid Build Coastguard Worker /* they're sending us a ping request */
1872*1c60b9acSAndroid Build Coastguard Worker struct lws_h2_protocol_send *pps =
1873*1c60b9acSAndroid Build Coastguard Worker lws_h2_new_pps(LWS_H2_PPS_PONG);
1874*1c60b9acSAndroid Build Coastguard Worker if (!pps)
1875*1c60b9acSAndroid Build Coastguard Worker return 1;
1876*1c60b9acSAndroid Build Coastguard Worker
1877*1c60b9acSAndroid Build Coastguard Worker lwsl_info("rx ping, preparing pong\n");
1878*1c60b9acSAndroid Build Coastguard Worker
1879*1c60b9acSAndroid Build Coastguard Worker memcpy(pps->u.ping.ping_payload, h2n->ping_payload, 8);
1880*1c60b9acSAndroid Build Coastguard Worker lws_pps_schedule(wsi, pps);
1881*1c60b9acSAndroid Build Coastguard Worker }
1882*1c60b9acSAndroid Build Coastguard Worker
1883*1c60b9acSAndroid Build Coastguard Worker break;
1884*1c60b9acSAndroid Build Coastguard Worker
1885*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_FRAME_TYPE_WINDOW_UPDATE:
1886*1c60b9acSAndroid Build Coastguard Worker /*
1887*1c60b9acSAndroid Build Coastguard Worker * We only have an unsigned 31-bit (positive) increment possible
1888*1c60b9acSAndroid Build Coastguard Worker */
1889*1c60b9acSAndroid Build Coastguard Worker h2n->hpack_e_dep &= ~(1u << 31);
1890*1c60b9acSAndroid Build Coastguard Worker lwsl_info("WINDOW_UPDATE: sid %u %u (0x%x)\n",
1891*1c60b9acSAndroid Build Coastguard Worker (unsigned int)h2n->sid,
1892*1c60b9acSAndroid Build Coastguard Worker (unsigned int)h2n->hpack_e_dep,
1893*1c60b9acSAndroid Build Coastguard Worker (unsigned int)h2n->hpack_e_dep);
1894*1c60b9acSAndroid Build Coastguard Worker
1895*1c60b9acSAndroid Build Coastguard Worker if (h2n->sid)
1896*1c60b9acSAndroid Build Coastguard Worker eff_wsi = h2n->swsi;
1897*1c60b9acSAndroid Build Coastguard Worker
1898*1c60b9acSAndroid Build Coastguard Worker if (!eff_wsi) {
1899*1c60b9acSAndroid Build Coastguard Worker if (h2n->sid > h2n->highest_sid_opened)
1900*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR,
1901*1c60b9acSAndroid Build Coastguard Worker "alien sid");
1902*1c60b9acSAndroid Build Coastguard Worker break; /* ignore */
1903*1c60b9acSAndroid Build Coastguard Worker }
1904*1c60b9acSAndroid Build Coastguard Worker
1905*1c60b9acSAndroid Build Coastguard Worker if (eff_wsi->a.vhost->options &
1906*1c60b9acSAndroid Build Coastguard Worker LWS_SERVER_OPTION_H2_JUST_FIX_WINDOW_UPDATE_OVERFLOW &&
1907*1c60b9acSAndroid Build Coastguard Worker (uint64_t)eff_wsi->txc.tx_cr + (uint64_t)h2n->hpack_e_dep >
1908*1c60b9acSAndroid Build Coastguard Worker (uint64_t)0x7fffffff)
1909*1c60b9acSAndroid Build Coastguard Worker h2n->hpack_e_dep = (uint32_t)(0x7fffffff - eff_wsi->txc.tx_cr);
1910*1c60b9acSAndroid Build Coastguard Worker
1911*1c60b9acSAndroid Build Coastguard Worker if ((uint64_t)eff_wsi->txc.tx_cr + (uint64_t)h2n->hpack_e_dep >
1912*1c60b9acSAndroid Build Coastguard Worker (uint64_t)0x7fffffff) {
1913*1c60b9acSAndroid Build Coastguard Worker lwsl_warn("%s: WINDOW_UPDATE 0x%llx + 0x%llx = 0x%llx, too high\n",
1914*1c60b9acSAndroid Build Coastguard Worker __func__, (unsigned long long)eff_wsi->txc.tx_cr,
1915*1c60b9acSAndroid Build Coastguard Worker (unsigned long long)h2n->hpack_e_dep,
1916*1c60b9acSAndroid Build Coastguard Worker (unsigned long long)eff_wsi->txc.tx_cr + (unsigned long long)h2n->hpack_e_dep);
1917*1c60b9acSAndroid Build Coastguard Worker if (h2n->sid)
1918*1c60b9acSAndroid Build Coastguard Worker lws_h2_rst_stream(h2n->swsi,
1919*1c60b9acSAndroid Build Coastguard Worker H2_ERR_FLOW_CONTROL_ERROR,
1920*1c60b9acSAndroid Build Coastguard Worker "Flow control exceeded max");
1921*1c60b9acSAndroid Build Coastguard Worker else
1922*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, H2_ERR_FLOW_CONTROL_ERROR,
1923*1c60b9acSAndroid Build Coastguard Worker "Flow control exceeded max");
1924*1c60b9acSAndroid Build Coastguard Worker break;
1925*1c60b9acSAndroid Build Coastguard Worker }
1926*1c60b9acSAndroid Build Coastguard Worker
1927*1c60b9acSAndroid Build Coastguard Worker if (!h2n->hpack_e_dep) {
1928*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR,
1929*1c60b9acSAndroid Build Coastguard Worker "Zero length window update");
1930*1c60b9acSAndroid Build Coastguard Worker break;
1931*1c60b9acSAndroid Build Coastguard Worker }
1932*1c60b9acSAndroid Build Coastguard Worker n = eff_wsi->txc.tx_cr;
1933*1c60b9acSAndroid Build Coastguard Worker eff_wsi->txc.tx_cr += (int32_t)h2n->hpack_e_dep;
1934*1c60b9acSAndroid Build Coastguard Worker
1935*1c60b9acSAndroid Build Coastguard Worker lws_wsi_txc_report_manual_txcr_in(eff_wsi,
1936*1c60b9acSAndroid Build Coastguard Worker (int32_t)h2n->hpack_e_dep);
1937*1c60b9acSAndroid Build Coastguard Worker
1938*1c60b9acSAndroid Build Coastguard Worker lws_wsi_txc_describe(&eff_wsi->txc, "WINDOW_UPDATE in",
1939*1c60b9acSAndroid Build Coastguard Worker eff_wsi->mux.my_sid);
1940*1c60b9acSAndroid Build Coastguard Worker
1941*1c60b9acSAndroid Build Coastguard Worker if (n <= 0 && eff_wsi->txc.tx_cr <= 0)
1942*1c60b9acSAndroid Build Coastguard Worker /* it helps, but won't change sendability for anyone */
1943*1c60b9acSAndroid Build Coastguard Worker break;
1944*1c60b9acSAndroid Build Coastguard Worker
1945*1c60b9acSAndroid Build Coastguard Worker /*
1946*1c60b9acSAndroid Build Coastguard Worker * It may have changed sendability (depends on SID 0 tx credit
1947*1c60b9acSAndroid Build Coastguard Worker * too)... for us and any children waiting on us... reassess
1948*1c60b9acSAndroid Build Coastguard Worker * blockage for all children first
1949*1c60b9acSAndroid Build Coastguard Worker */
1950*1c60b9acSAndroid Build Coastguard Worker lws_start_foreach_ll(struct lws *, w, wsi->mux.child_list) {
1951*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(w);
1952*1c60b9acSAndroid Build Coastguard Worker } lws_end_foreach_ll(w, mux.sibling_list);
1953*1c60b9acSAndroid Build Coastguard Worker
1954*1c60b9acSAndroid Build Coastguard Worker if (eff_wsi->txc.skint &&
1955*1c60b9acSAndroid Build Coastguard Worker !lws_wsi_txc_check_skint(&eff_wsi->txc,
1956*1c60b9acSAndroid Build Coastguard Worker lws_h2_tx_cr_get(eff_wsi)))
1957*1c60b9acSAndroid Build Coastguard Worker /*
1958*1c60b9acSAndroid Build Coastguard Worker * This one became un-skint, schedule a writeable
1959*1c60b9acSAndroid Build Coastguard Worker * callback
1960*1c60b9acSAndroid Build Coastguard Worker */
1961*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(eff_wsi);
1962*1c60b9acSAndroid Build Coastguard Worker
1963*1c60b9acSAndroid Build Coastguard Worker break;
1964*1c60b9acSAndroid Build Coastguard Worker
1965*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_FRAME_TYPE_GOAWAY:
1966*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("GOAWAY: last sid %u, error 0x%08X, string '%s'\n",
1967*1c60b9acSAndroid Build Coastguard Worker (unsigned int)h2n->goaway_last_sid,
1968*1c60b9acSAndroid Build Coastguard Worker (unsigned int)h2n->goaway_err, h2n->goaway_str);
1969*1c60b9acSAndroid Build Coastguard Worker
1970*1c60b9acSAndroid Build Coastguard Worker return 1;
1971*1c60b9acSAndroid Build Coastguard Worker
1972*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_FRAME_TYPE_RST_STREAM:
1973*1c60b9acSAndroid Build Coastguard Worker lwsl_info("LWS_H2_FRAME_TYPE_RST_STREAM: sid %u: reason 0x%x\n",
1974*1c60b9acSAndroid Build Coastguard Worker (unsigned int)h2n->sid,
1975*1c60b9acSAndroid Build Coastguard Worker (unsigned int)h2n->hpack_e_dep);
1976*1c60b9acSAndroid Build Coastguard Worker break;
1977*1c60b9acSAndroid Build Coastguard Worker
1978*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_FRAME_TYPE_COUNT: /* IGNORING FRAME */
1979*1c60b9acSAndroid Build Coastguard Worker break;
1980*1c60b9acSAndroid Build Coastguard Worker }
1981*1c60b9acSAndroid Build Coastguard Worker
1982*1c60b9acSAndroid Build Coastguard Worker return 0;
1983*1c60b9acSAndroid Build Coastguard Worker }
1984*1c60b9acSAndroid Build Coastguard Worker
1985*1c60b9acSAndroid Build Coastguard Worker /*
1986*1c60b9acSAndroid Build Coastguard Worker * This may want to send something on the network wsi, which may be in the
1987*1c60b9acSAndroid Build Coastguard Worker * middle of a partial send. PPS sends are OK because they are queued to
1988*1c60b9acSAndroid Build Coastguard Worker * go through the WRITABLE handler already.
1989*1c60b9acSAndroid Build Coastguard Worker *
1990*1c60b9acSAndroid Build Coastguard Worker * The read parser for the network wsi has no choice but to parse its stream
1991*1c60b9acSAndroid Build Coastguard Worker * anyway, because otherwise it will not be able to get tx credit window
1992*1c60b9acSAndroid Build Coastguard Worker * messages.
1993*1c60b9acSAndroid Build Coastguard Worker *
1994*1c60b9acSAndroid Build Coastguard Worker * Therefore if we will send non-PPS, ie, lws_http_action() for a stream
1995*1c60b9acSAndroid Build Coastguard Worker * wsi, we must change its state and handle it as a priority in the
1996*1c60b9acSAndroid Build Coastguard Worker * POLLOUT handler instead of writing it here.
1997*1c60b9acSAndroid Build Coastguard Worker *
1998*1c60b9acSAndroid Build Coastguard Worker * About closing... for the main network wsi, it should return nonzero to
1999*1c60b9acSAndroid Build Coastguard Worker * close it all. If it needs to close an swsi, it can do it here.
2000*1c60b9acSAndroid Build Coastguard Worker */
2001*1c60b9acSAndroid Build Coastguard Worker int
lws_h2_parser(struct lws * wsi,unsigned char * in,lws_filepos_t _inlen,lws_filepos_t * inused)2002*1c60b9acSAndroid Build Coastguard Worker lws_h2_parser(struct lws *wsi, unsigned char *in, lws_filepos_t _inlen,
2003*1c60b9acSAndroid Build Coastguard Worker lws_filepos_t *inused)
2004*1c60b9acSAndroid Build Coastguard Worker {
2005*1c60b9acSAndroid Build Coastguard Worker struct lws_h2_netconn *h2n = wsi->h2.h2n;
2006*1c60b9acSAndroid Build Coastguard Worker struct lws_h2_protocol_send *pps;
2007*1c60b9acSAndroid Build Coastguard Worker unsigned char c, *oldin = in, *iend = in + (size_t)_inlen;
2008*1c60b9acSAndroid Build Coastguard Worker int n, m;
2009*1c60b9acSAndroid Build Coastguard Worker
2010*1c60b9acSAndroid Build Coastguard Worker if (!h2n)
2011*1c60b9acSAndroid Build Coastguard Worker goto fail;
2012*1c60b9acSAndroid Build Coastguard Worker
2013*1c60b9acSAndroid Build Coastguard Worker while (in < iend) {
2014*1c60b9acSAndroid Build Coastguard Worker
2015*1c60b9acSAndroid Build Coastguard Worker c = *in++;
2016*1c60b9acSAndroid Build Coastguard Worker
2017*1c60b9acSAndroid Build Coastguard Worker switch (lwsi_state(wsi)) {
2018*1c60b9acSAndroid Build Coastguard Worker case LRS_H2_AWAIT_PREFACE:
2019*1c60b9acSAndroid Build Coastguard Worker if (preface[h2n->count++] != c)
2020*1c60b9acSAndroid Build Coastguard Worker goto fail;
2021*1c60b9acSAndroid Build Coastguard Worker
2022*1c60b9acSAndroid Build Coastguard Worker if (preface[h2n->count])
2023*1c60b9acSAndroid Build Coastguard Worker break;
2024*1c60b9acSAndroid Build Coastguard Worker
2025*1c60b9acSAndroid Build Coastguard Worker lwsl_info("http2: %s: established\n", lws_wsi_tag(wsi));
2026*1c60b9acSAndroid Build Coastguard Worker lwsi_set_state(wsi, LRS_H2_AWAIT_SETTINGS);
2027*1c60b9acSAndroid Build Coastguard Worker lws_validity_confirmed(wsi);
2028*1c60b9acSAndroid Build Coastguard Worker h2n->count = 0;
2029*1c60b9acSAndroid Build Coastguard Worker wsi->txc.tx_cr = 65535;
2030*1c60b9acSAndroid Build Coastguard Worker
2031*1c60b9acSAndroid Build Coastguard Worker /*
2032*1c60b9acSAndroid Build Coastguard Worker * we must send a settings frame -- empty one is OK...
2033*1c60b9acSAndroid Build Coastguard Worker * that must be the first thing sent by server
2034*1c60b9acSAndroid Build Coastguard Worker * and the peer must send a SETTINGS with ACK flag...
2035*1c60b9acSAndroid Build Coastguard Worker */
2036*1c60b9acSAndroid Build Coastguard Worker pps = lws_h2_new_pps(LWS_H2_PPS_MY_SETTINGS);
2037*1c60b9acSAndroid Build Coastguard Worker if (!pps)
2038*1c60b9acSAndroid Build Coastguard Worker goto fail;
2039*1c60b9acSAndroid Build Coastguard Worker lws_pps_schedule(wsi, pps);
2040*1c60b9acSAndroid Build Coastguard Worker break;
2041*1c60b9acSAndroid Build Coastguard Worker
2042*1c60b9acSAndroid Build Coastguard Worker case LRS_H2_WAITING_TO_SEND_HEADERS:
2043*1c60b9acSAndroid Build Coastguard Worker case LRS_ESTABLISHED:
2044*1c60b9acSAndroid Build Coastguard Worker case LRS_H2_AWAIT_SETTINGS:
2045*1c60b9acSAndroid Build Coastguard Worker
2046*1c60b9acSAndroid Build Coastguard Worker if (h2n->frame_state != LWS_H2_FRAME_HEADER_LENGTH)
2047*1c60b9acSAndroid Build Coastguard Worker goto try_frame_start;
2048*1c60b9acSAndroid Build Coastguard Worker
2049*1c60b9acSAndroid Build Coastguard Worker /*
2050*1c60b9acSAndroid Build Coastguard Worker * post-header, preamble / payload / padding part
2051*1c60b9acSAndroid Build Coastguard Worker */
2052*1c60b9acSAndroid Build Coastguard Worker h2n->count++;
2053*1c60b9acSAndroid Build Coastguard Worker
2054*1c60b9acSAndroid Build Coastguard Worker if (h2n->type == LWS_H2_FRAME_TYPE_COUNT) { /* IGNORING FRAME */
2055*1c60b9acSAndroid Build Coastguard Worker //lwsl_debug("%s: consuming for ignored %u %u\n", __func__, (unsigned int)h2n->count, (unsigned int)h2n->length);
2056*1c60b9acSAndroid Build Coastguard Worker goto frame_end;
2057*1c60b9acSAndroid Build Coastguard Worker }
2058*1c60b9acSAndroid Build Coastguard Worker
2059*1c60b9acSAndroid Build Coastguard Worker
2060*1c60b9acSAndroid Build Coastguard Worker if (h2n->flags & LWS_H2_FLAG_PADDED &&
2061*1c60b9acSAndroid Build Coastguard Worker !h2n->pad_length) {
2062*1c60b9acSAndroid Build Coastguard Worker /*
2063*1c60b9acSAndroid Build Coastguard Worker * Get the padding count... actual padding is
2064*1c60b9acSAndroid Build Coastguard Worker * at the end of the frame.
2065*1c60b9acSAndroid Build Coastguard Worker */
2066*1c60b9acSAndroid Build Coastguard Worker h2n->padding = c;
2067*1c60b9acSAndroid Build Coastguard Worker h2n->pad_length = 1;
2068*1c60b9acSAndroid Build Coastguard Worker h2n->preamble++;
2069*1c60b9acSAndroid Build Coastguard Worker
2070*1c60b9acSAndroid Build Coastguard Worker if (h2n->padding > h2n->length - 1)
2071*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi,
2072*1c60b9acSAndroid Build Coastguard Worker H2_ERR_PROTOCOL_ERROR,
2073*1c60b9acSAndroid Build Coastguard Worker "execssive padding");
2074*1c60b9acSAndroid Build Coastguard Worker break; /* we consumed this */
2075*1c60b9acSAndroid Build Coastguard Worker }
2076*1c60b9acSAndroid Build Coastguard Worker
2077*1c60b9acSAndroid Build Coastguard Worker if (h2n->flags & LWS_H2_FLAG_PRIORITY &&
2078*1c60b9acSAndroid Build Coastguard Worker !h2n->collected_priority) {
2079*1c60b9acSAndroid Build Coastguard Worker /* going to be 5 preamble bytes */
2080*1c60b9acSAndroid Build Coastguard Worker
2081*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("PRIORITY FLAG: 0x%x\n", c);
2082*1c60b9acSAndroid Build Coastguard Worker
2083*1c60b9acSAndroid Build Coastguard Worker if (h2n->preamble++ - h2n->pad_length < 4) {
2084*1c60b9acSAndroid Build Coastguard Worker h2n->dep = ((h2n->dep) << 8) | c;
2085*1c60b9acSAndroid Build Coastguard Worker break; /* we consumed this */
2086*1c60b9acSAndroid Build Coastguard Worker }
2087*1c60b9acSAndroid Build Coastguard Worker h2n->weight_temp = c;
2088*1c60b9acSAndroid Build Coastguard Worker h2n->collected_priority = 1;
2089*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("PRI FL: dep 0x%x, weight 0x%02X\n",
2090*1c60b9acSAndroid Build Coastguard Worker (unsigned int)h2n->dep,
2091*1c60b9acSAndroid Build Coastguard Worker h2n->weight_temp);
2092*1c60b9acSAndroid Build Coastguard Worker break; /* we consumed this */
2093*1c60b9acSAndroid Build Coastguard Worker }
2094*1c60b9acSAndroid Build Coastguard Worker if (h2n->padding && h2n->count >
2095*1c60b9acSAndroid Build Coastguard Worker (h2n->length - h2n->padding)) {
2096*1c60b9acSAndroid Build Coastguard Worker if (c) {
2097*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR,
2098*1c60b9acSAndroid Build Coastguard Worker "nonzero padding");
2099*1c60b9acSAndroid Build Coastguard Worker break;
2100*1c60b9acSAndroid Build Coastguard Worker }
2101*1c60b9acSAndroid Build Coastguard Worker goto frame_end;
2102*1c60b9acSAndroid Build Coastguard Worker }
2103*1c60b9acSAndroid Build Coastguard Worker
2104*1c60b9acSAndroid Build Coastguard Worker /* applies to wsi->h2.swsi which may be wsi */
2105*1c60b9acSAndroid Build Coastguard Worker switch(h2n->type) {
2106*1c60b9acSAndroid Build Coastguard Worker
2107*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_FRAME_TYPE_SETTINGS:
2108*1c60b9acSAndroid Build Coastguard Worker n = (int)(h2n->count - 1u - h2n->preamble) %
2109*1c60b9acSAndroid Build Coastguard Worker LWS_H2_SETTINGS_LEN;
2110*1c60b9acSAndroid Build Coastguard Worker h2n->one_setting[n] = c;
2111*1c60b9acSAndroid Build Coastguard Worker if (n != LWS_H2_SETTINGS_LEN - 1)
2112*1c60b9acSAndroid Build Coastguard Worker break;
2113*1c60b9acSAndroid Build Coastguard Worker lws_h2_settings(wsi, &h2n->peer_set,
2114*1c60b9acSAndroid Build Coastguard Worker h2n->one_setting,
2115*1c60b9acSAndroid Build Coastguard Worker LWS_H2_SETTINGS_LEN);
2116*1c60b9acSAndroid Build Coastguard Worker break;
2117*1c60b9acSAndroid Build Coastguard Worker
2118*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_FRAME_TYPE_CONTINUATION:
2119*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_FRAME_TYPE_HEADERS:
2120*1c60b9acSAndroid Build Coastguard Worker if (!h2n->swsi)
2121*1c60b9acSAndroid Build Coastguard Worker break;
2122*1c60b9acSAndroid Build Coastguard Worker if (lws_hpack_interpret(h2n->swsi, c)) {
2123*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: hpack failed\n",
2124*1c60b9acSAndroid Build Coastguard Worker __func__);
2125*1c60b9acSAndroid Build Coastguard Worker goto fail;
2126*1c60b9acSAndroid Build Coastguard Worker }
2127*1c60b9acSAndroid Build Coastguard Worker break;
2128*1c60b9acSAndroid Build Coastguard Worker
2129*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_FRAME_TYPE_GOAWAY:
2130*1c60b9acSAndroid Build Coastguard Worker switch (h2n->inside++) {
2131*1c60b9acSAndroid Build Coastguard Worker case 0:
2132*1c60b9acSAndroid Build Coastguard Worker case 1:
2133*1c60b9acSAndroid Build Coastguard Worker case 2:
2134*1c60b9acSAndroid Build Coastguard Worker case 3:
2135*1c60b9acSAndroid Build Coastguard Worker h2n->goaway_last_sid <<= 8;
2136*1c60b9acSAndroid Build Coastguard Worker h2n->goaway_last_sid |= c;
2137*1c60b9acSAndroid Build Coastguard Worker h2n->goaway_str[0] = '\0';
2138*1c60b9acSAndroid Build Coastguard Worker break;
2139*1c60b9acSAndroid Build Coastguard Worker
2140*1c60b9acSAndroid Build Coastguard Worker case 4:
2141*1c60b9acSAndroid Build Coastguard Worker case 5:
2142*1c60b9acSAndroid Build Coastguard Worker case 6:
2143*1c60b9acSAndroid Build Coastguard Worker case 7:
2144*1c60b9acSAndroid Build Coastguard Worker h2n->goaway_err <<= 8;
2145*1c60b9acSAndroid Build Coastguard Worker h2n->goaway_err |= c;
2146*1c60b9acSAndroid Build Coastguard Worker break;
2147*1c60b9acSAndroid Build Coastguard Worker
2148*1c60b9acSAndroid Build Coastguard Worker default:
2149*1c60b9acSAndroid Build Coastguard Worker if (h2n->inside - 9 <
2150*1c60b9acSAndroid Build Coastguard Worker sizeof(h2n->goaway_str) - 1)
2151*1c60b9acSAndroid Build Coastguard Worker h2n->goaway_str[
2152*1c60b9acSAndroid Build Coastguard Worker h2n->inside - 9] = (char)c;
2153*1c60b9acSAndroid Build Coastguard Worker h2n->goaway_str[
2154*1c60b9acSAndroid Build Coastguard Worker sizeof(h2n->goaway_str) - 1] = '\0';
2155*1c60b9acSAndroid Build Coastguard Worker break;
2156*1c60b9acSAndroid Build Coastguard Worker }
2157*1c60b9acSAndroid Build Coastguard Worker break;
2158*1c60b9acSAndroid Build Coastguard Worker
2159*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_FRAME_TYPE_DATA:
2160*1c60b9acSAndroid Build Coastguard Worker
2161*1c60b9acSAndroid Build Coastguard Worker // lwsl_info("%s: LWS_H2_FRAME_TYPE_DATA: fl 0x%x\n",
2162*1c60b9acSAndroid Build Coastguard Worker // __func__, h2n->flags);
2163*1c60b9acSAndroid Build Coastguard Worker
2164*1c60b9acSAndroid Build Coastguard Worker /*
2165*1c60b9acSAndroid Build Coastguard Worker * let the network wsi live a bit longer if
2166*1c60b9acSAndroid Build Coastguard Worker * subs are active... our frame may take a long
2167*1c60b9acSAndroid Build Coastguard Worker * time to chew through
2168*1c60b9acSAndroid Build Coastguard Worker */
2169*1c60b9acSAndroid Build Coastguard Worker if (!wsi->immortal_substream_count)
2170*1c60b9acSAndroid Build Coastguard Worker lws_set_timeout(wsi,
2171*1c60b9acSAndroid Build Coastguard Worker PENDING_TIMEOUT_HTTP_KEEPALIVE_IDLE,
2172*1c60b9acSAndroid Build Coastguard Worker wsi->a.vhost->keepalive_timeout ?
2173*1c60b9acSAndroid Build Coastguard Worker wsi->a.vhost->keepalive_timeout : 31);
2174*1c60b9acSAndroid Build Coastguard Worker
2175*1c60b9acSAndroid Build Coastguard Worker if (!h2n->swsi)
2176*1c60b9acSAndroid Build Coastguard Worker break;
2177*1c60b9acSAndroid Build Coastguard Worker
2178*1c60b9acSAndroid Build Coastguard Worker if (lws_buflist_next_segment_len(
2179*1c60b9acSAndroid Build Coastguard Worker &h2n->swsi->buflist, NULL))
2180*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: substream has pending\n",
2181*1c60b9acSAndroid Build Coastguard Worker __func__);
2182*1c60b9acSAndroid Build Coastguard Worker
2183*1c60b9acSAndroid Build Coastguard Worker if (lwsi_role_http(h2n->swsi) &&
2184*1c60b9acSAndroid Build Coastguard Worker lwsi_state(h2n->swsi) == LRS_ESTABLISHED) {
2185*1c60b9acSAndroid Build Coastguard Worker lwsi_set_state(h2n->swsi, LRS_BODY);
2186*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: %s to LRS_BODY\n",
2187*1c60b9acSAndroid Build Coastguard Worker __func__, lws_wsi_tag(h2n->swsi));
2188*1c60b9acSAndroid Build Coastguard Worker }
2189*1c60b9acSAndroid Build Coastguard Worker
2190*1c60b9acSAndroid Build Coastguard Worker /*
2191*1c60b9acSAndroid Build Coastguard Worker * in + length may cover multiple frames, we
2192*1c60b9acSAndroid Build Coastguard Worker * can only consider the length of the DATA
2193*1c60b9acSAndroid Build Coastguard Worker * in front of us
2194*1c60b9acSAndroid Build Coastguard Worker */
2195*1c60b9acSAndroid Build Coastguard Worker
2196*1c60b9acSAndroid Build Coastguard Worker if (lws_hdr_total_length(h2n->swsi,
2197*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP_CONTENT_LENGTH) &&
2198*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->http.rx_content_length &&
2199*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->http.rx_content_remain <
2200*1c60b9acSAndroid Build Coastguard Worker h2n->length && /* last */
2201*1c60b9acSAndroid Build Coastguard Worker h2n->inside < h2n->length) {
2202*1c60b9acSAndroid Build Coastguard Worker
2203*1c60b9acSAndroid Build Coastguard Worker lwsl_warn("%s: %lu %lu %lu %lu\n", __func__,
2204*1c60b9acSAndroid Build Coastguard Worker (unsigned long)h2n->swsi->http.rx_content_remain,
2205*1c60b9acSAndroid Build Coastguard Worker (unsigned long)(lws_ptr_diff_size_t(iend, in) + 1),
2206*1c60b9acSAndroid Build Coastguard Worker (unsigned long)h2n->inside, (unsigned long)h2n->length);
2207*1c60b9acSAndroid Build Coastguard Worker
2208*1c60b9acSAndroid Build Coastguard Worker /* unread data in frame */
2209*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi,
2210*1c60b9acSAndroid Build Coastguard Worker H2_ERR_PROTOCOL_ERROR,
2211*1c60b9acSAndroid Build Coastguard Worker "More rx than content_length told");
2212*1c60b9acSAndroid Build Coastguard Worker break;
2213*1c60b9acSAndroid Build Coastguard Worker }
2214*1c60b9acSAndroid Build Coastguard Worker
2215*1c60b9acSAndroid Build Coastguard Worker /*
2216*1c60b9acSAndroid Build Coastguard Worker * We operate on a frame. The RX we have at
2217*1c60b9acSAndroid Build Coastguard Worker * hand may exceed the current frame.
2218*1c60b9acSAndroid Build Coastguard Worker */
2219*1c60b9acSAndroid Build Coastguard Worker
2220*1c60b9acSAndroid Build Coastguard Worker n = (int)lws_ptr_diff_size_t(iend, in) + 1;
2221*1c60b9acSAndroid Build Coastguard Worker if (n > (int)(h2n->length - h2n->count + 1)) {
2222*1c60b9acSAndroid Build Coastguard Worker if (h2n->count > h2n->length)
2223*1c60b9acSAndroid Build Coastguard Worker goto close_swsi_and_return;
2224*1c60b9acSAndroid Build Coastguard Worker n = (int)(h2n->length - h2n->count) + 1;
2225*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("---- restricting len to %d "
2226*1c60b9acSAndroid Build Coastguard Worker "\n", n);
2227*1c60b9acSAndroid Build Coastguard Worker }
2228*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
2229*1c60b9acSAndroid Build Coastguard Worker if (h2n->swsi->client_mux_substream) {
2230*1c60b9acSAndroid Build Coastguard Worker if (!h2n->swsi->a.protocol) {
2231*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: %p doesn't have protocol\n",
2232*1c60b9acSAndroid Build Coastguard Worker __func__, lws_wsi_tag(h2n->swsi));
2233*1c60b9acSAndroid Build Coastguard Worker m = 1;
2234*1c60b9acSAndroid Build Coastguard Worker } else {
2235*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->txc.peer_tx_cr_est -= n;
2236*1c60b9acSAndroid Build Coastguard Worker wsi->txc.peer_tx_cr_est -= n;
2237*1c60b9acSAndroid Build Coastguard Worker lws_wsi_txc_describe(&h2n->swsi->txc,
2238*1c60b9acSAndroid Build Coastguard Worker __func__,
2239*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->mux.my_sid);
2240*1c60b9acSAndroid Build Coastguard Worker m = user_callback_handle_rxflow(
2241*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->a.protocol->callback,
2242*1c60b9acSAndroid Build Coastguard Worker h2n->swsi,
2243*1c60b9acSAndroid Build Coastguard Worker LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ,
2244*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->user_space,
2245*1c60b9acSAndroid Build Coastguard Worker in - 1, (unsigned int)n);
2246*1c60b9acSAndroid Build Coastguard Worker }
2247*1c60b9acSAndroid Build Coastguard Worker
2248*1c60b9acSAndroid Build Coastguard Worker in += n - 1;
2249*1c60b9acSAndroid Build Coastguard Worker h2n->inside += (unsigned int)n;
2250*1c60b9acSAndroid Build Coastguard Worker h2n->count += (unsigned int)n - 1;
2251*1c60b9acSAndroid Build Coastguard Worker
2252*1c60b9acSAndroid Build Coastguard Worker if (m) {
2253*1c60b9acSAndroid Build Coastguard Worker lwsl_info("RECEIVE_CLIENT_HTTP "
2254*1c60b9acSAndroid Build Coastguard Worker "closed it\n");
2255*1c60b9acSAndroid Build Coastguard Worker goto close_swsi_and_return;
2256*1c60b9acSAndroid Build Coastguard Worker }
2257*1c60b9acSAndroid Build Coastguard Worker
2258*1c60b9acSAndroid Build Coastguard Worker goto do_windows;
2259*1c60b9acSAndroid Build Coastguard Worker }
2260*1c60b9acSAndroid Build Coastguard Worker #endif
2261*1c60b9acSAndroid Build Coastguard Worker if (lwsi_state(h2n->swsi) == LRS_DEFERRING_ACTION) {
2262*1c60b9acSAndroid Build Coastguard Worker m = lws_buflist_append_segment(
2263*1c60b9acSAndroid Build Coastguard Worker &h2n->swsi->buflist, in - 1, (unsigned int)n);
2264*1c60b9acSAndroid Build Coastguard Worker if (m < 0)
2265*1c60b9acSAndroid Build Coastguard Worker return -1;
2266*1c60b9acSAndroid Build Coastguard Worker
2267*1c60b9acSAndroid Build Coastguard Worker /*
2268*1c60b9acSAndroid Build Coastguard Worker * Since we're in an open-ended
2269*1c60b9acSAndroid Build Coastguard Worker * DEFERRING_ACTION, don't add this swsi
2270*1c60b9acSAndroid Build Coastguard Worker * to the pt list of wsi holding buflist
2271*1c60b9acSAndroid Build Coastguard Worker * content yet, we are not in a position
2272*1c60b9acSAndroid Build Coastguard Worker * to consume it until we get out of
2273*1c60b9acSAndroid Build Coastguard Worker * DEFERRING_ACTION.
2274*1c60b9acSAndroid Build Coastguard Worker */
2275*1c60b9acSAndroid Build Coastguard Worker
2276*1c60b9acSAndroid Build Coastguard Worker in += n - 1;
2277*1c60b9acSAndroid Build Coastguard Worker h2n->inside += (unsigned int)n;
2278*1c60b9acSAndroid Build Coastguard Worker h2n->count += (unsigned int)n - 1;
2279*1c60b9acSAndroid Build Coastguard Worker
2280*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: deferred %d\n", __func__, n);
2281*1c60b9acSAndroid Build Coastguard Worker goto do_windows;
2282*1c60b9acSAndroid Build Coastguard Worker }
2283*1c60b9acSAndroid Build Coastguard Worker
2284*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->outer_will_close = 1;
2285*1c60b9acSAndroid Build Coastguard Worker /*
2286*1c60b9acSAndroid Build Coastguard Worker * choose the length for this go so that we end at
2287*1c60b9acSAndroid Build Coastguard Worker * the frame boundary, in the case there is already
2288*1c60b9acSAndroid Build Coastguard Worker * more waiting leave it for next time around
2289*1c60b9acSAndroid Build Coastguard Worker */
2290*1c60b9acSAndroid Build Coastguard Worker
2291*1c60b9acSAndroid Build Coastguard Worker n = lws_read_h1(h2n->swsi, in - 1, (unsigned int)n);
2292*1c60b9acSAndroid Build Coastguard Worker // lwsl_notice("%s: lws_read_h1 %d\n", __func__, n);
2293*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->outer_will_close = 0;
2294*1c60b9acSAndroid Build Coastguard Worker /*
2295*1c60b9acSAndroid Build Coastguard Worker * can return 0 in POST body with
2296*1c60b9acSAndroid Build Coastguard Worker * content len exhausted somehow.
2297*1c60b9acSAndroid Build Coastguard Worker */
2298*1c60b9acSAndroid Build Coastguard Worker if (n < 0 ||
2299*1c60b9acSAndroid Build Coastguard Worker (!n && h2n->swsi->http.content_length_given && !lws_buflist_next_segment_len(
2300*1c60b9acSAndroid Build Coastguard Worker &wsi->buflist, NULL))) {
2301*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: lws_read_h1 told %d %u / %u\n",
2302*1c60b9acSAndroid Build Coastguard Worker __func__, n,
2303*1c60b9acSAndroid Build Coastguard Worker (unsigned int)h2n->count,
2304*1c60b9acSAndroid Build Coastguard Worker (unsigned int)h2n->length);
2305*1c60b9acSAndroid Build Coastguard Worker in += h2n->length - h2n->count;
2306*1c60b9acSAndroid Build Coastguard Worker h2n->inside = h2n->length;
2307*1c60b9acSAndroid Build Coastguard Worker h2n->count = h2n->length - 1;
2308*1c60b9acSAndroid Build Coastguard Worker
2309*1c60b9acSAndroid Build Coastguard Worker //if (n < 0)
2310*1c60b9acSAndroid Build Coastguard Worker // goto already_closed_swsi;
2311*1c60b9acSAndroid Build Coastguard Worker goto close_swsi_and_return;
2312*1c60b9acSAndroid Build Coastguard Worker }
2313*1c60b9acSAndroid Build Coastguard Worker
2314*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: lws_read_h1 telling %d %u / %u\n",
2315*1c60b9acSAndroid Build Coastguard Worker __func__, n,
2316*1c60b9acSAndroid Build Coastguard Worker (unsigned int)h2n->count,
2317*1c60b9acSAndroid Build Coastguard Worker (unsigned int)h2n->length);
2318*1c60b9acSAndroid Build Coastguard Worker
2319*1c60b9acSAndroid Build Coastguard Worker in += (unsigned int)n - 1;
2320*1c60b9acSAndroid Build Coastguard Worker h2n->inside += (unsigned int)n;
2321*1c60b9acSAndroid Build Coastguard Worker h2n->count += (unsigned int)n - 1;
2322*1c60b9acSAndroid Build Coastguard Worker
2323*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->txc.peer_tx_cr_est -= n;
2324*1c60b9acSAndroid Build Coastguard Worker wsi->txc.peer_tx_cr_est -= n;
2325*1c60b9acSAndroid Build Coastguard Worker
2326*1c60b9acSAndroid Build Coastguard Worker do_windows:
2327*1c60b9acSAndroid Build Coastguard Worker
2328*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
2329*1c60b9acSAndroid Build Coastguard Worker if (!(h2n->swsi->flags & LCCSCF_H2_MANUAL_RXFLOW))
2330*1c60b9acSAndroid Build Coastguard Worker #endif
2331*1c60b9acSAndroid Build Coastguard Worker {
2332*1c60b9acSAndroid Build Coastguard Worker /*
2333*1c60b9acSAndroid Build Coastguard Worker * The default behaviour is we just keep
2334*1c60b9acSAndroid Build Coastguard Worker * cranking the other side's tx credit
2335*1c60b9acSAndroid Build Coastguard Worker * back up, for simple bulk transfer as
2336*1c60b9acSAndroid Build Coastguard Worker * fast as we can take it
2337*1c60b9acSAndroid Build Coastguard Worker */
2338*1c60b9acSAndroid Build Coastguard Worker
2339*1c60b9acSAndroid Build Coastguard Worker m = n + 65536;
2340*1c60b9acSAndroid Build Coastguard Worker
2341*1c60b9acSAndroid Build Coastguard Worker /* update both the stream and nwsi */
2342*1c60b9acSAndroid Build Coastguard Worker
2343*1c60b9acSAndroid Build Coastguard Worker lws_h2_update_peer_txcredit_thresh(h2n->swsi,
2344*1c60b9acSAndroid Build Coastguard Worker h2n->sid, m, m);
2345*1c60b9acSAndroid Build Coastguard Worker }
2346*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
2347*1c60b9acSAndroid Build Coastguard Worker else {
2348*1c60b9acSAndroid Build Coastguard Worker /*
2349*1c60b9acSAndroid Build Coastguard Worker * If he's handling it himself, only
2350*1c60b9acSAndroid Build Coastguard Worker * repair the nwsi credit but allow the
2351*1c60b9acSAndroid Build Coastguard Worker * stream credit to run down until the
2352*1c60b9acSAndroid Build Coastguard Worker * user code deals with it
2353*1c60b9acSAndroid Build Coastguard Worker */
2354*1c60b9acSAndroid Build Coastguard Worker lws_h2_update_peer_txcredit(wsi, 0, n);
2355*1c60b9acSAndroid Build Coastguard Worker h2n->swsi->txc.manual = 1;
2356*1c60b9acSAndroid Build Coastguard Worker }
2357*1c60b9acSAndroid Build Coastguard Worker #endif
2358*1c60b9acSAndroid Build Coastguard Worker break;
2359*1c60b9acSAndroid Build Coastguard Worker
2360*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_FRAME_TYPE_PRIORITY:
2361*1c60b9acSAndroid Build Coastguard Worker if (h2n->count <= 4) {
2362*1c60b9acSAndroid Build Coastguard Worker h2n->dep <<= 8;
2363*1c60b9acSAndroid Build Coastguard Worker h2n->dep |= c;
2364*1c60b9acSAndroid Build Coastguard Worker break;
2365*1c60b9acSAndroid Build Coastguard Worker }
2366*1c60b9acSAndroid Build Coastguard Worker h2n->weight_temp = c;
2367*1c60b9acSAndroid Build Coastguard Worker lwsl_info("PRIORITY: dep 0x%x, weight 0x%02X\n",
2368*1c60b9acSAndroid Build Coastguard Worker (unsigned int)h2n->dep, h2n->weight_temp);
2369*1c60b9acSAndroid Build Coastguard Worker
2370*1c60b9acSAndroid Build Coastguard Worker if ((h2n->dep & ~(1u << 31)) == h2n->sid) {
2371*1c60b9acSAndroid Build Coastguard Worker lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR,
2372*1c60b9acSAndroid Build Coastguard Worker "cant depend on own sid");
2373*1c60b9acSAndroid Build Coastguard Worker break;
2374*1c60b9acSAndroid Build Coastguard Worker }
2375*1c60b9acSAndroid Build Coastguard Worker break;
2376*1c60b9acSAndroid Build Coastguard Worker
2377*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_FRAME_TYPE_RST_STREAM:
2378*1c60b9acSAndroid Build Coastguard Worker h2n->hpack_e_dep <<= 8;
2379*1c60b9acSAndroid Build Coastguard Worker h2n->hpack_e_dep |= c;
2380*1c60b9acSAndroid Build Coastguard Worker break;
2381*1c60b9acSAndroid Build Coastguard Worker
2382*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_FRAME_TYPE_PUSH_PROMISE:
2383*1c60b9acSAndroid Build Coastguard Worker break;
2384*1c60b9acSAndroid Build Coastguard Worker
2385*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_FRAME_TYPE_PING:
2386*1c60b9acSAndroid Build Coastguard Worker if (h2n->flags & LWS_H2_FLAG_SETTINGS_ACK) { // ack
2387*1c60b9acSAndroid Build Coastguard Worker } else { /* they're sending us a ping request */
2388*1c60b9acSAndroid Build Coastguard Worker if (h2n->count > 8)
2389*1c60b9acSAndroid Build Coastguard Worker return 1;
2390*1c60b9acSAndroid Build Coastguard Worker h2n->ping_payload[h2n->count - 1] = c;
2391*1c60b9acSAndroid Build Coastguard Worker }
2392*1c60b9acSAndroid Build Coastguard Worker break;
2393*1c60b9acSAndroid Build Coastguard Worker
2394*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_FRAME_TYPE_WINDOW_UPDATE:
2395*1c60b9acSAndroid Build Coastguard Worker h2n->hpack_e_dep <<= 8;
2396*1c60b9acSAndroid Build Coastguard Worker h2n->hpack_e_dep |= c;
2397*1c60b9acSAndroid Build Coastguard Worker break;
2398*1c60b9acSAndroid Build Coastguard Worker
2399*1c60b9acSAndroid Build Coastguard Worker case LWS_H2_FRAME_TYPE_COUNT: /* IGNORING FRAME */
2400*1c60b9acSAndroid Build Coastguard Worker //lwsl_debug("%s: consuming for ignored %u %u\n", __func__, (unsigned int)h2n->count, (unsigned int)h2n->length);
2401*1c60b9acSAndroid Build Coastguard Worker h2n->count++;
2402*1c60b9acSAndroid Build Coastguard Worker break;
2403*1c60b9acSAndroid Build Coastguard Worker
2404*1c60b9acSAndroid Build Coastguard Worker default:
2405*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: unhandled frame type %d\n",
2406*1c60b9acSAndroid Build Coastguard Worker __func__, h2n->type);
2407*1c60b9acSAndroid Build Coastguard Worker
2408*1c60b9acSAndroid Build Coastguard Worker goto fail;
2409*1c60b9acSAndroid Build Coastguard Worker }
2410*1c60b9acSAndroid Build Coastguard Worker
2411*1c60b9acSAndroid Build Coastguard Worker frame_end:
2412*1c60b9acSAndroid Build Coastguard Worker if (h2n->count > h2n->length) {
2413*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: count > length %u %u (type %d)\n",
2414*1c60b9acSAndroid Build Coastguard Worker __func__, (unsigned int)h2n->count,
2415*1c60b9acSAndroid Build Coastguard Worker (unsigned int)h2n->length, h2n->type);
2416*1c60b9acSAndroid Build Coastguard Worker
2417*1c60b9acSAndroid Build Coastguard Worker } else
2418*1c60b9acSAndroid Build Coastguard Worker if (h2n->count != h2n->length)
2419*1c60b9acSAndroid Build Coastguard Worker break;
2420*1c60b9acSAndroid Build Coastguard Worker
2421*1c60b9acSAndroid Build Coastguard Worker /*
2422*1c60b9acSAndroid Build Coastguard Worker * end of frame just happened
2423*1c60b9acSAndroid Build Coastguard Worker */
2424*1c60b9acSAndroid Build Coastguard Worker n = lws_h2_parse_end_of_frame(wsi);
2425*1c60b9acSAndroid Build Coastguard Worker if (n == 2) {
2426*1c60b9acSAndroid Build Coastguard Worker *inused = (lws_filepos_t)lws_ptr_diff_size_t(in, oldin);
2427*1c60b9acSAndroid Build Coastguard Worker
2428*1c60b9acSAndroid Build Coastguard Worker return 2;
2429*1c60b9acSAndroid Build Coastguard Worker }
2430*1c60b9acSAndroid Build Coastguard Worker if (n)
2431*1c60b9acSAndroid Build Coastguard Worker goto fail;
2432*1c60b9acSAndroid Build Coastguard Worker
2433*1c60b9acSAndroid Build Coastguard Worker break;
2434*1c60b9acSAndroid Build Coastguard Worker
2435*1c60b9acSAndroid Build Coastguard Worker try_frame_start:
2436*1c60b9acSAndroid Build Coastguard Worker if (h2n->frame_state <= 8) {
2437*1c60b9acSAndroid Build Coastguard Worker
2438*1c60b9acSAndroid Build Coastguard Worker switch (h2n->frame_state++) {
2439*1c60b9acSAndroid Build Coastguard Worker case 0:
2440*1c60b9acSAndroid Build Coastguard Worker h2n->pad_length = 0;
2441*1c60b9acSAndroid Build Coastguard Worker h2n->collected_priority = 0;
2442*1c60b9acSAndroid Build Coastguard Worker h2n->padding = 0;
2443*1c60b9acSAndroid Build Coastguard Worker h2n->preamble = 0;
2444*1c60b9acSAndroid Build Coastguard Worker h2n->length = c;
2445*1c60b9acSAndroid Build Coastguard Worker h2n->inside = 0;
2446*1c60b9acSAndroid Build Coastguard Worker break;
2447*1c60b9acSAndroid Build Coastguard Worker case 1:
2448*1c60b9acSAndroid Build Coastguard Worker case 2:
2449*1c60b9acSAndroid Build Coastguard Worker h2n->length <<= 8;
2450*1c60b9acSAndroid Build Coastguard Worker h2n->length |= c;
2451*1c60b9acSAndroid Build Coastguard Worker break;
2452*1c60b9acSAndroid Build Coastguard Worker case 3:
2453*1c60b9acSAndroid Build Coastguard Worker h2n->type = c;
2454*1c60b9acSAndroid Build Coastguard Worker break;
2455*1c60b9acSAndroid Build Coastguard Worker case 4:
2456*1c60b9acSAndroid Build Coastguard Worker h2n->flags = c;
2457*1c60b9acSAndroid Build Coastguard Worker break;
2458*1c60b9acSAndroid Build Coastguard Worker
2459*1c60b9acSAndroid Build Coastguard Worker case 5:
2460*1c60b9acSAndroid Build Coastguard Worker case 6:
2461*1c60b9acSAndroid Build Coastguard Worker case 7:
2462*1c60b9acSAndroid Build Coastguard Worker case 8:
2463*1c60b9acSAndroid Build Coastguard Worker h2n->sid <<= 8;
2464*1c60b9acSAndroid Build Coastguard Worker h2n->sid |= c;
2465*1c60b9acSAndroid Build Coastguard Worker break;
2466*1c60b9acSAndroid Build Coastguard Worker }
2467*1c60b9acSAndroid Build Coastguard Worker }
2468*1c60b9acSAndroid Build Coastguard Worker
2469*1c60b9acSAndroid Build Coastguard Worker if (h2n->frame_state == LWS_H2_FRAME_HEADER_LENGTH &&
2470*1c60b9acSAndroid Build Coastguard Worker lws_h2_parse_frame_header(wsi))
2471*1c60b9acSAndroid Build Coastguard Worker goto fail;
2472*1c60b9acSAndroid Build Coastguard Worker break;
2473*1c60b9acSAndroid Build Coastguard Worker
2474*1c60b9acSAndroid Build Coastguard Worker default:
2475*1c60b9acSAndroid Build Coastguard Worker if (h2n->type == LWS_H2_FRAME_TYPE_COUNT) { /* IGNORING FRAME */
2476*1c60b9acSAndroid Build Coastguard Worker //lwsl_debug("%s: consuming for ignored %u %u\n", __func__, (unsigned int)h2n->count, (unsigned int)h2n->length);
2477*1c60b9acSAndroid Build Coastguard Worker h2n->count++;
2478*1c60b9acSAndroid Build Coastguard Worker }
2479*1c60b9acSAndroid Build Coastguard Worker break;
2480*1c60b9acSAndroid Build Coastguard Worker }
2481*1c60b9acSAndroid Build Coastguard Worker }
2482*1c60b9acSAndroid Build Coastguard Worker
2483*1c60b9acSAndroid Build Coastguard Worker *inused = (lws_filepos_t)lws_ptr_diff_size_t(in, oldin);
2484*1c60b9acSAndroid Build Coastguard Worker
2485*1c60b9acSAndroid Build Coastguard Worker return 0;
2486*1c60b9acSAndroid Build Coastguard Worker
2487*1c60b9acSAndroid Build Coastguard Worker close_swsi_and_return:
2488*1c60b9acSAndroid Build Coastguard Worker
2489*1c60b9acSAndroid Build Coastguard Worker lws_close_free_wsi(h2n->swsi, 0, "close_swsi_and_return");
2490*1c60b9acSAndroid Build Coastguard Worker h2n->swsi = NULL;
2491*1c60b9acSAndroid Build Coastguard Worker h2n->frame_state = 0;
2492*1c60b9acSAndroid Build Coastguard Worker h2n->count = 0;
2493*1c60b9acSAndroid Build Coastguard Worker
2494*1c60b9acSAndroid Build Coastguard Worker // already_closed_swsi:
2495*1c60b9acSAndroid Build Coastguard Worker *inused = (lws_filepos_t)lws_ptr_diff_size_t(in, oldin);
2496*1c60b9acSAndroid Build Coastguard Worker
2497*1c60b9acSAndroid Build Coastguard Worker return 2;
2498*1c60b9acSAndroid Build Coastguard Worker
2499*1c60b9acSAndroid Build Coastguard Worker fail:
2500*1c60b9acSAndroid Build Coastguard Worker *inused = (lws_filepos_t)lws_ptr_diff_size_t(in, oldin);
2501*1c60b9acSAndroid Build Coastguard Worker
2502*1c60b9acSAndroid Build Coastguard Worker return 1;
2503*1c60b9acSAndroid Build Coastguard Worker }
2504*1c60b9acSAndroid Build Coastguard Worker
2505*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
2506*1c60b9acSAndroid Build Coastguard Worker int
lws_h2_client_handshake(struct lws * wsi)2507*1c60b9acSAndroid Build Coastguard Worker lws_h2_client_handshake(struct lws *wsi)
2508*1c60b9acSAndroid Build Coastguard Worker {
2509*1c60b9acSAndroid Build Coastguard Worker struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
2510*1c60b9acSAndroid Build Coastguard Worker uint8_t *buf, *start, *p, *p1, *end;
2511*1c60b9acSAndroid Build Coastguard Worker char *meth = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_METHOD),
2512*1c60b9acSAndroid Build Coastguard Worker *uri = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_URI), *simp;
2513*1c60b9acSAndroid Build Coastguard Worker struct lws *nwsi = lws_get_network_wsi(wsi);
2514*1c60b9acSAndroid Build Coastguard Worker const char *path = "/";
2515*1c60b9acSAndroid Build Coastguard Worker int n, m;
2516*1c60b9acSAndroid Build Coastguard Worker /*
2517*1c60b9acSAndroid Build Coastguard Worker * The identifier of a newly established stream MUST be numerically
2518*1c60b9acSAndroid Build Coastguard Worker * greater than all streams that the initiating endpoint has opened or
2519*1c60b9acSAndroid Build Coastguard Worker * reserved. This governs streams that are opened using a HEADERS frame
2520*1c60b9acSAndroid Build Coastguard Worker * and streams that are reserved using PUSH_PROMISE. An endpoint that
2521*1c60b9acSAndroid Build Coastguard Worker * receives an unexpected stream identifier MUST respond with a
2522*1c60b9acSAndroid Build Coastguard Worker * connection error (Section 5.4.1) of type PROTOCOL_ERROR.
2523*1c60b9acSAndroid Build Coastguard Worker */
2524*1c60b9acSAndroid Build Coastguard Worker unsigned int sid = nwsi->h2.h2n->highest_sid_opened + 2;
2525*1c60b9acSAndroid Build Coastguard Worker
2526*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s\n", __func__);
2527*1c60b9acSAndroid Build Coastguard Worker
2528*1c60b9acSAndroid Build Coastguard Worker /*
2529*1c60b9acSAndroid Build Coastguard Worker * We MUST allocate our sid here at the point we're about to send the
2530*1c60b9acSAndroid Build Coastguard Worker * stream open. It's because we don't know the order in which multiple
2531*1c60b9acSAndroid Build Coastguard Worker * open streams will send their headers... in h2, sending the headers
2532*1c60b9acSAndroid Build Coastguard Worker * is the point the stream is opened. The peer requires that we only
2533*1c60b9acSAndroid Build Coastguard Worker * open streams in ascending sid order
2534*1c60b9acSAndroid Build Coastguard Worker */
2535*1c60b9acSAndroid Build Coastguard Worker
2536*1c60b9acSAndroid Build Coastguard Worker wsi->mux.my_sid = nwsi->h2.h2n->highest_sid_opened = sid;
2537*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: %s: assigning SID %d at header send\n", __func__,
2538*1c60b9acSAndroid Build Coastguard Worker lws_wsi_tag(wsi), sid);
2539*1c60b9acSAndroid Build Coastguard Worker
2540*1c60b9acSAndroid Build Coastguard Worker
2541*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: CLIENT_WAITING_TO_SEND_HEADERS: pollout (sid %d)\n",
2542*1c60b9acSAndroid Build Coastguard Worker __func__, wsi->mux.my_sid);
2543*1c60b9acSAndroid Build Coastguard Worker
2544*1c60b9acSAndroid Build Coastguard Worker p = start = buf = pt->serv_buf + LWS_PRE;
2545*1c60b9acSAndroid Build Coastguard Worker end = start + (wsi->a.context->pt_serv_buf_size / 2) - LWS_PRE - 1;
2546*1c60b9acSAndroid Build Coastguard Worker
2547*1c60b9acSAndroid Build Coastguard Worker /* it's time for us to send our client stream headers */
2548*1c60b9acSAndroid Build Coastguard Worker
2549*1c60b9acSAndroid Build Coastguard Worker if (!meth)
2550*1c60b9acSAndroid Build Coastguard Worker meth = "GET";
2551*1c60b9acSAndroid Build Coastguard Worker
2552*1c60b9acSAndroid Build Coastguard Worker /* h2 pseudoheaders must be in a bunch at the start */
2553*1c60b9acSAndroid Build Coastguard Worker
2554*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_by_token(wsi,
2555*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP_COLON_METHOD,
2556*1c60b9acSAndroid Build Coastguard Worker (unsigned char *)meth,
2557*1c60b9acSAndroid Build Coastguard Worker (int)strlen(meth), &p, end))
2558*1c60b9acSAndroid Build Coastguard Worker goto fail_length;
2559*1c60b9acSAndroid Build Coastguard Worker
2560*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_by_token(wsi,
2561*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP_COLON_SCHEME,
2562*1c60b9acSAndroid Build Coastguard Worker (unsigned char *)"https", 5,
2563*1c60b9acSAndroid Build Coastguard Worker &p, end))
2564*1c60b9acSAndroid Build Coastguard Worker goto fail_length;
2565*1c60b9acSAndroid Build Coastguard Worker
2566*1c60b9acSAndroid Build Coastguard Worker
2567*1c60b9acSAndroid Build Coastguard Worker n = lws_hdr_total_length(wsi, _WSI_TOKEN_CLIENT_URI);
2568*1c60b9acSAndroid Build Coastguard Worker if (n)
2569*1c60b9acSAndroid Build Coastguard Worker path = uri;
2570*1c60b9acSAndroid Build Coastguard Worker else
2571*1c60b9acSAndroid Build Coastguard Worker if (wsi->stash && wsi->stash->cis[CIS_PATH]) {
2572*1c60b9acSAndroid Build Coastguard Worker path = wsi->stash->cis[CIS_PATH];
2573*1c60b9acSAndroid Build Coastguard Worker n = (int)strlen(path);
2574*1c60b9acSAndroid Build Coastguard Worker } else
2575*1c60b9acSAndroid Build Coastguard Worker n = 1;
2576*1c60b9acSAndroid Build Coastguard Worker
2577*1c60b9acSAndroid Build Coastguard Worker if (n > 1 && path[0] == '/' && path[1] == '/') {
2578*1c60b9acSAndroid Build Coastguard Worker path++;
2579*1c60b9acSAndroid Build Coastguard Worker n--;
2580*1c60b9acSAndroid Build Coastguard Worker }
2581*1c60b9acSAndroid Build Coastguard Worker
2582*1c60b9acSAndroid Build Coastguard Worker if (n && lws_add_http_header_by_token(wsi,
2583*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP_COLON_PATH,
2584*1c60b9acSAndroid Build Coastguard Worker (unsigned char *)path, n, &p, end))
2585*1c60b9acSAndroid Build Coastguard Worker goto fail_length;
2586*1c60b9acSAndroid Build Coastguard Worker
2587*1c60b9acSAndroid Build Coastguard Worker n = lws_hdr_total_length(wsi, _WSI_TOKEN_CLIENT_HOST);
2588*1c60b9acSAndroid Build Coastguard Worker simp = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_HOST);
2589*1c60b9acSAndroid Build Coastguard Worker if (!n && wsi->stash && wsi->stash->cis[CIS_ADDRESS]) {
2590*1c60b9acSAndroid Build Coastguard Worker n = (int)strlen(wsi->stash->cis[CIS_ADDRESS]);
2591*1c60b9acSAndroid Build Coastguard Worker simp = wsi->stash->cis[CIS_ADDRESS];
2592*1c60b9acSAndroid Build Coastguard Worker }
2593*1c60b9acSAndroid Build Coastguard Worker
2594*1c60b9acSAndroid Build Coastguard Worker // n = lws_hdr_total_length(wsi, _WSI_TOKEN_CLIENT_ORIGIN);
2595*1c60b9acSAndroid Build Coastguard Worker // simp = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN);
2596*1c60b9acSAndroid Build Coastguard Worker #if 0
2597*1c60b9acSAndroid Build Coastguard Worker if (n && simp && lws_add_http_header_by_token(wsi,
2598*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP_COLON_AUTHORITY,
2599*1c60b9acSAndroid Build Coastguard Worker (unsigned char *)simp, n, &p, end))
2600*1c60b9acSAndroid Build Coastguard Worker goto fail_length;
2601*1c60b9acSAndroid Build Coastguard Worker #endif
2602*1c60b9acSAndroid Build Coastguard Worker
2603*1c60b9acSAndroid Build Coastguard Worker
2604*1c60b9acSAndroid Build Coastguard Worker if (/*!wsi->client_h2_alpn && */n && simp &&
2605*1c60b9acSAndroid Build Coastguard Worker lws_add_http_header_by_token(wsi, WSI_TOKEN_HOST,
2606*1c60b9acSAndroid Build Coastguard Worker (unsigned char *)simp, n, &p, end))
2607*1c60b9acSAndroid Build Coastguard Worker goto fail_length;
2608*1c60b9acSAndroid Build Coastguard Worker
2609*1c60b9acSAndroid Build Coastguard Worker
2610*1c60b9acSAndroid Build Coastguard Worker if (wsi->flags & LCCSCF_HTTP_MULTIPART_MIME) {
2611*1c60b9acSAndroid Build Coastguard Worker p1 = lws_http_multipart_headers(wsi, p);
2612*1c60b9acSAndroid Build Coastguard Worker if (!p1)
2613*1c60b9acSAndroid Build Coastguard Worker goto fail_length;
2614*1c60b9acSAndroid Build Coastguard Worker p = p1;
2615*1c60b9acSAndroid Build Coastguard Worker }
2616*1c60b9acSAndroid Build Coastguard Worker
2617*1c60b9acSAndroid Build Coastguard Worker if (wsi->flags & LCCSCF_HTTP_X_WWW_FORM_URLENCODED) {
2618*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,
2619*1c60b9acSAndroid Build Coastguard Worker (unsigned char *)"application/x-www-form-urlencoded",
2620*1c60b9acSAndroid Build Coastguard Worker 33, &p, end))
2621*1c60b9acSAndroid Build Coastguard Worker goto fail_length;
2622*1c60b9acSAndroid Build Coastguard Worker lws_client_http_body_pending(wsi, 1);
2623*1c60b9acSAndroid Build Coastguard Worker }
2624*1c60b9acSAndroid Build Coastguard Worker
2625*1c60b9acSAndroid Build Coastguard Worker /* give userland a chance to append, eg, cookies */
2626*1c60b9acSAndroid Build Coastguard Worker
2627*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CACHE_NSCOOKIEJAR) && defined(LWS_WITH_CLIENT)
2628*1c60b9acSAndroid Build Coastguard Worker if (wsi->flags & LCCSCF_CACHE_COOKIES)
2629*1c60b9acSAndroid Build Coastguard Worker lws_cookie_send_cookies(wsi, (char **)&p, (char *)end);
2630*1c60b9acSAndroid Build Coastguard Worker #endif
2631*1c60b9acSAndroid Build Coastguard Worker
2632*1c60b9acSAndroid Build Coastguard Worker if (wsi->a.protocol->callback(wsi,
2633*1c60b9acSAndroid Build Coastguard Worker LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER,
2634*1c60b9acSAndroid Build Coastguard Worker wsi->user_space, &p, lws_ptr_diff_size_t(end, p) - 12))
2635*1c60b9acSAndroid Build Coastguard Worker goto fail_length;
2636*1c60b9acSAndroid Build Coastguard Worker
2637*1c60b9acSAndroid Build Coastguard Worker if (lws_finalize_http_header(wsi, &p, end))
2638*1c60b9acSAndroid Build Coastguard Worker goto fail_length;
2639*1c60b9acSAndroid Build Coastguard Worker
2640*1c60b9acSAndroid Build Coastguard Worker m = LWS_WRITE_HTTP_HEADERS;
2641*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
2642*1c60b9acSAndroid Build Coastguard Worker /* below is not needed in spec, indeed it destroys the long poll
2643*1c60b9acSAndroid Build Coastguard Worker * feature, but required by nghttp2 */
2644*1c60b9acSAndroid Build Coastguard Worker if ((wsi->flags & LCCSCF_H2_QUIRK_NGHTTP2_END_STREAM) &&
2645*1c60b9acSAndroid Build Coastguard Worker !(wsi->client_http_body_pending || lws_has_buffered_out(wsi)))
2646*1c60b9acSAndroid Build Coastguard Worker m |= LWS_WRITE_H2_STREAM_END;
2647*1c60b9acSAndroid Build Coastguard Worker #endif
2648*1c60b9acSAndroid Build Coastguard Worker
2649*1c60b9acSAndroid Build Coastguard Worker // lwsl_hexdump_notice(start, p - start);
2650*1c60b9acSAndroid Build Coastguard Worker
2651*1c60b9acSAndroid Build Coastguard Worker n = lws_write(wsi, start, lws_ptr_diff_size_t(p, start), (enum lws_write_protocol)m);
2652*1c60b9acSAndroid Build Coastguard Worker
2653*1c60b9acSAndroid Build Coastguard Worker if (n != lws_ptr_diff(p, start)) {
2654*1c60b9acSAndroid Build Coastguard Worker lwsl_err("_write returned %d from %ld\n", n,
2655*1c60b9acSAndroid Build Coastguard Worker (long)(p - start));
2656*1c60b9acSAndroid Build Coastguard Worker return -1;
2657*1c60b9acSAndroid Build Coastguard Worker }
2658*1c60b9acSAndroid Build Coastguard Worker
2659*1c60b9acSAndroid Build Coastguard Worker /*
2660*1c60b9acSAndroid Build Coastguard Worker * Normally let's charge up the peer tx credit a bit. But if
2661*1c60b9acSAndroid Build Coastguard Worker * MANUAL_REFLOW is set, just set it to the initial credit given in
2662*1c60b9acSAndroid Build Coastguard Worker * the client create info
2663*1c60b9acSAndroid Build Coastguard Worker */
2664*1c60b9acSAndroid Build Coastguard Worker
2665*1c60b9acSAndroid Build Coastguard Worker n = 4 * 65536;
2666*1c60b9acSAndroid Build Coastguard Worker if (wsi->flags & LCCSCF_H2_MANUAL_RXFLOW) {
2667*1c60b9acSAndroid Build Coastguard Worker n = wsi->txc.manual_initial_tx_credit;
2668*1c60b9acSAndroid Build Coastguard Worker wsi->txc.manual = 1;
2669*1c60b9acSAndroid Build Coastguard Worker }
2670*1c60b9acSAndroid Build Coastguard Worker
2671*1c60b9acSAndroid Build Coastguard Worker if (lws_h2_update_peer_txcredit(wsi, wsi->mux.my_sid, n))
2672*1c60b9acSAndroid Build Coastguard Worker return 1;
2673*1c60b9acSAndroid Build Coastguard Worker
2674*1c60b9acSAndroid Build Coastguard Worker lws_h2_state(wsi, LWS_H2_STATE_OPEN);
2675*1c60b9acSAndroid Build Coastguard Worker lwsi_set_state(wsi, LRS_ESTABLISHED);
2676*1c60b9acSAndroid Build Coastguard Worker
2677*1c60b9acSAndroid Build Coastguard Worker if (wsi->flags & LCCSCF_HTTP_MULTIPART_MIME)
2678*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(wsi);
2679*1c60b9acSAndroid Build Coastguard Worker
2680*1c60b9acSAndroid Build Coastguard Worker return 0;
2681*1c60b9acSAndroid Build Coastguard Worker
2682*1c60b9acSAndroid Build Coastguard Worker fail_length:
2683*1c60b9acSAndroid Build Coastguard Worker lwsl_err("Client hdrs too long: incr context info.pt_serv_buf_size\n");
2684*1c60b9acSAndroid Build Coastguard Worker
2685*1c60b9acSAndroid Build Coastguard Worker return -1;
2686*1c60b9acSAndroid Build Coastguard Worker }
2687*1c60b9acSAndroid Build Coastguard Worker #endif
2688*1c60b9acSAndroid Build Coastguard Worker
2689*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_ROLE_WS) && defined(LWS_WITH_SERVER)
2690*1c60b9acSAndroid Build Coastguard Worker int
lws_h2_ws_handshake(struct lws * wsi)2691*1c60b9acSAndroid Build Coastguard Worker lws_h2_ws_handshake(struct lws *wsi)
2692*1c60b9acSAndroid Build Coastguard Worker {
2693*1c60b9acSAndroid Build Coastguard Worker uint8_t buf[LWS_PRE + 2048], *p = buf + LWS_PRE, *start = p,
2694*1c60b9acSAndroid Build Coastguard Worker *end = &buf[sizeof(buf) - 1];
2695*1c60b9acSAndroid Build Coastguard Worker const struct lws_http_mount *hit;
2696*1c60b9acSAndroid Build Coastguard Worker const char * uri_ptr;
2697*1c60b9acSAndroid Build Coastguard Worker size_t m;
2698*1c60b9acSAndroid Build Coastguard Worker int n;
2699*1c60b9acSAndroid Build Coastguard Worker
2700*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end))
2701*1c60b9acSAndroid Build Coastguard Worker return -1;
2702*1c60b9acSAndroid Build Coastguard Worker
2703*1c60b9acSAndroid Build Coastguard Worker if (lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL) > 64)
2704*1c60b9acSAndroid Build Coastguard Worker return -1;
2705*1c60b9acSAndroid Build Coastguard Worker
2706*1c60b9acSAndroid Build Coastguard Worker if (wsi->proxied_ws_parent && wsi->child_list) {
2707*1c60b9acSAndroid Build Coastguard Worker if (lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL)) {
2708*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_by_token(wsi, WSI_TOKEN_PROTOCOL,
2709*1c60b9acSAndroid Build Coastguard Worker (uint8_t *)lws_hdr_simple_ptr(wsi,
2710*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_PROTOCOL),
2711*1c60b9acSAndroid Build Coastguard Worker (int)strlen(lws_hdr_simple_ptr(wsi,
2712*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_PROTOCOL)),
2713*1c60b9acSAndroid Build Coastguard Worker &p, end))
2714*1c60b9acSAndroid Build Coastguard Worker return -1;
2715*1c60b9acSAndroid Build Coastguard Worker }
2716*1c60b9acSAndroid Build Coastguard Worker } else {
2717*1c60b9acSAndroid Build Coastguard Worker
2718*1c60b9acSAndroid Build Coastguard Worker /* we can only return the protocol header if:
2719*1c60b9acSAndroid Build Coastguard Worker * - one came in, and ... */
2720*1c60b9acSAndroid Build Coastguard Worker if (lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL) &&
2721*1c60b9acSAndroid Build Coastguard Worker /* - it is not an empty string */
2722*1c60b9acSAndroid Build Coastguard Worker wsi->a.protocol->name && wsi->a.protocol->name[0]) {
2723*1c60b9acSAndroid Build Coastguard Worker
2724*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SECURE_STREAMS) && defined(LWS_WITH_SERVER)
2725*1c60b9acSAndroid Build Coastguard Worker
2726*1c60b9acSAndroid Build Coastguard Worker /*
2727*1c60b9acSAndroid Build Coastguard Worker * This is the h2 version of server-ws.c understanding that it
2728*1c60b9acSAndroid Build Coastguard Worker * did the ws upgrade on a ss server object, therefore it needs
2729*1c60b9acSAndroid Build Coastguard Worker * to pass back to the peer the policy ws-protocol name, not
2730*1c60b9acSAndroid Build Coastguard Worker * the generic ss-ws.c protocol name
2731*1c60b9acSAndroid Build Coastguard Worker */
2732*1c60b9acSAndroid Build Coastguard Worker
2733*1c60b9acSAndroid Build Coastguard Worker if (wsi->a.vhost && wsi->a.vhost->ss_handle &&
2734*1c60b9acSAndroid Build Coastguard Worker wsi->a.vhost->ss_handle->policy->u.http.u.ws.subprotocol) {
2735*1c60b9acSAndroid Build Coastguard Worker lws_ss_handle_t *h =
2736*1c60b9acSAndroid Build Coastguard Worker (lws_ss_handle_t *)wsi->a.opaque_user_data;
2737*1c60b9acSAndroid Build Coastguard Worker
2738*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: Server SS %s .wsi %s switching to ws protocol\n",
2739*1c60b9acSAndroid Build Coastguard Worker __func__, lws_ss_tag(h), lws_wsi_tag(h->wsi));
2740*1c60b9acSAndroid Build Coastguard Worker
2741*1c60b9acSAndroid Build Coastguard Worker wsi->a.protocol = &protocol_secstream_ws;
2742*1c60b9acSAndroid Build Coastguard Worker
2743*1c60b9acSAndroid Build Coastguard Worker /*
2744*1c60b9acSAndroid Build Coastguard Worker * inform the SS user code that this has done a one-way
2745*1c60b9acSAndroid Build Coastguard Worker * upgrade to some other protocol... it will likely
2746*1c60b9acSAndroid Build Coastguard Worker * want to treat subsequent payloads differently
2747*1c60b9acSAndroid Build Coastguard Worker */
2748*1c60b9acSAndroid Build Coastguard Worker
2749*1c60b9acSAndroid Build Coastguard Worker lws_ss_event_helper(h, LWSSSCS_SERVER_UPGRADE);
2750*1c60b9acSAndroid Build Coastguard Worker
2751*1c60b9acSAndroid Build Coastguard Worker lws_mux_mark_immortal(wsi);
2752*1c60b9acSAndroid Build Coastguard Worker
2753*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_by_token(wsi, WSI_TOKEN_PROTOCOL,
2754*1c60b9acSAndroid Build Coastguard Worker (unsigned char *)wsi->a.vhost->ss_handle->policy->
2755*1c60b9acSAndroid Build Coastguard Worker u.http.u.ws.subprotocol,
2756*1c60b9acSAndroid Build Coastguard Worker (int)strlen(wsi->a.vhost->ss_handle->policy->
2757*1c60b9acSAndroid Build Coastguard Worker u.http.u.ws.subprotocol), &p, end))
2758*1c60b9acSAndroid Build Coastguard Worker return -1;
2759*1c60b9acSAndroid Build Coastguard Worker } else
2760*1c60b9acSAndroid Build Coastguard Worker #endif
2761*1c60b9acSAndroid Build Coastguard Worker
2762*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_by_token(wsi, WSI_TOKEN_PROTOCOL,
2763*1c60b9acSAndroid Build Coastguard Worker (unsigned char *)wsi->a.protocol->name,
2764*1c60b9acSAndroid Build Coastguard Worker (int)strlen(wsi->a.protocol->name), &p, end))
2765*1c60b9acSAndroid Build Coastguard Worker return -1;
2766*1c60b9acSAndroid Build Coastguard Worker }
2767*1c60b9acSAndroid Build Coastguard Worker }
2768*1c60b9acSAndroid Build Coastguard Worker
2769*1c60b9acSAndroid Build Coastguard Worker if (lws_finalize_http_header(wsi, &p, end))
2770*1c60b9acSAndroid Build Coastguard Worker return -1;
2771*1c60b9acSAndroid Build Coastguard Worker
2772*1c60b9acSAndroid Build Coastguard Worker m = lws_ptr_diff_size_t(p, start);
2773*1c60b9acSAndroid Build Coastguard Worker // lwsl_hexdump_notice(start, m);
2774*1c60b9acSAndroid Build Coastguard Worker n = lws_write(wsi, start, m, LWS_WRITE_HTTP_HEADERS);
2775*1c60b9acSAndroid Build Coastguard Worker if (n != (int)m) {
2776*1c60b9acSAndroid Build Coastguard Worker lwsl_err("_write returned %d from %d\n", n, (int)m);
2777*1c60b9acSAndroid Build Coastguard Worker
2778*1c60b9acSAndroid Build Coastguard Worker return -1;
2779*1c60b9acSAndroid Build Coastguard Worker }
2780*1c60b9acSAndroid Build Coastguard Worker
2781*1c60b9acSAndroid Build Coastguard Worker /*
2782*1c60b9acSAndroid Build Coastguard Worker * alright clean up, set our state to generic ws established, the
2783*1c60b9acSAndroid Build Coastguard Worker * mode / state of the nwsi will get the h2 processing done.
2784*1c60b9acSAndroid Build Coastguard Worker */
2785*1c60b9acSAndroid Build Coastguard Worker
2786*1c60b9acSAndroid Build Coastguard Worker lwsi_set_state(wsi, LRS_ESTABLISHED);
2787*1c60b9acSAndroid Build Coastguard Worker wsi->lws_rx_parse_state = 0; // ==LWS_RXPS_NEW;
2788*1c60b9acSAndroid Build Coastguard Worker
2789*1c60b9acSAndroid Build Coastguard Worker uri_ptr = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_PATH);
2790*1c60b9acSAndroid Build Coastguard Worker n = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COLON_PATH);
2791*1c60b9acSAndroid Build Coastguard Worker hit = lws_find_mount(wsi, uri_ptr, n);
2792*1c60b9acSAndroid Build Coastguard Worker
2793*1c60b9acSAndroid Build Coastguard Worker if (hit && hit->cgienv &&
2794*1c60b9acSAndroid Build Coastguard Worker wsi->a.protocol->callback(wsi, LWS_CALLBACK_HTTP_PMO, wsi->user_space,
2795*1c60b9acSAndroid Build Coastguard Worker (void *)hit->cgienv, 0))
2796*1c60b9acSAndroid Build Coastguard Worker return 1;
2797*1c60b9acSAndroid Build Coastguard Worker
2798*1c60b9acSAndroid Build Coastguard Worker lws_validity_confirmed(wsi);
2799*1c60b9acSAndroid Build Coastguard Worker
2800*1c60b9acSAndroid Build Coastguard Worker return 0;
2801*1c60b9acSAndroid Build Coastguard Worker }
2802*1c60b9acSAndroid Build Coastguard Worker #endif
2803*1c60b9acSAndroid Build Coastguard Worker
2804*1c60b9acSAndroid Build Coastguard Worker int
lws_read_h2(struct lws * wsi,unsigned char * buf,lws_filepos_t len)2805*1c60b9acSAndroid Build Coastguard Worker lws_read_h2(struct lws *wsi, unsigned char *buf, lws_filepos_t len)
2806*1c60b9acSAndroid Build Coastguard Worker {
2807*1c60b9acSAndroid Build Coastguard Worker unsigned char *oldbuf = buf;
2808*1c60b9acSAndroid Build Coastguard Worker lws_filepos_t body_chunk_len;
2809*1c60b9acSAndroid Build Coastguard Worker
2810*1c60b9acSAndroid Build Coastguard Worker // lwsl_notice("%s: h2 path: wsistate 0x%x len %d\n", __func__,
2811*1c60b9acSAndroid Build Coastguard Worker // wsi->wsistate, (int)len);
2812*1c60b9acSAndroid Build Coastguard Worker
2813*1c60b9acSAndroid Build Coastguard Worker /*
2814*1c60b9acSAndroid Build Coastguard Worker * wsi here is always the network connection wsi, not a stream
2815*1c60b9acSAndroid Build Coastguard Worker * wsi. Once we unpicked the framing we will find the right
2816*1c60b9acSAndroid Build Coastguard Worker * swsi and make it the target of the frame.
2817*1c60b9acSAndroid Build Coastguard Worker *
2818*1c60b9acSAndroid Build Coastguard Worker * If it's ws over h2, the nwsi will get us here to do the h2
2819*1c60b9acSAndroid Build Coastguard Worker * processing, and that will call us back with the swsi +
2820*1c60b9acSAndroid Build Coastguard Worker * ESTABLISHED state for the inner payload, handled in a later
2821*1c60b9acSAndroid Build Coastguard Worker * case.
2822*1c60b9acSAndroid Build Coastguard Worker */
2823*1c60b9acSAndroid Build Coastguard Worker while (len) {
2824*1c60b9acSAndroid Build Coastguard Worker int m;
2825*1c60b9acSAndroid Build Coastguard Worker
2826*1c60b9acSAndroid Build Coastguard Worker /*
2827*1c60b9acSAndroid Build Coastguard Worker * we were accepting input but now we stopped doing so
2828*1c60b9acSAndroid Build Coastguard Worker */
2829*1c60b9acSAndroid Build Coastguard Worker if (lws_is_flowcontrolled(wsi)) {
2830*1c60b9acSAndroid Build Coastguard Worker lws_rxflow_cache(wsi, buf, 0, (size_t)len);
2831*1c60b9acSAndroid Build Coastguard Worker buf += len;
2832*1c60b9acSAndroid Build Coastguard Worker break;
2833*1c60b9acSAndroid Build Coastguard Worker }
2834*1c60b9acSAndroid Build Coastguard Worker
2835*1c60b9acSAndroid Build Coastguard Worker /*
2836*1c60b9acSAndroid Build Coastguard Worker * lws_h2_parser() may send something; when it gets the
2837*1c60b9acSAndroid Build Coastguard Worker * whole frame, it will want to perform some action
2838*1c60b9acSAndroid Build Coastguard Worker * involving a reply. But we may be in a partial send
2839*1c60b9acSAndroid Build Coastguard Worker * situation on the network wsi...
2840*1c60b9acSAndroid Build Coastguard Worker *
2841*1c60b9acSAndroid Build Coastguard Worker * Even though we may be in a partial send and unable to
2842*1c60b9acSAndroid Build Coastguard Worker * send anything new, we still have to parse the network
2843*1c60b9acSAndroid Build Coastguard Worker * wsi in order to gain tx credit to send, which is
2844*1c60b9acSAndroid Build Coastguard Worker * potentially necessary to clear the old partial send.
2845*1c60b9acSAndroid Build Coastguard Worker *
2846*1c60b9acSAndroid Build Coastguard Worker * ALL network wsi-specific frames are sent by PPS
2847*1c60b9acSAndroid Build Coastguard Worker * already, these are sent as a priority on the writable
2848*1c60b9acSAndroid Build Coastguard Worker * handler, and so respect partial sends. The only
2849*1c60b9acSAndroid Build Coastguard Worker * problem is when a stream wsi wants to send an, eg,
2850*1c60b9acSAndroid Build Coastguard Worker * reply headers frame in response to the parsing
2851*1c60b9acSAndroid Build Coastguard Worker * we will do now... the *stream wsi* must stall in a
2852*1c60b9acSAndroid Build Coastguard Worker * different state until it is able to do so from a
2853*1c60b9acSAndroid Build Coastguard Worker * priority on the WRITABLE callback, same way that
2854*1c60b9acSAndroid Build Coastguard Worker * file transfers operate.
2855*1c60b9acSAndroid Build Coastguard Worker */
2856*1c60b9acSAndroid Build Coastguard Worker
2857*1c60b9acSAndroid Build Coastguard Worker m = lws_h2_parser(wsi, buf, len, &body_chunk_len);
2858*1c60b9acSAndroid Build Coastguard Worker if (m && m != 2) {
2859*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: http2_parser bail: %d\n", __func__, m);
2860*1c60b9acSAndroid Build Coastguard Worker lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS,
2861*1c60b9acSAndroid Build Coastguard Worker "lws_read_h2 bail");
2862*1c60b9acSAndroid Build Coastguard Worker
2863*1c60b9acSAndroid Build Coastguard Worker return -1;
2864*1c60b9acSAndroid Build Coastguard Worker }
2865*1c60b9acSAndroid Build Coastguard Worker if (m == 2) {
2866*1c60b9acSAndroid Build Coastguard Worker /* swsi has been closed */
2867*1c60b9acSAndroid Build Coastguard Worker buf += body_chunk_len;
2868*1c60b9acSAndroid Build Coastguard Worker break;
2869*1c60b9acSAndroid Build Coastguard Worker }
2870*1c60b9acSAndroid Build Coastguard Worker
2871*1c60b9acSAndroid Build Coastguard Worker buf += body_chunk_len;
2872*1c60b9acSAndroid Build Coastguard Worker len -= body_chunk_len;
2873*1c60b9acSAndroid Build Coastguard Worker }
2874*1c60b9acSAndroid Build Coastguard Worker
2875*1c60b9acSAndroid Build Coastguard Worker return lws_ptr_diff(buf, oldbuf);
2876*1c60b9acSAndroid Build Coastguard Worker }
2877*1c60b9acSAndroid Build Coastguard Worker
2878*1c60b9acSAndroid Build Coastguard Worker int
lws_h2_client_stream_long_poll_rxonly(struct lws * wsi)2879*1c60b9acSAndroid Build Coastguard Worker lws_h2_client_stream_long_poll_rxonly(struct lws *wsi)
2880*1c60b9acSAndroid Build Coastguard Worker {
2881*1c60b9acSAndroid Build Coastguard Worker
2882*1c60b9acSAndroid Build Coastguard Worker if (!wsi->mux_substream)
2883*1c60b9acSAndroid Build Coastguard Worker return 1;
2884*1c60b9acSAndroid Build Coastguard Worker
2885*1c60b9acSAndroid Build Coastguard Worker /*
2886*1c60b9acSAndroid Build Coastguard Worker * Elect to send an empty DATA with END_STREAM, to force the stream
2887*1c60b9acSAndroid Build Coastguard Worker * into HALF_CLOSED LOCAL
2888*1c60b9acSAndroid Build Coastguard Worker */
2889*1c60b9acSAndroid Build Coastguard Worker wsi->h2.long_poll = 1;
2890*1c60b9acSAndroid Build Coastguard Worker wsi->h2.send_END_STREAM = 1;
2891*1c60b9acSAndroid Build Coastguard Worker
2892*1c60b9acSAndroid Build Coastguard Worker // lws_header_table_detach(wsi, 0);
2893*1c60b9acSAndroid Build Coastguard Worker
2894*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(wsi);
2895*1c60b9acSAndroid Build Coastguard Worker
2896*1c60b9acSAndroid Build Coastguard Worker return 0;
2897*1c60b9acSAndroid Build Coastguard Worker }
2898