1d4afb5ceSopenharmony_ci/* 2d4afb5ceSopenharmony_ci * libwebsockets - small server side websockets and web server implementation 3d4afb5ceSopenharmony_ci * 4d4afb5ceSopenharmony_ci * Copyright (C) 2010 - 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#include "private-lib-event-libs-libuv.h" 27d4afb5ceSopenharmony_ci 28d4afb5ceSopenharmony_ci#define pt_to_priv_uv(_pt) ((struct lws_pt_eventlibs_libuv *)(_pt)->evlib_pt) 29d4afb5ceSopenharmony_ci#define wsi_to_priv_uv(_w) ((struct lws_wsi_eventlibs_libuv *)(_w)->evlib_wsi) 30d4afb5ceSopenharmony_ci 31d4afb5ceSopenharmony_cistatic void 32d4afb5ceSopenharmony_cilws_uv_sultimer_cb(uv_timer_t *timer 33d4afb5ceSopenharmony_ci#if UV_VERSION_MAJOR == 0 34d4afb5ceSopenharmony_ci , int status 35d4afb5ceSopenharmony_ci#endif 36d4afb5ceSopenharmony_ci) 37d4afb5ceSopenharmony_ci{ 38d4afb5ceSopenharmony_ci struct lws_pt_eventlibs_libuv *ptpr = lws_container_of(timer, 39d4afb5ceSopenharmony_ci struct lws_pt_eventlibs_libuv, sultimer); 40d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = ptpr->pt; 41d4afb5ceSopenharmony_ci lws_usec_t us; 42d4afb5ceSopenharmony_ci 43d4afb5ceSopenharmony_ci lws_context_lock(pt->context, __func__); 44d4afb5ceSopenharmony_ci lws_pt_lock(pt, __func__); 45d4afb5ceSopenharmony_ci us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS, 46d4afb5ceSopenharmony_ci lws_now_usecs()); 47d4afb5ceSopenharmony_ci if (us) 48d4afb5ceSopenharmony_ci uv_timer_start(&pt_to_priv_uv(pt)->sultimer, lws_uv_sultimer_cb, 49d4afb5ceSopenharmony_ci LWS_US_TO_MS((uint64_t)us), 0); 50d4afb5ceSopenharmony_ci lws_pt_unlock(pt); 51d4afb5ceSopenharmony_ci lws_context_unlock(pt->context); 52d4afb5ceSopenharmony_ci} 53d4afb5ceSopenharmony_ci 54d4afb5ceSopenharmony_cistatic void 55d4afb5ceSopenharmony_cilws_uv_idle(uv_idle_t *handle 56d4afb5ceSopenharmony_ci#if UV_VERSION_MAJOR == 0 57d4afb5ceSopenharmony_ci , int status 58d4afb5ceSopenharmony_ci#endif 59d4afb5ceSopenharmony_ci) 60d4afb5ceSopenharmony_ci{ struct lws_pt_eventlibs_libuv *ptpr = lws_container_of(handle, 61d4afb5ceSopenharmony_ci struct lws_pt_eventlibs_libuv, idle); 62d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = ptpr->pt; 63d4afb5ceSopenharmony_ci lws_usec_t us; 64d4afb5ceSopenharmony_ci 65d4afb5ceSopenharmony_ci lws_service_do_ripe_rxflow(pt); 66d4afb5ceSopenharmony_ci 67d4afb5ceSopenharmony_ci lws_context_lock(pt->context, __func__); 68d4afb5ceSopenharmony_ci lws_pt_lock(pt, __func__); 69d4afb5ceSopenharmony_ci 70d4afb5ceSopenharmony_ci /* 71d4afb5ceSopenharmony_ci * is there anybody with pending stuff that needs service forcing? 72d4afb5ceSopenharmony_ci */ 73d4afb5ceSopenharmony_ci if (!lws_service_adjust_timeout(pt->context, 1, pt->tid)) 74d4afb5ceSopenharmony_ci /* -1 timeout means just do forced service */ 75d4afb5ceSopenharmony_ci _lws_plat_service_forced_tsi(pt->context, pt->tid); 76d4afb5ceSopenharmony_ci 77d4afb5ceSopenharmony_ci /* account for sultimer */ 78d4afb5ceSopenharmony_ci 79d4afb5ceSopenharmony_ci us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS, 80d4afb5ceSopenharmony_ci lws_now_usecs()); 81d4afb5ceSopenharmony_ci if (us) 82d4afb5ceSopenharmony_ci uv_timer_start(&pt_to_priv_uv(pt)->sultimer, lws_uv_sultimer_cb, 83d4afb5ceSopenharmony_ci LWS_US_TO_MS((uint64_t)us), 0); 84d4afb5ceSopenharmony_ci 85d4afb5ceSopenharmony_ci /* if there is nobody who needs service forcing, shut down idle */ 86d4afb5ceSopenharmony_ci if (lws_service_adjust_timeout(pt->context, 1, pt->tid)) 87d4afb5ceSopenharmony_ci uv_idle_stop(handle); 88d4afb5ceSopenharmony_ci 89d4afb5ceSopenharmony_ci lws_pt_unlock(pt); 90d4afb5ceSopenharmony_ci lws_context_unlock(pt->context); 91d4afb5ceSopenharmony_ci} 92d4afb5ceSopenharmony_ci 93d4afb5ceSopenharmony_cistatic void 94d4afb5ceSopenharmony_cilws_io_cb(uv_poll_t *watcher, int status, int revents) 95d4afb5ceSopenharmony_ci{ 96d4afb5ceSopenharmony_ci struct lws *wsi = (struct lws *)((uv_handle_t *)watcher)->data; 97d4afb5ceSopenharmony_ci struct lws_context *context = wsi->a.context; 98d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; 99d4afb5ceSopenharmony_ci struct lws_pt_eventlibs_libuv *ptpriv = pt_to_priv_uv(pt); 100d4afb5ceSopenharmony_ci struct lws_pollfd eventfd; 101d4afb5ceSopenharmony_ci 102d4afb5ceSopenharmony_ci lws_context_lock(pt->context, __func__); 103d4afb5ceSopenharmony_ci lws_pt_lock(pt, __func__); 104d4afb5ceSopenharmony_ci 105d4afb5ceSopenharmony_ci if (pt->is_destroyed) 106d4afb5ceSopenharmony_ci goto bail; 107d4afb5ceSopenharmony_ci 108d4afb5ceSopenharmony_ci if (!ptpriv->thread_valid) { 109d4afb5ceSopenharmony_ci /* record the thread id that gave us our first event */ 110d4afb5ceSopenharmony_ci ptpriv->uv_thread = uv_thread_self(); 111d4afb5ceSopenharmony_ci ptpriv->thread_valid = 1; 112d4afb5ceSopenharmony_ci } 113d4afb5ceSopenharmony_ci 114d4afb5ceSopenharmony_ci#if defined(WIN32) || defined(_WIN32) 115d4afb5ceSopenharmony_ci eventfd.fd = watcher->socket; 116d4afb5ceSopenharmony_ci#else 117d4afb5ceSopenharmony_ci eventfd.fd = watcher->io_watcher.fd; 118d4afb5ceSopenharmony_ci#endif 119d4afb5ceSopenharmony_ci eventfd.events = 0; 120d4afb5ceSopenharmony_ci eventfd.revents = 0; 121d4afb5ceSopenharmony_ci 122d4afb5ceSopenharmony_ci if (status < 0) { 123d4afb5ceSopenharmony_ci /* 124d4afb5ceSopenharmony_ci * At this point status will be an UV error, like UV_EBADF, 125d4afb5ceSopenharmony_ci * we treat all errors as LWS_POLLHUP 126d4afb5ceSopenharmony_ci * 127d4afb5ceSopenharmony_ci * You might want to return; instead of servicing the fd in 128d4afb5ceSopenharmony_ci * some cases */ 129d4afb5ceSopenharmony_ci if (status == UV_EAGAIN) 130d4afb5ceSopenharmony_ci goto bail; 131d4afb5ceSopenharmony_ci 132d4afb5ceSopenharmony_ci eventfd.events |= LWS_POLLHUP; 133d4afb5ceSopenharmony_ci eventfd.revents |= LWS_POLLHUP; 134d4afb5ceSopenharmony_ci } else { 135d4afb5ceSopenharmony_ci if (revents & UV_READABLE) { 136d4afb5ceSopenharmony_ci eventfd.events |= LWS_POLLIN; 137d4afb5ceSopenharmony_ci eventfd.revents |= LWS_POLLIN; 138d4afb5ceSopenharmony_ci } 139d4afb5ceSopenharmony_ci if (revents & UV_WRITABLE) { 140d4afb5ceSopenharmony_ci eventfd.events |= LWS_POLLOUT; 141d4afb5ceSopenharmony_ci eventfd.revents |= LWS_POLLOUT; 142d4afb5ceSopenharmony_ci } 143d4afb5ceSopenharmony_ci } 144d4afb5ceSopenharmony_ci 145d4afb5ceSopenharmony_ci lws_pt_unlock(pt); 146d4afb5ceSopenharmony_ci lws_context_unlock(pt->context); 147d4afb5ceSopenharmony_ci 148d4afb5ceSopenharmony_ci lws_service_fd_tsi(context, &eventfd, wsi->tsi); 149d4afb5ceSopenharmony_ci 150d4afb5ceSopenharmony_ci if (pt->destroy_self) { 151d4afb5ceSopenharmony_ci lws_context_destroy(pt->context); 152d4afb5ceSopenharmony_ci return; 153d4afb5ceSopenharmony_ci } 154d4afb5ceSopenharmony_ci 155d4afb5ceSopenharmony_ci uv_idle_start(&ptpriv->idle, lws_uv_idle); 156d4afb5ceSopenharmony_ci return; 157d4afb5ceSopenharmony_ci 158d4afb5ceSopenharmony_cibail: 159d4afb5ceSopenharmony_ci lws_pt_unlock(pt); 160d4afb5ceSopenharmony_ci lws_context_unlock(pt->context); 161d4afb5ceSopenharmony_ci} 162d4afb5ceSopenharmony_ci 163d4afb5ceSopenharmony_ci/* 164d4afb5ceSopenharmony_ci * This does not actually stop the event loop. The reason is we have to pass 165d4afb5ceSopenharmony_ci * libuv handle closures through its event loop. So this tries to close all 166d4afb5ceSopenharmony_ci * wsi, and set a flag; when all the wsi closures are finalized then we 167d4afb5ceSopenharmony_ci * actually stop the libuv event loops. 168d4afb5ceSopenharmony_ci */ 169d4afb5ceSopenharmony_cistatic void 170d4afb5ceSopenharmony_cilws_libuv_stop(struct lws_context *context) 171d4afb5ceSopenharmony_ci{ 172d4afb5ceSopenharmony_ci if (context->requested_stop_internal_loops) { 173d4afb5ceSopenharmony_ci lwsl_cx_err(context, "ignoring"); 174d4afb5ceSopenharmony_ci return; 175d4afb5ceSopenharmony_ci } 176d4afb5ceSopenharmony_ci 177d4afb5ceSopenharmony_ci context->requested_stop_internal_loops = 1; 178d4afb5ceSopenharmony_ci lws_context_destroy(context); 179d4afb5ceSopenharmony_ci} 180d4afb5ceSopenharmony_ci 181d4afb5ceSopenharmony_cistatic void 182d4afb5ceSopenharmony_cilws_uv_signal_handler(uv_signal_t *watcher, int signum) 183d4afb5ceSopenharmony_ci{ 184d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = (struct lws_context_per_thread *) 185d4afb5ceSopenharmony_ci watcher->data; 186d4afb5ceSopenharmony_ci 187d4afb5ceSopenharmony_ci if (pt->context->eventlib_signal_cb) { 188d4afb5ceSopenharmony_ci pt->context->eventlib_signal_cb((void *)watcher, signum); 189d4afb5ceSopenharmony_ci 190d4afb5ceSopenharmony_ci return; 191d4afb5ceSopenharmony_ci } 192d4afb5ceSopenharmony_ci 193d4afb5ceSopenharmony_ci lwsl_cx_err(pt->context, "internal signal handler caught signal %d", 194d4afb5ceSopenharmony_ci signum); 195d4afb5ceSopenharmony_ci lws_libuv_stop(pt->context); 196d4afb5ceSopenharmony_ci} 197d4afb5ceSopenharmony_ci 198d4afb5ceSopenharmony_cistatic int 199d4afb5ceSopenharmony_cilws_uv_finalize_pt(struct lws_context_per_thread *pt) 200d4afb5ceSopenharmony_ci{ 201d4afb5ceSopenharmony_ci pt->event_loop_pt_unused = 1; 202d4afb5ceSopenharmony_ci 203d4afb5ceSopenharmony_ci lwsl_cx_info(pt->context, "thr %d", (int)(pt - pt->context->pt)); 204d4afb5ceSopenharmony_ci 205d4afb5ceSopenharmony_ci lws_context_lock(pt->context, __func__); 206d4afb5ceSopenharmony_ci 207d4afb5ceSopenharmony_ci if (!--pt->context->undestroyed_threads) { 208d4afb5ceSopenharmony_ci struct lws_vhost *vh = pt->context->vhost_list; 209d4afb5ceSopenharmony_ci 210d4afb5ceSopenharmony_ci /* 211d4afb5ceSopenharmony_ci * eventually, we emptied all the pts... 212d4afb5ceSopenharmony_ci */ 213d4afb5ceSopenharmony_ci 214d4afb5ceSopenharmony_ci lwsl_cx_debug(pt->context, "all pts down now"); 215d4afb5ceSopenharmony_ci 216d4afb5ceSopenharmony_ci /* protocols may have initialized libuv objects */ 217d4afb5ceSopenharmony_ci 218d4afb5ceSopenharmony_ci while (vh) { 219d4afb5ceSopenharmony_ci lws_vhost_destroy1(vh); 220d4afb5ceSopenharmony_ci vh = vh->vhost_next; 221d4afb5ceSopenharmony_ci } 222d4afb5ceSopenharmony_ci 223d4afb5ceSopenharmony_ci if (!pt->count_event_loop_static_asset_handles && 224d4afb5ceSopenharmony_ci pt->event_loop_foreign) { 225d4afb5ceSopenharmony_ci lwsl_cx_info(pt->context, "resuming context_destroy"); 226d4afb5ceSopenharmony_ci lws_context_unlock(pt->context); 227d4afb5ceSopenharmony_ci lws_context_destroy(pt->context); 228d4afb5ceSopenharmony_ci /* 229d4afb5ceSopenharmony_ci * For foreign, we're being called from the foreign 230d4afb5ceSopenharmony_ci * thread context the loop is associated with, we must 231d4afb5ceSopenharmony_ci * return to it cleanly even though we are done with it. 232d4afb5ceSopenharmony_ci */ 233d4afb5ceSopenharmony_ci return 1; 234d4afb5ceSopenharmony_ci } 235d4afb5ceSopenharmony_ci } else 236d4afb5ceSopenharmony_ci lwsl_cx_debug(pt->context, "still %d undestroyed", 237d4afb5ceSopenharmony_ci pt->context->undestroyed_threads); 238d4afb5ceSopenharmony_ci 239d4afb5ceSopenharmony_ci lws_context_unlock(pt->context); 240d4afb5ceSopenharmony_ci 241d4afb5ceSopenharmony_ci return 0; 242d4afb5ceSopenharmony_ci} 243d4afb5ceSopenharmony_ci 244d4afb5ceSopenharmony_ci// static void lws_uv_walk_cb(uv_handle_t *handle, void *arg) 245d4afb5ceSopenharmony_ci// { 246d4afb5ceSopenharmony_ci// if (!uv_is_closing(handle)) 247d4afb5ceSopenharmony_ci// lwsl_err("%s: handle %p still alive on loop\n", __func__, handle); 248d4afb5ceSopenharmony_ci// } 249d4afb5ceSopenharmony_ci 250d4afb5ceSopenharmony_ci 251d4afb5ceSopenharmony_cistatic const int sigs[] = { SIGINT, SIGTERM, SIGSEGV, SIGFPE, SIGHUP }; 252d4afb5ceSopenharmony_ci 253d4afb5ceSopenharmony_ci/* 254d4afb5ceSopenharmony_ci * Closing Phase 2: Close callback for a static UV asset 255d4afb5ceSopenharmony_ci */ 256d4afb5ceSopenharmony_ci 257d4afb5ceSopenharmony_cistatic void 258d4afb5ceSopenharmony_cilws_uv_close_cb_sa(uv_handle_t *handle) 259d4afb5ceSopenharmony_ci{ 260d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = 261d4afb5ceSopenharmony_ci LWS_UV_REFCOUNT_STATIC_HANDLE_TO_PT(handle); 262d4afb5ceSopenharmony_ci struct lws_pt_eventlibs_libuv *ptpriv = pt_to_priv_uv(pt); 263d4afb5ceSopenharmony_ci struct lws_context *context = pt->context; 264d4afb5ceSopenharmony_ci#if !defined(LWS_WITH_NO_LOGS) && defined(_DEBUG) 265d4afb5ceSopenharmony_ci int tsi = (int)(pt - &context->pt[0]); 266d4afb5ceSopenharmony_ci#endif 267d4afb5ceSopenharmony_ci 268d4afb5ceSopenharmony_ci lwsl_cx_info(context, "thr %d: sa left %d: dyn left: %d (rk %d)", 269d4afb5ceSopenharmony_ci tsi, 270d4afb5ceSopenharmony_ci pt->count_event_loop_static_asset_handles - 1, 271d4afb5ceSopenharmony_ci ptpriv->extant_handles, 272d4afb5ceSopenharmony_ci context->requested_stop_internal_loops); 273d4afb5ceSopenharmony_ci 274d4afb5ceSopenharmony_ci /* any static assets left? */ 275d4afb5ceSopenharmony_ci 276d4afb5ceSopenharmony_ci if (LWS_UV_REFCOUNT_STATIC_HANDLE_DESTROYED(handle) || 277d4afb5ceSopenharmony_ci ptpriv->extant_handles) 278d4afb5ceSopenharmony_ci return; 279d4afb5ceSopenharmony_ci 280d4afb5ceSopenharmony_ci /* 281d4afb5ceSopenharmony_ci * So we believe nothing of ours left on the loop. Let's sanity 282d4afb5ceSopenharmony_ci * check it to count what's still on the loop 283d4afb5ceSopenharmony_ci */ 284d4afb5ceSopenharmony_ci 285d4afb5ceSopenharmony_ci // uv_walk(pt_to_priv_uv(pt)->io_loop, lws_uv_walk_cb, NULL); 286d4afb5ceSopenharmony_ci 287d4afb5ceSopenharmony_ci /* 288d4afb5ceSopenharmony_ci * That's it... all wsi were down, and now every 289d4afb5ceSopenharmony_ci * static asset lws had a UV handle for is down. 290d4afb5ceSopenharmony_ci * 291d4afb5ceSopenharmony_ci * Stop the loop so we can get out of here. 292d4afb5ceSopenharmony_ci */ 293d4afb5ceSopenharmony_ci 294d4afb5ceSopenharmony_ci lwsl_cx_info(context, "thr %d: seen final static handle gone", tsi); 295d4afb5ceSopenharmony_ci 296d4afb5ceSopenharmony_ci if (!pt->event_loop_foreign) 297d4afb5ceSopenharmony_ci lws_context_destroy(context); 298d4afb5ceSopenharmony_ci 299d4afb5ceSopenharmony_ci lws_uv_finalize_pt(pt); 300d4afb5ceSopenharmony_ci 301d4afb5ceSopenharmony_ci lwsl_cx_info(context, "all done"); 302d4afb5ceSopenharmony_ci} 303d4afb5ceSopenharmony_ci 304d4afb5ceSopenharmony_ci/* 305d4afb5ceSopenharmony_ci * These must be called by protocols that want to use libuv objects directly... 306d4afb5ceSopenharmony_ci * 307d4afb5ceSopenharmony_ci * .... when the libuv object is created... 308d4afb5ceSopenharmony_ci */ 309d4afb5ceSopenharmony_ci 310d4afb5ceSopenharmony_civoid 311d4afb5ceSopenharmony_cilws_libuv_static_refcount_add(uv_handle_t *h, struct lws_context *context, 312d4afb5ceSopenharmony_ci int tsi) 313d4afb5ceSopenharmony_ci{ 314d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &context->pt[tsi]; 315d4afb5ceSopenharmony_ci 316d4afb5ceSopenharmony_ci LWS_UV_REFCOUNT_STATIC_HANDLE_NEW(h, pt); 317d4afb5ceSopenharmony_ci} 318d4afb5ceSopenharmony_ci 319d4afb5ceSopenharmony_ci/* 320d4afb5ceSopenharmony_ci * ... and in the close callback when the object is closed. 321d4afb5ceSopenharmony_ci */ 322d4afb5ceSopenharmony_ci 323d4afb5ceSopenharmony_civoid 324d4afb5ceSopenharmony_cilws_libuv_static_refcount_del(uv_handle_t *h) 325d4afb5ceSopenharmony_ci{ 326d4afb5ceSopenharmony_ci lws_uv_close_cb_sa(h); 327d4afb5ceSopenharmony_ci} 328d4afb5ceSopenharmony_ci 329d4afb5ceSopenharmony_civoid 330d4afb5ceSopenharmony_cilws_libuv_stop_without_kill(const struct lws_context *context, int tsi) 331d4afb5ceSopenharmony_ci{ 332d4afb5ceSopenharmony_ci if (pt_to_priv_uv(&context->pt[tsi])->io_loop) 333d4afb5ceSopenharmony_ci uv_stop(pt_to_priv_uv(&context->pt[tsi])->io_loop); 334d4afb5ceSopenharmony_ci} 335d4afb5ceSopenharmony_ci 336d4afb5ceSopenharmony_ciuv_loop_t * 337d4afb5ceSopenharmony_cilws_uv_getloop(struct lws_context *context, int tsi) 338d4afb5ceSopenharmony_ci{ 339d4afb5ceSopenharmony_ci if (pt_to_priv_uv(&context->pt[tsi])->io_loop) 340d4afb5ceSopenharmony_ci return pt_to_priv_uv(&context->pt[tsi])->io_loop; 341d4afb5ceSopenharmony_ci 342d4afb5ceSopenharmony_ci return NULL; 343d4afb5ceSopenharmony_ci} 344d4afb5ceSopenharmony_ci 345d4afb5ceSopenharmony_ciint 346d4afb5ceSopenharmony_cilws_libuv_check_watcher_active(struct lws *wsi) 347d4afb5ceSopenharmony_ci{ 348d4afb5ceSopenharmony_ci uv_handle_t *h = (uv_handle_t *)wsi_to_priv_uv(wsi)->w_read.pwatcher; 349d4afb5ceSopenharmony_ci 350d4afb5ceSopenharmony_ci if (!h) 351d4afb5ceSopenharmony_ci return 0; 352d4afb5ceSopenharmony_ci 353d4afb5ceSopenharmony_ci return uv_is_active(h); 354d4afb5ceSopenharmony_ci} 355d4afb5ceSopenharmony_ci 356d4afb5ceSopenharmony_cistatic int 357d4afb5ceSopenharmony_cielops_init_context_uv(struct lws_context *context, 358d4afb5ceSopenharmony_ci const struct lws_context_creation_info *info) 359d4afb5ceSopenharmony_ci{ 360d4afb5ceSopenharmony_ci int n; 361d4afb5ceSopenharmony_ci 362d4afb5ceSopenharmony_ci context->eventlib_signal_cb = info->signal_cb; 363d4afb5ceSopenharmony_ci 364d4afb5ceSopenharmony_ci for (n = 0; n < context->count_threads; n++) 365d4afb5ceSopenharmony_ci pt_to_priv_uv(&context->pt[n])->w_sigint.context = context; 366d4afb5ceSopenharmony_ci 367d4afb5ceSopenharmony_ci return 0; 368d4afb5ceSopenharmony_ci} 369d4afb5ceSopenharmony_ci 370d4afb5ceSopenharmony_cistatic int 371d4afb5ceSopenharmony_cielops_destroy_context1_uv(struct lws_context *context) 372d4afb5ceSopenharmony_ci{ 373d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt; 374d4afb5ceSopenharmony_ci int n, m = 0; 375d4afb5ceSopenharmony_ci 376d4afb5ceSopenharmony_ci for (n = 0; n < context->count_threads; n++) { 377d4afb5ceSopenharmony_ci int budget = 10000; 378d4afb5ceSopenharmony_ci pt = &context->pt[n]; 379d4afb5ceSopenharmony_ci 380d4afb5ceSopenharmony_ci /* only for internal loops... */ 381d4afb5ceSopenharmony_ci 382d4afb5ceSopenharmony_ci if (!pt->event_loop_foreign) { 383d4afb5ceSopenharmony_ci 384d4afb5ceSopenharmony_ci while (budget-- && (m = uv_run(pt_to_priv_uv(pt)->io_loop, 385d4afb5ceSopenharmony_ci UV_RUN_NOWAIT))) 386d4afb5ceSopenharmony_ci ; 387d4afb5ceSopenharmony_ci if (m) 388d4afb5ceSopenharmony_ci lwsl_cx_info(context, "tsi %d: unclosed", n); 389d4afb5ceSopenharmony_ci 390d4afb5ceSopenharmony_ci } 391d4afb5ceSopenharmony_ci } 392d4afb5ceSopenharmony_ci 393d4afb5ceSopenharmony_ci /* call destroy2 if internal loop */ 394d4afb5ceSopenharmony_ci return !context->pt[0].event_loop_foreign; 395d4afb5ceSopenharmony_ci} 396d4afb5ceSopenharmony_ci 397d4afb5ceSopenharmony_cistatic int 398d4afb5ceSopenharmony_cielops_destroy_context2_uv(struct lws_context *context) 399d4afb5ceSopenharmony_ci{ 400d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt; 401d4afb5ceSopenharmony_ci int n, internal = 0; 402d4afb5ceSopenharmony_ci 403d4afb5ceSopenharmony_ci for (n = 0; n < context->count_threads; n++) { 404d4afb5ceSopenharmony_ci pt = &context->pt[n]; 405d4afb5ceSopenharmony_ci 406d4afb5ceSopenharmony_ci /* only for internal loops... */ 407d4afb5ceSopenharmony_ci 408d4afb5ceSopenharmony_ci if (!pt->event_loop_foreign && pt_to_priv_uv(pt)->io_loop) { 409d4afb5ceSopenharmony_ci internal = 1; 410d4afb5ceSopenharmony_ci if (!context->evlib_finalize_destroy_after_int_loops_stop) 411d4afb5ceSopenharmony_ci uv_stop(pt_to_priv_uv(pt)->io_loop); 412d4afb5ceSopenharmony_ci else { 413d4afb5ceSopenharmony_ci#if UV_VERSION_MAJOR > 0 414d4afb5ceSopenharmony_ci uv_loop_close(pt_to_priv_uv(pt)->io_loop); 415d4afb5ceSopenharmony_ci#endif 416d4afb5ceSopenharmony_ci lws_free_set_NULL(pt_to_priv_uv(pt)->io_loop); 417d4afb5ceSopenharmony_ci } 418d4afb5ceSopenharmony_ci } 419d4afb5ceSopenharmony_ci } 420d4afb5ceSopenharmony_ci 421d4afb5ceSopenharmony_ci return internal; 422d4afb5ceSopenharmony_ci} 423d4afb5ceSopenharmony_ci 424d4afb5ceSopenharmony_cistatic int 425d4afb5ceSopenharmony_cielops_wsi_logical_close_uv(struct lws *wsi) 426d4afb5ceSopenharmony_ci{ 427d4afb5ceSopenharmony_ci if (!lws_socket_is_valid(wsi->desc.sockfd) && 428d4afb5ceSopenharmony_ci wsi->role_ops && strcmp(wsi->role_ops->name, "raw-file") && 429d4afb5ceSopenharmony_ci !wsi_to_priv_uv(wsi)->w_read.pwatcher) 430d4afb5ceSopenharmony_ci return 0; 431d4afb5ceSopenharmony_ci 432d4afb5ceSopenharmony_ci if (wsi->listener || wsi->event_pipe) { 433d4afb5ceSopenharmony_ci lwsl_wsi_debug(wsi, "%d %d stop listener / pipe poll", 434d4afb5ceSopenharmony_ci wsi->listener, 435d4afb5ceSopenharmony_ci wsi->event_pipe); 436d4afb5ceSopenharmony_ci if (wsi_to_priv_uv(wsi)->w_read.pwatcher) 437d4afb5ceSopenharmony_ci uv_poll_stop(wsi_to_priv_uv(wsi)->w_read.pwatcher); 438d4afb5ceSopenharmony_ci } 439d4afb5ceSopenharmony_ci lwsl_wsi_debug(wsi, "lws_libuv_closehandle"); 440d4afb5ceSopenharmony_ci /* 441d4afb5ceSopenharmony_ci * libuv has to do his own close handle processing asynchronously 442d4afb5ceSopenharmony_ci */ 443d4afb5ceSopenharmony_ci lws_libuv_closehandle(wsi); 444d4afb5ceSopenharmony_ci 445d4afb5ceSopenharmony_ci return 1; /* do not complete the wsi close, uv close cb will do it */ 446d4afb5ceSopenharmony_ci} 447d4afb5ceSopenharmony_ci 448d4afb5ceSopenharmony_cistatic int 449d4afb5ceSopenharmony_cielops_check_client_connect_ok_uv(struct lws *wsi) 450d4afb5ceSopenharmony_ci{ 451d4afb5ceSopenharmony_ci if (lws_libuv_check_watcher_active(wsi)) { 452d4afb5ceSopenharmony_ci lwsl_wsi_warn(wsi, "Waiting for libuv watcher to close"); 453d4afb5ceSopenharmony_ci return 1; 454d4afb5ceSopenharmony_ci } 455d4afb5ceSopenharmony_ci 456d4afb5ceSopenharmony_ci return 0; 457d4afb5ceSopenharmony_ci} 458d4afb5ceSopenharmony_ci 459d4afb5ceSopenharmony_cistatic void 460d4afb5ceSopenharmony_cilws_libuv_closewsi_m(uv_handle_t* handle) 461d4afb5ceSopenharmony_ci{ 462d4afb5ceSopenharmony_ci lws_sockfd_type sockfd = (lws_sockfd_type)(lws_intptr_t)handle->data; 463d4afb5ceSopenharmony_ci 464d4afb5ceSopenharmony_ci lwsl_debug("%s: sockfd %d\n", __func__, sockfd); 465d4afb5ceSopenharmony_ci compatible_close(sockfd); 466d4afb5ceSopenharmony_ci lws_free(handle); 467d4afb5ceSopenharmony_ci} 468d4afb5ceSopenharmony_ci 469d4afb5ceSopenharmony_cistatic void 470d4afb5ceSopenharmony_cielops_close_handle_manually_uv(struct lws *wsi) 471d4afb5ceSopenharmony_ci{ 472d4afb5ceSopenharmony_ci uv_handle_t *h = (uv_handle_t *)wsi_to_priv_uv(wsi)->w_read.pwatcher; 473d4afb5ceSopenharmony_ci 474d4afb5ceSopenharmony_ci lwsl_wsi_debug(wsi, "lws_libuv_closehandle"); 475d4afb5ceSopenharmony_ci 476d4afb5ceSopenharmony_ci /* 477d4afb5ceSopenharmony_ci * the "manual" variant only closes the handle itself and the 478d4afb5ceSopenharmony_ci * related fd. handle->data is the fd. 479d4afb5ceSopenharmony_ci */ 480d4afb5ceSopenharmony_ci h->data = (void *)(lws_intptr_t)wsi->desc.sockfd; 481d4afb5ceSopenharmony_ci 482d4afb5ceSopenharmony_ci /* 483d4afb5ceSopenharmony_ci * We take responsibility to close / destroy these now. 484d4afb5ceSopenharmony_ci * Remove any trace from the wsi. 485d4afb5ceSopenharmony_ci */ 486d4afb5ceSopenharmony_ci 487d4afb5ceSopenharmony_ci wsi->desc.sockfd = LWS_SOCK_INVALID; 488d4afb5ceSopenharmony_ci wsi_to_priv_uv(wsi)->w_read.pwatcher = NULL; 489d4afb5ceSopenharmony_ci wsi->told_event_loop_closed = 1; 490d4afb5ceSopenharmony_ci 491d4afb5ceSopenharmony_ci uv_close(h, lws_libuv_closewsi_m); 492d4afb5ceSopenharmony_ci} 493d4afb5ceSopenharmony_ci 494d4afb5ceSopenharmony_cistatic int 495d4afb5ceSopenharmony_cielops_accept_uv(struct lws *wsi) 496d4afb5ceSopenharmony_ci{ 497d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; 498d4afb5ceSopenharmony_ci struct lws_pt_eventlibs_libuv *ptpriv = pt_to_priv_uv(pt); 499d4afb5ceSopenharmony_ci struct lws_io_watcher_libuv *w_read = &wsi_to_priv_uv(wsi)->w_read; 500d4afb5ceSopenharmony_ci int n; 501d4afb5ceSopenharmony_ci 502d4afb5ceSopenharmony_ci if (!ptpriv->thread_valid) { 503d4afb5ceSopenharmony_ci /* record the thread id that gave us our first event */ 504d4afb5ceSopenharmony_ci ptpriv->uv_thread = uv_thread_self(); 505d4afb5ceSopenharmony_ci ptpriv->thread_valid = 1; 506d4afb5ceSopenharmony_ci } 507d4afb5ceSopenharmony_ci 508d4afb5ceSopenharmony_ci w_read->context = wsi->a.context; 509d4afb5ceSopenharmony_ci 510d4afb5ceSopenharmony_ci w_read->pwatcher = lws_malloc(sizeof(*w_read->pwatcher), "uvh"); 511d4afb5ceSopenharmony_ci if (!w_read->pwatcher) 512d4afb5ceSopenharmony_ci return -1; 513d4afb5ceSopenharmony_ci 514d4afb5ceSopenharmony_ci if (wsi->role_ops->file_handle) 515d4afb5ceSopenharmony_ci n = uv_poll_init(pt_to_priv_uv(pt)->io_loop, w_read->pwatcher, 516d4afb5ceSopenharmony_ci (int)(lws_intptr_t)wsi->desc.filefd); 517d4afb5ceSopenharmony_ci else 518d4afb5ceSopenharmony_ci n = uv_poll_init_socket(pt_to_priv_uv(pt)->io_loop, 519d4afb5ceSopenharmony_ci w_read->pwatcher, wsi->desc.sockfd); 520d4afb5ceSopenharmony_ci 521d4afb5ceSopenharmony_ci if (n) { 522d4afb5ceSopenharmony_ci lwsl_wsi_err(wsi, "uv_poll_init failed %d, sockfd=%p", n, 523d4afb5ceSopenharmony_ci (void *)(lws_intptr_t)wsi->desc.sockfd); 524d4afb5ceSopenharmony_ci lws_free(w_read->pwatcher); 525d4afb5ceSopenharmony_ci w_read->pwatcher = NULL; 526d4afb5ceSopenharmony_ci return -1; 527d4afb5ceSopenharmony_ci } 528d4afb5ceSopenharmony_ci 529d4afb5ceSopenharmony_ci ((uv_handle_t *)w_read->pwatcher)->data = (void *)wsi; 530d4afb5ceSopenharmony_ci 531d4afb5ceSopenharmony_ci ptpriv->extant_handles++; 532d4afb5ceSopenharmony_ci 533d4afb5ceSopenharmony_ci lwsl_wsi_debug(wsi, "thr %d: sa left %d: dyn left: %d", 534d4afb5ceSopenharmony_ci (int)(pt - &pt->context->pt[0]), 535d4afb5ceSopenharmony_ci pt->count_event_loop_static_asset_handles, 536d4afb5ceSopenharmony_ci ptpriv->extant_handles); 537d4afb5ceSopenharmony_ci 538d4afb5ceSopenharmony_ci return 0; 539d4afb5ceSopenharmony_ci} 540d4afb5ceSopenharmony_ci 541d4afb5ceSopenharmony_cistatic void 542d4afb5ceSopenharmony_cielops_io_uv(struct lws *wsi, unsigned int flags) 543d4afb5ceSopenharmony_ci{ 544d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; 545d4afb5ceSopenharmony_ci struct lws_io_watcher_libuv *w = &(wsi_to_priv_uv(wsi)->w_read); 546d4afb5ceSopenharmony_ci int current_events = w->actual_events & (UV_READABLE | UV_WRITABLE); 547d4afb5ceSopenharmony_ci 548d4afb5ceSopenharmony_ci lwsl_wsi_debug(wsi, "%d", flags); 549d4afb5ceSopenharmony_ci 550d4afb5ceSopenharmony_ci /* w->context is set after the loop is initialized */ 551d4afb5ceSopenharmony_ci 552d4afb5ceSopenharmony_ci if (!pt_to_priv_uv(pt)->io_loop || !w->context) { 553d4afb5ceSopenharmony_ci lwsl_wsi_info(wsi, "no io loop yet"); 554d4afb5ceSopenharmony_ci return; 555d4afb5ceSopenharmony_ci } 556d4afb5ceSopenharmony_ci 557d4afb5ceSopenharmony_ci if (!((flags & (LWS_EV_START | LWS_EV_STOP)) && 558d4afb5ceSopenharmony_ci (flags & (LWS_EV_READ | LWS_EV_WRITE)))) { 559d4afb5ceSopenharmony_ci lwsl_wsi_err(wsi, "assert: flags %d", flags); 560d4afb5ceSopenharmony_ci assert(0); 561d4afb5ceSopenharmony_ci } 562d4afb5ceSopenharmony_ci 563d4afb5ceSopenharmony_ci if (!w->pwatcher || wsi->told_event_loop_closed) { 564d4afb5ceSopenharmony_ci lwsl_wsi_info(wsi, "no watcher"); 565d4afb5ceSopenharmony_ci 566d4afb5ceSopenharmony_ci return; 567d4afb5ceSopenharmony_ci } 568d4afb5ceSopenharmony_ci 569d4afb5ceSopenharmony_ci if (flags & LWS_EV_START) { 570d4afb5ceSopenharmony_ci if (flags & LWS_EV_WRITE) 571d4afb5ceSopenharmony_ci current_events |= UV_WRITABLE; 572d4afb5ceSopenharmony_ci 573d4afb5ceSopenharmony_ci if (flags & LWS_EV_READ) 574d4afb5ceSopenharmony_ci current_events |= UV_READABLE; 575d4afb5ceSopenharmony_ci 576d4afb5ceSopenharmony_ci uv_poll_start(w->pwatcher, current_events, lws_io_cb); 577d4afb5ceSopenharmony_ci } else { 578d4afb5ceSopenharmony_ci if (flags & LWS_EV_WRITE) 579d4afb5ceSopenharmony_ci current_events &= ~UV_WRITABLE; 580d4afb5ceSopenharmony_ci 581d4afb5ceSopenharmony_ci if (flags & LWS_EV_READ) 582d4afb5ceSopenharmony_ci current_events &= ~UV_READABLE; 583d4afb5ceSopenharmony_ci 584d4afb5ceSopenharmony_ci if (!(current_events & (UV_READABLE | UV_WRITABLE))) 585d4afb5ceSopenharmony_ci uv_poll_stop(w->pwatcher); 586d4afb5ceSopenharmony_ci else 587d4afb5ceSopenharmony_ci uv_poll_start(w->pwatcher, current_events, lws_io_cb); 588d4afb5ceSopenharmony_ci } 589d4afb5ceSopenharmony_ci 590d4afb5ceSopenharmony_ci w->actual_events = (uint8_t)current_events; 591d4afb5ceSopenharmony_ci} 592d4afb5ceSopenharmony_ci 593d4afb5ceSopenharmony_cistatic int 594d4afb5ceSopenharmony_cielops_init_vhost_listen_wsi_uv(struct lws *wsi) 595d4afb5ceSopenharmony_ci{ 596d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt; 597d4afb5ceSopenharmony_ci struct lws_pt_eventlibs_libuv *ptpriv; 598d4afb5ceSopenharmony_ci struct lws_io_watcher_libuv *w_read; 599d4afb5ceSopenharmony_ci int n; 600d4afb5ceSopenharmony_ci 601d4afb5ceSopenharmony_ci if (!wsi) 602d4afb5ceSopenharmony_ci return 0; 603d4afb5ceSopenharmony_ci 604d4afb5ceSopenharmony_ci w_read = &wsi_to_priv_uv(wsi)->w_read; 605d4afb5ceSopenharmony_ci 606d4afb5ceSopenharmony_ci if (w_read->context) 607d4afb5ceSopenharmony_ci return 0; 608d4afb5ceSopenharmony_ci 609d4afb5ceSopenharmony_ci pt = &wsi->a.context->pt[(int)wsi->tsi]; 610d4afb5ceSopenharmony_ci ptpriv = pt_to_priv_uv(pt); 611d4afb5ceSopenharmony_ci if (!ptpriv->io_loop) 612d4afb5ceSopenharmony_ci return 0; 613d4afb5ceSopenharmony_ci 614d4afb5ceSopenharmony_ci w_read->context = wsi->a.context; 615d4afb5ceSopenharmony_ci 616d4afb5ceSopenharmony_ci w_read->pwatcher = lws_malloc(sizeof(*w_read->pwatcher), "uvh"); 617d4afb5ceSopenharmony_ci if (!w_read->pwatcher) 618d4afb5ceSopenharmony_ci return -1; 619d4afb5ceSopenharmony_ci 620d4afb5ceSopenharmony_ci n = uv_poll_init_socket(pt_to_priv_uv(pt)->io_loop, 621d4afb5ceSopenharmony_ci w_read->pwatcher, wsi->desc.sockfd); 622d4afb5ceSopenharmony_ci if (n) { 623d4afb5ceSopenharmony_ci lwsl_wsi_err(wsi, "uv_poll_init failed %d, sockfd=%p", n, 624d4afb5ceSopenharmony_ci (void *)(lws_intptr_t)wsi->desc.sockfd); 625d4afb5ceSopenharmony_ci 626d4afb5ceSopenharmony_ci return -1; 627d4afb5ceSopenharmony_ci } 628d4afb5ceSopenharmony_ci 629d4afb5ceSopenharmony_ci ptpriv->extant_handles++; 630d4afb5ceSopenharmony_ci 631d4afb5ceSopenharmony_ci lwsl_wsi_debug(wsi, "thr %d: sa left %d: dyn left: %d", 632d4afb5ceSopenharmony_ci (int)(pt - &pt->context->pt[0]), 633d4afb5ceSopenharmony_ci pt->count_event_loop_static_asset_handles, 634d4afb5ceSopenharmony_ci ptpriv->extant_handles); 635d4afb5ceSopenharmony_ci 636d4afb5ceSopenharmony_ci ((uv_handle_t *)w_read->pwatcher)->data = (void *)wsi; 637d4afb5ceSopenharmony_ci 638d4afb5ceSopenharmony_ci elops_io_uv(wsi, LWS_EV_START | LWS_EV_READ); 639d4afb5ceSopenharmony_ci 640d4afb5ceSopenharmony_ci return 0; 641d4afb5ceSopenharmony_ci} 642d4afb5ceSopenharmony_ci 643d4afb5ceSopenharmony_cistatic void 644d4afb5ceSopenharmony_cielops_run_pt_uv(struct lws_context *context, int tsi) 645d4afb5ceSopenharmony_ci{ 646d4afb5ceSopenharmony_ci if (pt_to_priv_uv(&context->pt[tsi])->io_loop) 647d4afb5ceSopenharmony_ci uv_run(pt_to_priv_uv(&context->pt[tsi])->io_loop, 0); 648d4afb5ceSopenharmony_ci} 649d4afb5ceSopenharmony_ci 650d4afb5ceSopenharmony_cistatic void 651d4afb5ceSopenharmony_cielops_destroy_pt_uv(struct lws_context *context, int tsi) 652d4afb5ceSopenharmony_ci{ 653d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &context->pt[tsi]; 654d4afb5ceSopenharmony_ci struct lws_pt_eventlibs_libuv *ptpriv = pt_to_priv_uv(pt); 655d4afb5ceSopenharmony_ci int m, ns; 656d4afb5ceSopenharmony_ci 657d4afb5ceSopenharmony_ci if (!lws_check_opt(context->options, LWS_SERVER_OPTION_LIBUV)) 658d4afb5ceSopenharmony_ci return; 659d4afb5ceSopenharmony_ci 660d4afb5ceSopenharmony_ci if (!ptpriv->io_loop) 661d4afb5ceSopenharmony_ci return; 662d4afb5ceSopenharmony_ci 663d4afb5ceSopenharmony_ci if (pt->event_loop_destroy_processing_done) { 664d4afb5ceSopenharmony_ci if (!pt->event_loop_foreign) { 665d4afb5ceSopenharmony_ci lwsl_warn("%s: stopping event loop\n", __func__); 666d4afb5ceSopenharmony_ci uv_stop(pt_to_priv_uv(pt)->io_loop); 667d4afb5ceSopenharmony_ci } 668d4afb5ceSopenharmony_ci return; 669d4afb5ceSopenharmony_ci } 670d4afb5ceSopenharmony_ci 671d4afb5ceSopenharmony_ci pt->event_loop_destroy_processing_done = 1; 672d4afb5ceSopenharmony_ci // lwsl_cx_debug(context, "%d", tsi); 673d4afb5ceSopenharmony_ci 674d4afb5ceSopenharmony_ci if (!pt->event_loop_foreign) { 675d4afb5ceSopenharmony_ci 676d4afb5ceSopenharmony_ci uv_signal_stop(&pt_to_priv_uv(pt)->w_sigint.watcher); 677d4afb5ceSopenharmony_ci 678d4afb5ceSopenharmony_ci ns = LWS_ARRAY_SIZE(sigs); 679d4afb5ceSopenharmony_ci if (lws_check_opt(context->options, 680d4afb5ceSopenharmony_ci LWS_SERVER_OPTION_UV_NO_SIGSEGV_SIGFPE_SPIN)) 681d4afb5ceSopenharmony_ci ns = 2; 682d4afb5ceSopenharmony_ci 683d4afb5ceSopenharmony_ci for (m = 0; m < ns; m++) { 684d4afb5ceSopenharmony_ci uv_signal_stop(&pt_to_priv_uv(pt)->signals[m]); 685d4afb5ceSopenharmony_ci uv_close((uv_handle_t *)&pt_to_priv_uv(pt)->signals[m], 686d4afb5ceSopenharmony_ci lws_uv_close_cb_sa); 687d4afb5ceSopenharmony_ci } 688d4afb5ceSopenharmony_ci } else 689d4afb5ceSopenharmony_ci lwsl_cx_debug(context, "not closing pt signals"); 690d4afb5ceSopenharmony_ci 691d4afb5ceSopenharmony_ci uv_timer_stop(&pt_to_priv_uv(pt)->sultimer); 692d4afb5ceSopenharmony_ci uv_close((uv_handle_t *)&pt_to_priv_uv(pt)->sultimer, lws_uv_close_cb_sa); 693d4afb5ceSopenharmony_ci 694d4afb5ceSopenharmony_ci uv_idle_stop(&pt_to_priv_uv(pt)->idle); 695d4afb5ceSopenharmony_ci uv_close((uv_handle_t *)&pt_to_priv_uv(pt)->idle, lws_uv_close_cb_sa); 696d4afb5ceSopenharmony_ci} 697d4afb5ceSopenharmony_ci 698d4afb5ceSopenharmony_cistatic int 699d4afb5ceSopenharmony_cielops_listen_init_uv(struct lws_dll2 *d, void *user) 700d4afb5ceSopenharmony_ci{ 701d4afb5ceSopenharmony_ci struct lws *wsi = lws_container_of(d, struct lws, listen_list); 702d4afb5ceSopenharmony_ci 703d4afb5ceSopenharmony_ci if (elops_init_vhost_listen_wsi_uv(wsi) == -1) 704d4afb5ceSopenharmony_ci return -1; 705d4afb5ceSopenharmony_ci 706d4afb5ceSopenharmony_ci return 0; 707d4afb5ceSopenharmony_ci} 708d4afb5ceSopenharmony_ci 709d4afb5ceSopenharmony_ci/* 710d4afb5ceSopenharmony_ci * This needs to be called after vhosts have been defined. 711d4afb5ceSopenharmony_ci * 712d4afb5ceSopenharmony_ci * If later, after server start, another vhost is added, this must be 713d4afb5ceSopenharmony_ci * called again to bind the vhost 714d4afb5ceSopenharmony_ci */ 715d4afb5ceSopenharmony_ci 716d4afb5ceSopenharmony_ciint 717d4afb5ceSopenharmony_cielops_init_pt_uv(struct lws_context *context, void *_loop, int tsi) 718d4afb5ceSopenharmony_ci{ 719d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &context->pt[tsi]; 720d4afb5ceSopenharmony_ci struct lws_pt_eventlibs_libuv *ptpriv = pt_to_priv_uv(pt); 721d4afb5ceSopenharmony_ci int status = 0, n, ns, first = 1; 722d4afb5ceSopenharmony_ci uv_loop_t *loop = (uv_loop_t *)_loop; 723d4afb5ceSopenharmony_ci 724d4afb5ceSopenharmony_ci ptpriv->pt = pt; 725d4afb5ceSopenharmony_ci 726d4afb5ceSopenharmony_ci if (!ptpriv->io_loop) { 727d4afb5ceSopenharmony_ci if (!loop) { 728d4afb5ceSopenharmony_ci loop = lws_malloc(sizeof(*loop), "libuv loop"); 729d4afb5ceSopenharmony_ci if (!loop) { 730d4afb5ceSopenharmony_ci lwsl_cx_err(context, "OOM"); 731d4afb5ceSopenharmony_ci return -1; 732d4afb5ceSopenharmony_ci } 733d4afb5ceSopenharmony_ci#if UV_VERSION_MAJOR > 0 734d4afb5ceSopenharmony_ci uv_loop_init(loop); 735d4afb5ceSopenharmony_ci#else 736d4afb5ceSopenharmony_ci lwsl_cx_err(context, "This libuv is too old to work..."); 737d4afb5ceSopenharmony_ci return 1; 738d4afb5ceSopenharmony_ci#endif 739d4afb5ceSopenharmony_ci pt->event_loop_foreign = 0; 740d4afb5ceSopenharmony_ci } else { 741d4afb5ceSopenharmony_ci lwsl_cx_notice(context, " Using foreign event loop..."); 742d4afb5ceSopenharmony_ci pt->event_loop_foreign = 1; 743d4afb5ceSopenharmony_ci } 744d4afb5ceSopenharmony_ci 745d4afb5ceSopenharmony_ci ptpriv->io_loop = loop; 746d4afb5ceSopenharmony_ci uv_idle_init(loop, &ptpriv->idle); 747d4afb5ceSopenharmony_ci LWS_UV_REFCOUNT_STATIC_HANDLE_NEW(&ptpriv->idle, pt); 748d4afb5ceSopenharmony_ci uv_idle_start(&ptpriv->idle, lws_uv_idle); 749d4afb5ceSopenharmony_ci 750d4afb5ceSopenharmony_ci ns = LWS_ARRAY_SIZE(sigs); 751d4afb5ceSopenharmony_ci if (lws_check_opt(context->options, 752d4afb5ceSopenharmony_ci LWS_SERVER_OPTION_UV_NO_SIGSEGV_SIGFPE_SPIN)) 753d4afb5ceSopenharmony_ci ns = 2; 754d4afb5ceSopenharmony_ci 755d4afb5ceSopenharmony_ci if (!pt->event_loop_foreign) { 756d4afb5ceSopenharmony_ci assert(ns <= (int)LWS_ARRAY_SIZE(ptpriv->signals)); 757d4afb5ceSopenharmony_ci for (n = 0; n < ns; n++) { 758d4afb5ceSopenharmony_ci uv_signal_init(loop, &ptpriv->signals[n]); 759d4afb5ceSopenharmony_ci LWS_UV_REFCOUNT_STATIC_HANDLE_NEW( 760d4afb5ceSopenharmony_ci &ptpriv->signals[n], pt); 761d4afb5ceSopenharmony_ci ptpriv->signals[n].data = pt; 762d4afb5ceSopenharmony_ci uv_signal_start(&ptpriv->signals[n], 763d4afb5ceSopenharmony_ci lws_uv_signal_handler, sigs[n]); 764d4afb5ceSopenharmony_ci } 765d4afb5ceSopenharmony_ci } 766d4afb5ceSopenharmony_ci } else 767d4afb5ceSopenharmony_ci first = 0; 768d4afb5ceSopenharmony_ci 769d4afb5ceSopenharmony_ci /* 770d4afb5ceSopenharmony_ci * Initialize the accept wsi read watcher with all the listening sockets 771d4afb5ceSopenharmony_ci * and register a callback for read operations 772d4afb5ceSopenharmony_ci * 773d4afb5ceSopenharmony_ci * We have to do it here because the uv loop(s) are not 774d4afb5ceSopenharmony_ci * initialized until after context creation. 775d4afb5ceSopenharmony_ci */ 776d4afb5ceSopenharmony_ci lws_vhost_foreach_listen_wsi(context, context, elops_listen_init_uv); 777d4afb5ceSopenharmony_ci 778d4afb5ceSopenharmony_ci if (!first) 779d4afb5ceSopenharmony_ci return status; 780d4afb5ceSopenharmony_ci 781d4afb5ceSopenharmony_ci uv_timer_init(ptpriv->io_loop, &ptpriv->sultimer); 782d4afb5ceSopenharmony_ci LWS_UV_REFCOUNT_STATIC_HANDLE_NEW(&ptpriv->sultimer, pt); 783d4afb5ceSopenharmony_ci 784d4afb5ceSopenharmony_ci return status; 785d4afb5ceSopenharmony_ci} 786d4afb5ceSopenharmony_ci 787d4afb5ceSopenharmony_cistatic void 788d4afb5ceSopenharmony_cilws_libuv_closewsi(uv_handle_t* handle) 789d4afb5ceSopenharmony_ci{ 790d4afb5ceSopenharmony_ci struct lws *wsi = (struct lws *)handle->data; 791d4afb5ceSopenharmony_ci struct lws_context *context = lws_get_context(wsi); 792d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; 793d4afb5ceSopenharmony_ci struct lws_pt_eventlibs_libuv *ptpriv = pt_to_priv_uv(pt); 794d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER) 795d4afb5ceSopenharmony_ci int lspd = 0; 796d4afb5ceSopenharmony_ci#endif 797d4afb5ceSopenharmony_ci 798d4afb5ceSopenharmony_ci // lwsl_wsi_notice(wsi, "in"); 799d4afb5ceSopenharmony_ci 800d4afb5ceSopenharmony_ci lws_context_lock(context, __func__); 801d4afb5ceSopenharmony_ci 802d4afb5ceSopenharmony_ci /* 803d4afb5ceSopenharmony_ci * We get called back here for every wsi that closes 804d4afb5ceSopenharmony_ci */ 805d4afb5ceSopenharmony_ci 806d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER) 807d4afb5ceSopenharmony_ci if (wsi->role_ops && !strcmp(wsi->role_ops->name, "listen") && 808d4afb5ceSopenharmony_ci wsi->a.context->deprecated) { 809d4afb5ceSopenharmony_ci lspd = 1; 810d4afb5ceSopenharmony_ci context->deprecation_pending_listen_close_count--; 811d4afb5ceSopenharmony_ci if (!context->deprecation_pending_listen_close_count) 812d4afb5ceSopenharmony_ci lspd = 2; 813d4afb5ceSopenharmony_ci } 814d4afb5ceSopenharmony_ci#endif 815d4afb5ceSopenharmony_ci 816d4afb5ceSopenharmony_ci lws_pt_lock(pt, __func__); 817d4afb5ceSopenharmony_ci 818d4afb5ceSopenharmony_ci lwsl_wsi_info(wsi, "thr %d: sa left %d: dyn left: %d (rk %d)", 819d4afb5ceSopenharmony_ci (int)(pt - &pt->context->pt[0]), 820d4afb5ceSopenharmony_ci pt->count_event_loop_static_asset_handles, 821d4afb5ceSopenharmony_ci ptpriv->extant_handles - 1, 822d4afb5ceSopenharmony_ci context->requested_stop_internal_loops); 823d4afb5ceSopenharmony_ci 824d4afb5ceSopenharmony_ci __lws_close_free_wsi_final(wsi); 825d4afb5ceSopenharmony_ci assert(ptpriv->extant_handles); 826d4afb5ceSopenharmony_ci ptpriv->extant_handles--; 827d4afb5ceSopenharmony_ci lws_pt_unlock(pt); 828d4afb5ceSopenharmony_ci 829d4afb5ceSopenharmony_ci /* it's our job to close the handle finally */ 830d4afb5ceSopenharmony_ci lws_free(handle); 831d4afb5ceSopenharmony_ci 832d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER) 833d4afb5ceSopenharmony_ci if (lspd == 2 && context->deprecation_cb) { 834d4afb5ceSopenharmony_ci lwsl_cx_notice(context, "calling deprecation callback"); 835d4afb5ceSopenharmony_ci context->deprecation_cb(); 836d4afb5ceSopenharmony_ci } 837d4afb5ceSopenharmony_ci#endif 838d4afb5ceSopenharmony_ci 839d4afb5ceSopenharmony_ci /* 840d4afb5ceSopenharmony_ci * eventually, we closed all the wsi... 841d4afb5ceSopenharmony_ci */ 842d4afb5ceSopenharmony_ci 843d4afb5ceSopenharmony_ci if (context->requested_stop_internal_loops && 844d4afb5ceSopenharmony_ci !ptpriv->extant_handles && 845d4afb5ceSopenharmony_ci !pt->count_event_loop_static_asset_handles) { 846d4afb5ceSopenharmony_ci 847d4afb5ceSopenharmony_ci /* 848d4afb5ceSopenharmony_ci * we closed everything on this pt 849d4afb5ceSopenharmony_ci */ 850d4afb5ceSopenharmony_ci 851d4afb5ceSopenharmony_ci lws_context_unlock(context); 852d4afb5ceSopenharmony_ci lws_uv_finalize_pt(pt); 853d4afb5ceSopenharmony_ci 854d4afb5ceSopenharmony_ci return; 855d4afb5ceSopenharmony_ci } 856d4afb5ceSopenharmony_ci 857d4afb5ceSopenharmony_ci lws_context_unlock(context); 858d4afb5ceSopenharmony_ci} 859d4afb5ceSopenharmony_ci 860d4afb5ceSopenharmony_civoid 861d4afb5ceSopenharmony_cilws_libuv_closehandle(struct lws *wsi) 862d4afb5ceSopenharmony_ci{ 863d4afb5ceSopenharmony_ci uv_handle_t* handle; 864d4afb5ceSopenharmony_ci struct lws_io_watcher_libuv *w_read = &wsi_to_priv_uv(wsi)->w_read; 865d4afb5ceSopenharmony_ci 866d4afb5ceSopenharmony_ci if (!w_read->pwatcher) 867d4afb5ceSopenharmony_ci return; 868d4afb5ceSopenharmony_ci 869d4afb5ceSopenharmony_ci if (wsi->told_event_loop_closed) 870d4afb5ceSopenharmony_ci return; 871d4afb5ceSopenharmony_ci 872d4afb5ceSopenharmony_ci// lwsl_wsi_debug(wsi, "in"); 873d4afb5ceSopenharmony_ci 874d4afb5ceSopenharmony_ci wsi->told_event_loop_closed = 1; 875d4afb5ceSopenharmony_ci 876d4afb5ceSopenharmony_ci /* 877d4afb5ceSopenharmony_ci * The normal close path attaches the related wsi as the 878d4afb5ceSopenharmony_ci * handle->data. 879d4afb5ceSopenharmony_ci */ 880d4afb5ceSopenharmony_ci 881d4afb5ceSopenharmony_ci handle = (uv_handle_t *)w_read->pwatcher; 882d4afb5ceSopenharmony_ci 883d4afb5ceSopenharmony_ci /* ensure we can only do this once */ 884d4afb5ceSopenharmony_ci 885d4afb5ceSopenharmony_ci w_read->pwatcher = NULL; 886d4afb5ceSopenharmony_ci 887d4afb5ceSopenharmony_ci uv_close(handle, lws_libuv_closewsi); 888d4afb5ceSopenharmony_ci} 889d4afb5ceSopenharmony_ci 890d4afb5ceSopenharmony_cistatic int 891d4afb5ceSopenharmony_cielops_foreign_thread_uv(struct lws_context *cx, int tsi) 892d4afb5ceSopenharmony_ci{ 893d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &cx->pt[tsi]; 894d4afb5ceSopenharmony_ci struct lws_pt_eventlibs_libuv *ptpriv = pt_to_priv_uv(pt); 895d4afb5ceSopenharmony_ci uv_thread_t th = uv_thread_self(); 896d4afb5ceSopenharmony_ci 897d4afb5ceSopenharmony_ci if (!ptpriv->thread_valid) 898d4afb5ceSopenharmony_ci /* 899d4afb5ceSopenharmony_ci * We can't judge it until we get the first event from the loop 900d4afb5ceSopenharmony_ci */ 901d4afb5ceSopenharmony_ci return 0; 902d4afb5ceSopenharmony_ci 903d4afb5ceSopenharmony_ci /* 904d4afb5ceSopenharmony_ci * This is the same thread that gave us the first event on this loop? 905d4afb5ceSopenharmony_ci * Return 0 if so. 906d4afb5ceSopenharmony_ci */ 907d4afb5ceSopenharmony_ci 908d4afb5ceSopenharmony_ci return !uv_thread_equal(&th, &ptpriv->uv_thread); 909d4afb5ceSopenharmony_ci} 910d4afb5ceSopenharmony_ci 911d4afb5ceSopenharmony_cistatic const struct lws_event_loop_ops event_loop_ops_uv = { 912d4afb5ceSopenharmony_ci /* name */ "libuv", 913d4afb5ceSopenharmony_ci /* init_context */ elops_init_context_uv, 914d4afb5ceSopenharmony_ci /* destroy_context1 */ elops_destroy_context1_uv, 915d4afb5ceSopenharmony_ci /* destroy_context2 */ elops_destroy_context2_uv, 916d4afb5ceSopenharmony_ci /* init_vhost_listen_wsi */ elops_init_vhost_listen_wsi_uv, 917d4afb5ceSopenharmony_ci /* init_pt */ elops_init_pt_uv, 918d4afb5ceSopenharmony_ci /* wsi_logical_close */ elops_wsi_logical_close_uv, 919d4afb5ceSopenharmony_ci /* check_client_connect_ok */ elops_check_client_connect_ok_uv, 920d4afb5ceSopenharmony_ci /* close_handle_manually */ elops_close_handle_manually_uv, 921d4afb5ceSopenharmony_ci /* accept */ elops_accept_uv, 922d4afb5ceSopenharmony_ci /* io */ elops_io_uv, 923d4afb5ceSopenharmony_ci /* run_pt */ elops_run_pt_uv, 924d4afb5ceSopenharmony_ci /* destroy_pt */ elops_destroy_pt_uv, 925d4afb5ceSopenharmony_ci /* destroy wsi */ NULL, 926d4afb5ceSopenharmony_ci /* foreign_thread */ elops_foreign_thread_uv, 927d4afb5ceSopenharmony_ci 928d4afb5ceSopenharmony_ci /* flags */ 0, 929d4afb5ceSopenharmony_ci 930d4afb5ceSopenharmony_ci /* evlib_size_ctx */ sizeof(struct lws_context_eventlibs_libuv), 931d4afb5ceSopenharmony_ci /* evlib_size_pt */ sizeof(struct lws_pt_eventlibs_libuv), 932d4afb5ceSopenharmony_ci /* evlib_size_vh */ 0, 933d4afb5ceSopenharmony_ci /* evlib_size_wsi */ sizeof(struct lws_io_watcher_libuv), 934d4afb5ceSopenharmony_ci}; 935d4afb5ceSopenharmony_ci 936d4afb5ceSopenharmony_ci#if defined(LWS_WITH_EVLIB_PLUGINS) 937d4afb5ceSopenharmony_ciLWS_VISIBLE 938d4afb5ceSopenharmony_ci#endif 939d4afb5ceSopenharmony_ciconst lws_plugin_evlib_t evlib_uv = { 940d4afb5ceSopenharmony_ci .hdr = { 941d4afb5ceSopenharmony_ci "libuv event loop", 942d4afb5ceSopenharmony_ci "lws_evlib_plugin", 943d4afb5ceSopenharmony_ci LWS_BUILD_HASH, 944d4afb5ceSopenharmony_ci LWS_PLUGIN_API_MAGIC 945d4afb5ceSopenharmony_ci }, 946d4afb5ceSopenharmony_ci 947d4afb5ceSopenharmony_ci .ops = &event_loop_ops_uv 948d4afb5ceSopenharmony_ci}; 949d4afb5ceSopenharmony_ci 950