diff --git a/CMakeLists.txt b/CMakeLists.txt
index 103b3e0041092274f343a74ab1b482a6296c7274..d58ee6744288fa64c6f841f37117831ae10d3507 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -52,6 +52,7 @@ option(LWS_WITHOUT_DEBUG "Don't compile debug related code" OFF)
 option(LWS_WITHOUT_EXTENSIONS "Don't compile with extensions" OFF)
 option(LWS_WITH_LATENCY "Build latency measuring code into the library" OFF)
 option(LWS_WITHOUT_DAEMONIZE "Don't build the daemonization api" OFF)
+option(LWS_WITH_LIBEV "Compile without support for libev" OFF)
 
 # Allow the user to override installation directories.
 set(LWS_INSTALL_LIB_DIR       lib CACHE PATH "Installation directory for libraries")
@@ -115,6 +116,11 @@ else()
 	set(_DEBUG 1)
 endif()
 
+if (LWS_WITH_LIBEV)
+	set(LWS_USE_LIBEV 1)
+	set(LWS_NO_EXTERNAL_POLL 1)
+endif()
+
 if (MINGW)
 	set(LWS_MINGW_SUPPORT 1)
 endif()
@@ -458,6 +464,10 @@ if (LWS_WITH_SSL)
 	endif()
 endif(LWS_WITH_SSL)
 
+if (LWS_WITH_LIBEV)
+	list(APPEND LIB_LIST "ev")
+endif(LWS_WITH_LIBEV)
+
 #
 # Platform specific libs.
 #
@@ -866,6 +876,7 @@ message(" LWS_WITHOUT_DEBUG = ${LWS_WITHOUT_DEBUG}")
 message(" LWS_WITHOUT_EXTENSIONS = ${LWS_WITHOUT_EXTENSIONS}")
 message(" LWS_WITH_LATENCY = ${LWS_WITH_LATENCY}")
 message(" LWS_WITHOUT_DAEMONIZE = ${LWS_WITHOUT_DAEMONIZE}")
+message(" LWS_USE_LIBEV = ${LWS_USE_LIBEV}")
 message("---------------------------------------------------------------------")
 
 # These will be available to parent projects including libwebsockets using add_subdirectory()
diff --git a/changelog b/changelog
index f9ceaa2319cac747a810888514458d1bd16937f8..e3c464f18645fdffb233a1cb35ca49ecc169a15c 100644
--- a/changelog
+++ b/changelog
@@ -39,6 +39,10 @@ If you will use another thread for this, take a lot of care about managing
 your list of live wsi by doing it from ESTABLISHED and CLOSED callbacks
 (with your own locking).
 
+If you configure cmake with -DLWS_WITH_LIBEV=1 then the code allowing the libev
+eventloop instead of the default poll() one will also be compiled in.  But to
+use it, you must also set the LWS_SERVER_OPTION_LIBEV flag on the context
+creation info struct options member.
 
 
 User api changes
diff --git a/config.h.cmake b/config.h.cmake
index 87bd94986ba96a8ff555b3eb7e89946c57a36449..a8247a9937c64d21c793ec8b54c03d060c123426 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -26,6 +26,9 @@
 /* Turn off websocket extensions */
 #cmakedefine LWS_NO_EXTENSIONS
 
+/* Enable libev io loop */
+#cmakedefine LWS_USE_LIBEV
+
 /* Turn on latency measuring code */
 #cmakedefine LWS_LATENCY
 
diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c
index 0abd6451538289bc08196c8844ebd3b6993c7f94..08a18446ce19e8e831aa9047ce1dfea622f0f47f 100644
--- a/lib/libwebsockets.c
+++ b/lib/libwebsockets.c
@@ -63,7 +63,13 @@ static int log_level = LLL_ERR | LLL_WARN | LLL_NOTICE;
 static void lwsl_emit_stderr(int level, const char *line);
 static void (*lwsl_emit)(int level, const char *line) = lwsl_emit_stderr;
 
