diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8aca4ea6b1362e3d2828d32eeb35107daecbd197..4b1c74946b5e2ccd320daf93c4e0756bc730fdff 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -324,6 +324,12 @@ if (NOT LWS_WITHOUT_EXTENSIONS)
)
endif()
+if (LWS_WITH_LIBEV)
+ list(APPEND SOURCES
+ lib/libev.c
+ )
+endif(LWS_WITH_LIBEV)
+
# Add helper files for Windows.
if (WIN32)
set(WIN32_HELPERS_PATH win32port/win32helpers)
diff --git a/lib/context.c b/lib/context.c
index 92383bf833c99535077bbdce4ceb4f25dfe920b6..fd89ae3e31560dabf1106143a045de02880cbdc2 100644
--- a/lib/context.c
+++ b/lib/context.c
@@ -91,14 +91,7 @@ libwebsocket_create_context(struct lws_context_creation_info *info)
#else
lwsl_notice("IPV6 not compiled in\n");
#endif
-#ifdef LWS_USE_LIBEV
- if (info->options & LWS_SERVER_OPTION_LIBEV)
- lwsl_notice("libev support compiled in and enabled\n");
- else
- lwsl_notice("libev support compiled in but disabled\n");
-#else
- lwsl_notice("libev support not compiled in\n");
-#endif
+ lws_feature_status_libev(info);
lwsl_info(" LWS_MAX_HEADER_LEN: %u\n", LWS_MAX_HEADER_LEN);
lwsl_info(" LWS_MAX_PROTOCOLS: %u\n", LWS_MAX_PROTOCOLS);
#ifndef LWS_NO_EXTENSIONS
diff --git a/lib/libev.c b/lib/libev.c
new file mode 100644
index 0000000000000000000000000000000000000000..b75c5ec4597beb417cb4bbe6c27fcdc9fb0202a0
--- /dev/null
+++ b/lib/libev.c
@@ -0,0 +1,175 @@
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010-2014 Andy Green <andy@warmcat.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation:
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#include "private-libwebsockets.h"
+
+void lws_feature_status_libev(struct lws_context_creation_info *info)
+{
+ if (info->options & LWS_SERVER_OPTION_LIBEV)
+ lwsl_notice("libev support compiled in and enabled\n");
+ else
+ lwsl_notice("libev support compiled in but disabled\n");
+}
+
+static void
+libwebsocket_accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
+{
+ struct libwebsocket_pollfd eventfd;
+ struct lws_io_watcher *lws_io = (struct lws_io_watcher *)watcher;
+ struct libwebsocket_context *context = lws_io->context;
+
+ if (revents & EV_ERROR)
+ return;
+
+ eventfd.fd = watcher->fd;
+ eventfd.revents = EV_NONE;
+ if (revents & EV_READ)
+ eventfd.revents |= LWS_POLLIN;
+
+ if (revents & EV_WRITE)
+ eventfd.revents |= LWS_POLLOUT;
+
+ libwebsocket_service_fd(context, &eventfd);
+}
+
+LWS_VISIBLE void
+libwebsocket_sigint_cb(struct ev_loop *loop,
+ struct ev_signal *watcher, int revents)
+{
+ ev_break(loop, EVBREAK_ALL);
+}
+
+LWS_VISIBLE int
+libwebsocket_initloop(
+ struct libwebsocket_context *context,
+ struct ev_loop *loop)
+{
+ int status = 0;
+ int backend;
+ const char * backend_name;
+ struct ev_io *w_accept = (ev_io *)&context->w_accept;
+ struct ev_signal *w_sigint = (ev_signal *)&context->w_sigint;
+
+ if (!loop)
+ loop = ev_default_loop(0);
+
+ context->io_loop = loop;
+
+ /*
+ * Initialize the accept w_accept with the listening socket
+ * and register a callback for read operations:
+ */
+ ev_io_init(w_accept, libwebsocket_accept_cb,
+ context->listen_service_fd, EV_READ);
+ ev_io_start(context->io_loop,w_accept);
+ ev_signal_init(w_sigint, libwebsocket_sigint_cb, SIGINT);
+ ev_signal_start(context->io_loop,w_sigint);
+ backend = ev_backend(loop);
+
+ switch (backend) {
+ case EVBACKEND_SELECT:
+ backend_name = "select";
+ break;
+ case EVBACKEND_POLL:
+ backend_name = "poll";
+ break;
+ case EVBACKEND_EPOLL:
+ backend_name = "epoll";
+ break;
+ case EVBACKEND_KQUEUE:
+ backend_name = "kqueue";
+ break;
+ case EVBACKEND_DEVPOLL:
+ backend_name = "/dev/poll";
+ break;
+ case EVBACKEND_PORT:
+ backend_name = "Solaris 10 \"port\"";
+ break;
+ default:
+ backend_name = "Unknown libev backend";
+ break;
+ };
+
+ lwsl_notice(" libev backend: %s\n", backend_name);
+
+ return status;
+}
+
+LWS_VISIBLE void
+lws_libev_accept(struct libwebsocket_context *context,
+ struct libwebsocket *new_wsi, int accept_fd)
+{
+ struct ev_io *r = &new_wsi->w_read.watcher;
+ struct ev_io *w = &new_wsi->w_write.watcher;
+
+ if (!LWS_LIBEV_ENABLED(context))
+ return;
+
+ new_wsi->w_read.context = context;
+ new_wsi->w_write.context = context;
+ ev_io_init(r, libwebsocket_accept_cb, accept_fd, EV_READ);
+ ev_io_init(w, libwebsocket_accept_cb, accept_fd, EV_WRITE);
+}
+
+LWS_VISIBLE void
+lws_libev_io(struct libwebsocket_context *context,
+ struct libwebsocket *wsi, int flags)
+{
+ if (!LWS_LIBEV_ENABLED(context))
+ return;
+
+ if (!context->io_loop)
+ return;
+
+ assert((flags & (LWS_EV_START | LWS_EV_STOP)) &&
+ (flags & (LWS_EV_READ | LWS_EV_WRITE)));
+
+ if (flags & LWS_EV_START) {
+ if (flags & LWS_EV_WRITE)
+ ev_io_start(context->io_loop, &wsi->w_write.watcher);
+ if (flags & LWS_EV_READ)
+ ev_io_start(context->io_loop, &wsi->w_read.watcher);
+ } else {
+ if (flags & LWS_EV_WRITE)
+ ev_io_stop(context->io_loop, &wsi->w_write.watcher);
+ if (flags & LWS_EV_READ)
+ ev_io_stop(context->io_loop, &wsi->w_read.watcher);
+ }
+}
+
+LWS_VISIBLE int
+lws_libev_init_fd_table(struct libwebsocket_context *context)
+{
+ if (!LWS_LIBEV_ENABLED(context))
+ return 0;
+
+ context->w_accept.context = context;
+ context->w_sigint.context = context;
+
+ return 1;
+}
+
+LWS_VISIBLE void
+lws_libev_run(struct libwebsocket_context *context)
+{
+ if (context->io_loop && LWS_LIBEV_ENABLED(context))
+ ev_run(context->io_loop, 0);
+}
diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h
index c5b1701366a894f77167a79e119b1afe435fa9f8..03ead6ed963270200e5af5a3710e6554a69eef06 100644
--- a/lib/libwebsockets.h
+++ b/lib/libwebsockets.h
@@ -982,10 +982,6 @@ LWS_VISIBLE LWS_EXTERN int
libwebsocket_initloop(
struct libwebsocket_context *context, struct ev_loop *loop);
-LWS_VISIBLE void
-libwebsocket_accept_cb(struct ev_loop *loop, struct ev_io *watcher,
- int revents);
-
LWS_VISIBLE void
libwebsocket_sigint_cb(
struct ev_loop *loop, struct ev_signal *watcher, int revents);
diff --git a/lib/lws-plat-unix.c b/lib/lws-plat-unix.c
index de094c74c6e5902d7c8f7bc2fe7049c488fd2f9c..279a3be4ad2b3a327aceacfcef8282f57de992c7 100644
--- a/lib/lws-plat-unix.c
+++ b/lib/lws-plat-unix.c
@@ -54,93 +54,6 @@ static void lws_sigusr2(int sig)
{
}
-#ifdef LWS_USE_LIBEV
-LWS_VISIBLE void
-libwebsocket_accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
-{
- struct libwebsocket_pollfd eventfd;
- struct lws_io_watcher *lws_io = (struct lws_io_watcher*)watcher;
- struct libwebsocket_context *context = lws_io->context;
-
- if (revents & EV_ERROR)
- return;
-
- eventfd.fd = watcher->fd;
- eventfd.revents = EV_NONE;
- if (revents & EV_READ)
- eventfd.revents |= LWS_POLLIN;
-
- if (revents & EV_WRITE)
- eventfd.revents |= LWS_POLLOUT;
-
- libwebsocket_service_fd(context,&eventfd);
-}
-
-LWS_VISIBLE void
-libwebsocket_sigint_cb(
- struct ev_loop *loop, struct ev_signal* watcher, int revents)
-{
- ev_break(loop, EVBREAK_ALL);
-}
-
-LWS_VISIBLE int
-libwebsocket_initloop(
- struct libwebsocket_context *context,
- struct ev_loop *loop)
-{
- int status = 0;
- int backend;
- const char * backend_name;
- struct ev_io *w_accept = (ev_io *)&context->w_accept;
- struct ev_signal *w_sigint = (ev_signal *)&context->w_sigint;
-
- if (!loop)
- loop = ev_default_loop(0);
-
- context->io_loop = loop;
-
- /*
- * Initialize the accept w_accept with the listening socket
- * and register a callback for read operations:
- */
- ev_io_init(w_accept, libwebsocket_accept_cb,
- context->listen_service_fd, EV_READ);
- ev_io_start(context->io_loop,w_accept);
- ev_signal_init(w_sigint, libwebsocket_sigint_cb, SIGINT);
- ev_signal_start(context->io_loop,w_sigint);
- backend = ev_backend(loop);
-
- switch (backend) {
- case EVBACKEND_SELECT:
- backend_name = "select";
- break;
- case EVBACKEND_POLL:
- backend_name = "poll";
- break;
- case EVBACKEND_EPOLL:
- backend_name = "epoll";
- break;
- case EVBACKEND_KQUEUE:
- backend_name = "kqueue";
- break;
- case EVBACKEND_DEVPOLL:
- backend_name = "/dev/poll";
- break;
- case EVBACKEND_PORT:
- backend_name = "Solaris 10 \"port\"";
- break;
- default:
- backend_name = "Unknown libev backend";
- break;
- };
-
- lwsl_notice(" libev backend: %s\n", backend_name);
-
- return status;
-}
-
-#endif /* LWS_USE_LIBEV */
-
/**
* libwebsocket_cancel_service() - Cancel servicing of pending websocket activity
* @context: Websocket context
@@ -187,13 +100,11 @@ lws_plat_service(struct libwebsocket_context *context, int timeout_ms)
/* stay dead once we are dead */
- if (context == NULL)
+ if (!context)
return 1;
-#ifdef LWS_USE_LIBEV
- if (context->io_loop && LWS_LIBEV_ENABLED(context))
- ev_run(context->io_loop, 0);
-#endif /* LWS_USE_LIBEV */
+ lws_libev_run(context);
+
context->service_tid = context->protocols[0].callback(context, NULL,
LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0);
@@ -305,13 +216,10 @@ lws_plat_drop_app_privileges(struct lws_context_creation_info *info)
LWS_VISIBLE int
lws_plat_init_fd_tables(struct libwebsocket_context *context)
{
-#ifdef LWS_USE_LIBEV
- if (LWS_LIBEV_ENABLED(context)) {
- context->w_accept.context = context;
- context->w_sigint.context = context;
+ if (lws_libev_init_fd_table(context))
+ /* libev handled it instead */
return 0;
- }
-#endif
+
if (pipe(context->dummy_pipe_fds)) {
lwsl_err("Unable to create pipe\n");
return 1;
@@ -433,10 +341,7 @@ LWS_VISIBLE void
lws_plat_insert_socket_into_fds(struct libwebsocket_context *context,
struct libwebsocket *wsi)
{
-#ifdef LWS_USE_LIBEV
- if (context && context->io_loop && LWS_LIBEV_ENABLED(context))
- ev_io_start(context->io_loop, (struct ev_io *)&wsi->w_read);
-#endif /* LWS_USE_LIBEV */
+ lws_libev_io(context, wsi, LWS_EV_START | LWS_EV_READ);
context->fds[context->fds_count++].revents = 0;
}
diff --git a/lib/pollfd.c b/lib/pollfd.c
index ee5bf9129f566db9cf700c62b82f0c493d1f9725..3995a378ac4167b8731df932ce95c12e7b18c332 100644
--- a/lib/pollfd.c
+++ b/lib/pollfd.c
@@ -74,12 +74,7 @@ remove_wsi_socket_from_fds(struct libwebsocket_context *context,
int m;
struct libwebsocket_pollargs pa = { wsi->sock, 0, 0 };
-#ifdef LWS_USE_LIBEV
- if (LWS_LIBEV_ENABLED(context)) {
- ev_io_stop(context->io_loop, (struct ev_io *)&wsi->w_read);
- ev_io_stop(context->io_loop, (struct ev_io *)&wsi->w_write);
- }
-#endif /* LWS_USE_LIBEV */
+ lws_libev_io(context, wsi, LWS_EV_STOP | LWS_EV_READ | LWS_EV_WRITE);
if (!--context->fds_count) {
context->protocols[0].callback(context, wsi,
@@ -164,8 +159,10 @@ lws_change_pollfd(struct libwebsocket *wsi, int _and, int _or)
*/
if (pa.prev_events != pa.events) {
- if (lws_plat_change_pollfd(context, wsi, pfd))
+ if (lws_plat_change_pollfd(context, wsi, pfd)) {
+ lwsl_info("%s failed\n", __func__);
return 1;
+ }
sampled_tid = context->service_tid;
if (sampled_tid) {
@@ -208,10 +205,7 @@ libwebsocket_callback_on_writable(struct libwebsocket_context *context,
if (lws_change_pollfd(wsi, 0, LWS_POLLOUT))
return -1;
-#ifdef LWS_USE_LIBEV
- if (LWS_LIBEV_ENABLED(context))
- ev_io_start(context->io_loop, (struct ev_io *)&wsi->w_write);
-#endif /* LWS_USE_LIBEV */
+ lws_libev_io(context, wsi, LWS_EV_START | LWS_EV_WRITE);
return 1;
}
diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h
index 94bd227013328f23e0c4dc713d21947d7b817ab8..8cfab08bb9a7732b30d658eab0f7a93dff0ece28 100644
--- a/lib/private-libwebsockets.h
+++ b/lib/private-libwebsockets.h
@@ -434,10 +434,34 @@ struct libwebsocket_context {
void *user_space;
};
+enum {
+ LWS_EV_READ = (1 << 0),
+ LWS_EV_WRITE = (1 << 1),
+ LWS_EV_START = (1 << 2),
+ LWS_EV_STOP = (1 << 3),
+};
+
#ifdef LWS_USE_LIBEV
#define LWS_LIBEV_ENABLED(context) (context->options & LWS_SERVER_OPTION_LIBEV)
+LWS_EXTERN void lws_feature_status_libev(struct lws_context_creation_info *info);
+LWS_EXTERN void
+lws_libev_accept(struct libwebsocket_context *context,
+ struct libwebsocket *new_wsi, int accept_fd);
+LWS_EXTERN void
+lws_libev_io(struct libwebsocket_context *context,
+ struct libwebsocket *wsi, int flags);
+LWS_EXTERN int
+lws_libev_init_fd_table(struct libwebsocket_context *context);
+LWS_EXTERN void
+lws_libev_run(struct libwebsocket_context *context);
#else
#define LWS_LIBEV_ENABLED(context) (0)
+#define lws_feature_status_libev(_a) \
+ lwsl_notice("libev support not compiled in\n")
+#define lws_libev_accept(_a, _b, _c) (0)
+#define lws_libev_io(_a, _b, _c) (0)
+#define lws_libev_init_fd_table(_a) (0)
+#define lws_libev_run(_a) (0)
#endif
#ifdef LWS_USE_IPV6
diff --git a/lib/server.c b/lib/server.c
index 2d2ffb303d39e9b9a17e4ade0fd869cc6aa4dc27..e58632a72abc7781ff5ca96b569885a163d99d42 100644
--- a/lib/server.c
+++ b/lib/server.c
@@ -154,8 +154,10 @@ _libwebsocket_rx_flow_control(struct libwebsocket *wsi)
/* adjust the pollfd for this wsi */
if (wsi->u.ws.rxflow_change_to & LWS_RXFLOW_ALLOW) {
- if (lws_change_pollfd(wsi, 0, LWS_POLLIN))
+ if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) {
+ lwsl_info("%s: fail\n", __func__);
return -1;
+ }
} else
if (lws_change_pollfd(wsi, LWS_POLLIN, 0))
return -1;
@@ -566,11 +568,8 @@ int lws_server_socket_service(struct libwebsocket_context *context,
/* one shot */
if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
goto fail;
-#ifdef LWS_USE_LIBEV
- if (LWS_LIBEV_ENABLED(context))
- ev_io_stop(context->io_loop,
- (struct ev_io *)&wsi->w_write);
-#endif /* LWS_USE_LIBEV */
+
+ lws_libev_io(context, wsi, LWS_EV_STOP | LWS_EV_WRITE);
if (wsi->state != WSI_STATE_HTTP_ISSUING_FILE) {
n = user_callback_handle_rxflow(
@@ -655,20 +654,7 @@ int lws_server_socket_service(struct libwebsocket_context *context,
(context->protocols[0].callback)(context, new_wsi,
LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED, NULL, NULL, 0);
-#ifdef LWS_USE_LIBEV
- if (LWS_LIBEV_ENABLED(context)) {
- new_wsi->w_read.context = context;
- new_wsi->w_write.context = context;
- /*
- new_wsi->w_read.wsi = new_wsi;
- new_wsi->w_write.wsi = new_wsi;
- */
- struct ev_io* w_read = (struct ev_io*)&(new_wsi->w_read);
- struct ev_io* w_write = (struct ev_io*)&(new_wsi->w_write);
- ev_io_init(w_read,libwebsocket_accept_cb,accept_fd,EV_READ);
- ev_io_init(w_write,libwebsocket_accept_cb,accept_fd,EV_WRITE);
- }
-#endif /* LWS_USE_LIBEV */
+ lws_libev_accept(context, new_wsi, accept_fd);
#ifdef LWS_OPENSSL_SUPPORT
new_wsi->ssl = NULL;
@@ -737,11 +723,8 @@ int lws_server_socket_service(struct libwebsocket_context *context,
if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
goto fail;
-#ifdef LWS_USE_LIBEV
- if (LWS_LIBEV_ENABLED(context))
- ev_io_stop(context->io_loop,
- (struct ev_io *)&wsi->w_write);
-#endif /* LWS_USE_LIBEV */
+
+ lws_libev_io(context, wsi, LWS_EV_STOP | LWS_EV_WRITE);
lws_latency_pre(context, wsi);
@@ -787,22 +770,18 @@ int lws_server_socket_service(struct libwebsocket_context *context,
if (m == SSL_ERROR_WANT_READ) {
if (lws_change_pollfd(wsi, 0, LWS_POLLIN))
goto fail;
-#ifdef LWS_USE_LIBEV
- if (LWS_LIBEV_ENABLED(context))
- ev_io_start(context->io_loop,
- (struct ev_io *)&wsi->w_read);
-#endif /* LWS_USE_LIBEV */
+
+ lws_libev_io(context, wsi, LWS_EV_START | LWS_EV_READ);
+
lwsl_info("SSL_ERROR_WANT_READ\n");
break;
}
if (m == SSL_ERROR_WANT_WRITE) {
if (lws_change_pollfd(wsi, 0, LWS_POLLOUT))
goto fail;
-#ifdef LWS_USE_LIBEV
- if (LWS_LIBEV_ENABLED(context))
- ev_io_start(context->io_loop,
- (struct ev_io *)&wsi->w_write);
-#endif /* LWS_USE_LIBEV */
+
+ lws_libev_io(context, wsi,
+ LWS_EV_START | LWS_EV_WRITE);
break;
}
lwsl_debug("SSL_accept failed skt %u: %s\n",
diff --git a/lib/service.c b/lib/service.c
index 9aa743e5c51cdd41614f7055f9b786f757f2dd63..409c2d231abdb2a3a048199e2c961b9174c1bbdf 100644
--- a/lib/service.c
+++ b/lib/service.c
@@ -145,11 +145,8 @@ user_service:
if (pollfd) {
if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
return 1;
-#ifdef LWS_USE_LIBEV
- if (LWS_LIBEV_ENABLED(context))
- ev_io_stop(context->io_loop,
- (struct ev_io *)&wsi->w_write);
-#endif /* LWS_USE_LIBEV */
+
+ lws_libev_io(context, wsi, LWS_EV_STOP | LWS_EV_WRITE);
}
notify_action:
diff --git a/test-server/test-server.c b/test-server/test-server.c
index d2e56b42acb70497883cfd94838091a0c4dae131..bd76ec8681a6668a1a6277a6c7fd4d752e884d69 100644
--- a/test-server/test-server.c
+++ b/test-server/test-server.c
@@ -743,7 +743,8 @@ static struct option options[] = {
{ "allow-non-ssl", no_argument, NULL, 'a' },
{ "interface", required_argument, NULL, 'i' },
{ "closetest", no_argument, NULL, 'c' },
-#ifndef LWS_NO_DAEMONIZE
+ { "libev", no_argument, NULL, 'e' },
+ #ifndef LWS_NO_DAEMONIZE
{ "daemonize", no_argument, NULL, 'D' },
#endif
{ "resource_path", required_argument, NULL, 'r' },
@@ -774,10 +775,13 @@ int main(int argc, char **argv)
info.port = 7681;
while (n >= 0) {
- n = getopt_long(argc, argv, "ci:hsap:d:Dr:", options, NULL);
+ n = getopt_long(argc, argv, "eci:hsap:d:Dr:", options, NULL);
if (n < 0)
continue;
switch (n) {
+ case 'e':
+ opts |= LWS_SERVER_OPTION_LIBEV;
+ break;
#ifndef LWS_NO_DAEMONIZE
case 'D':
daemonize = 1;