mirror of
https://libwebsockets.org/repo/libwebsockets
synced 2024-12-25 23:00:12 +00:00
163 lines
3.3 KiB
C
163 lines
3.3 KiB
C
/*
|
|
* lws-minimal-secure-streams-custom-proxy-transport
|
|
*
|
|
* Written in 2010-2021 by Andy Green <andy@warmcat.com>
|
|
* Kutoga <kutoga@user.github.invalid>
|
|
*
|
|
* This file is made available under the Creative Commons CC0 1.0
|
|
* Universal Public Domain Dedication.
|
|
*
|
|
*
|
|
* This represents some existing application event loop that liblws-sspc must
|
|
* cooperate with.
|
|
*/
|
|
|
|
#include "private.h"
|
|
|
|
custom_poll_ctx_t a_cpcx;
|
|
|
|
static struct pollfd *
|
|
custom_poll_find_fd(custom_poll_ctx_t *cpcx, lws_sockfd_type fd)
|
|
{
|
|
int n;
|
|
|
|
for (n = 0; n < cpcx->count_pollfds; n++)
|
|
if (cpcx->pollfds[n].fd == fd)
|
|
return &cpcx->pollfds[n];
|
|
|
|
return NULL;
|
|
}
|
|
|
|
int
|
|
custom_poll_add_fd(custom_poll_ctx_t *cpcx, lws_sockfd_type fd, int events,
|
|
void *priv)
|
|
{
|
|
struct pollfd *pfd;
|
|
|
|
lwsl_info("%s: ADD fd %d, ev %d\n", __func__, fd, events);
|
|
|
|
pfd = custom_poll_find_fd(cpcx, fd);
|
|
if (pfd) {
|
|
lwsl_err("%s: ADD fd %d already in ext table\n", __func__, fd);
|
|
return 1;
|
|
}
|
|
|
|
if (cpcx->count_pollfds == LWS_ARRAY_SIZE(cpcx->pollfds)) {
|
|
lwsl_err("%s: no room left\n", __func__);
|
|
return 1;
|
|
}
|
|
|
|
cpcx->priv[cpcx->count_pollfds] = priv;
|
|
pfd = &cpcx->pollfds[cpcx->count_pollfds++];
|
|
pfd->fd = fd;
|
|
pfd->events = (short)events;
|
|
pfd->revents = 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
custom_poll_del_fd(custom_poll_ctx_t *cpcx, lws_sockfd_type fd)
|
|
{
|
|
struct pollfd *pfd;
|
|
|
|
lwsl_info("%s: DEL fd %d\n", __func__, fd);
|
|
|
|
pfd = custom_poll_find_fd(cpcx, fd);
|
|
if (!pfd) {
|
|
lwsl_err("%s: DEL fd %d missing in ext table\n", __func__, fd);
|
|
return 1;
|
|
}
|
|
|
|
if (cpcx->count_pollfds > 1)
|
|
*pfd = cpcx->pollfds[cpcx->count_pollfds - 1];
|
|
|
|
cpcx->count_pollfds--;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
custom_poll_change_fd(custom_poll_ctx_t *cpcx, lws_sockfd_type fd,
|
|
int events_add, int events_remove)
|
|
{
|
|
struct pollfd *pfd;
|
|
|
|
lwsl_info("%s: CHG fd %d, ev_add %d, ev_rem %d\n", __func__, fd,
|
|
events_add, events_remove);
|
|
|
|
pfd = custom_poll_find_fd(cpcx, fd);
|
|
if (!pfd)
|
|
return 1;
|
|
|
|
pfd->events = (short)((pfd->events & (~events_remove)) | events_add);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
custom_poll_run(custom_poll_ctx_t *cpcx)
|
|
{
|
|
int n;
|
|
|
|
while (!interrupted) {
|
|
|
|
lws_usec_t timeout_us = 2000000000, now = lws_now_usecs();
|
|
|
|
if (cpcx->scheduler.count) {
|
|
lws_sorted_usec_list_t *sul = (lws_sorted_usec_list_t *)
|
|
lws_dll2_get_head(&cpcx->scheduler);
|
|
if (sul->us < now)
|
|
timeout_us = 0;
|
|
else
|
|
timeout_us = sul->us - now;
|
|
}
|
|
|
|
// lwsl_notice("%s: entering poll wait %dms\n", __func__, (int)(timeout_us / 1000));
|
|
|
|
n = poll(cpcx->pollfds, (nfds_t)cpcx->count_pollfds, (int)(timeout_us / 1000));
|
|
|
|
// lwsl_notice("%s: exiting poll after %lluus\n", __func__,
|
|
// (unsigned long long)(lws_now_usecs() - now));
|
|
|
|
do {
|
|
lws_sorted_usec_list_t *sul = (lws_sorted_usec_list_t *)
|
|
lws_dll2_get_head(&cpcx->scheduler);
|
|
|
|
if (!sul)
|
|
break;
|
|
|
|
if (sul->us > now)
|
|
break;
|
|
|
|
lws_dll2_remove(&sul->list);
|
|
sul->cb(sul);
|
|
} while (1);
|
|
|
|
if (n <= 0)
|
|
continue;
|
|
|
|
/* service anything that has active revents */
|
|
|
|
for (n = 0; n < cpcx->count_pollfds; n++) {
|
|
int m;
|
|
|
|
if (!cpcx->pollfds[n].revents)
|
|
continue;
|
|
|
|
/*
|
|
* the only fd we registered in this example is the
|
|
* transport fd, so we miss out the code to match the
|
|
* fd to the right callback
|
|
*/
|
|
|
|
m = custom_transport_event(&cpcx->pollfds[n], cpcx->priv[n]);
|
|
if (m < 0) {
|
|
custom_poll_del_fd(cpcx, cpcx->pollfds[n].fd);
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|