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-uloop.h" 27d4afb5ceSopenharmony_ci 28d4afb5ceSopenharmony_ci#define pt_to_priv_uloop(_pt) ((struct lws_pt_eventlibs_uloop *)(_pt)->evlib_pt) 29d4afb5ceSopenharmony_ci#define wsi_to_priv_uloop(_w) ((struct lws_wsi_eventlibs_uloop *)(_w)->evlib_wsi) 30d4afb5ceSopenharmony_ci 31d4afb5ceSopenharmony_cistatic void 32d4afb5ceSopenharmony_cilws_uloop_hrtimer_cb(struct uloop_timeout *ti) 33d4afb5ceSopenharmony_ci{ 34d4afb5ceSopenharmony_ci struct lws_pt_eventlibs_uloop *upt = lws_container_of(ti, 35d4afb5ceSopenharmony_ci struct lws_pt_eventlibs_uloop, hrtimer); 36d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = upt->pt; 37d4afb5ceSopenharmony_ci lws_usec_t us; 38d4afb5ceSopenharmony_ci 39d4afb5ceSopenharmony_ci lws_pt_lock(pt, __func__); 40d4afb5ceSopenharmony_ci us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS, 41d4afb5ceSopenharmony_ci lws_now_usecs()); 42d4afb5ceSopenharmony_ci if (us) 43d4afb5ceSopenharmony_ci uloop_timeout_set(ti, us < 1000 ? 1 : (int)(us / 1000)); 44d4afb5ceSopenharmony_ci 45d4afb5ceSopenharmony_ci lws_pt_unlock(pt); 46d4afb5ceSopenharmony_ci} 47d4afb5ceSopenharmony_ci 48d4afb5ceSopenharmony_cistatic void 49d4afb5ceSopenharmony_cilws_uloop_idle_timer_cb(struct uloop_timeout *ti) 50d4afb5ceSopenharmony_ci{ 51d4afb5ceSopenharmony_ci struct lws_pt_eventlibs_uloop *upt = lws_container_of(ti, 52d4afb5ceSopenharmony_ci struct lws_pt_eventlibs_uloop, 53d4afb5ceSopenharmony_ci idle_timer); 54d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = upt->pt; 55d4afb5ceSopenharmony_ci lws_usec_t us; 56d4afb5ceSopenharmony_ci 57d4afb5ceSopenharmony_ci if (pt->is_destroyed) 58d4afb5ceSopenharmony_ci return; 59d4afb5ceSopenharmony_ci 60d4afb5ceSopenharmony_ci lws_service_do_ripe_rxflow(pt); 61d4afb5ceSopenharmony_ci 62d4afb5ceSopenharmony_ci /* 63d4afb5ceSopenharmony_ci * is there anybody with pending stuff that needs service forcing? 64d4afb5ceSopenharmony_ci */ 65d4afb5ceSopenharmony_ci if (!lws_service_adjust_timeout(pt->context, 1, pt->tid)) { 66d4afb5ceSopenharmony_ci /* -1 timeout means just do forced service */ 67d4afb5ceSopenharmony_ci _lws_plat_service_forced_tsi(pt->context, pt->tid); 68d4afb5ceSopenharmony_ci /* still somebody left who wants forced service? */ 69d4afb5ceSopenharmony_ci if (!lws_service_adjust_timeout(pt->context, 1, pt->tid)) { 70d4afb5ceSopenharmony_ci /* yes... come back again later */ 71d4afb5ceSopenharmony_ci 72d4afb5ceSopenharmony_ci uloop_timeout_set(ti, 1 /* 1ms */); 73d4afb5ceSopenharmony_ci 74d4afb5ceSopenharmony_ci return; 75d4afb5ceSopenharmony_ci } 76d4afb5ceSopenharmony_ci } 77d4afb5ceSopenharmony_ci 78d4afb5ceSopenharmony_ci /* account for hrtimer */ 79d4afb5ceSopenharmony_ci 80d4afb5ceSopenharmony_ci lws_pt_lock(pt, __func__); 81d4afb5ceSopenharmony_ci us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS, 82d4afb5ceSopenharmony_ci lws_now_usecs()); 83d4afb5ceSopenharmony_ci if (us) { 84d4afb5ceSopenharmony_ci uloop_timeout_cancel(&upt->hrtimer); 85d4afb5ceSopenharmony_ci uloop_timeout_set(&upt->hrtimer, 86d4afb5ceSopenharmony_ci us < 1000 ? 1 : (int)(us / 1000)); 87d4afb5ceSopenharmony_ci } 88d4afb5ceSopenharmony_ci 89d4afb5ceSopenharmony_ci lws_pt_unlock(pt); 90d4afb5ceSopenharmony_ci 91d4afb5ceSopenharmony_ci if (pt->destroy_self) 92d4afb5ceSopenharmony_ci lws_context_destroy(pt->context); 93d4afb5ceSopenharmony_ci} 94d4afb5ceSopenharmony_ci 95d4afb5ceSopenharmony_cistatic void 96d4afb5ceSopenharmony_cilws_uloop_cb(struct uloop_fd *ufd, unsigned int revents) 97d4afb5ceSopenharmony_ci{ 98d4afb5ceSopenharmony_ci struct lws_wsi_eventlibs_uloop *wu = lws_container_of(ufd, 99d4afb5ceSopenharmony_ci struct lws_wsi_eventlibs_uloop, fd); 100d4afb5ceSopenharmony_ci struct lws_context *context = wu->wsi->a.context; 101d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt; 102d4afb5ceSopenharmony_ci struct lws_pollfd eventfd; 103d4afb5ceSopenharmony_ci 104d4afb5ceSopenharmony_ci eventfd.fd = wu->wsi->desc.sockfd; 105d4afb5ceSopenharmony_ci eventfd.events = 0; 106d4afb5ceSopenharmony_ci eventfd.revents = 0; 107d4afb5ceSopenharmony_ci 108d4afb5ceSopenharmony_ci if (revents & ULOOP_READ) { 109d4afb5ceSopenharmony_ci eventfd.events = LWS_POLLIN; 110d4afb5ceSopenharmony_ci eventfd.revents = LWS_POLLIN; 111d4afb5ceSopenharmony_ci } 112d4afb5ceSopenharmony_ci if (revents & ULOOP_WRITE) { 113d4afb5ceSopenharmony_ci eventfd.events |= LWS_POLLOUT; 114d4afb5ceSopenharmony_ci eventfd.revents |= LWS_POLLOUT; 115d4afb5ceSopenharmony_ci } 116d4afb5ceSopenharmony_ci 117d4afb5ceSopenharmony_ci pt = &context->pt[(int)wu->wsi->tsi]; 118d4afb5ceSopenharmony_ci if (pt->is_destroyed) 119d4afb5ceSopenharmony_ci return; 120d4afb5ceSopenharmony_ci 121d4afb5ceSopenharmony_ci lws_service_fd_tsi(context, &eventfd, wu->wsi->tsi); 122d4afb5ceSopenharmony_ci 123d4afb5ceSopenharmony_ci if (pt->destroy_self) { 124d4afb5ceSopenharmony_ci lwsl_cx_notice(context, "pt destroy self coming true"); 125d4afb5ceSopenharmony_ci lws_context_destroy(pt->context); 126d4afb5ceSopenharmony_ci return; 127d4afb5ceSopenharmony_ci } 128d4afb5ceSopenharmony_ci 129d4afb5ceSopenharmony_ci /* set the idle timer for 1ms ahead */ 130d4afb5ceSopenharmony_ci 131d4afb5ceSopenharmony_ci uloop_timeout_cancel(&pt_to_priv_uloop(pt)->idle_timer); 132d4afb5ceSopenharmony_ci uloop_timeout_set(&pt_to_priv_uloop(pt)->idle_timer, 1); 133d4afb5ceSopenharmony_ci} 134d4afb5ceSopenharmony_ci 135d4afb5ceSopenharmony_cistatic int 136d4afb5ceSopenharmony_cielops_listen_init_uloop(struct lws_dll2 *d, void *user) 137d4afb5ceSopenharmony_ci{ 138d4afb5ceSopenharmony_ci struct lws *wsi = lws_container_of(d, struct lws, listen_list); 139d4afb5ceSopenharmony_ci struct lws_wsi_eventlibs_uloop *wu = wsi_to_priv_uloop(wsi); 140d4afb5ceSopenharmony_ci 141d4afb5ceSopenharmony_ci wu->wsi = wsi; 142d4afb5ceSopenharmony_ci wu->fd.fd = wsi->desc.sockfd; 143d4afb5ceSopenharmony_ci wu->fd.cb = lws_uloop_cb; 144d4afb5ceSopenharmony_ci uloop_fd_add(&wu->fd, ULOOP_READ); 145d4afb5ceSopenharmony_ci wu->actual_events = ULOOP_READ; 146d4afb5ceSopenharmony_ci 147d4afb5ceSopenharmony_ci return 0; 148d4afb5ceSopenharmony_ci} 149d4afb5ceSopenharmony_ci 150d4afb5ceSopenharmony_cistatic int 151d4afb5ceSopenharmony_cielops_init_pt_uloop(struct lws_context *context, void *v, int tsi) 152d4afb5ceSopenharmony_ci{ 153d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &context->pt[tsi]; 154d4afb5ceSopenharmony_ci struct lws_pt_eventlibs_uloop *ptpr = pt_to_priv_uloop(pt); 155d4afb5ceSopenharmony_ci 156d4afb5ceSopenharmony_ci ptpr->pt = pt; 157d4afb5ceSopenharmony_ci 158d4afb5ceSopenharmony_ci lws_vhost_foreach_listen_wsi(context, NULL, elops_listen_init_uloop); 159d4afb5ceSopenharmony_ci 160d4afb5ceSopenharmony_ci /* static event loop objects */ 161d4afb5ceSopenharmony_ci 162d4afb5ceSopenharmony_ci ptpr->hrtimer.cb = lws_uloop_hrtimer_cb; 163d4afb5ceSopenharmony_ci ptpr->idle_timer.cb = lws_uloop_idle_timer_cb; 164d4afb5ceSopenharmony_ci 165d4afb5ceSopenharmony_ci uloop_timeout_add(&ptpr->hrtimer); 166d4afb5ceSopenharmony_ci uloop_timeout_add(&ptpr->idle_timer); 167d4afb5ceSopenharmony_ci 168d4afb5ceSopenharmony_ci uloop_timeout_set(&ptpr->hrtimer, 1); 169d4afb5ceSopenharmony_ci 170d4afb5ceSopenharmony_ci return 0; 171d4afb5ceSopenharmony_ci} 172d4afb5ceSopenharmony_ci 173d4afb5ceSopenharmony_cistatic int 174d4afb5ceSopenharmony_cielops_accept_uloop(struct lws *wsi) 175d4afb5ceSopenharmony_ci{ 176d4afb5ceSopenharmony_ci struct lws_wsi_eventlibs_uloop *wu = wsi_to_priv_uloop(wsi); 177d4afb5ceSopenharmony_ci 178d4afb5ceSopenharmony_ci wu->wsi = wsi; 179d4afb5ceSopenharmony_ci wu->fd.fd = wsi->desc.sockfd; 180d4afb5ceSopenharmony_ci wu->fd.cb = lws_uloop_cb; 181d4afb5ceSopenharmony_ci uloop_fd_add(&wu->fd, ULOOP_READ); 182d4afb5ceSopenharmony_ci wu->actual_events = ULOOP_READ; 183d4afb5ceSopenharmony_ci 184d4afb5ceSopenharmony_ci return 0; 185d4afb5ceSopenharmony_ci} 186d4afb5ceSopenharmony_ci 187d4afb5ceSopenharmony_cistatic void 188d4afb5ceSopenharmony_cielops_io_uloop(struct lws *wsi, unsigned int flags) 189d4afb5ceSopenharmony_ci{ 190d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; 191d4afb5ceSopenharmony_ci struct lws_wsi_eventlibs_uloop *wu = wsi_to_priv_uloop(wsi); 192d4afb5ceSopenharmony_ci unsigned int ulf = (unsigned int)(((flags & LWS_EV_WRITE) ? ULOOP_WRITE : 0) | 193d4afb5ceSopenharmony_ci ((flags & LWS_EV_READ) ? ULOOP_READ : 0)), u; 194d4afb5ceSopenharmony_ci 195d4afb5ceSopenharmony_ci if (wsi->a.context->being_destroyed || pt->is_destroyed) 196d4afb5ceSopenharmony_ci return; 197d4afb5ceSopenharmony_ci 198d4afb5ceSopenharmony_ci assert((flags & (LWS_EV_START | LWS_EV_STOP)) && 199d4afb5ceSopenharmony_ci (flags & (LWS_EV_READ | LWS_EV_WRITE))); 200d4afb5ceSopenharmony_ci 201d4afb5ceSopenharmony_ci u = wu->actual_events; 202d4afb5ceSopenharmony_ci if (flags & LWS_EV_START) 203d4afb5ceSopenharmony_ci u |= ulf; 204d4afb5ceSopenharmony_ci if (flags & LWS_EV_STOP) 205d4afb5ceSopenharmony_ci u &= ~ulf; 206d4afb5ceSopenharmony_ci 207d4afb5ceSopenharmony_ci uloop_fd_add(&wu->fd, u); 208d4afb5ceSopenharmony_ci wu->actual_events = u; 209d4afb5ceSopenharmony_ci} 210d4afb5ceSopenharmony_ci 211d4afb5ceSopenharmony_cistatic void 212d4afb5ceSopenharmony_cielops_run_pt_uloop(struct lws_context *context, int tsi) 213d4afb5ceSopenharmony_ci{ 214d4afb5ceSopenharmony_ci uloop_run(); 215d4afb5ceSopenharmony_ci} 216d4afb5ceSopenharmony_ci 217d4afb5ceSopenharmony_cistatic int 218d4afb5ceSopenharmony_cielops_listen_destroy_uloop(struct lws_dll2 *d, void *user) 219d4afb5ceSopenharmony_ci{ 220d4afb5ceSopenharmony_ci struct lws *wsi = lws_container_of(d, struct lws, listen_list); 221d4afb5ceSopenharmony_ci struct lws_wsi_eventlibs_uloop *wu = wsi_to_priv_uloop(wsi); 222d4afb5ceSopenharmony_ci 223d4afb5ceSopenharmony_ci uloop_fd_delete(&wu->fd); 224d4afb5ceSopenharmony_ci 225d4afb5ceSopenharmony_ci return 0; 226d4afb5ceSopenharmony_ci} 227d4afb5ceSopenharmony_ci 228d4afb5ceSopenharmony_cistatic void 229d4afb5ceSopenharmony_cielops_destroy_pt_uloop(struct lws_context *context, int tsi) 230d4afb5ceSopenharmony_ci{ 231d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &context->pt[tsi]; 232d4afb5ceSopenharmony_ci struct lws_pt_eventlibs_uloop *ptpr = pt_to_priv_uloop(pt); 233d4afb5ceSopenharmony_ci 234d4afb5ceSopenharmony_ci lws_vhost_foreach_listen_wsi(context, NULL, elops_listen_destroy_uloop); 235d4afb5ceSopenharmony_ci 236d4afb5ceSopenharmony_ci uloop_timeout_cancel(&ptpr->hrtimer); 237d4afb5ceSopenharmony_ci uloop_timeout_cancel(&ptpr->idle_timer); 238d4afb5ceSopenharmony_ci} 239d4afb5ceSopenharmony_ci 240d4afb5ceSopenharmony_cistatic void 241d4afb5ceSopenharmony_cielops_destroy_wsi_uloop(struct lws *wsi) 242d4afb5ceSopenharmony_ci{ 243d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt; 244d4afb5ceSopenharmony_ci 245d4afb5ceSopenharmony_ci if (!wsi) 246d4afb5ceSopenharmony_ci return; 247d4afb5ceSopenharmony_ci 248d4afb5ceSopenharmony_ci pt = &wsi->a.context->pt[(int)wsi->tsi]; 249d4afb5ceSopenharmony_ci if (pt->is_destroyed) 250d4afb5ceSopenharmony_ci return; 251d4afb5ceSopenharmony_ci 252d4afb5ceSopenharmony_ci uloop_fd_delete(&wsi_to_priv_uloop(wsi)->fd); 253d4afb5ceSopenharmony_ci} 254d4afb5ceSopenharmony_ci 255d4afb5ceSopenharmony_cistatic int 256d4afb5ceSopenharmony_cielops_wsi_logical_close_uloop(struct lws *wsi) 257d4afb5ceSopenharmony_ci{ 258d4afb5ceSopenharmony_ci elops_destroy_wsi_uloop(wsi); 259d4afb5ceSopenharmony_ci 260d4afb5ceSopenharmony_ci return 0; 261d4afb5ceSopenharmony_ci} 262d4afb5ceSopenharmony_ci 263d4afb5ceSopenharmony_cistatic int 264d4afb5ceSopenharmony_cielops_init_vhost_listen_wsi_uloop(struct lws *wsi) 265d4afb5ceSopenharmony_ci{ 266d4afb5ceSopenharmony_ci struct lws_wsi_eventlibs_uloop *wu; 267d4afb5ceSopenharmony_ci 268d4afb5ceSopenharmony_ci if (!wsi) { 269d4afb5ceSopenharmony_ci assert(0); 270d4afb5ceSopenharmony_ci return 0; 271d4afb5ceSopenharmony_ci } 272d4afb5ceSopenharmony_ci 273d4afb5ceSopenharmony_ci wu = wsi_to_priv_uloop(wsi); 274d4afb5ceSopenharmony_ci wu->wsi = wsi; 275d4afb5ceSopenharmony_ci wu->fd.fd = wsi->desc.sockfd; 276d4afb5ceSopenharmony_ci wu->fd.cb = lws_uloop_cb; 277d4afb5ceSopenharmony_ci uloop_fd_add(&wu->fd, ULOOP_READ); 278d4afb5ceSopenharmony_ci 279d4afb5ceSopenharmony_ci wu->actual_events = ULOOP_READ; 280d4afb5ceSopenharmony_ci 281d4afb5ceSopenharmony_ci return 0; 282d4afb5ceSopenharmony_ci} 283d4afb5ceSopenharmony_ci 284d4afb5ceSopenharmony_cistatic const struct lws_event_loop_ops event_loop_ops_uloop = { 285d4afb5ceSopenharmony_ci /* name */ "uloop", 286d4afb5ceSopenharmony_ci /* init_context */ NULL, 287d4afb5ceSopenharmony_ci /* destroy_context1 */ NULL, 288d4afb5ceSopenharmony_ci /* destroy_context2 */ NULL, 289d4afb5ceSopenharmony_ci /* init_vhost_listen_wsi */ elops_init_vhost_listen_wsi_uloop, 290d4afb5ceSopenharmony_ci /* init_pt */ elops_init_pt_uloop, 291d4afb5ceSopenharmony_ci /* wsi_logical_close */ elops_wsi_logical_close_uloop, 292d4afb5ceSopenharmony_ci /* check_client_connect_ok */ NULL, 293d4afb5ceSopenharmony_ci /* close_handle_manually */ NULL, 294d4afb5ceSopenharmony_ci /* accept */ elops_accept_uloop, 295d4afb5ceSopenharmony_ci /* io */ elops_io_uloop, 296d4afb5ceSopenharmony_ci /* run_pt */ elops_run_pt_uloop, 297d4afb5ceSopenharmony_ci /* destroy_pt */ elops_destroy_pt_uloop, 298d4afb5ceSopenharmony_ci /* destroy wsi */ elops_destroy_wsi_uloop, 299d4afb5ceSopenharmony_ci /* foreign_thread */ NULL, 300d4afb5ceSopenharmony_ci 301d4afb5ceSopenharmony_ci /* flags */ 0, 302d4afb5ceSopenharmony_ci 303d4afb5ceSopenharmony_ci /* evlib_size_ctx */ 0, 304d4afb5ceSopenharmony_ci /* evlib_size_pt */ sizeof(struct lws_pt_eventlibs_uloop), 305d4afb5ceSopenharmony_ci /* evlib_size_vh */ 0, 306d4afb5ceSopenharmony_ci /* evlib_size_wsi */ sizeof(struct lws_wsi_eventlibs_uloop), 307d4afb5ceSopenharmony_ci}; 308d4afb5ceSopenharmony_ci 309d4afb5ceSopenharmony_ci#if defined(LWS_WITH_EVLIB_PLUGINS) 310d4afb5ceSopenharmony_ciLWS_VISIBLE 311d4afb5ceSopenharmony_ci#endif 312d4afb5ceSopenharmony_ciconst lws_plugin_evlib_t evlib_uloop = { 313d4afb5ceSopenharmony_ci .hdr = { 314d4afb5ceSopenharmony_ci "uloop event loop", 315d4afb5ceSopenharmony_ci "lws_evlib_plugin", 316d4afb5ceSopenharmony_ci LWS_BUILD_HASH, 317d4afb5ceSopenharmony_ci LWS_PLUGIN_API_MAGIC 318d4afb5ceSopenharmony_ci }, 319d4afb5ceSopenharmony_ci 320d4afb5ceSopenharmony_ci .ops = &event_loop_ops_uloop 321d4afb5ceSopenharmony_ci}; 322