Coverage Report

Created: 2025-07-23 06:27

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