Coverage Report

Created: 2026-04-01 06:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libwebsockets/lib/roles/h2/http2.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
 * bitmap of control messages that are valid to receive for each http2 state
29
 */
30
31
static const uint16_t http2_rx_validity[] = {
32
  /* LWS_H2S_IDLE */
33
    (1 << LWS_H2_FRAME_TYPE_SETTINGS) |
34
    (1 << LWS_H2_FRAME_TYPE_PRIORITY) |
35
//    (1 << LWS_H2_FRAME_TYPE_WINDOW_UPDATE)| /* ignore */
36
    (1 << LWS_H2_FRAME_TYPE_HEADERS) |
37
    (1 << LWS_H2_FRAME_TYPE_CONTINUATION),
38
  /* LWS_H2S_RESERVED_LOCAL */
39
    (1 << LWS_H2_FRAME_TYPE_SETTINGS) |
40
    (1 << LWS_H2_FRAME_TYPE_RST_STREAM) |
41
    (1 << LWS_H2_FRAME_TYPE_PRIORITY) |
42
    (1 << LWS_H2_FRAME_TYPE_WINDOW_UPDATE),
43
  /* LWS_H2S_RESERVED_REMOTE */
44
    (1 << LWS_H2_FRAME_TYPE_SETTINGS) |
45
    (1 << LWS_H2_FRAME_TYPE_HEADERS) |
46
    (1 << LWS_H2_FRAME_TYPE_CONTINUATION) |
47
    (1 << LWS_H2_FRAME_TYPE_RST_STREAM) |
48
    (1 << LWS_H2_FRAME_TYPE_PRIORITY),
49
  /* LWS_H2S_OPEN */
50
    (1 << LWS_H2_FRAME_TYPE_DATA) |
51
    (1 << LWS_H2_FRAME_TYPE_HEADERS) |
52
    (1 << LWS_H2_FRAME_TYPE_PRIORITY) |
53
    (1 << LWS_H2_FRAME_TYPE_RST_STREAM) |
54
    (1 << LWS_H2_FRAME_TYPE_SETTINGS) |
55
    (1 << LWS_H2_FRAME_TYPE_PUSH_PROMISE) |
56
    (1 << LWS_H2_FRAME_TYPE_PING) |
57
    (1 << LWS_H2_FRAME_TYPE_GOAWAY) |
58
    (1 << LWS_H2_FRAME_TYPE_WINDOW_UPDATE) |
59
    (1 << LWS_H2_FRAME_TYPE_CONTINUATION),
60
  /* LWS_H2S_HALF_CLOSED_REMOTE */
61
    (1 << LWS_H2_FRAME_TYPE_SETTINGS) |
62
    (1 << LWS_H2_FRAME_TYPE_WINDOW_UPDATE) |
63
    (1 << LWS_H2_FRAME_TYPE_PRIORITY) |
64
    (1 << LWS_H2_FRAME_TYPE_RST_STREAM),
65
  /* LWS_H2S_HALF_CLOSED_LOCAL */
66
    (1 << LWS_H2_FRAME_TYPE_DATA) |
67
    (1 << LWS_H2_FRAME_TYPE_HEADERS) |
68
    (1 << LWS_H2_FRAME_TYPE_PRIORITY) |
69
    (1 << LWS_H2_FRAME_TYPE_RST_STREAM) |
70
    (1 << LWS_H2_FRAME_TYPE_SETTINGS) |
71
    (1 << LWS_H2_FRAME_TYPE_PUSH_PROMISE) |
72
    (1 << LWS_H2_FRAME_TYPE_PING) |
73
    (1 << LWS_H2_FRAME_TYPE_GOAWAY) |
74
    (1 << LWS_H2_FRAME_TYPE_WINDOW_UPDATE) |
75
    (1 << LWS_H2_FRAME_TYPE_CONTINUATION),
76
  /* LWS_H2S_CLOSED */
77
    (1 << LWS_H2_FRAME_TYPE_SETTINGS) |
78
    (1 << LWS_H2_FRAME_TYPE_PRIORITY) |
79
    (1 << LWS_H2_FRAME_TYPE_WINDOW_UPDATE) |
80
    (1 << LWS_H2_FRAME_TYPE_RST_STREAM),
81
};
82
83
static const char *preface = "PRI * HTTP/2.0\x0d\x0a\x0d\x0aSM\x0d\x0a\x0d\x0a";
84
85
static const char * const h2_state_names[] = {
86
  "LWS_H2S_IDLE",
87
  "LWS_H2S_RESERVED_LOCAL",
88
  "LWS_H2S_RESERVED_REMOTE",
89
  "LWS_H2S_OPEN",
90
  "LWS_H2S_HALF_CLOSED_REMOTE",
91
  "LWS_H2S_HALF_CLOSED_LOCAL",
92
  "LWS_H2S_CLOSED",
93
};
94
95
#if 0
96
static const char * const h2_setting_names[] = {
97
  "",
98
  "H2SET_HEADER_TABLE_SIZE",
99
  "H2SET_ENABLE_PUSH",
100
  "H2SET_MAX_CONCURRENT_STREAMS",
101
  "H2SET_INITIAL_WINDOW_SIZE",
102
  "H2SET_MAX_FRAME_SIZE",
103
  "H2SET_MAX_HEADER_LIST_SIZE",
104
  "reserved",
105
  "H2SET_ENABLE_CONNECT_PROTOCOL"
106
};
107
108
void
109
lws_h2_dump_settings(struct http2_settings *set)
110
{
111
  int n;
112
113
  for (n = 1; n < H2SET_COUNT; n++)
114
    lwsl_notice("   %30s: %10d\n", h2_setting_names[n], set->s[n]);
115
}
116
#else
117
void
118
lws_h2_dump_settings(struct http2_settings *set)
119
0
{
120
0
}
121
#endif
122
123
struct lws_h2_protocol_send *
124
lws_h2_new_pps(enum lws_h2_protocol_send_type type)
125
0
{
126
0
  struct lws_h2_protocol_send *pps = lws_malloc(sizeof(*pps), "pps");
127
128
0
  if (pps)
129
0
    pps->type = type;
130
131
0
  return pps;
132
0
}
133
134
void lws_h2_init(struct lws *wsi)
135
0
{
136
0
  wsi->h2.h2n->our_set = wsi->a.vhost->h2.set;
137
0
  wsi->h2.h2n->peer_set = lws_h2_defaults;
138
0
}
139
140
void
141
lws_h2_state(struct lws *wsi, enum lws_h2_states s)
142
0
{
143
0
  if (!wsi)
144
0
    return;
145
0
  lwsl_info("%s: %s: state %s -> %s\n", __func__, lws_wsi_tag(wsi),
146
0
      h2_state_names[wsi->h2.h2_state],
147
0
      h2_state_names[s]);
148
    
149
0
  (void)h2_state_names;
150
0
  wsi->h2.h2_state = (uint8_t)s;
151
0
}
152
153
int
154
lws_h2_update_peer_txcredit(struct lws *wsi, unsigned int sid, int bump)
155
0
{
156
0
  struct lws *nwsi = lws_get_network_wsi(wsi);
157
0
  struct lws_h2_protocol_send *pps;
158
159
0
  assert(wsi);
160
161
0
  if (!bump)
162
0
    return 0;
163
164
0
  if (sid == (unsigned int)-1)
165
0
    sid = wsi->mux.my_sid;
166
167
0
  lwsl_info("%s: sid %d: bump %d -> %d\n", __func__, sid, bump,
168
0
      (int)wsi->txc.peer_tx_cr_est + bump);
169
170
0
  pps = lws_h2_new_pps(LWS_H2_PPS_UPDATE_WINDOW);
171
0
  if (!pps)
172
0
    return 1;
173
174
0
  pps->u.update_window.sid = (unsigned int)sid;
175
0
  pps->u.update_window.credit = (unsigned int)bump;
176
0
  wsi->txc.peer_tx_cr_est += bump;
177
178
0
  lws_wsi_txc_describe(&wsi->txc, __func__, wsi->mux.my_sid);
179
180
0
  lws_pps_schedule(wsi, pps);
181
182
0
  pps = lws_h2_new_pps(LWS_H2_PPS_UPDATE_WINDOW);
183
0
  if (!pps)
184
0
    return 1;
185
186
0
  pps->u.update_window.sid = 0;
187
0
  pps->u.update_window.credit = (unsigned int)bump;
188
0
  nwsi->txc.peer_tx_cr_est += bump;
189
190
0
  lws_wsi_txc_describe(&nwsi->txc, __func__, nwsi->mux.my_sid);
191
192
0
  lws_pps_schedule(nwsi, pps);
193
194
0
  return 0;
195
0
}
196
197
int
198
lws_h2_get_peer_txcredit_estimate(struct lws *wsi)
199
0
{
200
0
  lws_wsi_txc_describe(&wsi->txc, __func__, wsi->mux.my_sid);
201
0
  return (int)wsi->txc.peer_tx_cr_est;
202
0
}
203
204
static int
205
lws_h2_update_peer_txcredit_thresh(struct lws *wsi, unsigned int sid, int threshold, int bump)
206
0
{
207
0
  if (wsi->txc.peer_tx_cr_est > threshold)
208
0
    return 0;
209
210
0
  return lws_h2_update_peer_txcredit(wsi, sid, bump);
211
0
}
212
213
/* cx + vh lock */
214
215
static struct lws *
216
__lws_wsi_server_new(struct lws_vhost *vh, struct lws *parent_wsi,
217
         unsigned int sid)
218
0
{
219
0
  struct lws *nwsi = lws_get_network_wsi(parent_wsi);
220
0
  struct lws_h2_netconn *h2n = nwsi->h2.h2n;
221
0
  char tmp[50], tmp1[50];
222
0
  unsigned int n, b = 0;
223
0
  struct lws *wsi;
224
0
  const char *p;
225
226
0
  lws_context_assert_lock_held(vh->context);
227
0
  lws_vhost_assert_lock_held(vh);
228
229
  /*
230
   * The identifier of a newly established stream MUST be numerically
231
     * greater than all streams that the initiating endpoint has opened or
232
     * reserved.  This governs streams that are opened using a HEADERS frame
233
     * and streams that are reserved using PUSH_PROMISE.  An endpoint that
234
     * receives an unexpected stream identifier MUST respond with a
235
     * connection error (Section 5.4.1) of type PROTOCOL_ERROR.
236
   */
237
0
  if (sid <= h2n->highest_sid_opened) {
238
0
    lwsl_info("%s: tried to open lower sid %d (%d)\n", __func__,
239
0
        sid, (int)h2n->highest_sid_opened);
240
0
    lws_h2_goaway(nwsi, H2_ERR_PROTOCOL_ERROR, "Bad sid");
241
0
    return NULL;
242
0
  }
243
244
  /* no more children allowed by parent */
245
0
  if (parent_wsi->mux.child_count + 1 >
246
0
      parent_wsi->h2.h2n->our_set.s[H2SET_MAX_CONCURRENT_STREAMS]) {
247
0
    lwsl_notice("reached concurrent stream limit\n");
248
0
    return NULL;
249
0
  }
250
251
0
  n = 0;
252
0
  p = &parent_wsi->lc.gutag[1];
253
0
  do {
254
0
    if (*p == '|') {
255
0
      b++;
256
0
      if (b == 3)
257
0
        continue;
258
0
    }
259
0
    tmp1[n++] = *p++;
260
0
  } while (b < 3 && n < sizeof(tmp1) - 2);
261
0
  tmp1[n] = '\0';
262
0
  lws_snprintf(tmp, sizeof(tmp), "h2_sid%u_(%s)", sid, tmp1);
263
0
  wsi = lws_create_new_server_wsi(vh, parent_wsi->tsi, LWSLCG_WSI_MUX, tmp);
264
0
  if (!wsi) {
265
0
    lwsl_notice("new server wsi failed (%s)\n", lws_vh_tag(vh));
266
0
    return NULL;
267
0
  }
268
269
0
#if defined(LWS_WITH_SERVER)
270
0
  if (lwsi_role_server(parent_wsi)) {
271
0
    lws_metrics_caliper_bind(wsi->cal_conn, wsi->a.context->mth_srv);
272
0
  }
273
0
#endif
274
275
0
  h2n->highest_sid_opened = sid;
276
277
0
  lws_wsi_mux_insert(wsi, parent_wsi, sid);
278
0
  if (sid >= h2n->highest_sid)
279
0
    h2n->highest_sid = sid + 2;
280
281
0
  wsi->mux_substream = 1;
282
0
  wsi->seen_nonpseudoheader = 0;
283
284
0
  wsi->txc.tx_cr = (int32_t)nwsi->h2.h2n->peer_set.s[H2SET_INITIAL_WINDOW_SIZE];
285
0
  wsi->txc.peer_tx_cr_est =
286
0
      (int32_t)nwsi->h2.h2n->our_set.s[H2SET_INITIAL_WINDOW_SIZE];
287
288
0
  lwsi_set_state(wsi, LRS_ESTABLISHED);
289
0
  lwsi_set_role(wsi, lwsi_role(parent_wsi));
290
291
0
  wsi->a.protocol = &vh->protocols[0];
292
0
  if (lws_ensure_user_space(wsi))
293
0
    goto bail1;
294
295
0
#if defined(LWS_WITH_SERVER) && defined(LWS_WITH_SECURE_STREAMS)
296
0
  if (lws_adopt_ss_server_accept(wsi))
297
0
    goto bail1;
298
0
#endif
299
300
  /* get the ball rolling */
301
0
  lws_validity_confirmed(wsi);
302
303
0
  lwsl_info("%s: %s new ch %s, sid %d, usersp=%p\n", __func__,
304
0
      lws_wsi_tag(parent_wsi), lws_wsi_tag(wsi), sid, wsi->user_space);
305
306
0
  lws_wsi_txc_describe(&wsi->txc, __func__, wsi->mux.my_sid);
307
0
  lws_wsi_txc_describe(&nwsi->txc, __func__, 0);
308
309
0
  return wsi;
310
311
0
bail1:
312
  /* undo the insert */
313
0
  parent_wsi->mux.child_list = wsi->mux.sibling_list;
314
0
  parent_wsi->mux.child_count--;
315
316
0
  if (wsi->user_space)
317
0
    lws_free_set_NULL(wsi->user_space);
318
0
  vh->protocols[0].callback(wsi, LWS_CALLBACK_WSI_DESTROY, NULL, NULL, 0);
319
0
  __lws_vhost_unbind_wsi(wsi);
320
0
  lws_free(wsi);
321
322
0
  return NULL;
323
0
}
324
325
struct lws *
326
lws_wsi_h2_adopt(struct lws *parent_wsi, struct lws *wsi)
327
0
{
328
0
  struct lws *nwsi = lws_get_network_wsi(parent_wsi);
329
330
  /* no more children allowed by parent */
331
0
  if (parent_wsi->mux.child_count + 1 >
332
0
      parent_wsi->h2.h2n->our_set.s[H2SET_MAX_CONCURRENT_STREAMS]) {
333
0
    lwsl_notice("reached concurrent stream limit\n");
334
0
    return NULL;
335
0
  }
336
337
  /* sid is set just before issuing the headers, ensuring monoticity */
338
339
0
  wsi->seen_nonpseudoheader = 0;
340
0
#if defined(LWS_WITH_CLIENT)
341
0
  wsi->client_mux_substream = 1;
342
0
#endif
343
0
  wsi->h2.initialized = 1;
344
345
#if 0
346
  /* only assign sid at header send time when we know it */
347
  if (!wsi->mux.my_sid) {
348
    wsi->mux.my_sid = nwsi->h2.h2n->highest_sid;
349
    nwsi->h2.h2n->highest_sid += 2;
350
  }
351
#endif
352
353
0
  lwsl_info("%s: binding wsi %s to sid %d (next %d)\n", __func__,
354
0
    lws_wsi_tag(wsi), (int)wsi->mux.my_sid, (int)nwsi->h2.h2n->highest_sid);
355
356
0
  lws_wsi_mux_insert(wsi, parent_wsi, wsi->mux.my_sid);
357
358
0
  wsi->txc.tx_cr = (int32_t)nwsi->h2.h2n->peer_set.s[H2SET_INITIAL_WINDOW_SIZE];
359
0
  wsi->txc.peer_tx_cr_est = (int32_t)
360
0
      nwsi->h2.h2n->our_set.s[H2SET_INITIAL_WINDOW_SIZE];
361
362
0
  lws_wsi_txc_describe(&wsi->txc, __func__, wsi->mux.my_sid);
363
364
0
  if (lws_ensure_user_space(wsi))
365
0
    goto bail1;
366
367
0
  lws_role_transition(wsi, LWSIFR_CLIENT, LRS_H2_WAITING_TO_SEND_HEADERS,
368
0
          &role_ops_h2);
369
370
0
  lws_callback_on_writable(wsi);
371
372
0
  return wsi;
373
374
0
bail1:
375
  /* undo the insert */
376
0
  parent_wsi->mux.child_list = wsi->mux.sibling_list;
377
0
  parent_wsi->mux.child_count--;
378
379
0
  if (wsi->user_space)
380
0
    lws_free_set_NULL(wsi->user_space);
381
0
  wsi->a.protocol->callback(wsi, LWS_CALLBACK_WSI_DESTROY, NULL, NULL, 0);
382
0
  lws_free(wsi);
383
384
0
  return NULL;
385
0
}
386
387
388
int
389
lws_h2_issue_preface(struct lws *wsi)
390
0
{
391
0
  struct lws_h2_netconn *h2n = wsi->h2.h2n;
392
0
  struct lws_h2_protocol_send *pps;
393
394
0
  if (!h2n) {
395
0
    lwsl_warn("%s: no valid h2n\n", __func__);
396
0
    return 1;
397
0
  }
398
399
0
  if (h2n->sent_preface)
400
0
    return 1;
401
402
0
  lwsl_debug("%s: %s: fd %d\n", __func__, lws_wsi_tag(wsi), (int)wsi->desc.sockfd);
403
404
0
  if (lws_issue_raw(wsi, (uint8_t *)preface, strlen(preface)) !=
405
0
    (int)strlen(preface))
406
0
    return 1;
407
408
0
  h2n->sent_preface = 1;
409
410
0
  lws_role_transition(wsi, LWSIFR_CLIENT, LRS_H2_WAITING_TO_SEND_HEADERS,
411
0
          &role_ops_h2);
412
413
0
  h2n->count = 0;
414
0
  wsi->txc.tx_cr = 65535;
415
416
  /*
417
   * we must send a settings frame
418
   */
419
0
  pps = lws_h2_new_pps(LWS_H2_PPS_MY_SETTINGS);
420
0
  if (!pps)
421
0
    return 1;
422
0
  lws_pps_schedule(wsi, pps);
423
0
  lwsl_info("%s: h2 client sending settings\n", __func__);
424
425
0
  return 0;
426
0
}
427
428
void
429
lws_pps_schedule(struct lws *wsi, struct lws_h2_protocol_send *pps)
430
0
{
431
0
  struct lws *nwsi = lws_get_network_wsi(wsi);
432
0
  struct lws_h2_netconn *h2n = nwsi->h2.h2n;
433
434
0
  if (!h2n) {
435
0
    lwsl_warn("%s: null h2n\n", __func__);
436
0
    lws_free(pps);
437
0
    return;
438
0
  }
439
440
0
  pps->next = h2n->pps;
441
0
  h2n->pps = pps;
442
0
  lws_rx_flow_control(wsi, LWS_RXFLOW_REASON_APPLIES_DISABLE |
443
0
         LWS_RXFLOW_REASON_H2_PPS_PENDING);
444
0
  lws_callback_on_writable(wsi);
445
0
}
446
447
int
448
lws_h2_goaway(struct lws *wsi, uint32_t err, const char *reason)
449
0
{
450
0
  struct lws_h2_netconn *h2n = wsi->h2.h2n;
451
0
  struct lws_h2_protocol_send *pps;
452
453
0
  if (h2n->type == LWS_H2_FRAME_TYPE_COUNT)
454
0
    return 0;
455
456
0
  pps = lws_h2_new_pps(LWS_H2_PPS_GOAWAY);
457
0
  if (!pps)
458
0
    return 1;
459
460
0
  lwsl_info("%s: %s: ERR 0x%x, '%s'\n", __func__, lws_wsi_tag(wsi), (int)err, reason);
461
462
0
  pps->u.ga.err = err;
463
0
  pps->u.ga.highest_sid = h2n->highest_sid;
464
0
  lws_strncpy(pps->u.ga.str, reason, sizeof(pps->u.ga.str));
465
0
  lws_pps_schedule(wsi, pps);
466
467
0
  h2n->type = LWS_H2_FRAME_TYPE_COUNT; /* ie, IGNORE */
468
469
0
  return 0;
470
0
}
471
472
int
473
lws_h2_rst_stream(struct lws *wsi, uint32_t err, const char *reason)
474
0
{
475
0
  struct lws *nwsi = lws_get_network_wsi(wsi);
476
0
  struct lws_h2_netconn *h2n = nwsi->h2.h2n;
477
0
  struct lws_h2_protocol_send *pps;
478
479
0
  if (!h2n)
480
0
    return 0;
481
482
0
  if (!wsi->h2_stream_carries_ws && h2n->type == LWS_H2_FRAME_TYPE_COUNT)
483
0
    return 0;
484
485
0
  pps = lws_h2_new_pps(LWS_H2_PPS_RST_STREAM);
486
0
  if (!pps)
487
0
    return 1;
488
489
0
  lwsl_info("%s: RST_STREAM 0x%x, sid %d, REASON '%s'\n", __func__,
490
0
      (int)err, wsi->mux.my_sid, reason);
491
492
0
  pps->u.rs.sid = wsi->mux.my_sid;
493
0
  pps->u.rs.err = err;
494
495
0
  lws_pps_schedule(wsi, pps);
496
497
0
  h2n->type = LWS_H2_FRAME_TYPE_COUNT; /* ie, IGNORE */
498
0
  lws_h2_state(wsi, LWS_H2_STATE_CLOSED);
499
500
0
  return 0;
501
0
}
502
503
int
504
lws_h2_settings(struct lws *wsi, struct http2_settings *settings,
505
    unsigned char *buf, int len)
