1d4afb5ceSopenharmony_ci/* 2d4afb5ceSopenharmony_ci * libwebsockets - small server side websockets and web server implementation 3d4afb5ceSopenharmony_ci * 4d4afb5ceSopenharmony_ci * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com> 5d4afb5ceSopenharmony_ci * 6d4afb5ceSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 7d4afb5ceSopenharmony_ci * of this software and associated documentation files (the "Software"), to 8d4afb5ceSopenharmony_ci * deal in the Software without restriction, including without limitation the 9d4afb5ceSopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10d4afb5ceSopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is 11d4afb5ceSopenharmony_ci * furnished to do so, subject to the following conditions: 12d4afb5ceSopenharmony_ci * 13d4afb5ceSopenharmony_ci * The above copyright notice and this permission notice shall be included in 14d4afb5ceSopenharmony_ci * all copies or substantial portions of the Software. 15d4afb5ceSopenharmony_ci * 16d4afb5ceSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17d4afb5ceSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18d4afb5ceSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19d4afb5ceSopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20d4afb5ceSopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21d4afb5ceSopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22d4afb5ceSopenharmony_ci * IN THE SOFTWARE. 23d4afb5ceSopenharmony_ci */ 24d4afb5ceSopenharmony_ci 25d4afb5ceSopenharmony_ci#include "private-lib-core.h" 26d4afb5ceSopenharmony_ci 27d4afb5ceSopenharmony_ciconst char * 28d4afb5ceSopenharmony_cilws_wsi_tag(struct lws *wsi) 29d4afb5ceSopenharmony_ci{ 30d4afb5ceSopenharmony_ci if (!wsi) 31d4afb5ceSopenharmony_ci return "[null wsi]"; 32d4afb5ceSopenharmony_ci return lws_lc_tag(&wsi->lc); 33d4afb5ceSopenharmony_ci} 34d4afb5ceSopenharmony_ci 35d4afb5ceSopenharmony_ci#if defined (_DEBUG) 36d4afb5ceSopenharmony_civoid lwsi_set_role(struct lws *wsi, lws_wsi_state_t role) 37d4afb5ceSopenharmony_ci{ 38d4afb5ceSopenharmony_ci wsi->wsistate = (wsi->wsistate & (~LWSI_ROLE_MASK)) | role; 39d4afb5ceSopenharmony_ci 40d4afb5ceSopenharmony_ci lwsl_wsi_debug(wsi, "state 0x%lx", (unsigned long)wsi->wsistate); 41d4afb5ceSopenharmony_ci} 42d4afb5ceSopenharmony_ci 43d4afb5ceSopenharmony_civoid lwsi_set_state(struct lws *wsi, lws_wsi_state_t lrs) 44d4afb5ceSopenharmony_ci{ 45d4afb5ceSopenharmony_ci lws_wsi_state_t old = wsi->wsistate; 46d4afb5ceSopenharmony_ci 47d4afb5ceSopenharmony_ci wsi->wsistate = (old & (unsigned int)(~LRS_MASK)) | lrs; 48d4afb5ceSopenharmony_ci 49d4afb5ceSopenharmony_ci lwsl_wsi_debug(wsi, "lwsi_set_state 0x%lx -> 0x%lx", 50d4afb5ceSopenharmony_ci (unsigned long)old, (unsigned long)wsi->wsistate); 51d4afb5ceSopenharmony_ci} 52d4afb5ceSopenharmony_ci#endif 53d4afb5ceSopenharmony_ci 54d4afb5ceSopenharmony_ci 55d4afb5ceSopenharmony_civoid 56d4afb5ceSopenharmony_cilws_log_prepend_wsi(struct lws_log_cx *cx, void *obj, char **p, char *e) 57d4afb5ceSopenharmony_ci{ 58d4afb5ceSopenharmony_ci struct lws *wsi = (struct lws *)obj; 59d4afb5ceSopenharmony_ci 60d4afb5ceSopenharmony_ci *p += lws_snprintf(*p, lws_ptr_diff_size_t(e, (*p)), "%s: ", 61d4afb5ceSopenharmony_ci lws_wsi_tag(wsi)); 62d4afb5ceSopenharmony_ci} 63d4afb5ceSopenharmony_ci 64d4afb5ceSopenharmony_civoid 65d4afb5ceSopenharmony_cilws_vhost_bind_wsi(struct lws_vhost *vh, struct lws *wsi) 66d4afb5ceSopenharmony_ci{ 67d4afb5ceSopenharmony_ci if (wsi->a.vhost == vh) 68d4afb5ceSopenharmony_ci return; 69d4afb5ceSopenharmony_ci 70d4afb5ceSopenharmony_ci lws_context_lock(vh->context, __func__); /* ---------- context { */ 71d4afb5ceSopenharmony_ci wsi->a.vhost = vh; 72d4afb5ceSopenharmony_ci 73d4afb5ceSopenharmony_ci#if defined(LWS_WITH_TLS_JIT_TRUST) 74d4afb5ceSopenharmony_ci if (!vh->count_bound_wsi && vh->grace_after_unref) { 75d4afb5ceSopenharmony_ci lwsl_wsi_info(wsi, "in use"); 76d4afb5ceSopenharmony_ci lws_sul_cancel(&vh->sul_unref); 77d4afb5ceSopenharmony_ci } 78d4afb5ceSopenharmony_ci#endif 79d4afb5ceSopenharmony_ci 80d4afb5ceSopenharmony_ci vh->count_bound_wsi++; 81d4afb5ceSopenharmony_ci lws_context_unlock(vh->context); /* } context ---------- */ 82d4afb5ceSopenharmony_ci 83d4afb5ceSopenharmony_ci lwsl_wsi_debug(wsi, "vh %s: wsi %s/%s, count_bound_wsi %d\n", 84d4afb5ceSopenharmony_ci vh->name, wsi->role_ops ? wsi->role_ops->name : "none", 85d4afb5ceSopenharmony_ci wsi->a.protocol ? wsi->a.protocol->name : "none", 86d4afb5ceSopenharmony_ci vh->count_bound_wsi); 87d4afb5ceSopenharmony_ci assert(wsi->a.vhost->count_bound_wsi > 0); 88d4afb5ceSopenharmony_ci} 89d4afb5ceSopenharmony_ci 90d4afb5ceSopenharmony_ci 91d4afb5ceSopenharmony_ci/* req cx lock... acquires vh lock */ 92d4afb5ceSopenharmony_civoid 93d4afb5ceSopenharmony_ci__lws_vhost_unbind_wsi(struct lws *wsi) 94d4afb5ceSopenharmony_ci{ 95d4afb5ceSopenharmony_ci struct lws_vhost *vh = wsi->a.vhost; 96d4afb5ceSopenharmony_ci 97d4afb5ceSopenharmony_ci if (!vh) 98d4afb5ceSopenharmony_ci return; 99d4afb5ceSopenharmony_ci 100d4afb5ceSopenharmony_ci lws_context_assert_lock_held(wsi->a.context); 101d4afb5ceSopenharmony_ci 102d4afb5ceSopenharmony_ci lws_vhost_lock(vh); 103d4afb5ceSopenharmony_ci 104d4afb5ceSopenharmony_ci assert(vh->count_bound_wsi > 0); 105d4afb5ceSopenharmony_ci vh->count_bound_wsi--; 106d4afb5ceSopenharmony_ci 107d4afb5ceSopenharmony_ci#if defined(LWS_WITH_TLS_JIT_TRUST) 108d4afb5ceSopenharmony_ci if (!vh->count_bound_wsi && vh->grace_after_unref) 109d4afb5ceSopenharmony_ci lws_tls_jit_trust_vh_start_grace(vh); 110d4afb5ceSopenharmony_ci#endif 111d4afb5ceSopenharmony_ci 112d4afb5ceSopenharmony_ci lwsl_wsi_debug(wsi, "vh %s: count_bound_wsi %d", 113d4afb5ceSopenharmony_ci vh->name, vh->count_bound_wsi); 114d4afb5ceSopenharmony_ci 115d4afb5ceSopenharmony_ci lws_vhost_unlock(vh); 116d4afb5ceSopenharmony_ci 117d4afb5ceSopenharmony_ci if (!vh->count_bound_wsi && vh->being_destroyed) 118d4afb5ceSopenharmony_ci /* 119d4afb5ceSopenharmony_ci * We have closed all wsi that were bound to this vhost 120d4afb5ceSopenharmony_ci * by any pt: nothing can be servicing any wsi belonging 121d4afb5ceSopenharmony_ci * to it any more. 122d4afb5ceSopenharmony_ci * 123d4afb5ceSopenharmony_ci * Finalize the vh destruction... must drop vh lock 124d4afb5ceSopenharmony_ci */ 125d4afb5ceSopenharmony_ci __lws_vhost_destroy2(vh); 126d4afb5ceSopenharmony_ci 127d4afb5ceSopenharmony_ci wsi->a.vhost = NULL; 128d4afb5ceSopenharmony_ci} 129d4afb5ceSopenharmony_ci 130d4afb5ceSopenharmony_cistruct lws * 131d4afb5ceSopenharmony_cilws_get_network_wsi(struct lws *wsi) 132d4afb5ceSopenharmony_ci{ 133d4afb5ceSopenharmony_ci if (!wsi) 134d4afb5ceSopenharmony_ci return NULL; 135d4afb5ceSopenharmony_ci 136d4afb5ceSopenharmony_ci#if defined(LWS_WITH_HTTP2) || defined(LWS_ROLE_MQTT) 137d4afb5ceSopenharmony_ci if (!wsi->mux_substream 138d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CLIENT) 139d4afb5ceSopenharmony_ci && !wsi->client_mux_substream 140d4afb5ceSopenharmony_ci#endif 141d4afb5ceSopenharmony_ci ) 142d4afb5ceSopenharmony_ci return wsi; 143d4afb5ceSopenharmony_ci 144d4afb5ceSopenharmony_ci while (wsi->mux.parent_wsi) 145d4afb5ceSopenharmony_ci wsi = wsi->mux.parent_wsi; 146d4afb5ceSopenharmony_ci#endif 147d4afb5ceSopenharmony_ci 148d4afb5ceSopenharmony_ci return wsi; 149d4afb5ceSopenharmony_ci} 150d4afb5ceSopenharmony_ci 151d4afb5ceSopenharmony_ci 152d4afb5ceSopenharmony_ciconst struct lws_protocols * 153d4afb5ceSopenharmony_cilws_vhost_name_to_protocol(struct lws_vhost *vh, const char *name) 154d4afb5ceSopenharmony_ci{ 155d4afb5ceSopenharmony_ci int n; 156d4afb5ceSopenharmony_ci 157d4afb5ceSopenharmony_ci for (n = 0; n < vh->count_protocols; n++) 158d4afb5ceSopenharmony_ci if (vh->protocols[n].name && !strcmp(name, vh->protocols[n].name)) 159d4afb5ceSopenharmony_ci return &vh->protocols[n]; 160d4afb5ceSopenharmony_ci 161d4afb5ceSopenharmony_ci return NULL; 162d4afb5ceSopenharmony_ci} 163d4afb5ceSopenharmony_ci 164d4afb5ceSopenharmony_ciint 165d4afb5ceSopenharmony_cilws_callback_all_protocol(struct lws_context *context, 166d4afb5ceSopenharmony_ci const struct lws_protocols *protocol, int reason) 167d4afb5ceSopenharmony_ci{ 168d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &context->pt[0]; 169d4afb5ceSopenharmony_ci unsigned int n, m = context->count_threads; 170d4afb5ceSopenharmony_ci struct lws *wsi; 171d4afb5ceSopenharmony_ci 172d4afb5ceSopenharmony_ci while (m--) { 173d4afb5ceSopenharmony_ci for (n = 0; n < pt->fds_count; n++) { 174d4afb5ceSopenharmony_ci wsi = wsi_from_fd(context, pt->fds[n].fd); 175d4afb5ceSopenharmony_ci if (!wsi) 176d4afb5ceSopenharmony_ci continue; 177d4afb5ceSopenharmony_ci if (wsi->a.protocol == protocol) 178d4afb5ceSopenharmony_ci protocol->callback(wsi, 179d4afb5ceSopenharmony_ci (enum lws_callback_reasons)reason, 180d4afb5ceSopenharmony_ci wsi->user_space, NULL, 0); 181d4afb5ceSopenharmony_ci } 182d4afb5ceSopenharmony_ci pt++; 183d4afb5ceSopenharmony_ci } 184d4afb5ceSopenharmony_ci 185d4afb5ceSopenharmony_ci return 0; 186d4afb5ceSopenharmony_ci} 187d4afb5ceSopenharmony_ci 188d4afb5ceSopenharmony_civoid * 189d4afb5ceSopenharmony_cilws_evlib_wsi_to_evlib_pt(struct lws *wsi) 190d4afb5ceSopenharmony_ci{ 191d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; 192d4afb5ceSopenharmony_ci 193d4afb5ceSopenharmony_ci return pt->evlib_pt; 194d4afb5ceSopenharmony_ci} 195d4afb5ceSopenharmony_ci 196d4afb5ceSopenharmony_civoid * 197d4afb5ceSopenharmony_cilws_evlib_tsi_to_evlib_pt(struct lws_context *cx, int tsi) 198d4afb5ceSopenharmony_ci{ 199d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &cx->pt[tsi]; 200d4afb5ceSopenharmony_ci 201d4afb5ceSopenharmony_ci return pt->evlib_pt; 202d4afb5ceSopenharmony_ci} 203d4afb5ceSopenharmony_ci 204d4afb5ceSopenharmony_ciint 205d4afb5ceSopenharmony_cilws_callback_all_protocol_vhost_args(struct lws_vhost *vh, 206d4afb5ceSopenharmony_ci const struct lws_protocols *protocol, int reason, 207d4afb5ceSopenharmony_ci void *argp, size_t len) 208d4afb5ceSopenharmony_ci{ 209d4afb5ceSopenharmony_ci struct lws_context *context = vh->context; 210d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &context->pt[0]; 211d4afb5ceSopenharmony_ci unsigned int n, m = context->count_threads; 212d4afb5ceSopenharmony_ci struct lws *wsi; 213d4afb5ceSopenharmony_ci 214d4afb5ceSopenharmony_ci while (m--) { 215d4afb5ceSopenharmony_ci for (n = 0; n < pt->fds_count; n++) { 216d4afb5ceSopenharmony_ci wsi = wsi_from_fd(context, pt->fds[n].fd); 217d4afb5ceSopenharmony_ci if (!wsi) 218d4afb5ceSopenharmony_ci continue; 219d4afb5ceSopenharmony_ci if (wsi->a.vhost == vh && (wsi->a.protocol == protocol || 220d4afb5ceSopenharmony_ci !protocol)) 221d4afb5ceSopenharmony_ci wsi->a.protocol->callback(wsi, (enum lws_callback_reasons)reason, 222d4afb5ceSopenharmony_ci wsi->user_space, argp, len); 223d4afb5ceSopenharmony_ci } 224d4afb5ceSopenharmony_ci pt++; 225d4afb5ceSopenharmony_ci } 226d4afb5ceSopenharmony_ci 227d4afb5ceSopenharmony_ci return 0; 228d4afb5ceSopenharmony_ci} 229d4afb5ceSopenharmony_ci 230d4afb5ceSopenharmony_ciint 231d4afb5ceSopenharmony_cilws_callback_all_protocol_vhost(struct lws_vhost *vh, 232d4afb5ceSopenharmony_ci const struct lws_protocols *protocol, int reason) 233d4afb5ceSopenharmony_ci{ 234d4afb5ceSopenharmony_ci return lws_callback_all_protocol_vhost_args(vh, protocol, reason, NULL, 0); 235d4afb5ceSopenharmony_ci} 236d4afb5ceSopenharmony_ci 237d4afb5ceSopenharmony_ciint 238d4afb5ceSopenharmony_cilws_callback_vhost_protocols(struct lws *wsi, int reason, void *in, size_t len) 239d4afb5ceSopenharmony_ci{ 240d4afb5ceSopenharmony_ci int n; 241d4afb5ceSopenharmony_ci 242d4afb5ceSopenharmony_ci for (n = 0; n < wsi->a.vhost->count_protocols; n++) 243d4afb5ceSopenharmony_ci if (wsi->a.vhost->protocols[n].callback(wsi, (enum lws_callback_reasons)reason, NULL, in, len)) 244d4afb5ceSopenharmony_ci return 1; 245d4afb5ceSopenharmony_ci 246d4afb5ceSopenharmony_ci return 0; 247d4afb5ceSopenharmony_ci} 248d4afb5ceSopenharmony_ci 249d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_FAULT_INJECTION) 250d4afb5ceSopenharmony_ci/* 251d4afb5ceSopenharmony_ci * We want to inject a fault that makes it feel like the peer hung up on us, 252d4afb5ceSopenharmony_ci * or we were otherwise cut off. 253d4afb5ceSopenharmony_ci */ 254d4afb5ceSopenharmony_civoid 255d4afb5ceSopenharmony_cilws_wsi_fault_timedclose_cb(lws_sorted_usec_list_t *s) 256d4afb5ceSopenharmony_ci{ 257d4afb5ceSopenharmony_ci struct lws *wsi = lws_container_of(s, struct lws, sul_fault_timedclose); 258d4afb5ceSopenharmony_ci 259d4afb5ceSopenharmony_ci lwsl_wsi_warn(wsi, "force-closing"); 260d4afb5ceSopenharmony_ci lws_wsi_close(wsi, LWS_TO_KILL_ASYNC); 261d4afb5ceSopenharmony_ci} 262d4afb5ceSopenharmony_ci#endif 263d4afb5ceSopenharmony_ci 264d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_FAULT_INJECTION) 265d4afb5ceSopenharmony_civoid 266d4afb5ceSopenharmony_cilws_wsi_fault_timedclose(struct lws *wsi) 267d4afb5ceSopenharmony_ci{ 268d4afb5ceSopenharmony_ci uint64_t u; 269d4afb5ceSopenharmony_ci 270d4afb5ceSopenharmony_ci if (!lws_fi(&wsi->fic, "timedclose")) 271d4afb5ceSopenharmony_ci return; 272d4afb5ceSopenharmony_ci 273d4afb5ceSopenharmony_ci if (lws_fi_range(&wsi->fic, "timedclose_ms", &u)) 274d4afb5ceSopenharmony_ci return; 275d4afb5ceSopenharmony_ci 276d4afb5ceSopenharmony_ci lwsl_wsi_warn(wsi, "injecting close in %ums", (unsigned int)u); 277d4afb5ceSopenharmony_ci lws_sul_schedule(wsi->a.context, wsi->tsi, &wsi->sul_fault_timedclose, 278d4afb5ceSopenharmony_ci lws_wsi_fault_timedclose_cb, 279d4afb5ceSopenharmony_ci (lws_usec_t)(u * 1000ull)); 280d4afb5ceSopenharmony_ci} 281d4afb5ceSopenharmony_ci#endif 282d4afb5ceSopenharmony_ci 283d4afb5ceSopenharmony_ci 284d4afb5ceSopenharmony_ci/* 285d4afb5ceSopenharmony_ci * We need the context lock 286d4afb5ceSopenharmony_ci */ 287d4afb5ceSopenharmony_ci 288d4afb5ceSopenharmony_cistruct lws * 289d4afb5ceSopenharmony_ci__lws_wsi_create_with_role(struct lws_context *context, int tsi, 290d4afb5ceSopenharmony_ci const struct lws_role_ops *ops, 291d4afb5ceSopenharmony_ci lws_log_cx_t *log_cx_template) 292d4afb5ceSopenharmony_ci{ 293d4afb5ceSopenharmony_ci size_t s = sizeof(struct lws); 294d4afb5ceSopenharmony_ci struct lws *wsi; 295d4afb5ceSopenharmony_ci 296d4afb5ceSopenharmony_ci assert(tsi >= 0 && tsi < LWS_MAX_SMP); 297d4afb5ceSopenharmony_ci 298d4afb5ceSopenharmony_ci lws_context_assert_lock_held(context); 299d4afb5ceSopenharmony_ci 300d4afb5ceSopenharmony_ci#if defined(LWS_WITH_EVENT_LIBS) 301d4afb5ceSopenharmony_ci s += context->event_loop_ops->evlib_size_wsi; 302d4afb5ceSopenharmony_ci#endif 303d4afb5ceSopenharmony_ci 304d4afb5ceSopenharmony_ci wsi = lws_zalloc(s, __func__); 305d4afb5ceSopenharmony_ci 306d4afb5ceSopenharmony_ci if (!wsi) { 307d4afb5ceSopenharmony_ci lwsl_cx_err(context, "OOM"); 308d4afb5ceSopenharmony_ci return NULL; 309d4afb5ceSopenharmony_ci } 310d4afb5ceSopenharmony_ci 311d4afb5ceSopenharmony_ci if (log_cx_template) 312d4afb5ceSopenharmony_ci wsi->lc.log_cx = log_cx_template; 313d4afb5ceSopenharmony_ci else 314d4afb5ceSopenharmony_ci wsi->lc.log_cx = context->log_cx; 315d4afb5ceSopenharmony_ci 316d4afb5ceSopenharmony_ci#if defined(LWS_WITH_EVENT_LIBS) 317d4afb5ceSopenharmony_ci wsi->evlib_wsi = (uint8_t *)wsi + sizeof(*wsi); 318d4afb5ceSopenharmony_ci#endif 319d4afb5ceSopenharmony_ci wsi->a.context = context; 320d4afb5ceSopenharmony_ci lws_role_transition(wsi, 0, LRS_UNCONNECTED, ops); 321d4afb5ceSopenharmony_ci wsi->pending_timeout = NO_PENDING_TIMEOUT; 322d4afb5ceSopenharmony_ci wsi->a.protocol = NULL; 323d4afb5ceSopenharmony_ci wsi->tsi = (char)tsi; 324d4afb5ceSopenharmony_ci wsi->a.vhost = NULL; 325d4afb5ceSopenharmony_ci wsi->desc.sockfd = LWS_SOCK_INVALID; 326d4afb5ceSopenharmony_ci wsi->position_in_fds_table = LWS_NO_FDS_POS; 327d4afb5ceSopenharmony_ci 328d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_FAULT_INJECTION) 329d4afb5ceSopenharmony_ci lws_xos_init(&wsi->fic.xos, lws_xos(&context->fic.xos)); 330d4afb5ceSopenharmony_ci#endif 331d4afb5ceSopenharmony_ci 332d4afb5ceSopenharmony_ci lws_fi_inherit_copy(&wsi->fic, &context->fic, "wsi", NULL); 333d4afb5ceSopenharmony_ci 334d4afb5ceSopenharmony_ci if (lws_fi(&wsi->fic, "createfail")) { 335d4afb5ceSopenharmony_ci lws_fi_destroy(&wsi->fic); 336d4afb5ceSopenharmony_ci lws_free(wsi); 337d4afb5ceSopenharmony_ci return NULL; 338d4afb5ceSopenharmony_ci } 339d4afb5ceSopenharmony_ci 340d4afb5ceSopenharmony_ci return wsi; 341d4afb5ceSopenharmony_ci} 342d4afb5ceSopenharmony_ci 343d4afb5ceSopenharmony_ciint 344d4afb5ceSopenharmony_cilws_wsi_inject_to_loop(struct lws_context_per_thread *pt, struct lws *wsi) 345d4afb5ceSopenharmony_ci{ 346d4afb5ceSopenharmony_ci int ret = 1; 347d4afb5ceSopenharmony_ci 348d4afb5ceSopenharmony_ci lws_pt_lock(pt, __func__); /* -------------- pt { */ 349d4afb5ceSopenharmony_ci 350d4afb5ceSopenharmony_ci if (pt->context->event_loop_ops->sock_accept) 351d4afb5ceSopenharmony_ci if (pt->context->event_loop_ops->sock_accept(wsi)) 352d4afb5ceSopenharmony_ci goto bail; 353d4afb5ceSopenharmony_ci 354d4afb5ceSopenharmony_ci if (__insert_wsi_socket_into_fds(pt->context, wsi)) 355d4afb5ceSopenharmony_ci goto bail; 356d4afb5ceSopenharmony_ci 357d4afb5ceSopenharmony_ci ret = 0; 358d4afb5ceSopenharmony_ci 359d4afb5ceSopenharmony_cibail: 360d4afb5ceSopenharmony_ci lws_pt_unlock(pt); 361d4afb5ceSopenharmony_ci 362d4afb5ceSopenharmony_ci return ret; 363d4afb5ceSopenharmony_ci} 364d4afb5ceSopenharmony_ci 365d4afb5ceSopenharmony_ci/* 366d4afb5ceSopenharmony_ci * Take a copy of wsi->desc.sockfd before calling this, then close it 367d4afb5ceSopenharmony_ci * afterwards 368d4afb5ceSopenharmony_ci */ 369d4afb5ceSopenharmony_ci 370d4afb5ceSopenharmony_ciint 371d4afb5ceSopenharmony_cilws_wsi_extract_from_loop(struct lws *wsi) 372d4afb5ceSopenharmony_ci{ 373d4afb5ceSopenharmony_ci if (lws_socket_is_valid(wsi->desc.sockfd)) 374d4afb5ceSopenharmony_ci __remove_wsi_socket_from_fds(wsi); 375d4afb5ceSopenharmony_ci 376d4afb5ceSopenharmony_ci if (!wsi->a.context->event_loop_ops->destroy_wsi && 377d4afb5ceSopenharmony_ci wsi->a.context->event_loop_ops->wsi_logical_close) { 378d4afb5ceSopenharmony_ci wsi->a.context->event_loop_ops->wsi_logical_close(wsi); 379d4afb5ceSopenharmony_ci return 1; /* close / destroy continues async */ 380d4afb5ceSopenharmony_ci } 381d4afb5ceSopenharmony_ci 382d4afb5ceSopenharmony_ci if (wsi->a.context->event_loop_ops->destroy_wsi) 383d4afb5ceSopenharmony_ci wsi->a.context->event_loop_ops->destroy_wsi(wsi); 384d4afb5ceSopenharmony_ci 385d4afb5ceSopenharmony_ci return 0; /* he is destroyed */ 386d4afb5ceSopenharmony_ci} 387d4afb5ceSopenharmony_ci 388d4afb5ceSopenharmony_ciint 389d4afb5ceSopenharmony_cilws_callback_vhost_protocols_vhost(struct lws_vhost *vh, int reason, void *in, 390d4afb5ceSopenharmony_ci size_t len) 391d4afb5ceSopenharmony_ci{ 392d4afb5ceSopenharmony_ci int n; 393d4afb5ceSopenharmony_ci struct lws *wsi = lws_zalloc(sizeof(*wsi), "fake wsi"); 394d4afb5ceSopenharmony_ci 395d4afb5ceSopenharmony_ci if (!wsi) 396d4afb5ceSopenharmony_ci return 1; 397d4afb5ceSopenharmony_ci 398d4afb5ceSopenharmony_ci wsi->a.context = vh->context; 399d4afb5ceSopenharmony_ci lws_vhost_bind_wsi(vh, wsi); 400d4afb5ceSopenharmony_ci 401d4afb5ceSopenharmony_ci for (n = 0; n < wsi->a.vhost->count_protocols; n++) { 402d4afb5ceSopenharmony_ci wsi->a.protocol = &vh->protocols[n]; 403d4afb5ceSopenharmony_ci if (wsi->a.protocol->callback(wsi, (enum lws_callback_reasons)reason, NULL, in, len)) { 404d4afb5ceSopenharmony_ci lws_free(wsi); 405d4afb5ceSopenharmony_ci return 1; 406d4afb5ceSopenharmony_ci } 407d4afb5ceSopenharmony_ci } 408d4afb5ceSopenharmony_ci 409d4afb5ceSopenharmony_ci lws_free(wsi); 410d4afb5ceSopenharmony_ci 411d4afb5ceSopenharmony_ci return 0; 412d4afb5ceSopenharmony_ci} 413d4afb5ceSopenharmony_ci 414d4afb5ceSopenharmony_ci 415d4afb5ceSopenharmony_ciint 416d4afb5ceSopenharmony_cilws_rx_flow_control(struct lws *wsi, int _enable) 417d4afb5ceSopenharmony_ci{ 418d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; 419d4afb5ceSopenharmony_ci int en = _enable; 420d4afb5ceSopenharmony_ci 421d4afb5ceSopenharmony_ci // h2 ignores rx flow control atm 422d4afb5ceSopenharmony_ci if (lwsi_role_h2(wsi) || wsi->mux_substream || 423d4afb5ceSopenharmony_ci lwsi_role_h2_ENCAPSULATION(wsi)) 424d4afb5ceSopenharmony_ci return 0; // !!! 425d4afb5ceSopenharmony_ci 426d4afb5ceSopenharmony_ci lwsl_wsi_info(wsi, "0x%x", _enable); 427d4afb5ceSopenharmony_ci 428d4afb5ceSopenharmony_ci if (!(_enable & LWS_RXFLOW_REASON_APPLIES)) { 429d4afb5ceSopenharmony_ci /* 430d4afb5ceSopenharmony_ci * convert user bool style to bitmap style... in user simple 431d4afb5ceSopenharmony_ci * bool style _enable = 0 = flow control it, = 1 = allow rx 432d4afb5ceSopenharmony_ci */ 433d4afb5ceSopenharmony_ci en = LWS_RXFLOW_REASON_APPLIES | LWS_RXFLOW_REASON_USER_BOOL; 434d4afb5ceSopenharmony_ci if (_enable & 1) 435d4afb5ceSopenharmony_ci en |= LWS_RXFLOW_REASON_APPLIES_ENABLE_BIT; 436d4afb5ceSopenharmony_ci } 437d4afb5ceSopenharmony_ci 438d4afb5ceSopenharmony_ci lws_pt_lock(pt, __func__); 439d4afb5ceSopenharmony_ci 440d4afb5ceSopenharmony_ci /* any bit set in rxflow_bitmap DISABLEs rxflow control */ 441d4afb5ceSopenharmony_ci if (en & LWS_RXFLOW_REASON_APPLIES_ENABLE_BIT) 442d4afb5ceSopenharmony_ci wsi->rxflow_bitmap = (uint8_t)(wsi->rxflow_bitmap & ~(en & 0xff)); 443d4afb5ceSopenharmony_ci else 444d4afb5ceSopenharmony_ci wsi->rxflow_bitmap = (uint8_t)(wsi->rxflow_bitmap | (en & 0xff)); 445d4afb5ceSopenharmony_ci 446d4afb5ceSopenharmony_ci if ((LWS_RXFLOW_PENDING_CHANGE | (!wsi->rxflow_bitmap)) == 447d4afb5ceSopenharmony_ci wsi->rxflow_change_to) 448d4afb5ceSopenharmony_ci goto skip; 449d4afb5ceSopenharmony_ci 450d4afb5ceSopenharmony_ci wsi->rxflow_change_to = LWS_RXFLOW_PENDING_CHANGE | 451d4afb5ceSopenharmony_ci (!wsi->rxflow_bitmap); 452d4afb5ceSopenharmony_ci 453d4afb5ceSopenharmony_ci lwsl_wsi_info(wsi, "bitmap 0x%x: en 0x%x, ch 0x%x", 454d4afb5ceSopenharmony_ci wsi->rxflow_bitmap, en, wsi->rxflow_change_to); 455d4afb5ceSopenharmony_ci 456d4afb5ceSopenharmony_ci if (_enable & LWS_RXFLOW_REASON_FLAG_PROCESS_NOW || 457d4afb5ceSopenharmony_ci !wsi->rxflow_will_be_applied) { 458d4afb5ceSopenharmony_ci en = __lws_rx_flow_control(wsi); 459d4afb5ceSopenharmony_ci lws_pt_unlock(pt); 460d4afb5ceSopenharmony_ci 461d4afb5ceSopenharmony_ci return en; 462d4afb5ceSopenharmony_ci } 463d4afb5ceSopenharmony_ci 464d4afb5ceSopenharmony_ciskip: 465d4afb5ceSopenharmony_ci lws_pt_unlock(pt); 466d4afb5ceSopenharmony_ci 467d4afb5ceSopenharmony_ci return 0; 468d4afb5ceSopenharmony_ci} 469d4afb5ceSopenharmony_ci 470d4afb5ceSopenharmony_civoid 471d4afb5ceSopenharmony_cilws_rx_flow_allow_all_protocol(const struct lws_context *context, 472d4afb5ceSopenharmony_ci const struct lws_protocols *protocol) 473d4afb5ceSopenharmony_ci{ 474d4afb5ceSopenharmony_ci const struct lws_context_per_thread *pt = &context->pt[0]; 475d4afb5ceSopenharmony_ci struct lws *wsi; 476d4afb5ceSopenharmony_ci unsigned int n, m = context->count_threads; 477d4afb5ceSopenharmony_ci 478d4afb5ceSopenharmony_ci while (m--) { 479d4afb5ceSopenharmony_ci for (n = 0; n < pt->fds_count; n++) { 480d4afb5ceSopenharmony_ci wsi = wsi_from_fd(context, pt->fds[n].fd); 481d4afb5ceSopenharmony_ci if (!wsi) 482d4afb5ceSopenharmony_ci continue; 483d4afb5ceSopenharmony_ci if (wsi->a.protocol == protocol) 484d4afb5ceSopenharmony_ci lws_rx_flow_control(wsi, LWS_RXFLOW_ALLOW); 485d4afb5ceSopenharmony_ci } 486d4afb5ceSopenharmony_ci pt++; 487d4afb5ceSopenharmony_ci } 488d4afb5ceSopenharmony_ci} 489d4afb5ceSopenharmony_ci 490d4afb5ceSopenharmony_ciint user_callback_handle_rxflow(lws_callback_function callback_function, 491d4afb5ceSopenharmony_ci struct lws *wsi, 492d4afb5ceSopenharmony_ci enum lws_callback_reasons reason, void *user, 493d4afb5ceSopenharmony_ci void *in, size_t len) 494d4afb5ceSopenharmony_ci{ 495d4afb5ceSopenharmony_ci int n; 496d4afb5ceSopenharmony_ci 497d4afb5ceSopenharmony_ci wsi->rxflow_will_be_applied = 1; 498d4afb5ceSopenharmony_ci n = callback_function(wsi, reason, user, in, len); 499d4afb5ceSopenharmony_ci wsi->rxflow_will_be_applied = 0; 500d4afb5ceSopenharmony_ci if (!n) 501d4afb5ceSopenharmony_ci n = __lws_rx_flow_control(wsi); 502d4afb5ceSopenharmony_ci 503d4afb5ceSopenharmony_ci return n; 504d4afb5ceSopenharmony_ci} 505d4afb5ceSopenharmony_ci 506d4afb5ceSopenharmony_ciint 507d4afb5ceSopenharmony_ci__lws_rx_flow_control(struct lws *wsi) 508d4afb5ceSopenharmony_ci{ 509d4afb5ceSopenharmony_ci struct lws *wsic = wsi->child_list; 510d4afb5ceSopenharmony_ci 511d4afb5ceSopenharmony_ci // h2 ignores rx flow control atm 512d4afb5ceSopenharmony_ci if (lwsi_role_h2(wsi) || wsi->mux_substream || 513d4afb5ceSopenharmony_ci lwsi_role_h2_ENCAPSULATION(wsi)) 514d4afb5ceSopenharmony_ci return 0; // !!! 515d4afb5ceSopenharmony_ci 516d4afb5ceSopenharmony_ci /* if he has children, do those if they were changed */ 517d4afb5ceSopenharmony_ci while (wsic) { 518d4afb5ceSopenharmony_ci if (wsic->rxflow_change_to & LWS_RXFLOW_PENDING_CHANGE) 519d4afb5ceSopenharmony_ci __lws_rx_flow_control(wsic); 520d4afb5ceSopenharmony_ci 521d4afb5ceSopenharmony_ci wsic = wsic->sibling_list; 522d4afb5ceSopenharmony_ci } 523d4afb5ceSopenharmony_ci 524d4afb5ceSopenharmony_ci /* there is no pending change */ 525d4afb5ceSopenharmony_ci if (!(wsi->rxflow_change_to & LWS_RXFLOW_PENDING_CHANGE)) 526d4afb5ceSopenharmony_ci return 0; 527d4afb5ceSopenharmony_ci 528d4afb5ceSopenharmony_ci /* stuff is still buffered, not ready to really accept new input */ 529d4afb5ceSopenharmony_ci if (lws_buflist_next_segment_len(&wsi->buflist, NULL)) { 530d4afb5ceSopenharmony_ci /* get ourselves called back to deal with stashed buffer */ 531d4afb5ceSopenharmony_ci lws_callback_on_writable(wsi); 532d4afb5ceSopenharmony_ci // return 0; 533d4afb5ceSopenharmony_ci } 534d4afb5ceSopenharmony_ci 535d4afb5ceSopenharmony_ci /* now the pending is cleared, we can change rxflow state */ 536d4afb5ceSopenharmony_ci 537d4afb5ceSopenharmony_ci wsi->rxflow_change_to &= (~LWS_RXFLOW_PENDING_CHANGE) & 3; 538d4afb5ceSopenharmony_ci 539d4afb5ceSopenharmony_ci lwsl_wsi_info(wsi, "rxflow: change_to %d", 540d4afb5ceSopenharmony_ci wsi->rxflow_change_to & LWS_RXFLOW_ALLOW); 541d4afb5ceSopenharmony_ci 542d4afb5ceSopenharmony_ci /* adjust the pollfd for this wsi */ 543d4afb5ceSopenharmony_ci 544d4afb5ceSopenharmony_ci if (wsi->rxflow_change_to & LWS_RXFLOW_ALLOW) { 545d4afb5ceSopenharmony_ci lwsl_wsi_info(wsi, "reenable POLLIN"); 546d4afb5ceSopenharmony_ci // lws_buflist_describe(&wsi->buflist, NULL, __func__); 547d4afb5ceSopenharmony_ci if (__lws_change_pollfd(wsi, 0, LWS_POLLIN)) { 548d4afb5ceSopenharmony_ci lwsl_wsi_info(wsi, "fail"); 549d4afb5ceSopenharmony_ci return -1; 550d4afb5ceSopenharmony_ci } 551d4afb5ceSopenharmony_ci } else 552d4afb5ceSopenharmony_ci if (__lws_change_pollfd(wsi, LWS_POLLIN, 0)) 553d4afb5ceSopenharmony_ci return -1; 554d4afb5ceSopenharmony_ci 555d4afb5ceSopenharmony_ci return 0; 556d4afb5ceSopenharmony_ci} 557d4afb5ceSopenharmony_ci 558d4afb5ceSopenharmony_ci 559d4afb5ceSopenharmony_ciconst struct lws_protocols * 560d4afb5ceSopenharmony_cilws_get_protocol(struct lws *wsi) 561d4afb5ceSopenharmony_ci{ 562d4afb5ceSopenharmony_ci return wsi->a.protocol; 563d4afb5ceSopenharmony_ci} 564d4afb5ceSopenharmony_ci 565d4afb5ceSopenharmony_ci 566d4afb5ceSopenharmony_ciint 567d4afb5ceSopenharmony_cilws_ensure_user_space(struct lws *wsi) 568d4afb5ceSopenharmony_ci{ 569d4afb5ceSopenharmony_ci if (!wsi->a.protocol) 570d4afb5ceSopenharmony_ci return 0; 571d4afb5ceSopenharmony_ci 572d4afb5ceSopenharmony_ci /* allocate the per-connection user memory (if any) */ 573d4afb5ceSopenharmony_ci 574d4afb5ceSopenharmony_ci if (wsi->a.protocol->per_session_data_size && !wsi->user_space) { 575d4afb5ceSopenharmony_ci wsi->user_space = lws_zalloc( 576d4afb5ceSopenharmony_ci wsi->a.protocol->per_session_data_size, "user space"); 577d4afb5ceSopenharmony_ci if (wsi->user_space == NULL) { 578d4afb5ceSopenharmony_ci lwsl_wsi_err(wsi, "OOM"); 579d4afb5ceSopenharmony_ci return 1; 580d4afb5ceSopenharmony_ci } 581d4afb5ceSopenharmony_ci } else 582d4afb5ceSopenharmony_ci lwsl_wsi_debug(wsi, "protocol pss %lu, user_space=%p", 583d4afb5ceSopenharmony_ci (long)wsi->a.protocol->per_session_data_size, 584d4afb5ceSopenharmony_ci wsi->user_space); 585d4afb5ceSopenharmony_ci return 0; 586d4afb5ceSopenharmony_ci} 587d4afb5ceSopenharmony_ci 588d4afb5ceSopenharmony_civoid * 589d4afb5ceSopenharmony_cilws_adjust_protocol_psds(struct lws *wsi, size_t new_size) 590d4afb5ceSopenharmony_ci{ 591d4afb5ceSopenharmony_ci ((struct lws_protocols *)lws_get_protocol(wsi))->per_session_data_size = 592d4afb5ceSopenharmony_ci new_size; 593d4afb5ceSopenharmony_ci 594d4afb5ceSopenharmony_ci if (lws_ensure_user_space(wsi)) 595d4afb5ceSopenharmony_ci return NULL; 596d4afb5ceSopenharmony_ci 597d4afb5ceSopenharmony_ci return wsi->user_space; 598d4afb5ceSopenharmony_ci} 599d4afb5ceSopenharmony_ci 600d4afb5ceSopenharmony_ciint 601d4afb5ceSopenharmony_cilws_get_tsi(struct lws *wsi) 602d4afb5ceSopenharmony_ci{ 603d4afb5ceSopenharmony_ci return (int)wsi->tsi; 604d4afb5ceSopenharmony_ci} 605d4afb5ceSopenharmony_ci 606d4afb5ceSopenharmony_ciint 607d4afb5ceSopenharmony_cilws_is_ssl(struct lws *wsi) 608d4afb5ceSopenharmony_ci{ 609d4afb5ceSopenharmony_ci#if defined(LWS_WITH_TLS) 610d4afb5ceSopenharmony_ci return wsi->tls.use_ssl & LCCSCF_USE_SSL; 611d4afb5ceSopenharmony_ci#else 612d4afb5ceSopenharmony_ci (void)wsi; 613d4afb5ceSopenharmony_ci return 0; 614d4afb5ceSopenharmony_ci#endif 615d4afb5ceSopenharmony_ci} 616d4afb5ceSopenharmony_ci 617d4afb5ceSopenharmony_ci#if defined(LWS_WITH_TLS) && !defined(LWS_WITH_MBEDTLS) 618d4afb5ceSopenharmony_cilws_tls_conn* 619d4afb5ceSopenharmony_cilws_get_ssl(struct lws *wsi) 620d4afb5ceSopenharmony_ci{ 621d4afb5ceSopenharmony_ci return wsi->tls.ssl; 622d4afb5ceSopenharmony_ci} 623d4afb5ceSopenharmony_ci#endif 624d4afb5ceSopenharmony_ci 625d4afb5ceSopenharmony_ciint 626d4afb5ceSopenharmony_cilws_has_buffered_out(struct lws *wsi) 627d4afb5ceSopenharmony_ci{ 628d4afb5ceSopenharmony_ci if (wsi->buflist_out) 629d4afb5ceSopenharmony_ci return 1; 630d4afb5ceSopenharmony_ci 631d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_H2) 632d4afb5ceSopenharmony_ci { 633d4afb5ceSopenharmony_ci struct lws *nwsi = lws_get_network_wsi(wsi); 634d4afb5ceSopenharmony_ci 635d4afb5ceSopenharmony_ci if (nwsi->buflist_out) 636d4afb5ceSopenharmony_ci return 1; 637d4afb5ceSopenharmony_ci } 638d4afb5ceSopenharmony_ci#endif 639d4afb5ceSopenharmony_ci 640d4afb5ceSopenharmony_ci return 0; 641d4afb5ceSopenharmony_ci} 642d4afb5ceSopenharmony_ci 643d4afb5ceSopenharmony_ciint 644d4afb5ceSopenharmony_cilws_partial_buffered(struct lws *wsi) 645d4afb5ceSopenharmony_ci{ 646d4afb5ceSopenharmony_ci return lws_has_buffered_out(wsi); 647d4afb5ceSopenharmony_ci} 648d4afb5ceSopenharmony_ci 649d4afb5ceSopenharmony_cilws_fileofs_t 650d4afb5ceSopenharmony_cilws_get_peer_write_allowance(struct lws *wsi) 651d4afb5ceSopenharmony_ci{ 652d4afb5ceSopenharmony_ci if (!lws_rops_fidx(wsi->role_ops, LWS_ROPS_tx_credit)) 653d4afb5ceSopenharmony_ci return -1; 654d4afb5ceSopenharmony_ci 655d4afb5ceSopenharmony_ci return lws_rops_func_fidx(wsi->role_ops, LWS_ROPS_tx_credit). 656d4afb5ceSopenharmony_ci tx_credit(wsi, LWSTXCR_US_TO_PEER, 0); 657d4afb5ceSopenharmony_ci} 658d4afb5ceSopenharmony_ci 659d4afb5ceSopenharmony_civoid 660d4afb5ceSopenharmony_cilws_role_transition(struct lws *wsi, enum lwsi_role role, enum lwsi_state state, 661d4afb5ceSopenharmony_ci const struct lws_role_ops *ops) 662d4afb5ceSopenharmony_ci{ 663d4afb5ceSopenharmony_ci#if (_LWS_ENABLED_LOGS & LLL_DEBUG) 664d4afb5ceSopenharmony_ci const char *name = "(unset)"; 665d4afb5ceSopenharmony_ci#endif 666d4afb5ceSopenharmony_ci wsi->wsistate = (unsigned int)role | (unsigned int)state; 667d4afb5ceSopenharmony_ci if (ops) 668d4afb5ceSopenharmony_ci wsi->role_ops = ops; 669d4afb5ceSopenharmony_ci#if (_LWS_ENABLED_LOGS & LLL_DEBUG) 670d4afb5ceSopenharmony_ci if (wsi->role_ops) 671d4afb5ceSopenharmony_ci name = wsi->role_ops->name; 672d4afb5ceSopenharmony_ci lwsl_wsi_debug(wsi, "wsistate 0x%lx, ops %s", 673d4afb5ceSopenharmony_ci (unsigned long)wsi->wsistate, name); 674d4afb5ceSopenharmony_ci#endif 675d4afb5ceSopenharmony_ci} 676d4afb5ceSopenharmony_ci 677d4afb5ceSopenharmony_ciint 678d4afb5ceSopenharmony_cilws_parse_uri(char *p, const char **prot, const char **ads, int *port, 679d4afb5ceSopenharmony_ci const char **path) 680d4afb5ceSopenharmony_ci{ 681d4afb5ceSopenharmony_ci const char *end; 682d4afb5ceSopenharmony_ci char unix_skt = 0; 683d4afb5ceSopenharmony_ci 684d4afb5ceSopenharmony_ci /* cut up the location into address, port and path */ 685d4afb5ceSopenharmony_ci *prot = p; 686d4afb5ceSopenharmony_ci while (*p && (*p != ':' || p[1] != '/' || p[2] != '/')) 687d4afb5ceSopenharmony_ci p++; 688d4afb5ceSopenharmony_ci if (!*p) { 689d4afb5ceSopenharmony_ci end = p; 690d4afb5ceSopenharmony_ci p = (char *)*prot; 691d4afb5ceSopenharmony_ci *prot = end; 692d4afb5ceSopenharmony_ci } else { 693d4afb5ceSopenharmony_ci *p = '\0'; 694d4afb5ceSopenharmony_ci p += 3; 695d4afb5ceSopenharmony_ci } 696d4afb5ceSopenharmony_ci if (*p == '+') /* unix skt */ 697d4afb5ceSopenharmony_ci unix_skt = 1; 698d4afb5ceSopenharmony_ci 699d4afb5ceSopenharmony_ci *ads = p; 700d4afb5ceSopenharmony_ci if (!strcmp(*prot, "http") || !strcmp(*prot, "ws")) 701d4afb5ceSopenharmony_ci *port = 80; 702d4afb5ceSopenharmony_ci else if (!strcmp(*prot, "https") || !strcmp(*prot, "wss")) 703d4afb5ceSopenharmony_ci *port = 443; 704d4afb5ceSopenharmony_ci 705d4afb5ceSopenharmony_ci if (*p == '[') { 706d4afb5ceSopenharmony_ci ++(*ads); 707d4afb5ceSopenharmony_ci while (*p && *p != ']') 708d4afb5ceSopenharmony_ci p++; 709d4afb5ceSopenharmony_ci if (*p) 710d4afb5ceSopenharmony_ci *p++ = '\0'; 711d4afb5ceSopenharmony_ci } else 712d4afb5ceSopenharmony_ci while (*p && *p != ':' && (unix_skt || *p != '/')) 713d4afb5ceSopenharmony_ci p++; 714d4afb5ceSopenharmony_ci 715d4afb5ceSopenharmony_ci if (*p == ':') { 716d4afb5ceSopenharmony_ci *p++ = '\0'; 717d4afb5ceSopenharmony_ci *port = atoi(p); 718d4afb5ceSopenharmony_ci while (*p && *p != '/') 719d4afb5ceSopenharmony_ci p++; 720d4afb5ceSopenharmony_ci } 721d4afb5ceSopenharmony_ci *path = "/"; 722d4afb5ceSopenharmony_ci if (*p) { 723d4afb5ceSopenharmony_ci *p++ = '\0'; 724d4afb5ceSopenharmony_ci if (*p) 725d4afb5ceSopenharmony_ci *path = p; 726d4afb5ceSopenharmony_ci } 727d4afb5ceSopenharmony_ci 728d4afb5ceSopenharmony_ci return 0; 729d4afb5ceSopenharmony_ci} 730d4afb5ceSopenharmony_ci 731d4afb5ceSopenharmony_ci/* ... */ 732d4afb5ceSopenharmony_ci 733d4afb5ceSopenharmony_ciint 734d4afb5ceSopenharmony_cilws_get_urlarg_by_name_safe(struct lws *wsi, const char *name, char *buf, int len) 735d4afb5ceSopenharmony_ci{ 736d4afb5ceSopenharmony_ci int n = 0, fraglen, sl = (int)strlen(name); 737d4afb5ceSopenharmony_ci 738d4afb5ceSopenharmony_ci do { 739d4afb5ceSopenharmony_ci fraglen = lws_hdr_copy_fragment(wsi, buf, len, 740d4afb5ceSopenharmony_ci WSI_TOKEN_HTTP_URI_ARGS, n); 741d4afb5ceSopenharmony_ci 742d4afb5ceSopenharmony_ci if (fraglen < 0) 743d4afb5ceSopenharmony_ci break; 744d4afb5ceSopenharmony_ci 745d4afb5ceSopenharmony_ci if (fraglen + 1 < len && 746d4afb5ceSopenharmony_ci fraglen >= sl && 747d4afb5ceSopenharmony_ci !strncmp(buf, name, (size_t)sl)) { 748d4afb5ceSopenharmony_ci /* 749d4afb5ceSopenharmony_ci * If he left off the trailing =, trim it from the 750d4afb5ceSopenharmony_ci * result 751d4afb5ceSopenharmony_ci */ 752d4afb5ceSopenharmony_ci 753d4afb5ceSopenharmony_ci if (name[sl - 1] != '=' && 754d4afb5ceSopenharmony_ci sl < fraglen && 755d4afb5ceSopenharmony_ci buf[sl] == '=') 756d4afb5ceSopenharmony_ci sl++; 757d4afb5ceSopenharmony_ci 758d4afb5ceSopenharmony_ci memmove(buf, buf + sl, (size_t)(fraglen - sl)); 759d4afb5ceSopenharmony_ci buf[fraglen - sl] = '\0'; 760d4afb5ceSopenharmony_ci 761d4afb5ceSopenharmony_ci return fraglen - sl; 762d4afb5ceSopenharmony_ci } 763d4afb5ceSopenharmony_ci 764d4afb5ceSopenharmony_ci n++; 765d4afb5ceSopenharmony_ci } while (1); 766d4afb5ceSopenharmony_ci 767d4afb5ceSopenharmony_ci return -1; 768d4afb5ceSopenharmony_ci} 769d4afb5ceSopenharmony_ci 770d4afb5ceSopenharmony_ciconst char * 771d4afb5ceSopenharmony_cilws_get_urlarg_by_name(struct lws *wsi, const char *name, char *buf, int len) 772d4afb5ceSopenharmony_ci{ 773d4afb5ceSopenharmony_ci int n = lws_get_urlarg_by_name_safe(wsi, name, buf, len); 774d4afb5ceSopenharmony_ci 775d4afb5ceSopenharmony_ci return n < 0 ? NULL : buf; 776d4afb5ceSopenharmony_ci} 777d4afb5ceSopenharmony_ci 778d4afb5ceSopenharmony_ci 779d4afb5ceSopenharmony_ci#if defined(LWS_WITHOUT_EXTENSIONS) 780d4afb5ceSopenharmony_ci 781d4afb5ceSopenharmony_ci/* we need to provide dummy callbacks for internal exts 782d4afb5ceSopenharmony_ci * so user code runs when faced with a lib compiled with 783d4afb5ceSopenharmony_ci * extensions disabled. 784d4afb5ceSopenharmony_ci */ 785d4afb5ceSopenharmony_ci 786d4afb5ceSopenharmony_ciint 787d4afb5ceSopenharmony_cilws_extension_callback_pm_deflate(struct lws_context *context, 788d4afb5ceSopenharmony_ci const struct lws_extension *ext, 789d4afb5ceSopenharmony_ci struct lws *wsi, 790d4afb5ceSopenharmony_ci enum lws_extension_callback_reasons reason, 791d4afb5ceSopenharmony_ci void *user, void *in, size_t len) 792d4afb5ceSopenharmony_ci{ 793d4afb5ceSopenharmony_ci (void)context; 794d4afb5ceSopenharmony_ci (void)ext; 795d4afb5ceSopenharmony_ci (void)wsi; 796d4afb5ceSopenharmony_ci (void)reason; 797d4afb5ceSopenharmony_ci (void)user; 798d4afb5ceSopenharmony_ci (void)in; 799d4afb5ceSopenharmony_ci (void)len; 800d4afb5ceSopenharmony_ci 801d4afb5ceSopenharmony_ci return 0; 802d4afb5ceSopenharmony_ci} 803d4afb5ceSopenharmony_ci 804d4afb5ceSopenharmony_ciint 805d4afb5ceSopenharmony_cilws_set_extension_option(struct lws *wsi, const char *ext_name, 806d4afb5ceSopenharmony_ci const char *opt_name, const char *opt_val) 807d4afb5ceSopenharmony_ci{ 808d4afb5ceSopenharmony_ci return -1; 809d4afb5ceSopenharmony_ci} 810d4afb5ceSopenharmony_ci#endif 811d4afb5ceSopenharmony_ci 812d4afb5ceSopenharmony_ciint 813d4afb5ceSopenharmony_cilws_is_cgi(struct lws *wsi) { 814d4afb5ceSopenharmony_ci#ifdef LWS_WITH_CGI 815d4afb5ceSopenharmony_ci return !!wsi->http.cgi; 816d4afb5ceSopenharmony_ci#else 817d4afb5ceSopenharmony_ci return 0; 818d4afb5ceSopenharmony_ci#endif 819d4afb5ceSopenharmony_ci} 820d4afb5ceSopenharmony_ci 821d4afb5ceSopenharmony_ciconst struct lws_protocol_vhost_options * 822d4afb5ceSopenharmony_cilws_pvo_search(const struct lws_protocol_vhost_options *pvo, const char *name) 823d4afb5ceSopenharmony_ci{ 824d4afb5ceSopenharmony_ci while (pvo) { 825d4afb5ceSopenharmony_ci if (!strcmp(pvo->name, name)) 826d4afb5ceSopenharmony_ci break; 827d4afb5ceSopenharmony_ci 828d4afb5ceSopenharmony_ci pvo = pvo->next; 829d4afb5ceSopenharmony_ci } 830d4afb5ceSopenharmony_ci 831d4afb5ceSopenharmony_ci return pvo; 832d4afb5ceSopenharmony_ci} 833d4afb5ceSopenharmony_ci 834d4afb5ceSopenharmony_ciint 835d4afb5ceSopenharmony_cilws_pvo_get_str(void *in, const char *name, const char **result) 836d4afb5ceSopenharmony_ci{ 837d4afb5ceSopenharmony_ci const struct lws_protocol_vhost_options *pv = 838d4afb5ceSopenharmony_ci lws_pvo_search((const struct lws_protocol_vhost_options *)in, 839d4afb5ceSopenharmony_ci name); 840d4afb5ceSopenharmony_ci 841d4afb5ceSopenharmony_ci if (!pv) 842d4afb5ceSopenharmony_ci return 1; 843d4afb5ceSopenharmony_ci 844d4afb5ceSopenharmony_ci *result = (const char *)pv->value; 845d4afb5ceSopenharmony_ci 846d4afb5ceSopenharmony_ci return 0; 847d4afb5ceSopenharmony_ci} 848d4afb5ceSopenharmony_ci 849d4afb5ceSopenharmony_ciint 850d4afb5ceSopenharmony_cilws_broadcast(struct lws_context_per_thread *pt, int reason, void *in, size_t len) 851d4afb5ceSopenharmony_ci{ 852d4afb5ceSopenharmony_ci struct lws_vhost *v = pt->context->vhost_list; 853d4afb5ceSopenharmony_ci lws_fakewsi_def_plwsa(pt); 854d4afb5ceSopenharmony_ci int n, ret = 0; 855d4afb5ceSopenharmony_ci 856d4afb5ceSopenharmony_ci lws_fakewsi_prep_plwsa_ctx(pt->context); 857d4afb5ceSopenharmony_ci#if !defined(LWS_PLAT_FREERTOS) && LWS_MAX_SMP > 1 858d4afb5ceSopenharmony_ci ((struct lws *)plwsa)->tsi = (char)(int)(pt - &pt->context->pt[0]); 859d4afb5ceSopenharmony_ci#endif 860d4afb5ceSopenharmony_ci 861d4afb5ceSopenharmony_ci while (v) { 862d4afb5ceSopenharmony_ci const struct lws_protocols *p = v->protocols; 863d4afb5ceSopenharmony_ci 864d4afb5ceSopenharmony_ci plwsa->vhost = v; /* not a real bound wsi */ 865d4afb5ceSopenharmony_ci 866d4afb5ceSopenharmony_ci for (n = 0; n < v->count_protocols; n++) { 867d4afb5ceSopenharmony_ci plwsa->protocol = p; 868d4afb5ceSopenharmony_ci if (p->callback && 869d4afb5ceSopenharmony_ci p->callback((struct lws *)plwsa, (enum lws_callback_reasons)reason, NULL, in, len)) 870d4afb5ceSopenharmony_ci ret |= 1; 871d4afb5ceSopenharmony_ci p++; 872d4afb5ceSopenharmony_ci } 873d4afb5ceSopenharmony_ci 874d4afb5ceSopenharmony_ci v = v->vhost_next; 875d4afb5ceSopenharmony_ci } 876d4afb5ceSopenharmony_ci 877d4afb5ceSopenharmony_ci return ret; 878d4afb5ceSopenharmony_ci} 879d4afb5ceSopenharmony_ci 880d4afb5ceSopenharmony_civoid * 881d4afb5ceSopenharmony_cilws_wsi_user(struct lws *wsi) 882d4afb5ceSopenharmony_ci{ 883d4afb5ceSopenharmony_ci return wsi->user_space; 884d4afb5ceSopenharmony_ci} 885d4afb5ceSopenharmony_ci 886d4afb5ceSopenharmony_ciint 887d4afb5ceSopenharmony_cilws_wsi_tsi(struct lws *wsi) 888d4afb5ceSopenharmony_ci{ 889d4afb5ceSopenharmony_ci return wsi->tsi; 890d4afb5ceSopenharmony_ci} 891d4afb5ceSopenharmony_ci 892d4afb5ceSopenharmony_ci 893d4afb5ceSopenharmony_civoid 894d4afb5ceSopenharmony_cilws_set_wsi_user(struct lws *wsi, void *data) 895d4afb5ceSopenharmony_ci{ 896d4afb5ceSopenharmony_ci if (!wsi->user_space_externally_allocated && wsi->user_space) 897d4afb5ceSopenharmony_ci lws_free(wsi->user_space); 898d4afb5ceSopenharmony_ci 899d4afb5ceSopenharmony_ci wsi->user_space_externally_allocated = 1; 900d4afb5ceSopenharmony_ci wsi->user_space = data; 901d4afb5ceSopenharmony_ci} 902d4afb5ceSopenharmony_ci 903d4afb5ceSopenharmony_cistruct lws * 904d4afb5ceSopenharmony_cilws_get_parent(const struct lws *wsi) 905d4afb5ceSopenharmony_ci{ 906d4afb5ceSopenharmony_ci return wsi->parent; 907d4afb5ceSopenharmony_ci} 908d4afb5ceSopenharmony_ci 909d4afb5ceSopenharmony_cistruct lws * 910d4afb5ceSopenharmony_cilws_get_child(const struct lws *wsi) 911d4afb5ceSopenharmony_ci{ 912d4afb5ceSopenharmony_ci return wsi->child_list; 913d4afb5ceSopenharmony_ci} 914d4afb5ceSopenharmony_ci 915d4afb5ceSopenharmony_civoid * 916d4afb5ceSopenharmony_cilws_get_opaque_parent_data(const struct lws *wsi) 917d4afb5ceSopenharmony_ci{ 918d4afb5ceSopenharmony_ci return wsi->opaque_parent_data; 919d4afb5ceSopenharmony_ci} 920d4afb5ceSopenharmony_ci 921d4afb5ceSopenharmony_civoid 922d4afb5ceSopenharmony_cilws_set_opaque_parent_data(struct lws *wsi, void *data) 923d4afb5ceSopenharmony_ci{ 924d4afb5ceSopenharmony_ci wsi->opaque_parent_data = data; 925d4afb5ceSopenharmony_ci} 926d4afb5ceSopenharmony_ci 927d4afb5ceSopenharmony_civoid * 928d4afb5ceSopenharmony_cilws_get_opaque_user_data(const struct lws *wsi) 929d4afb5ceSopenharmony_ci{ 930d4afb5ceSopenharmony_ci return wsi->a.opaque_user_data; 931d4afb5ceSopenharmony_ci} 932d4afb5ceSopenharmony_ci 933d4afb5ceSopenharmony_civoid 934d4afb5ceSopenharmony_cilws_set_opaque_user_data(struct lws *wsi, void *data) 935d4afb5ceSopenharmony_ci{ 936d4afb5ceSopenharmony_ci wsi->a.opaque_user_data = data; 937d4afb5ceSopenharmony_ci} 938d4afb5ceSopenharmony_ci 939d4afb5ceSopenharmony_ciint 940d4afb5ceSopenharmony_cilws_get_child_pending_on_writable(const struct lws *wsi) 941d4afb5ceSopenharmony_ci{ 942d4afb5ceSopenharmony_ci return wsi->parent_pending_cb_on_writable; 943d4afb5ceSopenharmony_ci} 944d4afb5ceSopenharmony_ci 945d4afb5ceSopenharmony_civoid 946d4afb5ceSopenharmony_cilws_clear_child_pending_on_writable(struct lws *wsi) 947d4afb5ceSopenharmony_ci{ 948d4afb5ceSopenharmony_ci wsi->parent_pending_cb_on_writable = 0; 949d4afb5ceSopenharmony_ci} 950d4afb5ceSopenharmony_ci 951d4afb5ceSopenharmony_ci 952d4afb5ceSopenharmony_ci 953d4afb5ceSopenharmony_ciconst char * 954d4afb5ceSopenharmony_cilws_get_vhost_name(struct lws_vhost *vhost) 955d4afb5ceSopenharmony_ci{ 956d4afb5ceSopenharmony_ci return vhost->name; 957d4afb5ceSopenharmony_ci} 958d4afb5ceSopenharmony_ci 959d4afb5ceSopenharmony_ciint 960d4afb5ceSopenharmony_cilws_get_vhost_port(struct lws_vhost *vhost) 961d4afb5ceSopenharmony_ci{ 962d4afb5ceSopenharmony_ci return vhost->listen_port; 963d4afb5ceSopenharmony_ci} 964d4afb5ceSopenharmony_ci 965d4afb5ceSopenharmony_civoid * 966d4afb5ceSopenharmony_cilws_get_vhost_user(struct lws_vhost *vhost) 967d4afb5ceSopenharmony_ci{ 968d4afb5ceSopenharmony_ci return vhost->user; 969d4afb5ceSopenharmony_ci} 970d4afb5ceSopenharmony_ci 971d4afb5ceSopenharmony_ciconst char * 972d4afb5ceSopenharmony_cilws_get_vhost_iface(struct lws_vhost *vhost) 973d4afb5ceSopenharmony_ci{ 974d4afb5ceSopenharmony_ci return vhost->iface; 975d4afb5ceSopenharmony_ci} 976d4afb5ceSopenharmony_ci 977d4afb5ceSopenharmony_cilws_sockfd_type 978d4afb5ceSopenharmony_cilws_get_socket_fd(struct lws *wsi) 979d4afb5ceSopenharmony_ci{ 980d4afb5ceSopenharmony_ci if (!wsi) 981d4afb5ceSopenharmony_ci return -1; 982d4afb5ceSopenharmony_ci return wsi->desc.sockfd; 983d4afb5ceSopenharmony_ci} 984d4afb5ceSopenharmony_ci 985d4afb5ceSopenharmony_ci 986d4afb5ceSopenharmony_cistruct lws_vhost * 987d4afb5ceSopenharmony_cilws_vhost_get(struct lws *wsi) 988d4afb5ceSopenharmony_ci{ 989d4afb5ceSopenharmony_ci return wsi->a.vhost; 990d4afb5ceSopenharmony_ci} 991d4afb5ceSopenharmony_ci 992d4afb5ceSopenharmony_cistruct lws_vhost * 993d4afb5ceSopenharmony_cilws_get_vhost(struct lws *wsi) 994d4afb5ceSopenharmony_ci{ 995d4afb5ceSopenharmony_ci return wsi->a.vhost; 996d4afb5ceSopenharmony_ci} 997d4afb5ceSopenharmony_ci 998d4afb5ceSopenharmony_ciconst struct lws_protocols * 999d4afb5ceSopenharmony_cilws_protocol_get(struct lws *wsi) 1000d4afb5ceSopenharmony_ci{ 1001d4afb5ceSopenharmony_ci return wsi->a.protocol; 1002d4afb5ceSopenharmony_ci} 1003d4afb5ceSopenharmony_ci 1004d4afb5ceSopenharmony_ci#if defined(LWS_WITH_UDP) 1005d4afb5ceSopenharmony_ciconst struct lws_udp * 1006d4afb5ceSopenharmony_cilws_get_udp(const struct lws *wsi) 1007d4afb5ceSopenharmony_ci{ 1008d4afb5ceSopenharmony_ci return wsi->udp; 1009d4afb5ceSopenharmony_ci} 1010d4afb5ceSopenharmony_ci#endif 1011d4afb5ceSopenharmony_ci 1012d4afb5ceSopenharmony_cistruct lws_context * 1013d4afb5ceSopenharmony_cilws_get_context(const struct lws *wsi) 1014d4afb5ceSopenharmony_ci{ 1015d4afb5ceSopenharmony_ci return wsi->a.context; 1016d4afb5ceSopenharmony_ci} 1017d4afb5ceSopenharmony_ci 1018d4afb5ceSopenharmony_cistruct lws_log_cx * 1019d4afb5ceSopenharmony_cilwsl_wsi_get_cx(struct lws *wsi) 1020d4afb5ceSopenharmony_ci{ 1021d4afb5ceSopenharmony_ci if (!wsi) 1022d4afb5ceSopenharmony_ci return NULL; 1023d4afb5ceSopenharmony_ci 1024d4afb5ceSopenharmony_ci return wsi->lc.log_cx; 1025d4afb5ceSopenharmony_ci} 1026d4afb5ceSopenharmony_ci 1027d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CLIENT) 1028d4afb5ceSopenharmony_ciint 1029d4afb5ceSopenharmony_ci_lws_generic_transaction_completed_active_conn(struct lws **_wsi, char take_vh_lock) 1030d4afb5ceSopenharmony_ci{ 1031d4afb5ceSopenharmony_ci struct lws *wnew, *wsi = *_wsi; 1032d4afb5ceSopenharmony_ci 1033d4afb5ceSopenharmony_ci /* 1034d4afb5ceSopenharmony_ci * Are we constitutionally capable of having a queue, ie, we are on 1035d4afb5ceSopenharmony_ci * the "active client connections" list? 1036d4afb5ceSopenharmony_ci * 1037d4afb5ceSopenharmony_ci * If not, that's it for us. 1038d4afb5ceSopenharmony_ci */ 1039d4afb5ceSopenharmony_ci 1040d4afb5ceSopenharmony_ci if (lws_dll2_is_detached(&wsi->dll_cli_active_conns)) 1041d4afb5ceSopenharmony_ci return 0; /* no new transaction */ 1042d4afb5ceSopenharmony_ci 1043d4afb5ceSopenharmony_ci /* 1044d4afb5ceSopenharmony_ci * With h1 queuing, the original "active client" moves his attributes 1045d4afb5ceSopenharmony_ci * like fd, ssl, queue and active client list entry to the next guy in 1046d4afb5ceSopenharmony_ci * the queue before closing... it's because the user code knows the 1047d4afb5ceSopenharmony_ci * individual wsi and the action must take place in the correct wsi 1048d4afb5ceSopenharmony_ci * context. Note this means we don't truly pipeline headers. 1049d4afb5ceSopenharmony_ci * 1050d4afb5ceSopenharmony_ci * Trying to keep the original "active client" in place to do the work 1051d4afb5ceSopenharmony_ci * of the wsi breaks down when dealing with queued POSTs otherwise; it's 1052d4afb5ceSopenharmony_ci * also competing with the real mux child arrangements and complicating 1053d4afb5ceSopenharmony_ci * the code. 1054d4afb5ceSopenharmony_ci * 1055d4afb5ceSopenharmony_ci * For that reason, see if we have any queued child now... 1056d4afb5ceSopenharmony_ci */ 1057d4afb5ceSopenharmony_ci 1058d4afb5ceSopenharmony_ci if (!wsi->dll2_cli_txn_queue_owner.head) { 1059d4afb5ceSopenharmony_ci /* 1060d4afb5ceSopenharmony_ci * Nothing pipelined... we should hang around a bit 1061d4afb5ceSopenharmony_ci * in case something turns up... otherwise we'll close 1062d4afb5ceSopenharmony_ci */ 1063d4afb5ceSopenharmony_ci lwsl_wsi_info(wsi, "nothing pipelined waiting"); 1064d4afb5ceSopenharmony_ci lwsi_set_state(wsi, LRS_IDLING); 1065d4afb5ceSopenharmony_ci 1066d4afb5ceSopenharmony_ci lws_set_timeout(wsi, PENDING_TIMEOUT_CLIENT_CONN_IDLE, 1067d4afb5ceSopenharmony_ci wsi->keep_warm_secs); 1068d4afb5ceSopenharmony_ci 1069d4afb5ceSopenharmony_ci return 0; /* no new transaction right now */ 1070d4afb5ceSopenharmony_ci } 1071d4afb5ceSopenharmony_ci 1072d4afb5ceSopenharmony_ci /* 1073d4afb5ceSopenharmony_ci * We have a queued child wsi we should bequeath our assets to, before 1074d4afb5ceSopenharmony_ci * closing ourself 1075d4afb5ceSopenharmony_ci */ 1076d4afb5ceSopenharmony_ci 1077d4afb5ceSopenharmony_ci if (take_vh_lock) 1078d4afb5ceSopenharmony_ci lws_vhost_lock(wsi->a.vhost); 1079d4afb5ceSopenharmony_ci 1080d4afb5ceSopenharmony_ci wnew = lws_container_of(wsi->dll2_cli_txn_queue_owner.head, struct lws, 1081d4afb5ceSopenharmony_ci dll2_cli_txn_queue); 1082d4afb5ceSopenharmony_ci 1083d4afb5ceSopenharmony_ci assert(wsi != wnew); 1084d4afb5ceSopenharmony_ci 1085d4afb5ceSopenharmony_ci lws_dll2_remove(&wnew->dll2_cli_txn_queue); 1086d4afb5ceSopenharmony_ci 1087d4afb5ceSopenharmony_ci assert(lws_socket_is_valid(wsi->desc.sockfd)); 1088d4afb5ceSopenharmony_ci 1089d4afb5ceSopenharmony_ci __lws_change_pollfd(wsi, LWS_POLLOUT | LWS_POLLIN, 0); 1090d4afb5ceSopenharmony_ci 1091d4afb5ceSopenharmony_ci /* copy the fd */ 1092d4afb5ceSopenharmony_ci wnew->desc = wsi->desc; 1093d4afb5ceSopenharmony_ci 1094d4afb5ceSopenharmony_ci assert(lws_socket_is_valid(wnew->desc.sockfd)); 1095d4afb5ceSopenharmony_ci 1096d4afb5ceSopenharmony_ci /* disconnect the fd from association with old wsi */ 1097d4afb5ceSopenharmony_ci 1098d4afb5ceSopenharmony_ci if (__remove_wsi_socket_from_fds(wsi)) 1099d4afb5ceSopenharmony_ci return -1; 1100d4afb5ceSopenharmony_ci 1101d4afb5ceSopenharmony_ci sanity_assert_no_wsi_traces(wsi->a.context, wsi); 1102d4afb5ceSopenharmony_ci sanity_assert_no_sockfd_traces(wsi->a.context, wsi->desc.sockfd); 1103d4afb5ceSopenharmony_ci wsi->desc.sockfd = LWS_SOCK_INVALID; 1104d4afb5ceSopenharmony_ci 1105d4afb5ceSopenharmony_ci __lws_wsi_remove_from_sul(wsi); 1106d4afb5ceSopenharmony_ci 1107d4afb5ceSopenharmony_ci /* 1108d4afb5ceSopenharmony_ci * ... we're doing some magic here in terms of handing off the socket 1109d4afb5ceSopenharmony_ci * that has been active to a wsi that has not yet itself been active... 1110d4afb5ceSopenharmony_ci * depending on the event lib we may need to give a magic spark to the 1111d4afb5ceSopenharmony_ci * new guy and snuff out the old guy's magic spark at that level as well 1112d4afb5ceSopenharmony_ci */ 1113d4afb5ceSopenharmony_ci 1114d4afb5ceSopenharmony_ci#if defined(LWS_WITH_EVENT_LIBS) 1115d4afb5ceSopenharmony_ci if (wsi->a.context->event_loop_ops->destroy_wsi) 1116d4afb5ceSopenharmony_ci wsi->a.context->event_loop_ops->destroy_wsi(wsi); 1117d4afb5ceSopenharmony_ci if (wsi->a.context->event_loop_ops->sock_accept) 1118d4afb5ceSopenharmony_ci wsi->a.context->event_loop_ops->sock_accept(wnew); 1119d4afb5ceSopenharmony_ci#endif 1120d4afb5ceSopenharmony_ci 1121d4afb5ceSopenharmony_ci /* point the fd table entry to new guy */ 1122d4afb5ceSopenharmony_ci 1123d4afb5ceSopenharmony_ci assert(lws_socket_is_valid(wnew->desc.sockfd)); 1124d4afb5ceSopenharmony_ci 1125d4afb5ceSopenharmony_ci if (__insert_wsi_socket_into_fds(wsi->a.context, wnew)) 1126d4afb5ceSopenharmony_ci return -1; 1127d4afb5ceSopenharmony_ci 1128d4afb5ceSopenharmony_ci#if defined(LWS_WITH_TLS) 1129d4afb5ceSopenharmony_ci /* pass on the tls */ 1130d4afb5ceSopenharmony_ci 1131d4afb5ceSopenharmony_ci wnew->tls = wsi->tls; 1132d4afb5ceSopenharmony_ci wsi->tls.client_bio = NULL; 1133d4afb5ceSopenharmony_ci wsi->tls.ssl = NULL; 1134d4afb5ceSopenharmony_ci wsi->tls.use_ssl = 0; 1135d4afb5ceSopenharmony_ci#endif 1136d4afb5ceSopenharmony_ci 1137d4afb5ceSopenharmony_ci /* take over his copy of his endpoint as an active connection */ 1138d4afb5ceSopenharmony_ci 1139d4afb5ceSopenharmony_ci if (!wnew->cli_hostname_copy && wsi->cli_hostname_copy) { 1140d4afb5ceSopenharmony_ci wnew->cli_hostname_copy = wsi->cli_hostname_copy; 1141d4afb5ceSopenharmony_ci wsi->cli_hostname_copy = NULL; 1142d4afb5ceSopenharmony_ci } 1143d4afb5ceSopenharmony_ci wnew->keep_warm_secs = wsi->keep_warm_secs; 1144d4afb5ceSopenharmony_ci 1145d4afb5ceSopenharmony_ci /* 1146d4afb5ceSopenharmony_ci * selected queued guy now replaces the original leader on the 1147d4afb5ceSopenharmony_ci * active client conn list 1148d4afb5ceSopenharmony_ci */ 1149d4afb5ceSopenharmony_ci 1150d4afb5ceSopenharmony_ci lws_dll2_remove(&wsi->dll_cli_active_conns); 1151d4afb5ceSopenharmony_ci lws_dll2_add_tail(&wnew->dll_cli_active_conns, 1152d4afb5ceSopenharmony_ci &wsi->a.vhost->dll_cli_active_conns_owner); 1153d4afb5ceSopenharmony_ci 1154d4afb5ceSopenharmony_ci /* move any queued guys to queue on new active conn */ 1155d4afb5ceSopenharmony_ci 1156d4afb5ceSopenharmony_ci lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, 1157d4afb5ceSopenharmony_ci wsi->dll2_cli_txn_queue_owner.head) { 1158d4afb5ceSopenharmony_ci struct lws *ww = lws_container_of(d, struct lws, 1159d4afb5ceSopenharmony_ci dll2_cli_txn_queue); 1160d4afb5ceSopenharmony_ci 1161d4afb5ceSopenharmony_ci lws_dll2_remove(&ww->dll2_cli_txn_queue); 1162d4afb5ceSopenharmony_ci lws_dll2_add_tail(&ww->dll2_cli_txn_queue, 1163d4afb5ceSopenharmony_ci &wnew->dll2_cli_txn_queue_owner); 1164d4afb5ceSopenharmony_ci 1165d4afb5ceSopenharmony_ci } lws_end_foreach_dll_safe(d, d1); 1166d4afb5ceSopenharmony_ci 1167d4afb5ceSopenharmony_ci if (take_vh_lock) 1168d4afb5ceSopenharmony_ci lws_vhost_unlock(wsi->a.vhost); 1169d4afb5ceSopenharmony_ci 1170d4afb5ceSopenharmony_ci /* 1171d4afb5ceSopenharmony_ci * The original leader who passed on all his powers already can die... 1172d4afb5ceSopenharmony_ci * in the call stack above us there are guys who still want to touch 1173d4afb5ceSopenharmony_ci * him, so have him die next time around the event loop, not now. 1174d4afb5ceSopenharmony_ci */ 1175d4afb5ceSopenharmony_ci 1176d4afb5ceSopenharmony_ci wsi->already_did_cce = 1; /* so the close doesn't trigger a CCE */ 1177d4afb5ceSopenharmony_ci lws_set_timeout(wsi, 1, LWS_TO_KILL_ASYNC); 1178d4afb5ceSopenharmony_ci 1179d4afb5ceSopenharmony_ci /* after the first one, they can only be coming from the queue */ 1180d4afb5ceSopenharmony_ci wnew->transaction_from_pipeline_queue = 1; 1181d4afb5ceSopenharmony_ci 1182d4afb5ceSopenharmony_ci lwsl_wsi_notice(wsi, " pipeline queue passed -> %s", lws_wsi_tag(wnew)); 1183d4afb5ceSopenharmony_ci 1184d4afb5ceSopenharmony_ci *_wsi = wnew; /* inform caller we swapped */ 1185d4afb5ceSopenharmony_ci 1186d4afb5ceSopenharmony_ci return 1; /* new transaction */ 1187d4afb5ceSopenharmony_ci} 1188d4afb5ceSopenharmony_ci#endif 1189d4afb5ceSopenharmony_ci 1190d4afb5ceSopenharmony_ciint LWS_WARN_UNUSED_RESULT 1191d4afb5ceSopenharmony_cilws_raw_transaction_completed(struct lws *wsi) 1192d4afb5ceSopenharmony_ci{ 1193d4afb5ceSopenharmony_ci if (lws_has_buffered_out(wsi)) { 1194d4afb5ceSopenharmony_ci /* 1195d4afb5ceSopenharmony_ci * ...so he tried to send something large, but it went out 1196d4afb5ceSopenharmony_ci * as a partial, but he immediately called us to say he wants 1197d4afb5ceSopenharmony_ci * to close the connection. 1198d4afb5ceSopenharmony_ci * 1199d4afb5ceSopenharmony_ci * Defer the close until the last part of the partial is sent. 1200d4afb5ceSopenharmony_ci * 1201d4afb5ceSopenharmony_ci */ 1202d4afb5ceSopenharmony_ci 1203d4afb5ceSopenharmony_ci lwsl_wsi_debug(wsi, "deferring due to partial"); 1204d4afb5ceSopenharmony_ci wsi->close_when_buffered_out_drained = 1; 1205d4afb5ceSopenharmony_ci lws_callback_on_writable(wsi); 1206d4afb5ceSopenharmony_ci 1207d4afb5ceSopenharmony_ci return 0; 1208d4afb5ceSopenharmony_ci } 1209d4afb5ceSopenharmony_ci 1210d4afb5ceSopenharmony_ci return -1; 1211d4afb5ceSopenharmony_ci} 1212d4afb5ceSopenharmony_ci 1213d4afb5ceSopenharmony_ciint 1214d4afb5ceSopenharmony_cilws_bind_protocol(struct lws *wsi, const struct lws_protocols *p, 1215d4afb5ceSopenharmony_ci const char *reason) 1216d4afb5ceSopenharmony_ci{ 1217d4afb5ceSopenharmony_ci// if (wsi->a.protocol == p) 1218d4afb5ceSopenharmony_ci// return 0; 1219d4afb5ceSopenharmony_ci const struct lws_protocols *vp = wsi->a.vhost->protocols, *vpo; 1220d4afb5ceSopenharmony_ci 1221d4afb5ceSopenharmony_ci if (wsi->a.protocol && wsi->protocol_bind_balance) { 1222d4afb5ceSopenharmony_ci wsi->a.protocol->callback(wsi, 1223d4afb5ceSopenharmony_ci wsi->role_ops->protocol_unbind_cb[!!lwsi_role_server(wsi)], 1224d4afb5ceSopenharmony_ci wsi->user_space, (void *)reason, 0); 1225d4afb5ceSopenharmony_ci wsi->protocol_bind_balance = 0; 1226d4afb5ceSopenharmony_ci } 1227d4afb5ceSopenharmony_ci if (!wsi->user_space_externally_allocated) 1228d4afb5ceSopenharmony_ci lws_free_set_NULL(wsi->user_space); 1229d4afb5ceSopenharmony_ci 1230d4afb5ceSopenharmony_ci lws_same_vh_protocol_remove(wsi); 1231d4afb5ceSopenharmony_ci 1232d4afb5ceSopenharmony_ci wsi->a.protocol = p; 1233d4afb5ceSopenharmony_ci if (!p) 1234d4afb5ceSopenharmony_ci return 0; 1235d4afb5ceSopenharmony_ci 1236d4afb5ceSopenharmony_ci if (lws_ensure_user_space(wsi)) 1237d4afb5ceSopenharmony_ci return 1; 1238d4afb5ceSopenharmony_ci 1239d4afb5ceSopenharmony_ci if (p > vp && p < &vp[wsi->a.vhost->count_protocols]) 1240d4afb5ceSopenharmony_ci lws_same_vh_protocol_insert(wsi, (int)(p - vp)); 1241d4afb5ceSopenharmony_ci else { 1242d4afb5ceSopenharmony_ci int n = wsi->a.vhost->count_protocols; 1243d4afb5ceSopenharmony_ci int hit = 0; 1244d4afb5ceSopenharmony_ci 1245d4afb5ceSopenharmony_ci vpo = vp; 1246d4afb5ceSopenharmony_ci 1247d4afb5ceSopenharmony_ci while (n--) { 1248d4afb5ceSopenharmony_ci if (p->name && vp->name && !strcmp(p->name, vp->name)) { 1249d4afb5ceSopenharmony_ci hit = 1; 1250d4afb5ceSopenharmony_ci lws_same_vh_protocol_insert(wsi, (int)(vp - vpo)); 1251d4afb5ceSopenharmony_ci break; 1252d4afb5ceSopenharmony_ci } 1253d4afb5ceSopenharmony_ci vp++; 1254d4afb5ceSopenharmony_ci } 1255d4afb5ceSopenharmony_ci if (!hit) 1256d4afb5ceSopenharmony_ci lwsl_err("%s: %p is not in vhost '%s' protocols list\n", 1257d4afb5ceSopenharmony_ci __func__, p, wsi->a.vhost->name); 1258d4afb5ceSopenharmony_ci } 1259d4afb5ceSopenharmony_ci 1260d4afb5ceSopenharmony_ci if (wsi->a.protocol->callback(wsi, wsi->role_ops->protocol_bind_cb[ 1261d4afb5ceSopenharmony_ci !!lwsi_role_server(wsi)], 1262d4afb5ceSopenharmony_ci wsi->user_space, NULL, 0)) 1263d4afb5ceSopenharmony_ci return 1; 1264d4afb5ceSopenharmony_ci 1265d4afb5ceSopenharmony_ci wsi->protocol_bind_balance = 1; 1266d4afb5ceSopenharmony_ci 1267d4afb5ceSopenharmony_ci return 0; 1268d4afb5ceSopenharmony_ci} 1269d4afb5ceSopenharmony_ci 1270d4afb5ceSopenharmony_civoid 1271d4afb5ceSopenharmony_cilws_http_close_immortal(struct lws *wsi) 1272d4afb5ceSopenharmony_ci{ 1273d4afb5ceSopenharmony_ci struct lws *nwsi; 1274d4afb5ceSopenharmony_ci 1275d4afb5ceSopenharmony_ci if (!wsi->mux_substream) 1276d4afb5ceSopenharmony_ci return; 1277d4afb5ceSopenharmony_ci 1278d4afb5ceSopenharmony_ci assert(wsi->mux_stream_immortal); 1279d4afb5ceSopenharmony_ci wsi->mux_stream_immortal = 0; 1280d4afb5ceSopenharmony_ci 1281d4afb5ceSopenharmony_ci nwsi = lws_get_network_wsi(wsi); 1282d4afb5ceSopenharmony_ci lwsl_wsi_debug(wsi, "%s (%d)", lws_wsi_tag(nwsi), 1283d4afb5ceSopenharmony_ci nwsi->immortal_substream_count); 1284d4afb5ceSopenharmony_ci assert(nwsi->immortal_substream_count); 1285d4afb5ceSopenharmony_ci nwsi->immortal_substream_count--; 1286d4afb5ceSopenharmony_ci if (!nwsi->immortal_substream_count) 1287d4afb5ceSopenharmony_ci /* 1288d4afb5ceSopenharmony_ci * since we closed the only immortal stream on this nwsi, we 1289d4afb5ceSopenharmony_ci * need to reapply a normal timeout regime to the nwsi 1290d4afb5ceSopenharmony_ci */ 1291d4afb5ceSopenharmony_ci lws_set_timeout(nwsi, PENDING_TIMEOUT_HTTP_KEEPALIVE_IDLE, 1292d4afb5ceSopenharmony_ci wsi->a.vhost->keepalive_timeout ? 1293d4afb5ceSopenharmony_ci wsi->a.vhost->keepalive_timeout : 31); 1294d4afb5ceSopenharmony_ci} 1295d4afb5ceSopenharmony_ci 1296d4afb5ceSopenharmony_civoid 1297d4afb5ceSopenharmony_cilws_mux_mark_immortal(struct lws *wsi) 1298d4afb5ceSopenharmony_ci{ 1299d4afb5ceSopenharmony_ci struct lws *nwsi; 1300d4afb5ceSopenharmony_ci 1301d4afb5ceSopenharmony_ci lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0); 1302d4afb5ceSopenharmony_ci 1303d4afb5ceSopenharmony_ci if (!wsi->mux_substream 1304d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CLIENT) 1305d4afb5ceSopenharmony_ci && !wsi->client_mux_substream 1306d4afb5ceSopenharmony_ci#endif 1307d4afb5ceSopenharmony_ci ) { 1308d4afb5ceSopenharmony_ci lwsl_wsi_err(wsi, "not mux substream"); 1309d4afb5ceSopenharmony_ci return; 1310d4afb5ceSopenharmony_ci } 1311d4afb5ceSopenharmony_ci 1312d4afb5ceSopenharmony_ci if (wsi->mux_stream_immortal) 1313d4afb5ceSopenharmony_ci /* only need to handle it once per child wsi */ 1314d4afb5ceSopenharmony_ci return; 1315d4afb5ceSopenharmony_ci 1316d4afb5ceSopenharmony_ci nwsi = lws_get_network_wsi(wsi); 1317d4afb5ceSopenharmony_ci if (!nwsi) 1318d4afb5ceSopenharmony_ci return; 1319d4afb5ceSopenharmony_ci 1320d4afb5ceSopenharmony_ci lwsl_wsi_debug(wsi, "%s (%d)\n", lws_wsi_tag(nwsi), 1321d4afb5ceSopenharmony_ci nwsi->immortal_substream_count); 1322d4afb5ceSopenharmony_ci 1323d4afb5ceSopenharmony_ci wsi->mux_stream_immortal = 1; 1324d4afb5ceSopenharmony_ci assert(nwsi->immortal_substream_count < 255); /* largest count */ 1325d4afb5ceSopenharmony_ci nwsi->immortal_substream_count++; 1326d4afb5ceSopenharmony_ci if (nwsi->immortal_substream_count == 1) 1327d4afb5ceSopenharmony_ci lws_set_timeout(nwsi, NO_PENDING_TIMEOUT, 0); 1328d4afb5ceSopenharmony_ci} 1329d4afb5ceSopenharmony_ci 1330d4afb5ceSopenharmony_ciint 1331d4afb5ceSopenharmony_cilws_http_mark_sse(struct lws *wsi) 1332d4afb5ceSopenharmony_ci{ 1333d4afb5ceSopenharmony_ci if (!wsi) 1334d4afb5ceSopenharmony_ci return 0; 1335d4afb5ceSopenharmony_ci 1336d4afb5ceSopenharmony_ci lws_http_headers_detach(wsi); 1337d4afb5ceSopenharmony_ci lws_mux_mark_immortal(wsi); 1338d4afb5ceSopenharmony_ci 1339d4afb5ceSopenharmony_ci if (wsi->mux_substream) 1340d4afb5ceSopenharmony_ci wsi->h2_stream_carries_sse = 1; 1341d4afb5ceSopenharmony_ci 1342d4afb5ceSopenharmony_ci return 0; 1343d4afb5ceSopenharmony_ci} 1344d4afb5ceSopenharmony_ci 1345d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CLIENT) 1346d4afb5ceSopenharmony_ci 1347d4afb5ceSopenharmony_ciconst char * 1348d4afb5ceSopenharmony_cilws_wsi_client_stash_item(struct lws *wsi, int stash_idx, int hdr_idx) 1349d4afb5ceSopenharmony_ci{ 1350d4afb5ceSopenharmony_ci /* try the generic client stash */ 1351d4afb5ceSopenharmony_ci if (wsi->stash) 1352d4afb5ceSopenharmony_ci return wsi->stash->cis[stash_idx]; 1353d4afb5ceSopenharmony_ci 1354d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) 1355d4afb5ceSopenharmony_ci /* if not, use the ah stash if applicable */ 1356d4afb5ceSopenharmony_ci return lws_hdr_simple_ptr(wsi, (enum lws_token_indexes)hdr_idx); 1357d4afb5ceSopenharmony_ci#else 1358d4afb5ceSopenharmony_ci return NULL; 1359d4afb5ceSopenharmony_ci#endif 1360d4afb5ceSopenharmony_ci} 1361d4afb5ceSopenharmony_ci#endif 1362d4afb5ceSopenharmony_ci 1363d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_H2) || defined(LWS_ROLE_MQTT) 1364d4afb5ceSopenharmony_ci 1365d4afb5ceSopenharmony_civoid 1366d4afb5ceSopenharmony_cilws_wsi_mux_insert(struct lws *wsi, struct lws *parent_wsi, unsigned int sid) 1367d4afb5ceSopenharmony_ci{ 1368d4afb5ceSopenharmony_ci lwsl_wsi_info(wsi, "par %s: assign sid %d (curr %d)", 1369d4afb5ceSopenharmony_ci lws_wsi_tag(parent_wsi), sid, wsi->mux.my_sid); 1370d4afb5ceSopenharmony_ci 1371d4afb5ceSopenharmony_ci if (wsi->mux.my_sid && wsi->mux.my_sid != (unsigned int)sid) 1372d4afb5ceSopenharmony_ci assert(0); 1373d4afb5ceSopenharmony_ci 1374d4afb5ceSopenharmony_ci wsi->mux.my_sid = sid; 1375d4afb5ceSopenharmony_ci wsi->mux.parent_wsi = parent_wsi; 1376d4afb5ceSopenharmony_ci wsi->role_ops = parent_wsi->role_ops; 1377d4afb5ceSopenharmony_ci 1378d4afb5ceSopenharmony_ci /* new guy's sibling is whoever was the first child before */ 1379d4afb5ceSopenharmony_ci wsi->mux.sibling_list = parent_wsi->mux.child_list; 1380d4afb5ceSopenharmony_ci 1381d4afb5ceSopenharmony_ci /* first child is now the new guy */ 1382d4afb5ceSopenharmony_ci parent_wsi->mux.child_list = wsi; 1383d4afb5ceSopenharmony_ci 1384d4afb5ceSopenharmony_ci parent_wsi->mux.child_count++; 1385d4afb5ceSopenharmony_ci} 1386d4afb5ceSopenharmony_ci 1387d4afb5ceSopenharmony_cistruct lws * 1388d4afb5ceSopenharmony_cilws_wsi_mux_from_id(struct lws *parent_wsi, unsigned int sid) 1389d4afb5ceSopenharmony_ci{ 1390d4afb5ceSopenharmony_ci lws_start_foreach_ll(struct lws *, wsi, parent_wsi->mux.child_list) { 1391d4afb5ceSopenharmony_ci if (wsi->mux.my_sid == sid) 1392d4afb5ceSopenharmony_ci return wsi; 1393d4afb5ceSopenharmony_ci } lws_end_foreach_ll(wsi, mux.sibling_list); 1394d4afb5ceSopenharmony_ci 1395d4afb5ceSopenharmony_ci return NULL; 1396d4afb5ceSopenharmony_ci} 1397d4afb5ceSopenharmony_ci 1398d4afb5ceSopenharmony_civoid 1399d4afb5ceSopenharmony_cilws_wsi_mux_dump_children(struct lws *wsi) 1400d4afb5ceSopenharmony_ci{ 1401d4afb5ceSopenharmony_ci#if defined(_DEBUG) 1402d4afb5ceSopenharmony_ci if (!wsi->mux.parent_wsi || !lwsl_visible(LLL_INFO)) 1403d4afb5ceSopenharmony_ci return; 1404d4afb5ceSopenharmony_ci 1405d4afb5ceSopenharmony_ci lws_start_foreach_llp(struct lws **, w, 1406d4afb5ceSopenharmony_ci wsi->mux.parent_wsi->mux.child_list) { 1407d4afb5ceSopenharmony_ci lwsl_wsi_info(wsi, " \\---- child %s %s\n", 1408d4afb5ceSopenharmony_ci (*w)->role_ops ? (*w)->role_ops->name : "?", 1409d4afb5ceSopenharmony_ci lws_wsi_tag(*w)); 1410d4afb5ceSopenharmony_ci assert(*w != (*w)->mux.sibling_list); 1411d4afb5ceSopenharmony_ci } lws_end_foreach_llp(w, mux.sibling_list); 1412d4afb5ceSopenharmony_ci#endif 1413d4afb5ceSopenharmony_ci} 1414d4afb5ceSopenharmony_ci 1415d4afb5ceSopenharmony_civoid 1416d4afb5ceSopenharmony_cilws_wsi_mux_close_children(struct lws *wsi, int reason) 1417d4afb5ceSopenharmony_ci{ 1418d4afb5ceSopenharmony_ci struct lws *wsi2; 1419d4afb5ceSopenharmony_ci struct lws **w; 1420d4afb5ceSopenharmony_ci 1421d4afb5ceSopenharmony_ci if (!wsi->mux.child_list) 1422d4afb5ceSopenharmony_ci return; 1423d4afb5ceSopenharmony_ci 1424d4afb5ceSopenharmony_ci w = &wsi->mux.child_list; 1425d4afb5ceSopenharmony_ci while (*w) { 1426d4afb5ceSopenharmony_ci lwsl_wsi_info((*w), " closing child"); 1427d4afb5ceSopenharmony_ci /* disconnect from siblings */ 1428d4afb5ceSopenharmony_ci wsi2 = (*w)->mux.sibling_list; 1429d4afb5ceSopenharmony_ci assert (wsi2 != *w); 1430d4afb5ceSopenharmony_ci (*w)->mux.sibling_list = NULL; 1431d4afb5ceSopenharmony_ci (*w)->socket_is_permanently_unusable = 1; 1432d4afb5ceSopenharmony_ci __lws_close_free_wsi(*w, (enum lws_close_status)reason, "mux child recurse"); 1433d4afb5ceSopenharmony_ci *w = wsi2; 1434d4afb5ceSopenharmony_ci } 1435d4afb5ceSopenharmony_ci} 1436d4afb5ceSopenharmony_ci 1437d4afb5ceSopenharmony_ci 1438d4afb5ceSopenharmony_civoid 1439d4afb5ceSopenharmony_cilws_wsi_mux_sibling_disconnect(struct lws *wsi) 1440d4afb5ceSopenharmony_ci{ 1441d4afb5ceSopenharmony_ci struct lws *wsi2; 1442d4afb5ceSopenharmony_ci 1443d4afb5ceSopenharmony_ci lws_start_foreach_llp(struct lws **, w, 1444d4afb5ceSopenharmony_ci wsi->mux.parent_wsi->mux.child_list) { 1445d4afb5ceSopenharmony_ci 1446d4afb5ceSopenharmony_ci /* disconnect from siblings */ 1447d4afb5ceSopenharmony_ci if (*w == wsi) { 1448d4afb5ceSopenharmony_ci wsi2 = (*w)->mux.sibling_list; 1449d4afb5ceSopenharmony_ci (*w)->mux.sibling_list = NULL; 1450d4afb5ceSopenharmony_ci *w = wsi2; 1451d4afb5ceSopenharmony_ci lwsl_wsi_debug(wsi, " disentangled from sibling %s", 1452d4afb5ceSopenharmony_ci lws_wsi_tag(wsi2)); 1453d4afb5ceSopenharmony_ci break; 1454d4afb5ceSopenharmony_ci } 1455d4afb5ceSopenharmony_ci } lws_end_foreach_llp(w, mux.sibling_list); 1456d4afb5ceSopenharmony_ci wsi->mux.parent_wsi->mux.child_count--; 1457d4afb5ceSopenharmony_ci 1458d4afb5ceSopenharmony_ci wsi->mux.parent_wsi = NULL; 1459d4afb5ceSopenharmony_ci} 1460d4afb5ceSopenharmony_ci 1461d4afb5ceSopenharmony_civoid 1462d4afb5ceSopenharmony_cilws_wsi_mux_dump_waiting_children(struct lws *wsi) 1463d4afb5ceSopenharmony_ci{ 1464d4afb5ceSopenharmony_ci#if defined(_DEBUG) 1465d4afb5ceSopenharmony_ci lwsl_info("%s: %s: children waiting for POLLOUT service:\n", 1466d4afb5ceSopenharmony_ci __func__, lws_wsi_tag(wsi)); 1467d4afb5ceSopenharmony_ci 1468d4afb5ceSopenharmony_ci wsi = wsi->mux.child_list; 1469d4afb5ceSopenharmony_ci while (wsi) { 1470d4afb5ceSopenharmony_ci lwsl_wsi_info(wsi, " %c sid %u: 0x%x %s %s", 1471d4afb5ceSopenharmony_ci wsi->mux.requested_POLLOUT ? '*' : ' ', 1472d4afb5ceSopenharmony_ci wsi->mux.my_sid, lwsi_state(wsi), 1473d4afb5ceSopenharmony_ci wsi->role_ops->name, 1474d4afb5ceSopenharmony_ci wsi->a.protocol ? wsi->a.protocol->name : "noprotocol"); 1475d4afb5ceSopenharmony_ci 1476d4afb5ceSopenharmony_ci wsi = wsi->mux.sibling_list; 1477d4afb5ceSopenharmony_ci } 1478d4afb5ceSopenharmony_ci#endif 1479d4afb5ceSopenharmony_ci} 1480d4afb5ceSopenharmony_ci 1481d4afb5ceSopenharmony_ciint 1482d4afb5ceSopenharmony_cilws_wsi_mux_mark_parents_needing_writeable(struct lws *wsi) 1483d4afb5ceSopenharmony_ci{ 1484d4afb5ceSopenharmony_ci struct lws /* *network_wsi = lws_get_network_wsi(wsi), */ *wsi2; 1485d4afb5ceSopenharmony_ci //int already = network_wsi->mux.requested_POLLOUT; 1486d4afb5ceSopenharmony_ci 1487d4afb5ceSopenharmony_ci /* mark everybody above him as requesting pollout */ 1488d4afb5ceSopenharmony_ci 1489d4afb5ceSopenharmony_ci wsi2 = wsi; 1490d4afb5ceSopenharmony_ci while (wsi2) { 1491d4afb5ceSopenharmony_ci wsi2->mux.requested_POLLOUT = 1; 1492d4afb5ceSopenharmony_ci lwsl_wsi_info(wsi2, "sid %u, pending writable", 1493d4afb5ceSopenharmony_ci wsi2->mux.my_sid); 1494d4afb5ceSopenharmony_ci wsi2 = wsi2->mux.parent_wsi; 1495d4afb5ceSopenharmony_ci } 1496d4afb5ceSopenharmony_ci 1497d4afb5ceSopenharmony_ci return 0; // already; 1498d4afb5ceSopenharmony_ci} 1499d4afb5ceSopenharmony_ci 1500d4afb5ceSopenharmony_cistruct lws * 1501d4afb5ceSopenharmony_cilws_wsi_mux_move_child_to_tail(struct lws **wsi2) 1502d4afb5ceSopenharmony_ci{ 1503d4afb5ceSopenharmony_ci struct lws *w = *wsi2; 1504d4afb5ceSopenharmony_ci 1505d4afb5ceSopenharmony_ci while (w) { 1506d4afb5ceSopenharmony_ci if (!w->mux.sibling_list) { /* w is the current last */ 1507d4afb5ceSopenharmony_ci lwsl_wsi_debug(w, "*wsi2 = %s\n", lws_wsi_tag(*wsi2)); 1508d4afb5ceSopenharmony_ci 1509d4afb5ceSopenharmony_ci if (w == *wsi2) /* we are already last */ 1510d4afb5ceSopenharmony_ci break; 1511d4afb5ceSopenharmony_ci 1512d4afb5ceSopenharmony_ci /* last points to us as new last */ 1513d4afb5ceSopenharmony_ci w->mux.sibling_list = *wsi2; 1514d4afb5ceSopenharmony_ci 1515d4afb5ceSopenharmony_ci /* guy pointing to us until now points to 1516d4afb5ceSopenharmony_ci * our old next */ 1517d4afb5ceSopenharmony_ci *wsi2 = (*wsi2)->mux.sibling_list; 1518d4afb5ceSopenharmony_ci 1519d4afb5ceSopenharmony_ci /* we point to nothing because we are last */ 1520d4afb5ceSopenharmony_ci w->mux.sibling_list->mux.sibling_list = NULL; 1521d4afb5ceSopenharmony_ci 1522d4afb5ceSopenharmony_ci /* w becomes us */ 1523d4afb5ceSopenharmony_ci w = w->mux.sibling_list; 1524d4afb5ceSopenharmony_ci break; 1525d4afb5ceSopenharmony_ci } 1526d4afb5ceSopenharmony_ci w = w->mux.sibling_list; 1527d4afb5ceSopenharmony_ci } 1528d4afb5ceSopenharmony_ci 1529d4afb5ceSopenharmony_ci /* clear the waiting for POLLOUT on the guy that was chosen */ 1530d4afb5ceSopenharmony_ci 1531d4afb5ceSopenharmony_ci if (w) 1532d4afb5ceSopenharmony_ci w->mux.requested_POLLOUT = 0; 1533d4afb5ceSopenharmony_ci 1534d4afb5ceSopenharmony_ci return w; 1535d4afb5ceSopenharmony_ci} 1536d4afb5ceSopenharmony_ci 1537d4afb5ceSopenharmony_ciint 1538d4afb5ceSopenharmony_cilws_wsi_mux_action_pending_writeable_reqs(struct lws *wsi) 1539d4afb5ceSopenharmony_ci{ 1540d4afb5ceSopenharmony_ci struct lws *w = wsi->mux.child_list; 1541d4afb5ceSopenharmony_ci 1542d4afb5ceSopenharmony_ci while (w) { 1543d4afb5ceSopenharmony_ci if (w->mux.requested_POLLOUT) { 1544d4afb5ceSopenharmony_ci if (lws_change_pollfd(wsi, 0, LWS_POLLOUT)) 1545d4afb5ceSopenharmony_ci return -1; 1546d4afb5ceSopenharmony_ci return 0; 1547d4afb5ceSopenharmony_ci } 1548d4afb5ceSopenharmony_ci w = w->mux.sibling_list; 1549d4afb5ceSopenharmony_ci } 1550d4afb5ceSopenharmony_ci 1551d4afb5ceSopenharmony_ci if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) 1552d4afb5ceSopenharmony_ci return -1; 1553d4afb5ceSopenharmony_ci 1554d4afb5ceSopenharmony_ci return 0; 1555d4afb5ceSopenharmony_ci} 1556d4afb5ceSopenharmony_ci 1557d4afb5ceSopenharmony_ciint 1558d4afb5ceSopenharmony_cilws_wsi_txc_check_skint(struct lws_tx_credit *txc, int32_t tx_cr) 1559d4afb5ceSopenharmony_ci{ 1560d4afb5ceSopenharmony_ci if (txc->tx_cr <= 0) { 1561d4afb5ceSopenharmony_ci /* 1562d4afb5ceSopenharmony_ci * If other side is not able to cope with us sending any DATA 1563d4afb5ceSopenharmony_ci * so no matter if we have POLLOUT on our side if it's DATA we 1564d4afb5ceSopenharmony_ci * want to send. 1565d4afb5ceSopenharmony_ci */ 1566d4afb5ceSopenharmony_ci 1567d4afb5ceSopenharmony_ci if (!txc->skint) 1568d4afb5ceSopenharmony_ci lwsl_info("%s: %p: skint (%d)\n", __func__, txc, 1569d4afb5ceSopenharmony_ci (int)txc->tx_cr); 1570d4afb5ceSopenharmony_ci 1571d4afb5ceSopenharmony_ci txc->skint = 1; 1572d4afb5ceSopenharmony_ci 1573d4afb5ceSopenharmony_ci return 1; 1574d4afb5ceSopenharmony_ci } 1575d4afb5ceSopenharmony_ci 1576d4afb5ceSopenharmony_ci if (txc->skint) 1577d4afb5ceSopenharmony_ci lwsl_info("%s: %p: unskint (%d)\n", __func__, txc, 1578d4afb5ceSopenharmony_ci (int)txc->tx_cr); 1579d4afb5ceSopenharmony_ci 1580d4afb5ceSopenharmony_ci txc->skint = 0; 1581d4afb5ceSopenharmony_ci 1582d4afb5ceSopenharmony_ci return 0; 1583d4afb5ceSopenharmony_ci} 1584d4afb5ceSopenharmony_ci 1585d4afb5ceSopenharmony_ci#if defined(_DEBUG) 1586d4afb5ceSopenharmony_civoid 1587d4afb5ceSopenharmony_cilws_wsi_txc_describe(struct lws_tx_credit *txc, const char *at, uint32_t sid) 1588d4afb5ceSopenharmony_ci{ 1589d4afb5ceSopenharmony_ci lwsl_info("%s: %p: %s: sid %d: %speer-to-us: %d, us-to-peer: %d\n", 1590d4afb5ceSopenharmony_ci __func__, txc, at, (int)sid, txc->skint ? "SKINT, " : "", 1591d4afb5ceSopenharmony_ci (int)txc->peer_tx_cr_est, (int)txc->tx_cr); 1592d4afb5ceSopenharmony_ci} 1593d4afb5ceSopenharmony_ci#endif 1594d4afb5ceSopenharmony_ci 1595d4afb5ceSopenharmony_ciint 1596d4afb5ceSopenharmony_cilws_wsi_tx_credit(struct lws *wsi, char peer_to_us, int add) 1597d4afb5ceSopenharmony_ci{ 1598d4afb5ceSopenharmony_ci if (wsi->role_ops && lws_rops_fidx(wsi->role_ops, LWS_ROPS_tx_credit)) 1599d4afb5ceSopenharmony_ci return lws_rops_func_fidx(wsi->role_ops, LWS_ROPS_tx_credit). 1600d4afb5ceSopenharmony_ci tx_credit(wsi, peer_to_us, add); 1601d4afb5ceSopenharmony_ci 1602d4afb5ceSopenharmony_ci return 0; 1603d4afb5ceSopenharmony_ci} 1604d4afb5ceSopenharmony_ci 1605d4afb5ceSopenharmony_ci/* 1606d4afb5ceSopenharmony_ci * Let the protocol know about incoming tx credit window updates if it's 1607d4afb5ceSopenharmony_ci * managing the flow control manually (it may want to proxy this information) 1608d4afb5ceSopenharmony_ci */ 1609d4afb5ceSopenharmony_ci 1610d4afb5ceSopenharmony_ciint 1611d4afb5ceSopenharmony_cilws_wsi_txc_report_manual_txcr_in(struct lws *wsi, int32_t bump) 1612d4afb5ceSopenharmony_ci{ 1613d4afb5ceSopenharmony_ci if (!wsi->txc.manual) 1614d4afb5ceSopenharmony_ci /* 1615d4afb5ceSopenharmony_ci * If we don't care about managing it manually, no need to 1616d4afb5ceSopenharmony_ci * report it 1617d4afb5ceSopenharmony_ci */ 1618d4afb5ceSopenharmony_ci return 0; 1619d4afb5ceSopenharmony_ci 1620d4afb5ceSopenharmony_ci return user_callback_handle_rxflow(wsi->a.protocol->callback, 1621d4afb5ceSopenharmony_ci wsi, LWS_CALLBACK_WSI_TX_CREDIT_GET, 1622d4afb5ceSopenharmony_ci wsi->user_space, NULL, (size_t)bump); 1623d4afb5ceSopenharmony_ci} 1624d4afb5ceSopenharmony_ci 1625d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CLIENT) 1626d4afb5ceSopenharmony_ci 1627d4afb5ceSopenharmony_ciint 1628d4afb5ceSopenharmony_cilws_wsi_mux_apply_queue(struct lws *wsi) 1629d4afb5ceSopenharmony_ci{ 1630d4afb5ceSopenharmony_ci /* we have a transaction queue that wants to pipeline */ 1631d4afb5ceSopenharmony_ci 1632d4afb5ceSopenharmony_ci lws_context_lock(wsi->a.context, __func__); /* -------------- cx { */ 1633d4afb5ceSopenharmony_ci lws_vhost_lock(wsi->a.vhost); 1634d4afb5ceSopenharmony_ci 1635d4afb5ceSopenharmony_ci lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, 1636d4afb5ceSopenharmony_ci wsi->dll2_cli_txn_queue_owner.head) { 1637d4afb5ceSopenharmony_ci struct lws *w = lws_container_of(d, struct lws, 1638d4afb5ceSopenharmony_ci dll2_cli_txn_queue); 1639d4afb5ceSopenharmony_ci 1640d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_H2) 1641d4afb5ceSopenharmony_ci if (lwsi_role_http(wsi) && 1642d4afb5ceSopenharmony_ci lwsi_state(w) == LRS_H2_WAITING_TO_SEND_HEADERS) { 1643d4afb5ceSopenharmony_ci lwsl_wsi_info(w, "cli pipeq to be h2"); 1644d4afb5ceSopenharmony_ci 1645d4afb5ceSopenharmony_ci lwsi_set_state(w, LRS_H1C_ISSUE_HANDSHAKE2); 1646d4afb5ceSopenharmony_ci 1647d4afb5ceSopenharmony_ci /* remove ourselves from client queue */ 1648d4afb5ceSopenharmony_ci lws_dll2_remove(&w->dll2_cli_txn_queue); 1649d4afb5ceSopenharmony_ci 1650d4afb5ceSopenharmony_ci /* attach ourselves as an h2 stream */ 1651d4afb5ceSopenharmony_ci lws_wsi_h2_adopt(wsi, w); 1652d4afb5ceSopenharmony_ci } 1653d4afb5ceSopenharmony_ci#endif 1654d4afb5ceSopenharmony_ci 1655d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_MQTT) 1656d4afb5ceSopenharmony_ci if (lwsi_role_mqtt(wsi) && 1657d4afb5ceSopenharmony_ci lwsi_state(wsi) == LRS_ESTABLISHED) { 1658d4afb5ceSopenharmony_ci lwsl_wsi_info(w, "cli pipeq to be mqtt\n"); 1659d4afb5ceSopenharmony_ci 1660d4afb5ceSopenharmony_ci /* remove ourselves from client queue */ 1661d4afb5ceSopenharmony_ci lws_dll2_remove(&w->dll2_cli_txn_queue); 1662d4afb5ceSopenharmony_ci 1663d4afb5ceSopenharmony_ci /* attach ourselves as an h2 stream */ 1664d4afb5ceSopenharmony_ci lws_wsi_mqtt_adopt(wsi, w); 1665d4afb5ceSopenharmony_ci } 1666d4afb5ceSopenharmony_ci#endif 1667d4afb5ceSopenharmony_ci 1668d4afb5ceSopenharmony_ci } lws_end_foreach_dll_safe(d, d1); 1669d4afb5ceSopenharmony_ci 1670d4afb5ceSopenharmony_ci lws_vhost_unlock(wsi->a.vhost); 1671d4afb5ceSopenharmony_ci lws_context_unlock(wsi->a.context); /* } cx -------------- */ 1672d4afb5ceSopenharmony_ci 1673d4afb5ceSopenharmony_ci return 0; 1674d4afb5ceSopenharmony_ci} 1675d4afb5ceSopenharmony_ci 1676d4afb5ceSopenharmony_ci#endif 1677d4afb5ceSopenharmony_ci 1678d4afb5ceSopenharmony_ci#endif 1679