Coverage Report

Created: 2026-04-12 06:57

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