summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaciej Soltysiak <maciej@soltysiak.com>2014-10-13 17:28:14 +0200
committerMaciej Soltysiak <maciej@soltysiak.com>2014-10-13 17:28:14 +0200
commitb625361a6a2b2bc4ba1c71a1d6dc89f5e2b4d9e0 (patch)
tree0e1cc42110ac29b3169ef9bd19bf6188239aa27c
parentc750c704c10c9e412fa5501fce051fa45d46ec84 (diff)
downloadlibevent-b625361a6a2b2bc4ba1c71a1d6dc89f5e2b4d9e0.tar.gz
Provide support for SO_REUSEPORT through LEV_OPT_REUSABLE_PORT
-rw-r--r--evutil.c14
-rw-r--r--include/event2/listener.h9
-rw-r--r--include/event2/util.h13
-rw-r--r--listener.c5
4 files changed, 41 insertions, 0 deletions
diff --git a/evutil.c b/evutil.c
index df93e67f..3d72e403 100644
--- a/evutil.c
+++ b/evutil.c
@@ -368,6 +368,20 @@ evutil_make_listen_socket_reuseable(evutil_socket_t sock)
}
int
+evutil_make_listen_socket_reuseable_port(evutil_socket_t sock)
+{
+#if defined __linux__ && defined(SO_REUSEPORT)
+ int one = 1;
+ /* REUSEPORT on Linux 3.9+ means, "Multiple servers (processes or
+ * threads) can bind to the same port if they each set the option. */
+ return setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (void*) &one,
+ (ev_socklen_t)sizeof(one));
+#else
+ return 0;
+#endif
+}
+
+int
evutil_make_tcp_listen_socket_deferred(evutil_socket_t sock)
{
#if defined(EVENT__HAVE_NETINET_TCP_H) && defined(TCP_DEFER_ACCEPT)
diff --git a/include/event2/listener.h b/include/event2/listener.h
index 8c77803d..84b4da05 100644
--- a/include/event2/listener.h
+++ b/include/event2/listener.h
@@ -88,6 +88,15 @@ typedef void (*evconnlistener_errorcb)(struct evconnlistener *, void *);
* to use the option before it is actually bound.
*/
#define LEV_OPT_DEFERRED_ACCEPT (1u<<6)
+/** Flag: Indicates that we ask to allow multiple servers (processes or
+ * threads) to bind to the same port if they each set the option.
+ *
+ * SO_REUSEPORT is what most people would expect SO_REUSEADDR to be, however
+ * SO_REUSEPORT does not imply SO_REUSEADDR.
+ *
+ * This is only available on Linux and kernel 3.9+
+ */
+#define LEV_OPT_REUSEABLE_PORT (1u<<7)
/**
Allocate a new evconnlistener object to listen for incoming TCP connections
diff --git a/include/event2/util.h b/include/event2/util.h
index 14c6a25d..62b94773 100644
--- a/include/event2/util.h
+++ b/include/event2/util.h
@@ -327,6 +327,19 @@ int evutil_make_socket_nonblocking(evutil_socket_t sock);
EVENT2_EXPORT_SYMBOL
int evutil_make_listen_socket_reuseable(evutil_socket_t sock);
+/** Do platform-specific operations to make a listener port reusable.
+
+ Specifically, we want to make sure that multiple programs which also
+ set the same socket option will be able to bind, listen at the same time.
+
+ This is a feature available only to Linux 3.9+
+
+ @param sock The socket to make reusable
+ @return 0 on success, -1 on failure
+ */
+EVENT2_EXPORT_SYMBOL
+int evutil_make_listen_socket_reuseable_port(evutil_socket_t sock);
+
/** Do platform-specific operations as needed to close a socket upon a
successful execution of one of the exec*() functions.
diff --git a/listener.c b/listener.c
index 3272c405..172d2927 100644
--- a/listener.c
+++ b/listener.c
@@ -235,6 +235,11 @@ evconnlistener_new_bind(struct event_base *base, evconnlistener_cb cb,
goto err;
}
+ if (flags & LEV_OPT_REUSEABLE_PORT) {
+ if (evutil_make_listen_socket_reuseable_port(fd) < 0)
+ goto err;
+ }
+
if (flags & LEV_OPT_DEFERRED_ACCEPT) {
if (evutil_make_tcp_listen_socket_deferred(fd) < 0)
goto err;