506
0
{
507
0
  struct lws *nwsi = lws_get_network_wsi(wsi);
508
0
  unsigned int a, b;
509
510
0
  if (!len)
511
0
    return 0;
512
513
0
  if (len < LWS_H2_SETTINGS_LEN)
514
0
    return 1;
515
516
0
  while (len >= LWS_H2_SETTINGS_LEN) {
517
0
    a = (unsigned int)((buf[0] << 8) | buf[1]);
518
0
    if (!a || a >= H2SET_COUNT)
519
0
      goto skip;
520
0
    b = (unsigned int)(buf[2] << 24 | buf[3] << 16 | buf[4] << 8 | buf[5]);
521
522
0
    switch (a) {
523
0
    case H2SET_HEADER_TABLE_SIZE:
524
0
      break;
525
0
    case H2SET_ENABLE_PUSH:
526
0
      if (b > 1) {
527
0
        lws_h2_goaway(nwsi, H2_ERR_PROTOCOL_ERROR,
528
0
                "ENABLE_PUSH invalid arg");
529
0
        return 1;
530
0
      }
531
0
      break;
532
0
    case H2SET_MAX_CONCURRENT_STREAMS:
533
0
      break;
534
0
    case H2SET_INITIAL_WINDOW_SIZE:
535
0
      if (b > 0x7fffffff) {
536
0
        lws_h2_goaway(nwsi, H2_ERR_FLOW_CONTROL_ERROR,
537
0
                "Initial Window beyond max");
538
0
        return 1;
539
0
      }
540
541
0
#if defined(LWS_WITH_CLIENT)
542
#if defined(LWS_AMAZON_RTOS) || defined(LWS_AMAZON_LINUX)
543
      if (
544
#else
545
0
      if (wsi->flags & LCCSCF_H2_QUIRK_OVERFLOWS_TXCR &&
546
0
#endif
547
0
          b == 0x7fffffff) {
548
0
        b >>= 4;
549
550
0
        break;
551
0
      }
552
0
#endif
553
554
      /*
555
       * In addition to changing the flow-control window for
556
       * streams that are not yet active, a SETTINGS frame
557
       * can alter the initial flow-control window size for
558
       * streams with active flow-control windows (that is,
559
       * streams in the "open" or "half-closed (remote)"
560
       * state).  When the value of
561
       * SETTINGS_INITIAL_WINDOW_SIZE changes, a receiver
562
       * MUST adjust the size of all stream flow-control
563
       * windows that it maintains by the difference between
564
       * the new value and the old value.
565
       */
566
567
0
      lws_start_foreach_ll(struct lws *, w,
568
0
               nwsi->mux.child_list) {
569
0
        lwsl_info("%s: adi child tc cr %d +%d -> %d",
570
0
            __func__, (int)w->txc.tx_cr,
571
0
            b - (unsigned int)settings->s[a],
572
0
            (int)(w->txc.tx_cr + (int)b -
573
0
              (int)settings->s[a]));
574
0
        w->txc.tx_cr += (int)b - (int)settings->s[a];
575
0
        if (w->txc.tx_cr > 0 &&
576
0
            w->txc.tx_cr <=
577
0
              (int32_t)(b - settings->s[a]))
578
579
0
          lws_callback_on_writable(w);
580
0
      } lws_end_foreach_ll(w, mux.sibling_list);
581
582
0
      break;
583
0
    case H2SET_MAX_FRAME_SIZE:
584
0
      if (b < wsi->a.vhost->h2.set.s[H2SET_MAX_FRAME_SIZE]) {
585
0
        lws_h2_goaway(nwsi, H2_ERR_PROTOCOL_ERROR,
586
0
                "Frame size < initial");
587
0
        return 1;
588
0
      }
589
0
      if (b > 0x00ffffff) {
590
0
        lws_h2_goaway(nwsi, H2_ERR_PROTOCOL_ERROR,
591
0
                "Settings Frame size above max");
592
0
        return 1;
593
0
      }
594
0
      break;
595
0
    case H2SET_MAX_HEADER_LIST_SIZE:
596
0
      break;
597
0
    }
598
0
    settings->s[a] = b;
599
0
    lwsl_info("http2 settings %d <- 0x%x\n", a, b);
600
0
skip:
601
0
    len -= LWS_H2_SETTINGS_LEN;
602
0
    buf += LWS_H2_SETTINGS_LEN;
603
0
  }
604
605
0
  if (len)
606
0
    return 1;
607
608
0
  lws_h2_dump_settings(settings);
609
610
0
  return 0;
611
0
}
612
613
/* RFC7640 Sect 6.9
614
 *
615
 * The WINDOW_UPDATE frame can be specific to a stream or to the entire
616
 * connection.  In the former case, the frame's stream identifier
617
 * indicates the affected stream; in the latter, the value "0" indicates
618
 * that the entire connection is the subject of the frame.
619
 *
620
 * ...
621
 *
622
 * Two flow-control windows are applicable: the stream flow-control
623
 * window and the connection flow-control window.  The sender MUST NOT
624
 * send a flow-controlled frame with a length that exceeds the space
625
 * available in either of the flow-control windows advertised by the
626
 * receiver.  Frames with zero length with the END_STREAM flag set (that
627
 * is, an empty DATA frame) MAY be sent if there is no available space
628
 * in either flow-control window.
629
 */
630
631
int
632
lws_h2_tx_cr_get(struct lws *wsi)
633
0
{
634
0
  int c = wsi->txc.tx_cr;
635
0
  struct lws *nwsi = lws_get_network_wsi(wsi);
636
637
0
  if (!wsi->mux_substream && !nwsi->upgraded_to_http2)
638
0
    return ~0x80000000;
639
640
0
  lwsl_info ("%s: %s: own tx credit %d: nwsi credit %d\n",
641
0
         __func__, lws_wsi_tag(wsi), c, (int)nwsi->txc.tx_cr);
642
643
0
  if (nwsi->txc.tx_cr < c)
644
0
    c = nwsi->txc.tx_cr;
645
646
0
  if (c < 0)
647
0
    return 0;
648
649
0
  return c;
650
0
}
651
652
void
653
lws_h2_tx_cr_consume(struct lws *wsi, int consumed)
654
0
{
655
0
  struct lws *nwsi = lws_get_network_wsi(wsi);
656
657
0
  wsi->txc.tx_cr -= consumed;
658
659
0
  if (nwsi != wsi)
660
0
    nwsi->txc.tx_cr -= consumed;
661
0
}
662
663
int lws_h2_frame_write(struct lws *wsi, int type, int flags,
664
           unsigned int sid, unsigned int len, unsigned char *buf)
665
0
{
666
0
  struct lws *nwsi = lws_get_network_wsi(wsi);
667
0
  unsigned char *p = &buf[-LWS_H2_FRAME_HEADER_LENGTH];
668
0
  int n;
669
670
  //if (wsi->h2_stream_carries_ws)
671
  // lwsl_hexdump_level(LLL_NOTICE, buf, len);
672
673
0
  *p++ = (uint8_t)(len >> 16);
674
0
  *p++ = (uint8_t)(len >> 8);
675
0
  *p++ = (uint8_t)len;
676
0
  *p++ = (uint8_t)type;
677
0
  *p++ = (uint8_t)flags;
678
0
  *p++ = (uint8_t)(sid >> 24);
679
0
  *p++ = (uint8_t)(sid >> 16);
680
0
  *p++ = (uint8_t)(sid >> 8);
681
0
  *p++ = (uint8_t)sid;
682
683
0
  lwsl_debug("%s: %s (eff %s). typ %d, fl 0x%x, sid=%d, len=%d, "
684
0
       "txcr=%d, nwsi->txcr=%d\n", __func__, lws_wsi_tag(wsi),
685
0
       lws_wsi_tag(nwsi), type, flags,
686
0
       sid, len, (int)wsi->txc.tx_cr, (int)nwsi->txc.tx_cr);
687
688
0
  if (type == LWS_H2_FRAME_TYPE_DATA) {
689
0
    if (wsi->txc.tx_cr < (int)len)
690
691
0
      lwsl_info("%s: %s: sending payload len %d"
692
0
         " but tx_cr only %d!\n", __func__,
693
0
         lws_wsi_tag(wsi), len, (int)wsi->txc.tx_cr);
694
0
        lws_h2_tx_cr_consume(wsi, (int)len);
695
0
  }
696
697
0
  n = lws_issue_raw(nwsi, &buf[-LWS_H2_FRAME_HEADER_LENGTH],
698
0
        len + LWS_H2_FRAME_HEADER_LENGTH);
699
0
  if (n < 0)
700
0
    return n;
701
702
0
  if (n >= LWS_H2_FRAME_HEADER_LENGTH)
703
0
    return n - LWS_H2_FRAME_HEADER_LENGTH;
704
705
0
  return n;
706
0
}
707
708
static void lws_h2_set_bin(struct lws *wsi, int n, unsigned char *buf)
709
0
{
710
0
  *buf++ = (uint8_t)(n >> 8);
711
0
  *buf++ = (uint8_t)n;
712
0
  *buf++ = (uint8_t)(wsi->h2.h2n->our_set.s[n] >> 24);
713
0
  *buf++ = (uint8_t)(wsi->h2.h2n->our_set.s[n] >> 16);
714
0
  *buf++ = (uint8_t)(wsi->h2.h2n->our_set.s[n] >> 8);
715
0
  *buf = (uint8_t)wsi->h2.h2n->our_set.s[n];
716
0
}
717
718
/* we get called on the network connection */
719
720
int lws_h2_do_pps_send(struct lws *wsi)
721
0
{
722
0
  struct lws_h2_netconn *h2n = wsi->h2.h2n;
723
0
  struct lws_h2_protocol_send *pps = NULL;
724
0
  struct lws *cwsi;
725
0
  uint8_t set[LWS_PRE + 64], *p = &set[LWS_PRE], *q;
726
0
  int n, m = 0, flags = 0;
727
728
0
  if (!h2n)
729
0
    return 1;
730
731
  /* get the oldest pps */
732
733
0
  lws_start_foreach_llp(struct lws_h2_protocol_send **, pps1, h2n->pps) {
734
0
    if ((*pps1)->next == NULL) { /* we are the oldest in the list */
735
0
      pps = *pps1; /* remove us from the list */
736
0
      *pps1 = NULL;
737
0
      continue;
738
0
    }
739
0
  } lws_end_foreach_llp(pps1, next);
740
741
0
  if (!pps)
742
0
    return 1;
743
744
0
  lwsl_info("%s: %s: %d\n", __func__, lws_wsi_tag(wsi), pps->type);
745
746
0
  switch (pps->type) {
747
748
0
  case LWS_H2_PPS_MY_SETTINGS:
749
750
    /*
751
     * if any of our settings varies from h2 "default defaults"
752
     * then we must inform the peer
753
     */
754
0
    for (n = 1; n < H2SET_COUNT; n++)
755
0
      if (h2n->our_set.s[n] != lws_h2_defaults.s[n]) {
756
0
        lwsl_debug("sending SETTING %d 0x%x\n", n,
757
0
             (unsigned int)
758
0
               wsi->h2.h2n->our_set.s[n]);
759
760
0
        lws_h2_set_bin(wsi, n, &set[LWS_PRE + m]);
761
0
        m += (int)sizeof(h2n->one_setting);
762
0
      }
763
0
    n = lws_h2_frame_write(wsi, LWS_H2_FRAME_TYPE_SETTINGS,
764
0
               flags, LWS_H2_STREAM_ID_MASTER, (unsigned int)m,
765
0
                   &set[LWS_PRE]);
766
0
    if (n != m) {
767
0
      lwsl_info("send %d %d\n", n, m);
768
0
      goto bail;
769
0
    }
770
0
    break;
771
772
0
  case LWS_H2_PPS_SETTINGS_INITIAL_UPDATE_WINDOW:
773
0
    q = &set[LWS_PRE];
774
0
    *q++ = (uint8_t)(H2SET_INITIAL_WINDOW_SIZE >> 8);
775
0
    *q++ = (uint8_t)(H2SET_INITIAL_WINDOW_SIZE);
776
0
    *q++ = (uint8_t)(pps->u.update_window.credit >> 24);
777
0
    *q++ = (uint8_t)(pps->u.update_window.credit >> 16);
778
0
    *q++ = (uint8_t)(pps->u.update_window.credit >> 8);
779
0
    *q = (uint8_t)(pps->u.update_window.credit);
780
781
0
    lwsl_debug("%s: resetting initial window to %d\n", __func__,
782
0
        (int)pps->u.update_window.credit);
783
784
0
    n = lws_h2_frame_write(wsi, LWS_H2_FRAME_TYPE_SETTINGS,
785
0
               flags, LWS_H2_STREAM_ID_MASTER, 6,
786
0
                   &set[LWS_PRE]);
787
0
    if (n != 6) {
788
0
      lwsl_info("send %d %d\n", n, m);
789
0
      goto bail;
790
0
    }
791
0
    break;
792
793
0
  case LWS_H2_PPS_ACK_SETTINGS:
794
    /* send ack ... always empty */
795
0
    n = lws_h2_frame_write(wsi, LWS_H2_FRAME_TYPE_SETTINGS, 1,
796
0
               LWS_H2_STREAM_ID_MASTER, 0,
797
0
               &set[LWS_PRE]);
798
0
    if (n) {
799
0
      lwsl_err("%s: writing settings ack frame failed %d\n", __func__, n);
800
0
      goto bail;
801
0
    }
802
0
    wsi->h2_acked_settings = 0;
803
    /* this is the end of the preface dance then? */
804
0
    if (lwsi_state(wsi) == LRS_H2_AWAIT_SETTINGS) {
805
0
      lwsi_set_state(wsi, LRS_ESTABLISHED);
806
0
#if defined(LWS_WITH_FILE_OPS)
807
0
      wsi->http.fop_fd = NULL;
808
0
#endif
809
0
      if (lws_is_ssl(lws_get_network_wsi(wsi)))
810
0
        break;
811
812
0
      if (wsi->a.vhost->options &
813
0
        LWS_SERVER_OPTION_H2_PRIOR_KNOWLEDGE)
814
0
        break;
815
816
      /*
817
       * we need to treat the headers from the upgrade as the
818
       * first job.  So these need to get shifted to sid 1.
819
       */
820
821
0
      lws_context_lock(wsi->a.context, "h2 mig");
822
0
      lws_vhost_lock(wsi->a.vhost);
823
824
0
      h2n->swsi = __lws_wsi_server_new(wsi->a.vhost, wsi, 1);
825
826
0
      lws_vhost_unlock(wsi->a.vhost);
827
0
      lws_context_unlock(wsi->a.context);
828
829
0
      if (!h2n->swsi)
830
0
        goto bail;
831
832
      /* pass on the initial headers to SID 1 */
833
0
      h2n->swsi->http.ah = wsi->http.ah;
834
0
      wsi->http.ah = NULL;
835
836
0
      lwsl_info("%s: inherited headers %p\n", __func__,
837
0
          h2n->swsi->http.ah);
838
0
      h2n->swsi->txc.tx_cr = (int32_t)
839
0
        h2n->our_set.s[H2SET_INITIAL_WINDOW_SIZE];
840
0
      lwsl_info("initial tx credit on %s: %d\n",
841
0
          lws_wsi_tag(h2n->swsi),
842
0
          (int)h2n->swsi->txc.tx_cr);
843
0
      h2n->swsi->h2.initialized = 1;
844
      /* demanded by HTTP2 */
845
0
      h2n->swsi->h2.END_STREAM = 1;
846
0
      lwsl_info("servicing initial http request\n");
847
848
0
#if defined(LWS_WITH_SERVER)
849
0
      if (lws_http_action(h2n->swsi))
850
0
        goto bail;
851
0
#endif
852
0
      break;
853
0
    }
854
0
    break;
855
856
  /*
857
   * h2 only has PING... ACK = 0 = ping, ACK = 1 = pong
858
   */
859
860
0
  case LWS_H2_PPS_PING:
861
0
  case LWS_H2_PPS_PONG:
862
0
    if (pps->type == LWS_H2_PPS_PING)
863
0
      lwsl_info("sending PING\n");
864
0
    else {
865
0
      lwsl_info("sending PONG\n");
866
0
      flags = LWS_H2_FLAG_SETTINGS_ACK;
867
0
    }
868
869
0
    memcpy(&set[LWS_PRE], pps->u.ping.ping_payload, 8);
870
0
    n = lws_h2_frame_write(wsi, LWS_H2_FRAME_TYPE_PING, flags,
871
0
               LWS_H2_STREAM_ID_MASTER, 8,
872
0
               &set[LWS_PRE]);
873
0
    if (n != 8)
874
0
      goto bail;
875
876
0
    break;
877
878
0
  case LWS_H2_PPS_GOAWAY:
879
0
    lwsl_info("LWS_H2_PPS_GOAWAY\n");
880
0
    *p++ = (uint8_t)(pps->u.ga.highest_sid >> 24);
881
0
    *p++ = (uint8_t)(pps->u.ga.highest_sid >> 16);
882
0
    *p++ = (uint8_t)(pps->u.ga.highest_sid >> 8);
883
0
    *p++ = (uint8_t)(pps->u.ga.highest_sid);
884
0
    *p++ = (uint8_t)(pps->u.ga.err >> 24);
885
0
    *p++ = (uint8_t)(pps->u.ga.err >> 16);
886
0
    *p++ = (uint8_t)(pps->u.ga.err >> 8);
887
0
    *p++ = (uint8_t)(pps->u.ga.err);
888
0
    q = (unsigned char *)pps->u.ga.str;
889
0
    n = 0;
890
0
    while (*q && n++ < (int)sizeof(pps->u.ga.str))
891
0
      *p++ = *q++;
892
0
    h2n->we_told_goaway = 1;
893
0
    n = lws_h2_frame_write(wsi, LWS_H2_FRAME_TYPE_GOAWAY, 0,
894
0
               LWS_H2_STREAM_ID_MASTER,
895
0
               (unsigned int)lws_ptr_diff(p, &set[LWS_PRE]),
896
0
               &set[LWS_PRE]);
897
0
    if (n != 4) {
898
0
      lwsl_info("send %d %d\n", n, m);
899
0
      goto bail;
900
0
    }
901
0
    goto bail;
902
903
0
  case LWS_H2_PPS_RST_STREAM:
904
0
    lwsl_info("LWS_H2_PPS_RST_STREAM\n");
905
0
    *p++ = (uint8_t)(pps->u.rs.err >> 24);
906
0
    *p++ = (uint8_t)(pps->u.rs.err >> 16);
907
0
    *p++ = (uint8_t)(pps->u.rs.err >> 8);
908
0
    *p++ = (uint8_t)(pps->u.rs.err);
909
0
    n = lws_h2_frame_write(wsi, LWS_H2_FRAME_TYPE_RST_STREAM,
910
0
               0, pps->u.rs.sid, 4, &set[LWS_PRE]);
911
0
    if (n != 4) {
912
0
      lwsl_info("send %d %d\n", n, m);
913
0
      goto bail;
914
0
    }
915
0
    cwsi = lws_wsi_mux_from_id(wsi, pps->u.rs.sid);
916
0
    if (cwsi) {
917
0
      lwsl_debug("%s: closing cwsi %s %s %s (wsi %s)\n",
918
0
           __func__, lws_wsi_tag(cwsi),
919
0
           cwsi->role_ops->name,
920
0
           cwsi->a.protocol->name, lws_wsi_tag(wsi));
921
0
      lws_close_free_wsi(cwsi, 0, "reset stream");
922
0
    }
923
0
    break;
924
925
0
  case LWS_H2_PPS_UPDATE_WINDOW:
926
0
    lwsl_info("Issuing LWS_H2_PPS_UPDATE_WINDOW: sid %d: add %d\n",
927
0
          (int)pps->u.update_window.sid,
928
0
          (int)pps->u.update_window.credit);
929
0
    *p++ = (uint8_t)((pps->u.update_window.credit >> 24) & 0x7f); /* 31b */
930
0
    *p++ = (uint8_t)(pps->u.update_window.credit >> 16);
931
0
    *p++ = (uint8_t)(pps->u.update_window.credit >> 8);
932
0
    *p++ = (uint8_t)(pps->u.update_window.credit);
933
0
    n = lws_h2_frame_write(wsi, LWS_H2_FRAME_TYPE_WINDOW_UPDATE,
934
0
               0, pps->u.update_window.sid, 4,
935
0
               &set[LWS_PRE]);
936
0
    if (n != 4) {
937
0
      lwsl_info("send %d %d\n", n, m);
938
0
      goto bail;
939
0
    }
940
0
    break;
941
942
0
  default:
943
0
    break;
944
0
  }
945
946
0
  lws_free(pps);
947
948
0
  return 0;
949
950
0
bail:
951
0
  lws_free(pps);
952
953
0
  return 1;
954
0
}
955
956
static int
957
lws_h2_parse_end_of_frame(struct lws *wsi);
958
959
/*
960
 * The frame header part has just completely arrived.
961
 * Perform actions for header completion.
962
 */
963
static int
964
lws_h2_parse_frame_header(struct lws *wsi)
965
0
{
966
0
  struct lws_h2_netconn *h2n = wsi->h2.h2n;
967
0
  struct lws_h2_protocol_send *pps;
968
0
  int n;
969
970
  /*
971
   * We just got the frame header
972
   */
973
0
  h2n->count = 0;
974
0
  h2n->swsi = wsi;
975
  /* b31 is a reserved bit */
976
0
  h2n->sid = h2n->sid & 0x7fffffff;
977
978
0
  if (h2n->sid && !(h2n->sid & 1)) {
979
0
    char pes[32];
980
0
    lws_snprintf(pes, sizeof(pes), "Even Stream ID 0x%x", (unsigned int)h2n->sid);
981
0
    lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR, pes);
982
983
0
    return 0;
984
0
  }
985
986
  /* let the network wsi live a bit longer if subs are active */
987
988
0
  if (!wsi->immortal_substream_count) {
989
0
    int ds = lws_wsi_keepalive_timeout_eff(wsi);
990
991
    /*
992
     * A short (5s) timeout here affects the reverse proxy if
993
     * the onward box takes a long time to respond, eg to a POST.
994
     * The mount can override the keepalive timeout, eg, to give
995
     * the right behaviour depending on reverse proxy for a particular
996
     * server.
997
     */
998
0
    lws_set_timeout(wsi, PENDING_TIMEOUT_HTTP_KEEPALIVE_IDLE, ds);
999
0
  }
1000
0
  if (h2n->sid)
1001
0
    h2n->swsi = lws_wsi_mux_from_id(wsi, h2n->sid);
1002
1003
0
  lwsl_debug("%s (%s): fr hdr: typ 0x%x, fla 0x%x, sid 0x%x, len 0x%x\n",
1004
0
      lws_wsi_tag(wsi), lws_wsi_tag(h2n->swsi), h2n->type,
1005
0
      h2n->flags, (unsigned int)h2n->sid, (unsigned int)h2n->length);
1006
1007
0
  if (h2n->we_told_goaway && h2n->sid > h2n->highest_sid)
1008
0
    h2n->type = LWS_H2_FRAME_TYPE_COUNT; /* ie, IGNORE */
1009
1010
0
  if (h2n->type >= LWS_H2_FRAME_TYPE_COUNT) {
1011
0
    lwsl_info("%s: ignoring unknown frame type %d (len %d)\n", __func__, h2n->type, (unsigned int)h2n->length);
1012
    /* we MUST ignore frames we don't understand */
1013
0
    h2n->type = LWS_H2_FRAME_TYPE_COUNT;
1014
0
  }
1015
1016
  /*
1017
   * Even if we have decided to logically ignore this frame, we must
1018
   * consume the correct "frame length" amount of data to retain sync
1019
   */
1020
1021
0
  if (h2n->length > h2n->our_set.s[H2SET_MAX_FRAME_SIZE]) {
1022
    /*
1023
     * peer sent us something bigger than we told
1024
     * it we would allow
1025
     */
1026
0
    lwsl_info("%s: received oversize frame %d\n", __func__,
1027
0
        (unsigned int)h2n->length);
1028
0
    lws_h2_goaway(wsi, H2_ERR_FRAME_SIZE_ERROR,
1029
0
            "Peer ignored our frame size setting");
1030
0
    return 1;
1031
0
  }
1032
1033
0
  if (h2n->swsi)
1034
0
    lwsl_info("%s: %s, State: %s, received cmd %d\n",
1035
0
      __func__, lws_wsi_tag(h2n->swsi),
1036
0
      h2_state_names[h2n->swsi->h2.h2_state], h2n->type);
1037
0
  else {
1038
    /* if it's data, either way no swsi means CLOSED state */
1039
0
    if (h2n->type == LWS_H2_FRAME_TYPE_DATA) {
1040
0
      if (h2n->sid <= h2n->highest_sid_opened
1041
0
#if defined(LWS_WITH_CLIENT)
1042
0
          && wsi->client_h2_alpn
1043
0
#endif
1044
0
      ) {
1045
0
        if (h2n->flags & LWS_H2_FLAG_END_STREAM)
1046
0
          lwsl_notice("%s: stragging EOS\n", __func__);
1047
0
        else {
1048
0
          lwsl_wsi_notice(wsi, "ignoring straggling "
1049
0
            "DATA (flags 0x%x, length %d)",
1050
0
              h2n->flags, (int)h2n->length);
1051
          /* ie, IGNORE */
1052
0
          h2n->type = LWS_H2_FRAME_TYPE_COUNT;
1053
0
        }
1054
0
      } else {
1055
0
        lwsl_info("%s: received %d bytes data for unknown sid %d, highest known %d\n",
1056
0
            __func__, (int)h2n->length, (int)h2n->sid, (int)h2n->highest_sid_opened);
1057
1058
//        if (h2n->sid > h2n->highest_sid_opened) {
1059
0
        lws_h2_goaway(wsi, H2_ERR_STREAM_CLOSED,
1060
0
              "Data for nonexistent sid");
1061
0
        return 0;
1062
//        }
1063
0
      }
1064
0
    }
1065
    /* if the sid is credible, treat as wsi for it closed */
1066
0
    if (h2n->sid > h2n->highest_sid_opened &&
1067
0
        h2n->type != LWS_H2_FRAME_TYPE_HEADERS &&
1068
0
        h2n->type != LWS_H2_FRAME_TYPE_PRIORITY) {
1069
      /* if not credible, reject it */
1070
0
      lwsl_info("%s: %s, No child for sid %d, rxcmd %d\n",
1071
0
        __func__, lws_wsi_tag(h2n->swsi), (unsigned int)h2n->sid, h2n->type);
1072
0
      lws_h2_goaway(wsi, H2_ERR_STREAM_CLOSED,
1073
0
             "Data for nonexistent sid");
1074
0
      return 0;
1075
0
    }
1076
0
  }
1077
1078
0
  if (h2n->swsi && h2n->sid && h2n->type != LWS_H2_FRAME_TYPE_COUNT &&
1079
0
      !(http2_rx_validity[h2n->swsi->h2.h2_state] & (1 << h2n->type))) {
1080
0
    lwsl_info("%s: %s, State: %s, ILLEGAL cmdrx %d (OK 0x%x)\n",
1081
0
        __func__, lws_wsi_tag(h2n->swsi),
1082
0
        h2_state_names[h2n->swsi->h2.h2_state], h2n->type,
1083
0
        http2_rx_validity[h2n->swsi->h2.h2_state]);
1084
1085
0
    if (h2n->swsi->h2.h2_state == LWS_H2_STATE_CLOSED ||
1086
0
        h2n->swsi->h2.h2_state == LWS_H2_STATE_HALF_CLOSED_REMOTE)
1087
0
      n = H2_ERR_STREAM_CLOSED;
1088
0
    else
1089
0
      n = H2_ERR_PROTOCOL_ERROR;
1090
0
    lws_h2_goaway(wsi, (unsigned int)n, "invalid rx for state");
1091
1092
0
    return 0;
1093
0
  }
1094
1095
0
  if (h2n->cont_exp && h2n->type != LWS_H2_FRAME_TYPE_COUNT &&
1096
0
      (h2n->cont_exp_sid != h2n->sid ||
1097
0
            h2n->type != LWS_H2_FRAME_TYPE_CONTINUATION)) {
1098
0
    lwsl_info("%s: expected cont on sid %u (got %d on sid %u)\n",
1099
0
        __func__, (unsigned int)h2n->cont_exp_sid, h2n->type,
1100
0
        (unsigned int)h2n->sid);
1101
0
    h2n->cont_exp = 0;
1102
0
    if (h2n->cont_exp_headers)
1103
0
      n = H2_ERR_COMPRESSION_ERROR;
1104
0
    else
1105
0
      n = H2_ERR_PROTOCOL_ERROR;
1106
0
    lws_h2_goaway(wsi, (unsigned int)n, "Continuation hdrs State");
1107
1108
0
    return 0;
1109
0
  }
1110
1111
0
  switch (h2n->type) {
1112
0
  case LWS_H2_FRAME_TYPE_DATA:
1113
0
    lwsl_info("seen incoming LWS_H2_FRAME_TYPE_DATA start\n");
1114
0
    if (!h2n->sid) {
1115
0
      lwsl_info("DATA: 0 sid\n");
1116
0
      lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR, "DATA 0 sid");
1117
0
      break;
1118
0
    }
1119
0
    lwsl_info("Frame header DATA: sid %u, flags 0x%x, len %u\n",
1120
0
        (unsigned int)h2n->sid, h2n->flags,
1121
0
        (unsigned int)h2n->length);
1122
1123
0
    if (!h2n->swsi) {
1124
0
      lwsl_notice("DATA: NULL swsi\n");
1125
0
      break;
1126
0
    }
1127
1128
0
    lwsl_info("DATA rx on state %d\n", h2n->swsi->h2.h2_state);
1129
1130
0
    if (
1131
0
        h2n->swsi->h2.h2_state == LWS_H2_STATE_HALF_CLOSED_REMOTE ||
1132
0
        h2n->swsi->h2.h2_state == LWS_H2_STATE_CLOSED) {
1133
0
      lws_h2_goaway(wsi, H2_ERR_STREAM_CLOSED, "conn closed");
1134
0
      break;
1135
0
    }
1136
1137
0
    if (h2n->length == 0)
1138
0
      lws_h2_parse_end_of_frame(wsi);
1139
1140
0
    break;
1141
1142
0
  case LWS_H2_FRAME_TYPE_PRIORITY:
1143
0
    lwsl_info("LWS_H2_FRAME_TYPE_PRIORITY complete frame\n");
1144
0
    if (!h2n->sid) {
1145
0
      lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR,
1146
0
              "Priority has 0 sid");
1147
0
      break;
1148
0
    }
