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