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