1149
0
    if (h2n->length != 5) {
1150
0
      lws_h2_goaway(wsi, H2_ERR_FRAME_SIZE_ERROR,
1151
0
              "Priority has length other than 5");
1152
0
      break;
1153
0
    }
1154
0
    break;
1155
0
  case LWS_H2_FRAME_TYPE_PUSH_PROMISE:
1156
0
    lwsl_info("LWS_H2_FRAME_TYPE_PUSH_PROMISE complete frame\n");
1157
0
    lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR, "Server only");
1158
0
    break;
1159
1160
0
  case LWS_H2_FRAME_TYPE_GOAWAY:
1161
0
    lwsl_debug("LWS_H2_FRAME_TYPE_GOAWAY received\n");
1162
0
    break;
1163
1164
0
  case LWS_H2_FRAME_TYPE_RST_STREAM:
1165
0
    if (!h2n->sid)
1166
0
      return 1;
1167
0
    if (!h2n->swsi) {
1168
0
      if (h2n->sid <= h2n->highest_sid_opened)
1169
0
        break;
1170
0
      lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR,
1171
0
              "crazy sid on RST_STREAM");
1172
0
      return 1;
1173
0
    }
1174
0
    if (h2n->length != 4) {
1175
0
      lws_h2_goaway(wsi, H2_ERR_FRAME_SIZE_ERROR,
1176
0
              "RST_STREAM can only be length 4");
1177
0
      break;
1178
0
    }