-static const char *library_version = LWS_LIBRARY_VERSION " " LWS_BUILD_HASH;
+#ifdef LWS_USE_LIBEV
+#define _LWS_EV_TAG " libev"
+#else
+#define _LWS_EV_TAG
+#endif /* LWS_USE_LIBEV */
+static const char *library_version =
+			LWS_LIBRARY_VERSION " " LWS_BUILD_HASH _LWS_EV_TAG;
 
 static const char * const log_level_names[] = {
 	"ERR",
@@ -173,6 +179,11 @@ insert_wsi_socket_into_fds(struct libwebsocket_context *context,
 	wsi->position_in_fds_table = context->fds_count;
 	context->fds[context->fds_count].fd = wsi->sock;
 	context->fds[context->fds_count].events = POLLIN;
+#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 */
 	context->fds[context->fds_count++].revents = 0;
 
 	/* external POLL support via protocol 0 */
@@ -431,6 +442,13 @@ just_kill_connection:
 	 * delete socket from the internal poll list if still present
 	 */
 
+#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 */
+
 	remove_wsi_socket_from_fds(context, wsi);
 
 	wsi->state = WSI_STATE_DEAD_SOCKET;
@@ -865,9 +883,14 @@ user_service:
 #endif
 	/* one shot */
 
-	if (pollfd)
+	if (pollfd) {
 		lws_change_pollfd(wsi, POLLOUT, 0);
-
+#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 */
+	}
 #ifndef LWS_NO_EXTENSIONS
 notify_action:
 #endif
@@ -974,6 +997,7 @@ libwebsocket_service_fd(struct libwebsocket_context *context,
 
 	time(&now);
 
+	/* TODO: if using libev, we should probably use timeout watchers... */
 	if (context->last_timeout_check_s != now) {
 		context->last_timeout_check_s = now;
 
@@ -1240,6 +1264,36 @@ handled:
 	return n;
 }
 
+#ifdef LWS_USE_LIBEV
+LWS_VISIBLE void 
+libwebsocket_accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
+{
+	struct 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 |= POLLIN;
+
+	if (revents & EV_WRITE)
+		eventfd.revents |= 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);
+}
+#endif /* LWS_USE_LIBEV */
+
 
 /**
  * libwebsocket_context_destroy() - Destroy the websocket context
@@ -1394,6 +1448,10 @@ libwebsocket_service(struct libwebsocket_context *context, int timeout_ms)
 	if (context == NULL)
 		return 1;
 
+#ifdef LWS_USE_LIBEV
+	if (context->io_loop && LWS_LIBEV_ENABLED(context))
+		ev_run(context->io_loop, 0);
+#endif /* LWS_USE_LIBEV */
 	context->service_tid = context->protocols[0].callback(context, NULL,
 				     LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0);
 	n = poll(context->fds, context->fds_count, timeout_ms);
@@ -1453,6 +1511,64 @@ libwebsocket_cancel_service(struct libwebsocket_context *context)
 #endif
 }
 
+#ifdef LWS_USE_LIBEV
+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 */
+
 #ifndef LWS_NO_EXTENSIONS
 int
 lws_any_extension_handled(struct libwebsocket_context *context,
@@ -1584,6 +1700,10 @@ libwebsocket_callback_on_writable(struct libwebsocket_context *context,
 	}
 
 	lws_change_pollfd(wsi, 0, POLLOUT);
+#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 */
 
 	return 1;
 }
@@ -2036,6 +2156,14 @@ libwebsocket_create_context(struct lws_context_creation_info *info)
 		free(context);
 		return NULL;
 	}
+
+#ifdef LWS_USE_LIBEV
+	if (LWS_LIBEV_ENABLED(context)) {
+		context->w_accept.context = context;
+		context->w_sigint.context = context;
+	}
+#endif /* LWS_USE_LIBEV */
+
 	context->lws_lookup = (struct libwebsocket **)
 		      malloc(sizeof(struct libwebsocket *) * context->max_fds);
 	if (context->lws_lookup == NULL) {
@@ -2049,23 +2177,25 @@ libwebsocket_create_context(struct lws_context_creation_info *info)
 	memset(context->lws_lookup, 0, sizeof(struct libwebsocket *) *
 							context->max_fds);
 
-#ifdef _WIN32
-	context->fds_count = 0;
-#else
-	if (pipe(context->dummy_pipe_fds)) {
-		lwsl_err("Unable to create pipe\n");
-		free(context->lws_lookup);
-		free(context->fds);
-		free(context);
-		return NULL;
-	}
+	if (!LWS_LIBEV_ENABLED(context)) {
+	#ifdef _WIN32
+		context->fds_count = 0;
+	#else
+		if (pipe(context->dummy_pipe_fds)) {
+			lwsl_err("Unable to create pipe\n");
+			free(context->lws_lookup);
+			free(context->fds);
+			free(context);
+			return NULL;
+		}
 
-	/* use the read end of pipe as first item */
-	context->fds[0].fd = context->dummy_pipe_fds[0];
-	context->fds[0].events = POLLIN;
-	context->fds[0].revents = 0;
-	context->fds_count = 1;
-#endif
+		/* use the read end of pipe as first item */
+		context->fds[0].fd = context->dummy_pipe_fds[0];
+		context->fds[0].events = POLLIN;
+		context->fds[0].revents = 0;
+		context->fds_count = 1;
+	#endif
+	}
 
 #ifndef LWS_NO_EXTENSIONS
 	context->extensions = info->extensions;
@@ -2140,7 +2270,7 @@ libwebsocket_create_context(struct lws_context_creation_info *info)
 	}
 
 #ifndef LWS_NO_SERVER
