diff options
author | Maciej Soltysiak <maciej@soltysiak.com> | 2014-10-13 17:28:14 +0200 |
---|---|---|
committer | Maciej Soltysiak <maciej@soltysiak.com> | 2014-10-13 17:28:14 +0200 |
commit | b625361a6a2b2bc4ba1c71a1d6dc89f5e2b4d9e0 (patch) | |
tree | 0e1cc42110ac29b3169ef9bd19bf6188239aa27c | |
parent | c750c704c10c9e412fa5501fce051fa45d46ec84 (diff) | |
download | libevent-b625361a6a2b2bc4ba1c71a1d6dc89f5e2b4d9e0.tar.gz |
Provide support for SO_REUSEPORT through LEV_OPT_REUSABLE_PORT
-rw-r--r-- | evutil.c | 14 | ||||
-rw-r--r-- | include/event2/listener.h | 9 | ||||
-rw-r--r-- | include/event2/util.h | 13 | ||||
-rw-r--r-- | listener.c | 5 |
4 files changed, 41 insertions, 0 deletions
@@ -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. @@ -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; |