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#ifndef _WINSOCK_DEPRECATED_NO_WARNINGS 26d4afb5ceSopenharmony_ci#define _WINSOCK_DEPRECATED_NO_WARNINGS 27d4afb5ceSopenharmony_ci#endif 28d4afb5ceSopenharmony_ci#include "private-lib-core.h" 29d4afb5ceSopenharmony_ci 30d4afb5ceSopenharmony_ci 31d4afb5ceSopenharmony_ciint 32d4afb5ceSopenharmony_ci_lws_plat_service_forced_tsi(struct lws_context *context, int tsi) 33d4afb5ceSopenharmony_ci{ 34d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &context->pt[tsi]; 35d4afb5ceSopenharmony_ci int m, n, r; 36d4afb5ceSopenharmony_ci 37d4afb5ceSopenharmony_ci r = lws_service_flag_pending(context, tsi); 38d4afb5ceSopenharmony_ci 39d4afb5ceSopenharmony_ci /* any socket with events to service? */ 40d4afb5ceSopenharmony_ci for (n = 0; n < (int)pt->fds_count; n++) { 41d4afb5ceSopenharmony_ci if (!pt->fds[n].revents) 42d4afb5ceSopenharmony_ci continue; 43d4afb5ceSopenharmony_ci 44d4afb5ceSopenharmony_ci unsigned int fds_count = pt->fds_count; 45d4afb5ceSopenharmony_ci m = lws_service_fd_tsi(context, &pt->fds[n], tsi); 46d4afb5ceSopenharmony_ci if (m < 0) 47d4afb5ceSopenharmony_ci return -1; 48d4afb5ceSopenharmony_ci /* if something closed, fds_count will change, retry this slot */ 49d4afb5ceSopenharmony_ci if (pt->fds_count != fds_count) 50d4afb5ceSopenharmony_ci n--; 51d4afb5ceSopenharmony_ci } 52d4afb5ceSopenharmony_ci 53d4afb5ceSopenharmony_ci lws_service_do_ripe_rxflow(pt); 54d4afb5ceSopenharmony_ci 55d4afb5ceSopenharmony_ci return r; 56d4afb5ceSopenharmony_ci} 57d4afb5ceSopenharmony_ci 58d4afb5ceSopenharmony_ciextern void lws_client_conn_wait_timeout(lws_sorted_usec_list_t *sul); 59d4afb5ceSopenharmony_ci 60d4afb5ceSopenharmony_ciint 61d4afb5ceSopenharmony_ci_lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) 62d4afb5ceSopenharmony_ci{ 63d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt; 64d4afb5ceSopenharmony_ci struct lws_pollfd *pfd; 65d4afb5ceSopenharmony_ci lws_usec_t timeout_us; 66d4afb5ceSopenharmony_ci struct lws *wsi; 67d4afb5ceSopenharmony_ci unsigned int i; 68d4afb5ceSopenharmony_ci int n; 69d4afb5ceSopenharmony_ci 70d4afb5ceSopenharmony_ci /* stay dead once we are dead */ 71d4afb5ceSopenharmony_ci if (context == NULL) 72d4afb5ceSopenharmony_ci return 1; 73d4afb5ceSopenharmony_ci 74d4afb5ceSopenharmony_ci pt = &context->pt[tsi]; 75d4afb5ceSopenharmony_ci 76d4afb5ceSopenharmony_ci if (!pt->service_tid_detected && context->vhost_list) { 77d4afb5ceSopenharmony_ci lws_fakewsi_def_plwsa(pt); 78d4afb5ceSopenharmony_ci 79d4afb5ceSopenharmony_ci lws_fakewsi_prep_plwsa_ctx(context); 80d4afb5ceSopenharmony_ci 81d4afb5ceSopenharmony_ci pt->service_tid = context->vhost_list-> 82d4afb5ceSopenharmony_ci protocols[0].callback((struct lws *)plwsa, 83d4afb5ceSopenharmony_ci LWS_CALLBACK_GET_THREAD_ID, 84d4afb5ceSopenharmony_ci NULL, NULL, 0); 85d4afb5ceSopenharmony_ci pt->service_tid_detected = 1; 86d4afb5ceSopenharmony_ci } 87d4afb5ceSopenharmony_ci 88d4afb5ceSopenharmony_ci if (timeout_ms < 0) 89d4afb5ceSopenharmony_ci timeout_ms = 0; 90d4afb5ceSopenharmony_ci else 91d4afb5ceSopenharmony_ci /* force a default timeout of 23 days */ 92d4afb5ceSopenharmony_ci timeout_ms = 2000000000; 93d4afb5ceSopenharmony_ci timeout_us = ((lws_usec_t)timeout_ms) * LWS_US_PER_MS; 94d4afb5ceSopenharmony_ci 95d4afb5ceSopenharmony_ci if (context->event_loop_ops->run_pt) 96d4afb5ceSopenharmony_ci context->event_loop_ops->run_pt(context, tsi); 97d4afb5ceSopenharmony_ci 98d4afb5ceSopenharmony_ci for (i = 0; i < pt->fds_count; ++i) { 99d4afb5ceSopenharmony_ci pfd = &pt->fds[i]; 100d4afb5ceSopenharmony_ci 101d4afb5ceSopenharmony_ci if (!(pfd->events & LWS_POLLOUT)) 102d4afb5ceSopenharmony_ci continue; 103d4afb5ceSopenharmony_ci 104d4afb5ceSopenharmony_ci wsi = wsi_from_fd(context, pfd->fd); 105d4afb5ceSopenharmony_ci if (!wsi || wsi->listener) 106d4afb5ceSopenharmony_ci continue; 107d4afb5ceSopenharmony_ci if (wsi->sock_send_blocking) 108d4afb5ceSopenharmony_ci continue; 109d4afb5ceSopenharmony_ci pfd->revents = LWS_POLLOUT; 110d4afb5ceSopenharmony_ci n = lws_service_fd(context, pfd); 111d4afb5ceSopenharmony_ci if (n < 0) 112d4afb5ceSopenharmony_ci return -1; 113d4afb5ceSopenharmony_ci 114d4afb5ceSopenharmony_ci /* 115d4afb5ceSopenharmony_ci * Force WSAWaitForMultipleEvents() to check events 116d4afb5ceSopenharmony_ci * and then return immediately. 117d4afb5ceSopenharmony_ci */ 118d4afb5ceSopenharmony_ci timeout_us = 0; 119d4afb5ceSopenharmony_ci 120d4afb5ceSopenharmony_ci /* if something closed, retry this slot */ 121d4afb5ceSopenharmony_ci if (n) 122d4afb5ceSopenharmony_ci i--; 123d4afb5ceSopenharmony_ci } 124d4afb5ceSopenharmony_ci 125d4afb5ceSopenharmony_ci /* 126d4afb5ceSopenharmony_ci * service pending callbacks and get maximum wait time 127d4afb5ceSopenharmony_ci */ 128d4afb5ceSopenharmony_ci { 129d4afb5ceSopenharmony_ci lws_usec_t us; 130d4afb5ceSopenharmony_ci 131d4afb5ceSopenharmony_ci lws_pt_lock(pt, __func__); 132d4afb5ceSopenharmony_ci /* don't stay in poll wait longer than next hr timeout */ 133d4afb5ceSopenharmony_ci us = __lws_sul_service_ripe(pt->pt_sul_owner, 134d4afb5ceSopenharmony_ci LWS_COUNT_PT_SUL_OWNERS, 135d4afb5ceSopenharmony_ci lws_now_usecs()); 136d4afb5ceSopenharmony_ci if (us && us < timeout_us) 137d4afb5ceSopenharmony_ci /* 138d4afb5ceSopenharmony_ci * If something wants zero wait, that's OK, but if the next sul 139d4afb5ceSopenharmony_ci * coming ripe is an interval less than our wait resolution, 140d4afb5ceSopenharmony_ci * bump it to be the wait resolution. 141d4afb5ceSopenharmony_ci */ 142d4afb5ceSopenharmony_ci timeout_us = us < context->us_wait_resolution ? 143d4afb5ceSopenharmony_ci context->us_wait_resolution : us; 144d4afb5ceSopenharmony_ci 145d4afb5ceSopenharmony_ci lws_pt_unlock(pt); 146d4afb5ceSopenharmony_ci } 147d4afb5ceSopenharmony_ci 148d4afb5ceSopenharmony_ci if (_lws_plat_service_forced_tsi(context, tsi)) 149d4afb5ceSopenharmony_ci timeout_us = 0; 150d4afb5ceSopenharmony_ci 151d4afb5ceSopenharmony_ci /* 152d4afb5ceSopenharmony_ci * is there anybody with pending stuff that needs service forcing? 153d4afb5ceSopenharmony_ci */ 154d4afb5ceSopenharmony_ci 155d4afb5ceSopenharmony_ci if (!lws_service_adjust_timeout(context, 1, tsi)) 156d4afb5ceSopenharmony_ci timeout_us = 0; 157d4afb5ceSopenharmony_ci 158d4afb5ceSopenharmony_ci// lwsl_notice("%s: in %dms, count %d\n", __func__, (int)(timeout_us / 1000), pt->fds_count); 159d4afb5ceSopenharmony_ci// for (n = 0; n < (int)pt->fds_count; n++) 160d4afb5ceSopenharmony_ci// lwsl_notice("%s: fd %d ev 0x%x POLLIN %d, POLLOUT %d\n", __func__, (int)pt->fds[n].fd, (int)pt->fds[n].events, POLLIN, POLLOUT); 161d4afb5ceSopenharmony_ci int d = WSAPoll((WSAPOLLFD *)&pt->fds[0], pt->fds_count, (int)(timeout_us / LWS_US_PER_MS)); 162d4afb5ceSopenharmony_ci if (d < 0) { 163d4afb5ceSopenharmony_ci lwsl_err("%s: WSAPoll failed: count %d, err %d: %d\n", __func__, pt->fds_count, d, WSAGetLastError()); 164d4afb5ceSopenharmony_ci return 0; 165d4afb5ceSopenharmony_ci } 166d4afb5ceSopenharmony_ci// lwsl_notice("%s: out\n", __func__); 167d4afb5ceSopenharmony_ci 168d4afb5ceSopenharmony_ci#if defined(LWS_WITH_TLS) 169d4afb5ceSopenharmony_ci if (pt->context->tls_ops && 170d4afb5ceSopenharmony_ci pt->context->tls_ops->fake_POLLIN_for_buffered) 171d4afb5ceSopenharmony_ci pt->context->tls_ops->fake_POLLIN_for_buffered(pt); 172d4afb5ceSopenharmony_ci#endif 173d4afb5ceSopenharmony_ci 174d4afb5ceSopenharmony_ci for (n = 0; n < (int)pt->fds_count; n++) 175d4afb5ceSopenharmony_ci if (pt->fds[n].fd != LWS_SOCK_INVALID && pt->fds[n].revents) { 176d4afb5ceSopenharmony_ci// lwsl_notice("%s: idx %d, revents 0x%x\n", __func__, n, pt->fds[n].revents); 177d4afb5ceSopenharmony_ci lws_service_fd_tsi(context, &pt->fds[n], tsi); 178d4afb5ceSopenharmony_ci } 179d4afb5ceSopenharmony_ci 180d4afb5ceSopenharmony_ci return 0; 181d4afb5ceSopenharmony_ci} 182d4afb5ceSopenharmony_ci 183d4afb5ceSopenharmony_ciint 184d4afb5ceSopenharmony_cilws_plat_service(struct lws_context *context, int timeout_ms) 185d4afb5ceSopenharmony_ci{ 186d4afb5ceSopenharmony_ci return _lws_plat_service_tsi(context, timeout_ms, 0); 187d4afb5ceSopenharmony_ci} 188