diff --git a/lib/core-net/vhost.c b/lib/core-net/vhost.c index ede8e0e2c..ce417df8f 100644 --- a/lib/core-net/vhost.c +++ b/lib/core-net/vhost.c @@ -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; diff --git a/lib/core/context.c b/lib/core/context.c index 385d97edd..ea926fd49 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -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); diff --git a/lib/core/private-lib-core.h b/lib/core/private-lib-core.h index 702d15d2b..5366da9db 100644 --- a/lib/core/private-lib-core.h +++ b/lib/core/private-lib-core.h @@ -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 diff --git a/lib/plat/freertos/freertos-pipe.c b/lib/plat/freertos/freertos-pipe.c index 92f99fb83..6a98c56d1 100644 --- a/lib/plat/freertos/freertos-pipe.c +++ b/lib/plat/freertos/freertos-pipe.c @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2020 Andy Green * * 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; }