1179
0
    lws_h2_state(h2n->swsi, LWS_H2_STATE_CLOSED);
1180
0
    break;
1181
1182
0
  case LWS_H2_FRAME_TYPE_SETTINGS:
1183
0
    lwsl_info("LWS_H2_FRAME_TYPE_SETTINGS complete frame\n");
1184
    /* nonzero sid on settings is illegal */
1185
0
    if (h2n->sid) {
1186
0
      lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR,
1187
0
           "Settings has nonzero sid");
1188
0
      break;
1189
0
    }
1190
1191
0
    if (!(h2n->flags & LWS_H2_FLAG_SETTINGS_ACK)) {
1192
0
      if (h2n->length % 6) {
1193
0
        lws_h2_goaway(wsi, H2_ERR_FRAME_SIZE_ERROR,
1194
0
             "Settings length error");
1195
0
        break;
1196
0
      }
1197
1198
0
      if (h2n->type == LWS_H2_FRAME_TYPE_COUNT)
1199
0
        return 0;
1200
1201
0
      if (wsi->upgraded_to_http2 &&
1202
0
#if defined(LWS_WITH_CLIENT)
1203
0
          (!(wsi->flags & LCCSCF_H2_QUIRK_NGHTTP2_END_STREAM) ||
1204
#else
1205
          (
1206
#endif
1207
0
              !wsi->h2_acked_settings)) {
1208
1209
0
        pps = lws_h2_new_pps(LWS_H2_PPS_ACK_SETTINGS);
1210
0
        if (!pps)
1211
0
          return 1;
1212
0
        lws_pps_schedule(wsi, pps);
1213
0
        wsi->h2_acked_settings = 1;
1214
0
      }
1215
0
      break;
1216
0
    }
1217
    /* came to us with ACK set... not allowed to have payload */
1218
1219
0
    if (h2n->length) {
1220
0
      lws_h2_goaway(wsi, H2_ERR_FRAME_SIZE_ERROR,
1221
0
              "Settings with ACK not allowed payload");
1222
0
      break;
1223
0
    }
1224
0
    break;
1225
0
  case LWS_H2_FRAME_TYPE_PING:
1226
0
    if (h2n->sid) {
1227
0
      lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR,
1228
0
              "Ping has nonzero sid");
1229
0
      break;
1230
0
    }
1231
0
    if (h2n->length != 8) {
1232
0
      lws_h2_goaway(wsi, H2_ERR_FRAME_SIZE_ERROR,
1233
0
              "Ping payload can only be 8");
1234
0
      break;
1235
0
    }
1236
0
    break;
1237
0
  case LWS_H2_FRAME_TYPE_CONTINUATION:
1238
0
    lwsl_info("LWS_H2_FRAME_TYPE_CONTINUATION: sid = %u %d %d\n",
1239
0
        (unsigned int)h2n->sid, (int)h2n->cont_exp,
1240
0
        (int)h2n->cont_exp_sid);
1241
1242
0
    if (!h2n->cont_exp ||
1243
0
         h2n->cont_exp_sid != h2n->sid ||
1244
0
         !h2n->sid ||
1245
0
         !h2n->swsi) {
1246
0
      lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR,
1247
0
              "unexpected CONTINUATION");
1248
0
      break;
1249
0
    }
1250
1251
0
    if (h2n->swsi->h2.END_HEADERS) {
1252
0
      lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR,
1253
0
              "END_HEADERS already seen");
1254
0
      break;
1255
0
    }
1256
    /* END_STREAM is in HEADERS, skip resetting it */
1257
0
    goto update_end_headers;
1258
1259
0
  case LWS_H2_FRAME_TYPE_HEADERS:
1260
0
    h2n->hpack_total_hdr_len = 0;
1261
0
    lwsl_info("HEADERS: frame header: sid = %u\n",
1262
0
        (unsigned int)h2n->sid);
1263
0
    if (!h2n->sid) {
1264
0
      lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR, "sid 0");
1265
0
      return 1;
1266
0
    }
1267
1268
0
    if (h2n->swsi && !h2n->swsi->h2.END_STREAM &&
1269
0
        h2n->swsi->h2.END_HEADERS &&
1270
0
        !(h2n->flags & LWS_H2_FLAG_END_STREAM)) {
1271
0
      lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR,
1272
0
              "extra HEADERS together");
1273
0
      return 1;
1274
0
    }
1275
1276
0
#if defined(LWS_WITH_CLIENT)
1277
0
    if (wsi->client_h2_alpn) {
1278
0
      if (h2n->sid) {
1279
0
        h2n->swsi = lws_wsi_mux_from_id(wsi, h2n->sid);
1280
0
        lwsl_info("HEADERS: nwsi %s: sid %u mapped "
1281
0
            "to wsi %s\n", lws_wsi_tag(wsi),
1282
0
            (unsigned int)h2n->sid,
1283
0
            lws_wsi_tag(h2n->swsi));
1284
0
        if (!h2n->swsi)
1285
0
          break;
1286
0
      }
1287
0
      goto update_end_headers;
1288
0
    }
1289
0
#endif
1290
1291
0
    if (!h2n->swsi) {
1292
      /* no more children allowed by parent */
1293
0
      if (wsi->mux.child_count + 1 >
1294
0
          wsi->h2.h2n->our_set.s[H2SET_MAX_CONCURRENT_STREAMS]) {
1295
0
        lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR,
1296
0
        "Another stream not allowed");
1297
1298
0
        return 1;
1299
0
      }
1300
1301
      /*
1302
       * The peer has sent us a HEADERS implying the creation
1303
       * of a new stream
1304
       */
1305
1306
0
      lws_context_lock(wsi->a.context, "h2 new str");
1307
0
      lws_vhost_lock(wsi->a.vhost);
1308
1309
0
      h2n->swsi = __lws_wsi_server_new(wsi->a.vhost, wsi,
1310
0
                     h2n->sid);
1311
1312
0
      lws_vhost_unlock(wsi->a.vhost);
1313
0
      lws_context_unlock(wsi->a.context);
1314
1315
0
      if (!h2n->swsi) {
1316
0
        lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR,
1317
0
                "OOM");
1318
1319
0
        return 1;
1320
0
      }
1321
1322
0
      if (h2n->sid >= h2n->highest_sid)
1323
0
        h2n->highest_sid = h2n->sid + 2;
1324
1325
0
      h2n->swsi->h2.initialized = 1;
1326
1327
0
      if (lws_h2_update_peer_txcredit(h2n->swsi,
1328
0
          h2n->swsi->mux.my_sid, 4 * 65536))
1329
0
        goto cleanup_wsi;
1330
0
    }
1331
1332
    /*
1333
     * ah needs attaching to child wsi, even though
1334
     * we only fill it from network wsi
1335
     */
1336
0
    if (!h2n->swsi->http.ah)
1337
0
      if (lws_header_table_attach(h2n->swsi, 0)) {
1338
0
        lwsl_err("%s: Failed to get ah\n", __func__);
1339
0
        return 1;
1340
0
      }
1341
1342
    /*
1343
     * The first use of a new stream identifier implicitly closes
1344
     * all streams in the "idle" state that might have been
1345
     * initiated by that peer with a lower-valued stream identifier.
1346
     *
1347
     * For example, if a client sends a HEADERS frame on stream 7
1348
     * without ever sending a frame on stream 5, then stream 5
1349
     * transitions to the "closed" state when the first frame for
1350
     * stream 7 is sent or received.
1351
     */
1352
0
    lws_start_foreach_ll(struct lws *, w, wsi->mux.child_list) {
1353
0
      if (w->mux.my_sid < h2n->sid &&
1354
0
          w->h2.h2_state == LWS_H2_STATE_IDLE)
1355
0
        lws_close_free_wsi(w, 0, "h2 sid close");
1356
0
      assert(w->mux.sibling_list != w);
1357
0
    } lws_end_foreach_ll(w, mux.sibling_list);
1358
1359
0
    h2n->cont_exp = !(h2n->flags & LWS_H2_FLAG_END_HEADERS);
1360
0
    h2n->cont_exp_sid = h2n->sid;
1361
0
    h2n->cont_exp_headers = 1;
1362
  //  lws_header_table_reset(h2n->swsi, 0);
1363
1364
0
update_end_headers:
1365
0
    if (lws_check_opt(h2n->swsi->a.vhost->options,
1366
0
             LWS_SERVER_OPTION_VH_H2_HALF_CLOSED_LONG_POLL)) {
1367
1368
      /*
1369
       * We don't directly timeout streams that enter the
1370
       * half-closed remote state, allowing immortal long
1371
       * poll
1372
       */
1373
0
      lws_mux_mark_immortal(h2n->swsi);
1374
0
      lwsl_info("%s: %s: h2 stream entering long poll\n",
1375
0
          __func__, lws_wsi_tag(h2n->swsi));
1376
1377
0
    } else {
1378
0
      h2n->swsi->h2.END_STREAM =
1379
0
          !!(h2n->flags & LWS_H2_FLAG_END_STREAM);
1380
0
      lwsl_debug("%s: hdr END_STREAM = %d\n",__func__,
1381
0
        h2n->swsi->h2.END_STREAM);
1382
0
    }
1383
1384
    /* no END_HEADERS means CONTINUATION must come */
1385
0
    h2n->swsi->h2.END_HEADERS =
1386
0
        !!(h2n->flags & LWS_H2_FLAG_END_HEADERS);
1387
0
    lwsl_info("%s: %s: END_HEADERS %d\n", __func__, lws_wsi_tag(h2n->swsi),
1388
0
        h2n->swsi->h2.END_HEADERS);
1389
0
    if (h2n->swsi->h2.END_HEADERS)
1390
0
      h2n->cont_exp = 0;
1391
0
    lwsl_debug("END_HEADERS %d\n", h2n->swsi->h2.END_HEADERS);
1392
0
    break;
1393
1394
0
cleanup_wsi:
1395
1396
0
    return 1;
1397
1398
0
  case LWS_H2_FRAME_TYPE_WINDOW_UPDATE:
1399
0
    if (h2n->length != 4) {
1400
0
      lws_h2_goaway(wsi, H2_ERR_FRAME_SIZE_ERROR,
1401
0
              "window update frame not 4");
1402
0
      break;
1403
0
    }
1404
0
    lwsl_info("LWS_H2_FRAME_TYPE_WINDOW_UPDATE\n");
1405
0
    break;
1406
0
  case LWS_H2_FRAME_TYPE_COUNT:
1407
0
    if (h2n->length == 0)
1408
0
      lws_h2_parse_end_of_frame(wsi);
1409
0
    else
1410
0
      lwsl_debug("%s: going on to deal with unknown frame remaining len %d\n", __func__, (unsigned int)h2n->length);
1411
0
    break;
1412
0
  default:
1413
0
    lwsl_info("%s: ILLEGAL FRAME TYPE %d\n", __func__, h2n->type);
1414
0
    h2n->type = LWS_H2_FRAME_TYPE_COUNT; /* ie, IGNORE */
1415
0
    break;
1416
0
  }
1417
0
  if (h2n->length == 0)
1418
0
    h2n->frame_state = 0;
1419
1420
0
  return 0;
1421
0
}
1422
1423
static const char * const method_names[] = {
1424
  "GET", "POST",
1425
#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS)
1426
  "OPTIONS", "PUT", "PATCH", "DELETE",
1427
#endif
1428
  "CONNECT", "HEAD"
1429
};
1430
static unsigned char method_index[] = {
1431
  WSI_TOKEN_GET_URI,
1432
  WSI_TOKEN_POST_URI,
1433
#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS)
1434
  WSI_TOKEN_OPTIONS_URI,
1435
  WSI_TOKEN_PUT_URI,
1436
  WSI_TOKEN_PATCH_URI,
1437
  WSI_TOKEN_DELETE_URI,
1438
#endif
1439
  WSI_TOKEN_CONNECT,
1440
  WSI_TOKEN_HEAD_URI,
1441
};
1442
1443
/*
1444
 * The last byte of the whole frame has been handled.
1445
 * Perform actions for frame completion.
1446
 *
1447
 * This is the crunch time for parsing that may have occured on a network
1448
 * wsi with a pending partial send... we may call lws_http_action() to send
1449
 * a response, conflicting with the partial.
1450
 *
1451
 * So in that case we change the wsi state and do the lws_http_action() in the
1452
 * WRITABLE handler as a priority.
1453
 */
