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_ciint 28d4afb5ceSopenharmony_cilws_plat_service(struct lws_context *context, int timeout_ms) 29d4afb5ceSopenharmony_ci{ 30d4afb5ceSopenharmony_ci int n = _lws_plat_service_tsi(context, timeout_ms, 0); 31d4afb5ceSopenharmony_ci 32d4afb5ceSopenharmony_ci#if !defined(LWS_AMAZON_RTOS) 33d4afb5ceSopenharmony_ci esp_task_wdt_reset(); 34d4afb5ceSopenharmony_ci#endif 35d4afb5ceSopenharmony_ci 36d4afb5ceSopenharmony_ci return n; 37d4afb5ceSopenharmony_ci} 38d4afb5ceSopenharmony_ci 39d4afb5ceSopenharmony_ci 40d4afb5ceSopenharmony_ciint 41d4afb5ceSopenharmony_ci_lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) 42d4afb5ceSopenharmony_ci{ 43d4afb5ceSopenharmony_ci volatile struct lws_context_per_thread *vpt; 44d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt; 45d4afb5ceSopenharmony_ci lws_usec_t timeout_us; 46d4afb5ceSopenharmony_ci int n = -1, m, c, a = 0; 47d4afb5ceSopenharmony_ci 48d4afb5ceSopenharmony_ci /* stay dead once we are dead */ 49d4afb5ceSopenharmony_ci 50d4afb5ceSopenharmony_ci if (!context) 51d4afb5ceSopenharmony_ci return 1; 52d4afb5ceSopenharmony_ci 53d4afb5ceSopenharmony_ci pt = &context->pt[tsi]; 54d4afb5ceSopenharmony_ci vpt = (volatile struct lws_context_per_thread *)pt; 55d4afb5ceSopenharmony_ci 56d4afb5ceSopenharmony_ci { 57d4afb5ceSopenharmony_ci unsigned long m = lws_now_secs(); 58d4afb5ceSopenharmony_ci 59d4afb5ceSopenharmony_ci if (m > context->time_last_state_dump) { 60d4afb5ceSopenharmony_ci context->time_last_state_dump = m; 61d4afb5ceSopenharmony_ci#if defined(LWS_ESP_PLATFORM) 62d4afb5ceSopenharmony_ci n = esp_get_free_heap_size(); 63d4afb5ceSopenharmony_ci#else 64d4afb5ceSopenharmony_ci n = xPortGetFreeHeapSize(); 65d4afb5ceSopenharmony_ci#endif 66d4afb5ceSopenharmony_ci if ((unsigned int)n != context->last_free_heap) { 67d4afb5ceSopenharmony_ci if ((unsigned int)n > context->last_free_heap) 68d4afb5ceSopenharmony_ci lwsl_debug(" heap :%ld (+%ld)\n", 69d4afb5ceSopenharmony_ci (unsigned long)n, 70d4afb5ceSopenharmony_ci (unsigned long)(n - 71d4afb5ceSopenharmony_ci context->last_free_heap)); 72d4afb5ceSopenharmony_ci else 73d4afb5ceSopenharmony_ci lwsl_debug(" heap :%ld (-%ld)\n", 74d4afb5ceSopenharmony_ci (unsigned long)n, 75d4afb5ceSopenharmony_ci (unsigned long)( 76d4afb5ceSopenharmony_ci context->last_free_heap - 77d4afb5ceSopenharmony_ci n)); 78d4afb5ceSopenharmony_ci context->last_free_heap = n; 79d4afb5ceSopenharmony_ci } 80d4afb5ceSopenharmony_ci } 81d4afb5ceSopenharmony_ci } 82d4afb5ceSopenharmony_ci 83d4afb5ceSopenharmony_ci if (timeout_ms < 0) 84d4afb5ceSopenharmony_ci timeout_ms = 0; 85d4afb5ceSopenharmony_ci else 86d4afb5ceSopenharmony_ci /* force a default timeout of 23 days */ 87d4afb5ceSopenharmony_ci timeout_ms = 2000000000; 88d4afb5ceSopenharmony_ci timeout_us = ((lws_usec_t)timeout_ms) * LWS_US_PER_MS; 89d4afb5ceSopenharmony_ci 90d4afb5ceSopenharmony_ci if (!pt->service_tid_detected && context->vhost_list) { 91d4afb5ceSopenharmony_ci lws_fakewsi_def_plwsa(pt); 92d4afb5ceSopenharmony_ci 93d4afb5ceSopenharmony_ci lws_fakewsi_prep_plwsa_ctx(context); 94d4afb5ceSopenharmony_ci 95d4afb5ceSopenharmony_ci pt->service_tid = context->vhost_list->protocols[0].callback( 96d4afb5ceSopenharmony_ci (struct lws *)plwsa, LWS_CALLBACK_GET_THREAD_ID, 97d4afb5ceSopenharmony_ci NULL, NULL, 0); 98d4afb5ceSopenharmony_ci pt->service_tid_detected = 1; 99d4afb5ceSopenharmony_ci } 100d4afb5ceSopenharmony_ci 101d4afb5ceSopenharmony_ci /* 102d4afb5ceSopenharmony_ci * is there anybody with pending stuff that needs service forcing? 103d4afb5ceSopenharmony_ci */ 104d4afb5ceSopenharmony_ci#if !defined(LWS_AMAZON_RTOS) 105d4afb5ceSopenharmony_ciagain: 106d4afb5ceSopenharmony_ci#endif 107d4afb5ceSopenharmony_ci n = 0; 108d4afb5ceSopenharmony_ci if (lws_service_adjust_timeout(context, 1, tsi)) { 109d4afb5ceSopenharmony_ci#if defined(LWS_AMAZON_RTOS) 110d4afb5ceSopenharmony_ciagain: 111d4afb5ceSopenharmony_ci#endif /* LWS_AMAZON_RTOS */ 112d4afb5ceSopenharmony_ci 113d4afb5ceSopenharmony_ci a = 0; 114d4afb5ceSopenharmony_ci if (timeout_us) { 115d4afb5ceSopenharmony_ci lws_usec_t us; 116d4afb5ceSopenharmony_ci 117d4afb5ceSopenharmony_ci lws_pt_lock(pt, __func__); 118d4afb5ceSopenharmony_ci /* don't stay in poll wait longer than next hr timeout */ 119d4afb5ceSopenharmony_ci us = __lws_sul_service_ripe(pt->pt_sul_owner, 120d4afb5ceSopenharmony_ci LWS_COUNT_PT_SUL_OWNERS, 121d4afb5ceSopenharmony_ci lws_now_usecs()); 122d4afb5ceSopenharmony_ci if (us && us < timeout_us) 123d4afb5ceSopenharmony_ci timeout_us = us; 124d4afb5ceSopenharmony_ci 125d4afb5ceSopenharmony_ci lws_pt_unlock(pt); 126d4afb5ceSopenharmony_ci } 127d4afb5ceSopenharmony_ci 128d4afb5ceSopenharmony_ci // n = poll(pt->fds, pt->fds_count, timeout_ms); 129d4afb5ceSopenharmony_ci { 130d4afb5ceSopenharmony_ci fd_set readfds, writefds, errfds; 131d4afb5ceSopenharmony_ci struct timeval tv = { timeout_us / LWS_US_PER_SEC, 132d4afb5ceSopenharmony_ci timeout_us % LWS_US_PER_SEC }, *ptv = &tv; 133d4afb5ceSopenharmony_ci int max_fd = 0; 134d4afb5ceSopenharmony_ci FD_ZERO(&readfds); 135d4afb5ceSopenharmony_ci FD_ZERO(&writefds); 136d4afb5ceSopenharmony_ci FD_ZERO(&errfds); 137d4afb5ceSopenharmony_ci 138d4afb5ceSopenharmony_ci for (n = 0; n < (int)pt->fds_count; n++) { 139d4afb5ceSopenharmony_ci pt->fds[n].revents = 0; 140d4afb5ceSopenharmony_ci if (pt->fds[n].fd >= max_fd) 141d4afb5ceSopenharmony_ci max_fd = pt->fds[n].fd; 142d4afb5ceSopenharmony_ci if (pt->fds[n].events & LWS_POLLIN) 143d4afb5ceSopenharmony_ci FD_SET(pt->fds[n].fd, &readfds); 144d4afb5ceSopenharmony_ci if (pt->fds[n].events & LWS_POLLOUT) 145d4afb5ceSopenharmony_ci FD_SET(pt->fds[n].fd, &writefds); 146d4afb5ceSopenharmony_ci FD_SET(pt->fds[n].fd, &errfds); 147d4afb5ceSopenharmony_ci } 148d4afb5ceSopenharmony_ci 149d4afb5ceSopenharmony_ci vpt->inside_poll = 1; 150d4afb5ceSopenharmony_ci lws_memory_barrier(); 151d4afb5ceSopenharmony_ci n = select(max_fd + 1, &readfds, &writefds, &errfds, ptv); 152d4afb5ceSopenharmony_ci vpt->inside_poll = 0; 153d4afb5ceSopenharmony_ci lws_memory_barrier(); 154d4afb5ceSopenharmony_ci n = 0; 155d4afb5ceSopenharmony_ci 156d4afb5ceSopenharmony_ci for (m = 0; m < (int)pt->fds_count; m++) { 157d4afb5ceSopenharmony_ci c = 0; 158d4afb5ceSopenharmony_ci if (FD_ISSET(pt->fds[m].fd, &readfds)) { 159d4afb5ceSopenharmony_ci pt->fds[m].revents |= LWS_POLLIN; 160d4afb5ceSopenharmony_ci c = 1; 161d4afb5ceSopenharmony_ci } 162d4afb5ceSopenharmony_ci if (FD_ISSET(pt->fds[m].fd, &writefds)) { 163d4afb5ceSopenharmony_ci pt->fds[m].revents |= LWS_POLLOUT; 164d4afb5ceSopenharmony_ci c = 1; 165d4afb5ceSopenharmony_ci } 166d4afb5ceSopenharmony_ci if (FD_ISSET(pt->fds[m].fd, &errfds)) { 167d4afb5ceSopenharmony_ci // lwsl_notice("errfds %d\n", pt->fds[m].fd); 168d4afb5ceSopenharmony_ci pt->fds[m].revents |= LWS_POLLHUP; 169d4afb5ceSopenharmony_ci c = 1; 170d4afb5ceSopenharmony_ci } 171d4afb5ceSopenharmony_ci 172d4afb5ceSopenharmony_ci if (c) 173d4afb5ceSopenharmony_ci n++; 174d4afb5ceSopenharmony_ci } 175d4afb5ceSopenharmony_ci } 176d4afb5ceSopenharmony_ci 177d4afb5ceSopenharmony_ci m = 0; 178d4afb5ceSopenharmony_ci 179d4afb5ceSopenharmony_ci #if defined(LWS_ROLE_WS) && !defined(LWS_WITHOUT_EXTENSIONS) 180d4afb5ceSopenharmony_ci m |= !!pt->ws.rx_draining_ext_list; 181d4afb5ceSopenharmony_ci #endif 182d4afb5ceSopenharmony_ci 183d4afb5ceSopenharmony_ci#if defined(LWS_WITH_TLS) 184d4afb5ceSopenharmony_ci if (pt->context->tls_ops && 185d4afb5ceSopenharmony_ci pt->context->tls_ops->fake_POLLIN_for_buffered) 186d4afb5ceSopenharmony_ci m |= pt->context->tls_ops->fake_POLLIN_for_buffered(pt); 187d4afb5ceSopenharmony_ci#endif 188d4afb5ceSopenharmony_ci if (!m && !n) 189d4afb5ceSopenharmony_ci return 0; 190d4afb5ceSopenharmony_ci } else 191d4afb5ceSopenharmony_ci a = 1; 192d4afb5ceSopenharmony_ci 193d4afb5ceSopenharmony_ci m = lws_service_flag_pending(context, tsi); 194d4afb5ceSopenharmony_ci c = m ? -1 : n; 195d4afb5ceSopenharmony_ci 196d4afb5ceSopenharmony_ci /* any socket with events to service? */ 197d4afb5ceSopenharmony_ci for (n = 0; n < (int)pt->fds_count && c; n++) { 198d4afb5ceSopenharmony_ci if (!pt->fds[n].revents) 199d4afb5ceSopenharmony_ci continue; 200d4afb5ceSopenharmony_ci 201d4afb5ceSopenharmony_ci c--; 202d4afb5ceSopenharmony_ci 203d4afb5ceSopenharmony_ci m = lws_service_fd_tsi(context, &pt->fds[n], tsi); 204d4afb5ceSopenharmony_ci if (m < 0) 205d4afb5ceSopenharmony_ci return -1; 206d4afb5ceSopenharmony_ci /* if something closed, retry this slot */ 207d4afb5ceSopenharmony_ci if (m) 208d4afb5ceSopenharmony_ci n--; 209d4afb5ceSopenharmony_ci } 210d4afb5ceSopenharmony_ci 211d4afb5ceSopenharmony_ci if (a) 212d4afb5ceSopenharmony_ci goto again; 213d4afb5ceSopenharmony_ci 214d4afb5ceSopenharmony_ci return 0; 215d4afb5ceSopenharmony_ci} 216