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