1454
static int
1455
lws_h2_parse_end_of_frame(struct lws *wsi)
1456
0
{
1457
0
  struct lws_h2_netconn *h2n = wsi->h2.h2n;
1458
0
  struct lws *eff_wsi = wsi;
1459
0
  const char *p;
1460
0
  int n;
1461
1462
0
  h2n->frame_state = 0;
1463
0
  h2n->count = 0;
1464
1465
0
  if (h2n->sid)
1466
0
    h2n->swsi = lws_wsi_mux_from_id(wsi, h2n->sid);
1467
1468
0
  if (h2n->sid > h2n->highest_sid)
1469
0
    h2n->highest_sid = h2n->sid;
1470
1471
0
  if (h2n->collected_priority && (h2n->dep & ~(1u << 31)) == h2n->sid) {
1472
0
    lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR, "depends on own sid");
1473
0
    return 0;
1474
0
  }
1475
1476
0
  switch (h2n->type) {
1477
1478
0
  case LWS_H2_FRAME_TYPE_SETTINGS:
1479
1480
0
#if defined(LWS_WITH_CLIENT)
1481
0
    if (wsi->client_h2_alpn && !wsi->client_mux_migrated &&
1482
0
        !(h2n->flags & LWS_H2_FLAG_SETTINGS_ACK)) {
1483
0
      struct lws_h2_protocol_send *pps;
1484
1485
      /* migrate original client ask on to substream 1 */
1486
0
#if defined(LWS_WITH_FILE_OPS)
1487
0
      wsi->http.fop_fd = NULL;
1488
0
#endif
1489
0
      lwsl_info("%s: migrating\n", __func__);
1490
0
      wsi->client_mux_migrated = 1;
1491
      /*
1492
       * we need to treat the headers from the upgrade as the
1493
       * first job.  So these need to get shifted to sid 1.
1494
       */
1495
0
      lws_context_lock(wsi->a.context, "h2 mig");
1496
0
      lws_vhost_lock(wsi->a.vhost);
1497
1498
0
      h2n->swsi = __lws_wsi_server_new(wsi->a.vhost, wsi, 1);
1499
1500
0
      lws_vhost_unlock(wsi->a.vhost);
1501
0
      lws_context_unlock(wsi->a.context);
1502
1503
0
      if (!h2n->swsi)
1504
0
        return 1;
1505
0
      h2n->sid = 1;
1506
1507
0
      assert(lws_wsi_mux_from_id(wsi, 1) == h2n->swsi);
1508
1509
    //  lws_role_transition(wsi, LWSIFR_CLIENT,
1510
    //          LRS_H2_WAITING_TO_SEND_HEADERS,
1511
    //          &role_ops_h2);
1512
1513
0
      lws_role_transition(h2n->swsi, LWSIFR_CLIENT,
1514
0
              LRS_H2_WAITING_TO_SEND_HEADERS,
1515
0
              &role_ops_h2);
1516
1517
      /* pass on the initial headers to SID 1 */
1518
0
      h2n->swsi->http.ah = wsi->http.ah;
1519
#if defined(LWS_WITH_SYS_FAULT_INJECTION)
1520
      lws_fi_import(&h2n->swsi->fic, &wsi->fic);
1521
#endif
1522
0
      h2n->swsi->client_mux_substream = 1;
1523
0
      h2n->swsi->client_h2_alpn = 1;
1524
0
#if defined(LWS_WITH_CLIENT)
1525
0
      h2n->swsi->flags = wsi->flags;
1526
0
#if defined(LWS_WITH_CONMON)
1527
      /* sid1 needs to represent the connection experience
1528
       * ... we take over responsibility for the DNS list
1529
       * copy as well
1530
       */
1531
0
      h2n->swsi->conmon = wsi->conmon;
1532
0
      h2n->swsi->conmon_datum = wsi->conmon_datum;
1533
0
      h2n->swsi->sa46_peer = wsi->sa46_peer;
1534
0
      wsi->conmon.dns_results_copy = NULL;
1535
0
#endif
1536
0
#endif /* CLIENT */
1537
1538
0
#if defined(LWS_WITH_SECURE_STREAMS)
1539
0
      if (wsi->for_ss) {
1540
0
        lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi);
1541
1542
0
        if (!h)
1543
0
          return 1;
1544
0
        h2n->swsi->for_ss = 1;
1545
0
        wsi->for_ss = 0;
1546
1547
0
        if (h->wsi == wsi)
1548
0
          h->wsi = h2n->swsi;
1549
0
      }
1550
0
#endif
1551
1552
0
      h2n->swsi->a.protocol = wsi->a.protocol;
1553
0
      if (h2n->swsi->user_space &&
1554
0
          !h2n->swsi->user_space_externally_allocated)
1555
0
        lws_free(h2n->swsi->user_space);
1556
0
      h2n->swsi->user_space = wsi->user_space;
1557
0
      h2n->swsi->user_space_externally_allocated =
1558
0
          wsi->user_space_externally_allocated;
1559
0
      h2n->swsi->a.opaque_user_data = wsi->a.opaque_user_data;
1560
0
      wsi->a.opaque_user_data = NULL;
1561
0
      h2n->swsi->txc.manual_initial_tx_credit =
1562
0
          wsi->txc.manual_initial_tx_credit;
1563
1564
0
#if defined(LWS_WITH_TLS)
1565
0
      lws_strncpy(h2n->swsi->alpn, wsi->alpn,
1566
0
          sizeof(wsi->alpn));
1567
0
#endif
1568
1569
0
      wsi->user_space = NULL;
1570
1571
0
      if (h2n->swsi->http.ah)
1572
0
        h2n->swsi->http.ah->wsi = h2n->swsi;
1573
0
      wsi->http.ah = NULL;
1574
1575
0
      lwsl_info("%s: MIGRATING nwsi %s -> swsi %s\n", __func__,
1576
0
          lws_wsi_tag(wsi), lws_wsi_tag(h2n->swsi));
1577
0
      h2n->swsi->txc.tx_cr = (int32_t)
1578
0
        h2n->peer_set.s[H2SET_INITIAL_WINDOW_SIZE];
1579
0
      lwsl_info("%s: initial tx credit on %s: %d\n",
1580
0
          __func__, lws_wsi_tag(h2n->swsi),
1581
0
          (int)h2n->swsi->txc.tx_cr);
1582
0
      h2n->swsi->h2.initialized = 1;
1583
1584
      /* set our initial window size */
1585
0
      if (!wsi->h2.initialized) {
1586
0
        wsi->txc.tx_cr = (int32_t)
1587
0
             h2n->peer_set.s[H2SET_INITIAL_WINDOW_SIZE];
1588
1589
0
        lwsl_info("%s: initial tx credit for us to "
1590
0
            "write on nwsi %s: %d\n", __func__,
1591
0
            lws_wsi_tag(wsi), (int)wsi->txc.tx_cr);
1592
0
        wsi->h2.initialized = 1;
1593
0
      }
1594
1595
0
      lws_callback_on_writable(h2n->swsi);
1596
1597
0
      if (!wsi->h2_acked_settings ||
1598
0
          !(wsi->flags & LCCSCF_H2_QUIRK_NGHTTP2_END_STREAM)
1599
0
      ) {
1600
0
        pps = lws_h2_new_pps(LWS_H2_PPS_ACK_SETTINGS);
1601
0
        if (!pps)
1602
0
          return 1;
1603
0
        lws_pps_schedule(wsi, pps);
1604
0
        lwsl_info("%s: SETTINGS ack PPS\n", __func__);
1605
0
        wsi->h2_acked_settings = 1;
1606
0
      }
1607
1608
      /* also attach any queued guys */
1609
1610
0
      lws_wsi_mux_apply_queue(wsi);
1611
0
    }
1612
0
#endif
1613
0
    break;
1614
1615
0
  case LWS_H2_FRAME_TYPE_CONTINUATION:
1616
0
  case LWS_H2_FRAME_TYPE_HEADERS:
1617
1618
0
    if (!h2n->swsi)
1619
0
      break;
1620
1621
    /* service the http request itself */
1622
1623
0
    if (h2n->last_action_dyntable_resize) {
1624
0
      lws_h2_goaway(wsi, H2_ERR_COMPRESSION_ERROR,
1625
0
        "dyntable resize last in headers");
1626
0
      break;
1627
0
    }
1628
1629
0
    if (!h2n->swsi->h2.END_HEADERS) {
1630
      /* we are not finished yet */
1631
0
      lwsl_info("withholding http action for continuation\n");
1632
0
      h2n->cont_exp_sid = h2n->sid;
1633
0
      h2n->cont_exp = 1;
1634
0
      break;
1635
0
    }
1636
1637
    /* confirm the hpack stream state is reasonable for finishing */
1638
1639
0
    if (h2n->hpack != HPKS_TYPE) {
1640
      /* hpack incomplete */
1641
0
      lwsl_info("hpack incomplete %d (type %d, len %u)\n",
1642
0
          h2n->hpack, h2n->type,
1643
0
          (unsigned int)h2n->hpack_len);
1644
0
      lws_h2_goaway(wsi, H2_ERR_COMPRESSION_ERROR,
1645
0
              "hpack incomplete");
1646
0
      break;
1647
0
    }
1648
1649
    /* this is the last part of HEADERS */
1650
0
    switch (h2n->swsi->h2.h2_state) {
1651
0
    case LWS_H2_STATE_IDLE:
1652
0
      lws_h2_state(h2n->swsi, LWS_H2_STATE_OPEN);
1653
0
      break;
1654
0
    case LWS_H2_STATE_RESERVED_REMOTE:
1655
0
      lws_h2_state(h2n->swsi, LWS_H2_STATE_HALF_CLOSED_LOCAL);
1656
0
      break;
1657
0
    }
1658
1659
0
    lwsl_info("http req, %s, h2n->swsi=%s\n", lws_wsi_tag(wsi),
1660
0
        lws_wsi_tag(h2n->swsi));
1661
0
    h2n->swsi->hdr_parsing_completed = 1;
1662
1663
0
#if defined(LWS_WITH_CLIENT)
1664
0
    if (h2n->swsi->client_mux_substream &&
1665
0
        lws_client_interpret_server_handshake(h2n->swsi)) {
1666
      /*
1667
       * This is more complicated than it looks, one exit from
1668
       * interpret_server_handshake() is to do a close that
1669
       * turns into a redirect.
1670
       *
1671
       * In that case, the wsi survives having being reset
1672
       * and detached from any h2 identity.  We need to get
1673
       * our parents out from touching it any more
1674
       */
1675
0
      lwsl_info("%s: cli int serv hs closed, or redir\n", __func__);
1676
0
      return 2;
1677
0
    }
1678
0
#endif
1679
1680
0
    if (lws_hdr_extant(h2n->swsi, WSI_TOKEN_HTTP_CONTENT_LENGTH)) {
1681
0
      const char *simp = lws_hdr_simple_ptr(h2n->swsi,
1682
0
                WSI_TOKEN_HTTP_CONTENT_LENGTH);
1683
1684
0
      if (!simp) /* coverity */
1685
0
        return 1;
1686
0
      {
1687
0
        long long cl_val = atoll(simp);
1688
0
        if (cl_val < 0)
1689
0
          return 1;
1690
0
        h2n->swsi->http.rx_content_length = (unsigned long long)cl_val;
1691
0
      }
1692
0
      h2n->swsi->http.rx_content_remain =
1693
0
          h2n->swsi->http.rx_content_length;
1694
0
      h2n->swsi->http.content_length_given = 1;
1695
0
      lwsl_info("setting rx_content_length %lld\n",
1696
0
          (long long)h2n->swsi->http.rx_content_length);
1697
0
    }
1698
1699
0
    {
1700
0
      int n = 0, len;
1701
0
      char buf[256];
1702
0
      const unsigned char *c;
1703
1704
0
      do {
1705
0
        c = lws_token_to_string((enum lws_token_indexes)n);
1706
0
        if (!c) {
1707
0
          n++;
1708
0
          continue;
1709
0
        }
1710
1711
0
        len = lws_hdr_total_length(h2n->swsi, (enum lws_token_indexes)n);
1712
0
        if (!len || len > (int)sizeof(buf) - 1) {
1713
0
          n++;
1714
0
          continue;
1715
0
        }
1716
1717
0
        if (lws_hdr_copy(h2n->swsi, buf, sizeof buf,
1718
0
            (enum lws_token_indexes)n) < 0) {
1719
0
          lwsl_info("    %s !oversize!\n",
1720
0
              (char *)c);
1721
0
        } else {
1722
0
          buf[sizeof(buf) - 1] = '\0';
1723
1724
0
          lwsl_info("    %s = %s\n",
1725
0
              (char *)c, buf);
1726
0
        }
1727
0
        n++;
1728
0
      } while (c);
1729
0
    }
1730
1731
0
    if (h2n->swsi->h2.h2_state == LWS_H2_STATE_HALF_CLOSED_REMOTE ||
1732
0
        h2n->swsi->h2.h2_state == LWS_H2_STATE_CLOSED) {
1733
0
      lws_h2_goaway(wsi, H2_ERR_STREAM_CLOSED,
1734
0
              "Banning service on CLOSED_REMOTE");
1735
0
      break;
1736
0
    }
1737
1738
0
    switch (h2n->swsi->h2.h2_state) {
1739
0
    case LWS_H2_STATE_IDLE:
1740
0
      lws_h2_state(h2n->swsi, LWS_H2_STATE_OPEN);
1741
0
      break;
1742
0
    case LWS_H2_STATE_OPEN:
1743
0
      if (h2n->swsi->h2.END_STREAM)
1744
0
        lws_h2_state(h2n->swsi,
1745
0
               LWS_H2_STATE_HALF_CLOSED_REMOTE);
1746
0
      break;
1747
0
    case LWS_H2_STATE_HALF_CLOSED_LOCAL:
1748
0
      if (h2n->swsi->h2.END_STREAM)
1749
        /*
1750
         * action the END_STREAM
1751
         */
1752
0
        lws_h2_state(h2n->swsi, LWS_H2_STATE_CLOSED);
1753
0
      break;
1754
0
    }
1755
1756
0
#if defined(LWS_WITH_CLIENT)
1757
1758
    /*
1759
     * If we already had the END_STREAM along with the END_HEADERS,
1760
     * we have already transitioned to STATE_CLOSED and we are not
1761
     * going to be doing anything further on this stream.
1762
     *
1763
     * In that case handle the transaction completion and
1764
     * finalize the stream for the peer
1765
     */
1766
1767
0
    if (h2n->swsi->h2.h2_state == LWS_H2_STATE_CLOSED &&
1768
0
      h2n->swsi->client_mux_substream) {
1769
1770
0
      lws_h2_rst_stream(h2n->swsi, H2_ERR_NO_ERROR,
1771
0
        "client done");
1772
1773
0
      if (lws_http_transaction_completed_client(h2n->swsi))
1774
0
        lwsl_debug("tx completed returned close\n");
1775
0
      break;
1776
0
    }
1777
1778
0
    if (h2n->swsi->client_mux_substream) {
1779
0
      lwsl_info("%s: %s: headers: client path (h2 state %s)\n",
1780
0
          __func__, lws_wsi_tag(wsi),
1781
0
          h2_state_names[h2n->swsi->h2.h2_state]);
1782
0
      break;
1783
0
    }
1784
0
#endif
1785
1786
0
    if (!lws_hdr_total_length(h2n->swsi, WSI_TOKEN_HTTP_COLON_PATH) ||
1787
0
        !lws_hdr_total_length(h2n->swsi, WSI_TOKEN_HTTP_COLON_METHOD) ||
1788
0
        !lws_hdr_total_length(h2n->swsi, WSI_TOKEN_HTTP_COLON_SCHEME) ||
1789
0
         lws_hdr_total_length(h2n->swsi, WSI_TOKEN_HTTP_COLON_STATUS) ||
1790
0
         lws_hdr_extant(h2n->swsi, WSI_TOKEN_CONNECTION)) {
1791
0
      lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR,
1792
0
              "Pseudoheader checks");
1793
0
      break;
1794
0
    }
1795
1796
0
    if (lws_hdr_extant(h2n->swsi, WSI_TOKEN_TE)) {
1797
0
      n = lws_hdr_total_length(h2n->swsi, WSI_TOKEN_TE);
1798
1799
0
      if (n != 8 ||
1800
0
          !lws_hdr_simple_ptr(h2n->swsi, WSI_TOKEN_TE) ||
1801
0
          strncmp(lws_hdr_simple_ptr(h2n->swsi, WSI_TOKEN_TE),
1802
0
          "trailers", (unsigned int)n)) {
1803
0
        lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR,
1804
0
                "Illegal transfer-encoding");
1805
0
        break;
1806
0
      }