-	if (info->port) {
+	if (info->port != CONTEXT_PORT_NO_LISTEN) {
 
 #ifdef LWS_OPENSSL_SUPPORT
 		context->use_ssl = info->ssl_cert_filepath != NULL &&
@@ -2405,7 +2535,7 @@ libwebsocket_create_context(struct lws_context_creation_info *info)
 #ifndef LWS_NO_SERVER
 	/* set up our external listening socket we serve on */
 
-	if (info->port) {
+	if (info->port != CONTEXT_PORT_NO_LISTEN) {
 		int sockfd;
 
 		sockfd = socket(AF_INET, SOCK_STREAM, 0);
@@ -2454,6 +2584,15 @@ libwebsocket_create_context(struct lws_context_creation_info *info)
 			compatible_close(sockfd);
 			goto bail;
 		}
+		
+	struct sockaddr_in sin;
+	socklen_t len = sizeof(sin);
+	if (getsockname(sockfd, (struct sockaddr *)&sin, &len) == -1)
+		perror("getsockname");
+	else
+		info->port = ntohs(sin.sin_port);
+	
+	context->listen_port = info->port;
 
 		wsi = (struct libwebsocket *)malloc(
 					sizeof(struct libwebsocket));
@@ -2524,7 +2663,7 @@ libwebsocket_create_context(struct lws_context_creation_info *info)
 	 */
 
 	m = LWS_EXT_CALLBACK_CLIENT_CONTEXT_CONSTRUCT;
-	if (info->port)
+	if (info->port != CONTEXT_PORT_NO_LISTEN)
 		m = LWS_EXT_CALLBACK_SERVER_CONTEXT_CONSTRUCT;
 
 	if (info->extensions) {
diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h
index 18da97d76cbce0bcfe60584ee937854070346e71..5bdd8b694b64576f55e99d1488a3c8730f98cd94 100644
--- a/lib/libwebsockets.h
+++ b/lib/libwebsockets.h
@@ -80,13 +80,17 @@ typedef SSIZE_T ssize_t;
 
 #endif
 
+#ifdef LWS_USE_LIBEV
+#include <ev.h>
+#endif /* LWS_USE_LIBEV */
+
 #include <assert.h>
 
 #ifndef LWS_EXTERN
 #define LWS_EXTERN extern
 #endif
 
-#define CONTEXT_PORT_NO_LISTEN 0
+#define CONTEXT_PORT_NO_LISTEN -1
 #define MAX_MUX_RECURSION 2
 
 enum lws_log_levels {
@@ -144,7 +148,8 @@ LWS_VISIBLE LWS_EXTERN void lwsl_hexdump(void *buf, size_t len);
 enum libwebsocket_context_options {
 	LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT = 2,
 	LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME = 4,
-	LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT = 8
+	LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT = 8,
+	LWS_SERVER_OPTION_LIBEV = 16
 };
 
 enum libwebsocket_callback_reasons {
@@ -968,6 +973,20 @@ libwebsocket_service(struct libwebsocket_context *context, int timeout_ms);
 LWS_VISIBLE LWS_EXTERN void
 libwebsocket_cancel_service(struct libwebsocket_context *context);
 
+#ifdef LWS_USE_LIBEV
+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);
+#endif /* LWS_USE_LIBEV */
+
 LWS_VISIBLE LWS_EXTERN int
 libwebsocket_service_fd(struct libwebsocket_context *context,
 							 struct pollfd *pollfd);
diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h
index 0d02f987fdcde1480198a62503aded7e07b0707f..f56aba5c31c118b85473ce600d453f687532dab1 100644
--- a/lib/private-libwebsockets.h
+++ b/lib/private-libwebsockets.h
@@ -92,6 +92,10 @@
 #include <netinet/tcp.h>
 #include <arpa/inet.h>
 #include <poll.h>
+#ifdef LWS_USE_LIBEV
+#include <ev.h>
+#endif /* LWS_USE_LIBEV */
+
 #include <sys/mman.h>
 #include <sys/time.h>
 
@@ -265,10 +269,27 @@ enum {
 struct libwebsocket_protocols;
 struct libwebsocket;
 
+#ifdef LWS_USE_LIBEV
+struct lws_io_watcher {
+	struct ev_io watcher;
+	struct libwebsocket_context* context;
+};
+
+struct lws_signal_watcher {
+	struct ev_signal watcher;
+	struct libwebsocket_context* context;
+};
+#endif /* LWS_USE_LIBEV */
+
 struct libwebsocket_context {
 	struct pollfd *fds;
 	struct libwebsocket **lws_lookup; /* fd to wsi */
 	int fds_count;
+#ifdef LWS_USE_LIBEV
+	struct ev_loop* io_loop;
+	struct lws_io_watcher w_accept;
+	struct lws_signal_watcher w_sigint;
+#endif /* LWS_USE_LIBEV */
 	int max_fds;
 	int listen_port;
 	const char *iface;
@@ -327,6 +348,13 @@ struct libwebsocket_context {
 	void *user_space;
 };
 
+#ifdef LWS_USE_LIBEV
+#define LWS_LIBEV_ENABLED(context) (context->options & LWS_SERVER_OPTION_LIBEV)
+#else
+#define LWS_LIBEV_ENABLED(context) (0)
+#endif
+
+
 enum uri_path_states {
 	URIPS_IDLE,
 	URIPS_SEEN_SLASH,
@@ -415,6 +443,10 @@ struct libwebsocket {
 
 	/* lifetime members */
 
+#ifdef LWS_USE_LIBEV
+    struct lws_io_watcher w_read;
+    struct lws_io_watcher w_write;
+#endif /* LWS_USE_LIBEV */
 	const struct libwebsocket_protocols *protocol;
 #ifndef LWS_NO_EXTENSIONS
 	struct libwebsocket_extension *
diff --git a/lib/server.c b/lib/server.c
index 0178df2fa4ac2cd8115bd7a67728d6373bd82224..2e76cd6d0700b1e73370f9988a4182c7e1ae98af 100644
--- a/lib/server.c
+++ b/lib/server.c
@@ -188,6 +188,9 @@ int lws_server_socket_service(struct libwebsocket_context *context,
 
 		/* one shot */
 		lws_change_pollfd(wsi, POLLOUT, 0);
+#ifdef LWS_USE_LIBEV
+        ev_io_stop(context->io_loop,(struct ev_io*)&(wsi->w_write));
+#endif /* LWS_USE_LIBEV */
 
 		if (wsi->state != WSI_STATE_HTTP_ISSUING_FILE) {
 			n = user_callback_handle_rxflow(
@@ -272,6 +275,18 @@ 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
+        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 */
 
 #ifdef LWS_OPENSSL_SUPPORT
 		new_wsi->ssl = NULL;
@@ -338,6 +353,9 @@ int lws_server_socket_service(struct libwebsocket_context *context,
 	case LWS_CONNMODE_SSL_ACK_PENDING:
 
 		lws_change_pollfd(wsi, POLLOUT, 0);
+#ifdef LWS_USE_LIBEV
+        ev_io_stop(context->io_loop,(struct ev_io*)&(wsi->w_write));
+#endif /* LWS_USE_LIBEV */
 
 		lws_latency_pre(context, wsi);
 
@@ -382,11 +400,17 @@ int lws_server_socket_service(struct libwebsocket_context *context,
 
 			if (m == SSL_ERROR_WANT_READ) {
 				lws_change_pollfd(wsi, 0, POLLIN);
+#ifdef LWS_USE_LIBEV
+                    ev_io_start(context->io_loop,(struct ev_io*)&(wsi->w_read));
+#endif /* LWS_USE_LIBEV */
 				lwsl_info("SSL_ERROR_WANT_READ\n");
 				break;
 			}
 			if (m == SSL_ERROR_WANT_WRITE) {
 				lws_change_pollfd(wsi, 0, POLLOUT);
+#ifdef LWS_USE_LIBEV
+                    ev_io_start(context->io_loop,(struct ev_io*)&(wsi->w_write));
+#endif /* LWS_USE_LIBEV */
 				break;
 			}
 			lwsl_debug("SSL_accept failed skt %u: %s\n",