]> granicus.if.org Git - libevent/commitdiff
Provide support for SO_REUSEPORT through LEV_OPT_REUSABLE_PORT
authorMaciej Soltysiak <maciej@soltysiak.com>
Mon, 13 Oct 2014 15:28:14 +0000 (17:28 +0200)
committerMaciej Soltysiak <maciej@soltysiak.com>
Mon, 13 Oct 2014 15:28:14 +0000 (17:28 +0200)
evutil.c
include/event2/listener.h
include/event2/util.h
listener.c

index df93e67f05e9dcf5ba788da6e19391a9fd24d644..3d72e4032450d89498ad84467aaa8df4ec848abc 100644 (file)
--- a/evutil.c
+++ b/evutil.c
@@ -367,6 +367,20 @@ evutil_make_listen_socket_reuseable(evutil_socket_t sock)
 #endif
 }
 
+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)
 {
index 8c77803d6d84ce19dcdfb15518a06413ca541ad1..84b4da055d8d24fa3edd1e4b1fa3f40f769991de 100644 (file)
@@ -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
index 14c6a25d7a86d1bb24578cd2579105fb05a9d5e2..62b94773ac88d02721368e0ab7a28ca64401c27a 100644 (file)
@@ -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.
 
index 3272c405ce6eeea844ccbde42c0632d32d7b49d1..172d2927c0c3c70198538b2711fe9100be968d6f 100644 (file)
@@ -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;