1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-09 00:00:04 +01:00

freertos: lws_cancel_service udp as pipe

Freertos + lwip doesn't support pipe2() or pipe()... implement a "pipe"
based on two UDP sockets, one listening on 127.0.0.1:54321 and the other
doing a sendto() there of a single byte to interrupt the event loop wait.

Re-use the arrangements for actual pipe fds and pipe role to deliver
lws_cancel_service() functionality using this.
This commit is contained in:
Andy Green 2020-01-15 08:31:28 +00:00
parent 66b2a4a645
commit 09ba5c6789
4 changed files with 86 additions and 14 deletions

View file

@ -881,9 +881,14 @@ lws_create_event_pipes(struct lws_context *context)
* not bound to a vhost or protocol (both are NULL)
*/
#if LWS_MAX_SMP > 1
for (n = 0; n < context->count_threads; n++) {
#else
n = 0;
{
#endif
if (context->pt[n].pipe_wsi)
continue;
return 0;
wsi = lws_zalloc(sizeof(*wsi), "event pipe wsi");
if (!wsi) {
@ -900,7 +905,7 @@ lws_create_event_pipes(struct lws_context *context)
context->pt[n].pipe_wsi = wsi;
context->count_wsi_allocated++;
if (lws_plat_pipe_create(wsi))
if (!lws_plat_pipe_create(wsi)) {
/*
* platform code returns 0 if it actually created pipes
* and initialized pt->dummy_pipe_fds[]. If it used
@ -909,17 +914,17 @@ lws_create_event_pipes(struct lws_context *context)
* related to dummy_pipe_fds[], adding it to the fds,
* etc.
*/
continue;
wsi->desc.sockfd = context->pt[n].dummy_pipe_fds[0];
lwsl_debug("event pipe fd %d\n", wsi->desc.sockfd);
wsi->desc.sockfd = context->pt[n].dummy_pipe_fds[0];
lwsl_debug("event pipe fd %d\n", wsi->desc.sockfd);
if (context->event_loop_ops->sock_accept)
if (context->event_loop_ops->sock_accept(wsi))
if (context->event_loop_ops->sock_accept)
if (context->event_loop_ops->sock_accept(wsi))
return 1;
if (__insert_wsi_socket_into_fds(context, wsi))
return 1;
if (__insert_wsi_socket_into_fds(context, wsi))
return 1;
}
}
return 0;

View file

@ -619,10 +619,8 @@ lws_create_context(const struct lws_context_creation_info *info)
goto bail;
}
#if !defined(LWS_AMAZON_RTOS)
if (lws_create_event_pipes(context))
goto bail;
#endif
#endif
lws_context_init_ssl_library(info);

View file

@ -314,6 +314,10 @@ struct lws_context {
lws_retry_bo_t default_retry;
lws_sorted_usec_list_t sul_system_state;
#if defined(LWS_PLAT_FREERTOS)
struct sockaddr_in frt_pipe_si;
#endif
#if defined(LWS_WITH_HTTP2)
struct http2_settings set;
#endif

View file

@ -1,7 +1,7 @@
/*
* libwebsockets - small server side websockets and web server implementation
*
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
* Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@ -27,16 +27,81 @@
int
lws_plat_pipe_create(struct lws *wsi)
{
struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
struct sockaddr_in *si = &wsi->context->frt_pipe_si;
lws_sockfd_type *fd = pt->dummy_pipe_fds;
/*
* There's no pipe abstraction on lwip / freertos... use a UDP socket
* listening on 127.0.0.1:54321 and send a byte to it from a second UDP
* socket to cancel the wait.
*/
fd[0] = socket(AF_INET, SOCK_DGRAM, 0);
if (fd[0] < 0)
goto bail;
fd[1] = socket(AF_INET, SOCK_DGRAM, 0);
if (fd[1] < 0)
goto bail;
/*
* No need for memset since it's in zalloc'd context... it's in the
* context so we can reuse the prepared sockaddr to send tp fd[0] whem
* we want to cancel the wait
*/
si->sin_family = AF_INET;
si->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
si->sin_port = htons(54321);
if (bind(fd[0], (const struct sockaddr *)si, sizeof(*si)) < 0)
goto bail;
return 0;
bail:
lwsl_err("%s: failed\n", __func__);
return 1;
}
int
lws_plat_pipe_signal(struct lws *wsi)
{
return 1;
struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
struct sockaddr_in *si = &wsi->context->frt_pipe_si;
lws_sockfd_type *fd = pt->dummy_pipe_fds;
uint8_t u = 0;
int n;
/*
* Send a single UDP byte payload to the listening socket fd[0], forcing
* the event loop wait to wake. fd[1] and context->frt_pipe_si are
* set at context creation and are static, the UDP sendto is supposed to
* be threadsafe for lwip:
*
* https://lwip.fandom.com/wiki/LwIP_and_multithreading
*
* Sockets generally can't be used by more than one application thread
* (on udp/raw netconn, doing a sendto/recv is currently possible).
*/
n = sendto(fd[1], &u, 1, 0, (struct sockaddr *)si, sizeof(*si));
return n != 1;
}
void
lws_plat_pipe_close(struct lws *wsi)
{
struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
lws_sockfd_type *fd = pt->dummy_pipe_fds;
if (fd[0] && fd[0] != -1)
close(fd[0]);
if (fd[1] && fd[1] != -1)
close(fd[1]);
fd[0] = fd[1] = -1;
}