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