1807
0
    }
1808
1809
#if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
1810
    lws_http_compression_validate(h2n->swsi);
1811
#endif
1812
1813
0
    p = lws_hdr_simple_ptr(h2n->swsi, WSI_TOKEN_HTTP_COLON_METHOD);
1814
    /*
1815
     * duplicate :path into the individual method uri header
1816
     * index, so that it looks the same as h1 in the ah
1817
     */
1818
0
    for (n = 0; n < (int)LWS_ARRAY_SIZE(method_names); n++)
1819
0
      if (p && !strcasecmp(p, method_names[n])) {
1820
0
        h2n->swsi->http.ah->frag_index[method_index[n]] =
1821
0
            h2n->swsi->http.ah->frag_index[
1822
0
                             WSI_TOKEN_HTTP_COLON_PATH];
1823
0
        break;
1824
0
      }
1825
1826
0
    {
1827
0
      lwsl_debug("%s: setting DEF_ACT from 0x%x\n", __func__,
1828
0
           (unsigned int)h2n->swsi->wsistate);
1829
0
      lwsi_set_state(h2n->swsi, LRS_DEFERRING_ACTION);
1830
0
      lws_callback_on_writable(h2n->swsi);
1831
0
    }
1832
0
    break;
1833
1834
0
  case LWS_H2_FRAME_TYPE_DATA:
1835
0
    lwsl_info("%s: DATA flags 0x%x\n", __func__, h2n->flags);
1836
0
    if (!h2n->swsi)
1837
0
      break;
1838
1839
0
    if (lws_hdr_total_length(h2n->swsi,
1840
0
           WSI_TOKEN_HTTP_CONTENT_LENGTH) &&
1841
0
        h2n->swsi->h2.END_STREAM &&
1842
0
        h2n->swsi->http.rx_content_length &&
1843
0
        h2n->swsi->http.rx_content_remain) {
1844
0
      lws_h2_rst_stream(h2n->swsi, H2_ERR_PROTOCOL_ERROR,
1845
0
            "Not enough rx content");
1846
0
      break;
1847
0
    }
1848
1849
0
    if (h2n->swsi->h2.END_STREAM &&
1850
0
        h2n->swsi->h2.h2_state == LWS_H2_STATE_OPEN)
1851
0
      lws_h2_state(h2n->swsi,
1852
0
             LWS_H2_STATE_HALF_CLOSED_REMOTE);
1853
1854
0
    if (h2n->swsi->h2.END_STREAM &&
1855
0
        h2n->swsi->h2.h2_state == LWS_H2_STATE_HALF_CLOSED_LOCAL)
1856
0
      lws_h2_state(h2n->swsi, LWS_H2_STATE_CLOSED);
1857
1858
0
#if defined(LWS_WITH_CLIENT)
1859
    /*
1860
     * client... remote END_STREAM implies we weren't going to
1861
     * send anything else anyway.
1862
     */
1863
1864
0
    if (h2n->swsi->client_mux_substream &&
1865
0
        (h2n->flags & LWS_H2_FLAG_END_STREAM)) {
1866
0
      lwsl_info("%s: %s: DATA: end stream\n",
1867
0
          __func__, lws_wsi_tag(h2n->swsi));
1868
1869
0
      if (h2n->swsi->h2.h2_state == LWS_H2_STATE_OPEN) {
1870
0
        lws_h2_state(h2n->swsi,
1871
0
               LWS_H2_STATE_HALF_CLOSED_REMOTE);
1872
    //    lws_h2_rst_stream(h2n->swsi, H2_ERR_NO_ERROR,
1873
    //          "client done");
1874
1875
    //    if (lws_http_transaction_completed_client(h2n->swsi))
1876
    //      lwsl_debug("tx completed returned close\n");
1877
0
      }
1878
1879
      //if (h2n->swsi->h2.h2_state == LWS_H2_STATE_HALF_CLOSED_LOCAL)
1880
0
      {
1881
0
        lws_h2_state(h2n->swsi, LWS_H2_STATE_CLOSED);
1882
1883
0
        lws_h2_rst_stream(h2n->swsi, H2_ERR_NO_ERROR,
1884
0
              "client done");
1885
1886
0
        if (lws_http_transaction_completed_client(h2n->swsi))
1887
0
          lwsl_debug("tx completed returned close\n");
1888
0
      }
1889
0
    }
1890
0
#endif
1891
0
    break;
1892
1893
0
  case LWS_H2_FRAME_TYPE_PING:
1894
0
    if (h2n->flags & LWS_H2_FLAG_SETTINGS_ACK)
1895
0
      lws_validity_confirmed(wsi);
1896
0
    else {
1897
      /* they're sending us a ping request */
1898
0
      struct lws_h2_protocol_send *pps =
1899
0
          lws_h2_new_pps(LWS_H2_PPS_PONG);
1900
0
      if (!pps)
1901
0
        return 1;
1902
1903
0
      lwsl_info("rx ping, preparing pong\n");
1904
1905
0
      memcpy(pps->u.ping.ping_payload, h2n->ping_payload, 8);
1906
0
      lws_pps_schedule(wsi, pps);
1907
0
    }
1908
1909
0
    break;
1910
1911
0
  case LWS_H2_FRAME_TYPE_WINDOW_UPDATE:
1912
    /*
1913
     * We only have an unsigned 31-bit (positive) increment possible
1914
     */
1915
0
    h2n->hpack_e_dep &= ~(1u << 31);
1916
0
    lwsl_info("WINDOW_UPDATE: sid %u %u (0x%x)\n",
1917
0
        (unsigned int)h2n->sid,
1918
0
        (unsigned int)h2n->hpack_e_dep,
1919
0
        (unsigned int)h2n->hpack_e_dep);
1920
1921
0
    if (h2n->sid)
1922
0
      eff_wsi = h2n->swsi;
1923
1924
0
    if (!eff_wsi) {
1925
0
      if (h2n->sid > h2n->highest_sid_opened)
1926
0
        lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR,
1927
0
                "alien sid");
1928
0
      break; /* ignore */
1929
0
    }
1930
1931
0
    if (eff_wsi->a.vhost->options &
1932
0
            LWS_SERVER_OPTION_H2_JUST_FIX_WINDOW_UPDATE_OVERFLOW &&
1933
0
        (uint64_t)eff_wsi->txc.tx_cr + (uint64_t)h2n->hpack_e_dep >
1934
0
        (uint64_t)0x7fffffff)
1935
0
      h2n->hpack_e_dep = (uint32_t)(0x7fffffff - eff_wsi->txc.tx_cr);
1936
1937
0
    if ((uint64_t)eff_wsi->txc.tx_cr + (uint64_t)h2n->hpack_e_dep >
1938
0
        (uint64_t)0x7fffffff) {
1939
0
      lwsl_warn("%s: WINDOW_UPDATE 0x%llx + 0x%llx = 0x%llx, too high\n",
1940
0
          __func__, (unsigned long long)eff_wsi->txc.tx_cr,
1941
0
          (unsigned long long)h2n->hpack_e_dep,
1942
0
          (unsigned long long)eff_wsi->txc.tx_cr + (unsigned long long)h2n->hpack_e_dep);
1943
0
      if (h2n->sid)
1944
0
        lws_h2_rst_stream(h2n->swsi,
1945
0
              H2_ERR_FLOW_CONTROL_ERROR,
1946
0
              "Flow control exceeded max");
1947
0
      else
1948
0
        lws_h2_goaway(wsi, H2_ERR_FLOW_CONTROL_ERROR,
1949
0
                "Flow control exceeded max");
1950
0
      break;
1951
0
    }
1952
1953
0
    if (!h2n->hpack_e_dep) {
1954
0
      lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR,
1955
0
              "Zero length window update");
1956
0
      break;
1957
0
    }
1958
0
    n = eff_wsi->txc.tx_cr;
1959
0
    eff_wsi->txc.tx_cr += (int32_t)h2n->hpack_e_dep;
1960
1961
0
    lws_wsi_txc_report_manual_txcr_in(eff_wsi,
1962
0
              (int32_t)h2n->hpack_e_dep);
1963
1964
0
    lws_wsi_txc_describe(&eff_wsi->txc, "WINDOW_UPDATE in",
1965
0
             eff_wsi->mux.my_sid);
1966
1967
0
    if (n <= 0 && eff_wsi->txc.tx_cr <= 0)
1968
      /* it helps, but won't change sendability for anyone */
1969
0
      break;
1970
1971
    /*
1972
     * It may have changed sendability (depends on SID 0 tx credit
1973
     * too)... for us and any children waiting on us... reassess
1974
     * blockage for all children first
1975
     */
1976
0
    lws_start_foreach_ll(struct lws *, w, wsi->mux.child_list) {
1977
0
      lws_callback_on_writable(w);
1978
0
    } lws_end_foreach_ll(w, mux.sibling_list);
1979
1980
0
    if (eff_wsi->txc.skint &&
1981
0
        !lws_wsi_txc_check_skint(&eff_wsi->txc,
1982
0
               lws_h2_tx_cr_get(eff_wsi)))
1983
      /*
1984
       * This one became un-skint, schedule a writeable
1985
       * callback
1986
       */
1987
0
      lws_callback_on_writable(eff_wsi);
1988
1989
0
    break;
1990
1991
0
  case LWS_H2_FRAME_TYPE_GOAWAY:
1992
0
    lwsl_wsi_notice(wsi, "RX GOAWAY: last sid %u, error 0x%08X, string '%s'\n",
1993
0
        (unsigned int)h2n->goaway_last_sid,
1994
0
        (unsigned int)h2n->goaway_err, h2n->goaway_str);
1995
1996
0
    return 1;
1997
1998
0
  case LWS_H2_FRAME_TYPE_RST_STREAM:
1999
0
    lwsl_info("LWS_H2_FRAME_TYPE_RST_STREAM: sid %u: reason 0x%x\n",
2000
0
        (unsigned int)h2n->sid,
2001
0
        (unsigned int)h2n->hpack_e_dep);
2002
0
    break;
2003
2004
0
  case LWS_H2_FRAME_TYPE_COUNT: /* IGNORING FRAME */
2005
0
    break;
2006
0
  }
2007
2008
0
  return 0;
2009
0
}
2010
2011
/*
2012
 * This may want to send something on the network wsi, which may be in the
2013
 * middle of a partial send.  PPS sends are OK because they are queued to
2014
 * go through the WRITABLE handler already.
2015
 *
2016
 * The read parser for the network wsi has no choice but to parse its stream
2017
 * anyway, because otherwise it will not be able to get tx credit window
2018
 * messages.
2019
 *
2020
 * Therefore if we will send non-PPS, ie, lws_http_action() for a stream
2021
 * wsi, we must change its state and handle it as a priority in the
2022
 * POLLOUT handler instead of writing it here.
2023
 *
2024
 * About closing... for the main network wsi, it should return nonzero to
2025
 * close it all.  If it needs to close an swsi, it can do it here.
2026
 */
2027
int
2028
lws_h2_parser(struct lws *wsi, unsigned char *in, lws_filepos_t _inlen,
2029
        lws_filepos_t *inused)
