xref: /aosp_15_r20/external/libwebsockets/lib/roles/h2/ops-h2.c (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker  * libwebsockets - small server side websockets and web server implementation
3*1c60b9acSAndroid Build Coastguard Worker  *
4*1c60b9acSAndroid Build Coastguard Worker  * Copyright (C) 2010 - 2019 Andy Green <[email protected]>
5*1c60b9acSAndroid Build Coastguard Worker  *
6*1c60b9acSAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a copy
7*1c60b9acSAndroid Build Coastguard Worker  * of this software and associated documentation files (the "Software"), to
8*1c60b9acSAndroid Build Coastguard Worker  * deal in the Software without restriction, including without limitation the
9*1c60b9acSAndroid Build Coastguard Worker  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10*1c60b9acSAndroid Build Coastguard Worker  * sell copies of the Software, and to permit persons to whom the Software is
11*1c60b9acSAndroid Build Coastguard Worker  * furnished to do so, subject to the following conditions:
12*1c60b9acSAndroid Build Coastguard Worker  *
13*1c60b9acSAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be included in
14*1c60b9acSAndroid Build Coastguard Worker  * all copies or substantial portions of the Software.
15*1c60b9acSAndroid Build Coastguard Worker  *
16*1c60b9acSAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*1c60b9acSAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*1c60b9acSAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19*1c60b9acSAndroid Build Coastguard Worker  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*1c60b9acSAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21*1c60b9acSAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22*1c60b9acSAndroid Build Coastguard Worker  * IN THE SOFTWARE.
23*1c60b9acSAndroid Build Coastguard Worker  */
24*1c60b9acSAndroid Build Coastguard Worker 
25*1c60b9acSAndroid Build Coastguard Worker #include <private-lib-core.h>
26*1c60b9acSAndroid Build Coastguard Worker 
27*1c60b9acSAndroid Build Coastguard Worker /*
28*1c60b9acSAndroid Build Coastguard Worker  * These are the standardized defaults.
29*1c60b9acSAndroid Build Coastguard Worker  * Override what actually goes in the vhost settings in platform or user code.
30*1c60b9acSAndroid Build Coastguard Worker  * Leave these alone because they are used to determine "what is different
31*1c60b9acSAndroid Build Coastguard Worker  * from the protocol defaults".
32*1c60b9acSAndroid Build Coastguard Worker  */
33*1c60b9acSAndroid Build Coastguard Worker const struct http2_settings lws_h2_defaults = { {
34*1c60b9acSAndroid Build Coastguard Worker 	1,
35*1c60b9acSAndroid Build Coastguard Worker 	/* H2SET_HEADER_TABLE_SIZE */			4096,
36*1c60b9acSAndroid Build Coastguard Worker 	/* *** This controls how many entries in the dynamic table ***
37*1c60b9acSAndroid Build Coastguard Worker 	 * Allows the sender to inform the remote endpoint of the maximum
38*1c60b9acSAndroid Build Coastguard Worker 	 * size of the header compression table used to decode header
39*1c60b9acSAndroid Build Coastguard Worker 	 * blocks, in octets.  The encoder can select any size equal to or
40*1c60b9acSAndroid Build Coastguard Worker 	 * less than this value by using signaling specific to the header
41*1c60b9acSAndroid Build Coastguard Worker 	 * compression format inside a header block (see [COMPRESSION]).
42*1c60b9acSAndroid Build Coastguard Worker 	 * The initial value is 4,096 octets.
43*1c60b9acSAndroid Build Coastguard Worker 	 */
44*1c60b9acSAndroid Build Coastguard Worker 	/* H2SET_ENABLE_PUSH */				   1,
45*1c60b9acSAndroid Build Coastguard Worker 	/* H2SET_MAX_CONCURRENT_STREAMS */	  0x7fffffff,
46*1c60b9acSAndroid Build Coastguard Worker 	/* H2SET_INITIAL_WINDOW_SIZE */		       65535,
47*1c60b9acSAndroid Build Coastguard Worker 	/* H2SET_MAX_FRAME_SIZE */		       16384,
48*1c60b9acSAndroid Build Coastguard Worker 	/* H2SET_MAX_HEADER_LIST_SIZE */	  0x7fffffff,
49*1c60b9acSAndroid Build Coastguard Worker 	/*< This advisory setting informs a peer of the maximum size of
50*1c60b9acSAndroid Build Coastguard Worker 	 * header list that the sender is prepared to accept, in octets.
51*1c60b9acSAndroid Build Coastguard Worker 	 * The value is based on the uncompressed size of header fields,
52*1c60b9acSAndroid Build Coastguard Worker 	 * including the length of the name and value in octets plus an
53*1c60b9acSAndroid Build Coastguard Worker 	 * overhead of 32 octets for each header field.
54*1c60b9acSAndroid Build Coastguard Worker 	 */
55*1c60b9acSAndroid Build Coastguard Worker 	/* H2SET_RESERVED7 */				   0,
56*1c60b9acSAndroid Build Coastguard Worker 	/* H2SET_ENABLE_CONNECT_PROTOCOL */		   0,
57*1c60b9acSAndroid Build Coastguard Worker }};
58*1c60b9acSAndroid Build Coastguard Worker 
59*1c60b9acSAndroid Build Coastguard Worker /* these are the "lws defaults"... they can be overridden in plat */
60*1c60b9acSAndroid Build Coastguard Worker 
61*1c60b9acSAndroid Build Coastguard Worker const struct http2_settings lws_h2_stock_settings = { {
62*1c60b9acSAndroid Build Coastguard Worker 	1,
63*1c60b9acSAndroid Build Coastguard Worker 	/* H2SET_HEADER_TABLE_SIZE */			65536, /* ffox */
64*1c60b9acSAndroid Build Coastguard Worker 	/* *** This controls how many entries in the dynamic table ***
65*1c60b9acSAndroid Build Coastguard Worker 	 * Allows the sender to inform the remote endpoint of the maximum
66*1c60b9acSAndroid Build Coastguard Worker 	 * size of the header compression table used to decode header
67*1c60b9acSAndroid Build Coastguard Worker 	 * blocks, in octets.  The encoder can select any size equal to or
68*1c60b9acSAndroid Build Coastguard Worker 	 * less than this value by using signaling specific to the header
69*1c60b9acSAndroid Build Coastguard Worker 	 * compression format inside a header block (see [COMPRESSION]).
70*1c60b9acSAndroid Build Coastguard Worker 	 * The initial value is 4,096 octets.
71*1c60b9acSAndroid Build Coastguard Worker 	 *
72*1c60b9acSAndroid Build Coastguard Worker 	 * Can't pass h2spec with less than 4096 here...
73*1c60b9acSAndroid Build Coastguard Worker 	 */
74*1c60b9acSAndroid Build Coastguard Worker 	/* H2SET_ENABLE_PUSH */				   0,
75*1c60b9acSAndroid Build Coastguard Worker 	/* H2SET_MAX_CONCURRENT_STREAMS */		  24,
76*1c60b9acSAndroid Build Coastguard Worker 	/* H2SET_INITIAL_WINDOW_SIZE */		           0,
77*1c60b9acSAndroid Build Coastguard Worker 	/*< This is managed by explicit WINDOW_UPDATE.  Because otherwise no
78*1c60b9acSAndroid Build Coastguard Worker 	 * way to precisely control it when we do want to.
79*1c60b9acSAndroid Build Coastguard Worker 	 */
80*1c60b9acSAndroid Build Coastguard Worker 	/* H2SET_MAX_FRAME_SIZE */		       16384,
81*1c60b9acSAndroid Build Coastguard Worker 	/* H2SET_MAX_HEADER_LIST_SIZE */	        4096,
82*1c60b9acSAndroid Build Coastguard Worker 	/*< This advisory setting informs a peer of the maximum size of
83*1c60b9acSAndroid Build Coastguard Worker 	 * header list that the sender is prepared to accept, in octets.
84*1c60b9acSAndroid Build Coastguard Worker 	 * The value is based on the uncompressed size of header fields,
85*1c60b9acSAndroid Build Coastguard Worker 	 * including the length of the name and value in octets plus an
86*1c60b9acSAndroid Build Coastguard Worker 	 * overhead of 32 octets for each header field.
87*1c60b9acSAndroid Build Coastguard Worker 	 */
88*1c60b9acSAndroid Build Coastguard Worker 	/* H2SET_RESERVED7 */				   0,
89*1c60b9acSAndroid Build Coastguard Worker 	/* H2SET_ENABLE_CONNECT_PROTOCOL */		   1,
90*1c60b9acSAndroid Build Coastguard Worker }};
91*1c60b9acSAndroid Build Coastguard Worker 
92*1c60b9acSAndroid Build Coastguard Worker /*
93*1c60b9acSAndroid Build Coastguard Worker  * The wsi at this level is normally the network wsi... we can get called on
94*1c60b9acSAndroid Build Coastguard Worker  * another path via lws_service_do_ripe_rxflow() on mux children too tho...
95*1c60b9acSAndroid Build Coastguard Worker  */
96*1c60b9acSAndroid Build Coastguard Worker 
97*1c60b9acSAndroid Build Coastguard Worker static int
rops_handle_POLLIN_h2(struct lws_context_per_thread * pt,struct lws * wsi,struct lws_pollfd * pollfd)98*1c60b9acSAndroid Build Coastguard Worker rops_handle_POLLIN_h2(struct lws_context_per_thread *pt, struct lws *wsi,
99*1c60b9acSAndroid Build Coastguard Worker 		       struct lws_pollfd *pollfd)
100*1c60b9acSAndroid Build Coastguard Worker {
101*1c60b9acSAndroid Build Coastguard Worker 	struct lws_tokens ebuf;
102*1c60b9acSAndroid Build Coastguard Worker 	unsigned int pending = 0;
103*1c60b9acSAndroid Build Coastguard Worker 	char buffered = 0;
104*1c60b9acSAndroid Build Coastguard Worker 	struct lws *wsi1;
105*1c60b9acSAndroid Build Coastguard Worker 	int n, m;
106*1c60b9acSAndroid Build Coastguard Worker 
107*1c60b9acSAndroid Build Coastguard Worker #ifdef LWS_WITH_CGI
108*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->http.cgi && (pollfd->revents & LWS_POLLOUT)) {
109*1c60b9acSAndroid Build Coastguard Worker 		if (lws_handle_POLLOUT_event(wsi, pollfd))
110*1c60b9acSAndroid Build Coastguard Worker 			return LWS_HPI_RET_PLEASE_CLOSE_ME;
111*1c60b9acSAndroid Build Coastguard Worker 
112*1c60b9acSAndroid Build Coastguard Worker 		return LWS_HPI_RET_HANDLED;
113*1c60b9acSAndroid Build Coastguard Worker 	}
114*1c60b9acSAndroid Build Coastguard Worker #endif
115*1c60b9acSAndroid Build Coastguard Worker 
116*1c60b9acSAndroid Build Coastguard Worker 	 lwsl_info("%s: %s wsistate 0x%x, events %d, revents %d, pollout %d\n", __func__,
117*1c60b9acSAndroid Build Coastguard Worker 		   wsi->lc.gutag, (unsigned int)wsi->wsistate,
118*1c60b9acSAndroid Build Coastguard Worker 		   pollfd->events, pollfd->revents,
119*1c60b9acSAndroid Build Coastguard Worker 		   pollfd->revents & LWS_POLLOUT);
120*1c60b9acSAndroid Build Coastguard Worker 
121*1c60b9acSAndroid Build Coastguard Worker 	 /* !!! */
122*1c60b9acSAndroid Build Coastguard Worker 	 if (wsi->wsistate == 0x10000013) {
123*1c60b9acSAndroid Build Coastguard Worker 		 wsi->bugcatcher++;
124*1c60b9acSAndroid Build Coastguard Worker 		 if (wsi->bugcatcher == 250) {
125*1c60b9acSAndroid Build Coastguard Worker 			 lwsl_err("%s: BUGCATCHER\n", __func__);
126*1c60b9acSAndroid Build Coastguard Worker 			 return LWS_HPI_RET_PLEASE_CLOSE_ME;
127*1c60b9acSAndroid Build Coastguard Worker 		 }
128*1c60b9acSAndroid Build Coastguard Worker 	 } else
129*1c60b9acSAndroid Build Coastguard Worker 		 wsi->bugcatcher = 0;
130*1c60b9acSAndroid Build Coastguard Worker 
131*1c60b9acSAndroid Build Coastguard Worker 	/*
132*1c60b9acSAndroid Build Coastguard Worker 	 * something went wrong with parsing the handshake, and
133*1c60b9acSAndroid Build Coastguard Worker 	 * we ended up back in the event loop without completing it
134*1c60b9acSAndroid Build Coastguard Worker 	 */
135*1c60b9acSAndroid Build Coastguard Worker 	if (lwsi_state(wsi) == LRS_PRE_WS_SERVING_ACCEPT) {
136*1c60b9acSAndroid Build Coastguard Worker 		wsi->socket_is_permanently_unusable = 1;
137*1c60b9acSAndroid Build Coastguard Worker 		return LWS_HPI_RET_PLEASE_CLOSE_ME;
138*1c60b9acSAndroid Build Coastguard Worker 	}
139*1c60b9acSAndroid Build Coastguard Worker 
140*1c60b9acSAndroid Build Coastguard Worker 	if (lwsi_state(wsi) == LRS_WAITING_CONNECT) {
141*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
142*1c60b9acSAndroid Build Coastguard Worker 		if ((pollfd->revents & LWS_POLLOUT) &&
143*1c60b9acSAndroid Build Coastguard Worker 		    lws_handle_POLLOUT_event(wsi, pollfd)) {
144*1c60b9acSAndroid Build Coastguard Worker 			lwsl_debug("POLLOUT event closed it\n");
145*1c60b9acSAndroid Build Coastguard Worker 			return LWS_HPI_RET_PLEASE_CLOSE_ME;
146*1c60b9acSAndroid Build Coastguard Worker 		}
147*1c60b9acSAndroid Build Coastguard Worker 
148*1c60b9acSAndroid Build Coastguard Worker 		n = lws_http_client_socket_service(wsi, pollfd);
149*1c60b9acSAndroid Build Coastguard Worker 		if (n)
150*1c60b9acSAndroid Build Coastguard Worker 			return LWS_HPI_RET_WSI_ALREADY_DIED;
151*1c60b9acSAndroid Build Coastguard Worker #endif
152*1c60b9acSAndroid Build Coastguard Worker 		return LWS_HPI_RET_HANDLED;
153*1c60b9acSAndroid Build Coastguard Worker 	}
154*1c60b9acSAndroid Build Coastguard Worker 
155*1c60b9acSAndroid Build Coastguard Worker 	/* 1: something requested a callback when it was OK to write */
156*1c60b9acSAndroid Build Coastguard Worker 
157*1c60b9acSAndroid Build Coastguard Worker 	if ((pollfd->revents & LWS_POLLOUT) &&
158*1c60b9acSAndroid Build Coastguard Worker 	    lwsi_state_can_handle_POLLOUT(wsi) &&
159*1c60b9acSAndroid Build Coastguard Worker 	    lws_handle_POLLOUT_event(wsi, pollfd)) {
160*1c60b9acSAndroid Build Coastguard Worker 		if (lwsi_state(wsi) == LRS_RETURNED_CLOSE)
161*1c60b9acSAndroid Build Coastguard Worker 			lwsi_set_state(wsi, LRS_FLUSHING_BEFORE_CLOSE);
162*1c60b9acSAndroid Build Coastguard Worker 		/* the write failed... it's had it */
163*1c60b9acSAndroid Build Coastguard Worker 		wsi->socket_is_permanently_unusable = 1;
164*1c60b9acSAndroid Build Coastguard Worker 
165*1c60b9acSAndroid Build Coastguard Worker 		return LWS_HPI_RET_PLEASE_CLOSE_ME;
166*1c60b9acSAndroid Build Coastguard Worker 	}
167*1c60b9acSAndroid Build Coastguard Worker 
168*1c60b9acSAndroid Build Coastguard Worker 	if (lwsi_state(wsi) == LRS_RETURNED_CLOSE ||
169*1c60b9acSAndroid Build Coastguard Worker 	    lwsi_state(wsi) == LRS_WAITING_TO_SEND_CLOSE ||
170*1c60b9acSAndroid Build Coastguard Worker 	    lwsi_state(wsi) == LRS_AWAITING_CLOSE_ACK) {
171*1c60b9acSAndroid Build Coastguard Worker 		/*
172*1c60b9acSAndroid Build Coastguard Worker 		 * we stopped caring about anything except control
173*1c60b9acSAndroid Build Coastguard Worker 		 * packets.  Force flow control off, defeat tx
174*1c60b9acSAndroid Build Coastguard Worker 		 * draining.
175*1c60b9acSAndroid Build Coastguard Worker 		 */
176*1c60b9acSAndroid Build Coastguard Worker 		lws_rx_flow_control(wsi, 1);
177*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_ROLE_WS) && !defined(LWS_WITHOUT_EXTENSIONS)
178*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->ws)
179*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->tx_draining_ext = 0;
180*1c60b9acSAndroid Build Coastguard Worker #endif
181*1c60b9acSAndroid Build Coastguard Worker 	}
182*1c60b9acSAndroid Build Coastguard Worker 
183*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->mux_substream || wsi->upgraded_to_http2) {
184*1c60b9acSAndroid Build Coastguard Worker 		wsi1 = lws_get_network_wsi(wsi);
185*1c60b9acSAndroid Build Coastguard Worker 		if (wsi1 && lws_has_buffered_out(wsi1)) {
186*1c60b9acSAndroid Build Coastguard Worker 
187*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("%s: has buffered out\n", __func__);
188*1c60b9acSAndroid Build Coastguard Worker 			/*
189*1c60b9acSAndroid Build Coastguard Worker 			 * We cannot deal with any kind of new RX
190*1c60b9acSAndroid Build Coastguard Worker 			 * because we are dealing with a partial send
191*1c60b9acSAndroid Build Coastguard Worker 			 * (new RX may trigger new http_action() that
192*1c60b9acSAndroid Build Coastguard Worker 			 * expect to be able to send)
193*1c60b9acSAndroid Build Coastguard Worker 			 */
194*1c60b9acSAndroid Build Coastguard Worker 			return LWS_HPI_RET_HANDLED;
195*1c60b9acSAndroid Build Coastguard Worker 		}
196*1c60b9acSAndroid Build Coastguard Worker 	}
197*1c60b9acSAndroid Build Coastguard Worker 
198*1c60b9acSAndroid Build Coastguard Worker read:
199*1c60b9acSAndroid Build Coastguard Worker 	/* 3: network wsi buflist needs to be drained */
200*1c60b9acSAndroid Build Coastguard Worker 
201*1c60b9acSAndroid Build Coastguard Worker 	// lws_buflist_describe(&wsi->buflist, wsi, __func__);
202*1c60b9acSAndroid Build Coastguard Worker 
203*1c60b9acSAndroid Build Coastguard Worker 	ebuf.len = (int)lws_buflist_next_segment_len(&wsi->buflist,
204*1c60b9acSAndroid Build Coastguard Worker 						&ebuf.token);
205*1c60b9acSAndroid Build Coastguard Worker 	if (ebuf.len) {
206*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("draining buflist (len %d)\n", ebuf.len);
207*1c60b9acSAndroid Build Coastguard Worker 		buffered = 1;
208*1c60b9acSAndroid Build Coastguard Worker 		goto drain;
209*1c60b9acSAndroid Build Coastguard Worker 	} else {
210*1c60b9acSAndroid Build Coastguard Worker 
211*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->mux_substream) {
212*1c60b9acSAndroid Build Coastguard Worker 			lwsl_warn("%s: uh... %s mux child with nothing to drain\n", __func__, lws_wsi_tag(wsi));
213*1c60b9acSAndroid Build Coastguard Worker 			// assert(0);
214*1c60b9acSAndroid Build Coastguard Worker 			lws_dll2_remove(&wsi->dll_buflist);
215*1c60b9acSAndroid Build Coastguard Worker 			return LWS_HPI_RET_HANDLED;
216*1c60b9acSAndroid Build Coastguard Worker 		}
217*1c60b9acSAndroid Build Coastguard Worker 	}
218*1c60b9acSAndroid Build Coastguard Worker 
219*1c60b9acSAndroid Build Coastguard Worker 	if (!lws_ssl_pending(wsi) &&
220*1c60b9acSAndroid Build Coastguard Worker 	    !(pollfd->revents & pollfd->events & LWS_POLLIN))
221*1c60b9acSAndroid Build Coastguard Worker 		return LWS_HPI_RET_HANDLED;
222*1c60b9acSAndroid Build Coastguard Worker 
223*1c60b9acSAndroid Build Coastguard Worker 	/* We have something to read... */
224*1c60b9acSAndroid Build Coastguard Worker 
225*1c60b9acSAndroid Build Coastguard Worker 	if (!(lwsi_role_client(wsi) &&
226*1c60b9acSAndroid Build Coastguard Worker 	      (lwsi_state(wsi) != LRS_ESTABLISHED &&
227*1c60b9acSAndroid Build Coastguard Worker 	       // lwsi_state(wsi) != LRS_H1C_ISSUE_HANDSHAKE2 &&
228*1c60b9acSAndroid Build Coastguard Worker 	       lwsi_state(wsi) != LRS_H2_WAITING_TO_SEND_HEADERS))) {
229*1c60b9acSAndroid Build Coastguard Worker 
230*1c60b9acSAndroid Build Coastguard Worker 		ebuf.token = pt->serv_buf;
231*1c60b9acSAndroid Build Coastguard Worker 		ebuf.len = lws_ssl_capable_read(wsi,
232*1c60b9acSAndroid Build Coastguard Worker 					ebuf.token,
233*1c60b9acSAndroid Build Coastguard Worker 					wsi->a.context->pt_serv_buf_size);
234*1c60b9acSAndroid Build Coastguard Worker 		switch (ebuf.len) {
235*1c60b9acSAndroid Build Coastguard Worker 		case 0:
236*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("%s: zero length read\n", __func__);
237*1c60b9acSAndroid Build Coastguard Worker 			return LWS_HPI_RET_PLEASE_CLOSE_ME;
238*1c60b9acSAndroid Build Coastguard Worker 		case LWS_SSL_CAPABLE_MORE_SERVICE:
239*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("SSL Capable more service\n");
240*1c60b9acSAndroid Build Coastguard Worker 			return LWS_HPI_RET_HANDLED;
241*1c60b9acSAndroid Build Coastguard Worker 		case LWS_SSL_CAPABLE_ERROR:
242*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("%s: LWS_SSL_CAPABLE_ERROR\n", __func__);
243*1c60b9acSAndroid Build Coastguard Worker 			return LWS_HPI_RET_PLEASE_CLOSE_ME;
244*1c60b9acSAndroid Build Coastguard Worker 		}
245*1c60b9acSAndroid Build Coastguard Worker 
246*1c60b9acSAndroid Build Coastguard Worker 		// lwsl_notice("%s: Actual RX %d\n", __func__, ebuf.len);
247*1c60b9acSAndroid Build Coastguard Worker 		// if (ebuf.len > 0)
248*1c60b9acSAndroid Build Coastguard Worker 		//	lwsl_hexdump_notice(ebuf.token, ebuf.len);
249*1c60b9acSAndroid Build Coastguard Worker 	} else
250*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: skipped read\n", __func__);
251*1c60b9acSAndroid Build Coastguard Worker 
252*1c60b9acSAndroid Build Coastguard Worker 	if (ebuf.len < 0)
253*1c60b9acSAndroid Build Coastguard Worker 		return LWS_HPI_RET_PLEASE_CLOSE_ME;
254*1c60b9acSAndroid Build Coastguard Worker 
255*1c60b9acSAndroid Build Coastguard Worker drain:
256*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
257*1c60b9acSAndroid Build Coastguard Worker 	if (lwsi_role_http(wsi) && lwsi_role_client(wsi) &&
258*1c60b9acSAndroid Build Coastguard Worker 	    wsi->hdr_parsing_completed && !wsi->told_user_closed) {
259*1c60b9acSAndroid Build Coastguard Worker 
260*1c60b9acSAndroid Build Coastguard Worker 		/*
261*1c60b9acSAndroid Build Coastguard Worker 		 * In SSL mode we get POLLIN notification about
262*1c60b9acSAndroid Build Coastguard Worker 		 * encrypted data in.
263*1c60b9acSAndroid Build Coastguard Worker 		 *
264*1c60b9acSAndroid Build Coastguard Worker 		 * But that is not necessarily related to decrypted
265*1c60b9acSAndroid Build Coastguard Worker 		 * data out becoming available; in may need to perform
266*1c60b9acSAndroid Build Coastguard Worker 		 * other in or out before that happens.
267*1c60b9acSAndroid Build Coastguard Worker 		 *
268*1c60b9acSAndroid Build Coastguard Worker 		 * simply mark ourselves as having readable data
269*1c60b9acSAndroid Build Coastguard Worker 		 * and turn off our POLLIN
270*1c60b9acSAndroid Build Coastguard Worker 		 */
271*1c60b9acSAndroid Build Coastguard Worker 		wsi->client_rx_avail = 1;
272*1c60b9acSAndroid Build Coastguard Worker 		if (lws_change_pollfd(wsi, LWS_POLLIN, 0))
273*1c60b9acSAndroid Build Coastguard Worker 			return LWS_HPI_RET_PLEASE_CLOSE_ME;
274*1c60b9acSAndroid Build Coastguard Worker 
275*1c60b9acSAndroid Build Coastguard Worker 		/* let user code know, he'll usually ask for writeable
276*1c60b9acSAndroid Build Coastguard Worker 		 * callback and drain / re-enable it there
277*1c60b9acSAndroid Build Coastguard Worker 		 */
278*1c60b9acSAndroid Build Coastguard Worker 		if (user_callback_handle_rxflow(
279*1c60b9acSAndroid Build Coastguard Worker 				wsi->a.protocol->callback,
280*1c60b9acSAndroid Build Coastguard Worker 				wsi, LWS_CALLBACK_RECEIVE_CLIENT_HTTP,
281*1c60b9acSAndroid Build Coastguard Worker 				wsi->user_space, NULL, 0)) {
282*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("RECEIVE_CLIENT_HTTP closed it\n");
283*1c60b9acSAndroid Build Coastguard Worker 			return LWS_HPI_RET_PLEASE_CLOSE_ME;
284*1c60b9acSAndroid Build Coastguard Worker 		}
285*1c60b9acSAndroid Build Coastguard Worker 
286*1c60b9acSAndroid Build Coastguard Worker 		return LWS_HPI_RET_HANDLED;
287*1c60b9acSAndroid Build Coastguard Worker 	}
288*1c60b9acSAndroid Build Coastguard Worker #endif
289*1c60b9acSAndroid Build Coastguard Worker 
290*1c60b9acSAndroid Build Coastguard Worker 	/* service incoming data */
291*1c60b9acSAndroid Build Coastguard Worker 
292*1c60b9acSAndroid Build Coastguard Worker 	if (ebuf.len) {
293*1c60b9acSAndroid Build Coastguard Worker 		n = 0;
294*1c60b9acSAndroid Build Coastguard Worker 		if (lwsi_role_h2(wsi) && lwsi_state(wsi) != LRS_BODY &&
295*1c60b9acSAndroid Build Coastguard Worker 		    lwsi_state(wsi) != LRS_DISCARD_BODY)
296*1c60b9acSAndroid Build Coastguard Worker 			n = lws_read_h2(wsi, ebuf.token, (unsigned int)ebuf.len);
297*1c60b9acSAndroid Build Coastguard Worker 		else
298*1c60b9acSAndroid Build Coastguard Worker 			n = lws_read_h1(wsi, ebuf.token, (unsigned int)ebuf.len);
299*1c60b9acSAndroid Build Coastguard Worker 
300*1c60b9acSAndroid Build Coastguard Worker 		if (n < 0) {
301*1c60b9acSAndroid Build Coastguard Worker 			/* we closed wsi */
302*1c60b9acSAndroid Build Coastguard Worker 			return LWS_HPI_RET_WSI_ALREADY_DIED;
303*1c60b9acSAndroid Build Coastguard Worker 		}
304*1c60b9acSAndroid Build Coastguard Worker 
305*1c60b9acSAndroid Build Coastguard Worker 		if (n && buffered) {
306*1c60b9acSAndroid Build Coastguard Worker 			// lwsl_notice("%s: h2 use %d\n", __func__, n);
307*1c60b9acSAndroid Build Coastguard Worker 			m = (int)lws_buflist_use_segment(&wsi->buflist, (size_t)n);
308*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("%s: draining rxflow: used %d, next %d\n",
309*1c60b9acSAndroid Build Coastguard Worker 				    __func__, n, m);
310*1c60b9acSAndroid Build Coastguard Worker 			if (!m) {
311*1c60b9acSAndroid Build Coastguard Worker 				lwsl_notice("%s: removed %s from dll_buflist\n",
312*1c60b9acSAndroid Build Coastguard Worker 					    __func__, lws_wsi_tag(wsi));
313*1c60b9acSAndroid Build Coastguard Worker 				lws_dll2_remove(&wsi->dll_buflist);
314*1c60b9acSAndroid Build Coastguard Worker 			}
315*1c60b9acSAndroid Build Coastguard Worker 		} else
316*1c60b9acSAndroid Build Coastguard Worker 			if (n && n < ebuf.len && ebuf.len > 0) {
317*1c60b9acSAndroid Build Coastguard Worker 				// lwsl_notice("%s: h2 append seg %d\n", __func__, ebuf.len - n);
318*1c60b9acSAndroid Build Coastguard Worker 				m = lws_buflist_append_segment(&wsi->buflist,
319*1c60b9acSAndroid Build Coastguard Worker 						ebuf.token + n,
320*1c60b9acSAndroid Build Coastguard Worker 						(unsigned int)(ebuf.len - n));
321*1c60b9acSAndroid Build Coastguard Worker 				if (m < 0)
322*1c60b9acSAndroid Build Coastguard Worker 					return LWS_HPI_RET_PLEASE_CLOSE_ME;
323*1c60b9acSAndroid Build Coastguard Worker 				if (m) {
324*1c60b9acSAndroid Build Coastguard Worker 					lwsl_debug("%s: added %s to rxflow list\n",
325*1c60b9acSAndroid Build Coastguard Worker 						   __func__, lws_wsi_tag(wsi));
326*1c60b9acSAndroid Build Coastguard Worker 					if (lws_dll2_is_detached(&wsi->dll_buflist))
327*1c60b9acSAndroid Build Coastguard Worker 						lws_dll2_add_head(&wsi->dll_buflist,
328*1c60b9acSAndroid Build Coastguard Worker 							 &pt->dll_buflist_owner);
329*1c60b9acSAndroid Build Coastguard Worker 				}
330*1c60b9acSAndroid Build Coastguard Worker 			}
331*1c60b9acSAndroid Build Coastguard Worker 	}
332*1c60b9acSAndroid Build Coastguard Worker 
333*1c60b9acSAndroid Build Coastguard Worker 	// lws_buflist_describe(&wsi->buflist, wsi, __func__);
334*1c60b9acSAndroid Build Coastguard Worker 
335*1c60b9acSAndroid Build Coastguard Worker #if 0
336*1c60b9acSAndroid Build Coastguard Worker 
337*1c60b9acSAndroid Build Coastguard Worker 	/*
338*1c60b9acSAndroid Build Coastguard Worker 	 * This seems to be too aggressive... we don't want the ah stuck
339*1c60b9acSAndroid Build Coastguard Worker 	 * there but eg, WINDOW_UPDATE may come and detach it if we leave
340*1c60b9acSAndroid Build Coastguard Worker 	 * it like that... it will get detached at stream close
341*1c60b9acSAndroid Build Coastguard Worker 	 */
342*1c60b9acSAndroid Build Coastguard Worker 
343*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->http.ah
344*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
345*1c60b9acSAndroid Build Coastguard Worker 			&& !wsi->client_h2_alpn
346*1c60b9acSAndroid Build Coastguard Worker #endif
347*1c60b9acSAndroid Build Coastguard Worker 			) {
348*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("xxx\n");
349*1c60b9acSAndroid Build Coastguard Worker 
350*1c60b9acSAndroid Build Coastguard Worker 		lws_header_table_detach(wsi, 0);
351*1c60b9acSAndroid Build Coastguard Worker 	}
352*1c60b9acSAndroid Build Coastguard Worker #endif
353*1c60b9acSAndroid Build Coastguard Worker 
354*1c60b9acSAndroid Build Coastguard Worker 	pending = (unsigned int)lws_ssl_pending(wsi);
355*1c60b9acSAndroid Build Coastguard Worker 	if (pending) {
356*1c60b9acSAndroid Build Coastguard Worker 		// lwsl_info("going around\n");
357*1c60b9acSAndroid Build Coastguard Worker 		goto read;
358*1c60b9acSAndroid Build Coastguard Worker 	}
359*1c60b9acSAndroid Build Coastguard Worker 
360*1c60b9acSAndroid Build Coastguard Worker 	return LWS_HPI_RET_HANDLED;
361*1c60b9acSAndroid Build Coastguard Worker }
362*1c60b9acSAndroid Build Coastguard Worker 
rops_handle_POLLOUT_h2(struct lws * wsi)363*1c60b9acSAndroid Build Coastguard Worker int rops_handle_POLLOUT_h2(struct lws *wsi)
364*1c60b9acSAndroid Build Coastguard Worker {
365*1c60b9acSAndroid Build Coastguard Worker 	// lwsl_notice("%s\n", __func__);
366*1c60b9acSAndroid Build Coastguard Worker 
367*1c60b9acSAndroid Build Coastguard Worker 	if (lwsi_state(wsi) == LRS_ISSUE_HTTP_BODY)
368*1c60b9acSAndroid Build Coastguard Worker 		return LWS_HP_RET_USER_SERVICE;
369*1c60b9acSAndroid Build Coastguard Worker 
370*1c60b9acSAndroid Build Coastguard Worker 	/*
371*1c60b9acSAndroid Build Coastguard Worker 	 * Priority 1: H2 protocol packets
372*1c60b9acSAndroid Build Coastguard Worker 	 */
373*1c60b9acSAndroid Build Coastguard Worker 	if ((wsi->upgraded_to_http2
374*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
375*1c60b9acSAndroid Build Coastguard Worker 			|| wsi->client_h2_alpn
376*1c60b9acSAndroid Build Coastguard Worker #endif
377*1c60b9acSAndroid Build Coastguard Worker 			) && wsi->h2.h2n->pps) {
378*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("servicing pps\n");
379*1c60b9acSAndroid Build Coastguard Worker 		/*
380*1c60b9acSAndroid Build Coastguard Worker 		 * this is called on the network connection, but may close
381*1c60b9acSAndroid Build Coastguard Worker 		 * substreams... that may affect callers
382*1c60b9acSAndroid Build Coastguard Worker 		 */
383*1c60b9acSAndroid Build Coastguard Worker 		if (lws_h2_do_pps_send(wsi)) {
384*1c60b9acSAndroid Build Coastguard Worker 			wsi->socket_is_permanently_unusable = 1;
385*1c60b9acSAndroid Build Coastguard Worker 			return LWS_HP_RET_BAIL_DIE;
386*1c60b9acSAndroid Build Coastguard Worker 		}
387*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->h2.h2n->pps)
388*1c60b9acSAndroid Build Coastguard Worker 			return LWS_HP_RET_BAIL_OK;
389*1c60b9acSAndroid Build Coastguard Worker 
390*1c60b9acSAndroid Build Coastguard Worker 		/* we can resume whatever we were doing */
391*1c60b9acSAndroid Build Coastguard Worker 		lws_rx_flow_control(wsi, LWS_RXFLOW_REASON_APPLIES_ENABLE |
392*1c60b9acSAndroid Build Coastguard Worker 					 LWS_RXFLOW_REASON_H2_PPS_PENDING);
393*1c60b9acSAndroid Build Coastguard Worker 
394*1c60b9acSAndroid Build Coastguard Worker 		return LWS_HP_RET_BAIL_OK; /* leave POLLOUT active */
395*1c60b9acSAndroid Build Coastguard Worker 	}
396*1c60b9acSAndroid Build Coastguard Worker 
397*1c60b9acSAndroid Build Coastguard Worker 	/* Priority 2: if we are closing, not allowed to send more data frags
398*1c60b9acSAndroid Build Coastguard Worker 	 *	       which means user callback or tx ext flush banned now
399*1c60b9acSAndroid Build Coastguard Worker 	 */
400*1c60b9acSAndroid Build Coastguard Worker 	if (lwsi_state(wsi) == LRS_RETURNED_CLOSE)
401*1c60b9acSAndroid Build Coastguard Worker 		return LWS_HP_RET_USER_SERVICE;
402*1c60b9acSAndroid Build Coastguard Worker 
403*1c60b9acSAndroid Build Coastguard Worker 	return LWS_HP_RET_USER_SERVICE;
404*1c60b9acSAndroid Build Coastguard Worker }
405*1c60b9acSAndroid Build Coastguard Worker 
406*1c60b9acSAndroid Build Coastguard Worker static int
rops_write_role_protocol_h2(struct lws * wsi,unsigned char * buf,size_t len,enum lws_write_protocol * wp)407*1c60b9acSAndroid Build Coastguard Worker rops_write_role_protocol_h2(struct lws *wsi, unsigned char *buf, size_t len,
408*1c60b9acSAndroid Build Coastguard Worker 			    enum lws_write_protocol *wp)
409*1c60b9acSAndroid Build Coastguard Worker {
410*1c60b9acSAndroid Build Coastguard Worker 	unsigned char flags = 0, base = (*wp) & 0x1f;
411*1c60b9acSAndroid Build Coastguard Worker 	size_t olen = len;
412*1c60b9acSAndroid Build Coastguard Worker 	int n;
413*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
414*1c60b9acSAndroid Build Coastguard Worker 	unsigned char mtubuf[4096 + LWS_PRE];
415*1c60b9acSAndroid Build Coastguard Worker #endif
416*1c60b9acSAndroid Build Coastguard Worker 
417*1c60b9acSAndroid Build Coastguard Worker 	/* if not in a state to send stuff, then just send nothing */
418*1c60b9acSAndroid Build Coastguard Worker 
419*1c60b9acSAndroid Build Coastguard Worker 	if (!lwsi_role_ws(wsi) && !wsi->mux_stream_immortal &&
420*1c60b9acSAndroid Build Coastguard Worker 	    base != LWS_WRITE_HTTP &&
421*1c60b9acSAndroid Build Coastguard Worker 	    base != LWS_WRITE_HTTP_FINAL &&
422*1c60b9acSAndroid Build Coastguard Worker 	    base != LWS_WRITE_HTTP_HEADERS_CONTINUATION &&
423*1c60b9acSAndroid Build Coastguard Worker 	    base != LWS_WRITE_HTTP_HEADERS && lwsi_state(wsi) != LRS_BODY &&
424*1c60b9acSAndroid Build Coastguard Worker 	    ((lwsi_state(wsi) != LRS_RETURNED_CLOSE &&
425*1c60b9acSAndroid Build Coastguard Worker 	      lwsi_state(wsi) != LRS_WAITING_TO_SEND_CLOSE &&
426*1c60b9acSAndroid Build Coastguard Worker 	      lwsi_state(wsi) != LRS_ESTABLISHED &&
427*1c60b9acSAndroid Build Coastguard Worker 	      lwsi_state(wsi) != LRS_AWAITING_CLOSE_ACK)
428*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_ROLE_WS)
429*1c60b9acSAndroid Build Coastguard Worker 	   || base != LWS_WRITE_CLOSE
430*1c60b9acSAndroid Build Coastguard Worker #endif
431*1c60b9acSAndroid Build Coastguard Worker 	)) {
432*1c60b9acSAndroid Build Coastguard Worker 		//assert(0);
433*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: binning wsistate 0x%x %d: %s\n", __func__,
434*1c60b9acSAndroid Build Coastguard Worker 				(unsigned int)wsi->wsistate, *wp, wsi->a.protocol ?
435*1c60b9acSAndroid Build Coastguard Worker 					wsi->a.protocol->name : "no protocol");
436*1c60b9acSAndroid Build Coastguard Worker 
437*1c60b9acSAndroid Build Coastguard Worker 		return 0;
438*1c60b9acSAndroid Build Coastguard Worker 	}
439*1c60b9acSAndroid Build Coastguard Worker 
440*1c60b9acSAndroid Build Coastguard Worker 	/* compression transform... */
441*1c60b9acSAndroid Build Coastguard Worker 
442*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
443*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->http.lcs) {
444*1c60b9acSAndroid Build Coastguard Worker 		unsigned char *out = mtubuf + LWS_PRE;
445*1c60b9acSAndroid Build Coastguard Worker 		size_t o = sizeof(mtubuf) - LWS_PRE;
446*1c60b9acSAndroid Build Coastguard Worker 
447*1c60b9acSAndroid Build Coastguard Worker 		n = lws_http_compression_transform(wsi, buf, len, wp, &out, &o);
448*1c60b9acSAndroid Build Coastguard Worker 		if (n)
449*1c60b9acSAndroid Build Coastguard Worker 			return n;
450*1c60b9acSAndroid Build Coastguard Worker 
451*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: %s: transformed %d bytes to %d "
452*1c60b9acSAndroid Build Coastguard Worker 			   "(wp 0x%x, more %d)\n", __func__,
453*1c60b9acSAndroid Build Coastguard Worker 			   lws_wsi_tag(wsi), (int)len, (int)o, (int)*wp,
454*1c60b9acSAndroid Build Coastguard Worker 			   wsi->http.comp_ctx.may_have_more);
455*1c60b9acSAndroid Build Coastguard Worker 
456*1c60b9acSAndroid Build Coastguard Worker 		buf = out;
457*1c60b9acSAndroid Build Coastguard Worker 		len = o;
458*1c60b9acSAndroid Build Coastguard Worker 		base = (*wp) & 0x1f;
459*1c60b9acSAndroid Build Coastguard Worker 
460*1c60b9acSAndroid Build Coastguard Worker 		if (!len)
461*1c60b9acSAndroid Build Coastguard Worker 			return (int)olen;
462*1c60b9acSAndroid Build Coastguard Worker 	}
463*1c60b9acSAndroid Build Coastguard Worker #endif
464*1c60b9acSAndroid Build Coastguard Worker 
465*1c60b9acSAndroid Build Coastguard Worker 	/*
466*1c60b9acSAndroid Build Coastguard Worker 	 * ws-over-h2 also ends up here after the ws framing applied
467*1c60b9acSAndroid Build Coastguard Worker 	 */
468*1c60b9acSAndroid Build Coastguard Worker 
469*1c60b9acSAndroid Build Coastguard Worker 	n = LWS_H2_FRAME_TYPE_DATA;
470*1c60b9acSAndroid Build Coastguard Worker 	if (base == LWS_WRITE_HTTP_HEADERS) {
471*1c60b9acSAndroid Build Coastguard Worker 		n = LWS_H2_FRAME_TYPE_HEADERS;
472*1c60b9acSAndroid Build Coastguard Worker 		if (!((*wp) & LWS_WRITE_NO_FIN))
473*1c60b9acSAndroid Build Coastguard Worker 			flags = LWS_H2_FLAG_END_HEADERS;
474*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->h2.send_END_STREAM ||
475*1c60b9acSAndroid Build Coastguard Worker 		    ((*wp) & LWS_WRITE_H2_STREAM_END)) {
476*1c60b9acSAndroid Build Coastguard Worker 			flags |= LWS_H2_FLAG_END_STREAM;
477*1c60b9acSAndroid Build Coastguard Worker 			wsi->h2.send_END_STREAM = 1;
478*1c60b9acSAndroid Build Coastguard Worker 		}
479*1c60b9acSAndroid Build Coastguard Worker 	}
480*1c60b9acSAndroid Build Coastguard Worker 
481*1c60b9acSAndroid Build Coastguard Worker 	if (base == LWS_WRITE_HTTP_HEADERS_CONTINUATION) {
482*1c60b9acSAndroid Build Coastguard Worker 		n = LWS_H2_FRAME_TYPE_CONTINUATION;
483*1c60b9acSAndroid Build Coastguard Worker 		if (!((*wp) & LWS_WRITE_NO_FIN))
484*1c60b9acSAndroid Build Coastguard Worker 			flags = LWS_H2_FLAG_END_HEADERS;
485*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->h2.send_END_STREAM ||
486*1c60b9acSAndroid Build Coastguard Worker 		    ((*wp) & LWS_WRITE_H2_STREAM_END)) {
487*1c60b9acSAndroid Build Coastguard Worker 			flags |= LWS_H2_FLAG_END_STREAM;
488*1c60b9acSAndroid Build Coastguard Worker 			wsi->h2.send_END_STREAM = 1;
489*1c60b9acSAndroid Build Coastguard Worker 		}
490*1c60b9acSAndroid Build Coastguard Worker 	}
491*1c60b9acSAndroid Build Coastguard Worker 
492*1c60b9acSAndroid Build Coastguard Worker 	if ((base == LWS_WRITE_HTTP ||
493*1c60b9acSAndroid Build Coastguard Worker 	     base == LWS_WRITE_HTTP_FINAL) &&
494*1c60b9acSAndroid Build Coastguard Worker 	     wsi->http.tx_content_length) {
495*1c60b9acSAndroid Build Coastguard Worker 		wsi->http.tx_content_remain -= len;
496*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: %s: tx_content_rem = %llu\n", __func__,
497*1c60b9acSAndroid Build Coastguard Worker 			  lws_wsi_tag(wsi),
498*1c60b9acSAndroid Build Coastguard Worker 			  (unsigned long long)wsi->http.tx_content_remain);
499*1c60b9acSAndroid Build Coastguard Worker 		if (!wsi->http.tx_content_remain) {
500*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("%s: selecting final write mode\n", __func__);
501*1c60b9acSAndroid Build Coastguard Worker 			base = *wp = LWS_WRITE_HTTP_FINAL;
502*1c60b9acSAndroid Build Coastguard Worker 		}
503*1c60b9acSAndroid Build Coastguard Worker 	}
504*1c60b9acSAndroid Build Coastguard Worker 
505*1c60b9acSAndroid Build Coastguard Worker 	if (base == LWS_WRITE_HTTP_FINAL || ((*wp) & LWS_WRITE_H2_STREAM_END)) {
506*1c60b9acSAndroid Build Coastguard Worker 		flags |= LWS_H2_FLAG_END_STREAM;
507*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: %s: setting END_STREAM, 0x%x\n", __func__,
508*1c60b9acSAndroid Build Coastguard Worker 				lws_wsi_tag(wsi), flags);
509*1c60b9acSAndroid Build Coastguard Worker 		wsi->h2.send_END_STREAM = 1;
510*1c60b9acSAndroid Build Coastguard Worker 	}
511*1c60b9acSAndroid Build Coastguard Worker 
512*1c60b9acSAndroid Build Coastguard Worker 	n = lws_h2_frame_write(wsi, n, flags, wsi->mux.my_sid, (unsigned int)len, buf);
513*1c60b9acSAndroid Build Coastguard Worker 	if (n < 0)
514*1c60b9acSAndroid Build Coastguard Worker 		return n;
515*1c60b9acSAndroid Build Coastguard Worker 
516*1c60b9acSAndroid Build Coastguard Worker 	/* hide it may have been compressed... */
517*1c60b9acSAndroid Build Coastguard Worker 
518*1c60b9acSAndroid Build Coastguard Worker 	return (int)olen;
519*1c60b9acSAndroid Build Coastguard Worker }
520*1c60b9acSAndroid Build Coastguard Worker 
521*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SERVER)
522*1c60b9acSAndroid Build Coastguard Worker static int
rops_check_upgrades_h2(struct lws * wsi)523*1c60b9acSAndroid Build Coastguard Worker rops_check_upgrades_h2(struct lws *wsi)
524*1c60b9acSAndroid Build Coastguard Worker {
525*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_ROLE_WS)
526*1c60b9acSAndroid Build Coastguard Worker 	char *p;
527*1c60b9acSAndroid Build Coastguard Worker 
528*1c60b9acSAndroid Build Coastguard Worker 	/*
529*1c60b9acSAndroid Build Coastguard Worker 	 * with H2 there's also a way to upgrade a stream to something
530*1c60b9acSAndroid Build Coastguard Worker 	 * else... :method is CONNECT and :protocol says the name of
531*1c60b9acSAndroid Build Coastguard Worker 	 * the new protocol we want to carry.  We have to have sent a
532*1c60b9acSAndroid Build Coastguard Worker 	 * SETTINGS saying that we support it though.
533*1c60b9acSAndroid Build Coastguard Worker 	 */
534*1c60b9acSAndroid Build Coastguard Worker 	p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_METHOD);
535*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi->a.vhost->h2.set.s[H2SET_ENABLE_CONNECT_PROTOCOL] ||
536*1c60b9acSAndroid Build Coastguard Worker 	    !wsi->mux_substream || !p || strcmp(p, "CONNECT"))
537*1c60b9acSAndroid Build Coastguard Worker 		return LWS_UPG_RET_CONTINUE;
538*1c60b9acSAndroid Build Coastguard Worker 
539*1c60b9acSAndroid Build Coastguard Worker 	p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_COLON_PROTOCOL);
540*1c60b9acSAndroid Build Coastguard Worker 	if (!p || strcmp(p, "websocket"))
541*1c60b9acSAndroid Build Coastguard Worker 		return LWS_UPG_RET_CONTINUE;
542*1c60b9acSAndroid Build Coastguard Worker 
543*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("Upgrade h2 to ws\n");
544*1c60b9acSAndroid Build Coastguard Worker 	lws_mux_mark_immortal(wsi);
545*1c60b9acSAndroid Build Coastguard Worker 	wsi->h2_stream_carries_ws = 1;
546*1c60b9acSAndroid Build Coastguard Worker 
547*1c60b9acSAndroid Build Coastguard Worker 	lws_metrics_tag_wsi_add(wsi, "upg", "ws_over_h2");
548*1c60b9acSAndroid Build Coastguard Worker 
549*1c60b9acSAndroid Build Coastguard Worker 	if (lws_process_ws_upgrade(wsi))
550*1c60b9acSAndroid Build Coastguard Worker 		return LWS_UPG_RET_BAIL;
551*1c60b9acSAndroid Build Coastguard Worker 
552*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("Upgraded h2 to ws OK\n");
553*1c60b9acSAndroid Build Coastguard Worker 
554*1c60b9acSAndroid Build Coastguard Worker 	return LWS_UPG_RET_DONE;
555*1c60b9acSAndroid Build Coastguard Worker #else
556*1c60b9acSAndroid Build Coastguard Worker 	return LWS_UPG_RET_CONTINUE;
557*1c60b9acSAndroid Build Coastguard Worker #endif
558*1c60b9acSAndroid Build Coastguard Worker }
559*1c60b9acSAndroid Build Coastguard Worker #endif
560*1c60b9acSAndroid Build Coastguard Worker 
561*1c60b9acSAndroid Build Coastguard Worker static int
rops_init_vhost_h2(struct lws_vhost * vh,const struct lws_context_creation_info * info)562*1c60b9acSAndroid Build Coastguard Worker rops_init_vhost_h2(struct lws_vhost *vh,
563*1c60b9acSAndroid Build Coastguard Worker 		   const struct lws_context_creation_info *info)
564*1c60b9acSAndroid Build Coastguard Worker {
565*1c60b9acSAndroid Build Coastguard Worker 	vh->h2.set = vh->context->set;
566*1c60b9acSAndroid Build Coastguard Worker 	if (info->http2_settings[0]) {
567*1c60b9acSAndroid Build Coastguard Worker 		int n;
568*1c60b9acSAndroid Build Coastguard Worker 
569*1c60b9acSAndroid Build Coastguard Worker 		for (n = 1; n < LWS_H2_SETTINGS_LEN; n++)
570*1c60b9acSAndroid Build Coastguard Worker 			vh->h2.set.s[n] = info->http2_settings[n];
571*1c60b9acSAndroid Build Coastguard Worker 	}
572*1c60b9acSAndroid Build Coastguard Worker 
573*1c60b9acSAndroid Build Coastguard Worker 	return 0;
574*1c60b9acSAndroid Build Coastguard Worker }
575*1c60b9acSAndroid Build Coastguard Worker 
576*1c60b9acSAndroid Build Coastguard Worker int
rops_pt_init_destroy_h2(struct lws_context * context,const struct lws_context_creation_info * info,struct lws_context_per_thread * pt,int destroy)577*1c60b9acSAndroid Build Coastguard Worker rops_pt_init_destroy_h2(struct lws_context *context,
578*1c60b9acSAndroid Build Coastguard Worker 		    const struct lws_context_creation_info *info,
579*1c60b9acSAndroid Build Coastguard Worker 		    struct lws_context_per_thread *pt, int destroy)
580*1c60b9acSAndroid Build Coastguard Worker {
581*1c60b9acSAndroid Build Coastguard Worker 	/* if not already set by plat, use lws default SETTINGS */
582*1c60b9acSAndroid Build Coastguard Worker 	if (!context->set.s[0])
583*1c60b9acSAndroid Build Coastguard Worker 		context->set = lws_h2_stock_settings;
584*1c60b9acSAndroid Build Coastguard Worker 
585*1c60b9acSAndroid Build Coastguard Worker 	/*
586*1c60b9acSAndroid Build Coastguard Worker 	 * We only want to do this once... we will do it if we are built
587*1c60b9acSAndroid Build Coastguard Worker 	 * otherwise h1 ops will do it (or nobody if no http at all)
588*1c60b9acSAndroid Build Coastguard Worker 	 */
589*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_ROLE_H2) && defined(LWS_WITH_SERVER)
590*1c60b9acSAndroid Build Coastguard Worker 	if (!destroy) {
591*1c60b9acSAndroid Build Coastguard Worker 
592*1c60b9acSAndroid Build Coastguard Worker 		pt->sul_ah_lifecheck.cb = lws_sul_http_ah_lifecheck;
593*1c60b9acSAndroid Build Coastguard Worker 
594*1c60b9acSAndroid Build Coastguard Worker 		__lws_sul_insert_us(&pt->pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED],
595*1c60b9acSAndroid Build Coastguard Worker 				 &pt->sul_ah_lifecheck, 30 * LWS_US_PER_SEC);
596*1c60b9acSAndroid Build Coastguard Worker 	} else
597*1c60b9acSAndroid Build Coastguard Worker 		lws_dll2_remove(&pt->sul_ah_lifecheck.list);
598*1c60b9acSAndroid Build Coastguard Worker #endif
599*1c60b9acSAndroid Build Coastguard Worker 
600*1c60b9acSAndroid Build Coastguard Worker 	return 0;
601*1c60b9acSAndroid Build Coastguard Worker }
602*1c60b9acSAndroid Build Coastguard Worker 
603*1c60b9acSAndroid Build Coastguard Worker 
604*1c60b9acSAndroid Build Coastguard Worker static int
rops_tx_credit_h2(struct lws * wsi,char peer_to_us,int add)605*1c60b9acSAndroid Build Coastguard Worker rops_tx_credit_h2(struct lws *wsi, char peer_to_us, int add)
606*1c60b9acSAndroid Build Coastguard Worker {
607*1c60b9acSAndroid Build Coastguard Worker 	struct lws *nwsi = lws_get_network_wsi(wsi);
608*1c60b9acSAndroid Build Coastguard Worker 	int n;
609*1c60b9acSAndroid Build Coastguard Worker 
610*1c60b9acSAndroid Build Coastguard Worker 	if (add) {
611*1c60b9acSAndroid Build Coastguard Worker 		if (peer_to_us == LWSTXCR_PEER_TO_US) {
612*1c60b9acSAndroid Build Coastguard Worker 			/*
613*1c60b9acSAndroid Build Coastguard Worker 			 * We want to tell the peer they can write an additional
614*1c60b9acSAndroid Build Coastguard Worker 			 * "add" bytes to us
615*1c60b9acSAndroid Build Coastguard Worker 			 */
616*1c60b9acSAndroid Build Coastguard Worker 			return lws_h2_update_peer_txcredit(wsi, (unsigned int)-1, add);
617*1c60b9acSAndroid Build Coastguard Worker 		}
618*1c60b9acSAndroid Build Coastguard Worker 
619*1c60b9acSAndroid Build Coastguard Worker 		/*
620*1c60b9acSAndroid Build Coastguard Worker 		 * We're being told we can write an additional "add" bytes
621*1c60b9acSAndroid Build Coastguard Worker 		 * to the peer
622*1c60b9acSAndroid Build Coastguard Worker 		 */
623*1c60b9acSAndroid Build Coastguard Worker 
624*1c60b9acSAndroid Build Coastguard Worker 		wsi->txc.tx_cr += add;
625*1c60b9acSAndroid Build Coastguard Worker 		nwsi->txc.tx_cr += add;
626*1c60b9acSAndroid Build Coastguard Worker 
627*1c60b9acSAndroid Build Coastguard Worker 		return 0;
628*1c60b9acSAndroid Build Coastguard Worker 	}
629*1c60b9acSAndroid Build Coastguard Worker 
630*1c60b9acSAndroid Build Coastguard Worker 	if (peer_to_us == LWSTXCR_US_TO_PEER)
631*1c60b9acSAndroid Build Coastguard Worker 		return lws_h2_tx_cr_get(wsi);
632*1c60b9acSAndroid Build Coastguard Worker 
633*1c60b9acSAndroid Build Coastguard Worker 	n = wsi->txc.peer_tx_cr_est;
634*1c60b9acSAndroid Build Coastguard Worker 	if (n > nwsi->txc.peer_tx_cr_est)
635*1c60b9acSAndroid Build Coastguard Worker 		n = nwsi->txc.peer_tx_cr_est;
636*1c60b9acSAndroid Build Coastguard Worker 
637*1c60b9acSAndroid Build Coastguard Worker 	return n;
638*1c60b9acSAndroid Build Coastguard Worker }
639*1c60b9acSAndroid Build Coastguard Worker 
640*1c60b9acSAndroid Build Coastguard Worker static int
rops_destroy_role_h2(struct lws * wsi)641*1c60b9acSAndroid Build Coastguard Worker rops_destroy_role_h2(struct lws *wsi)
642*1c60b9acSAndroid Build Coastguard Worker {
643*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
644*1c60b9acSAndroid Build Coastguard Worker 	struct allocated_headers *ah;
645*1c60b9acSAndroid Build Coastguard Worker 
646*1c60b9acSAndroid Build Coastguard Worker 	/* we may not have an ah, but may be on the waiting list... */
647*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("%s: %s: ah det due to close\n", __func__, lws_wsi_tag(wsi));
648*1c60b9acSAndroid Build Coastguard Worker 	__lws_header_table_detach(wsi, 0);
649*1c60b9acSAndroid Build Coastguard Worker 
650*1c60b9acSAndroid Build Coastguard Worker 	ah = pt->http.ah_list;
651*1c60b9acSAndroid Build Coastguard Worker 
652*1c60b9acSAndroid Build Coastguard Worker 	while (ah) {
653*1c60b9acSAndroid Build Coastguard Worker 		if (ah->in_use && ah->wsi == wsi) {
654*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: ah leak: %s\n", __func__, lws_wsi_tag(wsi));
655*1c60b9acSAndroid Build Coastguard Worker 			ah->in_use = 0;
656*1c60b9acSAndroid Build Coastguard Worker 			ah->wsi = NULL;
657*1c60b9acSAndroid Build Coastguard Worker 			pt->http.ah_count_in_use--;
658*1c60b9acSAndroid Build Coastguard Worker 			break;
659*1c60b9acSAndroid Build Coastguard Worker 		}
660*1c60b9acSAndroid Build Coastguard Worker 		ah = ah->next;
661*1c60b9acSAndroid Build Coastguard Worker 	}
662*1c60b9acSAndroid Build Coastguard Worker 
663*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
664*1c60b9acSAndroid Build Coastguard Worker 	lws_http_compression_destroy(wsi);
665*1c60b9acSAndroid Build Coastguard Worker #endif
666*1c60b9acSAndroid Build Coastguard Worker 
667*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->upgraded_to_http2 || wsi->mux_substream) {
668*1c60b9acSAndroid Build Coastguard Worker 		lws_hpack_destroy_dynamic_header(wsi);
669*1c60b9acSAndroid Build Coastguard Worker 
670*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->h2.h2n)
671*1c60b9acSAndroid Build Coastguard Worker 			lws_free_set_NULL(wsi->h2.h2n);
672*1c60b9acSAndroid Build Coastguard Worker 	}
673*1c60b9acSAndroid Build Coastguard Worker 
674*1c60b9acSAndroid Build Coastguard Worker 	return 0;
675*1c60b9acSAndroid Build Coastguard Worker }
676*1c60b9acSAndroid Build Coastguard Worker 
677*1c60b9acSAndroid Build Coastguard Worker static int
rops_close_kill_connection_h2(struct lws * wsi,enum lws_close_status reason)678*1c60b9acSAndroid Build Coastguard Worker rops_close_kill_connection_h2(struct lws *wsi, enum lws_close_status reason)
679*1c60b9acSAndroid Build Coastguard Worker {
680*1c60b9acSAndroid Build Coastguard Worker 
681*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_PROXY)
682*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->http.proxy_clientside) {
683*1c60b9acSAndroid Build Coastguard Worker 
684*1c60b9acSAndroid Build Coastguard Worker 		wsi->http.proxy_clientside = 0;
685*1c60b9acSAndroid Build Coastguard Worker 
686*1c60b9acSAndroid Build Coastguard Worker 		if (user_callback_handle_rxflow(wsi->a.protocol->callback,
687*1c60b9acSAndroid Build Coastguard Worker 						wsi,
688*1c60b9acSAndroid Build Coastguard Worker 					    LWS_CALLBACK_COMPLETED_CLIENT_HTTP,
689*1c60b9acSAndroid Build Coastguard Worker 						wsi->user_space, NULL, 0))
690*1c60b9acSAndroid Build Coastguard Worker 			wsi->http.proxy_clientside = 0;
691*1c60b9acSAndroid Build Coastguard Worker 	}
692*1c60b9acSAndroid Build Coastguard Worker #endif
693*1c60b9acSAndroid Build Coastguard Worker 
694*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->mux_substream && wsi->h2_stream_carries_ws)
695*1c60b9acSAndroid Build Coastguard Worker 		lws_h2_rst_stream(wsi, 0, "none");
696*1c60b9acSAndroid Build Coastguard Worker /*	else
697*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->mux_substream)
698*1c60b9acSAndroid Build Coastguard Worker 			lws_h2_rst_stream(wsi, H2_ERR_STREAM_CLOSED, "swsi got closed");
699*1c60b9acSAndroid Build Coastguard Worker */
700*1c60b9acSAndroid Build Coastguard Worker 
701*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info(" %s, his parent %s: siblings:\n", lws_wsi_tag(wsi), lws_wsi_tag(wsi->mux.parent_wsi));
702*1c60b9acSAndroid Build Coastguard Worker 	lws_wsi_mux_dump_children(wsi);
703*1c60b9acSAndroid Build Coastguard Worker 
704*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->upgraded_to_http2 || wsi->mux_substream
705*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
706*1c60b9acSAndroid Build Coastguard Worker 			|| wsi->client_mux_substream
707*1c60b9acSAndroid Build Coastguard Worker #endif
708*1c60b9acSAndroid Build Coastguard Worker 	) {
709*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("closing %s: parent %s\n", lws_wsi_tag(wsi),
710*1c60b9acSAndroid Build Coastguard Worker 				lws_wsi_tag(wsi->mux.parent_wsi));
711*1c60b9acSAndroid Build Coastguard Worker 
712*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->mux.child_list && lwsl_visible(LLL_INFO)) {
713*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info(" parent %s: closing children: list:\n", lws_wsi_tag(wsi));
714*1c60b9acSAndroid Build Coastguard Worker 			lws_wsi_mux_dump_children(wsi);
715*1c60b9acSAndroid Build Coastguard Worker 		}
716*1c60b9acSAndroid Build Coastguard Worker 		lws_wsi_mux_close_children(wsi, (int)reason);
717*1c60b9acSAndroid Build Coastguard Worker 	}
718*1c60b9acSAndroid Build Coastguard Worker 
719*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->upgraded_to_http2) {
720*1c60b9acSAndroid Build Coastguard Worker 		/* remove pps */
721*1c60b9acSAndroid Build Coastguard Worker 		struct lws_h2_protocol_send *w = wsi->h2.h2n->pps, *w1;
722*1c60b9acSAndroid Build Coastguard Worker 
723*1c60b9acSAndroid Build Coastguard Worker 		while (w) {
724*1c60b9acSAndroid Build Coastguard Worker 			w1 = w->next;
725*1c60b9acSAndroid Build Coastguard Worker 			free(w);
726*1c60b9acSAndroid Build Coastguard Worker 			w = w1;
727*1c60b9acSAndroid Build Coastguard Worker 		}
728*1c60b9acSAndroid Build Coastguard Worker 		wsi->h2.h2n->pps = NULL;
729*1c60b9acSAndroid Build Coastguard Worker 	}
730*1c60b9acSAndroid Build Coastguard Worker 
731*1c60b9acSAndroid Build Coastguard Worker 	if ((
732*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
733*1c60b9acSAndroid Build Coastguard Worker 			wsi->client_mux_substream ||
734*1c60b9acSAndroid Build Coastguard Worker #endif
735*1c60b9acSAndroid Build Coastguard Worker 			wsi->mux_substream) &&
736*1c60b9acSAndroid Build Coastguard Worker 	     wsi->mux.parent_wsi) {
737*1c60b9acSAndroid Build Coastguard Worker 		lws_wsi_mux_sibling_disconnect(wsi);
738*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->h2.pending_status_body)
739*1c60b9acSAndroid Build Coastguard Worker 			lws_free_set_NULL(wsi->h2.pending_status_body);
740*1c60b9acSAndroid Build Coastguard Worker 	}
741*1c60b9acSAndroid Build Coastguard Worker 
742*1c60b9acSAndroid Build Coastguard Worker 	return 0;
743*1c60b9acSAndroid Build Coastguard Worker }
744*1c60b9acSAndroid Build Coastguard Worker 
745*1c60b9acSAndroid Build Coastguard Worker static int
rops_callback_on_writable_h2(struct lws * wsi)746*1c60b9acSAndroid Build Coastguard Worker rops_callback_on_writable_h2(struct lws *wsi)
747*1c60b9acSAndroid Build Coastguard Worker {
748*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
749*1c60b9acSAndroid Build Coastguard Worker 	struct lws *network_wsi;
750*1c60b9acSAndroid Build Coastguard Worker #endif
751*1c60b9acSAndroid Build Coastguard Worker 	int already;
752*1c60b9acSAndroid Build Coastguard Worker 
753*1c60b9acSAndroid Build Coastguard Worker //	if (!lwsi_role_h2(wsi) && !lwsi_role_h2_ENCAPSULATION(wsi))
754*1c60b9acSAndroid Build Coastguard Worker //		return 0;
755*1c60b9acSAndroid Build Coastguard Worker 
756*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->mux.requested_POLLOUT
757*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
758*1c60b9acSAndroid Build Coastguard Worker 			&& !wsi->client_h2_alpn
759*1c60b9acSAndroid Build Coastguard Worker #endif
760*1c60b9acSAndroid Build Coastguard Worker 	) {
761*1c60b9acSAndroid Build Coastguard Worker 		lwsl_debug("already pending writable\n");
762*1c60b9acSAndroid Build Coastguard Worker 		// return 1;
763*1c60b9acSAndroid Build Coastguard Worker 	}
764*1c60b9acSAndroid Build Coastguard Worker 
765*1c60b9acSAndroid Build Coastguard Worker 	/* is this for DATA or for control messages? */
766*1c60b9acSAndroid Build Coastguard Worker 
767*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->upgraded_to_http2 && !wsi->h2.h2n->pps &&
768*1c60b9acSAndroid Build Coastguard Worker 	    lws_wsi_txc_check_skint(&wsi->txc, lws_h2_tx_cr_get(wsi))) {
769*1c60b9acSAndroid Build Coastguard Worker 		/*
770*1c60b9acSAndroid Build Coastguard Worker 		 * refuse his efforts to get WRITABLE if we have no credit and
771*1c60b9acSAndroid Build Coastguard Worker 		 * no non-DATA pps to send
772*1c60b9acSAndroid Build Coastguard Worker 		 */
773*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: skint\n", __func__);
774*1c60b9acSAndroid Build Coastguard Worker 		return 0;
775*1c60b9acSAndroid Build Coastguard Worker 	}
776*1c60b9acSAndroid Build Coastguard Worker 
777*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
778*1c60b9acSAndroid Build Coastguard Worker 	network_wsi = lws_get_network_wsi(wsi);
779*1c60b9acSAndroid Build Coastguard Worker #endif
780*1c60b9acSAndroid Build Coastguard Worker 	already = lws_wsi_mux_mark_parents_needing_writeable(wsi);
781*1c60b9acSAndroid Build Coastguard Worker 
782*1c60b9acSAndroid Build Coastguard Worker 	/* for network action, act only on the network wsi */
783*1c60b9acSAndroid Build Coastguard Worker 
784*1c60b9acSAndroid Build Coastguard Worker 	if (already
785*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
786*1c60b9acSAndroid Build Coastguard Worker 			&& !network_wsi->client_h2_alpn
787*1c60b9acSAndroid Build Coastguard Worker 			&& !network_wsi->client_mux_substream
788*1c60b9acSAndroid Build Coastguard Worker #endif
789*1c60b9acSAndroid Build Coastguard Worker 			)
790*1c60b9acSAndroid Build Coastguard Worker 		return 1;
791*1c60b9acSAndroid Build Coastguard Worker 
792*1c60b9acSAndroid Build Coastguard Worker 	return 0;
793*1c60b9acSAndroid Build Coastguard Worker }
794*1c60b9acSAndroid Build Coastguard Worker 
795*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SERVER)
796*1c60b9acSAndroid Build Coastguard Worker static int
lws_h2_bind_for_post_before_action(struct lws * wsi)797*1c60b9acSAndroid Build Coastguard Worker lws_h2_bind_for_post_before_action(struct lws *wsi)
798*1c60b9acSAndroid Build Coastguard Worker {
799*1c60b9acSAndroid Build Coastguard Worker 	const struct lws_http_mount *hit;
800*1c60b9acSAndroid Build Coastguard Worker 	char *uri_ptr = NULL;
801*1c60b9acSAndroid Build Coastguard Worker 	uint8_t *buffered;
802*1c60b9acSAndroid Build Coastguard Worker 	int uri_len = 0;
803*1c60b9acSAndroid Build Coastguard Worker 	const char *p;
804*1c60b9acSAndroid Build Coastguard Worker 	size_t blen;
805*1c60b9acSAndroid Build Coastguard Worker 
806*1c60b9acSAndroid Build Coastguard Worker 	p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_METHOD);
807*1c60b9acSAndroid Build Coastguard Worker 	if (!p || strcmp(p, "POST"))
808*1c60b9acSAndroid Build Coastguard Worker 		return 0;
809*1c60b9acSAndroid Build Coastguard Worker 
810*1c60b9acSAndroid Build Coastguard Worker 
811*1c60b9acSAndroid Build Coastguard Worker 	if (!lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COLON_PATH) ||
812*1c60b9acSAndroid Build Coastguard Worker 	    !lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_PATH))
813*1c60b9acSAndroid Build Coastguard Worker 		/*
814*1c60b9acSAndroid Build Coastguard Worker 		 * There must be a path.  Actually this is checked at
815*1c60b9acSAndroid Build Coastguard Worker 		 * http2.c along with the other required header
816*1c60b9acSAndroid Build Coastguard Worker 		 * presence before we can get here.
817*1c60b9acSAndroid Build Coastguard Worker 		 *
818*1c60b9acSAndroid Build Coastguard Worker 		 * But Coverity insists to see us check it.
819*1c60b9acSAndroid Build Coastguard Worker 		 */
820*1c60b9acSAndroid Build Coastguard Worker 		return 1;
821*1c60b9acSAndroid Build Coastguard Worker 
822*1c60b9acSAndroid Build Coastguard Worker 	hit = lws_find_mount(wsi,
823*1c60b9acSAndroid Build Coastguard Worker 		  lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_PATH),
824*1c60b9acSAndroid Build Coastguard Worker 		  lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COLON_PATH));
825*1c60b9acSAndroid Build Coastguard Worker 
826*1c60b9acSAndroid Build Coastguard Worker 	lwsl_debug("%s: %s: hit %p: %s\n", __func__,
827*1c60b9acSAndroid Build Coastguard Worker 		    lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_PATH),
828*1c60b9acSAndroid Build Coastguard Worker 		    hit, hit ? hit->origin : "null");
829*1c60b9acSAndroid Build Coastguard Worker 	if (hit) {
830*1c60b9acSAndroid Build Coastguard Worker 		const struct lws_protocols *pp;
831*1c60b9acSAndroid Build Coastguard Worker 		const char *name = hit->origin;
832*1c60b9acSAndroid Build Coastguard Worker 
833*1c60b9acSAndroid Build Coastguard Worker 		if (hit->origin_protocol == LWSMPRO_CGI ||
834*1c60b9acSAndroid Build Coastguard Worker 		    hit->origin_protocol == LWSMPRO_HTTP ||
835*1c60b9acSAndroid Build Coastguard Worker 		    hit->origin_protocol == LWSMPRO_HTTPS)
836*1c60b9acSAndroid Build Coastguard Worker 			return 0;
837*1c60b9acSAndroid Build Coastguard Worker 
838*1c60b9acSAndroid Build Coastguard Worker 		if (hit->protocol)
839*1c60b9acSAndroid Build Coastguard Worker 			name = hit->protocol;
840*1c60b9acSAndroid Build Coastguard Worker 		else
841*1c60b9acSAndroid Build Coastguard Worker 			if (hit->origin_protocol == LWSMPRO_FILE)
842*1c60b9acSAndroid Build Coastguard Worker 				return 0;
843*1c60b9acSAndroid Build Coastguard Worker 
844*1c60b9acSAndroid Build Coastguard Worker 		pp = lws_vhost_name_to_protocol(wsi->a.vhost, name);
845*1c60b9acSAndroid Build Coastguard Worker 		if (!pp) {
846*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("Unable to find protocol '%s'\n", name);
847*1c60b9acSAndroid Build Coastguard Worker 			return 1;
848*1c60b9acSAndroid Build Coastguard Worker 		}
849*1c60b9acSAndroid Build Coastguard Worker 
850*1c60b9acSAndroid Build Coastguard Worker 		if (lws_bind_protocol(wsi, pp, __func__))
851*1c60b9acSAndroid Build Coastguard Worker 			return 1;
852*1c60b9acSAndroid Build Coastguard Worker 	}
853*1c60b9acSAndroid Build Coastguard Worker 	if (lws_http_get_uri_and_method(wsi, &uri_ptr, &uri_len) >= 0)
854*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->a.protocol->callback(wsi, LWS_CALLBACK_HTTP,
855*1c60b9acSAndroid Build Coastguard Worker 					      wsi->user_space,
856*1c60b9acSAndroid Build Coastguard Worker 					      hit ? uri_ptr +
857*1c60b9acSAndroid Build Coastguard Worker 						  hit->mountpoint_len : uri_ptr,
858*1c60b9acSAndroid Build Coastguard Worker 					      (size_t)(hit ? uri_len -
859*1c60b9acSAndroid Build Coastguard Worker 							  hit->mountpoint_len :
860*1c60b9acSAndroid Build Coastguard Worker 							  uri_len)))
861*1c60b9acSAndroid Build Coastguard Worker 			return 1;
862*1c60b9acSAndroid Build Coastguard Worker 
863*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("%s: setting LRS_BODY from 0x%x (%s)\n", __func__,
864*1c60b9acSAndroid Build Coastguard Worker 		    (int)wsi->wsistate, wsi->a.protocol->name);
865*1c60b9acSAndroid Build Coastguard Worker 
866*1c60b9acSAndroid Build Coastguard Worker 	lwsi_set_state(wsi, LRS_BODY);
867*1c60b9acSAndroid Build Coastguard Worker 
868*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->http.content_length_explicitly_zero)
869*1c60b9acSAndroid Build Coastguard Worker 		return 0;
870*1c60b9acSAndroid Build Coastguard Worker 
871*1c60b9acSAndroid Build Coastguard Worker 	/*
872*1c60b9acSAndroid Build Coastguard Worker 	 * Dump any stashed body
873*1c60b9acSAndroid Build Coastguard Worker 	 */
874*1c60b9acSAndroid Build Coastguard Worker 
875*1c60b9acSAndroid Build Coastguard Worker 	while (((!wsi->http.content_length_given) ||
876*1c60b9acSAndroid Build Coastguard Worker 		  wsi->http.rx_content_length) &&
877*1c60b9acSAndroid Build Coastguard Worker 	       (blen = lws_buflist_next_segment_len(&wsi->buflist, &buffered))) {
878*1c60b9acSAndroid Build Coastguard Worker 
879*1c60b9acSAndroid Build Coastguard Worker 		if ((size_t)wsi->http.rx_content_length < blen)
880*1c60b9acSAndroid Build Coastguard Worker 			blen = (size_t)wsi->http.rx_content_length;
881*1c60b9acSAndroid Build Coastguard Worker 
882*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->a.protocol->callback(wsi, LWS_CALLBACK_HTTP_BODY,
883*1c60b9acSAndroid Build Coastguard Worker 				wsi->user_space, buffered, blen))
884*1c60b9acSAndroid Build Coastguard Worker 			return 1;
885*1c60b9acSAndroid Build Coastguard Worker 		lws_buflist_use_segment(&wsi->buflist, blen);
886*1c60b9acSAndroid Build Coastguard Worker 
887*1c60b9acSAndroid Build Coastguard Worker 		wsi->http.rx_content_length -= blen;
888*1c60b9acSAndroid Build Coastguard Worker 	}
889*1c60b9acSAndroid Build Coastguard Worker 
890*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi->buflist)
891*1c60b9acSAndroid Build Coastguard Worker 		/* Take us off the pt's "wsi holding input buflist" list */
892*1c60b9acSAndroid Build Coastguard Worker 		lws_dll2_remove(&wsi->dll_buflist);
893*1c60b9acSAndroid Build Coastguard Worker 
894*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->http.content_length_given && wsi->http.rx_content_length)
895*1c60b9acSAndroid Build Coastguard Worker 		/* still a-ways to go */
896*1c60b9acSAndroid Build Coastguard Worker 		return 0;
897*1c60b9acSAndroid Build Coastguard Worker 
898*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi->http.content_length_given && !wsi->h2.END_STREAM)
899*1c60b9acSAndroid Build Coastguard Worker 		return 0;
900*1c60b9acSAndroid Build Coastguard Worker 
901*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->a.protocol->callback(wsi, LWS_CALLBACK_HTTP_BODY_COMPLETION,
902*1c60b9acSAndroid Build Coastguard Worker 				      wsi->user_space, NULL, 0))
903*1c60b9acSAndroid Build Coastguard Worker 		return 1;
904*1c60b9acSAndroid Build Coastguard Worker 
905*1c60b9acSAndroid Build Coastguard Worker 	return 0;
906*1c60b9acSAndroid Build Coastguard Worker }
907*1c60b9acSAndroid Build Coastguard Worker #endif
908*1c60b9acSAndroid Build Coastguard Worker 
909*1c60b9acSAndroid Build Coastguard Worker /*
910*1c60b9acSAndroid Build Coastguard Worker  * we are the 'network wsi' for potentially many muxed child wsi with
911*1c60b9acSAndroid Build Coastguard Worker  * no network connection of their own, who have to use us for all their
912*1c60b9acSAndroid Build Coastguard Worker  * network actions.  So we use a round-robin scheme to share out the
913*1c60b9acSAndroid Build Coastguard Worker  * POLLOUT notifications to our children.
914*1c60b9acSAndroid Build Coastguard Worker  *
915*1c60b9acSAndroid Build Coastguard Worker  * But because any child could exhaust the socket's ability to take
916*1c60b9acSAndroid Build Coastguard Worker  * writes, we can only let one child get notified each time.
917*1c60b9acSAndroid Build Coastguard Worker  *
918*1c60b9acSAndroid Build Coastguard Worker  * In addition children may be closed / deleted / added between POLLOUT
919*1c60b9acSAndroid Build Coastguard Worker  * notifications, so we can't hold pointers
920*1c60b9acSAndroid Build Coastguard Worker  */
921*1c60b9acSAndroid Build Coastguard Worker 
922*1c60b9acSAndroid Build Coastguard Worker static int
rops_perform_user_POLLOUT_h2(struct lws * wsi)923*1c60b9acSAndroid Build Coastguard Worker rops_perform_user_POLLOUT_h2(struct lws *wsi)
924*1c60b9acSAndroid Build Coastguard Worker {
925*1c60b9acSAndroid Build Coastguard Worker 	struct lws **wsi2;
926*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_ROLE_WS)
927*1c60b9acSAndroid Build Coastguard Worker 	int write_type = LWS_WRITE_PONG;
928*1c60b9acSAndroid Build Coastguard Worker #endif
929*1c60b9acSAndroid Build Coastguard Worker 	int n;
930*1c60b9acSAndroid Build Coastguard Worker 
931*1c60b9acSAndroid Build Coastguard Worker 	wsi = lws_get_network_wsi(wsi);
932*1c60b9acSAndroid Build Coastguard Worker 
933*1c60b9acSAndroid Build Coastguard Worker 	wsi->mux.requested_POLLOUT = 0;
934*1c60b9acSAndroid Build Coastguard Worker //	if (!wsi->h2.initialized) {
935*1c60b9acSAndroid Build Coastguard Worker //		lwsl_info("pollout on uninitialized http2 conn\n");
936*1c60b9acSAndroid Build Coastguard Worker //		return 0;
937*1c60b9acSAndroid Build Coastguard Worker //	}
938*1c60b9acSAndroid Build Coastguard Worker 
939*1c60b9acSAndroid Build Coastguard Worker 	lws_wsi_mux_dump_waiting_children(wsi);
940*1c60b9acSAndroid Build Coastguard Worker 
941*1c60b9acSAndroid Build Coastguard Worker 	wsi2 = &wsi->mux.child_list;
942*1c60b9acSAndroid Build Coastguard Worker 	if (!*wsi2)
943*1c60b9acSAndroid Build Coastguard Worker 		return 0;
944*1c60b9acSAndroid Build Coastguard Worker 
945*1c60b9acSAndroid Build Coastguard Worker 	do {
946*1c60b9acSAndroid Build Coastguard Worker 		struct lws *w, **wa;
947*1c60b9acSAndroid Build Coastguard Worker 
948*1c60b9acSAndroid Build Coastguard Worker 		wa = &(*wsi2)->mux.sibling_list;
949*1c60b9acSAndroid Build Coastguard Worker 		if (!(*wsi2)->mux.requested_POLLOUT)
950*1c60b9acSAndroid Build Coastguard Worker 			goto next_child;
951*1c60b9acSAndroid Build Coastguard Worker 
952*1c60b9acSAndroid Build Coastguard Worker 		/*
953*1c60b9acSAndroid Build Coastguard Worker 		 * we're going to do writable callback for this child.
954*1c60b9acSAndroid Build Coastguard Worker 		 * move him to be the last child
955*1c60b9acSAndroid Build Coastguard Worker 		 */
956*1c60b9acSAndroid Build Coastguard Worker 
957*1c60b9acSAndroid Build Coastguard Worker 		lwsl_debug("servicing child %s\n", lws_wsi_tag(*wsi2));
958*1c60b9acSAndroid Build Coastguard Worker 
959*1c60b9acSAndroid Build Coastguard Worker 		w = lws_wsi_mux_move_child_to_tail(wsi2);
960*1c60b9acSAndroid Build Coastguard Worker 
961*1c60b9acSAndroid Build Coastguard Worker 		if (!w) {
962*1c60b9acSAndroid Build Coastguard Worker 			wa = &wsi->mux.child_list;
963*1c60b9acSAndroid Build Coastguard Worker 			goto next_child;
964*1c60b9acSAndroid Build Coastguard Worker 		}
965*1c60b9acSAndroid Build Coastguard Worker 
966*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: child %s, sid %d, (wsistate 0x%x)\n",
967*1c60b9acSAndroid Build Coastguard Worker 			  __func__, lws_wsi_tag(w), w->mux.my_sid,
968*1c60b9acSAndroid Build Coastguard Worker 			  (unsigned int)w->wsistate);
969*1c60b9acSAndroid Build Coastguard Worker 
970*1c60b9acSAndroid Build Coastguard Worker 		/* priority 1: post compression-transform buffered output */
971*1c60b9acSAndroid Build Coastguard Worker 
972*1c60b9acSAndroid Build Coastguard Worker 		if (lws_has_buffered_out(w)) {
973*1c60b9acSAndroid Build Coastguard Worker 			lwsl_debug("%s: completing partial\n", __func__);
974*1c60b9acSAndroid Build Coastguard Worker 			if (lws_issue_raw(w, NULL, 0) < 0) {
975*1c60b9acSAndroid Build Coastguard Worker 				lwsl_info("%s signalling to close\n", __func__);
976*1c60b9acSAndroid Build Coastguard Worker 				lws_close_free_wsi(w, LWS_CLOSE_STATUS_NOSTATUS,
977*1c60b9acSAndroid Build Coastguard Worker 						   "h2 end stream 1");
978*1c60b9acSAndroid Build Coastguard Worker 				wa = &wsi->mux.child_list;
979*1c60b9acSAndroid Build Coastguard Worker 				goto next_child;
980*1c60b9acSAndroid Build Coastguard Worker 			}
981*1c60b9acSAndroid Build Coastguard Worker 			lws_callback_on_writable(w);
982*1c60b9acSAndroid Build Coastguard Worker 			wa = &wsi->mux.child_list;
983*1c60b9acSAndroid Build Coastguard Worker 			goto next_child;
984*1c60b9acSAndroid Build Coastguard Worker 		}
985*1c60b9acSAndroid Build Coastguard Worker 
986*1c60b9acSAndroid Build Coastguard Worker 		/* priority 2: pre compression-transform buffered output */
987*1c60b9acSAndroid Build Coastguard Worker 
988*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
989*1c60b9acSAndroid Build Coastguard Worker 		if (w->http.comp_ctx.buflist_comp ||
990*1c60b9acSAndroid Build Coastguard Worker 		    w->http.comp_ctx.may_have_more) {
991*1c60b9acSAndroid Build Coastguard Worker 			enum lws_write_protocol wp = LWS_WRITE_HTTP;
992*1c60b9acSAndroid Build Coastguard Worker 
993*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("%s: completing comp partial"
994*1c60b9acSAndroid Build Coastguard Worker 				   "(buflist_comp %p, may %d)\n",
995*1c60b9acSAndroid Build Coastguard Worker 				   __func__, w->http.comp_ctx.buflist_comp,
996*1c60b9acSAndroid Build Coastguard Worker 				    w->http.comp_ctx.may_have_more);
997*1c60b9acSAndroid Build Coastguard Worker 
998*1c60b9acSAndroid Build Coastguard Worker 			if (rops_write_role_protocol_h2(w, NULL, 0, &wp) < 0) {
999*1c60b9acSAndroid Build Coastguard Worker 				lwsl_info("%s signalling to close\n", __func__);
1000*1c60b9acSAndroid Build Coastguard Worker 				lws_close_free_wsi(w, LWS_CLOSE_STATUS_NOSTATUS,
1001*1c60b9acSAndroid Build Coastguard Worker 						   "comp write fail");
1002*1c60b9acSAndroid Build Coastguard Worker 			}
1003*1c60b9acSAndroid Build Coastguard Worker 			lws_callback_on_writable(w);
1004*1c60b9acSAndroid Build Coastguard Worker 			wa = &wsi->mux.child_list;
1005*1c60b9acSAndroid Build Coastguard Worker 			goto next_child;
1006*1c60b9acSAndroid Build Coastguard Worker 		}
1007*1c60b9acSAndroid Build Coastguard Worker #endif
1008*1c60b9acSAndroid Build Coastguard Worker 
1009*1c60b9acSAndroid Build Coastguard Worker 		/* priority 3: if no buffered out and waiting for that... */
1010*1c60b9acSAndroid Build Coastguard Worker 
1011*1c60b9acSAndroid Build Coastguard Worker 		if (lwsi_state(w) == LRS_FLUSHING_BEFORE_CLOSE) {
1012*1c60b9acSAndroid Build Coastguard Worker 			w->socket_is_permanently_unusable = 1;
1013*1c60b9acSAndroid Build Coastguard Worker 			lws_close_free_wsi(w, LWS_CLOSE_STATUS_NOSTATUS,
1014*1c60b9acSAndroid Build Coastguard Worker 					   "h2 end stream 1");
1015*1c60b9acSAndroid Build Coastguard Worker 			wa = &wsi->mux.child_list;
1016*1c60b9acSAndroid Build Coastguard Worker 			goto next_child;
1017*1c60b9acSAndroid Build Coastguard Worker 		}
1018*1c60b9acSAndroid Build Coastguard Worker 
1019*1c60b9acSAndroid Build Coastguard Worker 		/* if we arrived here, even by looping, we checked choked */
1020*1c60b9acSAndroid Build Coastguard Worker 		w->could_have_pending = 0;
1021*1c60b9acSAndroid Build Coastguard Worker 		wsi->could_have_pending = 0;
1022*1c60b9acSAndroid Build Coastguard Worker 
1023*1c60b9acSAndroid Build Coastguard Worker 		if (w->h2.pending_status_body) {
1024*1c60b9acSAndroid Build Coastguard Worker 			w->h2.send_END_STREAM = 1;
1025*1c60b9acSAndroid Build Coastguard Worker 			n = lws_write(w, (uint8_t *)w->h2.pending_status_body +
1026*1c60b9acSAndroid Build Coastguard Worker 					 LWS_PRE,
1027*1c60b9acSAndroid Build Coastguard Worker 				         strlen(w->h2.pending_status_body +
1028*1c60b9acSAndroid Build Coastguard Worker 					        LWS_PRE), LWS_WRITE_HTTP_FINAL);
1029*1c60b9acSAndroid Build Coastguard Worker 			lws_free_set_NULL(w->h2.pending_status_body);
1030*1c60b9acSAndroid Build Coastguard Worker 			lws_close_free_wsi(w, LWS_CLOSE_STATUS_NOSTATUS,
1031*1c60b9acSAndroid Build Coastguard Worker 					   "h2 end stream 1");
1032*1c60b9acSAndroid Build Coastguard Worker 			wa = &wsi->mux.child_list;
1033*1c60b9acSAndroid Build Coastguard Worker 			goto next_child;
1034*1c60b9acSAndroid Build Coastguard Worker 		}
1035*1c60b9acSAndroid Build Coastguard Worker 
1036*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
1037*1c60b9acSAndroid Build Coastguard Worker 		if (lwsi_state(w) == LRS_H2_WAITING_TO_SEND_HEADERS) {
1038*1c60b9acSAndroid Build Coastguard Worker 			if (lws_h2_client_handshake(w))
1039*1c60b9acSAndroid Build Coastguard Worker 				return -1;
1040*1c60b9acSAndroid Build Coastguard Worker 
1041*1c60b9acSAndroid Build Coastguard Worker 			goto next_child;
1042*1c60b9acSAndroid Build Coastguard Worker 		}
1043*1c60b9acSAndroid Build Coastguard Worker #endif
1044*1c60b9acSAndroid Build Coastguard Worker 
1045*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SERVER)
1046*1c60b9acSAndroid Build Coastguard Worker 		if (lwsi_state(w) == LRS_DEFERRING_ACTION) {
1047*1c60b9acSAndroid Build Coastguard Worker 
1048*1c60b9acSAndroid Build Coastguard Worker 			/*
1049*1c60b9acSAndroid Build Coastguard Worker 			 * we had to defer the http_action to the POLLOUT
1050*1c60b9acSAndroid Build Coastguard Worker 			 * handler, because we know it will send something and
1051*1c60b9acSAndroid Build Coastguard Worker 			 * only in the POLLOUT handler do we know for sure
1052*1c60b9acSAndroid Build Coastguard Worker 			 * that there is no partial pending on the network wsi.
1053*1c60b9acSAndroid Build Coastguard Worker 			 */
1054*1c60b9acSAndroid Build Coastguard Worker 
1055*1c60b9acSAndroid Build Coastguard Worker 			lwsi_set_state(w, LRS_ESTABLISHED);
1056*1c60b9acSAndroid Build Coastguard Worker 
1057*1c60b9acSAndroid Build Coastguard Worker 			if (w->buflist) {
1058*1c60b9acSAndroid Build Coastguard Worker 				struct lws_context_per_thread *pt;
1059*1c60b9acSAndroid Build Coastguard Worker 
1060*1c60b9acSAndroid Build Coastguard Worker 				pt = &w->a.context->pt[(int)w->tsi];
1061*1c60b9acSAndroid Build Coastguard Worker 				lwsl_debug("%s: added %s to rxflow list\n",
1062*1c60b9acSAndroid Build Coastguard Worker 					   __func__, lws_wsi_tag(w));
1063*1c60b9acSAndroid Build Coastguard Worker 				lws_dll2_add_head(
1064*1c60b9acSAndroid Build Coastguard Worker 					&w->dll_buflist,
1065*1c60b9acSAndroid Build Coastguard Worker 					&pt->dll_buflist_owner);
1066*1c60b9acSAndroid Build Coastguard Worker 			}
1067*1c60b9acSAndroid Build Coastguard Worker 
1068*1c60b9acSAndroid Build Coastguard Worker 			if (lws_h2_bind_for_post_before_action(w))
1069*1c60b9acSAndroid Build Coastguard Worker 				return -1;
1070*1c60b9acSAndroid Build Coastguard Worker 
1071*1c60b9acSAndroid Build Coastguard Worker 			/*
1072*1c60b9acSAndroid Build Coastguard Worker 			 * Well, we could be getting a POST from the client, it
1073*1c60b9acSAndroid Build Coastguard Worker 			 * may not have any content-length.  In that case, we
1074*1c60b9acSAndroid Build Coastguard Worker 			 * will be in LRS_BODY state, we can't actually start
1075*1c60b9acSAndroid Build Coastguard Worker 			 * the action until we had the body and the stream is
1076*1c60b9acSAndroid Build Coastguard Worker 			 * half-closed, indicating that we can reply
1077*1c60b9acSAndroid Build Coastguard Worker 			 */
1078*1c60b9acSAndroid Build Coastguard Worker 
1079*1c60b9acSAndroid Build Coastguard Worker 			if (lwsi_state(w) == LRS_BODY &&
1080*1c60b9acSAndroid Build Coastguard Worker 			    w->h2.h2_state != LWS_H2_STATE_HALF_CLOSED_REMOTE)
1081*1c60b9acSAndroid Build Coastguard Worker 				goto next_child;
1082*1c60b9acSAndroid Build Coastguard Worker 
1083*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("  h2 action start...\n");
1084*1c60b9acSAndroid Build Coastguard Worker 			n = lws_http_action(w);
1085*1c60b9acSAndroid Build Coastguard Worker 			if (n < 0)
1086*1c60b9acSAndroid Build Coastguard Worker 				lwsl_info ("   h2 action result %d\n", n);
1087*1c60b9acSAndroid Build Coastguard Worker 			else
1088*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("  h2 action result %d "
1089*1c60b9acSAndroid Build Coastguard Worker 				  "(wsi->http.rx_content_remain %lld)\n",
1090*1c60b9acSAndroid Build Coastguard Worker 				  n, w->http.rx_content_remain);
1091*1c60b9acSAndroid Build Coastguard Worker 
1092*1c60b9acSAndroid Build Coastguard Worker 			/*
1093*1c60b9acSAndroid Build Coastguard Worker 			 * Commonly we only managed to start a larger transfer
1094*1c60b9acSAndroid Build Coastguard Worker 			 * that will complete asynchronously under its own wsi
1095*1c60b9acSAndroid Build Coastguard Worker 			 * states.  In those cases we will hear about
1096*1c60b9acSAndroid Build Coastguard Worker 			 * END_STREAM going out in the POLLOUT handler.
1097*1c60b9acSAndroid Build Coastguard Worker 			 */
1098*1c60b9acSAndroid Build Coastguard Worker 			if (n >= 0 && !w->h2.pending_status_body &&
1099*1c60b9acSAndroid Build Coastguard Worker 			    (n || w->h2.send_END_STREAM)) {
1100*1c60b9acSAndroid Build Coastguard Worker 				lwsl_info("closing stream after h2 action\n");
1101*1c60b9acSAndroid Build Coastguard Worker 				lws_close_free_wsi(w, LWS_CLOSE_STATUS_NOSTATUS,
1102*1c60b9acSAndroid Build Coastguard Worker 						   "h2 end stream");
1103*1c60b9acSAndroid Build Coastguard Worker 				wa = &wsi->mux.child_list;
1104*1c60b9acSAndroid Build Coastguard Worker 			}
1105*1c60b9acSAndroid Build Coastguard Worker 
1106*1c60b9acSAndroid Build Coastguard Worker 			if (n < 0)
1107*1c60b9acSAndroid Build Coastguard Worker 				wa = &wsi->mux.child_list;
1108*1c60b9acSAndroid Build Coastguard Worker 
1109*1c60b9acSAndroid Build Coastguard Worker 			goto next_child;
1110*1c60b9acSAndroid Build Coastguard Worker 		}
1111*1c60b9acSAndroid Build Coastguard Worker 
1112*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_FILE_OPS)
1113*1c60b9acSAndroid Build Coastguard Worker 
1114*1c60b9acSAndroid Build Coastguard Worker 		if (lwsi_state(w) == LRS_ISSUING_FILE) {
1115*1c60b9acSAndroid Build Coastguard Worker 
1116*1c60b9acSAndroid Build Coastguard Worker 			if (lws_wsi_txc_check_skint(&w->txc,
1117*1c60b9acSAndroid Build Coastguard Worker 						    lws_h2_tx_cr_get(w))) {
1118*1c60b9acSAndroid Build Coastguard Worker 				wa = &wsi->mux.child_list;
1119*1c60b9acSAndroid Build Coastguard Worker 				goto next_child;
1120*1c60b9acSAndroid Build Coastguard Worker 			}
1121*1c60b9acSAndroid Build Coastguard Worker 
1122*1c60b9acSAndroid Build Coastguard Worker 			((volatile struct lws *)w)->leave_pollout_active = 0;
1123*1c60b9acSAndroid Build Coastguard Worker 
1124*1c60b9acSAndroid Build Coastguard Worker 			/* >0 == completion, <0 == error
1125*1c60b9acSAndroid Build Coastguard Worker 			 *
1126*1c60b9acSAndroid Build Coastguard Worker 			 * We'll get a LWS_CALLBACK_HTTP_FILE_COMPLETION
1127*1c60b9acSAndroid Build Coastguard Worker 			 * callback when it's done.  That's the case even if we
1128*1c60b9acSAndroid Build Coastguard Worker 			 * just completed the send, so wait for that.
1129*1c60b9acSAndroid Build Coastguard Worker 			 */
1130*1c60b9acSAndroid Build Coastguard Worker 			n = lws_serve_http_file_fragment(w);
1131*1c60b9acSAndroid Build Coastguard Worker 			lwsl_debug("lws_serve_http_file_fragment says %d\n", n);
1132*1c60b9acSAndroid Build Coastguard Worker 
1133*1c60b9acSAndroid Build Coastguard Worker 			/*
1134*1c60b9acSAndroid Build Coastguard Worker 			 * We will often hear about out having sent the final
1135*1c60b9acSAndroid Build Coastguard Worker 			 * DATA here... if so close the actual wsi
1136*1c60b9acSAndroid Build Coastguard Worker 			 */
1137*1c60b9acSAndroid Build Coastguard Worker 			if (n < 0 || w->h2.send_END_STREAM) {
1138*1c60b9acSAndroid Build Coastguard Worker 				lwsl_debug("Closing POLLOUT child %s\n",
1139*1c60b9acSAndroid Build Coastguard Worker 						lws_wsi_tag(w));
1140*1c60b9acSAndroid Build Coastguard Worker 				lws_close_free_wsi(w, LWS_CLOSE_STATUS_NOSTATUS,
1141*1c60b9acSAndroid Build Coastguard Worker 						   "h2 end stream file");
1142*1c60b9acSAndroid Build Coastguard Worker 				wa = &wsi->mux.child_list;
1143*1c60b9acSAndroid Build Coastguard Worker 				goto next_child;
1144*1c60b9acSAndroid Build Coastguard Worker 			}
1145*1c60b9acSAndroid Build Coastguard Worker 			if (n > 0)
1146*1c60b9acSAndroid Build Coastguard Worker 				if (lws_http_transaction_completed(w))
1147*1c60b9acSAndroid Build Coastguard Worker 					return -1;
1148*1c60b9acSAndroid Build Coastguard Worker 			if (!n) {
1149*1c60b9acSAndroid Build Coastguard Worker 				lws_callback_on_writable(w);
1150*1c60b9acSAndroid Build Coastguard Worker 				(w)->mux.requested_POLLOUT = 1;
1151*1c60b9acSAndroid Build Coastguard Worker 			}
1152*1c60b9acSAndroid Build Coastguard Worker 
1153*1c60b9acSAndroid Build Coastguard Worker 			goto next_child;
1154*1c60b9acSAndroid Build Coastguard Worker 		}
1155*1c60b9acSAndroid Build Coastguard Worker #endif
1156*1c60b9acSAndroid Build Coastguard Worker #endif
1157*1c60b9acSAndroid Build Coastguard Worker 
1158*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_ROLE_WS)
1159*1c60b9acSAndroid Build Coastguard Worker 
1160*1c60b9acSAndroid Build Coastguard Worker 		/* Notify peer that we decided to close */
1161*1c60b9acSAndroid Build Coastguard Worker 
1162*1c60b9acSAndroid Build Coastguard Worker 		if (lwsi_role_ws(w) &&
1163*1c60b9acSAndroid Build Coastguard Worker 		    lwsi_state(w) == LRS_WAITING_TO_SEND_CLOSE) {
1164*1c60b9acSAndroid Build Coastguard Worker 			lwsl_debug("sending close packet\n");
1165*1c60b9acSAndroid Build Coastguard Worker 			w->waiting_to_send_close_frame = 0;
1166*1c60b9acSAndroid Build Coastguard Worker 			n = lws_write(w, &w->ws->ping_payload_buf[LWS_PRE],
1167*1c60b9acSAndroid Build Coastguard Worker 				      w->ws->close_in_ping_buffer_len,
1168*1c60b9acSAndroid Build Coastguard Worker 				      LWS_WRITE_CLOSE);
1169*1c60b9acSAndroid Build Coastguard Worker 			if (n >= 0) {
1170*1c60b9acSAndroid Build Coastguard Worker 				lwsi_set_state(w, LRS_AWAITING_CLOSE_ACK);
1171*1c60b9acSAndroid Build Coastguard Worker 				lws_set_timeout(w, PENDING_TIMEOUT_CLOSE_ACK, 5);
1172*1c60b9acSAndroid Build Coastguard Worker 				lwsl_debug("sent close frame, awaiting ack\n");
1173*1c60b9acSAndroid Build Coastguard Worker 			}
1174*1c60b9acSAndroid Build Coastguard Worker 
1175*1c60b9acSAndroid Build Coastguard Worker 			goto next_child;
1176*1c60b9acSAndroid Build Coastguard Worker 		}
1177*1c60b9acSAndroid Build Coastguard Worker 
1178*1c60b9acSAndroid Build Coastguard Worker 		/*
1179*1c60b9acSAndroid Build Coastguard Worker 		 * Acknowledge receipt of peer's notification he closed,
1180*1c60b9acSAndroid Build Coastguard Worker 		 * then logically close ourself
1181*1c60b9acSAndroid Build Coastguard Worker 		 */
1182*1c60b9acSAndroid Build Coastguard Worker 
1183*1c60b9acSAndroid Build Coastguard Worker 		if ((lwsi_role_ws(w) && w->ws->pong_pending_flag) ||
1184*1c60b9acSAndroid Build Coastguard Worker 		    (lwsi_state(w) == LRS_RETURNED_CLOSE &&
1185*1c60b9acSAndroid Build Coastguard Worker 		     w->ws->payload_is_close)) {
1186*1c60b9acSAndroid Build Coastguard Worker 
1187*1c60b9acSAndroid Build Coastguard Worker 			if (w->ws->payload_is_close)
1188*1c60b9acSAndroid Build Coastguard Worker 				write_type = LWS_WRITE_CLOSE |
1189*1c60b9acSAndroid Build Coastguard Worker 					     LWS_WRITE_H2_STREAM_END;
1190*1c60b9acSAndroid Build Coastguard Worker 
1191*1c60b9acSAndroid Build Coastguard Worker 			n = lws_write(w, &w->ws->pong_payload_buf[LWS_PRE],
1192*1c60b9acSAndroid Build Coastguard Worker 				      w->ws->pong_payload_len, (enum lws_write_protocol)write_type);
1193*1c60b9acSAndroid Build Coastguard Worker 			if (n < 0)
1194*1c60b9acSAndroid Build Coastguard Worker 				return -1;
1195*1c60b9acSAndroid Build Coastguard Worker 
1196*1c60b9acSAndroid Build Coastguard Worker 			/* well he is sent, mark him done */
1197*1c60b9acSAndroid Build Coastguard Worker 			w->ws->pong_pending_flag = 0;
1198*1c60b9acSAndroid Build Coastguard Worker 			if (w->ws->payload_is_close) {
1199*1c60b9acSAndroid Build Coastguard Worker 				/* oh... a close frame... then we are done */
1200*1c60b9acSAndroid Build Coastguard Worker 				lwsl_debug("Ack'd peer's close packet\n");
1201*1c60b9acSAndroid Build Coastguard Worker 				w->ws->payload_is_close = 0;
1202*1c60b9acSAndroid Build Coastguard Worker 				lwsi_set_state(w, LRS_RETURNED_CLOSE);
1203*1c60b9acSAndroid Build Coastguard Worker 				lws_close_free_wsi(w, LWS_CLOSE_STATUS_NOSTATUS,
1204*1c60b9acSAndroid Build Coastguard Worker 						   "returned close packet");
1205*1c60b9acSAndroid Build Coastguard Worker 				wa = &wsi->mux.child_list;
1206*1c60b9acSAndroid Build Coastguard Worker 				goto next_child;
1207*1c60b9acSAndroid Build Coastguard Worker 			}
1208*1c60b9acSAndroid Build Coastguard Worker 
1209*1c60b9acSAndroid Build Coastguard Worker 			lws_callback_on_writable(w);
1210*1c60b9acSAndroid Build Coastguard Worker 			(w)->mux.requested_POLLOUT = 1;
1211*1c60b9acSAndroid Build Coastguard Worker 
1212*1c60b9acSAndroid Build Coastguard Worker 			/* otherwise for PING, leave POLLOUT active both ways */
1213*1c60b9acSAndroid Build Coastguard Worker 			goto next_child;
1214*1c60b9acSAndroid Build Coastguard Worker 		}
1215*1c60b9acSAndroid Build Coastguard Worker #endif
1216*1c60b9acSAndroid Build Coastguard Worker 
1217*1c60b9acSAndroid Build Coastguard Worker 		/*
1218*1c60b9acSAndroid Build Coastguard Worker 		 * set client wsi to immortal long-poll mode; send END_STREAM
1219*1c60b9acSAndroid Build Coastguard Worker 		 * flag on headers to indicate to a server, that allows
1220*1c60b9acSAndroid Build Coastguard Worker 		 * it, that you want them to leave the stream in a long poll
1221*1c60b9acSAndroid Build Coastguard Worker 		 * ro immortal state.  We have to send headers so the client
1222*1c60b9acSAndroid Build Coastguard Worker 		 * understands the http connection is ongoing.
1223*1c60b9acSAndroid Build Coastguard Worker 		 */
1224*1c60b9acSAndroid Build Coastguard Worker 
1225*1c60b9acSAndroid Build Coastguard Worker 		if (w->h2.send_END_STREAM && w->h2.long_poll) {
1226*1c60b9acSAndroid Build Coastguard Worker 			uint8_t buf[LWS_PRE + 1];
1227*1c60b9acSAndroid Build Coastguard Worker 			enum lws_write_protocol wp = 0;
1228*1c60b9acSAndroid Build Coastguard Worker 
1229*1c60b9acSAndroid Build Coastguard Worker 			if (!rops_write_role_protocol_h2(w, buf + LWS_PRE, 0,
1230*1c60b9acSAndroid Build Coastguard Worker 							 &wp)) {
1231*1c60b9acSAndroid Build Coastguard Worker 				lwsl_info("%s: %s: entering ro long poll\n",
1232*1c60b9acSAndroid Build Coastguard Worker 					  __func__, lws_wsi_tag(w));
1233*1c60b9acSAndroid Build Coastguard Worker 				lws_mux_mark_immortal(w);
1234*1c60b9acSAndroid Build Coastguard Worker 			} else
1235*1c60b9acSAndroid Build Coastguard Worker 				lwsl_err("%s: %s: failed to set long poll\n",
1236*1c60b9acSAndroid Build Coastguard Worker 						__func__, lws_wsi_tag(w));
1237*1c60b9acSAndroid Build Coastguard Worker 			goto next_child;
1238*1c60b9acSAndroid Build Coastguard Worker 		}
1239*1c60b9acSAndroid Build Coastguard Worker 
1240*1c60b9acSAndroid Build Coastguard Worker 		if (lws_callback_as_writeable(w)) {
1241*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("Closing POLLOUT child (end stream %d)\n",
1242*1c60b9acSAndroid Build Coastguard Worker 				  w->h2.send_END_STREAM);
1243*1c60b9acSAndroid Build Coastguard Worker 			lws_close_free_wsi(w, LWS_CLOSE_STATUS_NOSTATUS,
1244*1c60b9acSAndroid Build Coastguard Worker 					   "h2 pollout handle");
1245*1c60b9acSAndroid Build Coastguard Worker 			wa = &wsi->mux.child_list;
1246*1c60b9acSAndroid Build Coastguard Worker 		} else
1247*1c60b9acSAndroid Build Coastguard Worker 			 if (w->h2.send_END_STREAM)
1248*1c60b9acSAndroid Build Coastguard Worker 				lws_h2_state(w, LWS_H2_STATE_HALF_CLOSED_LOCAL);
1249*1c60b9acSAndroid Build Coastguard Worker 
1250*1c60b9acSAndroid Build Coastguard Worker next_child:
1251*1c60b9acSAndroid Build Coastguard Worker 		wsi2 = wa;
1252*1c60b9acSAndroid Build Coastguard Worker 	} while (wsi2 && *wsi2 && !lws_send_pipe_choked(wsi));
1253*1c60b9acSAndroid Build Coastguard Worker 
1254*1c60b9acSAndroid Build Coastguard Worker 	// lws_wsi_mux_dump_waiting_children(wsi);
1255*1c60b9acSAndroid Build Coastguard Worker 
1256*1c60b9acSAndroid Build Coastguard Worker 	if (lws_wsi_mux_action_pending_writeable_reqs(wsi))
1257*1c60b9acSAndroid Build Coastguard Worker 		return -1;
1258*1c60b9acSAndroid Build Coastguard Worker 
1259*1c60b9acSAndroid Build Coastguard Worker 	return 0;
1260*1c60b9acSAndroid Build Coastguard Worker }
1261*1c60b9acSAndroid Build Coastguard Worker 
1262*1c60b9acSAndroid Build Coastguard Worker static struct lws *
rops_encapsulation_parent_h2(struct lws * wsi)1263*1c60b9acSAndroid Build Coastguard Worker rops_encapsulation_parent_h2(struct lws *wsi)
1264*1c60b9acSAndroid Build Coastguard Worker {
1265*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->mux.parent_wsi)
1266*1c60b9acSAndroid Build Coastguard Worker 		return wsi->mux.parent_wsi;
1267*1c60b9acSAndroid Build Coastguard Worker 
1268*1c60b9acSAndroid Build Coastguard Worker 	return NULL;
1269*1c60b9acSAndroid Build Coastguard Worker }
1270*1c60b9acSAndroid Build Coastguard Worker 
1271*1c60b9acSAndroid Build Coastguard Worker static int
rops_alpn_negotiated_h2(struct lws * wsi,const char * alpn)1272*1c60b9acSAndroid Build Coastguard Worker rops_alpn_negotiated_h2(struct lws *wsi, const char *alpn)
1273*1c60b9acSAndroid Build Coastguard Worker {
1274*1c60b9acSAndroid Build Coastguard Worker 	struct allocated_headers *ah;
1275*1c60b9acSAndroid Build Coastguard Worker 
1276*1c60b9acSAndroid Build Coastguard Worker 	lwsl_debug("%s: client %d\n", __func__, lwsi_role_client(wsi));
1277*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
1278*1c60b9acSAndroid Build Coastguard Worker 	if (lwsi_role_client(wsi)) {
1279*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: upgraded to H2\n", __func__);
1280*1c60b9acSAndroid Build Coastguard Worker 		wsi->client_h2_alpn = 1;
1281*1c60b9acSAndroid Build Coastguard Worker 	}
1282*1c60b9acSAndroid Build Coastguard Worker #endif
1283*1c60b9acSAndroid Build Coastguard Worker 
1284*1c60b9acSAndroid Build Coastguard Worker 	wsi->upgraded_to_http2 = 1;
1285*1c60b9acSAndroid Build Coastguard Worker 
1286*1c60b9acSAndroid Build Coastguard Worker 	/* adopt the header info */
1287*1c60b9acSAndroid Build Coastguard Worker 
1288*1c60b9acSAndroid Build Coastguard Worker 	ah = wsi->http.ah;
1289*1c60b9acSAndroid Build Coastguard Worker 
1290*1c60b9acSAndroid Build Coastguard Worker 	lws_role_transition(wsi, lwsi_role_client(wsi) ? LWSIFR_CLIENT : LWSIFR_SERVER, LRS_H2_AWAIT_PREFACE,
1291*1c60b9acSAndroid Build Coastguard Worker 			    &role_ops_h2);
1292*1c60b9acSAndroid Build Coastguard Worker 
1293*1c60b9acSAndroid Build Coastguard Worker 	/* http2 union member has http union struct at start */
1294*1c60b9acSAndroid Build Coastguard Worker 	wsi->http.ah = ah;
1295*1c60b9acSAndroid Build Coastguard Worker 
1296*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi->h2.h2n)
1297*1c60b9acSAndroid Build Coastguard Worker 		wsi->h2.h2n = lws_zalloc(sizeof(*wsi->h2.h2n), "h2n");
1298*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi->h2.h2n)
1299*1c60b9acSAndroid Build Coastguard Worker 		return 1;
1300*1c60b9acSAndroid Build Coastguard Worker 
1301*1c60b9acSAndroid Build Coastguard Worker 	lws_h2_init(wsi);
1302*1c60b9acSAndroid Build Coastguard Worker 
1303*1c60b9acSAndroid Build Coastguard Worker 	/* HTTP2 union */
1304*1c60b9acSAndroid Build Coastguard Worker 
1305*1c60b9acSAndroid Build Coastguard Worker 	if (lws_hpack_dynamic_size(wsi,
1306*1c60b9acSAndroid Build Coastguard Worker 			   (int)wsi->h2.h2n->our_set.s[H2SET_HEADER_TABLE_SIZE]))
1307*1c60b9acSAndroid Build Coastguard Worker 		return 1;
1308*1c60b9acSAndroid Build Coastguard Worker 	wsi->txc.tx_cr = 65535;
1309*1c60b9acSAndroid Build Coastguard Worker 
1310*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("%s: %s: configured for h2\n", __func__, lws_wsi_tag(wsi));
1311*1c60b9acSAndroid Build Coastguard Worker 
1312*1c60b9acSAndroid Build Coastguard Worker 	return 0;
1313*1c60b9acSAndroid Build Coastguard Worker }
1314*1c60b9acSAndroid Build Coastguard Worker 
1315*1c60b9acSAndroid Build Coastguard Worker static int
rops_issue_keepalive_h2(struct lws * wsi,int isvalid)1316*1c60b9acSAndroid Build Coastguard Worker rops_issue_keepalive_h2(struct lws *wsi, int isvalid)
1317*1c60b9acSAndroid Build Coastguard Worker {
1318*1c60b9acSAndroid Build Coastguard Worker 	struct lws *nwsi = lws_get_network_wsi(wsi);
1319*1c60b9acSAndroid Build Coastguard Worker 	struct lws_h2_protocol_send *pps;
1320*1c60b9acSAndroid Build Coastguard Worker 	uint64_t us = (uint64_t)lws_now_usecs();
1321*1c60b9acSAndroid Build Coastguard Worker 
1322*1c60b9acSAndroid Build Coastguard Worker 	if (isvalid) {
1323*1c60b9acSAndroid Build Coastguard Worker 		_lws_validity_confirmed_role(nwsi);
1324*1c60b9acSAndroid Build Coastguard Worker 
1325*1c60b9acSAndroid Build Coastguard Worker 		return 0;
1326*1c60b9acSAndroid Build Coastguard Worker 	}
1327*1c60b9acSAndroid Build Coastguard Worker 
1328*1c60b9acSAndroid Build Coastguard Worker 	/*
1329*1c60b9acSAndroid Build Coastguard Worker 	 * We can only send these frames on the network connection itself...
1330*1c60b9acSAndroid Build Coastguard Worker 	 * we shouldn't be tracking validity on anything else
1331*1c60b9acSAndroid Build Coastguard Worker 	 */
1332*1c60b9acSAndroid Build Coastguard Worker 
1333*1c60b9acSAndroid Build Coastguard Worker 	assert(wsi == nwsi);
1334*1c60b9acSAndroid Build Coastguard Worker 
1335*1c60b9acSAndroid Build Coastguard Worker 	pps = lws_h2_new_pps(LWS_H2_PPS_PING);
1336*1c60b9acSAndroid Build Coastguard Worker 	if (!pps)
1337*1c60b9acSAndroid Build Coastguard Worker 		return 1;
1338*1c60b9acSAndroid Build Coastguard Worker 
1339*1c60b9acSAndroid Build Coastguard Worker 	/*
1340*1c60b9acSAndroid Build Coastguard Worker 	 * The peer is defined to copy us back the unchanged payload in another
1341*1c60b9acSAndroid Build Coastguard Worker 	 * PING frame this time with ACK set.  So by sending that out with the
1342*1c60b9acSAndroid Build Coastguard Worker 	 * current time, it's an interesting opportunity to learn the effective
1343*1c60b9acSAndroid Build Coastguard Worker 	 * RTT on the link when the PONG comes in, plus or minus the time to
1344*1c60b9acSAndroid Build Coastguard Worker 	 * schedule the PPS.
1345*1c60b9acSAndroid Build Coastguard Worker 	 */
1346*1c60b9acSAndroid Build Coastguard Worker 
1347*1c60b9acSAndroid Build Coastguard Worker 	memcpy(pps->u.ping.ping_payload, &us, 8);
1348*1c60b9acSAndroid Build Coastguard Worker 	lws_pps_schedule(nwsi, pps);
1349*1c60b9acSAndroid Build Coastguard Worker 
1350*1c60b9acSAndroid Build Coastguard Worker 	return 0;
1351*1c60b9acSAndroid Build Coastguard Worker }
1352*1c60b9acSAndroid Build Coastguard Worker 
1353*1c60b9acSAndroid Build Coastguard Worker static const lws_rops_t rops_table_h2[] = {
1354*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SERVER)
1355*1c60b9acSAndroid Build Coastguard Worker 	/*  1 */ { .check_upgrades	  = rops_check_upgrades_h2 },
1356*1c60b9acSAndroid Build Coastguard Worker #else
1357*1c60b9acSAndroid Build Coastguard Worker 	/*  1 */ { .check_upgrades	  = NULL },
1358*1c60b9acSAndroid Build Coastguard Worker #endif
1359*1c60b9acSAndroid Build Coastguard Worker 	/*  2 */ { .pt_init_destroy	  = rops_pt_init_destroy_h2 },
1360*1c60b9acSAndroid Build Coastguard Worker 	/*  3 */ { .init_vhost		  = rops_init_vhost_h2 },
1361*1c60b9acSAndroid Build Coastguard Worker 	/*  4 */ { .handle_POLLIN	  = rops_handle_POLLIN_h2 },
1362*1c60b9acSAndroid Build Coastguard Worker 	/*  5 */ { .handle_POLLOUT	  = rops_handle_POLLOUT_h2 },
1363*1c60b9acSAndroid Build Coastguard Worker 	/*  6 */ { .perform_user_POLLOUT  = rops_perform_user_POLLOUT_h2 },
1364*1c60b9acSAndroid Build Coastguard Worker 	/*  7 */ { .callback_on_writable  = rops_callback_on_writable_h2 },
1365*1c60b9acSAndroid Build Coastguard Worker 	/*  8 */ { .tx_credit		  = rops_tx_credit_h2 },
1366*1c60b9acSAndroid Build Coastguard Worker 	/*  9 */ { .write_role_protocol	  = rops_write_role_protocol_h2 },
1367*1c60b9acSAndroid Build Coastguard Worker 	/* 10 */ { .encapsulation_parent  = rops_encapsulation_parent_h2 },
1368*1c60b9acSAndroid Build Coastguard Worker 	/* 11 */ { .alpn_negotiated	  = rops_alpn_negotiated_h2 },
1369*1c60b9acSAndroid Build Coastguard Worker 	/* 12 */ { .close_kill_connection = rops_close_kill_connection_h2 },
1370*1c60b9acSAndroid Build Coastguard Worker 	/* 13 */ { .destroy_role	  = rops_destroy_role_h2 },
1371*1c60b9acSAndroid Build Coastguard Worker 	/* 14 */ { .issue_keepalive	  = rops_issue_keepalive_h2 },
1372*1c60b9acSAndroid Build Coastguard Worker };
1373*1c60b9acSAndroid Build Coastguard Worker 
1374*1c60b9acSAndroid Build Coastguard Worker 
1375*1c60b9acSAndroid Build Coastguard Worker const struct lws_role_ops role_ops_h2 = {
1376*1c60b9acSAndroid Build Coastguard Worker 	/* role name */			"h2",
1377*1c60b9acSAndroid Build Coastguard Worker 	/* alpn id */			"h2",
1378*1c60b9acSAndroid Build Coastguard Worker 
1379*1c60b9acSAndroid Build Coastguard Worker 	/* rops_table */		rops_table_h2,
1380*1c60b9acSAndroid Build Coastguard Worker 	/* rops_idx */			{
1381*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_check_upgrades */
1382*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SERVER)
1383*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_pt_init_destroy */		0x12,
1384*1c60b9acSAndroid Build Coastguard Worker #else
1385*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_pt_init_destroy */		0x02,
1386*1c60b9acSAndroid Build Coastguard Worker #endif
1387*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_init_vhost */
1388*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_destroy_vhost */			0x30,
1389*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_service_flag_pending */
1390*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_handle_POLLIN */			0x04,
1391*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_handle_POLLOUT */
1392*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_perform_user_POLLOUT */		0x56,
1393*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_callback_on_writable */
1394*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_tx_credit */			0x78,
1395*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_write_role_protocol */
1396*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_encapsulation_parent */		0x9a,
1397*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_alpn_negotiated */
1398*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_close_via_role_protocol */	0xb0,
1399*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_close_role */
1400*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_close_kill_connection */		0x0c,
1401*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_destroy_role */
1402*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_adoption_bind */			0xd0,
1403*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_client_bind */
1404*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_issue_keepalive */		0x0e,
1405*1c60b9acSAndroid Build Coastguard Worker 					},
1406*1c60b9acSAndroid Build Coastguard Worker 	/* adoption_cb clnt, srv */	{ LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED,
1407*1c60b9acSAndroid Build Coastguard Worker 					  LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED },
1408*1c60b9acSAndroid Build Coastguard Worker 	/* rx cb clnt, srv */		{ LWS_CALLBACK_RECEIVE_CLIENT_HTTP,
1409*1c60b9acSAndroid Build Coastguard Worker 					  0 /* may be POST, etc */ },
1410*1c60b9acSAndroid Build Coastguard Worker 	/* writeable cb clnt, srv */	{ LWS_CALLBACK_CLIENT_HTTP_WRITEABLE,
1411*1c60b9acSAndroid Build Coastguard Worker 					  LWS_CALLBACK_HTTP_WRITEABLE },
1412*1c60b9acSAndroid Build Coastguard Worker 	/* close cb clnt, srv */	{ LWS_CALLBACK_CLOSED_CLIENT_HTTP,
1413*1c60b9acSAndroid Build Coastguard Worker 					  LWS_CALLBACK_CLOSED_HTTP },
1414*1c60b9acSAndroid Build Coastguard Worker 	/* protocol_bind cb c, srv */	{ LWS_CALLBACK_CLIENT_HTTP_BIND_PROTOCOL,
1415*1c60b9acSAndroid Build Coastguard Worker 					  LWS_CALLBACK_HTTP_BIND_PROTOCOL },
1416*1c60b9acSAndroid Build Coastguard Worker 	/* protocol_unbind cb c, srv */	{ LWS_CALLBACK_CLIENT_HTTP_DROP_PROTOCOL,
1417*1c60b9acSAndroid Build Coastguard Worker 					  LWS_CALLBACK_HTTP_DROP_PROTOCOL },
1418*1c60b9acSAndroid Build Coastguard Worker 	/* file_handle */		0,
1419*1c60b9acSAndroid Build Coastguard Worker };
1420