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#include <private-lib-core.h> 26d4afb5ceSopenharmony_ci 27d4afb5ceSopenharmony_cistatic const struct ss_pcols *ss_pcols[] = { 28d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_H1) 29d4afb5ceSopenharmony_ci &ss_pcol_h1, /* LWSSSP_H1 */ 30d4afb5ceSopenharmony_ci#else 31d4afb5ceSopenharmony_ci NULL, 32d4afb5ceSopenharmony_ci#endif 33d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_H2) 34d4afb5ceSopenharmony_ci &ss_pcol_h2, /* LWSSSP_H2 */ 35d4afb5ceSopenharmony_ci#else 36d4afb5ceSopenharmony_ci NULL, 37d4afb5ceSopenharmony_ci#endif 38d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_WS) 39d4afb5ceSopenharmony_ci &ss_pcol_ws, /* LWSSSP_WS */ 40d4afb5ceSopenharmony_ci#else 41d4afb5ceSopenharmony_ci NULL, 42d4afb5ceSopenharmony_ci#endif 43d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_MQTT) 44d4afb5ceSopenharmony_ci &ss_pcol_mqtt, /* LWSSSP_MQTT */ 45d4afb5ceSopenharmony_ci#else 46d4afb5ceSopenharmony_ci NULL, 47d4afb5ceSopenharmony_ci#endif 48d4afb5ceSopenharmony_ci &ss_pcol_raw, /* LWSSSP_RAW */ 49d4afb5ceSopenharmony_ci NULL, 50d4afb5ceSopenharmony_ci}; 51d4afb5ceSopenharmony_ci 52d4afb5ceSopenharmony_cistatic const char *state_names[] = { 53d4afb5ceSopenharmony_ci "(unset)", 54d4afb5ceSopenharmony_ci "LWSSSCS_CREATING", 55d4afb5ceSopenharmony_ci "LWSSSCS_DISCONNECTED", 56d4afb5ceSopenharmony_ci "LWSSSCS_UNREACHABLE", 57d4afb5ceSopenharmony_ci "LWSSSCS_AUTH_FAILED", 58d4afb5ceSopenharmony_ci "LWSSSCS_CONNECTED", 59d4afb5ceSopenharmony_ci "LWSSSCS_CONNECTING", 60d4afb5ceSopenharmony_ci "LWSSSCS_DESTROYING", 61d4afb5ceSopenharmony_ci "LWSSSCS_POLL", 62d4afb5ceSopenharmony_ci "LWSSSCS_ALL_RETRIES_FAILED", 63d4afb5ceSopenharmony_ci "LWSSSCS_QOS_ACK_REMOTE", 64d4afb5ceSopenharmony_ci "LWSSSCS_QOS_NACK_REMOTE", 65d4afb5ceSopenharmony_ci "LWSSSCS_QOS_ACK_LOCAL", 66d4afb5ceSopenharmony_ci "LWSSSCS_QOS_NACK_LOCAL", 67d4afb5ceSopenharmony_ci "LWSSSCS_TIMEOUT", 68d4afb5ceSopenharmony_ci "LWSSSCS_SERVER_TXN", 69d4afb5ceSopenharmony_ci "LWSSSCS_SERVER_UPGRADE", 70d4afb5ceSopenharmony_ci "LWSSSCS_EVENT_WAIT_CANCELLED", 71d4afb5ceSopenharmony_ci "LWSSSCS_UPSTREAM_LINK_RETRY", 72d4afb5ceSopenharmony_ci}; 73d4afb5ceSopenharmony_ci 74d4afb5ceSopenharmony_ci/* 75d4afb5ceSopenharmony_ci * For each "current state", set bit offsets for valid "next states". 76d4afb5ceSopenharmony_ci * 77d4afb5ceSopenharmony_ci * Since there are complicated ways to arrive at state transitions like proxying 78d4afb5ceSopenharmony_ci * and asynchronous destruction etc, so we monitor the state transitions we are 79d4afb5ceSopenharmony_ci * giving the ss user code to ensure we never deliver illegal state transitions 80d4afb5ceSopenharmony_ci * (because we will assert if we have bugs that do it) 81d4afb5ceSopenharmony_ci */ 82d4afb5ceSopenharmony_ci 83d4afb5ceSopenharmony_ciconst uint32_t ss_state_txn_validity[] = { 84d4afb5ceSopenharmony_ci 85d4afb5ceSopenharmony_ci /* if we was last in this state... we can legally go to these states */ 86d4afb5ceSopenharmony_ci 87d4afb5ceSopenharmony_ci [0] = (1 << LWSSSCS_CREATING) | 88d4afb5ceSopenharmony_ci (1 << LWSSSCS_DESTROYING), 89d4afb5ceSopenharmony_ci 90d4afb5ceSopenharmony_ci [LWSSSCS_CREATING] = (1 << LWSSSCS_CONNECTING) | 91d4afb5ceSopenharmony_ci (1 << LWSSSCS_TIMEOUT) | 92d4afb5ceSopenharmony_ci (1 << LWSSSCS_POLL) | 93d4afb5ceSopenharmony_ci (1 << LWSSSCS_SERVER_UPGRADE) | 94d4afb5ceSopenharmony_ci (1 << LWSSSCS_DESTROYING), 95d4afb5ceSopenharmony_ci 96d4afb5ceSopenharmony_ci [LWSSSCS_DISCONNECTED] = (1 << LWSSSCS_CONNECTING) | 97d4afb5ceSopenharmony_ci (1 << LWSSSCS_TIMEOUT) | 98d4afb5ceSopenharmony_ci (1 << LWSSSCS_POLL) | 99d4afb5ceSopenharmony_ci (1 << LWSSSCS_DESTROYING), 100d4afb5ceSopenharmony_ci 101d4afb5ceSopenharmony_ci [LWSSSCS_UNREACHABLE] = (1 << LWSSSCS_ALL_RETRIES_FAILED) | 102d4afb5ceSopenharmony_ci (1 << LWSSSCS_TIMEOUT) | 103d4afb5ceSopenharmony_ci (1 << LWSSSCS_POLL) | 104d4afb5ceSopenharmony_ci (1 << LWSSSCS_CONNECTING) | 105d4afb5ceSopenharmony_ci /* win conn failure > retry > succ */ 106d4afb5ceSopenharmony_ci (1 << LWSSSCS_CONNECTED) | 107d4afb5ceSopenharmony_ci (1 << LWSSSCS_DESTROYING), 108d4afb5ceSopenharmony_ci 109d4afb5ceSopenharmony_ci [LWSSSCS_AUTH_FAILED] = (1 << LWSSSCS_ALL_RETRIES_FAILED) | 110d4afb5ceSopenharmony_ci (1 << LWSSSCS_TIMEOUT) | 111d4afb5ceSopenharmony_ci (1 << LWSSSCS_CONNECTING) | 112d4afb5ceSopenharmony_ci (1 << LWSSSCS_DESTROYING), 113d4afb5ceSopenharmony_ci 114d4afb5ceSopenharmony_ci [LWSSSCS_CONNECTED] = (1 << LWSSSCS_SERVER_UPGRADE) | 115d4afb5ceSopenharmony_ci (1 << LWSSSCS_SERVER_TXN) | 116d4afb5ceSopenharmony_ci (1 << LWSSSCS_AUTH_FAILED) | 117d4afb5ceSopenharmony_ci (1 << LWSSSCS_QOS_ACK_REMOTE) | 118d4afb5ceSopenharmony_ci (1 << LWSSSCS_QOS_NACK_REMOTE) | 119d4afb5ceSopenharmony_ci (1 << LWSSSCS_QOS_ACK_LOCAL) | 120d4afb5ceSopenharmony_ci (1 << LWSSSCS_QOS_NACK_LOCAL) | 121d4afb5ceSopenharmony_ci (1 << LWSSSCS_DISCONNECTED) | 122d4afb5ceSopenharmony_ci (1 << LWSSSCS_TIMEOUT) | 123d4afb5ceSopenharmony_ci (1 << LWSSSCS_POLL) | /* proxy retry */ 124d4afb5ceSopenharmony_ci (1 << LWSSSCS_DESTROYING), 125d4afb5ceSopenharmony_ci 126d4afb5ceSopenharmony_ci [LWSSSCS_CONNECTING] = (1 << LWSSSCS_UNREACHABLE) | 127d4afb5ceSopenharmony_ci (1 << LWSSSCS_AUTH_FAILED) | 128d4afb5ceSopenharmony_ci (1 << LWSSSCS_CONNECTING) | 129d4afb5ceSopenharmony_ci (1 << LWSSSCS_CONNECTED) | 130d4afb5ceSopenharmony_ci (1 << LWSSSCS_TIMEOUT) | 131d4afb5ceSopenharmony_ci (1 << LWSSSCS_POLL) | 132d4afb5ceSopenharmony_ci (1 << LWSSSCS_DISCONNECTED) | /* proxy retry */ 133d4afb5ceSopenharmony_ci (1 << LWSSSCS_DESTROYING), 134d4afb5ceSopenharmony_ci 135d4afb5ceSopenharmony_ci [LWSSSCS_DESTROYING] = 0, 136d4afb5ceSopenharmony_ci 137d4afb5ceSopenharmony_ci [LWSSSCS_POLL] = (1 << LWSSSCS_CONNECTING) | 138d4afb5ceSopenharmony_ci (1 << LWSSSCS_TIMEOUT) | 139d4afb5ceSopenharmony_ci (1 << LWSSSCS_ALL_RETRIES_FAILED) | 140d4afb5ceSopenharmony_ci (1 << LWSSSCS_DESTROYING), 141d4afb5ceSopenharmony_ci 142d4afb5ceSopenharmony_ci [LWSSSCS_ALL_RETRIES_FAILED] = (1 << LWSSSCS_CONNECTING) | 143d4afb5ceSopenharmony_ci (1 << LWSSSCS_TIMEOUT) | 144d4afb5ceSopenharmony_ci (1 << LWSSSCS_DESTROYING), 145d4afb5ceSopenharmony_ci 146d4afb5ceSopenharmony_ci [LWSSSCS_QOS_ACK_REMOTE] = (1 << LWSSSCS_DISCONNECTED) | 147d4afb5ceSopenharmony_ci (1 << LWSSSCS_TIMEOUT) | 148d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_MQTT) 149d4afb5ceSopenharmony_ci (1 << LWSSSCS_QOS_ACK_REMOTE) | 150d4afb5ceSopenharmony_ci (1 << LWSSSCS_QOS_NACK_REMOTE) | 151d4afb5ceSopenharmony_ci#endif 152d4afb5ceSopenharmony_ci (1 << LWSSSCS_DESTROYING), 153d4afb5ceSopenharmony_ci 154d4afb5ceSopenharmony_ci [LWSSSCS_QOS_NACK_REMOTE] = (1 << LWSSSCS_DISCONNECTED) | 155d4afb5ceSopenharmony_ci (1 << LWSSSCS_TIMEOUT) | 156d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_MQTT) 157d4afb5ceSopenharmony_ci (1 << LWSSSCS_QOS_ACK_REMOTE) | 158d4afb5ceSopenharmony_ci (1 << LWSSSCS_QOS_NACK_REMOTE) | 159d4afb5ceSopenharmony_ci#endif 160d4afb5ceSopenharmony_ci (1 << LWSSSCS_DESTROYING), 161d4afb5ceSopenharmony_ci 162d4afb5ceSopenharmony_ci [LWSSSCS_QOS_ACK_LOCAL] = (1 << LWSSSCS_DISCONNECTED) | 163d4afb5ceSopenharmony_ci (1 << LWSSSCS_TIMEOUT) | 164d4afb5ceSopenharmony_ci (1 << LWSSSCS_DESTROYING), 165d4afb5ceSopenharmony_ci 166d4afb5ceSopenharmony_ci [LWSSSCS_QOS_NACK_LOCAL] = (1 << LWSSSCS_DESTROYING) | 167d4afb5ceSopenharmony_ci (1 << LWSSSCS_TIMEOUT), 168d4afb5ceSopenharmony_ci 169d4afb5ceSopenharmony_ci /* he can get the timeout at any point and take no action... */ 170d4afb5ceSopenharmony_ci [LWSSSCS_TIMEOUT] = (1 << LWSSSCS_CONNECTING) | 171d4afb5ceSopenharmony_ci (1 << LWSSSCS_CONNECTED) | 172d4afb5ceSopenharmony_ci (1 << LWSSSCS_QOS_ACK_REMOTE) | 173d4afb5ceSopenharmony_ci (1 << LWSSSCS_QOS_NACK_REMOTE) | 174d4afb5ceSopenharmony_ci (1 << LWSSSCS_POLL) | 175d4afb5ceSopenharmony_ci (1 << LWSSSCS_TIMEOUT) | 176d4afb5ceSopenharmony_ci (1 << LWSSSCS_DISCONNECTED) | 177d4afb5ceSopenharmony_ci (1 << LWSSSCS_UNREACHABLE) | 178d4afb5ceSopenharmony_ci (1 << LWSSSCS_DESTROYING), 179d4afb5ceSopenharmony_ci 180d4afb5ceSopenharmony_ci [LWSSSCS_SERVER_TXN] = (1 << LWSSSCS_DISCONNECTED) | 181d4afb5ceSopenharmony_ci (1 << LWSSSCS_TIMEOUT) | 182d4afb5ceSopenharmony_ci (1 << LWSSSCS_DESTROYING), 183d4afb5ceSopenharmony_ci 184d4afb5ceSopenharmony_ci [LWSSSCS_SERVER_UPGRADE] = (1 << LWSSSCS_SERVER_TXN) | 185d4afb5ceSopenharmony_ci (1 << LWSSSCS_TIMEOUT) | 186d4afb5ceSopenharmony_ci (1 << LWSSSCS_DISCONNECTED) | 187d4afb5ceSopenharmony_ci (1 << LWSSSCS_DESTROYING), 188d4afb5ceSopenharmony_ci}; 189d4afb5ceSopenharmony_ci 190d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CONMON) 191d4afb5ceSopenharmony_ci 192d4afb5ceSopenharmony_ci/* 193d4afb5ceSopenharmony_ci * Convert any conmon data to JSON and attach to the ss handle. 194d4afb5ceSopenharmony_ci */ 195d4afb5ceSopenharmony_ci 196d4afb5ceSopenharmony_cilws_ss_state_return_t 197d4afb5ceSopenharmony_cilws_conmon_ss_json(lws_ss_handle_t *h) 198d4afb5ceSopenharmony_ci{ 199d4afb5ceSopenharmony_ci char ads[48], *end, *buf, *obuf; 200d4afb5ceSopenharmony_ci const struct addrinfo *ai; 201d4afb5ceSopenharmony_ci lws_ss_state_return_t ret = LWSSSSRET_OK; 202d4afb5ceSopenharmony_ci struct lws_conmon cm; 203d4afb5ceSopenharmony_ci size_t len = 500; 204d4afb5ceSopenharmony_ci 205d4afb5ceSopenharmony_ci if (!h->policy || !(h->policy->flags & LWSSSPOLF_PERF) || !h->wsi || 206d4afb5ceSopenharmony_ci h->wsi->perf_done) 207d4afb5ceSopenharmony_ci return LWSSSSRET_OK; 208d4afb5ceSopenharmony_ci 209d4afb5ceSopenharmony_ci if (h->conmon_json) 210d4afb5ceSopenharmony_ci lws_free_set_NULL(h->conmon_json); 211d4afb5ceSopenharmony_ci 212d4afb5ceSopenharmony_ci h->conmon_json = lws_malloc(len, __func__); 213d4afb5ceSopenharmony_ci if (!h->conmon_json) 214d4afb5ceSopenharmony_ci return LWSSSSRET_OK; 215d4afb5ceSopenharmony_ci 216d4afb5ceSopenharmony_ci obuf = buf = h->conmon_json; 217d4afb5ceSopenharmony_ci end = buf + len - 1; 218d4afb5ceSopenharmony_ci 219d4afb5ceSopenharmony_ci lws_conmon_wsi_take(h->wsi, &cm); 220d4afb5ceSopenharmony_ci 221d4afb5ceSopenharmony_ci lws_sa46_write_numeric_address(&cm.peer46, ads, sizeof(ads)); 222d4afb5ceSopenharmony_ci buf += lws_snprintf(buf, lws_ptr_diff_size_t(end, buf), 223d4afb5ceSopenharmony_ci "{\"peer\":\"%s\"," 224d4afb5ceSopenharmony_ci "\"dns_us\":%u," 225d4afb5ceSopenharmony_ci "\"dns_disp\":%u," 226d4afb5ceSopenharmony_ci "\"sockconn_us\":%u," 227d4afb5ceSopenharmony_ci "\"tls_us\":%u," 228d4afb5ceSopenharmony_ci "\"txn_resp_us\":%u," 229d4afb5ceSopenharmony_ci "\"dns\":[", 230d4afb5ceSopenharmony_ci ads, 231d4afb5ceSopenharmony_ci (unsigned int)cm.ciu_dns, 232d4afb5ceSopenharmony_ci (unsigned int)cm.dns_disposition, 233d4afb5ceSopenharmony_ci (unsigned int)cm.ciu_sockconn, 234d4afb5ceSopenharmony_ci (unsigned int)cm.ciu_tls, 235d4afb5ceSopenharmony_ci (unsigned int)cm.ciu_txn_resp); 236d4afb5ceSopenharmony_ci 237d4afb5ceSopenharmony_ci ai = cm.dns_results_copy; 238d4afb5ceSopenharmony_ci while (ai) { 239d4afb5ceSopenharmony_ci lws_sa46_write_numeric_address((lws_sockaddr46 *)ai->ai_addr, ads, sizeof(ads)); 240d4afb5ceSopenharmony_ci buf += lws_snprintf(buf, lws_ptr_diff_size_t(end, buf), "\"%s\"", ads); 241d4afb5ceSopenharmony_ci if (ai->ai_next && buf < end - 2) 242d4afb5ceSopenharmony_ci *buf++ = ','; 243d4afb5ceSopenharmony_ci ai = ai->ai_next; 244d4afb5ceSopenharmony_ci } 245d4afb5ceSopenharmony_ci 246d4afb5ceSopenharmony_ci buf += lws_snprintf(buf, lws_ptr_diff_size_t(end, buf), "]"); 247d4afb5ceSopenharmony_ci 248d4afb5ceSopenharmony_ci switch (cm.pcol) { 249d4afb5ceSopenharmony_ci case LWSCONMON_PCOL_HTTP: 250d4afb5ceSopenharmony_ci buf += lws_snprintf(buf, lws_ptr_diff_size_t(end, buf), 251d4afb5ceSopenharmony_ci ",\"prot_specific\":{\"protocol\":\"http\",\"resp\":%u}", 252d4afb5ceSopenharmony_ci (unsigned int)cm.protocol_specific.http.response); 253d4afb5ceSopenharmony_ci break; 254d4afb5ceSopenharmony_ci default: 255d4afb5ceSopenharmony_ci break; 256d4afb5ceSopenharmony_ci } 257d4afb5ceSopenharmony_ci 258d4afb5ceSopenharmony_ci buf += lws_snprintf(buf, lws_ptr_diff_size_t(end, buf), "}"); 259d4afb5ceSopenharmony_ci 260d4afb5ceSopenharmony_ci /* 261d4afb5ceSopenharmony_ci * This destroys the DNS list in the lws_conmon that we took 262d4afb5ceSopenharmony_ci * responsibility for when we used lws_conmon_wsi_take() 263d4afb5ceSopenharmony_ci */ 264d4afb5ceSopenharmony_ci 265d4afb5ceSopenharmony_ci lws_conmon_release(&cm); 266d4afb5ceSopenharmony_ci 267d4afb5ceSopenharmony_ci h->conmon_len = (uint16_t)lws_ptr_diff(buf, obuf); 268d4afb5ceSopenharmony_ci 269d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) 270d4afb5ceSopenharmony_ci if (h->proxy_onward) { 271d4afb5ceSopenharmony_ci 272d4afb5ceSopenharmony_ci /* 273d4afb5ceSopenharmony_ci * ask to forward it on the proxy link 274d4afb5ceSopenharmony_ci */ 275d4afb5ceSopenharmony_ci 276d4afb5ceSopenharmony_ci ss_proxy_onward_link_req_writeable(h); 277d4afb5ceSopenharmony_ci return LWSSSSRET_OK; 278d4afb5ceSopenharmony_ci } 279d4afb5ceSopenharmony_ci#endif 280d4afb5ceSopenharmony_ci 281d4afb5ceSopenharmony_ci /* 282d4afb5ceSopenharmony_ci * We can deliver it directly 283d4afb5ceSopenharmony_ci */ 284d4afb5ceSopenharmony_ci 285d4afb5ceSopenharmony_ci if (h->info.rx) 286d4afb5ceSopenharmony_ci ret = h->info.rx(ss_to_userobj(h), (uint8_t *)h->conmon_json, 287d4afb5ceSopenharmony_ci (unsigned int)h->conmon_len, 288d4afb5ceSopenharmony_ci (int)(LWSSS_FLAG_SOM | LWSSS_FLAG_EOM | 289d4afb5ceSopenharmony_ci LWSSS_FLAG_PERF_JSON)); 290d4afb5ceSopenharmony_ci 291d4afb5ceSopenharmony_ci lws_free_set_NULL(h->conmon_json); 292d4afb5ceSopenharmony_ci 293d4afb5ceSopenharmony_ci return ret; 294d4afb5ceSopenharmony_ci} 295d4afb5ceSopenharmony_ci#endif 296d4afb5ceSopenharmony_ci 297d4afb5ceSopenharmony_ciint 298d4afb5ceSopenharmony_cilws_ss_check_next_state(lws_lifecycle_t *lc, uint8_t *prevstate, 299d4afb5ceSopenharmony_ci lws_ss_constate_t cs) 300d4afb5ceSopenharmony_ci{ 301d4afb5ceSopenharmony_ci if (cs >= LWSSSCS_USER_BASE || 302d4afb5ceSopenharmony_ci cs == LWSSSCS_EVENT_WAIT_CANCELLED || 303d4afb5ceSopenharmony_ci cs == LWSSSCS_SERVER_TXN || 304d4afb5ceSopenharmony_ci cs == LWSSSCS_UPSTREAM_LINK_RETRY) 305d4afb5ceSopenharmony_ci /* 306d4afb5ceSopenharmony_ci * we can't judge user or transient states, leave the old state 307d4afb5ceSopenharmony_ci * and just wave them through 308d4afb5ceSopenharmony_ci */ 309d4afb5ceSopenharmony_ci return 0; 310d4afb5ceSopenharmony_ci 311d4afb5ceSopenharmony_ci if (cs >= LWS_ARRAY_SIZE(ss_state_txn_validity)) { 312d4afb5ceSopenharmony_ci /* we don't recognize this state as usable */ 313d4afb5ceSopenharmony_ci lwsl_err("%s: %s: bad new state %u\n", __func__, lc->gutag, cs); 314d4afb5ceSopenharmony_ci assert(0); 315d4afb5ceSopenharmony_ci return 1; 316d4afb5ceSopenharmony_ci } 317d4afb5ceSopenharmony_ci 318d4afb5ceSopenharmony_ci if (*prevstate >= LWS_ARRAY_SIZE(ss_state_txn_validity)) { 319d4afb5ceSopenharmony_ci /* existing state is broken */ 320d4afb5ceSopenharmony_ci lwsl_err("%s: %s: bad existing state %u\n", __func__, 321d4afb5ceSopenharmony_ci lc->gutag, (unsigned int)*prevstate); 322d4afb5ceSopenharmony_ci assert(0); 323d4afb5ceSopenharmony_ci return 1; 324d4afb5ceSopenharmony_ci } 325d4afb5ceSopenharmony_ci 326d4afb5ceSopenharmony_ci if (ss_state_txn_validity[*prevstate] & (1u << cs)) { 327d4afb5ceSopenharmony_ci 328d4afb5ceSopenharmony_ci lwsl_notice("%s: %s: %s -> %s\n", __func__, lc->gutag, 329d4afb5ceSopenharmony_ci lws_ss_state_name((int)*prevstate), 330d4afb5ceSopenharmony_ci lws_ss_state_name((int)cs)); 331d4afb5ceSopenharmony_ci 332d4afb5ceSopenharmony_ci /* this is explicitly allowed, update old state to new */ 333d4afb5ceSopenharmony_ci *prevstate = (uint8_t)cs; 334d4afb5ceSopenharmony_ci 335d4afb5ceSopenharmony_ci return 0; 336d4afb5ceSopenharmony_ci } 337d4afb5ceSopenharmony_ci 338d4afb5ceSopenharmony_ci lwsl_err("%s: %s: transition from %s -> %s is illegal\n", __func__, 339d4afb5ceSopenharmony_ci lc->gutag, lws_ss_state_name((int)*prevstate), 340d4afb5ceSopenharmony_ci lws_ss_state_name((int)cs)); 341d4afb5ceSopenharmony_ci 342d4afb5ceSopenharmony_ci assert(0); 343d4afb5ceSopenharmony_ci 344d4afb5ceSopenharmony_ci return 1; 345d4afb5ceSopenharmony_ci} 346d4afb5ceSopenharmony_ci 347d4afb5ceSopenharmony_ciint 348d4afb5ceSopenharmony_cilws_ss_check_next_state_ss(lws_ss_handle_t *ss, uint8_t *prevstate, 349d4afb5ceSopenharmony_ci lws_ss_constate_t cs) 350d4afb5ceSopenharmony_ci{ 351d4afb5ceSopenharmony_ci if (cs >= LWSSSCS_USER_BASE || 352d4afb5ceSopenharmony_ci cs == LWSSSCS_EVENT_WAIT_CANCELLED || 353d4afb5ceSopenharmony_ci cs == LWSSSCS_UPSTREAM_LINK_RETRY) 354d4afb5ceSopenharmony_ci /* 355d4afb5ceSopenharmony_ci * we can't judge user or transient states, leave the old state 356d4afb5ceSopenharmony_ci * and just wave them through 357d4afb5ceSopenharmony_ci */ 358d4afb5ceSopenharmony_ci return 0; 359d4afb5ceSopenharmony_ci 360d4afb5ceSopenharmony_ci if (cs >= LWS_ARRAY_SIZE(ss_state_txn_validity)) { 361d4afb5ceSopenharmony_ci /* we don't recognize this state as usable */ 362d4afb5ceSopenharmony_ci lwsl_ss_err(ss, "bad new state %u", cs); 363d4afb5ceSopenharmony_ci assert(0); 364d4afb5ceSopenharmony_ci return 1; 365d4afb5ceSopenharmony_ci } 366d4afb5ceSopenharmony_ci 367d4afb5ceSopenharmony_ci if (*prevstate >= LWS_ARRAY_SIZE(ss_state_txn_validity)) { 368d4afb5ceSopenharmony_ci /* existing state is broken */ 369d4afb5ceSopenharmony_ci lwsl_ss_err(ss, "bad existing state %u", 370d4afb5ceSopenharmony_ci (unsigned int)*prevstate); 371d4afb5ceSopenharmony_ci assert(0); 372d4afb5ceSopenharmony_ci return 1; 373d4afb5ceSopenharmony_ci } 374d4afb5ceSopenharmony_ci 375d4afb5ceSopenharmony_ci if (ss_state_txn_validity[*prevstate] & (1u << cs)) { 376d4afb5ceSopenharmony_ci 377d4afb5ceSopenharmony_ci lwsl_ss_notice(ss, "%s -> %s", 378d4afb5ceSopenharmony_ci lws_ss_state_name((int)*prevstate), 379d4afb5ceSopenharmony_ci lws_ss_state_name((int)cs)); 380d4afb5ceSopenharmony_ci 381d4afb5ceSopenharmony_ci /* this is explicitly allowed, update old state to new */ 382d4afb5ceSopenharmony_ci *prevstate = (uint8_t)cs; 383d4afb5ceSopenharmony_ci 384d4afb5ceSopenharmony_ci return 0; 385d4afb5ceSopenharmony_ci } 386d4afb5ceSopenharmony_ci 387d4afb5ceSopenharmony_ci lwsl_ss_err(ss, "transition from %s -> %s is illegal", 388d4afb5ceSopenharmony_ci lws_ss_state_name((int)*prevstate), 389d4afb5ceSopenharmony_ci lws_ss_state_name((int)cs)); 390d4afb5ceSopenharmony_ci 391d4afb5ceSopenharmony_ci assert(0); 392d4afb5ceSopenharmony_ci 393d4afb5ceSopenharmony_ci return 1; 394d4afb5ceSopenharmony_ci} 395d4afb5ceSopenharmony_ci 396d4afb5ceSopenharmony_ciconst char * 397d4afb5ceSopenharmony_cilws_ss_state_name(int state) 398d4afb5ceSopenharmony_ci{ 399d4afb5ceSopenharmony_ci if (state >= LWSSSCS_USER_BASE) 400d4afb5ceSopenharmony_ci return "user state"; 401d4afb5ceSopenharmony_ci 402d4afb5ceSopenharmony_ci if (state >= (int)LWS_ARRAY_SIZE(state_names)) 403d4afb5ceSopenharmony_ci return "unknown"; 404d4afb5ceSopenharmony_ci 405d4afb5ceSopenharmony_ci return state_names[state]; 406d4afb5ceSopenharmony_ci} 407d4afb5ceSopenharmony_ci 408d4afb5ceSopenharmony_cilws_ss_state_return_t 409d4afb5ceSopenharmony_cilws_ss_event_helper(lws_ss_handle_t *h, lws_ss_constate_t cs) 410d4afb5ceSopenharmony_ci{ 411d4afb5ceSopenharmony_ci lws_ss_state_return_t r; 412d4afb5ceSopenharmony_ci 413d4afb5ceSopenharmony_ci if (!h) 414d4afb5ceSopenharmony_ci return LWSSSSRET_OK; 415d4afb5ceSopenharmony_ci 416d4afb5ceSopenharmony_ci if (lws_ss_check_next_state_ss(h, &h->prev_ss_state, cs)) 417d4afb5ceSopenharmony_ci return LWSSSSRET_DESTROY_ME; 418d4afb5ceSopenharmony_ci 419d4afb5ceSopenharmony_ci if (cs == LWSSSCS_CONNECTED) 420d4afb5ceSopenharmony_ci h->ss_dangling_connected = 1; 421d4afb5ceSopenharmony_ci if (cs == LWSSSCS_DISCONNECTED) 422d4afb5ceSopenharmony_ci h->ss_dangling_connected = 0; 423d4afb5ceSopenharmony_ci 424d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SEQUENCER) 425d4afb5ceSopenharmony_ci /* 426d4afb5ceSopenharmony_ci * A parent sequencer for the ss is optional, if we have one, keep it 427d4afb5ceSopenharmony_ci * informed of state changes on the ss connection 428d4afb5ceSopenharmony_ci */ 429d4afb5ceSopenharmony_ci if (h->seq && cs != LWSSSCS_DESTROYING) 430d4afb5ceSopenharmony_ci lws_seq_queue_event(h->seq, LWSSEQ_SS_STATE_BASE + cs, 431d4afb5ceSopenharmony_ci (void *)h, NULL); 432d4afb5ceSopenharmony_ci#endif 433d4afb5ceSopenharmony_ci 434d4afb5ceSopenharmony_ci if (h->info.state) { 435d4afb5ceSopenharmony_ci h->h_in_svc = h; 436d4afb5ceSopenharmony_ci r = h->info.state(ss_to_userobj(h), NULL, cs, 437d4afb5ceSopenharmony_ci cs == LWSSSCS_UNREACHABLE && 438d4afb5ceSopenharmony_ci h->wsi && h->wsi->dns_reachability); 439d4afb5ceSopenharmony_ci h->h_in_svc = NULL; 440d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER) 441d4afb5ceSopenharmony_ci if ((h->info.flags & LWSSSINFLAGS_ACCEPTED) && 442d4afb5ceSopenharmony_ci cs == LWSSSCS_DISCONNECTED) 443d4afb5ceSopenharmony_ci r = LWSSSSRET_DESTROY_ME; 444d4afb5ceSopenharmony_ci#endif 445d4afb5ceSopenharmony_ci return r; 446d4afb5ceSopenharmony_ci } 447d4afb5ceSopenharmony_ci 448d4afb5ceSopenharmony_ci return LWSSSSRET_OK; 449d4afb5ceSopenharmony_ci} 450d4afb5ceSopenharmony_ci 451d4afb5ceSopenharmony_ciint 452d4afb5ceSopenharmony_ci_lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(lws_ss_state_return_t r, struct lws *wsi, 453d4afb5ceSopenharmony_ci lws_ss_handle_t **ph) 454d4afb5ceSopenharmony_ci{ 455d4afb5ceSopenharmony_ci if (r == LWSSSSRET_DESTROY_ME) { 456d4afb5ceSopenharmony_ci lwsl_info("%s: DESTROY ME: %s, %s\n", __func__, 457d4afb5ceSopenharmony_ci lws_wsi_tag(wsi), lws_ss_tag(*ph)); 458d4afb5ceSopenharmony_ci if (wsi) { 459d4afb5ceSopenharmony_ci lws_set_opaque_user_data(wsi, NULL); 460d4afb5ceSopenharmony_ci lws_set_timeout(wsi, 1, LWS_TO_KILL_ASYNC); 461d4afb5ceSopenharmony_ci } else { 462d4afb5ceSopenharmony_ci if ((*ph)->wsi) { 463d4afb5ceSopenharmony_ci lws_set_opaque_user_data((*ph)->wsi, NULL); 464d4afb5ceSopenharmony_ci lws_set_timeout((*ph)->wsi, 1, LWS_TO_KILL_ASYNC); 465d4afb5ceSopenharmony_ci } 466d4afb5ceSopenharmony_ci } 467d4afb5ceSopenharmony_ci (*ph)->wsi = NULL; 468d4afb5ceSopenharmony_ci lws_ss_destroy(ph); 469d4afb5ceSopenharmony_ci } 470d4afb5ceSopenharmony_ci 471d4afb5ceSopenharmony_ci return -1; /* close connection */ 472d4afb5ceSopenharmony_ci} 473d4afb5ceSopenharmony_ci 474d4afb5ceSopenharmony_cistatic void 475d4afb5ceSopenharmony_cilws_ss_timeout_sul_check_cb(lws_sorted_usec_list_t *sul) 476d4afb5ceSopenharmony_ci{ 477d4afb5ceSopenharmony_ci lws_ss_state_return_t r; 478d4afb5ceSopenharmony_ci lws_ss_handle_t *h = lws_container_of(sul, lws_ss_handle_t, sul); 479d4afb5ceSopenharmony_ci 480d4afb5ceSopenharmony_ci lwsl_info("%s: retrying %s after backoff\n", __func__, lws_ss_tag(h)); 481d4afb5ceSopenharmony_ci /* we want to retry... */ 482d4afb5ceSopenharmony_ci h->seqstate = SSSEQ_DO_RETRY; 483d4afb5ceSopenharmony_ci 484d4afb5ceSopenharmony_ci r = _lws_ss_request_tx(h); 485d4afb5ceSopenharmony_ci _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, NULL, &h); 486d4afb5ceSopenharmony_ci} 487d4afb5ceSopenharmony_ci 488d4afb5ceSopenharmony_ciint 489d4afb5ceSopenharmony_cilws_ss_exp_cb_metadata(void *priv, const char *name, char *out, size_t *pos, 490d4afb5ceSopenharmony_ci size_t olen, size_t *exp_ofs) 491d4afb5ceSopenharmony_ci{ 492d4afb5ceSopenharmony_ci lws_ss_handle_t *h = (lws_ss_handle_t *)priv; 493d4afb5ceSopenharmony_ci const char *replace = NULL; 494d4afb5ceSopenharmony_ci size_t total, budget; 495d4afb5ceSopenharmony_ci lws_ss_metadata_t *md = lws_ss_policy_metadata(h->policy, name), 496d4afb5ceSopenharmony_ci *hmd = lws_ss_get_handle_metadata(h, name); 497d4afb5ceSopenharmony_ci 498d4afb5ceSopenharmony_ci if (!md) { 499d4afb5ceSopenharmony_ci lwsl_err("%s: Unknown metadata %s\n", __func__, name); 500d4afb5ceSopenharmony_ci 501d4afb5ceSopenharmony_ci return LSTRX_FATAL_NAME_UNKNOWN; 502d4afb5ceSopenharmony_ci } 503d4afb5ceSopenharmony_ci 504d4afb5ceSopenharmony_ci if (!hmd) 505d4afb5ceSopenharmony_ci return LSTRX_FILLED_OUT; 506d4afb5ceSopenharmony_ci 507d4afb5ceSopenharmony_ci replace = hmd->value__may_own_heap; 508d4afb5ceSopenharmony_ci 509d4afb5ceSopenharmony_ci if (!replace) 510d4afb5ceSopenharmony_ci return LSTRX_DONE; 511d4afb5ceSopenharmony_ci 512d4afb5ceSopenharmony_ci total = hmd->length; 513d4afb5ceSopenharmony_ci 514d4afb5ceSopenharmony_ci budget = olen - *pos; 515d4afb5ceSopenharmony_ci total -= *exp_ofs; 516d4afb5ceSopenharmony_ci if (total < budget) 517d4afb5ceSopenharmony_ci budget = total; 518d4afb5ceSopenharmony_ci 519d4afb5ceSopenharmony_ci if (out) 520d4afb5ceSopenharmony_ci memcpy(out + *pos, replace + (*exp_ofs), budget); 521d4afb5ceSopenharmony_ci *exp_ofs += budget; 522d4afb5ceSopenharmony_ci *pos += budget; 523d4afb5ceSopenharmony_ci 524d4afb5ceSopenharmony_ci if (budget == total) 525d4afb5ceSopenharmony_ci return LSTRX_DONE; 526d4afb5ceSopenharmony_ci 527d4afb5ceSopenharmony_ci return LSTRX_FILLED_OUT; 528d4afb5ceSopenharmony_ci} 529d4afb5ceSopenharmony_ci 530d4afb5ceSopenharmony_ciint 531d4afb5ceSopenharmony_cilws_ss_set_timeout_us(lws_ss_handle_t *h, lws_usec_t us) 532d4afb5ceSopenharmony_ci{ 533d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &h->context->pt[h->tsi]; 534d4afb5ceSopenharmony_ci 535d4afb5ceSopenharmony_ci h->sul.cb = lws_ss_timeout_sul_check_cb; 536d4afb5ceSopenharmony_ci __lws_sul_insert_us(&pt->pt_sul_owner[ 537d4afb5ceSopenharmony_ci !!(h->policy->flags & LWSSSPOLF_WAKE_SUSPEND__VALIDITY)], 538d4afb5ceSopenharmony_ci &h->sul, us); 539d4afb5ceSopenharmony_ci 540d4afb5ceSopenharmony_ci return 0; 541d4afb5ceSopenharmony_ci} 542d4afb5ceSopenharmony_ci 543d4afb5ceSopenharmony_cilws_ss_state_return_t 544d4afb5ceSopenharmony_ci_lws_ss_backoff(lws_ss_handle_t *h, lws_usec_t us_override) 545d4afb5ceSopenharmony_ci{ 546d4afb5ceSopenharmony_ci uint64_t ms; 547d4afb5ceSopenharmony_ci char conceal; 548d4afb5ceSopenharmony_ci 549d4afb5ceSopenharmony_ci lws_service_assert_loop_thread(h->context, h->tsi); 550d4afb5ceSopenharmony_ci 551d4afb5ceSopenharmony_ci if (h->seqstate == SSSEQ_RECONNECT_WAIT) 552d4afb5ceSopenharmony_ci return LWSSSSRET_OK; 553d4afb5ceSopenharmony_ci 554d4afb5ceSopenharmony_ci /* figure out what we should do about another retry */ 555d4afb5ceSopenharmony_ci 556d4afb5ceSopenharmony_ci lwsl_info("%s: %s: retry backoff after failure\n", __func__, lws_ss_tag(h)); 557d4afb5ceSopenharmony_ci ms = lws_retry_get_delay_ms(h->context, h->policy->retry_bo, 558d4afb5ceSopenharmony_ci &h->retry, &conceal); 559d4afb5ceSopenharmony_ci if (!conceal) { 560d4afb5ceSopenharmony_ci lwsl_info("%s: %s: abandon conn attempt \n",__func__, lws_ss_tag(h)); 561d4afb5ceSopenharmony_ci 562d4afb5ceSopenharmony_ci if (h->seqstate == SSSEQ_IDLE) /* been here? */ 563d4afb5ceSopenharmony_ci return LWSSSSRET_OK; 564d4afb5ceSopenharmony_ci 565d4afb5ceSopenharmony_ci h->seqstate = SSSEQ_IDLE; 566d4afb5ceSopenharmony_ci 567d4afb5ceSopenharmony_ci return lws_ss_event_helper(h, LWSSSCS_ALL_RETRIES_FAILED); 568d4afb5ceSopenharmony_ci } 569d4afb5ceSopenharmony_ci 570d4afb5ceSopenharmony_ci /* Only increase our planned backoff, or go with it */ 571d4afb5ceSopenharmony_ci 572d4afb5ceSopenharmony_ci if (us_override < (lws_usec_t)ms * LWS_US_PER_MS) 573d4afb5ceSopenharmony_ci us_override = (lws_usec_t)(ms * LWS_US_PER_MS); 574d4afb5ceSopenharmony_ci 575d4afb5ceSopenharmony_ci h->seqstate = SSSEQ_RECONNECT_WAIT; 576d4afb5ceSopenharmony_ci lws_ss_set_timeout_us(h, us_override); 577d4afb5ceSopenharmony_ci 578d4afb5ceSopenharmony_ci lwsl_info("%s: %s: retry wait %dms\n", __func__, lws_ss_tag(h), 579d4afb5ceSopenharmony_ci (int)(us_override / 1000)); 580d4afb5ceSopenharmony_ci 581d4afb5ceSopenharmony_ci return LWSSSSRET_OK; 582d4afb5ceSopenharmony_ci} 583d4afb5ceSopenharmony_ci 584d4afb5ceSopenharmony_cilws_ss_state_return_t 585d4afb5ceSopenharmony_cilws_ss_backoff(lws_ss_handle_t *h) 586d4afb5ceSopenharmony_ci{ 587d4afb5ceSopenharmony_ci return _lws_ss_backoff(h, 0); 588d4afb5ceSopenharmony_ci} 589d4afb5ceSopenharmony_ci 590d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_SMD) 591d4afb5ceSopenharmony_ci 592d4afb5ceSopenharmony_ci/* 593d4afb5ceSopenharmony_ci * Local SMD <-> SS 594d4afb5ceSopenharmony_ci * 595d4afb5ceSopenharmony_ci * We pass received messages through to the SS handler synchronously, using the 596d4afb5ceSopenharmony_ci * lws service thread context. 597d4afb5ceSopenharmony_ci * 598d4afb5ceSopenharmony_ci * After the SS is created and registered, still nothing is going to come here 599d4afb5ceSopenharmony_ci * until the peer sends us his rx_class_mask and we update his registration with 600d4afb5ceSopenharmony_ci * it, because from SS creation his rx_class_mask defaults to 0. 601d4afb5ceSopenharmony_ci */ 602d4afb5ceSopenharmony_ci 603d4afb5ceSopenharmony_cistatic int 604d4afb5ceSopenharmony_cilws_smd_ss_cb(void *opaque, lws_smd_class_t _class, 605d4afb5ceSopenharmony_ci lws_usec_t timestamp, void *buf, size_t len) 606d4afb5ceSopenharmony_ci{ 607d4afb5ceSopenharmony_ci lws_ss_handle_t *h = (lws_ss_handle_t *)opaque; 608d4afb5ceSopenharmony_ci uint8_t *p = (uint8_t *)buf - LWS_SMD_SS_RX_HEADER_LEN; 609d4afb5ceSopenharmony_ci 610d4afb5ceSopenharmony_ci lws_service_assert_loop_thread(h->context, h->tsi); 611d4afb5ceSopenharmony_ci 612d4afb5ceSopenharmony_ci /* 613d4afb5ceSopenharmony_ci * When configured with SS enabled, lws over-allocates 614d4afb5ceSopenharmony_ci * LWS_SMD_SS_RX_HEADER_LEN bytes behind the payload of the queued 615d4afb5ceSopenharmony_ci * message, for prepending serialized class and timestamp data in-band 616d4afb5ceSopenharmony_ci * with the payload. 617d4afb5ceSopenharmony_ci */ 618d4afb5ceSopenharmony_ci 619d4afb5ceSopenharmony_ci lws_ser_wu64be(p, _class); 620d4afb5ceSopenharmony_ci lws_ser_wu64be(p + 8, (uint64_t)timestamp); 621d4afb5ceSopenharmony_ci 622d4afb5ceSopenharmony_ci if (h->info.rx) 623d4afb5ceSopenharmony_ci h->info.rx((void *)(h + 1), p, len + LWS_SMD_SS_RX_HEADER_LEN, 624d4afb5ceSopenharmony_ci LWSSS_FLAG_SOM | LWSSS_FLAG_EOM); 625d4afb5ceSopenharmony_ci 626d4afb5ceSopenharmony_ci return 0; 627d4afb5ceSopenharmony_ci} 628d4afb5ceSopenharmony_ci 629d4afb5ceSopenharmony_cistatic void 630d4afb5ceSopenharmony_cilws_ss_smd_tx_cb(lws_sorted_usec_list_t *sul) 631d4afb5ceSopenharmony_ci{ 632d4afb5ceSopenharmony_ci lws_ss_handle_t *h = lws_container_of(sul, lws_ss_handle_t, u.smd.sul_write); 633d4afb5ceSopenharmony_ci uint8_t buf[LWS_SMD_SS_RX_HEADER_LEN + LWS_SMD_MAX_PAYLOAD], *p; 634d4afb5ceSopenharmony_ci size_t len = sizeof(buf); 635d4afb5ceSopenharmony_ci lws_smd_class_t _class; 636d4afb5ceSopenharmony_ci int flags = 0, n; 637d4afb5ceSopenharmony_ci 638d4afb5ceSopenharmony_ci lws_service_assert_loop_thread(h->context, h->tsi); 639d4afb5ceSopenharmony_ci 640d4afb5ceSopenharmony_ci if (!h->info.tx) 641d4afb5ceSopenharmony_ci return; 642d4afb5ceSopenharmony_ci 643d4afb5ceSopenharmony_ci n = h->info.tx((h + 1), h->txord++, buf, &len, &flags); 644d4afb5ceSopenharmony_ci if (n) 645d4afb5ceSopenharmony_ci /* nonzero return means don't want to send anything */ 646d4afb5ceSopenharmony_ci return; 647d4afb5ceSopenharmony_ci 648d4afb5ceSopenharmony_ci // lwsl_notice("%s: (SS %p bound to _lws_smd creates message) tx len %d\n", __func__, h, (int)len); 649d4afb5ceSopenharmony_ci // lwsl_hexdump_notice(buf, len); 650d4afb5ceSopenharmony_ci 651d4afb5ceSopenharmony_ci assert(len >= LWS_SMD_SS_RX_HEADER_LEN); 652d4afb5ceSopenharmony_ci _class = (lws_smd_class_t)lws_ser_ru64be(buf); 653d4afb5ceSopenharmony_ci p = lws_smd_msg_alloc(h->context, _class, len - LWS_SMD_SS_RX_HEADER_LEN); 654d4afb5ceSopenharmony_ci if (!p) { 655d4afb5ceSopenharmony_ci // this can be rejected if nobody listening for this class 656d4afb5ceSopenharmony_ci //lwsl_notice("%s: failed to alloc\n", __func__); 657d4afb5ceSopenharmony_ci return; 658d4afb5ceSopenharmony_ci } 659d4afb5ceSopenharmony_ci 660d4afb5ceSopenharmony_ci memcpy(p, buf + LWS_SMD_SS_RX_HEADER_LEN, len - LWS_SMD_SS_RX_HEADER_LEN); 661d4afb5ceSopenharmony_ci if (lws_smd_msg_send(h->context, p)) { 662d4afb5ceSopenharmony_ci lwsl_notice("%s: failed to queue\n", __func__); 663d4afb5ceSopenharmony_ci return; 664d4afb5ceSopenharmony_ci } 665d4afb5ceSopenharmony_ci} 666d4afb5ceSopenharmony_ci 667d4afb5ceSopenharmony_ci#endif 668d4afb5ceSopenharmony_ci 669d4afb5ceSopenharmony_cilws_ss_state_return_t 670d4afb5ceSopenharmony_ci_lws_ss_client_connect(lws_ss_handle_t *h, int is_retry, void *conn_if_sspc_onw) 671d4afb5ceSopenharmony_ci{ 672d4afb5ceSopenharmony_ci const char *prot, *_prot, *ipath, *_ipath, *ads, *_ads; 673d4afb5ceSopenharmony_ci struct lws_client_connect_info i; 674d4afb5ceSopenharmony_ci const struct ss_pcols *ssp; 675d4afb5ceSopenharmony_ci size_t used_in, used_out; 676d4afb5ceSopenharmony_ci union lws_ss_contemp ct; 677d4afb5ceSopenharmony_ci lws_ss_state_return_t r; 678d4afb5ceSopenharmony_ci int port, _port, tls; 679d4afb5ceSopenharmony_ci char *path, ep[96]; 680d4afb5ceSopenharmony_ci lws_strexp_t exp; 681d4afb5ceSopenharmony_ci struct lws *wsi; 682d4afb5ceSopenharmony_ci 683d4afb5ceSopenharmony_ci lws_service_assert_loop_thread(h->context, h->tsi); 684d4afb5ceSopenharmony_ci 685d4afb5ceSopenharmony_ci if (!h->policy) { 686d4afb5ceSopenharmony_ci lwsl_err("%s: ss with no policy\n", __func__); 687d4afb5ceSopenharmony_ci 688d4afb5ceSopenharmony_ci return LWSSSSRET_OK; 689d4afb5ceSopenharmony_ci } 690d4afb5ceSopenharmony_ci 691d4afb5ceSopenharmony_ci /* 692d4afb5ceSopenharmony_ci * We are already bound to a sink? 693d4afb5ceSopenharmony_ci */ 694d4afb5ceSopenharmony_ci 695d4afb5ceSopenharmony_ci// if (h->h_sink) 696d4afb5ceSopenharmony_ci// return 0; 697d4afb5ceSopenharmony_ci 698d4afb5ceSopenharmony_ci if (!is_retry) 699d4afb5ceSopenharmony_ci h->retry = 0; 700d4afb5ceSopenharmony_ci 701d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_SMD) 702d4afb5ceSopenharmony_ci if (h->policy == &pol_smd) { 703d4afb5ceSopenharmony_ci 704d4afb5ceSopenharmony_ci if (h->u.smd.smd_peer) 705d4afb5ceSopenharmony_ci return LWSSSSRET_OK; 706d4afb5ceSopenharmony_ci 707d4afb5ceSopenharmony_ci // lwsl_notice("%s: received connect for _lws_smd, registering for class mask 0x%x\n", 708d4afb5ceSopenharmony_ci // __func__, h->info.manual_initial_tx_credit); 709d4afb5ceSopenharmony_ci 710d4afb5ceSopenharmony_ci h->u.smd.smd_peer = lws_smd_register(h->context, h, 711d4afb5ceSopenharmony_ci (h->info.flags & LWSSSINFLAGS_PROXIED) ? 712d4afb5ceSopenharmony_ci LWSSMDREG_FLAG_PROXIED_SS : 0, 713d4afb5ceSopenharmony_ci (lws_smd_class_t)h->info.manual_initial_tx_credit, 714d4afb5ceSopenharmony_ci lws_smd_ss_cb); 715d4afb5ceSopenharmony_ci if (!h->u.smd.smd_peer) 716d4afb5ceSopenharmony_ci return LWSSSSRET_TX_DONT_SEND; 717d4afb5ceSopenharmony_ci 718d4afb5ceSopenharmony_ci if (lws_ss_event_helper(h, LWSSSCS_CONNECTING)) 719d4afb5ceSopenharmony_ci return LWSSSSRET_TX_DONT_SEND; 720d4afb5ceSopenharmony_ci 721d4afb5ceSopenharmony_ci if (lws_ss_event_helper(h, LWSSSCS_CONNECTED)) 722d4afb5ceSopenharmony_ci return LWSSSSRET_TX_DONT_SEND; 723d4afb5ceSopenharmony_ci return LWSSSSRET_OK; 724d4afb5ceSopenharmony_ci } 725d4afb5ceSopenharmony_ci#endif 726d4afb5ceSopenharmony_ci 727d4afb5ceSopenharmony_ci /* 728d4afb5ceSopenharmony_ci * We're going to substitute ${metadata} in the endpoint at connection- 729d4afb5ceSopenharmony_ci * time, so this can be set dynamically... 730d4afb5ceSopenharmony_ci */ 731d4afb5ceSopenharmony_ci 732d4afb5ceSopenharmony_ci lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, ep, sizeof(ep)); 733d4afb5ceSopenharmony_ci 734d4afb5ceSopenharmony_ci if (lws_strexp_expand(&exp, h->policy->endpoint, 735d4afb5ceSopenharmony_ci strlen(h->policy->endpoint), 736d4afb5ceSopenharmony_ci &used_in, &used_out) != LSTRX_DONE) { 737d4afb5ceSopenharmony_ci lwsl_err("%s: address strexp failed\n", __func__); 738d4afb5ceSopenharmony_ci 739d4afb5ceSopenharmony_ci return LWSSSSRET_TX_DONT_SEND; 740d4afb5ceSopenharmony_ci } 741d4afb5ceSopenharmony_ci 742d4afb5ceSopenharmony_ci /* 743d4afb5ceSopenharmony_ci * ... in some cases, we might want the user to be able to override 744d4afb5ceSopenharmony_ci * some policy settings by what he provided in there. For example, 745d4afb5ceSopenharmony_ci * if he set the endpoint to "https://myendpoint.com:4443/mypath" it 746d4afb5ceSopenharmony_ci * might be quite convenient to override the policy to follow the info 747d4afb5ceSopenharmony_ci * that was given for at least server, port and the url path. 748d4afb5ceSopenharmony_ci */ 749d4afb5ceSopenharmony_ci 750d4afb5ceSopenharmony_ci _port = port = h->policy->port; 751d4afb5ceSopenharmony_ci _prot = prot = NULL; 752d4afb5ceSopenharmony_ci _ipath = ipath = ""; 753d4afb5ceSopenharmony_ci _ads = ads = ep; 754d4afb5ceSopenharmony_ci 755d4afb5ceSopenharmony_ci if (strchr(ep, ':') && 756d4afb5ceSopenharmony_ci !lws_parse_uri(ep, &_prot, &_ads, &_port, &_ipath)) { 757d4afb5ceSopenharmony_ci lwsl_debug("%s: using uri parse results '%s' '%s' %d '%s'\n", 758d4afb5ceSopenharmony_ci __func__, _prot, _ads, _port, _ipath); 759d4afb5ceSopenharmony_ci prot = _prot; 760d4afb5ceSopenharmony_ci ads = _ads; 761d4afb5ceSopenharmony_ci port = _port; 762d4afb5ceSopenharmony_ci ipath = _ipath; 763d4afb5ceSopenharmony_ci } 764d4afb5ceSopenharmony_ci 765d4afb5ceSopenharmony_ci memset(&i, 0, sizeof i); /* otherwise uninitialized garbage */ 766d4afb5ceSopenharmony_ci i.context = h->context; 767d4afb5ceSopenharmony_ci tls = !!(h->policy->flags & LWSSSPOLF_TLS); 768d4afb5ceSopenharmony_ci 769d4afb5ceSopenharmony_ci if (prot && (!strcmp(prot, "http") || !strcmp(prot, "ws") || 770d4afb5ceSopenharmony_ci !strcmp(prot, "mqtt"))) 771d4afb5ceSopenharmony_ci tls = 0; 772d4afb5ceSopenharmony_ci 773d4afb5ceSopenharmony_ci if (tls) { 774d4afb5ceSopenharmony_ci lwsl_info("%s: using tls\n", __func__); 775d4afb5ceSopenharmony_ci i.ssl_connection = LCCSCF_USE_SSL; 776d4afb5ceSopenharmony_ci 777d4afb5ceSopenharmony_ci if (!h->policy->trust.store) 778d4afb5ceSopenharmony_ci lwsl_info("%s: using platform trust store\n", __func__); 779d4afb5ceSopenharmony_ci else { 780d4afb5ceSopenharmony_ci 781d4afb5ceSopenharmony_ci i.vhost = lws_get_vhost_by_name(h->context, 782d4afb5ceSopenharmony_ci h->policy->trust.store->name); 783d4afb5ceSopenharmony_ci if (!i.vhost) { 784d4afb5ceSopenharmony_ci lwsl_err("%s: missing vh for policy %s\n", 785d4afb5ceSopenharmony_ci __func__, 786d4afb5ceSopenharmony_ci h->policy->trust.store->name); 787d4afb5ceSopenharmony_ci 788d4afb5ceSopenharmony_ci return -1; 789d4afb5ceSopenharmony_ci } 790d4afb5ceSopenharmony_ci } 791d4afb5ceSopenharmony_ci } 792d4afb5ceSopenharmony_ci 793d4afb5ceSopenharmony_ci if (h->policy->flags & LWSSSPOLF_WAKE_SUSPEND__VALIDITY) 794d4afb5ceSopenharmony_ci i.ssl_connection |= LCCSCF_WAKE_SUSPEND__VALIDITY; 795d4afb5ceSopenharmony_ci 796d4afb5ceSopenharmony_ci /* translate policy attributes to IP ToS flags */ 797d4afb5ceSopenharmony_ci 798d4afb5ceSopenharmony_ci if (h->policy->flags & LWSSSPOLF_ATTR_LOW_LATENCY) 799d4afb5ceSopenharmony_ci i.ssl_connection |= LCCSCF_IP_LOW_LATENCY; 800d4afb5ceSopenharmony_ci if (h->policy->flags & LWSSSPOLF_ATTR_HIGH_THROUGHPUT) 801d4afb5ceSopenharmony_ci i.ssl_connection |= LCCSCF_IP_HIGH_THROUGHPUT; 802d4afb5ceSopenharmony_ci if (h->policy->flags & LWSSSPOLF_ATTR_HIGH_RELIABILITY) 803d4afb5ceSopenharmony_ci i.ssl_connection |= LCCSCF_IP_HIGH_RELIABILITY; 804d4afb5ceSopenharmony_ci if (h->policy->flags & LWSSSPOLF_ATTR_LOW_COST) 805d4afb5ceSopenharmony_ci i.ssl_connection |= LCCSCF_IP_LOW_COST; 806d4afb5ceSopenharmony_ci if (h->policy->flags & LWSSSPOLF_PERF) /* collect conmon stats on this */ 807d4afb5ceSopenharmony_ci i.ssl_connection |= LCCSCF_CONMON; 808d4afb5ceSopenharmony_ci 809d4afb5ceSopenharmony_ci /* mark the connection with the streamtype priority from the policy */ 810d4afb5ceSopenharmony_ci 811d4afb5ceSopenharmony_ci i.priority = h->policy->priority; 812d4afb5ceSopenharmony_ci 813d4afb5ceSopenharmony_ci i.ssl_connection |= LCCSCF_SECSTREAM_CLIENT; 814d4afb5ceSopenharmony_ci 815d4afb5ceSopenharmony_ci if (conn_if_sspc_onw) { 816d4afb5ceSopenharmony_ci i.ssl_connection |= LCCSCF_SECSTREAM_PROXY_ONWARD; 817d4afb5ceSopenharmony_ci h->conn_if_sspc_onw = conn_if_sspc_onw; 818d4afb5ceSopenharmony_ci } 819d4afb5ceSopenharmony_ci 820d4afb5ceSopenharmony_ci 821d4afb5ceSopenharmony_ci i.address = ads; 822d4afb5ceSopenharmony_ci i.port = port; 823d4afb5ceSopenharmony_ci i.host = i.address; 824d4afb5ceSopenharmony_ci i.origin = i.address; 825d4afb5ceSopenharmony_ci i.opaque_user_data = h; 826d4afb5ceSopenharmony_ci i.seq = h->seq; 827d4afb5ceSopenharmony_ci i.retry_and_idle_policy = h->policy->retry_bo; 828d4afb5ceSopenharmony_ci i.sys_tls_client_cert = h->policy->client_cert; 829d4afb5ceSopenharmony_ci 830d4afb5ceSopenharmony_ci i.path = ipath; 831d4afb5ceSopenharmony_ci /* if this is not "", munge should use it instead of policy 832d4afb5ceSopenharmony_ci * url path 833d4afb5ceSopenharmony_ci */ 834d4afb5ceSopenharmony_ci 835d4afb5ceSopenharmony_ci ssp = ss_pcols[(int)h->policy->protocol]; 836d4afb5ceSopenharmony_ci if (!ssp) { 837d4afb5ceSopenharmony_ci lwsl_err("%s: unsupported protocol\n", __func__); 838d4afb5ceSopenharmony_ci 839d4afb5ceSopenharmony_ci return LWSSSSRET_TX_DONT_SEND; 840d4afb5ceSopenharmony_ci } 841d4afb5ceSopenharmony_ci i.alpn = ssp->alpn; 842d4afb5ceSopenharmony_ci 843d4afb5ceSopenharmony_ci /* 844d4afb5ceSopenharmony_ci * For http, we can get the method from the http object, override in 845d4afb5ceSopenharmony_ci * the protocol-specific munge callback below if not http 846d4afb5ceSopenharmony_ci */ 847d4afb5ceSopenharmony_ci i.method = h->policy->u.http.method; 848d4afb5ceSopenharmony_ci i.protocol = ssp->protocol->name; /* lws protocol name */ 849d4afb5ceSopenharmony_ci i.local_protocol_name = i.protocol; 850d4afb5ceSopenharmony_ci 851d4afb5ceSopenharmony_ci path = lws_malloc(h->context->max_http_header_data, __func__); 852d4afb5ceSopenharmony_ci if (!path) { 853d4afb5ceSopenharmony_ci lwsl_warn("%s: OOM on path prealloc\n", __func__); 854d4afb5ceSopenharmony_ci return LWSSSSRET_TX_DONT_SEND; 855d4afb5ceSopenharmony_ci } 856d4afb5ceSopenharmony_ci 857d4afb5ceSopenharmony_ci if (ssp->munge) /* eg, raw doesn't use; endpoint strexp already done */ 858d4afb5ceSopenharmony_ci ssp->munge(h, path, h->context->max_http_header_data, &i, &ct); 859d4afb5ceSopenharmony_ci 860d4afb5ceSopenharmony_ci i.pwsi = &h->wsi; 861d4afb5ceSopenharmony_ci 862d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SSPLUGINS) 863d4afb5ceSopenharmony_ci if (h->policy->plugins[0] && h->policy->plugins[0]->munge) 864d4afb5ceSopenharmony_ci h->policy->plugins[0]->munge(h, path, h->context->max_http_header_data); 865d4afb5ceSopenharmony_ci#endif 866d4afb5ceSopenharmony_ci 867d4afb5ceSopenharmony_ci lwsl_info("%s: connecting %s, '%s' '%s' %s\n", __func__, i.method, 868d4afb5ceSopenharmony_ci i.alpn, i.address, i.path); 869d4afb5ceSopenharmony_ci 870d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_METRICS) 871d4afb5ceSopenharmony_ci /* possibly already hanging connect retry... */ 872d4afb5ceSopenharmony_ci if (!h->cal_txn.mt) 873d4afb5ceSopenharmony_ci lws_metrics_caliper_bind(h->cal_txn, h->context->mth_ss_conn); 874d4afb5ceSopenharmony_ci 875d4afb5ceSopenharmony_ci if (h->policy->streamtype) 876d4afb5ceSopenharmony_ci lws_metrics_tag_add(&h->cal_txn.mtags_owner, "ss", 877d4afb5ceSopenharmony_ci h->policy->streamtype); 878d4afb5ceSopenharmony_ci#endif 879d4afb5ceSopenharmony_ci 880d4afb5ceSopenharmony_ci h->txn_ok = 0; 881d4afb5ceSopenharmony_ci r = lws_ss_event_helper(h, LWSSSCS_CONNECTING); 882d4afb5ceSopenharmony_ci if (r) { 883d4afb5ceSopenharmony_ci lws_free(path); 884d4afb5ceSopenharmony_ci return r; 885d4afb5ceSopenharmony_ci } 886d4afb5ceSopenharmony_ci 887d4afb5ceSopenharmony_ci h->inside_connect = 1; 888d4afb5ceSopenharmony_ci h->pending_ret = LWSSSSRET_OK; 889d4afb5ceSopenharmony_ci wsi = lws_client_connect_via_info(&i); 890d4afb5ceSopenharmony_ci h->inside_connect = 0; 891d4afb5ceSopenharmony_ci lws_free(path); 892d4afb5ceSopenharmony_ci if (!wsi) { 893d4afb5ceSopenharmony_ci /* 894d4afb5ceSopenharmony_ci * We already found that we could not connect, without even 895d4afb5ceSopenharmony_ci * having to go around the event loop 896d4afb5ceSopenharmony_ci */ 897d4afb5ceSopenharmony_ci 898d4afb5ceSopenharmony_ci if (h->pending_ret) 899d4afb5ceSopenharmony_ci return h->pending_ret; 900d4afb5ceSopenharmony_ci 901d4afb5ceSopenharmony_ci if (h->prev_ss_state != LWSSSCS_UNREACHABLE && 902d4afb5ceSopenharmony_ci h->prev_ss_state != LWSSSCS_ALL_RETRIES_FAILED) { 903d4afb5ceSopenharmony_ci /* 904d4afb5ceSopenharmony_ci * blocking DNS failure can get to unreachable via 905d4afb5ceSopenharmony_ci * CCE, and unreachable can get to ALL_RETRIES_FAILED 906d4afb5ceSopenharmony_ci */ 907d4afb5ceSopenharmony_ci r = lws_ss_event_helper(h, LWSSSCS_UNREACHABLE); 908d4afb5ceSopenharmony_ci if (r) 909d4afb5ceSopenharmony_ci return r; 910d4afb5ceSopenharmony_ci 911d4afb5ceSopenharmony_ci r = lws_ss_backoff(h); 912d4afb5ceSopenharmony_ci if (r) 913d4afb5ceSopenharmony_ci return r; 914d4afb5ceSopenharmony_ci } 915d4afb5ceSopenharmony_ci 916d4afb5ceSopenharmony_ci return LWSSSSRET_TX_DONT_SEND; 917d4afb5ceSopenharmony_ci } 918d4afb5ceSopenharmony_ci 919d4afb5ceSopenharmony_ci return LWSSSSRET_OK; 920d4afb5ceSopenharmony_ci} 921d4afb5ceSopenharmony_ci 922d4afb5ceSopenharmony_cilws_ss_state_return_t 923d4afb5ceSopenharmony_cilws_ss_client_connect(lws_ss_handle_t *h) 924d4afb5ceSopenharmony_ci{ 925d4afb5ceSopenharmony_ci lws_ss_state_return_t r; 926d4afb5ceSopenharmony_ci 927d4afb5ceSopenharmony_ci lws_service_assert_loop_thread(h->context, h->tsi); 928d4afb5ceSopenharmony_ci 929d4afb5ceSopenharmony_ci r = _lws_ss_client_connect(h, 0, 0); 930d4afb5ceSopenharmony_ci 931d4afb5ceSopenharmony_ci return r; 932d4afb5ceSopenharmony_ci} 933d4afb5ceSopenharmony_ci 934d4afb5ceSopenharmony_ci/* 935d4afb5ceSopenharmony_ci * Public API 936d4afb5ceSopenharmony_ci */ 937d4afb5ceSopenharmony_ci 938d4afb5ceSopenharmony_ci/* 939d4afb5ceSopenharmony_ci * Create either a stream or a sink 940d4afb5ceSopenharmony_ci */ 941d4afb5ceSopenharmony_ci 942d4afb5ceSopenharmony_ciint 943d4afb5ceSopenharmony_cilws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, 944d4afb5ceSopenharmony_ci void *opaque_user_data, lws_ss_handle_t **ppss, 945d4afb5ceSopenharmony_ci struct lws_sequencer *seq_owner, const char **ppayload_fmt) 946d4afb5ceSopenharmony_ci{ 947d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &context->pt[tsi]; 948d4afb5ceSopenharmony_ci const lws_ss_policy_t *pol; 949d4afb5ceSopenharmony_ci lws_ss_state_return_t r; 950d4afb5ceSopenharmony_ci lws_ss_metadata_t *smd; 951d4afb5ceSopenharmony_ci lws_ss_handle_t *h; 952d4afb5ceSopenharmony_ci size_t size; 953d4afb5ceSopenharmony_ci void **v; 954d4afb5ceSopenharmony_ci char *p; 955d4afb5ceSopenharmony_ci int n; 956d4afb5ceSopenharmony_ci 957d4afb5ceSopenharmony_ci lws_service_assert_loop_thread(context, tsi); 958d4afb5ceSopenharmony_ci 959d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SECURE_STREAMS_CPP) 960d4afb5ceSopenharmony_ci pol = ssi->policy; 961d4afb5ceSopenharmony_ci if (!pol) { 962d4afb5ceSopenharmony_ci#endif 963d4afb5ceSopenharmony_ci 964d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_FAULT_INJECTION) 965d4afb5ceSopenharmony_ci lws_fi_ctx_t temp_fic; 966d4afb5ceSopenharmony_ci 967d4afb5ceSopenharmony_ci /* 968d4afb5ceSopenharmony_ci * We have to do a temp inherit from context to find out 969d4afb5ceSopenharmony_ci * early if we are supposed to inject a fault concealing 970d4afb5ceSopenharmony_ci * the policy 971d4afb5ceSopenharmony_ci */ 972d4afb5ceSopenharmony_ci 973d4afb5ceSopenharmony_ci memset(&temp_fic, 0, sizeof(temp_fic)); 974d4afb5ceSopenharmony_ci lws_xos_init(&temp_fic.xos, lws_xos(&context->fic.xos)); 975d4afb5ceSopenharmony_ci lws_fi_inherit_copy(&temp_fic, &context->fic, "ss", ssi->streamtype); 976d4afb5ceSopenharmony_ci 977d4afb5ceSopenharmony_ci if (lws_fi(&temp_fic, "ss_no_streamtype_policy")) 978d4afb5ceSopenharmony_ci pol = NULL; 979d4afb5ceSopenharmony_ci else 980d4afb5ceSopenharmony_ci pol = lws_ss_policy_lookup(context, ssi->streamtype); 981d4afb5ceSopenharmony_ci 982d4afb5ceSopenharmony_ci lws_fi_destroy(&temp_fic); 983d4afb5ceSopenharmony_ci#else 984d4afb5ceSopenharmony_ci pol = lws_ss_policy_lookup(context, ssi->streamtype); 985d4afb5ceSopenharmony_ci#endif 986d4afb5ceSopenharmony_ci if (!pol) { 987d4afb5ceSopenharmony_ci lwsl_cx_info(context, "unknown stream type %s", 988d4afb5ceSopenharmony_ci ssi->streamtype); 989d4afb5ceSopenharmony_ci return 1; 990d4afb5ceSopenharmony_ci } 991d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SECURE_STREAMS_CPP) 992d4afb5ceSopenharmony_ci } 993d4afb5ceSopenharmony_ci#endif 994d4afb5ceSopenharmony_ci 995d4afb5ceSopenharmony_ci#if 0 996d4afb5ceSopenharmony_ci if (ssi->flags & LWSSSINFLAGS_REGISTER_SINK) { 997d4afb5ceSopenharmony_ci /* 998d4afb5ceSopenharmony_ci * This can register a secure streams sink as well as normal 999d4afb5ceSopenharmony_ci * secure streams connections. If that's what's happening, 1000d4afb5ceSopenharmony_ci * confirm the policy agrees that this streamtype should be 1001d4afb5ceSopenharmony_ci * directed to a sink. 1002d4afb5ceSopenharmony_ci */ 1003d4afb5ceSopenharmony_ci if (!(pol->flags & LWSSSPOLF_LOCAL_SINK)) { 1004d4afb5ceSopenharmony_ci /* 1005d4afb5ceSopenharmony_ci * Caller wanted to create a sink for this streamtype, 1006d4afb5ceSopenharmony_ci * but the policy does not agree the streamtype should 1007d4afb5ceSopenharmony_ci * be routed to a local sink. 1008d4afb5ceSopenharmony_ci */ 1009d4afb5ceSopenharmony_ci lwsl_err("%s: %s policy does not allow local sink\n", 1010d4afb5ceSopenharmony_ci __func__, ssi->streamtype); 1011d4afb5ceSopenharmony_ci 1012d4afb5ceSopenharmony_ci return 1; 1013d4afb5ceSopenharmony_ci } 1014d4afb5ceSopenharmony_ci } else { 1015d4afb5ceSopenharmony_ci 1016d4afb5ceSopenharmony_ci if (!(pol->flags & LWSSSPOLF_LOCAL_SINK)) { 1017d4afb5ceSopenharmony_ci 1018d4afb5ceSopenharmony_ci } 1019d4afb5ceSopenharmony_ci// lws_dll2_foreach_safe(&pt->ss_owner, NULL, lws_ss_destroy_dll); 1020d4afb5ceSopenharmony_ci } 1021d4afb5ceSopenharmony_ci#endif 1022d4afb5ceSopenharmony_ci 1023d4afb5ceSopenharmony_ci /* 1024d4afb5ceSopenharmony_ci * We overallocate and point to things in the overallocation... 1025d4afb5ceSopenharmony_ci * 1026d4afb5ceSopenharmony_ci * 1) the user_alloc from the stream info 1027d4afb5ceSopenharmony_ci * 2) network auth plugin instantiation data 1028d4afb5ceSopenharmony_ci * 3) stream auth plugin instantiation data 1029d4afb5ceSopenharmony_ci * 4) as many metadata pointer structs as the policy tells 1030d4afb5ceSopenharmony_ci * 5) the streamtype name (length is not aligned) 1031d4afb5ceSopenharmony_ci * 1032d4afb5ceSopenharmony_ci * ... when we come to destroy it, just one free to do. 1033d4afb5ceSopenharmony_ci */ 1034d4afb5ceSopenharmony_ci 1035d4afb5ceSopenharmony_ci size = sizeof(*h) + ssi->user_alloc + 1036d4afb5ceSopenharmony_ci (ssi->streamtype ? strlen(ssi->streamtype): 0) + 1; 1037d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SSPLUGINS) 1038d4afb5ceSopenharmony_ci if (pol->plugins[0]) 1039d4afb5ceSopenharmony_ci size += pol->plugins[0]->alloc; 1040d4afb5ceSopenharmony_ci if (pol->plugins[1]) 1041d4afb5ceSopenharmony_ci size += pol->plugins[1]->alloc; 1042d4afb5ceSopenharmony_ci#endif 1043d4afb5ceSopenharmony_ci size += pol->metadata_count * sizeof(lws_ss_metadata_t); 1044d4afb5ceSopenharmony_ci 1045d4afb5ceSopenharmony_ci h = lws_zalloc(size, __func__); 1046d4afb5ceSopenharmony_ci if (!h) 1047d4afb5ceSopenharmony_ci return 2; 1048d4afb5ceSopenharmony_ci 1049d4afb5ceSopenharmony_ci h->lc.log_cx = context->log_cx; 1050d4afb5ceSopenharmony_ci 1051d4afb5ceSopenharmony_ci if (ssi->sss_protocol_version) 1052d4afb5ceSopenharmony_ci __lws_lc_tag(context, &context->lcg[LWSLCG_WSI_SS_CLIENT], 1053d4afb5ceSopenharmony_ci &h->lc, "%s|v%u|%u", 1054d4afb5ceSopenharmony_ci ssi->streamtype ? ssi->streamtype : "nostreamtype", 1055d4afb5ceSopenharmony_ci (unsigned int)ssi->sss_protocol_version, 1056d4afb5ceSopenharmony_ci (unsigned int)ssi->client_pid); 1057d4afb5ceSopenharmony_ci else 1058d4afb5ceSopenharmony_ci __lws_lc_tag(context, &context->lcg[LWSLCG_WSI_SS_CLIENT], 1059d4afb5ceSopenharmony_ci &h->lc, "%s", 1060d4afb5ceSopenharmony_ci ssi->streamtype ? ssi->streamtype : "nostreamtype"); 1061d4afb5ceSopenharmony_ci 1062d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_FAULT_INJECTION) 1063d4afb5ceSopenharmony_ci h->fic.name = "ss"; 1064d4afb5ceSopenharmony_ci lws_xos_init(&h->fic.xos, lws_xos(&context->fic.xos)); 1065d4afb5ceSopenharmony_ci if (ssi->fic.fi_owner.count) 1066d4afb5ceSopenharmony_ci lws_fi_import(&h->fic, &ssi->fic); 1067d4afb5ceSopenharmony_ci 1068d4afb5ceSopenharmony_ci lws_fi_inherit_copy(&h->fic, &context->fic, "ss", ssi->streamtype); 1069d4afb5ceSopenharmony_ci#endif 1070d4afb5ceSopenharmony_ci 1071d4afb5ceSopenharmony_ci h->info = *ssi; 1072d4afb5ceSopenharmony_ci h->policy = pol; 1073d4afb5ceSopenharmony_ci h->context = context; 1074d4afb5ceSopenharmony_ci h->tsi = (uint8_t)tsi; 1075d4afb5ceSopenharmony_ci h->seq = seq_owner; 1076d4afb5ceSopenharmony_ci 1077d4afb5ceSopenharmony_ci if (h->info.flags & LWSSSINFLAGS_PROXIED) 1078d4afb5ceSopenharmony_ci h->proxy_onward = 1; 1079d4afb5ceSopenharmony_ci 1080d4afb5ceSopenharmony_ci /* start of overallocated area */ 1081d4afb5ceSopenharmony_ci p = (char *)(h + 1); 1082d4afb5ceSopenharmony_ci 1083d4afb5ceSopenharmony_ci /* set the handle pointer in the user data struct */ 1084d4afb5ceSopenharmony_ci v = (void **)(p + ssi->handle_offset); 1085d4afb5ceSopenharmony_ci *v = h; 1086d4afb5ceSopenharmony_ci 1087d4afb5ceSopenharmony_ci /* set the opaque user data in the user data struct */ 1088d4afb5ceSopenharmony_ci v = (void **)(p + ssi->opaque_user_data_offset); 1089d4afb5ceSopenharmony_ci *v = opaque_user_data; 1090d4afb5ceSopenharmony_ci 1091d4afb5ceSopenharmony_ci p += ssi->user_alloc; 1092d4afb5ceSopenharmony_ci 1093d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SSPLUGINS) 1094d4afb5ceSopenharmony_ci if (pol->plugins[0]) { 1095d4afb5ceSopenharmony_ci h->nauthi = p; 1096d4afb5ceSopenharmony_ci p += pol->plugins[0]->alloc; 1097d4afb5ceSopenharmony_ci } 1098d4afb5ceSopenharmony_ci if (pol->plugins[1]) { 1099d4afb5ceSopenharmony_ci h->sauthi = p; 1100d4afb5ceSopenharmony_ci p += pol->plugins[1]->alloc; 1101d4afb5ceSopenharmony_ci } 1102d4afb5ceSopenharmony_ci#endif 1103d4afb5ceSopenharmony_ci 1104d4afb5ceSopenharmony_ci if (pol->metadata_count) { 1105d4afb5ceSopenharmony_ci h->metadata = (lws_ss_metadata_t *)p; 1106d4afb5ceSopenharmony_ci p += pol->metadata_count * sizeof(lws_ss_metadata_t); 1107d4afb5ceSopenharmony_ci 1108d4afb5ceSopenharmony_ci lwsl_cx_info(context, "%s metadata count %d", 1109d4afb5ceSopenharmony_ci pol->streamtype, pol->metadata_count); 1110d4afb5ceSopenharmony_ci } 1111d4afb5ceSopenharmony_ci 1112d4afb5ceSopenharmony_ci smd = pol->metadata; 1113d4afb5ceSopenharmony_ci for (n = 0; n < pol->metadata_count; n++) { 1114d4afb5ceSopenharmony_ci h->metadata[n].name = smd->name; 1115d4afb5ceSopenharmony_ci if (n + 1 == pol->metadata_count) 1116d4afb5ceSopenharmony_ci h->metadata[n].next = NULL; 1117d4afb5ceSopenharmony_ci else 1118d4afb5ceSopenharmony_ci h->metadata[n].next = &h->metadata[n + 1]; 1119d4afb5ceSopenharmony_ci smd = smd->next; 1120d4afb5ceSopenharmony_ci } 1121d4afb5ceSopenharmony_ci 1122d4afb5ceSopenharmony_ci if (ssi->streamtype) 1123d4afb5ceSopenharmony_ci memcpy(p, ssi->streamtype, strlen(ssi->streamtype) + 1); 1124d4afb5ceSopenharmony_ci /* don't mark accepted ss as being the server */ 1125d4afb5ceSopenharmony_ci if (ssi->flags & LWSSSINFLAGS_SERVER) 1126d4afb5ceSopenharmony_ci h->info.flags &= (uint8_t)~LWSSSINFLAGS_SERVER; 1127d4afb5ceSopenharmony_ci h->info.streamtype = p; 1128d4afb5ceSopenharmony_ci 1129d4afb5ceSopenharmony_ci lws_pt_lock(pt, __func__); 1130d4afb5ceSopenharmony_ci lws_dll2_add_head(&h->list, &pt->ss_owner); 1131d4afb5ceSopenharmony_ci lws_pt_unlock(pt); 1132d4afb5ceSopenharmony_ci 1133d4afb5ceSopenharmony_ci if (ppss) 1134d4afb5ceSopenharmony_ci *ppss = h; 1135d4afb5ceSopenharmony_ci 1136d4afb5ceSopenharmony_ci if (ppayload_fmt) 1137d4afb5ceSopenharmony_ci *ppayload_fmt = pol->payload_fmt; 1138d4afb5ceSopenharmony_ci 1139d4afb5ceSopenharmony_ci if (ssi->flags & LWSSSINFLAGS_SERVER) 1140d4afb5ceSopenharmony_ci /* 1141d4afb5ceSopenharmony_ci * return early for accepted connection flow 1142d4afb5ceSopenharmony_ci */ 1143d4afb5ceSopenharmony_ci return 0; 1144d4afb5ceSopenharmony_ci 1145d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_SMD) 1146d4afb5ceSopenharmony_ci /* 1147d4afb5ceSopenharmony_ci * For a local Secure Streams connection 1148d4afb5ceSopenharmony_ci */ 1149d4afb5ceSopenharmony_ci if (!(ssi->flags & LWSSSINFLAGS_PROXIED) && 1150d4afb5ceSopenharmony_ci pol == &pol_smd) { 1151d4afb5ceSopenharmony_ci 1152d4afb5ceSopenharmony_ci /* 1153d4afb5ceSopenharmony_ci * So he has asked to be wired up to SMD over a SS link. 1154d4afb5ceSopenharmony_ci * Register him as an smd participant in his own right. 1155d4afb5ceSopenharmony_ci * 1156d4afb5ceSopenharmony_ci * Just for this case, ssi->manual_initial_tx_credit is used 1157d4afb5ceSopenharmony_ci * to set the rx class mask (this is part of the SS serialization 1158d4afb5ceSopenharmony_ci * format as well) 1159d4afb5ceSopenharmony_ci */ 1160d4afb5ceSopenharmony_ci h->u.smd.smd_peer = lws_smd_register(context, h, 0, 1161d4afb5ceSopenharmony_ci (lws_smd_class_t)ssi->manual_initial_tx_credit, 1162d4afb5ceSopenharmony_ci lws_smd_ss_cb); 1163d4afb5ceSopenharmony_ci if (!h->u.smd.smd_peer || lws_fi(&h->fic, "ss_create_smd")) 1164d4afb5ceSopenharmony_ci goto fail_creation; 1165d4afb5ceSopenharmony_ci lwsl_cx_info(context, "registered SS SMD"); 1166d4afb5ceSopenharmony_ci } 1167d4afb5ceSopenharmony_ci#endif 1168d4afb5ceSopenharmony_ci 1169d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER) 1170d4afb5ceSopenharmony_ci if (h->policy->flags & LWSSSPOLF_SERVER) { 1171d4afb5ceSopenharmony_ci const struct lws_protocols *pprot[3], **ppp = &pprot[0]; 1172d4afb5ceSopenharmony_ci struct lws_context_creation_info i; 1173d4afb5ceSopenharmony_ci struct lws_vhost *vho = NULL; 1174d4afb5ceSopenharmony_ci 1175d4afb5ceSopenharmony_ci lwsl_cx_info(context, "creating server"); 1176d4afb5ceSopenharmony_ci 1177d4afb5ceSopenharmony_ci if (h->policy->endpoint && 1178d4afb5ceSopenharmony_ci h->policy->endpoint[0] == '!') { 1179d4afb5ceSopenharmony_ci /* 1180d4afb5ceSopenharmony_ci * There's already a vhost existing that we want to 1181d4afb5ceSopenharmony_ci * bind to, we don't have to specify and create one. 1182d4afb5ceSopenharmony_ci * 1183d4afb5ceSopenharmony_ci * The vhost must enable any protocols that we want. 1184d4afb5ceSopenharmony_ci */ 1185d4afb5ceSopenharmony_ci 1186d4afb5ceSopenharmony_ci vho = lws_get_vhost_by_name(context, 1187d4afb5ceSopenharmony_ci &h->policy->endpoint[1]); 1188d4afb5ceSopenharmony_ci if (!vho || lws_fi(&h->fic, "ss_create_vhost")) { 1189d4afb5ceSopenharmony_ci lwsl_err("%s: no vhost %s\n", __func__, 1190d4afb5ceSopenharmony_ci &h->policy->endpoint[1]); 1191d4afb5ceSopenharmony_ci goto fail_creation; 1192d4afb5ceSopenharmony_ci } 1193d4afb5ceSopenharmony_ci 1194d4afb5ceSopenharmony_ci goto extant; 1195d4afb5ceSopenharmony_ci } 1196d4afb5ceSopenharmony_ci 1197d4afb5ceSopenharmony_ci /* 1198d4afb5ceSopenharmony_ci * This streamtype represents a server, we're being asked to 1199d4afb5ceSopenharmony_ci * instantiate a corresponding vhost for it 1200d4afb5ceSopenharmony_ci */ 1201d4afb5ceSopenharmony_ci 1202d4afb5ceSopenharmony_ci memset(&i, 0, sizeof i); 1203d4afb5ceSopenharmony_ci 1204d4afb5ceSopenharmony_ci i.iface = h->policy->endpoint; 1205d4afb5ceSopenharmony_ci i.vhost_name = h->policy->streamtype; 1206d4afb5ceSopenharmony_ci i.port = h->policy->port; 1207d4afb5ceSopenharmony_ci 1208d4afb5ceSopenharmony_ci if (i.iface && i.iface[0] == '+') { 1209d4afb5ceSopenharmony_ci i.iface++; 1210d4afb5ceSopenharmony_ci i.options |= LWS_SERVER_OPTION_UNIX_SOCK; 1211d4afb5ceSopenharmony_ci } 1212d4afb5ceSopenharmony_ci 1213d4afb5ceSopenharmony_ci if (!ss_pcols[h->policy->protocol] || 1214d4afb5ceSopenharmony_ci lws_fi(&h->fic, "ss_create_pcol")) { 1215d4afb5ceSopenharmony_ci lwsl_err("%s: unsupp protocol", __func__); 1216d4afb5ceSopenharmony_ci goto fail_creation; 1217d4afb5ceSopenharmony_ci } 1218d4afb5ceSopenharmony_ci 1219d4afb5ceSopenharmony_ci *ppp++ = ss_pcols[h->policy->protocol]->protocol; 1220d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_WS) 1221d4afb5ceSopenharmony_ci if (h->policy->u.http.u.ws.subprotocol) 1222d4afb5ceSopenharmony_ci /* 1223d4afb5ceSopenharmony_ci * He names a ws subprotocol, ie, we want to support 1224d4afb5ceSopenharmony_ci * ss-ws protocol in this vhost 1225d4afb5ceSopenharmony_ci */ 1226d4afb5ceSopenharmony_ci *ppp++ = &protocol_secstream_ws; 1227d4afb5ceSopenharmony_ci#endif 1228d4afb5ceSopenharmony_ci *ppp = NULL; 1229d4afb5ceSopenharmony_ci i.pprotocols = pprot; 1230d4afb5ceSopenharmony_ci 1231d4afb5ceSopenharmony_ci#if defined(LWS_WITH_TLS) 1232d4afb5ceSopenharmony_ci if (h->policy->flags & LWSSSPOLF_TLS) { 1233d4afb5ceSopenharmony_ci i.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; 1234d4afb5ceSopenharmony_ci i.server_ssl_cert_mem = 1235d4afb5ceSopenharmony_ci h->policy->trust.server.cert->ca_der; 1236d4afb5ceSopenharmony_ci i.server_ssl_cert_mem_len = (unsigned int) 1237d4afb5ceSopenharmony_ci h->policy->trust.server.cert->ca_der_len; 1238d4afb5ceSopenharmony_ci i.server_ssl_private_key_mem = 1239d4afb5ceSopenharmony_ci h->policy->trust.server.key->ca_der; 1240d4afb5ceSopenharmony_ci i.server_ssl_private_key_mem_len = (unsigned int) 1241d4afb5ceSopenharmony_ci h->policy->trust.server.key->ca_der_len; 1242d4afb5ceSopenharmony_ci } 1243d4afb5ceSopenharmony_ci#endif 1244d4afb5ceSopenharmony_ci 1245d4afb5ceSopenharmony_ci if (!lws_fi(&h->fic, "ss_srv_vh_fail")) 1246d4afb5ceSopenharmony_ci vho = lws_create_vhost(context, &i); 1247d4afb5ceSopenharmony_ci else 1248d4afb5ceSopenharmony_ci vho = NULL; 1249d4afb5ceSopenharmony_ci if (!vho) { 1250d4afb5ceSopenharmony_ci lwsl_cx_err(context, "failed to create vh"); 1251d4afb5ceSopenharmony_ci goto fail_creation; 1252d4afb5ceSopenharmony_ci } 1253d4afb5ceSopenharmony_ci 1254d4afb5ceSopenharmony_ciextant: 1255d4afb5ceSopenharmony_ci 1256d4afb5ceSopenharmony_ci /* 1257d4afb5ceSopenharmony_ci * Mark this vhost as having to apply ss server semantics to 1258d4afb5ceSopenharmony_ci * any incoming accepted connection 1259d4afb5ceSopenharmony_ci */ 1260d4afb5ceSopenharmony_ci vho->ss_handle = h; 1261d4afb5ceSopenharmony_ci 1262d4afb5ceSopenharmony_ci r = lws_ss_event_helper(h, LWSSSCS_CREATING); 1263d4afb5ceSopenharmony_ci lwsl_cx_info(context, "CREATING returned status %d", (int)r); 1264d4afb5ceSopenharmony_ci if (r == LWSSSSRET_DESTROY_ME || 1265d4afb5ceSopenharmony_ci lws_fi(&h->fic, "ss_create_destroy_me")) 1266d4afb5ceSopenharmony_ci goto fail_creation; 1267d4afb5ceSopenharmony_ci 1268d4afb5ceSopenharmony_ci lwsl_cx_notice(context, "created server %s", 1269d4afb5ceSopenharmony_ci h->policy->streamtype); 1270d4afb5ceSopenharmony_ci 1271d4afb5ceSopenharmony_ci return 0; 1272d4afb5ceSopenharmony_ci } 1273d4afb5ceSopenharmony_ci#endif 1274d4afb5ceSopenharmony_ci 1275d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) 1276d4afb5ceSopenharmony_ci 1277d4afb5ceSopenharmony_ci /* 1278d4afb5ceSopenharmony_ci * For static policy case, dynamically ref / instantiate the related 1279d4afb5ceSopenharmony_ci * trust store and vhost. We do it by logical ss rather than connection 1280d4afb5ceSopenharmony_ci * because we don't want to expose the latency of creating the x.509 1281d4afb5ceSopenharmony_ci * trust store at the first connection. 1282d4afb5ceSopenharmony_ci * 1283d4afb5ceSopenharmony_ci * But it might be given the tls linkup takes time anyway, it can move 1284d4afb5ceSopenharmony_ci * to the ss connect code instead. 1285d4afb5ceSopenharmony_ci */ 1286d4afb5ceSopenharmony_ci 1287d4afb5ceSopenharmony_ci if (!lws_ss_policy_ref_trust_store(context, h->policy, 1 /* do the ref */) || 1288d4afb5ceSopenharmony_ci lws_fi(&h->fic, "ss_create_no_ts")) { 1289d4afb5ceSopenharmony_ci lwsl_err("%s: unable to get vhost / trust store\n", __func__); 1290d4afb5ceSopenharmony_ci goto fail_creation; 1291d4afb5ceSopenharmony_ci } 1292d4afb5ceSopenharmony_ci#else 1293d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SECURE_STREAMS_CPP) 1294d4afb5ceSopenharmony_ci if (!ssi->streamtype && 1295d4afb5ceSopenharmony_ci !lws_ss_policy_ref_trust_store(context, h->policy, 1 /* do the ref */)) { 1296d4afb5ceSopenharmony_ci lwsl_err("%s: unable to get vhost / trust store\n", __func__); 1297d4afb5ceSopenharmony_ci goto fail_creation; 1298d4afb5ceSopenharmony_ci } 1299d4afb5ceSopenharmony_ci#endif 1300d4afb5ceSopenharmony_ci#endif 1301d4afb5ceSopenharmony_ci 1302d4afb5ceSopenharmony_ci r = lws_ss_event_helper(h, LWSSSCS_CREATING); 1303d4afb5ceSopenharmony_ci lwsl_ss_info(h, "CREATING returned status %d", (int)r); 1304d4afb5ceSopenharmony_ci if (r == LWSSSSRET_DESTROY_ME || 1305d4afb5ceSopenharmony_ci lws_fi(&h->fic, "ss_create_destroy_me")) 1306d4afb5ceSopenharmony_ci goto fail_creation; 1307d4afb5ceSopenharmony_ci 1308d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_SMD) 1309d4afb5ceSopenharmony_ci if (!(ssi->flags & LWSSSINFLAGS_PROXIED) && 1310d4afb5ceSopenharmony_ci pol == &pol_smd) { 1311d4afb5ceSopenharmony_ci r = lws_ss_event_helper(h, LWSSSCS_CONNECTING); 1312d4afb5ceSopenharmony_ci if (r || lws_fi(&h->fic, "ss_create_smd_1")) 1313d4afb5ceSopenharmony_ci goto fail_creation; 1314d4afb5ceSopenharmony_ci r = lws_ss_event_helper(h, LWSSSCS_CONNECTED); 1315d4afb5ceSopenharmony_ci if (r || lws_fi(&h->fic, "ss_create_smd_2")) 1316d4afb5ceSopenharmony_ci goto fail_creation; 1317d4afb5ceSopenharmony_ci } 1318d4afb5ceSopenharmony_ci#endif 1319d4afb5ceSopenharmony_ci 1320d4afb5ceSopenharmony_ci if (!(ssi->flags & LWSSSINFLAGS_REGISTER_SINK) && 1321d4afb5ceSopenharmony_ci ((h->policy->flags & LWSSSPOLF_NAILED_UP) 1322d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_SMD) 1323d4afb5ceSopenharmony_ci || ((h->policy == &pol_smd) //&& 1324d4afb5ceSopenharmony_ci //(ssi->flags & LWSSSINFLAGS_PROXIED)) 1325d4afb5ceSopenharmony_ci ) 1326d4afb5ceSopenharmony_ci#endif 1327d4afb5ceSopenharmony_ci )) { 1328d4afb5ceSopenharmony_ci r = _lws_ss_client_connect(h, 0, 0); 1329d4afb5ceSopenharmony_ci if (lws_fi(&h->fic, "ss_create_conn")) 1330d4afb5ceSopenharmony_ci r = LWSSSSRET_DESTROY_ME; 1331d4afb5ceSopenharmony_ci switch (r) { 1332d4afb5ceSopenharmony_ci case LWSSSSRET_OK: 1333d4afb5ceSopenharmony_ci break; 1334d4afb5ceSopenharmony_ci case LWSSSSRET_TX_DONT_SEND: 1335d4afb5ceSopenharmony_ci case LWSSSSRET_DISCONNECT_ME: 1336d4afb5ceSopenharmony_ci if (lws_ss_backoff(h) == LWSSSSRET_DESTROY_ME) 1337d4afb5ceSopenharmony_ci goto fail_creation; 1338d4afb5ceSopenharmony_ci break; 1339d4afb5ceSopenharmony_ci case LWSSSSRET_DESTROY_ME: 1340d4afb5ceSopenharmony_ci goto fail_creation; 1341d4afb5ceSopenharmony_ci } 1342d4afb5ceSopenharmony_ci } 1343d4afb5ceSopenharmony_ci 1344d4afb5ceSopenharmony_ci return 0; 1345d4afb5ceSopenharmony_ci 1346d4afb5ceSopenharmony_cifail_creation: 1347d4afb5ceSopenharmony_ci 1348d4afb5ceSopenharmony_ci if (ppss) 1349d4afb5ceSopenharmony_ci *ppss = NULL; 1350d4afb5ceSopenharmony_ci 1351d4afb5ceSopenharmony_ci lws_ss_destroy(&h); 1352d4afb5ceSopenharmony_ci 1353d4afb5ceSopenharmony_ci return 1; 1354d4afb5ceSopenharmony_ci} 1355d4afb5ceSopenharmony_ci 1356d4afb5ceSopenharmony_civoid * 1357d4afb5ceSopenharmony_cilws_ss_to_user_object(struct lws_ss_handle *h) 1358d4afb5ceSopenharmony_ci{ 1359d4afb5ceSopenharmony_ci return (void *)(h + 1); 1360d4afb5ceSopenharmony_ci} 1361d4afb5ceSopenharmony_ci 1362d4afb5ceSopenharmony_civoid 1363d4afb5ceSopenharmony_cilws_ss_destroy(lws_ss_handle_t **ppss) 1364d4afb5ceSopenharmony_ci{ 1365d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt; 1366d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER) 1367d4afb5ceSopenharmony_ci struct lws_vhost *v = NULL; 1368d4afb5ceSopenharmony_ci#endif 1369d4afb5ceSopenharmony_ci lws_ss_handle_t *h = *ppss; 1370d4afb5ceSopenharmony_ci lws_ss_metadata_t *pmd; 1371d4afb5ceSopenharmony_ci 1372d4afb5ceSopenharmony_ci if (!h) 1373d4afb5ceSopenharmony_ci return; 1374d4afb5ceSopenharmony_ci 1375d4afb5ceSopenharmony_ci lws_service_assert_loop_thread(h->context, h->tsi); 1376d4afb5ceSopenharmony_ci 1377d4afb5ceSopenharmony_ci if (h == h->h_in_svc) { 1378d4afb5ceSopenharmony_ci lwsl_err("%s: illegal destroy, return LWSSSSRET_DESTROY_ME instead\n", 1379d4afb5ceSopenharmony_ci __func__); 1380d4afb5ceSopenharmony_ci assert(0); 1381d4afb5ceSopenharmony_ci return; 1382d4afb5ceSopenharmony_ci } 1383d4afb5ceSopenharmony_ci 1384d4afb5ceSopenharmony_ci if (h->destroying) { 1385d4afb5ceSopenharmony_ci lwsl_info("%s: reentrant destroy\n", __func__); 1386d4afb5ceSopenharmony_ci return; 1387d4afb5ceSopenharmony_ci } 1388d4afb5ceSopenharmony_ci h->destroying = 1; 1389d4afb5ceSopenharmony_ci 1390d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CONMON) 1391d4afb5ceSopenharmony_ci if (h->conmon_json) 1392d4afb5ceSopenharmony_ci lws_free_set_NULL(h->conmon_json); 1393d4afb5ceSopenharmony_ci#endif 1394d4afb5ceSopenharmony_ci 1395d4afb5ceSopenharmony_ci if (h->wsi) { 1396d4afb5ceSopenharmony_ci /* 1397d4afb5ceSopenharmony_ci * Don't let the wsi point to us any more, 1398d4afb5ceSopenharmony_ci * we (the ss object bound to the wsi) are going away now 1399d4afb5ceSopenharmony_ci */ 1400d4afb5ceSopenharmony_ci lws_set_opaque_user_data(h->wsi, NULL); 1401d4afb5ceSopenharmony_ci lws_set_timeout(h->wsi, 1, LWS_TO_KILL_SYNC); 1402d4afb5ceSopenharmony_ci } 1403d4afb5ceSopenharmony_ci 1404d4afb5ceSopenharmony_ci /* 1405d4afb5ceSopenharmony_ci * if we bound an smd registration to the SS, unregister it 1406d4afb5ceSopenharmony_ci */ 1407d4afb5ceSopenharmony_ci 1408d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_SMD) 1409d4afb5ceSopenharmony_ci if (h->policy == &pol_smd) { 1410d4afb5ceSopenharmony_ci lws_sul_cancel(&h->u.smd.sul_write); 1411d4afb5ceSopenharmony_ci 1412d4afb5ceSopenharmony_ci if (h->u.smd.smd_peer) { 1413d4afb5ceSopenharmony_ci lws_smd_unregister(h->u.smd.smd_peer); 1414d4afb5ceSopenharmony_ci h->u.smd.smd_peer = NULL; 1415d4afb5ceSopenharmony_ci } 1416d4afb5ceSopenharmony_ci } 1417d4afb5ceSopenharmony_ci#endif 1418d4afb5ceSopenharmony_ci 1419d4afb5ceSopenharmony_ci pt = &h->context->pt[h->tsi]; 1420d4afb5ceSopenharmony_ci 1421d4afb5ceSopenharmony_ci lws_pt_lock(pt, __func__); 1422d4afb5ceSopenharmony_ci *ppss = NULL; 1423d4afb5ceSopenharmony_ci lws_dll2_remove(&h->list); 1424d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER) 1425d4afb5ceSopenharmony_ci lws_dll2_remove(&h->cli_list); 1426d4afb5ceSopenharmony_ci#endif 1427d4afb5ceSopenharmony_ci lws_dll2_remove(&h->to_list); 1428d4afb5ceSopenharmony_ci lws_sul_cancel(&h->sul_timeout); 1429d4afb5ceSopenharmony_ci 1430d4afb5ceSopenharmony_ci /* 1431d4afb5ceSopenharmony_ci * for lss, DESTROYING deletes the C++ lss object, making the 1432d4afb5ceSopenharmony_ci * self-defined h->policy radioactive 1433d4afb5ceSopenharmony_ci */ 1434d4afb5ceSopenharmony_ci 1435d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER) 1436d4afb5ceSopenharmony_ci if (h->policy && (h->policy->flags & LWSSSPOLF_SERVER)) 1437d4afb5ceSopenharmony_ci v = lws_get_vhost_by_name(h->context, h->policy->streamtype); 1438d4afb5ceSopenharmony_ci#endif 1439d4afb5ceSopenharmony_ci 1440d4afb5ceSopenharmony_ci /* 1441d4afb5ceSopenharmony_ci * Since we also come here to unpick create, it's possible we failed 1442d4afb5ceSopenharmony_ci * the creation before issuing any states, even CREATING. We should 1443d4afb5ceSopenharmony_ci * only issue cleanup states on destroy if we previously got as far as 1444d4afb5ceSopenharmony_ci * issuing CREATING. 1445d4afb5ceSopenharmony_ci */ 1446d4afb5ceSopenharmony_ci 1447d4afb5ceSopenharmony_ci if (h->prev_ss_state) { 1448d4afb5ceSopenharmony_ci if (h->ss_dangling_connected) 1449d4afb5ceSopenharmony_ci (void)lws_ss_event_helper(h, LWSSSCS_DISCONNECTED); 1450d4afb5ceSopenharmony_ci 1451d4afb5ceSopenharmony_ci (void)lws_ss_event_helper(h, LWSSSCS_DESTROYING); 1452d4afb5ceSopenharmony_ci } 1453d4afb5ceSopenharmony_ci 1454d4afb5ceSopenharmony_ci lws_pt_unlock(pt); 1455d4afb5ceSopenharmony_ci 1456d4afb5ceSopenharmony_ci /* in proxy case, metadata value on heap may need cleaning up */ 1457d4afb5ceSopenharmony_ci 1458d4afb5ceSopenharmony_ci pmd = h->metadata; 1459d4afb5ceSopenharmony_ci while (pmd) { 1460d4afb5ceSopenharmony_ci lwsl_info("%s: pmd %p\n", __func__, pmd); 1461d4afb5ceSopenharmony_ci if (pmd->value_on_lws_heap) 1462d4afb5ceSopenharmony_ci lws_free_set_NULL(pmd->value__may_own_heap); 1463d4afb5ceSopenharmony_ci 1464d4afb5ceSopenharmony_ci pmd = pmd->next; 1465d4afb5ceSopenharmony_ci } 1466d4afb5ceSopenharmony_ci 1467d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SS_DIRECT_PROTOCOL_STR) 1468d4afb5ceSopenharmony_ci { 1469d4afb5ceSopenharmony_ci 1470d4afb5ceSopenharmony_ci lws_ss_metadata_t *imd; 1471d4afb5ceSopenharmony_ci 1472d4afb5ceSopenharmony_ci pmd = h->instant_metadata; 1473d4afb5ceSopenharmony_ci 1474d4afb5ceSopenharmony_ci while (pmd) { 1475d4afb5ceSopenharmony_ci imd = pmd; 1476d4afb5ceSopenharmony_ci pmd = pmd->next; 1477d4afb5ceSopenharmony_ci 1478d4afb5ceSopenharmony_ci lwsl_info("%s: instant md %p\n", __func__, imd); 1479d4afb5ceSopenharmony_ci lws_free(imd); 1480d4afb5ceSopenharmony_ci } 1481d4afb5ceSopenharmony_ci h->instant_metadata = NULL; 1482d4afb5ceSopenharmony_ci 1483d4afb5ceSopenharmony_ci if (h->imd_ac) 1484d4afb5ceSopenharmony_ci lwsac_free(&h->imd_ac); 1485d4afb5ceSopenharmony_ci } 1486d4afb5ceSopenharmony_ci#endif 1487d4afb5ceSopenharmony_ci 1488d4afb5ceSopenharmony_ci lws_sul_cancel(&h->sul); 1489d4afb5ceSopenharmony_ci 1490d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) 1491d4afb5ceSopenharmony_ci 1492d4afb5ceSopenharmony_ci /* 1493d4afb5ceSopenharmony_ci * For static policy case, dynamically ref / instantiate the related 1494d4afb5ceSopenharmony_ci * trust store and vhost. We do it by logical ss rather than connection 1495d4afb5ceSopenharmony_ci * because we don't want to expose the latency of creating the x.509 1496d4afb5ceSopenharmony_ci * trust store at the first connection. 1497d4afb5ceSopenharmony_ci * 1498d4afb5ceSopenharmony_ci * But it might be given the tls linkup takes time anyway, it can move 1499d4afb5ceSopenharmony_ci * to the ss connect code instead. 1500d4afb5ceSopenharmony_ci */ 1501d4afb5ceSopenharmony_ci 1502d4afb5ceSopenharmony_ci if (h->policy) 1503d4afb5ceSopenharmony_ci lws_ss_policy_unref_trust_store(h->context, h->policy); 1504d4afb5ceSopenharmony_ci#else 1505d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SECURE_STREAMS_CPP) 1506d4afb5ceSopenharmony_ci if (!h->info.streamtype || !*(h->info.streamtype)) 1507d4afb5ceSopenharmony_ci lws_ss_policy_unref_trust_store(h->context, h->policy); 1508d4afb5ceSopenharmony_ci#endif 1509d4afb5ceSopenharmony_ci#endif 1510d4afb5ceSopenharmony_ci 1511d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER) 1512d4afb5ceSopenharmony_ci if (v) 1513d4afb5ceSopenharmony_ci /* 1514d4afb5ceSopenharmony_ci * For server, the policy describes a vhost that implements the 1515d4afb5ceSopenharmony_ci * server, when we take down the ss, we take down the related 1516d4afb5ceSopenharmony_ci * vhost (if it got that far) 1517d4afb5ceSopenharmony_ci */ 1518d4afb5ceSopenharmony_ci lws_vhost_destroy(v); 1519d4afb5ceSopenharmony_ci#endif 1520d4afb5ceSopenharmony_ci 1521d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_FAULT_INJECTION) 1522d4afb5ceSopenharmony_ci lws_fi_destroy(&h->fic); 1523d4afb5ceSopenharmony_ci#endif 1524d4afb5ceSopenharmony_ci 1525d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_METRICS) 1526d4afb5ceSopenharmony_ci /* 1527d4afb5ceSopenharmony_ci * If any hanging caliper measurement, dump it, and free any tags 1528d4afb5ceSopenharmony_ci */ 1529d4afb5ceSopenharmony_ci lws_metrics_caliper_report_hist(h->cal_txn, (struct lws *)NULL); 1530d4afb5ceSopenharmony_ci#endif 1531d4afb5ceSopenharmony_ci 1532d4afb5ceSopenharmony_ci lws_sul_cancel(&h->sul_timeout); 1533d4afb5ceSopenharmony_ci 1534d4afb5ceSopenharmony_ci /* confirm no sul left scheduled in handle or user allocation object */ 1535d4afb5ceSopenharmony_ci lws_sul_debug_zombies(h->context, h, sizeof(*h) + h->info.user_alloc, 1536d4afb5ceSopenharmony_ci __func__); 1537d4afb5ceSopenharmony_ci 1538d4afb5ceSopenharmony_ci __lws_lc_untag(h->context, &h->lc); 1539d4afb5ceSopenharmony_ci 1540d4afb5ceSopenharmony_ci lws_explicit_bzero((void *)h, sizeof(*h) + h->info.user_alloc); 1541d4afb5ceSopenharmony_ci 1542d4afb5ceSopenharmony_ci lws_free_set_NULL(h); 1543d4afb5ceSopenharmony_ci} 1544d4afb5ceSopenharmony_ci 1545d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER) 1546d4afb5ceSopenharmony_civoid 1547d4afb5ceSopenharmony_cilws_ss_server_ack(struct lws_ss_handle *h, int nack) 1548d4afb5ceSopenharmony_ci{ 1549d4afb5ceSopenharmony_ci h->txn_resp = nack; 1550d4afb5ceSopenharmony_ci h->txn_resp_set = 1; 1551d4afb5ceSopenharmony_ci} 1552d4afb5ceSopenharmony_ci 1553d4afb5ceSopenharmony_civoid 1554d4afb5ceSopenharmony_cilws_ss_server_foreach_client(struct lws_ss_handle *h, lws_sssfec_cb cb, 1555d4afb5ceSopenharmony_ci void *arg) 1556d4afb5ceSopenharmony_ci{ 1557d4afb5ceSopenharmony_ci lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, h->src_list.head) { 1558d4afb5ceSopenharmony_ci struct lws_ss_handle *h = 1559d4afb5ceSopenharmony_ci lws_container_of(d, struct lws_ss_handle, cli_list); 1560d4afb5ceSopenharmony_ci 1561d4afb5ceSopenharmony_ci cb(h, arg); 1562d4afb5ceSopenharmony_ci 1563d4afb5ceSopenharmony_ci } lws_end_foreach_dll_safe(d, d1); 1564d4afb5ceSopenharmony_ci} 1565d4afb5ceSopenharmony_ci#endif 1566d4afb5ceSopenharmony_ci 1567d4afb5ceSopenharmony_cilws_ss_state_return_t 1568d4afb5ceSopenharmony_cilws_ss_request_tx(lws_ss_handle_t *h) 1569d4afb5ceSopenharmony_ci{ 1570d4afb5ceSopenharmony_ci lws_ss_state_return_t r; 1571d4afb5ceSopenharmony_ci 1572d4afb5ceSopenharmony_ci r = _lws_ss_request_tx(h); 1573d4afb5ceSopenharmony_ci 1574d4afb5ceSopenharmony_ci return r; 1575d4afb5ceSopenharmony_ci} 1576d4afb5ceSopenharmony_ci 1577d4afb5ceSopenharmony_cilws_ss_state_return_t 1578d4afb5ceSopenharmony_ci_lws_ss_request_tx(lws_ss_handle_t *h) 1579d4afb5ceSopenharmony_ci{ 1580d4afb5ceSopenharmony_ci lws_ss_state_return_t r; 1581d4afb5ceSopenharmony_ci 1582d4afb5ceSopenharmony_ci // lwsl_notice("%s: h %p, wsi %p\n", __func__, h, h->wsi); 1583d4afb5ceSopenharmony_ci 1584d4afb5ceSopenharmony_ci lws_service_assert_loop_thread(h->context, h->tsi); 1585d4afb5ceSopenharmony_ci 1586d4afb5ceSopenharmony_ci if (h->wsi) { 1587d4afb5ceSopenharmony_ci lws_callback_on_writable(h->wsi); 1588d4afb5ceSopenharmony_ci 1589d4afb5ceSopenharmony_ci return LWSSSSRET_OK; 1590d4afb5ceSopenharmony_ci } 1591d4afb5ceSopenharmony_ci 1592d4afb5ceSopenharmony_ci if (!h->policy) { 1593d4afb5ceSopenharmony_ci /* avoid crash */ 1594d4afb5ceSopenharmony_ci lwsl_err("%s: null policy\n", __func__); 1595d4afb5ceSopenharmony_ci return LWSSSSRET_OK; 1596d4afb5ceSopenharmony_ci } 1597d4afb5ceSopenharmony_ci 1598d4afb5ceSopenharmony_ci if (h->policy->flags & LWSSSPOLF_SERVER) 1599d4afb5ceSopenharmony_ci return LWSSSSRET_OK; 1600d4afb5ceSopenharmony_ci 1601d4afb5ceSopenharmony_ci /* 1602d4afb5ceSopenharmony_ci * there's currently no wsi / connection associated with the ss handle 1603d4afb5ceSopenharmony_ci */ 1604d4afb5ceSopenharmony_ci 1605d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_SMD) 1606d4afb5ceSopenharmony_ci if (h->policy == &pol_smd) { 1607d4afb5ceSopenharmony_ci /* 1608d4afb5ceSopenharmony_ci * He's an _lws_smd... and no wsi... since we're just going 1609d4afb5ceSopenharmony_ci * to queue it, we could call his tx() right here, but rather 1610d4afb5ceSopenharmony_ci * than surprise him let's set a sul to do it next time around 1611d4afb5ceSopenharmony_ci * the event loop 1612d4afb5ceSopenharmony_ci */ 1613d4afb5ceSopenharmony_ci 1614d4afb5ceSopenharmony_ci lws_sul_schedule(h->context, 0, &h->u.smd.sul_write, 1615d4afb5ceSopenharmony_ci lws_ss_smd_tx_cb, 1); 1616d4afb5ceSopenharmony_ci 1617d4afb5ceSopenharmony_ci return LWSSSSRET_OK; 1618d4afb5ceSopenharmony_ci } 1619d4afb5ceSopenharmony_ci#endif 1620d4afb5ceSopenharmony_ci 1621d4afb5ceSopenharmony_ci if (h->seqstate != SSSEQ_IDLE && 1622d4afb5ceSopenharmony_ci h->seqstate != SSSEQ_DO_RETRY) 1623d4afb5ceSopenharmony_ci return LWSSSSRET_OK; 1624d4afb5ceSopenharmony_ci 1625d4afb5ceSopenharmony_ci h->seqstate = SSSEQ_TRY_CONNECT; 1626d4afb5ceSopenharmony_ci if (h->prev_ss_state != LWSSSCS_POLL) { /* possible if we were created 1627d4afb5ceSopenharmony_ci * before we could action it */ 1628d4afb5ceSopenharmony_ci r = lws_ss_event_helper(h, LWSSSCS_POLL); 1629d4afb5ceSopenharmony_ci if (r) 1630d4afb5ceSopenharmony_ci return r; 1631d4afb5ceSopenharmony_ci } 1632d4afb5ceSopenharmony_ci 1633d4afb5ceSopenharmony_ci /* 1634d4afb5ceSopenharmony_ci * Retries operate via lws_ss_request_tx(), explicitly ask for a 1635d4afb5ceSopenharmony_ci * reconnection to clear the retry limit 1636d4afb5ceSopenharmony_ci */ 1637d4afb5ceSopenharmony_ci r = _lws_ss_client_connect(h, 1, 0); 1638d4afb5ceSopenharmony_ci if (r == LWSSSSRET_DESTROY_ME) 1639d4afb5ceSopenharmony_ci return r; 1640d4afb5ceSopenharmony_ci 1641d4afb5ceSopenharmony_ci if (r) 1642d4afb5ceSopenharmony_ci return lws_ss_backoff(h); 1643d4afb5ceSopenharmony_ci 1644d4afb5ceSopenharmony_ci return LWSSSSRET_OK; 1645d4afb5ceSopenharmony_ci} 1646d4afb5ceSopenharmony_ci 1647d4afb5ceSopenharmony_cilws_ss_state_return_t 1648d4afb5ceSopenharmony_cilws_ss_request_tx_len(lws_ss_handle_t *h, unsigned long len) 1649d4afb5ceSopenharmony_ci{ 1650d4afb5ceSopenharmony_ci lws_service_assert_loop_thread(h->context, h->tsi); 1651d4afb5ceSopenharmony_ci 1652d4afb5ceSopenharmony_ci if (h->wsi && h->policy && 1653d4afb5ceSopenharmony_ci (h->policy->protocol == LWSSSP_H1 || 1654d4afb5ceSopenharmony_ci h->policy->protocol == LWSSSP_H2 || 1655d4afb5ceSopenharmony_ci h->policy->protocol == LWSSSP_WS)) 1656d4afb5ceSopenharmony_ci h->wsi->http.writeable_len = len; 1657d4afb5ceSopenharmony_ci else 1658d4afb5ceSopenharmony_ci h->writeable_len = len; 1659d4afb5ceSopenharmony_ci 1660d4afb5ceSopenharmony_ci return lws_ss_request_tx(h); 1661d4afb5ceSopenharmony_ci} 1662d4afb5ceSopenharmony_ci 1663d4afb5ceSopenharmony_ci/* 1664d4afb5ceSopenharmony_ci * private helpers 1665d4afb5ceSopenharmony_ci */ 1666d4afb5ceSopenharmony_ci 1667d4afb5ceSopenharmony_ci/* used on context destroy when iterating listed lws_ss on a pt */ 1668d4afb5ceSopenharmony_ci 1669d4afb5ceSopenharmony_ciint 1670d4afb5ceSopenharmony_cilws_ss_destroy_dll(struct lws_dll2 *d, void *user) 1671d4afb5ceSopenharmony_ci{ 1672d4afb5ceSopenharmony_ci lws_ss_handle_t *h = lws_container_of(d, lws_ss_handle_t, list); 1673d4afb5ceSopenharmony_ci 1674d4afb5ceSopenharmony_ci lws_ss_destroy(&h); 1675d4afb5ceSopenharmony_ci 1676d4afb5ceSopenharmony_ci return 0; 1677d4afb5ceSopenharmony_ci} 1678d4afb5ceSopenharmony_ci 1679d4afb5ceSopenharmony_ciint 1680d4afb5ceSopenharmony_cilws_ss_cancel_notify_dll(struct lws_dll2 *d, void *user) 1681d4afb5ceSopenharmony_ci{ 1682d4afb5ceSopenharmony_ci lws_ss_handle_t *h = lws_container_of(d, lws_ss_handle_t, list); 1683d4afb5ceSopenharmony_ci 1684d4afb5ceSopenharmony_ci if (lws_ss_event_helper(h, LWSSSCS_EVENT_WAIT_CANCELLED)) 1685d4afb5ceSopenharmony_ci lwsl_warn("%s: cancel event ignores return\n", __func__); 1686d4afb5ceSopenharmony_ci 1687d4afb5ceSopenharmony_ci return 0; 1688d4afb5ceSopenharmony_ci} 1689d4afb5ceSopenharmony_ci 1690d4afb5ceSopenharmony_cistruct lws_sequencer * 1691d4afb5ceSopenharmony_cilws_ss_get_sequencer(lws_ss_handle_t *h) 1692d4afb5ceSopenharmony_ci{ 1693d4afb5ceSopenharmony_ci return h->seq; 1694d4afb5ceSopenharmony_ci} 1695d4afb5ceSopenharmony_ci 1696d4afb5ceSopenharmony_cistruct lws_context * 1697d4afb5ceSopenharmony_cilws_ss_get_context(struct lws_ss_handle *h) 1698d4afb5ceSopenharmony_ci{ 1699d4afb5ceSopenharmony_ci return h->context; 1700d4afb5ceSopenharmony_ci} 1701d4afb5ceSopenharmony_ci 1702d4afb5ceSopenharmony_ciconst char * 1703d4afb5ceSopenharmony_cilws_ss_rideshare(struct lws_ss_handle *h) 1704d4afb5ceSopenharmony_ci{ 1705d4afb5ceSopenharmony_ci if (!h->rideshare) 1706d4afb5ceSopenharmony_ci return h->policy->streamtype; 1707d4afb5ceSopenharmony_ci 1708d4afb5ceSopenharmony_ci return h->rideshare->streamtype; 1709d4afb5ceSopenharmony_ci} 1710d4afb5ceSopenharmony_ci 1711d4afb5ceSopenharmony_ciint 1712d4afb5ceSopenharmony_cilws_ss_add_peer_tx_credit(struct lws_ss_handle *h, int32_t bump) 1713d4afb5ceSopenharmony_ci{ 1714d4afb5ceSopenharmony_ci const struct ss_pcols *ssp; 1715d4afb5ceSopenharmony_ci 1716d4afb5ceSopenharmony_ci lws_service_assert_loop_thread(h->context, h->tsi); 1717d4afb5ceSopenharmony_ci 1718d4afb5ceSopenharmony_ci ssp = ss_pcols[(int)h->policy->protocol]; 1719d4afb5ceSopenharmony_ci 1720d4afb5ceSopenharmony_ci if (h->wsi && ssp && ssp->tx_cr_add) 1721d4afb5ceSopenharmony_ci return ssp->tx_cr_add(h, bump); 1722d4afb5ceSopenharmony_ci 1723d4afb5ceSopenharmony_ci return 0; 1724d4afb5ceSopenharmony_ci} 1725d4afb5ceSopenharmony_ci 1726d4afb5ceSopenharmony_ciint 1727d4afb5ceSopenharmony_cilws_ss_get_est_peer_tx_credit(struct lws_ss_handle *h) 1728d4afb5ceSopenharmony_ci{ 1729d4afb5ceSopenharmony_ci const struct ss_pcols *ssp; 1730d4afb5ceSopenharmony_ci 1731d4afb5ceSopenharmony_ci lws_service_assert_loop_thread(h->context, h->tsi); 1732d4afb5ceSopenharmony_ci 1733d4afb5ceSopenharmony_ci ssp = ss_pcols[(int)h->policy->protocol]; 1734d4afb5ceSopenharmony_ci 1735d4afb5ceSopenharmony_ci if (h->wsi && ssp && ssp->tx_cr_add) 1736d4afb5ceSopenharmony_ci return ssp->tx_cr_est(h); 1737d4afb5ceSopenharmony_ci 1738d4afb5ceSopenharmony_ci return 0; 1739d4afb5ceSopenharmony_ci} 1740d4afb5ceSopenharmony_ci 1741d4afb5ceSopenharmony_ci/* 1742d4afb5ceSopenharmony_ci * protocol-independent handler for ss timeout 1743d4afb5ceSopenharmony_ci */ 1744d4afb5ceSopenharmony_ci 1745d4afb5ceSopenharmony_cistatic void 1746d4afb5ceSopenharmony_cilws_ss_to_cb(lws_sorted_usec_list_t *sul) 1747d4afb5ceSopenharmony_ci{ 1748d4afb5ceSopenharmony_ci lws_ss_handle_t *h = lws_container_of(sul, lws_ss_handle_t, sul_timeout); 1749d4afb5ceSopenharmony_ci lws_ss_state_return_t r; 1750d4afb5ceSopenharmony_ci 1751d4afb5ceSopenharmony_ci lwsl_info("%s: %s timeout fired\n", __func__, lws_ss_tag(h)); 1752d4afb5ceSopenharmony_ci 1753d4afb5ceSopenharmony_ci r = lws_ss_event_helper(h, LWSSSCS_TIMEOUT); 1754d4afb5ceSopenharmony_ci if (r != LWSSSSRET_DISCONNECT_ME && r != LWSSSSRET_DESTROY_ME) 1755d4afb5ceSopenharmony_ci return; 1756d4afb5ceSopenharmony_ci 1757d4afb5ceSopenharmony_ci if (h->wsi) 1758d4afb5ceSopenharmony_ci lws_set_timeout(h->wsi, 1, LWS_TO_KILL_ASYNC); 1759d4afb5ceSopenharmony_ci 1760d4afb5ceSopenharmony_ci _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, h->wsi, &h); 1761d4afb5ceSopenharmony_ci} 1762d4afb5ceSopenharmony_ci 1763d4afb5ceSopenharmony_civoid 1764d4afb5ceSopenharmony_cilws_ss_start_timeout(struct lws_ss_handle *h, unsigned int timeout_ms) 1765d4afb5ceSopenharmony_ci{ 1766d4afb5ceSopenharmony_ci lws_service_assert_loop_thread(h->context, h->tsi); 1767d4afb5ceSopenharmony_ci 1768d4afb5ceSopenharmony_ci if (!timeout_ms && !h->policy->timeout_ms) 1769d4afb5ceSopenharmony_ci return; 1770d4afb5ceSopenharmony_ci 1771d4afb5ceSopenharmony_ci lws_sul_schedule(h->context, 0, &h->sul_timeout, lws_ss_to_cb, 1772d4afb5ceSopenharmony_ci (timeout_ms ? timeout_ms : h->policy->timeout_ms) * 1773d4afb5ceSopenharmony_ci LWS_US_PER_MS); 1774d4afb5ceSopenharmony_ci} 1775d4afb5ceSopenharmony_ci 1776d4afb5ceSopenharmony_civoid 1777d4afb5ceSopenharmony_cilws_ss_cancel_timeout(struct lws_ss_handle *h) 1778d4afb5ceSopenharmony_ci{ 1779d4afb5ceSopenharmony_ci lws_service_assert_loop_thread(h->context, h->tsi); 1780d4afb5ceSopenharmony_ci lws_sul_cancel(&h->sul_timeout); 1781d4afb5ceSopenharmony_ci} 1782d4afb5ceSopenharmony_ci 1783d4afb5ceSopenharmony_civoid 1784d4afb5ceSopenharmony_cilws_ss_change_handlers(struct lws_ss_handle *h, 1785d4afb5ceSopenharmony_ci lws_ss_state_return_t (*rx)(void *userobj, const uint8_t *buf, 1786d4afb5ceSopenharmony_ci size_t len, int flags), 1787d4afb5ceSopenharmony_ci lws_ss_state_return_t (*tx)(void *userobj, lws_ss_tx_ordinal_t ord, 1788d4afb5ceSopenharmony_ci uint8_t *buf, size_t *len, int *flags), 1789d4afb5ceSopenharmony_ci lws_ss_state_return_t (*state)(void *userobj, void *h_src /* ss handle type */, 1790d4afb5ceSopenharmony_ci lws_ss_constate_t state, 1791d4afb5ceSopenharmony_ci lws_ss_tx_ordinal_t ack)) 1792d4afb5ceSopenharmony_ci{ 1793d4afb5ceSopenharmony_ci if (rx) 1794d4afb5ceSopenharmony_ci h->info.rx = rx; 1795d4afb5ceSopenharmony_ci if (tx) 1796d4afb5ceSopenharmony_ci h->info.tx = tx; 1797d4afb5ceSopenharmony_ci if (state) 1798d4afb5ceSopenharmony_ci h->info.state = state; 1799d4afb5ceSopenharmony_ci} 1800d4afb5ceSopenharmony_ci 1801d4afb5ceSopenharmony_ciconst char * 1802d4afb5ceSopenharmony_cilws_ss_tag(struct lws_ss_handle *h) 1803d4afb5ceSopenharmony_ci{ 1804d4afb5ceSopenharmony_ci if (!h) 1805d4afb5ceSopenharmony_ci return "[null ss]"; 1806d4afb5ceSopenharmony_ci return lws_lc_tag(&h->lc); 1807d4afb5ceSopenharmony_ci} 1808d4afb5ceSopenharmony_ci 1809d4afb5ceSopenharmony_cistruct lws_log_cx * 1810d4afb5ceSopenharmony_cilwsl_ss_get_cx(struct lws_ss_handle *ss) 1811d4afb5ceSopenharmony_ci{ 1812d4afb5ceSopenharmony_ci if (!ss) 1813d4afb5ceSopenharmony_ci return NULL; 1814d4afb5ceSopenharmony_ci 1815d4afb5ceSopenharmony_ci return ss->lc.log_cx; 1816d4afb5ceSopenharmony_ci} 1817d4afb5ceSopenharmony_ci 1818d4afb5ceSopenharmony_civoid 1819d4afb5ceSopenharmony_cilws_log_prepend_ss(struct lws_log_cx *cx, void *obj, char **p, char *e) 1820d4afb5ceSopenharmony_ci{ 1821d4afb5ceSopenharmony_ci struct lws_ss_handle *h = (struct lws_ss_handle *)obj; 1822d4afb5ceSopenharmony_ci 1823d4afb5ceSopenharmony_ci *p += lws_snprintf(*p, lws_ptr_diff_size_t(e, (*p)), "%s: ", 1824d4afb5ceSopenharmony_ci lws_ss_tag(h)); 1825d4afb5ceSopenharmony_ci} 1826d4afb5ceSopenharmony_ci 1827d4afb5ceSopenharmony_ci#if defined(_DEBUG) 1828d4afb5ceSopenharmony_civoid 1829d4afb5ceSopenharmony_cilws_ss_assert_extant(struct lws_context *cx, int tsi, struct lws_ss_handle *h) 1830d4afb5ceSopenharmony_ci{ 1831d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &cx->pt[tsi]; 1832d4afb5ceSopenharmony_ci 1833d4afb5ceSopenharmony_ci lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, pt->ss_owner.head) { 1834d4afb5ceSopenharmony_ci struct lws_ss_handle *h1 = lws_container_of(d, 1835d4afb5ceSopenharmony_ci struct lws_ss_handle, list); 1836d4afb5ceSopenharmony_ci 1837d4afb5ceSopenharmony_ci if (h == h1) 1838d4afb5ceSopenharmony_ci return; /* okay */ 1839d4afb5ceSopenharmony_ci 1840d4afb5ceSopenharmony_ci } lws_end_foreach_dll_safe(d, d1); 1841d4afb5ceSopenharmony_ci 1842d4afb5ceSopenharmony_ci /* 1843d4afb5ceSopenharmony_ci * The ss handle is not listed in the pt ss handle owner... 1844d4afb5ceSopenharmony_ci */ 1845d4afb5ceSopenharmony_ci 1846d4afb5ceSopenharmony_ci assert(0); 1847d4afb5ceSopenharmony_ci} 1848d4afb5ceSopenharmony_ci#endif 1849