2030
0
{
2031
0
  struct lws_h2_netconn *h2n = wsi->h2.h2n;
2032
0
  struct lws_h2_protocol_send *pps;
2033
0
  unsigned char c, *oldin = in, *iend = in + (size_t)_inlen;
2034
0
  int n, m;
2035
2036
0
  if (!h2n)
2037
0
    goto fail;
2038
2039
0
  while (in < iend) {
2040
2041
0
    c = *in++;
2042
2043
0
    switch (lwsi_state(wsi)) {
2044
0
    case LRS_H2_AWAIT_PREFACE:
2045
0
      if (preface[h2n->count++] != c)
2046
0
        goto fail;
2047
2048
0
      if (preface[h2n->count])
2049
0
        break;
2050
2051
0
      lwsl_info("http2: %s: established\n", lws_wsi_tag(wsi));
2052
0
      lwsi_set_state(wsi, LRS_H2_AWAIT_SETTINGS);
2053
0
      lws_validity_confirmed(wsi);
2054
0
      h2n->count = 0;
2055
0
      wsi->txc.tx_cr = 65535;
2056
2057
      /*
2058
       * we must send a settings frame -- empty one is OK...
2059
       * that must be the first thing sent by server
2060
       * and the peer must send a SETTINGS with ACK flag...
2061
       */
2062
0
      pps = lws_h2_new_pps(LWS_H2_PPS_MY_SETTINGS);
2063
0
      if (!pps)
2064
0
        goto fail;
2065
0
      lws_pps_schedule(wsi, pps);
2066
0
      break;
2067
2068
0
    case LRS_H2_WAITING_TO_SEND_HEADERS:
2069
0
    case LRS_ESTABLISHED:
2070
0
    case LRS_H2_AWAIT_SETTINGS:
2071
2072
0
      if (h2n->frame_state != LWS_H2_FRAME_HEADER_LENGTH)
2073
0
        goto try_frame_start;
2074
2075
      /*
2076
       * post-header, preamble / payload / padding part
2077
       */
2078
0
      h2n->count++;
2079
2080
0
      if (h2n->type == LWS_H2_FRAME_TYPE_COUNT) { /* IGNORING FRAME */
2081
        //lwsl_debug("%s: consuming for ignored %u %u\n", __func__, (unsigned int)h2n->count, (unsigned int)h2n->length);
2082
0
        goto frame_end;
2083
0
      }
2084
2085
2086
0
      if (h2n->flags & LWS_H2_FLAG_PADDED &&
2087
0
          !h2n->pad_length) {
2088
        /*
2089
         * Get the padding count... actual padding is
2090
         * at the end of the frame.
2091
         */
2092
0
        h2n->padding = c;
2093
0
        h2n->pad_length = 1;
2094
0
        h2n->preamble++;
2095
2096
0
        if (h2n->padding > h2n->length - 1)
2097
0
          lws_h2_goaway(wsi,
2098
0
                  H2_ERR_PROTOCOL_ERROR,
2099
0
                  "execssive padding");
2100
0
        break; /* we consumed this */
2101
0
      }
2102
2103
0
      if (h2n->flags & LWS_H2_FLAG_PRIORITY &&
2104
0
          !h2n->collected_priority) {
2105
        /* going to be 5 preamble bytes */
2106
2107
0
        lwsl_debug("PRIORITY FLAG:  0x%x\n", c);
2108
2109
0
        if (h2n->preamble++ - h2n->pad_length < 4) {
2110
0
          h2n->dep = ((h2n->dep) << 8) | c;
2111
0
          break; /* we consumed this */
2112
0
        }
2113
0
        h2n->weight_temp = c;
2114
0
        h2n->collected_priority = 1;
2115
0
        lwsl_debug("PRI FL: dep 0x%x, weight 0x%02X\n",
2116
0
             (unsigned int)h2n->dep,
2117
0
             h2n->weight_temp);
2118
0
        break; /* we consumed this */
2119
0
      }
2120
0
      if (h2n->padding && h2n->count >
2121
0
          (h2n->length - h2n->padding)) {
2122
0
        if (c) {
2123
0
          lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR,
2124
0
                  "nonzero padding");
2125
0
          break;
2126
0
        }
2127
0
        goto frame_end;
2128
0
      }
2129
2130
      /* applies to wsi->h2.swsi which may be wsi */
2131
0
      switch(h2n->type) {
2132
2133
0
      case LWS_H2_FRAME_TYPE_SETTINGS:
2134
0
        n = (int)(h2n->count - 1u - h2n->preamble) %
2135
0
             LWS_H2_SETTINGS_LEN;
2136
0
        h2n->one_setting[n] = c;
2137
0
        if (n != LWS_H2_SETTINGS_LEN - 1)
2138
0
          break;
2139
0
        lws_h2_settings(wsi, &h2n->peer_set,
2140
0
            h2n->one_setting,
2141
0
            LWS_H2_SETTINGS_LEN);
2142
0
        break;
2143
2144
0
      case LWS_H2_FRAME_TYPE_CONTINUATION:
2145
0
      case LWS_H2_FRAME_TYPE_HEADERS:
2146
0
        if (!h2n->swsi)
2147
0
          break;
2148
0
        if (lws_hpack_interpret(h2n->swsi, c)) {
2149
0
          lwsl_info("%s: hpack failed\n",
2150
0
              __func__);
2151
0
          goto fail;
2152
0
        }
2153
0
        break;
2154
2155
0
      case LWS_H2_FRAME_TYPE_GOAWAY:
2156
0
        switch (h2n->inside++) {
2157
0
        case 0:
2158
0
        case 1:
2159
0
        case 2:
2160
0
        case 3:
2161
0
          h2n->goaway_last_sid <<= 8;
2162
0
          h2n->goaway_last_sid |= c;
2163
0
          h2n->goaway_str[0] = '\0';
2164
0
          break;
2165
2166
0
        case 4:
2167
0
        case 5:
2168
0
        case 6:
2169
0
        case 7:
2170
0
          h2n->goaway_err <<= 8;
2171
0
          h2n->goaway_err |= c;
2172
0
          break;
2173
2174
0
        default:
2175
0
          if (h2n->inside - 9 <
2176
0
              sizeof(h2n->goaway_str) - 1)
2177
0
            h2n->goaway_str[
2178
0
                       h2n->inside - 9] = (char)c;
2179
0
          h2n->goaway_str[
2180
0
              sizeof(h2n->goaway_str) - 1] = '\0';
2181
0
          break;
2182
0
        }
2183
0
        break;
2184
2185
0
      case LWS_H2_FRAME_TYPE_DATA:
2186
2187
      //  lwsl_info("%s: LWS_H2_FRAME_TYPE_DATA: fl 0x%x\n",
2188
      //      __func__, h2n->flags);
2189
2190
        /*
2191
         * let the network wsi live a bit longer if
2192
         * subs are active... our frame may take a long
2193
         * time to chew through
2194
         */
2195
0
        if (!wsi->immortal_substream_count)
2196
0
          lws_set_timeout(wsi,
2197
0
            PENDING_TIMEOUT_HTTP_KEEPALIVE_IDLE,
2198
0
            lws_wsi_keepalive_timeout_eff(wsi));
2199
2200
0
        if (!h2n->swsi || h2n->swsi->socket_is_permanently_unusable)
2201
0
          break;
2202
2203
0
        if (lws_buflist_next_segment_len(
2204
0
            &h2n->swsi->buflist, NULL))
2205
0
          lwsl_info("%s: substream has pending\n",
2206
0
              __func__);
2207
2208
0
        if (lwsi_role_http(h2n->swsi) &&
2209
0
            lwsi_state(h2n->swsi) == LRS_ESTABLISHED) {
2210
0
          lwsi_set_state(h2n->swsi, LRS_BODY);
2211
0
          lwsl_info("%s: %s to LRS_BODY\n",
2212
0
              __func__, lws_wsi_tag(h2n->swsi));
2213
0
        }
2214
2215
        /*
2216
         * in + length may cover multiple frames, we
2217
         * can only consider the length of the DATA
2218
         * in front of us
2219
         */
2220
2221
0
        if (lws_hdr_total_length(h2n->swsi,
2222
0
               WSI_TOKEN_HTTP_CONTENT_LENGTH) &&
2223
0
            h2n->swsi->http.rx_content_length &&
2224
0
            h2n->swsi->http.rx_content_remain <
2225
0
                 h2n->length - h2n->inside && /* last */
2226
0
            h2n->inside < h2n->length) {
2227
2228
0
          lwsl_warn("%s: rx.cl: %lu, rx.content_remain: %lu, buf left: %lu, "
2229
0
              "h2->inside: %lu, h2->length: %lu\n", __func__,
2230
0
              (unsigned long)h2n->swsi->http.rx_content_length,
2231
0
              (unsigned long)h2n->swsi->http.rx_content_remain,
2232
0
              (unsigned long)(lws_ptr_diff_size_t(iend, in) + 1),
2233
0
              (unsigned long)h2n->inside, (unsigned long)h2n->length);
2234
2235
          /* unread data in frame */
2236
0
          lws_h2_goaway(wsi,
2237
0
                  H2_ERR_PROTOCOL_ERROR,
2238
0
              "More rx than content_length told");
2239
0
          break;
2240
0
        }
2241
2242
        /*
2243
         * We operate on a frame.  The RX we have at
2244
         * hand may exceed the current frame.
2245
         */
2246
2247
0
        n = (int)lws_ptr_diff_size_t(iend, in)  + 1;
2248
0
        if (n > (int)(h2n->length - h2n->count + 1)) {
2249
0
          if (h2n->count > h2n->length)
2250
0
            goto close_swsi_and_return;
2251
0
          n = (int)(h2n->length - h2n->count) + 1;
2252
0
          lwsl_debug("---- restricting len to %d "
2253
0
               "\n", n);
2254
0
        }
2255
0
#if defined(LWS_WITH_CLIENT)
2256
0
        if (h2n->swsi->client_mux_substream) {
2257
0
          if (!h2n->swsi->a.protocol) {
2258
0
            lwsl_err("%s: %p doesn't have protocol\n",
2259
0
               __func__, lws_wsi_tag(h2n->swsi));
2260
0
            m = 1;
2261
0
          } else {
2262
0
            h2n->swsi->txc.peer_tx_cr_est -= n;
2263
0
            wsi->txc.peer_tx_cr_est -= n;
2264
0
            lws_wsi_txc_describe(&h2n->swsi->txc,
2265
0
              __func__,
2266
0
              h2n->swsi->mux.my_sid);
2267
0
          m = user_callback_handle_rxflow(
2268
0
            h2n->swsi->a.protocol->callback,
2269
0
            h2n->swsi,
2270
0
            LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ,
2271
0
            h2n->swsi->user_space,
2272
0
            in - 1, (unsigned int)n);
2273
0
          }
2274
2275
0
          in += n - 1;
2276
0
          h2n->inside += (unsigned int)n;
2277
0
          h2n->count += (unsigned int)n - 1;
2278
2279
0
          if (m) {
2280
0
            lwsl_info("RECEIVE_CLIENT_HTTP "
2281
0
                "closed it\n");
2282
0
            goto close_swsi_and_return;
2283
0
          }
2284
2285
0
          goto do_windows;
2286
0
        }
2287
0
#endif
2288
0
        if (lwsi_state(h2n->swsi) == LRS_DEFERRING_ACTION) {
2289
0
          m = lws_buflist_append_segment(
2290
0
            &h2n->swsi->buflist, in - 1, (unsigned int)n);
2291
0
          if (m < 0)
2292
0
            return -1;
2293
2294
          /*
2295
           * Since we're in an open-ended
2296
           * DEFERRING_ACTION, don't add this swsi
2297
           * to the pt list of wsi holding buflist
2298
           * content yet, we are not in a position
2299
           * to consume it until we get out of
2300
           * DEFERRING_ACTION.
2301
           */
2302
2303
0
          in += n - 1;
2304
0
          h2n->inside += (unsigned int)n;
2305
0
          h2n->count += (unsigned int)n - 1;
2306
2307
0
          lwsl_debug("%s: deferred %d\n", __func__, n);
2308
0
          goto do_windows;
2309
0
        }
2310
2311
0
        h2n->swsi->outer_will_close = 1;
2312
        /*
2313
         * choose the length for this go so that we end at
2314
         * the frame boundary, in the case there is already
2315
         * more waiting leave it for next time around
2316
         */
2317
2318
0
        n = lws_read_h1(h2n->swsi, in - 1, (unsigned int)n);
2319
        // lwsl_notice("%s: lws_read_h1 %d\n", __func__, n);
2320
0
        h2n->swsi->outer_will_close = 0;
2321
        /*
2322
         * can return 0 in POST body with
2323
         * content len exhausted somehow.
2324
         */
2325
0
        if (n < 0 ||
2326
0
            (!n && h2n->swsi->http.content_length_given && !lws_buflist_next_segment_len(
2327
0
                &wsi->buflist, NULL))) {
2328
0
          lwsl_info("%s: lws_read_h1 told %d %u / %u\n",
2329
0
            __func__, n,
2330
0
            (unsigned int)h2n->count,
2331
0
            (unsigned int)h2n->length);
2332
0
          in += h2n->length - h2n->count;
2333
0
          h2n->inside = h2n->length;
2334
0
          h2n->count = h2n->length - 1;
2335
2336
          //if (n < 0)
2337
          //  goto already_closed_swsi;
2338
0
          goto close_swsi_and_return;
2339
0
        }
2340
2341
0
        lwsl_info("%s: lws_read_h1 telling %d %u / %u\n",
2342
0
            __func__, n,
2343
0
            (unsigned int)h2n->count,
2344
0
            (unsigned int)h2n->length);
2345
2346
0
        if (n) {
2347
0
          in += (unsigned int)n - 1;
2348
0
          h2n->inside += (unsigned int)n;
2349
0
          h2n->count += (unsigned int)n - 1;
2350
2351
0
          h2n->swsi->txc.peer_tx_cr_est -= n;
2352
0
          wsi->txc.peer_tx_cr_est -= n;
2353
0
        }
2354
2355
0
do_windows:
2356
2357
0
#if defined(LWS_WITH_CLIENT)
2358
0
        if (!(h2n->swsi->flags & LCCSCF_H2_MANUAL_RXFLOW))
2359
0
#endif
2360
0
        {
2361
          /*
2362
           * The default behaviour is we just keep
2363
           * cranking the other side's tx credit
2364
           * back up, for simple bulk transfer as
2365
           * fast as we can take it
2366
           */
2367
2368
0
          m = n  + 65536;
2369
2370
          /* update both the stream and nwsi */
2371
2372
0
          lws_h2_update_peer_txcredit_thresh(h2n->swsi,
2373
0
                    h2n->sid, m, m);
2374
0
        }
2375
0
#if defined(LWS_WITH_CLIENT)
2376
0
        else {
2377
          /*
2378
           * If he's handling it himself, only
2379
           * repair the nwsi credit but allow the
2380
           * stream credit to run down until the
2381
           * user code deals with it
2382
           */
2383
0
          lws_h2_update_peer_txcredit(wsi, (unsigned int)0, n);
2384
0
          h2n->swsi->txc.manual = 1;
2385
0
        }
2386
0
#endif
2387
0
        break;
2388
2389
0
      case LWS_H2_FRAME_TYPE_PRIORITY:
2390
0
        if (h2n->count <= 4) {
2391
0
          h2n->dep <<= 8;
2392
0
          h2n->dep |= c;
2393
0
          break;
2394
0
        }
2395
0
        h2n->weight_temp = c;
2396
0
        lwsl_info("PRIORITY: dep 0x%x, weight 0x%02X\n",
2397
0
            (unsigned int)h2n->dep, h2n->weight_temp);
2398
2399
0
        if ((h2n->dep & ~(1u << 31)) == h2n->sid) {
2400
0
          lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR,
2401
0
                  "cant depend on own sid");
2402
0
          break;
2403
0
        }
2404
0
        break;
2405
2406
0
      case LWS_H2_FRAME_TYPE_RST_STREAM:
2407
0
        h2n->hpack_e_dep <<= 8;
2408
0
        h2n->hpack_e_dep |= c;
2409
0
        break;
2410
2411
0
      case LWS_H2_FRAME_TYPE_PUSH_PROMISE:
2412
0
        break;
2413
2414
0
      case LWS_H2_FRAME_TYPE_PING:
2415
0
        if (h2n->flags & LWS_H2_FLAG_SETTINGS_ACK) { // ack
2416
0
        } else { /* they're sending us a ping request */
2417
0
          if (h2n->count > 8)
2418
0
            return 1;
2419
0
          h2n->ping_payload[h2n->count - 1] = c;
2420
0
        }
2421
0
        break;
2422
2423
0
      case LWS_H2_FRAME_TYPE_WINDOW_UPDATE:
2424
0
        h2n->hpack_e_dep <<= 8;
2425
0
        h2n->hpack_e_dep |= c;
2426
0
        break;
2427
2428
0
      case LWS_H2_FRAME_TYPE_COUNT: /* IGNORING FRAME */
2429
        //lwsl_debug("%s: consuming for ignored %u %u\n", __func__, (unsigned int)h2n->count, (unsigned int)h2n->length);
2430
0
        h2n->count++;
2431
0
        break;
2432
2433
0
      default:
2434
0
        lwsl_notice("%s: unhandled frame type %d\n",
2435
0
              __func__, h2n->type);
2436
2437
0
        goto fail;
2438
0
      }
2439
2440
0
frame_end:
2441
0
      if (h2n->count > h2n->length) {
2442
0
        lwsl_notice("%s: count > length %u %u (type %d)\n",
2443
0
              __func__, (unsigned int)h2n->count,
2444
0
              (unsigned int)h2n->length, h2n->type);
2445
2446
0
      } else
2447
0
        if (h2n->count != h2n->length)
2448
0
          break;
2449
2450
      /*
2451
       * end of frame just happened
2452
       */
2453
0
      n = lws_h2_parse_end_of_frame(wsi);
2454
0
      if (n == 2) {
2455
0
        *inused = (lws_filepos_t)lws_ptr_diff_size_t(in, oldin);
2456
2457
0
        return 2;
2458
0
      }
2459
0
      if (n)
2460
0
        goto fail;
2461
2462
0
      break;
2463
2464
0
try_frame_start:
2465
0
      if (h2n->frame_state <= 8) {
2466
2467
0
        switch (h2n->frame_state++) {
2468
0
        case 0:
2469
0
          h2n->pad_length = 0;
2470
0
          h2n->collected_priority = 0;
2471
0
          h2n->padding = 0;
2472
0
          h2n->preamble = 0;
2473
0
          h2n->length = c;
2474
0
          h2n->inside = 0;
2475
0
          break;
2476
0
        case 1:
2477
0
        case 2:
2478
0
          h2n->length <<= 8;
2479
0
          h2n->length |= c;
2480
0
          break;
2481
0
        case 3:
2482
0
          h2n->type = c;
2483
0
          break;
2484
0
        case 4:
2485
0
          h2n->flags = c;
2486
0
          break;
2487
2488
0
        case 5:
2489
0
        case 6:
2490
0
        case 7:
2491
0
        case 8:
2492
0
          h2n->sid <<= 8;
2493
0
          h2n->sid |= c;
2494
0
          break;
2495
0
        }
2496
0
      }
2497
2498
0
      if (h2n->frame_state == LWS_H2_FRAME_HEADER_LENGTH &&
2499
0
          lws_h2_parse_frame_header(wsi))
2500
0
        goto fail;
2501
0
      break;
2502
2503
0
    default:
2504
0
      if (h2n->type == LWS_H2_FRAME_TYPE_COUNT) { /* IGNORING FRAME */
2505
        //lwsl_debug("%s: consuming for ignored %u %u\n", __func__, (unsigned int)h2n->count, (unsigned int)h2n->length);
2506
0
        h2n->count++;
2507
0
      }
2508
0
      break;
2509
0
    }
2510
0
  }
2511
2512
0
  *inused = (lws_filepos_t)lws_ptr_diff_size_t(in, oldin);
2513
2514
0
  return 0;
2515
2516
0
close_swsi_and_return:
2517
2518
0
  lws_close_free_wsi(h2n->swsi, 0, "close_swsi_and_return");
2519
0
  h2n->swsi = NULL;
2520
0
  h2n->frame_state = 0;
2521
0
  h2n->count = 0;
2522
2523
// already_closed_swsi:
2524
0
  *inused = (lws_filepos_t)lws_ptr_diff_size_t(in, oldin);
2525
2526
0
  return 2;
2527
2528
0
fail:
2529
0
  *inused = (lws_filepos_t)lws_ptr_diff_size_t(in, oldin);
2530
2531
0
  return 1;
2532
0
}
2533
2534
#if defined(LWS_WITH_CLIENT)
2535
int
2536
lws_h2_client_handshake(struct lws *wsi)
2537
0
{
2538
0
  struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
2539
0
  uint8_t *buf, *start, *p, *p1, *end;
2540
0
  char *meth = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_METHOD),
2541
0
       *uri = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_URI), *simp;
2542
0
  struct lws *nwsi = lws_get_network_wsi(wsi);
2543
0
  const char *path = "/";
2544
0
  int n, m;
2545
  /*
2546
   * The identifier of a newly established stream MUST be numerically
2547
   * greater than all streams that the initiating endpoint has opened or
2548
   * reserved.  This governs streams that are opened using a HEADERS frame
2549
   * and streams that are reserved using PUSH_PROMISE.  An endpoint that
2550
   * receives an unexpected stream identifier MUST respond with a
2551
   * connection error (Section 5.4.1) of type PROTOCOL_ERROR.
2552
   */
2553
0
  unsigned int sid = nwsi->h2.h2n->highest_sid_opened + 2;
2554
2555
0
  lwsl_debug("%s\n", __func__);
2556
2557
  /*
2558
   * We MUST allocate our sid here at the point we're about to send the
2559
   * stream open.  It's because we don't know the order in which multiple
2560
   * open streams will send their headers... in h2, sending the headers
2561
   * is the point the stream is opened.  The peer requires that we only
2562
   * open streams in ascending sid order
2563
   */
2564
2565
0
  wsi->mux.my_sid = nwsi->h2.h2n->highest_sid_opened = sid;
