1d4afb5ceSopenharmony_ci/* 2d4afb5ceSopenharmony_ci * libwebsockets - small server side websockets and web server implementation 3d4afb5ceSopenharmony_ci * 4d4afb5ceSopenharmony_ci * Copyright (C) 2019 - 2021 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 * In the case Secure Streams protocol needs to pass through a buffer, 26d4afb5ceSopenharmony_ci * or a streamed connection, the protocol metadata must be serialized. This 27d4afb5ceSopenharmony_ci * file provides internal apis to perform the serialization and deserialization 28d4afb5ceSopenharmony_ci * in and out of an lws_dsh fifo-type buffer. 29d4afb5ceSopenharmony_ci */ 30d4afb5ceSopenharmony_ci 31d4afb5ceSopenharmony_ci#include <private-lib-core.h> 32d4afb5ceSopenharmony_ci 33d4afb5ceSopenharmony_citypedef enum { 34d4afb5ceSopenharmony_ci RPAR_TYPE, 35d4afb5ceSopenharmony_ci RPAR_LEN_MSB, 36d4afb5ceSopenharmony_ci RPAR_LEN_LSB, 37d4afb5ceSopenharmony_ci 38d4afb5ceSopenharmony_ci RPAR_FLAG_B3, 39d4afb5ceSopenharmony_ci RPAR_FLAG_B2, 40d4afb5ceSopenharmony_ci RPAR_FLAG_B1, 41d4afb5ceSopenharmony_ci RPAR_FLAG_B0, 42d4afb5ceSopenharmony_ci 43d4afb5ceSopenharmony_ci RPAR_LATA3, 44d4afb5ceSopenharmony_ci RPAR_LATA2, 45d4afb5ceSopenharmony_ci RPAR_LATA1, 46d4afb5ceSopenharmony_ci RPAR_LATA0, 47d4afb5ceSopenharmony_ci 48d4afb5ceSopenharmony_ci RPAR_LATB7, 49d4afb5ceSopenharmony_ci RPAR_LATB6, 50d4afb5ceSopenharmony_ci RPAR_LATB5, 51d4afb5ceSopenharmony_ci RPAR_LATB4, 52d4afb5ceSopenharmony_ci RPAR_LATB3, 53d4afb5ceSopenharmony_ci RPAR_LATB2, 54d4afb5ceSopenharmony_ci RPAR_LATB1, 55d4afb5ceSopenharmony_ci RPAR_LATB0, 56d4afb5ceSopenharmony_ci 57d4afb5ceSopenharmony_ci RPAR_RIDESHARE_LEN, 58d4afb5ceSopenharmony_ci RPAR_RIDESHARE, 59d4afb5ceSopenharmony_ci 60d4afb5ceSopenharmony_ci RPAR_PERF, 61d4afb5ceSopenharmony_ci 62d4afb5ceSopenharmony_ci RPAR_RESULT_CREATION_DSH, 63d4afb5ceSopenharmony_ci RPAR_RESULT_CREATION_RIDESHARE, 64d4afb5ceSopenharmony_ci 65d4afb5ceSopenharmony_ci RPAR_METADATA_NAMELEN, 66d4afb5ceSopenharmony_ci RPAR_METADATA_NAME, 67d4afb5ceSopenharmony_ci RPAR_METADATA_VALUE, 68d4afb5ceSopenharmony_ci 69d4afb5ceSopenharmony_ci RPAR_PAYLOAD, 70d4afb5ceSopenharmony_ci 71d4afb5ceSopenharmony_ci RPAR_RX_TXCR_UPDATE, 72d4afb5ceSopenharmony_ci 73d4afb5ceSopenharmony_ci RPAR_STREAMTYPE, 74d4afb5ceSopenharmony_ci RPAR_INIT_PROVERS, 75d4afb5ceSopenharmony_ci RPAR_INIT_PID, 76d4afb5ceSopenharmony_ci RPAR_INITTXC0, 77d4afb5ceSopenharmony_ci 78d4afb5ceSopenharmony_ci RPAR_TXCR0, 79d4afb5ceSopenharmony_ci 80d4afb5ceSopenharmony_ci RPAR_TIMEOUT0, 81d4afb5ceSopenharmony_ci 82d4afb5ceSopenharmony_ci RPAR_PAYLEN0, 83d4afb5ceSopenharmony_ci 84d4afb5ceSopenharmony_ci RPAR_RESULT_CREATION, 85d4afb5ceSopenharmony_ci 86d4afb5ceSopenharmony_ci RPAR_STATEINDEX, 87d4afb5ceSopenharmony_ci RPAR_ORD3, 88d4afb5ceSopenharmony_ci RPAR_ORD2, 89d4afb5ceSopenharmony_ci RPAR_ORD1, 90d4afb5ceSopenharmony_ci RPAR_ORD0, 91d4afb5ceSopenharmony_ci} rx_parser_t; 92d4afb5ceSopenharmony_ci 93d4afb5ceSopenharmony_ci#if defined(_DEBUG) && !defined(LWS_WITH_NO_LOGS) 94d4afb5ceSopenharmony_cistatic const char *sn[] = { 95d4afb5ceSopenharmony_ci "unset", 96d4afb5ceSopenharmony_ci 97d4afb5ceSopenharmony_ci "LPCSPROX_WAIT_INITIAL_TX", 98d4afb5ceSopenharmony_ci "LPCSPROX_REPORTING_FAIL", 99d4afb5ceSopenharmony_ci "LPCSPROX_REPORTING_OK", 100d4afb5ceSopenharmony_ci "LPCSPROX_OPERATIONAL", 101d4afb5ceSopenharmony_ci "LPCSPROX_DESTROYED", 102d4afb5ceSopenharmony_ci 103d4afb5ceSopenharmony_ci "LPCSCLI_SENDING_INITIAL_TX", 104d4afb5ceSopenharmony_ci "LPCSCLI_WAITING_CREATE_RESULT", 105d4afb5ceSopenharmony_ci "LPCSCLI_LOCAL_CONNECTED", 106d4afb5ceSopenharmony_ci "LPCSCLI_ONWARD_CONNECT", 107d4afb5ceSopenharmony_ci "LPCSCLI_OPERATIONAL", 108d4afb5ceSopenharmony_ci}; 109d4afb5ceSopenharmony_ci#endif 110d4afb5ceSopenharmony_ci 111d4afb5ceSopenharmony_cistruct lws_log_cx * 112d4afb5ceSopenharmony_cilwsl_sspc_get_cx(struct lws_sspc_handle *sspc) 113d4afb5ceSopenharmony_ci{ 114d4afb5ceSopenharmony_ci if (!sspc) 115d4afb5ceSopenharmony_ci return NULL; 116d4afb5ceSopenharmony_ci 117d4afb5ceSopenharmony_ci return sspc->lc.log_cx; 118d4afb5ceSopenharmony_ci} 119d4afb5ceSopenharmony_ci 120d4afb5ceSopenharmony_ci 121d4afb5ceSopenharmony_civoid 122d4afb5ceSopenharmony_cilws_log_prepend_sspc(struct lws_log_cx *cx, void *obj, char **p, char *e) 123d4afb5ceSopenharmony_ci{ 124d4afb5ceSopenharmony_ci struct lws_sspc_handle *h = (struct lws_sspc_handle *)obj; 125d4afb5ceSopenharmony_ci 126d4afb5ceSopenharmony_ci *p += lws_snprintf(*p, lws_ptr_diff_size_t(e, (*p)), "%s: ", 127d4afb5ceSopenharmony_ci lws_sspc_tag(h)); 128d4afb5ceSopenharmony_ci} 129d4afb5ceSopenharmony_ci 130d4afb5ceSopenharmony_cistatic void 131d4afb5ceSopenharmony_cilws_ss_serialize_state_transition(lws_sspc_handle_t *h, 132d4afb5ceSopenharmony_ci lws_ss_conn_states_t *state, int new_state) 133d4afb5ceSopenharmony_ci{ 134d4afb5ceSopenharmony_ci#if defined(_DEBUG) 135d4afb5ceSopenharmony_ci lwsl_sspc_info(h, "%s -> %s", sn[*state], sn[new_state]); 136d4afb5ceSopenharmony_ci#endif 137d4afb5ceSopenharmony_ci *state = (lws_ss_conn_states_t)new_state; 138d4afb5ceSopenharmony_ci} 139d4afb5ceSopenharmony_ci 140d4afb5ceSopenharmony_ci 141d4afb5ceSopenharmony_ci/* 142d4afb5ceSopenharmony_ci * event loop received something and is queueing it for the foreign side of 143d4afb5ceSopenharmony_ci * the dsh to consume later as serialized rx 144d4afb5ceSopenharmony_ci */ 145d4afb5ceSopenharmony_ci 146d4afb5ceSopenharmony_ciint 147d4afb5ceSopenharmony_cilws_ss_serialize_rx_payload(struct lws_dsh *dsh, const uint8_t *buf, 148d4afb5ceSopenharmony_ci size_t len, int flags, const char *rsp) 149d4afb5ceSopenharmony_ci{ 150d4afb5ceSopenharmony_ci lws_usec_t us = lws_now_usecs(); 151d4afb5ceSopenharmony_ci uint8_t pre[128]; 152d4afb5ceSopenharmony_ci int est = 19, l = 0; 153d4afb5ceSopenharmony_ci 154d4afb5ceSopenharmony_ci if (flags & LWSSS_FLAG_RIDESHARE) { 155d4afb5ceSopenharmony_ci /* 156d4afb5ceSopenharmony_ci * We should have the rideshare name if we have been told it's 157d4afb5ceSopenharmony_ci * on a non-default rideshare 158d4afb5ceSopenharmony_ci */ 159d4afb5ceSopenharmony_ci assert(rsp); 160d4afb5ceSopenharmony_ci if (!rsp) 161d4afb5ceSopenharmony_ci return 1; 162d4afb5ceSopenharmony_ci l = (int)strlen(rsp); 163d4afb5ceSopenharmony_ci est += 1 + l; 164d4afb5ceSopenharmony_ci } else 165d4afb5ceSopenharmony_ci assert(!rsp); 166d4afb5ceSopenharmony_ci 167d4afb5ceSopenharmony_ci // lwsl_user("%s: len %d, flags: %d\n", __func__, (int)len, flags); 168d4afb5ceSopenharmony_ci // lwsl_hexdump_info(buf, len); 169d4afb5ceSopenharmony_ci 170d4afb5ceSopenharmony_ci pre[0] = LWSSS_SER_RXPRE_RX_PAYLOAD; 171d4afb5ceSopenharmony_ci lws_ser_wu16be(&pre[1], (uint16_t)(len + (size_t)est - 3)); 172d4afb5ceSopenharmony_ci lws_ser_wu32be(&pre[3], (uint32_t)flags); 173d4afb5ceSopenharmony_ci lws_ser_wu32be(&pre[7], 0); /* write will compute latency here... */ 174d4afb5ceSopenharmony_ci lws_ser_wu64be(&pre[11], (uint64_t)us); /* ... and set this to the write time */ 175d4afb5ceSopenharmony_ci 176d4afb5ceSopenharmony_ci /* 177d4afb5ceSopenharmony_ci * If we are on a non-default rideshare, append the non-default name to 178d4afb5ceSopenharmony_ci * the headers of the payload part, 1-byte length first 179d4afb5ceSopenharmony_ci */ 180d4afb5ceSopenharmony_ci 181d4afb5ceSopenharmony_ci if (flags & LWSSS_FLAG_RIDESHARE) { 182d4afb5ceSopenharmony_ci pre[19] = (uint8_t)l; 183d4afb5ceSopenharmony_ci memcpy(&pre[20], rsp, (unsigned int)l); 184d4afb5ceSopenharmony_ci } 185d4afb5ceSopenharmony_ci 186d4afb5ceSopenharmony_ci if (lws_dsh_alloc_tail(dsh, KIND_SS_TO_P, pre, (unsigned int)est, buf, len)) { 187d4afb5ceSopenharmony_ci lwsl_err("%s: unable to alloc in dsh 1\n", __func__); 188d4afb5ceSopenharmony_ci 189d4afb5ceSopenharmony_ci return 1; 190d4afb5ceSopenharmony_ci } 191d4afb5ceSopenharmony_ci 192d4afb5ceSopenharmony_ci return 0; 193d4afb5ceSopenharmony_ci} 194d4afb5ceSopenharmony_ci 195d4afb5ceSopenharmony_ci/* 196d4afb5ceSopenharmony_ci * event loop is consuming dsh-buffered, already-serialized tx from the 197d4afb5ceSopenharmony_ci * foreign side 198d4afb5ceSopenharmony_ci */ 199d4afb5ceSopenharmony_ci 200d4afb5ceSopenharmony_ciint 201d4afb5ceSopenharmony_cilws_ss_deserialize_tx_payload(struct lws_dsh *dsh, struct lws *wsi, 202d4afb5ceSopenharmony_ci lws_ss_tx_ordinal_t ord, uint8_t *buf, 203d4afb5ceSopenharmony_ci size_t *len, int *flags) 204d4afb5ceSopenharmony_ci{ 205d4afb5ceSopenharmony_ci uint8_t *p; 206d4afb5ceSopenharmony_ci size_t si; 207d4afb5ceSopenharmony_ci 208d4afb5ceSopenharmony_ci if (lws_dsh_get_head(dsh, KIND_C_TO_P, (void **)&p, &si)) { 209d4afb5ceSopenharmony_ci *len = 0; 210d4afb5ceSopenharmony_ci return 0; 211d4afb5ceSopenharmony_ci } 212d4afb5ceSopenharmony_ci 213d4afb5ceSopenharmony_ci /* 214d4afb5ceSopenharmony_ci * The packet in the dsh has a proxying serialization header, process 215d4afb5ceSopenharmony_ci * and strip it so we just forward the payload 216d4afb5ceSopenharmony_ci */ 217d4afb5ceSopenharmony_ci 218d4afb5ceSopenharmony_ci if (*len <= si - 23 || si < 23) { 219d4afb5ceSopenharmony_ci /* 220d4afb5ceSopenharmony_ci * What comes out of the dsh needs to fit in the tx buffer... 221d4afb5ceSopenharmony_ci * we have arrangements at the proxy rx of the client UDS to 222d4afb5ceSopenharmony_ci * chop chunks larger than 1380 into seuqential lumps of 1380 223d4afb5ceSopenharmony_ci */ 224d4afb5ceSopenharmony_ci lwsl_err("%s: *len = %d, si = %d\n", __func__, (int)*len, (int)si); 225d4afb5ceSopenharmony_ci assert(0); 226d4afb5ceSopenharmony_ci return 1; 227d4afb5ceSopenharmony_ci } 228d4afb5ceSopenharmony_ci if (p[0] != LWSSS_SER_TXPRE_TX_PAYLOAD) { 229d4afb5ceSopenharmony_ci assert(0); 230d4afb5ceSopenharmony_ci return 1; 231d4afb5ceSopenharmony_ci } 232d4afb5ceSopenharmony_ci 233d4afb5ceSopenharmony_ci *len = (size_t)(lws_ser_ru16be(&p[1]) - (23 - 3)); 234d4afb5ceSopenharmony_ci if (*len != si - 23) { 235d4afb5ceSopenharmony_ci /* 236d4afb5ceSopenharmony_ci * We cannot accept any length that doesn't reflect the actual 237d4afb5ceSopenharmony_ci * length of what came in from the dsh, either something nasty 238d4afb5ceSopenharmony_ci * happened with truncation or we are being attacked 239d4afb5ceSopenharmony_ci */ 240d4afb5ceSopenharmony_ci assert(0); 241d4afb5ceSopenharmony_ci 242d4afb5ceSopenharmony_ci return 1; 243d4afb5ceSopenharmony_ci } 244d4afb5ceSopenharmony_ci 245d4afb5ceSopenharmony_ci memcpy(buf, p + 23, si - 23); 246d4afb5ceSopenharmony_ci 247d4afb5ceSopenharmony_ci *flags = (int)lws_ser_ru32be(&p[3]); 248d4afb5ceSopenharmony_ci 249d4afb5ceSopenharmony_ci lws_dsh_free((void **)&p); 250d4afb5ceSopenharmony_ci 251d4afb5ceSopenharmony_ci return 0; 252d4afb5ceSopenharmony_ci} 253d4afb5ceSopenharmony_ci 254d4afb5ceSopenharmony_ci/* 255d4afb5ceSopenharmony_ci * event loop side is issuing state, serialize and put it in the dbuf for 256d4afb5ceSopenharmony_ci * the foreign side to consume later 257d4afb5ceSopenharmony_ci */ 258d4afb5ceSopenharmony_ci 259d4afb5ceSopenharmony_ciint 260d4afb5ceSopenharmony_cilws_ss_serialize_state(struct lws *wsi, struct lws_dsh *dsh, lws_ss_constate_t state, 261d4afb5ceSopenharmony_ci lws_ss_tx_ordinal_t ack) 262d4afb5ceSopenharmony_ci{ 263d4afb5ceSopenharmony_ci uint8_t pre[12]; 264d4afb5ceSopenharmony_ci int n = 4; 265d4afb5ceSopenharmony_ci 266d4afb5ceSopenharmony_ci if (state == LWSSSCS_EVENT_WAIT_CANCELLED) 267d4afb5ceSopenharmony_ci return 0; 268d4afb5ceSopenharmony_ci 269d4afb5ceSopenharmony_ci lwsl_info("%s: %s, ord 0x%x\n", __func__, lws_ss_state_name((int)state), 270d4afb5ceSopenharmony_ci (unsigned int)ack); 271d4afb5ceSopenharmony_ci 272d4afb5ceSopenharmony_ci pre[0] = LWSSS_SER_RXPRE_CONNSTATE; 273d4afb5ceSopenharmony_ci pre[1] = 0; 274d4afb5ceSopenharmony_ci 275d4afb5ceSopenharmony_ci if (state > 255) { 276d4afb5ceSopenharmony_ci pre[2] = 8; 277d4afb5ceSopenharmony_ci lws_ser_wu32be(&pre[3], state); 278d4afb5ceSopenharmony_ci n = 7; 279d4afb5ceSopenharmony_ci } else { 280d4afb5ceSopenharmony_ci pre[2] = 5; 281d4afb5ceSopenharmony_ci pre[3] = (uint8_t)state; 282d4afb5ceSopenharmony_ci } 283d4afb5ceSopenharmony_ci 284d4afb5ceSopenharmony_ci lws_ser_wu32be(&pre[n], ack); 285d4afb5ceSopenharmony_ci 286d4afb5ceSopenharmony_ci if (lws_dsh_alloc_tail(dsh, KIND_SS_TO_P, pre, (unsigned int)n + 4, NULL, 0) || 287d4afb5ceSopenharmony_ci (wsi && lws_fi(&wsi->fic, "sspc_dsh_ss2p_oom"))) { 288d4afb5ceSopenharmony_ci lwsl_err("%s: unable to alloc in dsh 2\n", __func__); 289d4afb5ceSopenharmony_ci 290d4afb5ceSopenharmony_ci return 1; 291d4afb5ceSopenharmony_ci } 292d4afb5ceSopenharmony_ci 293d4afb5ceSopenharmony_ci return 0; 294d4afb5ceSopenharmony_ci} 295d4afb5ceSopenharmony_ci 296d4afb5ceSopenharmony_ci/* 297d4afb5ceSopenharmony_ci * event loop side was told about remote peer tx credit window update, serialize 298d4afb5ceSopenharmony_ci * and put it in the dbuf for the foreign side to consume later 299d4afb5ceSopenharmony_ci */ 300d4afb5ceSopenharmony_ci 301d4afb5ceSopenharmony_ciint 302d4afb5ceSopenharmony_cilws_ss_serialize_txcr(struct lws_dsh *dsh, int txcr) 303d4afb5ceSopenharmony_ci{ 304d4afb5ceSopenharmony_ci uint8_t pre[7]; 305d4afb5ceSopenharmony_ci 306d4afb5ceSopenharmony_ci lwsl_info("%s: %d\n", __func__, txcr); 307d4afb5ceSopenharmony_ci 308d4afb5ceSopenharmony_ci pre[0] = LWSSS_SER_RXPRE_TXCR_UPDATE; 309d4afb5ceSopenharmony_ci pre[1] = 0; 310d4afb5ceSopenharmony_ci pre[2] = 4; 311d4afb5ceSopenharmony_ci lws_ser_wu32be(&pre[3], (uint32_t)txcr); 312d4afb5ceSopenharmony_ci 313d4afb5ceSopenharmony_ci if (lws_dsh_alloc_tail(dsh, KIND_SS_TO_P, pre, 7, NULL, 0)) { 314d4afb5ceSopenharmony_ci lwsl_err("%s: unable to alloc in dsh 2\n", __func__); 315d4afb5ceSopenharmony_ci 316d4afb5ceSopenharmony_ci return 1; 317d4afb5ceSopenharmony_ci } 318d4afb5ceSopenharmony_ci 319d4afb5ceSopenharmony_ci return 0; 320d4afb5ceSopenharmony_ci} 321d4afb5ceSopenharmony_ci 322d4afb5ceSopenharmony_ci/* 323d4afb5ceSopenharmony_ci * event loop side is consuming serialized data from the client via dsh, parse 324d4afb5ceSopenharmony_ci * it using a bytewise parser for the serialization header(s)... 325d4afb5ceSopenharmony_ci * it's possibly coalesced 326d4afb5ceSopenharmony_ci * 327d4afb5ceSopenharmony_ci * client: pss is pointing to the start of userdata. We can use 328d4afb5ceSopenharmony_ci * pss_to_sspc_h(_pss, _ssi) to convert that to a pointer to the sspc 329d4afb5ceSopenharmony_ci * handle 330d4afb5ceSopenharmony_ci * 331d4afb5ceSopenharmony_ci * proxy: pss is pointing to &conn->ss, a pointer to the ss handle 332d4afb5ceSopenharmony_ci * 333d4afb5ceSopenharmony_ci * Returns one of 334d4afb5ceSopenharmony_ci * 335d4afb5ceSopenharmony_ci * LWSSSSRET_OK 336d4afb5ceSopenharmony_ci * LWSSSSRET_DISCONNECT_ME 337d4afb5ceSopenharmony_ci * LWSSSSRET_DESTROY_ME 338d4afb5ceSopenharmony_ci */ 339d4afb5ceSopenharmony_ci 340d4afb5ceSopenharmony_ci/* convert userdata ptr _pss to handle pointer, allowing for any layout in 341d4afb5ceSopenharmony_ci * userdata */ 342d4afb5ceSopenharmony_ci#define client_pss_to_sspc_h(_pss, _ssi) (*((lws_sspc_handle_t **) \ 343d4afb5ceSopenharmony_ci ((uint8_t *)_pss) + _ssi->handle_offset)) 344d4afb5ceSopenharmony_ci/* client pss to sspc userdata */ 345d4afb5ceSopenharmony_ci#define client_pss_to_userdata(_pss) ((void *)_pss) 346d4afb5ceSopenharmony_ci/* proxy convert pss to ss handle */ 347d4afb5ceSopenharmony_ci#define proxy_pss_to_ss_h(_pss) (*_pss) 348d4afb5ceSopenharmony_ci 349d4afb5ceSopenharmony_ci/* convert userdata ptr _pss to handle pointer, allowing for any layout in 350d4afb5ceSopenharmony_ci * userdata */ 351d4afb5ceSopenharmony_ci#define client_pss_to_sspc_h(_pss, _ssi) (*((lws_sspc_handle_t **) \ 352d4afb5ceSopenharmony_ci ((uint8_t *)_pss) + _ssi->handle_offset)) 353d4afb5ceSopenharmony_ci/* client pss to sspc userdata */ 354d4afb5ceSopenharmony_ci#define client_pss_to_userdata(_pss) ((void *)_pss) 355d4afb5ceSopenharmony_ci/* proxy convert pss to ss handle */ 356d4afb5ceSopenharmony_ci#define proxy_pss_to_ss_h(_pss) (*_pss) 357d4afb5ceSopenharmony_ci 358d4afb5ceSopenharmony_ciint 359d4afb5ceSopenharmony_cilws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, 360d4afb5ceSopenharmony_ci struct lws_context *context, 361d4afb5ceSopenharmony_ci struct lws_dsh *dsh, const uint8_t *cp, size_t len, 362d4afb5ceSopenharmony_ci lws_ss_conn_states_t *state, void *parconn, 363d4afb5ceSopenharmony_ci lws_ss_handle_t **pss, lws_ss_info_t *ssi, char client) 364d4afb5ceSopenharmony_ci{ 365d4afb5ceSopenharmony_ci lws_ss_state_return_t r; 366d4afb5ceSopenharmony_ci lws_ss_metadata_t *pm; 367d4afb5ceSopenharmony_ci lws_sspc_handle_t *h; 368d4afb5ceSopenharmony_ci uint8_t pre[23]; 369d4afb5ceSopenharmony_ci uint32_t flags; 370d4afb5ceSopenharmony_ci lws_usec_t us; 371d4afb5ceSopenharmony_ci uint8_t *p; 372d4afb5ceSopenharmony_ci int n; 373d4afb5ceSopenharmony_ci 374d4afb5ceSopenharmony_ci while (len--) { 375d4afb5ceSopenharmony_ci 376d4afb5ceSopenharmony_ci switch (par->ps) { 377d4afb5ceSopenharmony_ci case RPAR_TYPE: 378d4afb5ceSopenharmony_ci par->type = *cp++; 379d4afb5ceSopenharmony_ci par->ps++; 380d4afb5ceSopenharmony_ci break; 381d4afb5ceSopenharmony_ci 382d4afb5ceSopenharmony_ci case RPAR_LEN_MSB: /* this is remaining frame length */ 383d4afb5ceSopenharmony_ci par->rem = (uint16_t)((*cp++) << 8); 384d4afb5ceSopenharmony_ci par->ps++; 385d4afb5ceSopenharmony_ci break; 386d4afb5ceSopenharmony_ci 387d4afb5ceSopenharmony_ci case RPAR_LEN_LSB: 388d4afb5ceSopenharmony_ci par->rem = (uint16_t)(par->rem | *cp++); 389d4afb5ceSopenharmony_ci switch (par->type) { 390d4afb5ceSopenharmony_ci 391d4afb5ceSopenharmony_ci /* event loop side */ 392d4afb5ceSopenharmony_ci 393d4afb5ceSopenharmony_ci case LWSSS_SER_TXPRE_TX_PAYLOAD: 394d4afb5ceSopenharmony_ci if (client) 395d4afb5ceSopenharmony_ci goto hangup; 396d4afb5ceSopenharmony_ci if (*state != LPCSPROX_OPERATIONAL) 397d4afb5ceSopenharmony_ci goto hangup; 398d4afb5ceSopenharmony_ci 399d4afb5ceSopenharmony_ci par->ps = RPAR_FLAG_B3; 400d4afb5ceSopenharmony_ci break; 401d4afb5ceSopenharmony_ci 402d4afb5ceSopenharmony_ci case LWSSS_SER_TXPRE_DESTROYING: 403d4afb5ceSopenharmony_ci if (client) 404d4afb5ceSopenharmony_ci goto hangup; 405d4afb5ceSopenharmony_ci par->ps = RPAR_TYPE; 406d4afb5ceSopenharmony_ci lwsl_cx_notice(context, "DESTROYING"); 407d4afb5ceSopenharmony_ci goto hangup; 408d4afb5ceSopenharmony_ci 409d4afb5ceSopenharmony_ci case LWSSS_SER_TXPRE_ONWARD_CONNECT: 410d4afb5ceSopenharmony_ci if (client) 411d4afb5ceSopenharmony_ci goto hangup; 412d4afb5ceSopenharmony_ci 413d4afb5ceSopenharmony_ci if (*state != LPCSPROX_OPERATIONAL) 414d4afb5ceSopenharmony_ci goto hangup; 415d4afb5ceSopenharmony_ci 416d4afb5ceSopenharmony_ci par->ps = RPAR_TYPE; 417d4afb5ceSopenharmony_ci lwsl_cx_notice(context, "ONWARD_CONNECT"); 418d4afb5ceSopenharmony_ci 419d4afb5ceSopenharmony_ci /* 420d4afb5ceSopenharmony_ci * Shrug it off if we are already connecting or 421d4afb5ceSopenharmony_ci * connected 422d4afb5ceSopenharmony_ci */ 423d4afb5ceSopenharmony_ci 424d4afb5ceSopenharmony_ci if (!proxy_pss_to_ss_h(pss) || 425d4afb5ceSopenharmony_ci proxy_pss_to_ss_h(pss)->wsi) 426d4afb5ceSopenharmony_ci break; 427d4afb5ceSopenharmony_ci 428d4afb5ceSopenharmony_ci /* 429d4afb5ceSopenharmony_ci * We're going to try to do the onward connect 430d4afb5ceSopenharmony_ci */ 431d4afb5ceSopenharmony_ci 432d4afb5ceSopenharmony_ci if ((proxy_pss_to_ss_h(pss) && 433d4afb5ceSopenharmony_ci lws_fi(&proxy_pss_to_ss_h(pss)->fic, "ssproxy_onward_conn_fail")) || 434d4afb5ceSopenharmony_ci _lws_ss_client_connect(proxy_pss_to_ss_h(pss), 435d4afb5ceSopenharmony_ci 0, parconn) == 436d4afb5ceSopenharmony_ci LWSSSSRET_DESTROY_ME) 437d4afb5ceSopenharmony_ci goto hangup; 438d4afb5ceSopenharmony_ci break; 439d4afb5ceSopenharmony_ci 440d4afb5ceSopenharmony_ci case LWSSS_SER_TXPRE_STREAMTYPE: 441d4afb5ceSopenharmony_ci if (client) 442d4afb5ceSopenharmony_ci goto hangup; 443d4afb5ceSopenharmony_ci if (*state != LPCSPROX_WAIT_INITIAL_TX) 444d4afb5ceSopenharmony_ci goto hangup; 445d4afb5ceSopenharmony_ci if (par->rem < 1 + 4 + 1) 446d4afb5ceSopenharmony_ci goto hangup; 447d4afb5ceSopenharmony_ci par->ps = RPAR_INIT_PROVERS; 448d4afb5ceSopenharmony_ci break; 449d4afb5ceSopenharmony_ci 450d4afb5ceSopenharmony_ci case LWSSS_SER_TXPRE_METADATA: 451d4afb5ceSopenharmony_ci if (client) 452d4afb5ceSopenharmony_ci goto hangup; 453d4afb5ceSopenharmony_ci if (par->rem < 3) 454d4afb5ceSopenharmony_ci goto hangup; 455d4afb5ceSopenharmony_ci par->ctr = 0; 456d4afb5ceSopenharmony_ci par->ps = RPAR_METADATA_NAMELEN; 457d4afb5ceSopenharmony_ci break; 458d4afb5ceSopenharmony_ci 459d4afb5ceSopenharmony_ci case LWSSS_SER_TXPRE_TXCR_UPDATE: 460d4afb5ceSopenharmony_ci par->ps = RPAR_TXCR0; 461d4afb5ceSopenharmony_ci par->ctr = 0; 462d4afb5ceSopenharmony_ci break; 463d4afb5ceSopenharmony_ci 464d4afb5ceSopenharmony_ci case LWSSS_SER_TXPRE_TIMEOUT_UPDATE: 465d4afb5ceSopenharmony_ci if (client) 466d4afb5ceSopenharmony_ci goto hangup; 467d4afb5ceSopenharmony_ci if (par->rem != 4) 468d4afb5ceSopenharmony_ci goto hangup; 469d4afb5ceSopenharmony_ci par->ps = RPAR_TIMEOUT0; 470d4afb5ceSopenharmony_ci par->ctr = 0; 471d4afb5ceSopenharmony_ci break; 472d4afb5ceSopenharmony_ci 473d4afb5ceSopenharmony_ci case LWSSS_SER_TXPRE_PAYLOAD_LENGTH_HINT: 474d4afb5ceSopenharmony_ci if (client) 475d4afb5ceSopenharmony_ci goto hangup; 476d4afb5ceSopenharmony_ci if (par->rem != 4) 477d4afb5ceSopenharmony_ci goto hangup; 478d4afb5ceSopenharmony_ci par->ps = RPAR_PAYLEN0; 479d4afb5ceSopenharmony_ci par->ctr = 0; 480d4afb5ceSopenharmony_ci break; 481d4afb5ceSopenharmony_ci 482d4afb5ceSopenharmony_ci /* client side */ 483d4afb5ceSopenharmony_ci 484d4afb5ceSopenharmony_ci case LWSSS_SER_RXPRE_RX_PAYLOAD: 485d4afb5ceSopenharmony_ci if (!client) 486d4afb5ceSopenharmony_ci goto hangup; 487d4afb5ceSopenharmony_ci if (*state != LPCSCLI_OPERATIONAL && 488d4afb5ceSopenharmony_ci *state != LPCSCLI_LOCAL_CONNECTED) 489d4afb5ceSopenharmony_ci goto hangup; 490d4afb5ceSopenharmony_ci 491d4afb5ceSopenharmony_ci par->rideshare[0] = '\0'; 492d4afb5ceSopenharmony_ci par->ps = RPAR_FLAG_B3; 493d4afb5ceSopenharmony_ci break; 494d4afb5ceSopenharmony_ci 495d4afb5ceSopenharmony_ci case LWSSS_SER_RXPRE_CREATE_RESULT: 496d4afb5ceSopenharmony_ci if (!client) 497d4afb5ceSopenharmony_ci goto hangup; 498d4afb5ceSopenharmony_ci if (*state != LPCSCLI_WAITING_CREATE_RESULT) 499d4afb5ceSopenharmony_ci goto hangup; 500d4afb5ceSopenharmony_ci 501d4afb5ceSopenharmony_ci if (par->rem < 1) 502d4afb5ceSopenharmony_ci goto hangup; 503d4afb5ceSopenharmony_ci 504d4afb5ceSopenharmony_ci par->ps = RPAR_RESULT_CREATION; 505d4afb5ceSopenharmony_ci break; 506d4afb5ceSopenharmony_ci 507d4afb5ceSopenharmony_ci case LWSSS_SER_RXPRE_CONNSTATE: 508d4afb5ceSopenharmony_ci if (!client) 509d4afb5ceSopenharmony_ci goto hangup; 510d4afb5ceSopenharmony_ci if (*state != LPCSCLI_LOCAL_CONNECTED && 511d4afb5ceSopenharmony_ci *state != LPCSCLI_OPERATIONAL) 512d4afb5ceSopenharmony_ci goto hangup; 513d4afb5ceSopenharmony_ci 514d4afb5ceSopenharmony_ci if (par->rem < 5 || par->rem > 8) 515d4afb5ceSopenharmony_ci goto hangup; 516d4afb5ceSopenharmony_ci 517d4afb5ceSopenharmony_ci par->ps = RPAR_STATEINDEX; 518d4afb5ceSopenharmony_ci par->ctr = 0; 519d4afb5ceSopenharmony_ci break; 520d4afb5ceSopenharmony_ci 521d4afb5ceSopenharmony_ci case LWSSS_SER_RXPRE_METADATA: 522d4afb5ceSopenharmony_ci if (!client) 523d4afb5ceSopenharmony_ci goto hangup; 524d4afb5ceSopenharmony_ci if (par->rem < 3) 525d4afb5ceSopenharmony_ci goto hangup; 526d4afb5ceSopenharmony_ci par->ctr = 0; 527d4afb5ceSopenharmony_ci par->ps = RPAR_METADATA_NAMELEN; 528d4afb5ceSopenharmony_ci break; 529d4afb5ceSopenharmony_ci 530d4afb5ceSopenharmony_ci case LWSSS_SER_RXPRE_TXCR_UPDATE: 531d4afb5ceSopenharmony_ci par->ctr = 0; 532d4afb5ceSopenharmony_ci par->ps = RPAR_RX_TXCR_UPDATE; 533d4afb5ceSopenharmony_ci break; 534d4afb5ceSopenharmony_ci 535d4afb5ceSopenharmony_ci case LWSSS_SER_RXPRE_PERF: 536d4afb5ceSopenharmony_ci par->ctr = 0; 537d4afb5ceSopenharmony_ci if (!par->rem) 538d4afb5ceSopenharmony_ci goto hangup; 539d4afb5ceSopenharmony_ci par->ps = RPAR_PERF; 540d4afb5ceSopenharmony_ci break; 541d4afb5ceSopenharmony_ci 542d4afb5ceSopenharmony_ci default: 543d4afb5ceSopenharmony_ci lwsl_cx_notice(context, "bad type 0x%x", 544d4afb5ceSopenharmony_ci par->type); 545d4afb5ceSopenharmony_ci goto hangup; 546d4afb5ceSopenharmony_ci } 547d4afb5ceSopenharmony_ci break; 548d4afb5ceSopenharmony_ci 549d4afb5ceSopenharmony_ci case RPAR_FLAG_B3: 550d4afb5ceSopenharmony_ci case RPAR_FLAG_B2: 551d4afb5ceSopenharmony_ci case RPAR_FLAG_B1: 552d4afb5ceSopenharmony_ci case RPAR_FLAG_B0: 553d4afb5ceSopenharmony_ci par->flags <<= 8; 554d4afb5ceSopenharmony_ci par->flags |= *cp++; 555d4afb5ceSopenharmony_ci par->ps++; 556d4afb5ceSopenharmony_ci if (!par->rem--) 557d4afb5ceSopenharmony_ci goto hangup; 558d4afb5ceSopenharmony_ci break; 559d4afb5ceSopenharmony_ci 560d4afb5ceSopenharmony_ci case RPAR_LATA3: 561d4afb5ceSopenharmony_ci case RPAR_LATA2: 562d4afb5ceSopenharmony_ci case RPAR_LATA1: 563d4afb5ceSopenharmony_ci case RPAR_LATA0: 564d4afb5ceSopenharmony_ci par->usd_phandling <<= 8; 565d4afb5ceSopenharmony_ci par->usd_phandling |= *cp++; 566d4afb5ceSopenharmony_ci par->ps++; 567d4afb5ceSopenharmony_ci if (!par->rem--) 568d4afb5ceSopenharmony_ci goto hangup; 569d4afb5ceSopenharmony_ci break; 570d4afb5ceSopenharmony_ci 571d4afb5ceSopenharmony_ci case RPAR_LATB7: 572d4afb5ceSopenharmony_ci case RPAR_LATB6: 573d4afb5ceSopenharmony_ci case RPAR_LATB5: 574d4afb5ceSopenharmony_ci case RPAR_LATB4: 575d4afb5ceSopenharmony_ci case RPAR_LATB3: 576d4afb5ceSopenharmony_ci case RPAR_LATB2: 577d4afb5ceSopenharmony_ci case RPAR_LATB1: 578d4afb5ceSopenharmony_ci case RPAR_LATB0: 579d4afb5ceSopenharmony_ci par->ust_pwait <<= 8; 580d4afb5ceSopenharmony_ci par->ust_pwait |= *cp++; 581d4afb5ceSopenharmony_ci par->ps++; 582d4afb5ceSopenharmony_ci par->frag1 = 1; 583d4afb5ceSopenharmony_ci if (!par->rem--) 584d4afb5ceSopenharmony_ci goto hangup; 585d4afb5ceSopenharmony_ci 586d4afb5ceSopenharmony_ci if (par->ps == RPAR_RIDESHARE_LEN && 587d4afb5ceSopenharmony_ci !(par->flags & LWSSS_FLAG_RIDESHARE)) 588d4afb5ceSopenharmony_ci par->ps = RPAR_PAYLOAD; 589d4afb5ceSopenharmony_ci 590d4afb5ceSopenharmony_ci if (par->rem) 591d4afb5ceSopenharmony_ci break; 592d4afb5ceSopenharmony_ci 593d4afb5ceSopenharmony_ci /* fallthru - handle 0-length payload */ 594d4afb5ceSopenharmony_ci 595d4afb5ceSopenharmony_ci if (!(par->flags & LWSSS_FLAG_RIDESHARE)) 596d4afb5ceSopenharmony_ci goto payload_ff; 597d4afb5ceSopenharmony_ci goto hangup; 598d4afb5ceSopenharmony_ci 599d4afb5ceSopenharmony_ci /* 600d4afb5ceSopenharmony_ci * Inbound rideshare info is provided on the RX packet 601d4afb5ceSopenharmony_ci * itself 602d4afb5ceSopenharmony_ci */ 603d4afb5ceSopenharmony_ci 604d4afb5ceSopenharmony_ci case RPAR_RIDESHARE_LEN: 605d4afb5ceSopenharmony_ci par->slen = *cp++; 606d4afb5ceSopenharmony_ci par->ctr = 0; 607d4afb5ceSopenharmony_ci par->ps++; 608d4afb5ceSopenharmony_ci if (par->rem-- < par->slen) 609d4afb5ceSopenharmony_ci goto hangup; 610d4afb5ceSopenharmony_ci break; 611d4afb5ceSopenharmony_ci 612d4afb5ceSopenharmony_ci case RPAR_PERF: 613d4afb5ceSopenharmony_ci n = (int)len + 1; 614d4afb5ceSopenharmony_ci if (n > par->rem) 615d4afb5ceSopenharmony_ci n = par->rem; 616d4afb5ceSopenharmony_ci 617d4afb5ceSopenharmony_ci if (client && 618d4afb5ceSopenharmony_ci client_pss_to_sspc_h(pss, ssi) && 619d4afb5ceSopenharmony_ci ssi->rx) { 620d4afb5ceSopenharmony_ci int ret; 621d4afb5ceSopenharmony_ci 622d4afb5ceSopenharmony_ci /* we still have an sspc handle */ 623d4afb5ceSopenharmony_ci ret = ssi->rx(client_pss_to_userdata(pss), 624d4afb5ceSopenharmony_ci (uint8_t *)cp, (unsigned int)n, 625d4afb5ceSopenharmony_ci (int)(LWSSS_FLAG_SOM | LWSSS_FLAG_EOM | 626d4afb5ceSopenharmony_ci LWSSS_FLAG_PERF_JSON)); 627d4afb5ceSopenharmony_ci 628d4afb5ceSopenharmony_ci if (lws_fi(&client_pss_to_sspc_h(pss, ssi)->fic, 629d4afb5ceSopenharmony_ci "sspc_perf_rx_fake_destroy_me")) 630d4afb5ceSopenharmony_ci ret = LWSSSSRET_DESTROY_ME; 631d4afb5ceSopenharmony_ci 632d4afb5ceSopenharmony_ci switch (ret) { 633d4afb5ceSopenharmony_ci case LWSSSSRET_OK: 634d4afb5ceSopenharmony_ci break; 635d4afb5ceSopenharmony_ci case LWSSSSRET_DISCONNECT_ME: 636d4afb5ceSopenharmony_ci goto hangup; 637d4afb5ceSopenharmony_ci case LWSSSSRET_DESTROY_ME: 638d4afb5ceSopenharmony_ci return LWSSSSRET_DESTROY_ME; 639d4afb5ceSopenharmony_ci } 640d4afb5ceSopenharmony_ci } 641d4afb5ceSopenharmony_ci if (n) { 642d4afb5ceSopenharmony_ci cp += n; 643d4afb5ceSopenharmony_ci par->rem = (uint16_t)(par->rem - (uint16_t)(unsigned int)n); 644d4afb5ceSopenharmony_ci len = (len + 1) - (unsigned int)n; 645d4afb5ceSopenharmony_ci } 646d4afb5ceSopenharmony_ci if (!par->rem) 647d4afb5ceSopenharmony_ci par->ps = RPAR_TYPE; 648d4afb5ceSopenharmony_ci break; 649d4afb5ceSopenharmony_ci 650d4afb5ceSopenharmony_ci case RPAR_RIDESHARE: 651d4afb5ceSopenharmony_ci par->rideshare[par->ctr++] = (char)*cp++; 652d4afb5ceSopenharmony_ci if (!par->rem--) 653d4afb5ceSopenharmony_ci goto hangup; 654d4afb5ceSopenharmony_ci if (par->ctr != par->slen) 655d4afb5ceSopenharmony_ci break; 656d4afb5ceSopenharmony_ci par->ps = RPAR_PAYLOAD; 657d4afb5ceSopenharmony_ci if (par->rem) 658d4afb5ceSopenharmony_ci break; 659d4afb5ceSopenharmony_ci 660d4afb5ceSopenharmony_ci /* fallthru - handle 0-length payload */ 661d4afb5ceSopenharmony_ci 662d4afb5ceSopenharmony_ci case RPAR_PAYLOAD: 663d4afb5ceSopenharmony_cipayload_ff: 664d4afb5ceSopenharmony_ci n = (int)len + 1; 665d4afb5ceSopenharmony_ci if (n > par->rem) 666d4afb5ceSopenharmony_ci n = par->rem; 667d4afb5ceSopenharmony_ci /* 668d4afb5ceSopenharmony_ci * We get called with a serialized buffer of a size 669d4afb5ceSopenharmony_ci * chosen by the client. We can only create dsh entries 670d4afb5ceSopenharmony_ci * with up to 1380 payload, to guarantee we can emit 671d4afb5ceSopenharmony_ci * them on the onward connection atomically. 672d4afb5ceSopenharmony_ci * 673d4afb5ceSopenharmony_ci * If 1380 isn't enough to cover what was handed to us, 674d4afb5ceSopenharmony_ci * we'll stop at 1380 and go around again and create 675d4afb5ceSopenharmony_ci * more dsh entries for the rest, with their own 676d4afb5ceSopenharmony_ci * headers. 677d4afb5ceSopenharmony_ci */ 678d4afb5ceSopenharmony_ci 679d4afb5ceSopenharmony_ci if (n > 1380) 680d4afb5ceSopenharmony_ci n = 1380; 681d4afb5ceSopenharmony_ci 682d4afb5ceSopenharmony_ci /* 683d4afb5ceSopenharmony_ci * Since we're in the business of fragmenting client 684d4afb5ceSopenharmony_ci * serialized payloads at 1380, we have to deal with 685d4afb5ceSopenharmony_ci * refragmenting the SOM / EOM flags that covered the 686d4afb5ceSopenharmony_ci * whole client serialized packet, so they apply to 687d4afb5ceSopenharmony_ci * each dsh entry we split it into correctly 688d4afb5ceSopenharmony_ci */ 689d4afb5ceSopenharmony_ci 690d4afb5ceSopenharmony_ci flags = par->flags & LWSSS_FLAG_RELATED_START; 691d4afb5ceSopenharmony_ci if (par->frag1) 692d4afb5ceSopenharmony_ci /* 693d4afb5ceSopenharmony_ci * Only set the first time we came to this 694d4afb5ceSopenharmony_ci * state after deserialization of the header 695d4afb5ceSopenharmony_ci */ 696d4afb5ceSopenharmony_ci flags |= par->flags & 697d4afb5ceSopenharmony_ci (LWSSS_FLAG_SOM | LWSSS_FLAG_POLL); 698d4afb5ceSopenharmony_ci 699d4afb5ceSopenharmony_ci if (par->rem == n) 700d4afb5ceSopenharmony_ci /* 701d4afb5ceSopenharmony_ci * We are going to complete the advertised 702d4afb5ceSopenharmony_ci * payload length from the client on this dsh, 703d4afb5ceSopenharmony_ci * so give him the EOM type flags if any 704d4afb5ceSopenharmony_ci */ 705d4afb5ceSopenharmony_ci flags |= par->flags & (LWSSS_FLAG_EOM | 706d4afb5ceSopenharmony_ci LWSSS_FLAG_RELATED_END); 707d4afb5ceSopenharmony_ci 708d4afb5ceSopenharmony_ci par->frag1 = 0; 709d4afb5ceSopenharmony_ci us = lws_now_usecs(); 710d4afb5ceSopenharmony_ci 711d4afb5ceSopenharmony_ci if (!client) { 712d4afb5ceSopenharmony_ci lws_ss_handle_t *hss; 713d4afb5ceSopenharmony_ci 714d4afb5ceSopenharmony_ci /* 715d4afb5ceSopenharmony_ci * Proxy - we received some serialized tx from 716d4afb5ceSopenharmony_ci * the client. 717d4afb5ceSopenharmony_ci * 718d4afb5ceSopenharmony_ci * The header for buffering private to the 719d4afb5ceSopenharmony_ci * proxy is 23 bytes vs 19, so we can hold the 720d4afb5ceSopenharmony_ci * current time when it was buffered 721d4afb5ceSopenharmony_ci * additionally 722d4afb5ceSopenharmony_ci */ 723d4afb5ceSopenharmony_ci 724d4afb5ceSopenharmony_ci hss = proxy_pss_to_ss_h(pss); 725d4afb5ceSopenharmony_ci if (hss) 726d4afb5ceSopenharmony_ci lwsl_ss_info(hss, "C2P RX: len %d", (int)n); 727d4afb5ceSopenharmony_ci 728d4afb5ceSopenharmony_ci p = pre; 729d4afb5ceSopenharmony_ci pre[0] = LWSSS_SER_TXPRE_TX_PAYLOAD; 730d4afb5ceSopenharmony_ci lws_ser_wu16be(&p[1], (uint16_t)((unsigned int)n + 23 - 3)); 731d4afb5ceSopenharmony_ci lws_ser_wu32be(&p[3], flags); 732d4afb5ceSopenharmony_ci /* us held at client before written */ 733d4afb5ceSopenharmony_ci lws_ser_wu32be(&p[7], par->usd_phandling); 734d4afb5ceSopenharmony_ci /* us taken for transit to proxy */ 735d4afb5ceSopenharmony_ci lws_ser_wu32be(&p[11], (uint32_t)(us - (lws_usec_t)par->ust_pwait)); 736d4afb5ceSopenharmony_ci /* time used later to find proxy hold time */ 737d4afb5ceSopenharmony_ci lws_ser_wu64be(&p[15], (uint64_t)us); 738d4afb5ceSopenharmony_ci 739d4afb5ceSopenharmony_ci if ((hss && 740d4afb5ceSopenharmony_ci lws_fi(&hss->fic, "ssproxy_dsh_c2p_pay_oom")) || 741d4afb5ceSopenharmony_ci lws_dsh_alloc_tail(dsh, KIND_C_TO_P, pre, 742d4afb5ceSopenharmony_ci 23, cp, (unsigned int)n)) { 743d4afb5ceSopenharmony_ci lwsl_ss_err(hss, "unable to alloc in dsh 3"); 744d4afb5ceSopenharmony_ci 745d4afb5ceSopenharmony_ci return LWSSSSRET_DISCONNECT_ME; 746d4afb5ceSopenharmony_ci } 747d4afb5ceSopenharmony_ci 748d4afb5ceSopenharmony_ci if (hss) 749d4afb5ceSopenharmony_ci _lws_ss_request_tx(hss); 750d4afb5ceSopenharmony_ci } else { 751d4afb5ceSopenharmony_ci 752d4afb5ceSopenharmony_ci /* 753d4afb5ceSopenharmony_ci * Client receives some RX from proxy 754d4afb5ceSopenharmony_ci * 755d4afb5ceSopenharmony_ci * Pass whatever payload we have to ss user 756d4afb5ceSopenharmony_ci */ 757d4afb5ceSopenharmony_ci 758d4afb5ceSopenharmony_ci h = lws_container_of(par, lws_sspc_handle_t, 759d4afb5ceSopenharmony_ci parser); 760d4afb5ceSopenharmony_ci h->txc.peer_tx_cr_est -= n; 761d4afb5ceSopenharmony_ci 762d4afb5ceSopenharmony_ci lwsl_sspc_info(h, "P2C RX: len %d", (int)n); 763d4afb5ceSopenharmony_ci 764d4afb5ceSopenharmony_ci if (ssi->rx && client_pss_to_sspc_h(pss, ssi)) { 765d4afb5ceSopenharmony_ci /* we still have an sspc handle */ 766d4afb5ceSopenharmony_ci int ret; 767d4afb5ceSopenharmony_ci 768d4afb5ceSopenharmony_ci ret = ssi->rx(client_pss_to_userdata(pss), 769d4afb5ceSopenharmony_ci (uint8_t *)cp, (unsigned int)n, (int)flags); 770d4afb5ceSopenharmony_ci 771d4afb5ceSopenharmony_ci if (client_pss_to_sspc_h(pss, ssi) && 772d4afb5ceSopenharmony_ci lws_fi(&client_pss_to_sspc_h(pss, ssi)->fic, "sspc_rx_fake_destroy_me")) 773d4afb5ceSopenharmony_ci ret = LWSSSSRET_DESTROY_ME; 774d4afb5ceSopenharmony_ci 775d4afb5ceSopenharmony_ci switch (ret) { 776d4afb5ceSopenharmony_ci case LWSSSSRET_OK: 777d4afb5ceSopenharmony_ci break; 778d4afb5ceSopenharmony_ci case LWSSSSRET_DISCONNECT_ME: 779d4afb5ceSopenharmony_ci goto hangup; 780d4afb5ceSopenharmony_ci case LWSSSSRET_DESTROY_ME: 781d4afb5ceSopenharmony_ci return LWSSSSRET_DESTROY_ME; 782d4afb5ceSopenharmony_ci } 783d4afb5ceSopenharmony_ci } 784d4afb5ceSopenharmony_ci 785d4afb5ceSopenharmony_ci#if 0 786d4afb5ceSopenharmony_ci if (lws_det_lat_active(context)) { 787d4afb5ceSopenharmony_ci lws_detlat_t d; 788d4afb5ceSopenharmony_ci 789d4afb5ceSopenharmony_ci d.type = LDLT_READ; 790d4afb5ceSopenharmony_ci d.acc_size = d.req_size = n; 791d4afb5ceSopenharmony_ci d.latencies[LAT_DUR_USERCB] = 792d4afb5ceSopenharmony_ci lws_now_usecs() - us; 793d4afb5ceSopenharmony_ci d.latencies[LAT_DUR_PROXY_CLIENT_REQ_TO_WRITE] = 794d4afb5ceSopenharmony_ci par->usd_phandling; 795d4afb5ceSopenharmony_ci d.latencies[LAT_DUR_PROXY_CLIENT_WRITE_TO_PROXY_RX] = 796d4afb5ceSopenharmony_ci us - par->ust_pwait; 797d4afb5ceSopenharmony_ci 798d4afb5ceSopenharmony_ci lws_det_lat_cb(context, &d); 799d4afb5ceSopenharmony_ci } 800d4afb5ceSopenharmony_ci#endif 801d4afb5ceSopenharmony_ci } 802d4afb5ceSopenharmony_ci 803d4afb5ceSopenharmony_ci if (n) { 804d4afb5ceSopenharmony_ci cp += n; 805d4afb5ceSopenharmony_ci par->rem = (uint16_t)(par->rem - (uint16_t)(unsigned int)n); 806d4afb5ceSopenharmony_ci len = (len + 1) - (unsigned int)n; 807d4afb5ceSopenharmony_ci /* 808d4afb5ceSopenharmony_ci * if we didn't consume it all, we'll come 809d4afb5ceSopenharmony_ci * around again and produce more dsh entries up 810d4afb5ceSopenharmony_ci * to 1380 each until it is gone 811d4afb5ceSopenharmony_ci */ 812d4afb5ceSopenharmony_ci } 813d4afb5ceSopenharmony_ci if (!par->rem) 814d4afb5ceSopenharmony_ci par->ps = RPAR_TYPE; 815d4afb5ceSopenharmony_ci break; 816d4afb5ceSopenharmony_ci 817d4afb5ceSopenharmony_ci case RPAR_RX_TXCR_UPDATE: 818d4afb5ceSopenharmony_ci if (!--par->rem && par->ctr != 3) 819d4afb5ceSopenharmony_ci goto hangup; 820d4afb5ceSopenharmony_ci 821d4afb5ceSopenharmony_ci par->temp32 = (par->temp32 << 8) | *cp++; 822d4afb5ceSopenharmony_ci if (++par->ctr < 4) 823d4afb5ceSopenharmony_ci break; 824d4afb5ceSopenharmony_ci 825d4afb5ceSopenharmony_ci /* 826d4afb5ceSopenharmony_ci * Proxy is telling us remote endpoint is allowing us 827d4afb5ceSopenharmony_ci * par->temp32 more bytes tx credit to write to it 828d4afb5ceSopenharmony_ci */ 829d4afb5ceSopenharmony_ci 830d4afb5ceSopenharmony_ci h = lws_container_of(par, lws_sspc_handle_t, parser); 831d4afb5ceSopenharmony_ci h->txc.tx_cr += par->temp32; 832d4afb5ceSopenharmony_ci lwsl_info("%s: RX_PEER_TXCR: %d\n", __func__, par->temp32); 833d4afb5ceSopenharmony_ci lws_sspc_request_tx(h); /* in case something waiting */ 834d4afb5ceSopenharmony_ci par->ctr = 0; 835d4afb5ceSopenharmony_ci par->ps = RPAR_TYPE; 836d4afb5ceSopenharmony_ci break; 837d4afb5ceSopenharmony_ci 838d4afb5ceSopenharmony_ci case RPAR_INIT_PROVERS: 839d4afb5ceSopenharmony_ci /* Protocol version byte for this connection */ 840d4afb5ceSopenharmony_ci par->protocol_version = *cp++; 841d4afb5ceSopenharmony_ci 842d4afb5ceSopenharmony_ci /* 843d4afb5ceSopenharmony_ci * So we have to know what versions of the serialization 844d4afb5ceSopenharmony_ci * protocol we can support at the proxy side, and 845d4afb5ceSopenharmony_ci * reject anythng we don't know how to deal with 846d4afb5ceSopenharmony_ci * noisily in the logs. 847d4afb5ceSopenharmony_ci */ 848d4afb5ceSopenharmony_ci 849d4afb5ceSopenharmony_ci if (par->protocol_version != 1) { 850d4afb5ceSopenharmony_ci lwsl_err("%s: Rejecting client with " 851d4afb5ceSopenharmony_ci "unsupported SSv%d protocol\n", 852d4afb5ceSopenharmony_ci __func__, par->protocol_version); 853d4afb5ceSopenharmony_ci 854d4afb5ceSopenharmony_ci goto hangup; 855d4afb5ceSopenharmony_ci } 856d4afb5ceSopenharmony_ci 857d4afb5ceSopenharmony_ci if (!--par->rem) 858d4afb5ceSopenharmony_ci goto hangup; 859d4afb5ceSopenharmony_ci par->ctr = 0; 860d4afb5ceSopenharmony_ci par->ps = RPAR_INIT_PID; 861d4afb5ceSopenharmony_ci break; 862d4afb5ceSopenharmony_ci 863d4afb5ceSopenharmony_ci 864d4afb5ceSopenharmony_ci case RPAR_INIT_PID: 865d4afb5ceSopenharmony_ci if (!--par->rem) 866d4afb5ceSopenharmony_ci goto hangup; 867d4afb5ceSopenharmony_ci 868d4afb5ceSopenharmony_ci par->temp32 = (par->temp32 << 8) | *cp++; 869d4afb5ceSopenharmony_ci if (++par->ctr < 4) 870d4afb5ceSopenharmony_ci break; 871d4afb5ceSopenharmony_ci 872d4afb5ceSopenharmony_ci par->client_pid = (uint32_t)par->temp32; 873d4afb5ceSopenharmony_ci par->ctr = 0; 874d4afb5ceSopenharmony_ci par->ps = RPAR_INITTXC0; 875d4afb5ceSopenharmony_ci break; 876d4afb5ceSopenharmony_ci 877d4afb5ceSopenharmony_ci case RPAR_INITTXC0: 878d4afb5ceSopenharmony_ci if (!--par->rem) 879d4afb5ceSopenharmony_ci goto hangup; 880d4afb5ceSopenharmony_ci 881d4afb5ceSopenharmony_ci par->temp32 = (par->temp32 << 8) | *cp++; 882d4afb5ceSopenharmony_ci if (++par->ctr < 4) 883d4afb5ceSopenharmony_ci break; 884d4afb5ceSopenharmony_ci 885d4afb5ceSopenharmony_ci par->txcr_out = par->temp32; 886d4afb5ceSopenharmony_ci par->ctr = 0; 887d4afb5ceSopenharmony_ci par->ps = RPAR_STREAMTYPE; 888d4afb5ceSopenharmony_ci break; 889d4afb5ceSopenharmony_ci 890d4afb5ceSopenharmony_ci /* 891d4afb5ceSopenharmony_ci * These are the client adjusting our / the remote peer ability 892d4afb5ceSopenharmony_ci * to send back to him. He's sending a signed u32 BE 893d4afb5ceSopenharmony_ci */ 894d4afb5ceSopenharmony_ci 895d4afb5ceSopenharmony_ci case RPAR_TXCR0: 896d4afb5ceSopenharmony_ci 897d4afb5ceSopenharmony_ci par->temp32 = (par->temp32 << 8) | *cp++; 898d4afb5ceSopenharmony_ci if (++par->ctr < 4) { 899d4afb5ceSopenharmony_ci if (!--par->rem) 900d4afb5ceSopenharmony_ci goto hangup; 901d4afb5ceSopenharmony_ci break; 902d4afb5ceSopenharmony_ci } 903d4afb5ceSopenharmony_ci 904d4afb5ceSopenharmony_ci if (--par->rem) 905d4afb5ceSopenharmony_ci goto hangup; 906d4afb5ceSopenharmony_ci 907d4afb5ceSopenharmony_ci if (!client) { 908d4afb5ceSopenharmony_ci /* 909d4afb5ceSopenharmony_ci * We're the proxy, being told by the client 910d4afb5ceSopenharmony_ci * that it wants to allow more tx from the peer 911d4afb5ceSopenharmony_ci * on the onward connection towards it. 912d4afb5ceSopenharmony_ci */ 913d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_H2) || defined(LWS_ROLE_MQTT) 914d4afb5ceSopenharmony_ci if (proxy_pss_to_ss_h(pss) && 915d4afb5ceSopenharmony_ci proxy_pss_to_ss_h(pss)->wsi) { 916d4afb5ceSopenharmony_ci lws_wsi_tx_credit( 917d4afb5ceSopenharmony_ci proxy_pss_to_ss_h(pss)->wsi, 918d4afb5ceSopenharmony_ci LWSTXCR_PEER_TO_US, 919d4afb5ceSopenharmony_ci par->temp32); 920d4afb5ceSopenharmony_ci lwsl_notice("%s: proxy RX_PEER_TXCR: +%d (est %d)\n", 921d4afb5ceSopenharmony_ci __func__, par->temp32, 922d4afb5ceSopenharmony_ci proxy_pss_to_ss_h(pss)->wsi-> 923d4afb5ceSopenharmony_ci txc.peer_tx_cr_est); 924d4afb5ceSopenharmony_ci _lws_ss_request_tx(proxy_pss_to_ss_h(pss)); 925d4afb5ceSopenharmony_ci } else 926d4afb5ceSopenharmony_ci#endif 927d4afb5ceSopenharmony_ci lwsl_info("%s: dropping TXCR\n", __func__); 928d4afb5ceSopenharmony_ci } else { 929d4afb5ceSopenharmony_ci /* 930d4afb5ceSopenharmony_ci * We're the client, being told by the proxy 931d4afb5ceSopenharmony_ci * about tx credit being given to us from the 932d4afb5ceSopenharmony_ci * remote peer, allowing the client to write to 933d4afb5ceSopenharmony_ci * it. 934d4afb5ceSopenharmony_ci */ 935d4afb5ceSopenharmony_ci h = lws_container_of(par, lws_sspc_handle_t, 936d4afb5ceSopenharmony_ci parser); 937d4afb5ceSopenharmony_ci h->txc.tx_cr += par->temp32; 938d4afb5ceSopenharmony_ci lwsl_info("%s: client RX_PEER_TXCR: %d\n", 939d4afb5ceSopenharmony_ci __func__, par->temp32); 940d4afb5ceSopenharmony_ci lws_sspc_request_tx(h); /* in case something waiting */ 941d4afb5ceSopenharmony_ci } 942d4afb5ceSopenharmony_ci par->ps = RPAR_TYPE; 943d4afb5ceSopenharmony_ci break; 944d4afb5ceSopenharmony_ci 945d4afb5ceSopenharmony_ci case RPAR_TIMEOUT0: 946d4afb5ceSopenharmony_ci 947d4afb5ceSopenharmony_ci par->temp32 = (par->temp32 << 8) | *cp++; 948d4afb5ceSopenharmony_ci if (++par->ctr < 4) { 949d4afb5ceSopenharmony_ci if (!--par->rem) 950d4afb5ceSopenharmony_ci goto hangup; 951d4afb5ceSopenharmony_ci break; 952d4afb5ceSopenharmony_ci } 953d4afb5ceSopenharmony_ci 954d4afb5ceSopenharmony_ci if (--par->rem) 955d4afb5ceSopenharmony_ci goto hangup; 956d4afb5ceSopenharmony_ci 957d4afb5ceSopenharmony_ci /* 958d4afb5ceSopenharmony_ci * Proxy... 959d4afb5ceSopenharmony_ci * 960d4afb5ceSopenharmony_ci * *pss may have gone away asynchronously inbetweentimes 961d4afb5ceSopenharmony_ci */ 962d4afb5ceSopenharmony_ci 963d4afb5ceSopenharmony_ci if (proxy_pss_to_ss_h(pss)) { 964d4afb5ceSopenharmony_ci 965d4afb5ceSopenharmony_ci if ((unsigned int)par->temp32 == 0xffffffff) { 966d4afb5ceSopenharmony_ci lwsl_notice("%s: cancel ss timeout\n", 967d4afb5ceSopenharmony_ci __func__); 968d4afb5ceSopenharmony_ci lws_ss_cancel_timeout( 969d4afb5ceSopenharmony_ci proxy_pss_to_ss_h(pss)); 970d4afb5ceSopenharmony_ci } else { 971d4afb5ceSopenharmony_ci 972d4afb5ceSopenharmony_ci if (!par->temp32) 973d4afb5ceSopenharmony_ci par->temp32 = (int) 974d4afb5ceSopenharmony_ci proxy_pss_to_ss_h(pss)-> 975d4afb5ceSopenharmony_ci policy->timeout_ms; 976d4afb5ceSopenharmony_ci 977d4afb5ceSopenharmony_ci lwsl_notice("%s: set ss timeout for +%ums\n", 978d4afb5ceSopenharmony_ci __func__, par->temp32); 979d4afb5ceSopenharmony_ci 980d4afb5ceSopenharmony_ci lws_ss_start_timeout( 981d4afb5ceSopenharmony_ci proxy_pss_to_ss_h(pss), (unsigned int) 982d4afb5ceSopenharmony_ci par->temp32); 983d4afb5ceSopenharmony_ci } 984d4afb5ceSopenharmony_ci } 985d4afb5ceSopenharmony_ci 986d4afb5ceSopenharmony_ci par->ps = RPAR_TYPE; 987d4afb5ceSopenharmony_ci break; 988d4afb5ceSopenharmony_ci 989d4afb5ceSopenharmony_ci case RPAR_PAYLEN0: 990d4afb5ceSopenharmony_ci /* 991d4afb5ceSopenharmony_ci * It's the length from lws_ss_request_tx_len() being 992d4afb5ceSopenharmony_ci * passed up to the proxy 993d4afb5ceSopenharmony_ci */ 994d4afb5ceSopenharmony_ci par->temp32 = (par->temp32 << 8) | *cp++; 995d4afb5ceSopenharmony_ci if (++par->ctr < 4) { 996d4afb5ceSopenharmony_ci if (!--par->rem) 997d4afb5ceSopenharmony_ci goto hangup; 998d4afb5ceSopenharmony_ci break; 999d4afb5ceSopenharmony_ci } 1000d4afb5ceSopenharmony_ci 1001d4afb5ceSopenharmony_ci if (--par->rem) 1002d4afb5ceSopenharmony_ci goto hangup; 1003d4afb5ceSopenharmony_ci 1004d4afb5ceSopenharmony_ci lwsl_notice("%s: set payload len %u\n", __func__, 1005d4afb5ceSopenharmony_ci par->temp32); 1006d4afb5ceSopenharmony_ci 1007d4afb5ceSopenharmony_ci par->ps = RPAR_TYPE; 1008d4afb5ceSopenharmony_ci 1009d4afb5ceSopenharmony_ci if (proxy_pss_to_ss_h(pss)) { 1010d4afb5ceSopenharmony_ci r = lws_ss_request_tx_len(proxy_pss_to_ss_h(pss), 1011d4afb5ceSopenharmony_ci (unsigned long)par->temp32); 1012d4afb5ceSopenharmony_ci if (r == LWSSSSRET_DESTROY_ME) 1013d4afb5ceSopenharmony_ci goto hangup; 1014d4afb5ceSopenharmony_ci } 1015d4afb5ceSopenharmony_ci break; 1016d4afb5ceSopenharmony_ci 1017d4afb5ceSopenharmony_ci case RPAR_METADATA_NAMELEN: 1018d4afb5ceSopenharmony_ci /* both client and proxy */ 1019d4afb5ceSopenharmony_ci if (!--par->rem) 1020d4afb5ceSopenharmony_ci goto hangup; 1021d4afb5ceSopenharmony_ci par->slen = *cp++; 1022d4afb5ceSopenharmony_ci if (par->slen >= sizeof(par->metadata_name) - 1) 1023d4afb5ceSopenharmony_ci goto hangup; 1024d4afb5ceSopenharmony_ci par->ctr = 0; 1025d4afb5ceSopenharmony_ci par->ps++; 1026d4afb5ceSopenharmony_ci break; 1027d4afb5ceSopenharmony_ci 1028d4afb5ceSopenharmony_ci case RPAR_METADATA_NAME: 1029d4afb5ceSopenharmony_ci /* both client and proxy */ 1030d4afb5ceSopenharmony_ci if (!--par->rem) 1031d4afb5ceSopenharmony_ci goto hangup; 1032d4afb5ceSopenharmony_ci par->metadata_name[par->ctr++] = (char)*cp++; 1033d4afb5ceSopenharmony_ci if (par->ctr != par->slen) 1034d4afb5ceSopenharmony_ci break; 1035d4afb5ceSopenharmony_ci par->metadata_name[par->ctr] = '\0'; 1036d4afb5ceSopenharmony_ci par->ps = RPAR_METADATA_VALUE; 1037d4afb5ceSopenharmony_ci 1038d4afb5ceSopenharmony_ci if (client) { 1039d4afb5ceSopenharmony_ci lws_sspc_metadata_t *md; 1040d4afb5ceSopenharmony_ci lws_sspc_handle_t *h = 1041d4afb5ceSopenharmony_ci client_pss_to_sspc_h(pss, ssi); 1042d4afb5ceSopenharmony_ci 1043d4afb5ceSopenharmony_ci /* 1044d4afb5ceSopenharmony_ci * client side does not have access to policy 1045d4afb5ceSopenharmony_ci * and any metadata are new to it each time, 1046d4afb5ceSopenharmony_ci * we allocate them, removing any existing with 1047d4afb5ceSopenharmony_ci * the same name first 1048d4afb5ceSopenharmony_ci */ 1049d4afb5ceSopenharmony_ci 1050d4afb5ceSopenharmony_ci lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, 1051d4afb5ceSopenharmony_ci lws_dll2_get_head( 1052d4afb5ceSopenharmony_ci &h->metadata_owner_rx)) { 1053d4afb5ceSopenharmony_ci md = lws_container_of(d, 1054d4afb5ceSopenharmony_ci lws_sspc_metadata_t, list); 1055d4afb5ceSopenharmony_ci 1056d4afb5ceSopenharmony_ci if (!strcmp(md->name, 1057d4afb5ceSopenharmony_ci par->metadata_name)) { 1058d4afb5ceSopenharmony_ci lws_dll2_remove(&md->list); 1059d4afb5ceSopenharmony_ci lws_free(md); 1060d4afb5ceSopenharmony_ci } 1061d4afb5ceSopenharmony_ci 1062d4afb5ceSopenharmony_ci } lws_end_foreach_dll_safe(d, d1); 1063d4afb5ceSopenharmony_ci 1064d4afb5ceSopenharmony_ci /* 1065d4afb5ceSopenharmony_ci * Create the client's rx metadata entry 1066d4afb5ceSopenharmony_ci */ 1067d4afb5ceSopenharmony_ci 1068d4afb5ceSopenharmony_ci if (h && lws_fi(&h->fic, "sspc_rx_metadata_oom")) 1069d4afb5ceSopenharmony_ci md = NULL; 1070d4afb5ceSopenharmony_ci else 1071d4afb5ceSopenharmony_ci md = lws_malloc(sizeof(lws_sspc_metadata_t) + 1072d4afb5ceSopenharmony_ci par->rem + 1, "rxmeta"); 1073d4afb5ceSopenharmony_ci if (!md) { 1074d4afb5ceSopenharmony_ci lwsl_err("%s: OOM\n", __func__); 1075d4afb5ceSopenharmony_ci goto hangup; 1076d4afb5ceSopenharmony_ci } 1077d4afb5ceSopenharmony_ci 1078d4afb5ceSopenharmony_ci if (!h) 1079d4afb5ceSopenharmony_ci /* coverity */ 1080d4afb5ceSopenharmony_ci goto hangup; 1081d4afb5ceSopenharmony_ci 1082d4afb5ceSopenharmony_ci memset(md, 0, sizeof(lws_sspc_metadata_t)); 1083d4afb5ceSopenharmony_ci 1084d4afb5ceSopenharmony_ci lws_strncpy(md->name, par->metadata_name, 1085d4afb5ceSopenharmony_ci sizeof(md->name)); 1086d4afb5ceSopenharmony_ci md->len = par->rem; 1087d4afb5ceSopenharmony_ci par->rxmetaval = (uint8_t *)&md[1]; 1088d4afb5ceSopenharmony_ci /* 1089d4afb5ceSopenharmony_ci * Overallocate by 1 and put a NUL just beyond 1090d4afb5ceSopenharmony_ci * the official md->len, so value can be easily 1091d4afb5ceSopenharmony_ci * dereferenced safely for NUL-terminated string 1092d4afb5ceSopenharmony_ci * apis that's the most common usage 1093d4afb5ceSopenharmony_ci */ 1094d4afb5ceSopenharmony_ci par->rxmetaval[md->len] = '\0'; 1095d4afb5ceSopenharmony_ci lws_dll2_add_tail(&md->list, 1096d4afb5ceSopenharmony_ci &h->metadata_owner_rx); 1097d4afb5ceSopenharmony_ci par->ctr = 0; 1098d4afb5ceSopenharmony_ci break; 1099d4afb5ceSopenharmony_ci } 1100d4afb5ceSopenharmony_ci 1101d4afb5ceSopenharmony_ci /* proxy side is receiving it */ 1102d4afb5ceSopenharmony_ci 1103d4afb5ceSopenharmony_ci if (!proxy_pss_to_ss_h(pss)) 1104d4afb5ceSopenharmony_ci goto hangup; 1105d4afb5ceSopenharmony_ci 1106d4afb5ceSopenharmony_ci if (!proxy_pss_to_ss_h(pss)->policy) { 1107d4afb5ceSopenharmony_ci lwsl_err("%s: null policy\n", __func__); 1108d4afb5ceSopenharmony_ci goto hangup; 1109d4afb5ceSopenharmony_ci } 1110d4afb5ceSopenharmony_ci 1111d4afb5ceSopenharmony_ci /* 1112d4afb5ceSopenharmony_ci * This is the policy's metadata list for the given 1113d4afb5ceSopenharmony_ci * name 1114d4afb5ceSopenharmony_ci */ 1115d4afb5ceSopenharmony_ci pm = lws_ss_policy_metadata( 1116d4afb5ceSopenharmony_ci proxy_pss_to_ss_h(pss)->policy, 1117d4afb5ceSopenharmony_ci par->metadata_name); 1118d4afb5ceSopenharmony_ci if (!pm) { 1119d4afb5ceSopenharmony_ci lwsl_err("%s: metadata %s not in proxy policy\n", 1120d4afb5ceSopenharmony_ci __func__, par->metadata_name); 1121d4afb5ceSopenharmony_ci 1122d4afb5ceSopenharmony_ci goto hangup; 1123d4afb5ceSopenharmony_ci } 1124d4afb5ceSopenharmony_ci 1125d4afb5ceSopenharmony_ci par->ssmd = lws_ss_get_handle_metadata( 1126d4afb5ceSopenharmony_ci proxy_pss_to_ss_h(pss), 1127d4afb5ceSopenharmony_ci par->metadata_name); 1128d4afb5ceSopenharmony_ci 1129d4afb5ceSopenharmony_ci if (par->ssmd) { 1130d4afb5ceSopenharmony_ci 1131d4afb5ceSopenharmony_ci if (par->ssmd->value_on_lws_heap) 1132d4afb5ceSopenharmony_ci lws_free_set_NULL(par->ssmd->value__may_own_heap); 1133d4afb5ceSopenharmony_ci par->ssmd->value_on_lws_heap = 0; 1134d4afb5ceSopenharmony_ci 1135d4afb5ceSopenharmony_ci if (proxy_pss_to_ss_h(pss) && 1136d4afb5ceSopenharmony_ci lws_fi(&proxy_pss_to_ss_h(pss)->fic, "ssproxy_rx_metadata_oom")) 1137d4afb5ceSopenharmony_ci par->ssmd->value__may_own_heap = NULL; 1138d4afb5ceSopenharmony_ci else 1139d4afb5ceSopenharmony_ci par->ssmd->value__may_own_heap = 1140d4afb5ceSopenharmony_ci lws_malloc((unsigned int)par->rem + 1, "metadata"); 1141d4afb5ceSopenharmony_ci 1142d4afb5ceSopenharmony_ci if (!par->ssmd->value__may_own_heap) { 1143d4afb5ceSopenharmony_ci lwsl_err("%s: OOM mdv\n", __func__); 1144d4afb5ceSopenharmony_ci goto hangup; 1145d4afb5ceSopenharmony_ci } 1146d4afb5ceSopenharmony_ci par->ssmd->length = par->rem; 1147d4afb5ceSopenharmony_ci ((uint8_t *)par->ssmd->value__may_own_heap)[par->rem] = '\0'; 1148d4afb5ceSopenharmony_ci /* mark it as needing cleanup */ 1149d4afb5ceSopenharmony_ci par->ssmd->value_on_lws_heap = 1; 1150d4afb5ceSopenharmony_ci } 1151d4afb5ceSopenharmony_ci par->ctr = 0; 1152d4afb5ceSopenharmony_ci break; 1153d4afb5ceSopenharmony_ci 1154d4afb5ceSopenharmony_ci case RPAR_METADATA_VALUE: 1155d4afb5ceSopenharmony_ci /* both client and proxy */ 1156d4afb5ceSopenharmony_ci 1157d4afb5ceSopenharmony_ci if (client) { 1158d4afb5ceSopenharmony_ci *par->rxmetaval++ = *cp++; 1159d4afb5ceSopenharmony_ci } else { 1160d4afb5ceSopenharmony_ci 1161d4afb5ceSopenharmony_ci if (!par->ssmd) { 1162d4afb5ceSopenharmony_ci /* we don't recognize the name */ 1163d4afb5ceSopenharmony_ci 1164d4afb5ceSopenharmony_ci cp++; 1165d4afb5ceSopenharmony_ci 1166d4afb5ceSopenharmony_ci if (--par->rem) 1167d4afb5ceSopenharmony_ci break; 1168d4afb5ceSopenharmony_ci 1169d4afb5ceSopenharmony_ci par->ps = RPAR_TYPE; 1170d4afb5ceSopenharmony_ci break; 1171d4afb5ceSopenharmony_ci } 1172d4afb5ceSopenharmony_ci 1173d4afb5ceSopenharmony_ci ((uint8_t *)(par->ssmd->value__may_own_heap))[par->ctr++] = *cp++; 1174d4afb5ceSopenharmony_ci } 1175d4afb5ceSopenharmony_ci 1176d4afb5ceSopenharmony_ci if (--par->rem) 1177d4afb5ceSopenharmony_ci break; 1178d4afb5ceSopenharmony_ci 1179d4afb5ceSopenharmony_ci /* we think we got all the value */ 1180d4afb5ceSopenharmony_ci if (client) { 1181d4afb5ceSopenharmony_ci h = lws_container_of(par, lws_sspc_handle_t, parser); 1182d4afb5ceSopenharmony_ci lwsl_sspc_notice(h, "RX METADATA %s", 1183d4afb5ceSopenharmony_ci par->metadata_name); 1184d4afb5ceSopenharmony_ci } else { 1185d4afb5ceSopenharmony_ci lwsl_ss_info(proxy_pss_to_ss_h(pss), 1186d4afb5ceSopenharmony_ci "RPAR_METADATA_VALUE for %s (len %d)", 1187d4afb5ceSopenharmony_ci par->ssmd->name, 1188d4afb5ceSopenharmony_ci (int)par->ssmd->length); 1189d4afb5ceSopenharmony_ci lwsl_hexdump_ss_info(proxy_pss_to_ss_h(pss), 1190d4afb5ceSopenharmony_ci par->ssmd->value__may_own_heap, 1191d4afb5ceSopenharmony_ci par->ssmd->length); 1192d4afb5ceSopenharmony_ci } 1193d4afb5ceSopenharmony_ci par->ps = RPAR_TYPE; 1194d4afb5ceSopenharmony_ci break; 1195d4afb5ceSopenharmony_ci 1196d4afb5ceSopenharmony_ci case RPAR_STREAMTYPE: 1197d4afb5ceSopenharmony_ci 1198d4afb5ceSopenharmony_ci /* only the proxy can get these */ 1199d4afb5ceSopenharmony_ci 1200d4afb5ceSopenharmony_ci if (client) 1201d4afb5ceSopenharmony_ci goto hangup; 1202d4afb5ceSopenharmony_ci if (par->ctr == sizeof(par->streamtype) - 1) 1203d4afb5ceSopenharmony_ci goto hangup; 1204d4afb5ceSopenharmony_ci 1205d4afb5ceSopenharmony_ci /* 1206d4afb5ceSopenharmony_ci * We can only expect to get this if we ourselves are 1207d4afb5ceSopenharmony_ci * in the state that we're waiting for it. If it comes 1208d4afb5ceSopenharmony_ci * later it's a protocol error. 1209d4afb5ceSopenharmony_ci */ 1210d4afb5ceSopenharmony_ci 1211d4afb5ceSopenharmony_ci if (*state != LPCSPROX_WAIT_INITIAL_TX) 1212d4afb5ceSopenharmony_ci goto hangup; 1213d4afb5ceSopenharmony_ci 1214d4afb5ceSopenharmony_ci /* 1215d4afb5ceSopenharmony_ci * We're the proxy, creating an SS on behalf of a 1216d4afb5ceSopenharmony_ci * client 1217d4afb5ceSopenharmony_ci */ 1218d4afb5ceSopenharmony_ci 1219d4afb5ceSopenharmony_ci par->streamtype[par->ctr++] = (char)*cp++; 1220d4afb5ceSopenharmony_ci if (--par->rem) 1221d4afb5ceSopenharmony_ci break; 1222d4afb5ceSopenharmony_ci 1223d4afb5ceSopenharmony_ci par->ps = RPAR_TYPE; 1224d4afb5ceSopenharmony_ci par->streamtype[par->ctr] = '\0'; 1225d4afb5ceSopenharmony_ci lwsl_info("%s: proxy ss '%s', sssv%d, txcr %d\n", 1226d4afb5ceSopenharmony_ci __func__, par->streamtype, 1227d4afb5ceSopenharmony_ci par->protocol_version, par->txcr_out); 1228d4afb5ceSopenharmony_ci 1229d4afb5ceSopenharmony_ci ssi->streamtype = par->streamtype; 1230d4afb5ceSopenharmony_ci if (par->txcr_out) // !!! 1231d4afb5ceSopenharmony_ci ssi->manual_initial_tx_credit = par->txcr_out; 1232d4afb5ceSopenharmony_ci 1233d4afb5ceSopenharmony_ci /* 1234d4afb5ceSopenharmony_ci * Even for a synthetic SS proxing action like _lws_smd, 1235d4afb5ceSopenharmony_ci * we create an actual SS in the proxy representing the 1236d4afb5ceSopenharmony_ci * connection 1237d4afb5ceSopenharmony_ci */ 1238d4afb5ceSopenharmony_ci 1239d4afb5ceSopenharmony_ci ssi->flags |= LWSSSINFLAGS_PROXIED; 1240d4afb5ceSopenharmony_ci ssi->sss_protocol_version = par->protocol_version; 1241d4afb5ceSopenharmony_ci ssi->client_pid = par->client_pid; 1242d4afb5ceSopenharmony_ci 1243d4afb5ceSopenharmony_ci if (lws_ss_create(context, 0, ssi, parconn, pss, 1244d4afb5ceSopenharmony_ci NULL, NULL)) { 1245d4afb5ceSopenharmony_ci /* 1246d4afb5ceSopenharmony_ci * We're unable to create the onward secure 1247d4afb5ceSopenharmony_ci * stream he asked for... schedule a chance to 1248d4afb5ceSopenharmony_ci * inform him 1249d4afb5ceSopenharmony_ci */ 1250d4afb5ceSopenharmony_ci lwsl_err("%s: create '%s' fail\n", __func__, 1251d4afb5ceSopenharmony_ci par->streamtype); 1252d4afb5ceSopenharmony_ci *state = LPCSPROX_REPORTING_FAIL; 1253d4afb5ceSopenharmony_ci break; 1254d4afb5ceSopenharmony_ci } else { 1255d4afb5ceSopenharmony_ci lwsl_debug("%s: create '%s' OK\n", 1256d4afb5ceSopenharmony_ci __func__, par->streamtype); 1257d4afb5ceSopenharmony_ci *state = LPCSPROX_REPORTING_OK; 1258d4afb5ceSopenharmony_ci } 1259d4afb5ceSopenharmony_ci 1260d4afb5ceSopenharmony_ci if (*pss) { 1261d4afb5ceSopenharmony_ci (*pss)->being_serialized = 1; 1262d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_SMD) 1263d4afb5ceSopenharmony_ci if ((*pss)->policy != &pol_smd) 1264d4afb5ceSopenharmony_ci /* 1265d4afb5ceSopenharmony_ci * In SMD case we overloaded the 1266d4afb5ceSopenharmony_ci * initial credit to be the class mask 1267d4afb5ceSopenharmony_ci */ 1268d4afb5ceSopenharmony_ci#endif 1269d4afb5ceSopenharmony_ci { 1270d4afb5ceSopenharmony_ci lwsl_info("%s: Created SS initial credit %d\n", 1271d4afb5ceSopenharmony_ci __func__, par->txcr_out); 1272d4afb5ceSopenharmony_ci 1273d4afb5ceSopenharmony_ci (*pss)->info.manual_initial_tx_credit = par->txcr_out; 1274d4afb5ceSopenharmony_ci } 1275d4afb5ceSopenharmony_ci } 1276d4afb5ceSopenharmony_ci 1277d4afb5ceSopenharmony_ci /* parent needs to schedule write on client conn */ 1278d4afb5ceSopenharmony_ci break; 1279d4afb5ceSopenharmony_ci 1280d4afb5ceSopenharmony_ci /* clientside states */ 1281d4afb5ceSopenharmony_ci 1282d4afb5ceSopenharmony_ci case RPAR_RESULT_CREATION: 1283d4afb5ceSopenharmony_ci if (*cp++) { 1284d4afb5ceSopenharmony_ci lwsl_err("%s: stream creation failed\n", 1285d4afb5ceSopenharmony_ci __func__); 1286d4afb5ceSopenharmony_ci goto hangup; 1287d4afb5ceSopenharmony_ci } 1288d4afb5ceSopenharmony_ci 1289d4afb5ceSopenharmony_ci if (--par->rem < 4) 1290d4afb5ceSopenharmony_ci goto hangup; 1291d4afb5ceSopenharmony_ci 1292d4afb5ceSopenharmony_ci par->ps = RPAR_RESULT_CREATION_DSH; 1293d4afb5ceSopenharmony_ci par->ctr = 0; 1294d4afb5ceSopenharmony_ci break; 1295d4afb5ceSopenharmony_ci 1296d4afb5ceSopenharmony_ci case RPAR_RESULT_CREATION_DSH: 1297d4afb5ceSopenharmony_ci 1298d4afb5ceSopenharmony_ci par->temp32 = (par->temp32 << 8) | (*cp++); 1299d4afb5ceSopenharmony_ci if (!par->rem--) 1300d4afb5ceSopenharmony_ci goto hangup; 1301d4afb5ceSopenharmony_ci if (++par->ctr < 4) 1302d4afb5ceSopenharmony_ci break; 1303d4afb5ceSopenharmony_ci 1304d4afb5ceSopenharmony_ci /* 1305d4afb5ceSopenharmony_ci * Client (par->temp32 == dsh alloc) 1306d4afb5ceSopenharmony_ci */ 1307d4afb5ceSopenharmony_ci 1308d4afb5ceSopenharmony_ci h = lws_container_of(par, lws_sspc_handle_t, parser); 1309d4afb5ceSopenharmony_ci 1310d4afb5ceSopenharmony_ci lws_ss_serialize_state_transition(h, state, 1311d4afb5ceSopenharmony_ci LPCSCLI_LOCAL_CONNECTED); 1312d4afb5ceSopenharmony_ci 1313d4afb5ceSopenharmony_ci lws_set_timeout(h->cwsi, NO_PENDING_TIMEOUT, 0); 1314d4afb5ceSopenharmony_ci 1315d4afb5ceSopenharmony_ci if (h->dsh) 1316d4afb5ceSopenharmony_ci goto hangup; 1317d4afb5ceSopenharmony_ci 1318d4afb5ceSopenharmony_ci /* 1319d4afb5ceSopenharmony_ci * This is telling us that the streamtype could be (and 1320d4afb5ceSopenharmony_ci * was) created at the proxy. It's not telling us that 1321d4afb5ceSopenharmony_ci * the onward peer connection could be connected. 1322d4afb5ceSopenharmony_ci * 1323d4afb5ceSopenharmony_ci * We'll get a proxied state() coming later that informs 1324d4afb5ceSopenharmony_ci * us about the situation with that. 1325d4afb5ceSopenharmony_ci * 1326d4afb5ceSopenharmony_ci * However at this point, we should choose to inform 1327d4afb5ceSopenharmony_ci * the client that his stream was created... we will 1328d4afb5ceSopenharmony_ci * later get a proxied CREATING state from the peer 1329d4afb5ceSopenharmony_ci * but we should do it now and suppress the later one. 1330d4afb5ceSopenharmony_ci * 1331d4afb5ceSopenharmony_ci * The reason is he may set metadata in CREATING, and 1332d4afb5ceSopenharmony_ci * we will try to do writeables to sync the stream to 1333d4afb5ceSopenharmony_ci * proxy and ultimately bring up the onward connection 1334d4afb5ceSopenharmony_ci * now we are in LOCAL_CONNECTED. We need to do the 1335d4afb5ceSopenharmony_ci * CREATING now so we'll know the metadata to sync. 1336d4afb5ceSopenharmony_ci */ 1337d4afb5ceSopenharmony_ci 1338d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_METRICS) 1339d4afb5ceSopenharmony_ci /* 1340d4afb5ceSopenharmony_ci * If any hanging caliper measurement, dump it, and free any tags 1341d4afb5ceSopenharmony_ci */ 1342d4afb5ceSopenharmony_ci lws_metrics_caliper_report_hist(h->cal_txn, (struct lws *)NULL); 1343d4afb5ceSopenharmony_ci#endif 1344d4afb5ceSopenharmony_ci 1345d4afb5ceSopenharmony_ci if (!h->creating_cb_done) { 1346d4afb5ceSopenharmony_ci if (lws_ss_check_next_state_sspc(h, 1347d4afb5ceSopenharmony_ci &h->prev_ss_state, 1348d4afb5ceSopenharmony_ci LWSSSCS_CREATING)) 1349d4afb5ceSopenharmony_ci return LWSSSSRET_DESTROY_ME; 1350d4afb5ceSopenharmony_ci h->prev_ss_state = (uint8_t)LWSSSCS_CREATING; 1351d4afb5ceSopenharmony_ci h->creating_cb_done = 1; 1352d4afb5ceSopenharmony_ci } else 1353d4afb5ceSopenharmony_ci h->prev_ss_state = LWSSSCS_DISCONNECTED; 1354d4afb5ceSopenharmony_ci 1355d4afb5ceSopenharmony_ci if (ssi->state) { 1356d4afb5ceSopenharmony_ci n = ssi->state(client_pss_to_userdata(pss), 1357d4afb5ceSopenharmony_ci NULL, h->prev_ss_state, 0); 1358d4afb5ceSopenharmony_ci switch (n) { 1359d4afb5ceSopenharmony_ci case LWSSSSRET_OK: 1360d4afb5ceSopenharmony_ci break; 1361d4afb5ceSopenharmony_ci case LWSSSSRET_DISCONNECT_ME: 1362d4afb5ceSopenharmony_ci goto hangup; 1363d4afb5ceSopenharmony_ci case LWSSSSRET_DESTROY_ME: 1364d4afb5ceSopenharmony_ci return LWSSSSRET_DESTROY_ME; 1365d4afb5ceSopenharmony_ci } 1366d4afb5ceSopenharmony_ci } 1367d4afb5ceSopenharmony_ci 1368d4afb5ceSopenharmony_ci h->dsh = lws_dsh_create(NULL, (size_t)(par->temp32 ? 1369d4afb5ceSopenharmony_ci par->temp32 : 32768), 1); 1370d4afb5ceSopenharmony_ci if (!h->dsh) 1371d4afb5ceSopenharmony_ci goto hangup; 1372d4afb5ceSopenharmony_ci 1373d4afb5ceSopenharmony_ci lws_callback_on_writable(h->cwsi); 1374d4afb5ceSopenharmony_ci 1375d4afb5ceSopenharmony_ci par->rsl_pos = 0; 1376d4afb5ceSopenharmony_ci par->rsl_idx = 0; 1377d4afb5ceSopenharmony_ci 1378d4afb5ceSopenharmony_ci memset(&h->rideshare_ofs[0], 0, sizeof(h->rideshare_ofs[0])); 1379d4afb5ceSopenharmony_ci h->rideshare_list[0] = '\0'; 1380d4afb5ceSopenharmony_ci h->rsidx = 0; 1381d4afb5ceSopenharmony_ci 1382d4afb5ceSopenharmony_ci /* no rideshare data is OK */ 1383d4afb5ceSopenharmony_ci par->ps = RPAR_TYPE; 1384d4afb5ceSopenharmony_ci 1385d4afb5ceSopenharmony_ci if (par->rem) { 1386d4afb5ceSopenharmony_ci par->ps = RPAR_RESULT_CREATION_RIDESHARE; 1387d4afb5ceSopenharmony_ci if (par->rem >= sizeof(h->rideshare_list)) 1388d4afb5ceSopenharmony_ci goto hangup; 1389d4afb5ceSopenharmony_ci } 1390d4afb5ceSopenharmony_ci break; 1391d4afb5ceSopenharmony_ci 1392d4afb5ceSopenharmony_ci case RPAR_RESULT_CREATION_RIDESHARE: 1393d4afb5ceSopenharmony_ci h = lws_container_of(par, lws_sspc_handle_t, parser); 1394d4afb5ceSopenharmony_ci if (*cp == ',') { 1395d4afb5ceSopenharmony_ci cp++; 1396d4afb5ceSopenharmony_ci h->rideshare_list[par->rsl_pos++] = '\0'; 1397d4afb5ceSopenharmony_ci if (par->rsl_idx == LWS_ARRAY_SIZE(h->rideshare_ofs)) 1398d4afb5ceSopenharmony_ci goto hangup; 1399d4afb5ceSopenharmony_ci h->rideshare_ofs[++par->rsl_idx] = par->rsl_pos; 1400d4afb5ceSopenharmony_ci } else 1401d4afb5ceSopenharmony_ci h->rideshare_list[par->rsl_pos++] = (char)*cp++; 1402d4afb5ceSopenharmony_ci if (!--par->rem) 1403d4afb5ceSopenharmony_ci par->ps = RPAR_TYPE; 1404d4afb5ceSopenharmony_ci break; 1405d4afb5ceSopenharmony_ci 1406d4afb5ceSopenharmony_ci case RPAR_STATEINDEX: 1407d4afb5ceSopenharmony_ci par->ctr = (par->ctr << 8) | (*cp++); 1408d4afb5ceSopenharmony_ci if (--par->rem == 4) 1409d4afb5ceSopenharmony_ci par->ps = RPAR_ORD3; 1410d4afb5ceSopenharmony_ci break; 1411d4afb5ceSopenharmony_ci 1412d4afb5ceSopenharmony_ci case RPAR_ORD3: 1413d4afb5ceSopenharmony_ci par->flags = (uint32_t)((*cp++) << 24); 1414d4afb5ceSopenharmony_ci par->ps++; 1415d4afb5ceSopenharmony_ci break; 1416d4afb5ceSopenharmony_ci 1417d4afb5ceSopenharmony_ci case RPAR_ORD2: 1418d4afb5ceSopenharmony_ci par->flags |= (uint32_t)((*cp++) << 16); 1419d4afb5ceSopenharmony_ci par->ps++; 1420d4afb5ceSopenharmony_ci break; 1421d4afb5ceSopenharmony_ci 1422d4afb5ceSopenharmony_ci case RPAR_ORD1: 1423d4afb5ceSopenharmony_ci par->flags |= (uint32_t)((*cp++) << 8); 1424d4afb5ceSopenharmony_ci par->ps++; 1425d4afb5ceSopenharmony_ci break; 1426d4afb5ceSopenharmony_ci 1427d4afb5ceSopenharmony_ci case RPAR_ORD0: 1428d4afb5ceSopenharmony_ci par->flags |= (uint32_t)(*cp++); 1429d4afb5ceSopenharmony_ci par->ps++; 1430d4afb5ceSopenharmony_ci par->ps = RPAR_TYPE; 1431d4afb5ceSopenharmony_ci 1432d4afb5ceSopenharmony_ci /* 1433d4afb5ceSopenharmony_ci * Client received a proxied state change 1434d4afb5ceSopenharmony_ci */ 1435d4afb5ceSopenharmony_ci 1436d4afb5ceSopenharmony_ci h = client_pss_to_sspc_h(pss, ssi); 1437d4afb5ceSopenharmony_ci if (!h) 1438d4afb5ceSopenharmony_ci /* 1439d4afb5ceSopenharmony_ci * Since we're being informed we need to have 1440d4afb5ceSopenharmony_ci * a stream to inform. Assume whatever set this 1441d4afb5ceSopenharmony_ci * to NULL has started to close it. 1442d4afb5ceSopenharmony_ci */ 1443d4afb5ceSopenharmony_ci break; 1444d4afb5ceSopenharmony_ci 1445d4afb5ceSopenharmony_ci switch (par->ctr) { 1446d4afb5ceSopenharmony_ci case LWSSSCS_DISCONNECTED: 1447d4afb5ceSopenharmony_ci case LWSSSCS_UNREACHABLE: 1448d4afb5ceSopenharmony_ci case LWSSSCS_AUTH_FAILED: 1449d4afb5ceSopenharmony_ci lws_ss_serialize_state_transition(h, state, 1450d4afb5ceSopenharmony_ci LPCSCLI_LOCAL_CONNECTED); 1451d4afb5ceSopenharmony_ci h->conn_req_state = LWSSSPC_ONW_NONE; 1452d4afb5ceSopenharmony_ci break; 1453d4afb5ceSopenharmony_ci 1454d4afb5ceSopenharmony_ci case LWSSSCS_CONNECTED: 1455d4afb5ceSopenharmony_ci lwsl_sspc_info(h, "CONNECTED %s", 1456d4afb5ceSopenharmony_ci ssi->streamtype); 1457d4afb5ceSopenharmony_ci if (*state == LPCSCLI_OPERATIONAL) 1458d4afb5ceSopenharmony_ci /* 1459d4afb5ceSopenharmony_ci * Don't allow to see connected more 1460d4afb5ceSopenharmony_ci * than once for one connection 1461d4afb5ceSopenharmony_ci */ 1462d4afb5ceSopenharmony_ci goto swallow; 1463d4afb5ceSopenharmony_ci 1464d4afb5ceSopenharmony_ci lws_ss_serialize_state_transition(h, state, 1465d4afb5ceSopenharmony_ci LPCSCLI_OPERATIONAL); 1466d4afb5ceSopenharmony_ci 1467d4afb5ceSopenharmony_ci h->conn_req_state = LWSSSPC_ONW_CONN; 1468d4afb5ceSopenharmony_ci break; 1469d4afb5ceSopenharmony_ci case LWSSSCS_TIMEOUT: 1470d4afb5ceSopenharmony_ci break; 1471d4afb5ceSopenharmony_ci default: 1472d4afb5ceSopenharmony_ci break; 1473d4afb5ceSopenharmony_ci } 1474d4afb5ceSopenharmony_ci 1475d4afb5ceSopenharmony_ci if (par->ctr < 0) 1476d4afb5ceSopenharmony_ci goto hangup; 1477d4afb5ceSopenharmony_ci 1478d4afb5ceSopenharmony_ci#if defined(_DEBUG) 1479d4afb5ceSopenharmony_ci lwsl_sspc_info(h, "forwarding proxied state %s", 1480d4afb5ceSopenharmony_ci lws_ss_state_name(par->ctr)); 1481d4afb5ceSopenharmony_ci#endif 1482d4afb5ceSopenharmony_ci 1483d4afb5ceSopenharmony_ci if (par->ctr == LWSSSCS_CREATING) { 1484d4afb5ceSopenharmony_ci h = lws_container_of(par, lws_sspc_handle_t, parser); 1485d4afb5ceSopenharmony_ci if (h->creating_cb_done) 1486d4afb5ceSopenharmony_ci /* 1487d4afb5ceSopenharmony_ci * We have told him he's CREATING when 1488d4afb5ceSopenharmony_ci * we heard we had linked up to the 1489d4afb5ceSopenharmony_ci * proxy, so suppress the remote 1490d4afb5ceSopenharmony_ci * CREATING so that he only sees it once 1491d4afb5ceSopenharmony_ci */ 1492d4afb5ceSopenharmony_ci break; 1493d4afb5ceSopenharmony_ci 1494d4afb5ceSopenharmony_ci h->creating_cb_done = 1; 1495d4afb5ceSopenharmony_ci } 1496d4afb5ceSopenharmony_ci 1497d4afb5ceSopenharmony_ci if (ssi->state) { 1498d4afb5ceSopenharmony_ci h = lws_container_of(par, lws_sspc_handle_t, parser); 1499d4afb5ceSopenharmony_ci lws_ss_constate_t cs = (lws_ss_constate_t)par->ctr; 1500d4afb5ceSopenharmony_ci 1501d4afb5ceSopenharmony_ci if (cs == LWSSSCS_CONNECTED) 1502d4afb5ceSopenharmony_ci h->ss_dangling_connected = 1; 1503d4afb5ceSopenharmony_ci if (cs == LWSSSCS_DISCONNECTED) 1504d4afb5ceSopenharmony_ci h->ss_dangling_connected = 0; 1505d4afb5ceSopenharmony_ci 1506d4afb5ceSopenharmony_ci if (lws_ss_check_next_state_sspc(h, 1507d4afb5ceSopenharmony_ci &h->prev_ss_state, cs)) 1508d4afb5ceSopenharmony_ci return LWSSSSRET_DESTROY_ME; 1509d4afb5ceSopenharmony_ci 1510d4afb5ceSopenharmony_ci if (cs < LWSSSCS_USER_BASE) 1511d4afb5ceSopenharmony_ci h->prev_ss_state = (uint8_t)cs; 1512d4afb5ceSopenharmony_ci 1513d4afb5ceSopenharmony_ci h->h_in_svc = h; 1514d4afb5ceSopenharmony_ci n = ssi->state(client_pss_to_userdata(pss), 1515d4afb5ceSopenharmony_ci NULL, cs, par->flags); 1516d4afb5ceSopenharmony_ci h->h_in_svc = NULL; 1517d4afb5ceSopenharmony_ci switch (n) { 1518d4afb5ceSopenharmony_ci case LWSSSSRET_OK: 1519d4afb5ceSopenharmony_ci break; 1520d4afb5ceSopenharmony_ci case LWSSSSRET_DISCONNECT_ME: 1521d4afb5ceSopenharmony_ci goto hangup; 1522d4afb5ceSopenharmony_ci case LWSSSSRET_DESTROY_ME: 1523d4afb5ceSopenharmony_ci return LWSSSSRET_DESTROY_ME; 1524d4afb5ceSopenharmony_ci } 1525d4afb5ceSopenharmony_ci } 1526d4afb5ceSopenharmony_ci 1527d4afb5ceSopenharmony_ciswallow: 1528d4afb5ceSopenharmony_ci break; 1529d4afb5ceSopenharmony_ci 1530d4afb5ceSopenharmony_ci default: 1531d4afb5ceSopenharmony_ci goto hangup; 1532d4afb5ceSopenharmony_ci } 1533d4afb5ceSopenharmony_ci } 1534d4afb5ceSopenharmony_ci 1535d4afb5ceSopenharmony_ci return LWSSSSRET_OK; 1536d4afb5ceSopenharmony_ci 1537d4afb5ceSopenharmony_cihangup: 1538d4afb5ceSopenharmony_ci 1539d4afb5ceSopenharmony_ci lwsl_cx_notice(context, "hangup"); 1540d4afb5ceSopenharmony_ci 1541d4afb5ceSopenharmony_ci return LWSSSSRET_DISCONNECT_ME; 1542d4afb5ceSopenharmony_ci} 1543