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