2566
0
  lwsl_info("%s: %s: assigning SID %d at header send\n", __func__,
2567
0
      lws_wsi_tag(wsi), sid);
2568
2569
2570
0
  lwsl_info("%s: CLIENT_WAITING_TO_SEND_HEADERS: pollout (sid %d)\n",
2571
0
      __func__, wsi->mux.my_sid);
2572
2573
0
  p = start = buf = pt->serv_buf + LWS_PRE;
2574
0
  end = start + (wsi->a.context->pt_serv_buf_size / 2) - LWS_PRE - 1;
2575
2576
  /* it's time for us to send our client stream headers */
2577
2578
0
  if (!meth)
2579
0
    meth = "GET";
2580
2581
  /* h2 pseudoheaders must be in a bunch at the start */
2582
2583
0
  if (lws_add_http_header_by_token(wsi,
2584
0
        WSI_TOKEN_HTTP_COLON_METHOD,
2585
0
        (unsigned char *)meth,
2586
0
        (int)strlen(meth), &p, end))
2587
0
    goto fail_length;
2588
2589
0
  if (lws_add_http_header_by_token(wsi,
2590
0
        WSI_TOKEN_HTTP_COLON_SCHEME,
2591
0
        (unsigned char *)"https", 5,
2592
0
        &p, end))
2593
0
    goto fail_length;
2594
2595
2596
0
  n = lws_hdr_total_length(wsi, _WSI_TOKEN_CLIENT_URI);
2597
0
  if (n)
2598
0
    path = uri;
2599
0
  else
2600
0
    if (wsi->stash && wsi->stash->cis[CIS_PATH]) {
2601
0
      path = wsi->stash->cis[CIS_PATH];
2602
0
      n = (int)strlen(path);
2603
0
    } else
2604
0
      n = 1;
2605
2606
0
  if (n > 1 && path[0] == '/' && path[1] == '/') {
2607
0
    path++;
2608
0
    n--;
2609
0
  }
2610
2611
  // lwsl_hexdump_notice(path, (size_t)n);
2612
2613
0
  if (n && lws_add_http_header_by_token(wsi,
2614
0
        WSI_TOKEN_HTTP_COLON_PATH,
2615
0
        (unsigned char *)path, n, &p, end))
2616
0
    goto fail_length;
2617
2618
0
  n = lws_hdr_total_length(wsi, _WSI_TOKEN_CLIENT_HOST);
2619
0
  simp = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_HOST);
2620
0
  if (!n && wsi->stash && wsi->stash->cis[CIS_ADDRESS]) {
2621
0
    n = (int)strlen(wsi->stash->cis[CIS_ADDRESS]);
2622
0
    simp = wsi->stash->cis[CIS_ADDRESS];
2623
0
  }
2624
2625
//  n = lws_hdr_total_length(wsi, _WSI_TOKEN_CLIENT_ORIGIN);
2626
//  simp = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN);
2627
#if 0
2628
  if (n && simp && lws_add_http_header_by_token(wsi,
2629
        WSI_TOKEN_HTTP_COLON_AUTHORITY,
2630
        (unsigned char *)simp, n, &p, end))
2631
    goto fail_length;
2632
#endif
2633
2634
2635
0
  if (/*!wsi->client_h2_alpn && */n && simp &&
2636
0
      lws_add_http_header_by_token(wsi, WSI_TOKEN_HOST,
2637
0
        (unsigned char *)simp, n, &p, end))
2638
0
    goto fail_length;
2639
2640
2641
0
  if (wsi->flags & LCCSCF_HTTP_MULTIPART_MIME) {
2642
0
    p1 = lws_http_multipart_headers(wsi, p);
2643
0
    if (!p1)
2644
0
      goto fail_length;
2645
0
    p = p1;
2646
0
  }
2647
2648
0
  if (wsi->flags & LCCSCF_HTTP_X_WWW_FORM_URLENCODED) {
2649
0
    if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,
2650
0
         (unsigned char *)"application/x-www-form-urlencoded",
2651
0
         33, &p, end))
2652
0
      goto fail_length;
2653
0
    lws_client_http_body_pending(wsi, 1);
2654
0
  }
2655
2656
  /* give userland a chance to append, eg, cookies */
2657
2658
0
#if defined(LWS_WITH_CACHE_NSCOOKIEJAR) && defined(LWS_WITH_CLIENT)
2659
0
  if (wsi->flags & LCCSCF_CACHE_COOKIES)
2660
0
    lws_cookie_send_cookies(wsi, (char **)&p, (char *)end);
2661
0
#endif
2662
2663
0
  if (wsi->a.protocol->callback(wsi,
2664
0
        LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER,
2665
0
        wsi->user_space, &p, lws_ptr_diff_size_t(end, p) - 12))
2666
0
    goto fail_length;
2667
2668
0
  if (lws_finalize_http_header(wsi, &p, end))
2669
0
    goto fail_length;
2670
2671
0
  m = LWS_WRITE_HTTP_HEADERS;
2672
0
#if defined(LWS_WITH_CLIENT)
2673
  /* below is not needed in spec, indeed it destroys the long poll
2674
   * feature, but required by nghttp2 */
2675
0
  if ((wsi->flags & LCCSCF_H2_QUIRK_NGHTTP2_END_STREAM) &&
2676
0
      !(wsi->client_http_body_pending  || lws_has_buffered_out(wsi)))
2677
0
    m |= LWS_WRITE_H2_STREAM_END;
2678
0
#endif
2679
2680
  // lwsl_hexdump_notice(start, p - start);
2681
2682
0
  n = lws_write(wsi, start, lws_ptr_diff_size_t(p, start), (enum lws_write_protocol)m);
2683
2684
0
  if (n != lws_ptr_diff(p, start)) {
2685
0
    lwsl_err("_write returned %d from %ld\n", n,
2686
0
       (long)(p - start));
2687
0
    return -1;
2688
0
  }
2689
2690
  /*
2691
   * Normally let's charge up the peer tx credit a bit.  But if
2692
   * MANUAL_REFLOW is set, just set it to the initial credit given in
2693
   * the client create info
2694
   */
2695
2696
0
  n = 4 * 65536;
2697
0
  if (wsi->flags & LCCSCF_H2_MANUAL_RXFLOW) {
2698
0
    n = wsi->txc.manual_initial_tx_credit;
2699
0
    wsi->txc.manual = 1;
2700
0
  }
2701
2702
0
  if (lws_h2_update_peer_txcredit(wsi, wsi->mux.my_sid, n))
2703
0
    return 1;
2704
2705
0
  lws_h2_state(wsi, LWS_H2_STATE_OPEN);
2706
0
  lwsi_set_state(wsi, LRS_ESTABLISHED);
2707
2708
0
  if (wsi->flags & LCCSCF_HTTP_MULTIPART_MIME)
2709
0
    lws_callback_on_writable(wsi);
2710
2711
0
  return 0;
2712
2713
0
fail_length:
2714
0
  lwsl_err("Client hdrs too long: incr context info.pt_serv_buf_size\n");
2715
2716
0
  return -1;
2717
0
}
2718
#endif
2719
2720
#if defined(LWS_ROLE_WS) && defined(LWS_WITH_SERVER)
2721
int
2722
lws_h2_ws_handshake(struct lws *wsi)
2723
0
{
2724
0
  uint8_t buf[LWS_PRE + 2048], *p = buf + LWS_PRE, *start = p,
2725
0
    *end = &buf[sizeof(buf) - 1];
2726
0
  const struct lws_http_mount *hit;
2727
0
  const char * uri_ptr;
2728
0
  size_t m;
2729
0
  int n;
2730
2731
0
  if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end))
2732
0
    return -1;
2733
2734
0
  if (lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL) > 64)
2735
0
    return -1;
2736
2737
0
  if (wsi->proxied_ws_parent && wsi->child_list) {
2738
0
    if (lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL)) {
2739
0
      if (lws_add_http_header_by_token(wsi, WSI_TOKEN_PROTOCOL,
2740
0
        (uint8_t *)lws_hdr_simple_ptr(wsi,
2741
0
                 WSI_TOKEN_PROTOCOL),
2742
0
        (int)strlen(lws_hdr_simple_ptr(wsi,
2743
0
                 WSI_TOKEN_PROTOCOL)),
2744
0
             &p, end))
2745
0
      return -1;
2746
0
    }
2747
0
  } else {
2748
2749
    /* we can only return the protocol header if:
2750
     *  - one came in, and ... */
2751
0
    if (lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL) &&
2752
        /*  - it is not an empty string */
2753
0
        wsi->a.protocol->name && wsi->a.protocol->name[0]) {
2754
2755
0
#if defined(LWS_WITH_SECURE_STREAMS) && defined(LWS_WITH_SERVER)
2756
2757
    /*
2758
     * This is the h2 version of server-ws.c understanding that it
2759
     * did the ws upgrade on a ss server object, therefore it needs
2760
     * to pass back to the peer the policy ws-protocol name, not
2761
     * the generic ss-ws.c protocol name
2762
     */
2763
2764
0
    if (wsi->a.vhost && wsi->a.vhost->ss_handle &&
2765
0
        wsi->a.vhost->ss_handle->policy->u.http.u.ws.subprotocol) {
2766
0
      lws_ss_handle_t *h =
2767
0
        (lws_ss_handle_t *)wsi->a.opaque_user_data;
2768
2769
0
      lwsl_notice("%s: Server SS %s .wsi %s switching to ws protocol\n",
2770
0
          __func__, lws_ss_tag(h), lws_wsi_tag(h->wsi));
2771
2772
0
      wsi->a.protocol = &protocol_secstream_ws;
2773
2774
      /*
2775
       * inform the SS user code that this has done a one-way
2776
       * upgrade to some other protocol... it will likely
2777
       * want to treat subsequent payloads differently
2778
       */
2779
2780
0
      lws_ss_event_helper(h, LWSSSCS_SERVER_UPGRADE);
2781
2782
0
      lws_mux_mark_immortal(wsi);
2783
2784
0
      if (lws_add_http_header_by_token(wsi, WSI_TOKEN_PROTOCOL,
2785
0
        (unsigned char *)wsi->a.vhost->ss_handle->policy->
2786
0
            u.http.u.ws.subprotocol,
2787
0
        (int)strlen(wsi->a.vhost->ss_handle->policy->
2788
0
            u.http.u.ws.subprotocol), &p, end))
2789
0
          return -1;
2790
0
    } else
2791
0
#endif
2792
2793
0
      if (lws_add_http_header_by_token(wsi, WSI_TOKEN_PROTOCOL,
2794
0
        (unsigned char *)wsi->a.protocol->name,
2795
0
        (int)strlen(wsi->a.protocol->name), &p, end))
2796
0
          return -1;
2797
0
    }
2798
0
  }
2799
2800
#if !defined(LWS_WITHOUT_EXTENSIONS)
2801
        /*
2802
         * Figure out which extensions the client has that we want to
2803
         * enable on this connection, and give him back the list.
2804
         *
2805
         * Give him a limited write bugdet
2806
         */
2807
        if (lws_extension_server_handshake(wsi, (char **)&p, 192))
2808
               return -1;
2809
#endif
2810
2811
0
  {
2812
0
    struct lws_process_html_args args;
2813
2814
0
    args.p = (char *)p;
2815
0
    args.max_len = lws_ptr_diff(end, p);
2816
0
    if (user_callback_handle_rxflow(wsi->a.protocol->callback, wsi,
2817
0
            LWS_CALLBACK_ADD_HEADERS,
2818
0
            wsi->user_space, &args, 0))
2819
0
      return -1;
2820
2821
0
    p = (uint8_t *)args.p;
2822
0
  }
2823
2824
0
  if (lws_finalize_http_header(wsi, &p, end))
2825
0
    return -1;
2826
2827
0
  m = lws_ptr_diff_size_t(p, start);
2828
  // lwsl_hexdump_notice(start, m);
2829
0
  n = lws_write(wsi, start, m, LWS_WRITE_HTTP_HEADERS);
2830
0
  if (n != (int)m) {
2831
0
    lwsl_err("_write returned %d from %d\n", n, (int)m);
2832
2833
0
    return -1;
2834
0
  }
2835
2836
  /*
2837
   * alright clean up, set our state to generic ws established, the
2838
   * mode / state of the nwsi will get the h2 processing done.
2839
   */
2840
2841
0
  lwsi_set_state(wsi, LRS_ESTABLISHED);
2842
0
  wsi->lws_rx_parse_state = 0; // ==LWS_RXPS_NEW;
2843
2844
0
  uri_ptr = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_PATH);
2845
0
  n = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COLON_PATH);
2846
0
  hit = lws_find_mount(wsi, uri_ptr, n);
2847
2848
0
  if (hit && hit->cgienv &&
2849
0
      wsi->a.protocol->callback(wsi, LWS_CALLBACK_HTTP_PMO, wsi->user_space,
2850
0
            (void *)hit->cgienv, 0))
2851
0
    return 1;
2852
2853
0
  lws_validity_confirmed(wsi);
2854
2855
0
  return 0;
2856
0
}
2857
#endif
2858
2859
int
2860
lws_read_h2(struct lws *wsi, unsigned char *buf, lws_filepos_t len)
2861
0
{
2862
0
  unsigned char *oldbuf = buf;
2863
2864
  // lwsl_notice("%s: h2 path: wsistate 0x%x len %d\n", __func__,
2865
  //    wsi->wsistate, (int)len);
2866
2867
  /*
2868
   * wsi here is always the network connection wsi, not a stream
2869
   * wsi.  Once we unpicked the framing we will find the right
2870
   * swsi and make it the target of the frame.
2871
   *
2872
   * If it's ws over h2, the nwsi will get us here to do the h2
2873
   * processing, and that will call us back with the swsi +
2874
   * ESTABLISHED state for the inner payload, handled in a later
2875
   * case.
2876
   */
2877
0
  while (len) {
2878
0
    lws_filepos_t body_chunk_len = 0;
2879
0
    int m;
2880
2881
    /*
2882
     * we were accepting input but now we stopped doing so
2883
     */
2884
0
    if (lws_is_flowcontrolled(wsi)) {
2885
0
      lws_rxflow_cache(wsi, buf, 0, (size_t)len);
2886
0
      buf += len;
2887
0
      break;
2888
0
    }
2889
2890
    /*
2891
     * lws_h2_parser() may send something; when it gets the
2892
     * whole frame, it will want to perform some action
2893
     * involving a reply.  But we may be in a partial send
2894
     * situation on the network wsi...
2895
     *
2896
     * Even though we may be in a partial send and unable to
2897
     * send anything new, we still have to parse the network
2898
     * wsi in order to gain tx credit to send, which is
2899
     * potentially necessary to clear the old partial send.
2900
     *
2901
     * ALL network wsi-specific frames are sent by PPS
2902
     * already, these are sent as a priority on the writable
2903
     * handler, and so respect partial sends.  The only
2904
     * problem is when a stream wsi wants to send an, eg,
2905
     * reply headers frame in response to the parsing
2906
     * we will do now... the *stream wsi* must stall in a
2907
     * different state until it is able to do so from a
2908
     * priority on the WRITABLE callback, same way that
2909
     * file transfers operate.
2910
     */
2911
2912
0
    m = lws_h2_parser(wsi, buf, len, &body_chunk_len);
2913
2914
0
               body_chunk_len &= 0xffffffff; /* attempt workaround for finding len=7167 --> len = 0xffffffff00001bff on lws.org */
2915
2916
0
    if (m && m != 2) {
2917
0
      lwsl_debug("%s: http2_parser bail: %d\n", __func__, m);
2918
0
      lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS,
2919
0
             "lws_read_h2 bail");
2920
2921
0
      return -1;
2922
0
    }
2923
0
    if (m == 2) {
2924
      /* swsi has been closed */
2925
0
      buf += body_chunk_len;
2926
0
      break;
2927
0
    }
2928
2929
0
    buf += body_chunk_len;
2930
0
    len -= body_chunk_len;
2931
0
  }
2932
2933
0
  return lws_ptr_diff(buf, oldbuf);
2934
0
}
2935
2936
int
2937
lws_h2_client_stream_long_poll_rxonly(struct lws *wsi)
2938
0
{
2939
2940
0
  if (!wsi->mux_substream)
2941
0
    return 1;
2942
2943
  /*
2944
   * Elect to send an empty DATA with END_STREAM, to force the stream
2945
   * into HALF_CLOSED LOCAL
2946
   */
2947
0
  wsi->h2.long_poll = 1;
2948
0
  wsi->h2.send_END_STREAM = 1;
2949
2950
  // lws_header_table_detach(wsi, 0);
2951
2952
0
  lws_callback_on_writable(wsi);
2953
2954
0
  return 0;
2955
0
}