netdb.h \
netinet/in.h \
netinet/in6.h \
+ netinet/tcp.h \
poll.h \
port.h \
stdarg.h \
#ifdef _EVENT_HAVE_NETINET_IN6_H
#include <netinet/in6.h>
#endif
+#ifdef _EVENT_HAVE_NETINET_TCP_H
+#include <netinet/tcp.h>
+#endif
#ifdef _EVENT_HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#endif
}
+int
+evutil_make_tcp_listen_socket_deferred(evutil_socket_t sock)
+{
+#if defined(_EVENT_HAVE_NETINET_TCP_H) && defined(TCP_DEFER_ACCEPT)
+ int one = 1;
+
+ /* TCP_DEFER_ACCEPT tells the kernel to call defer accept() only after data
+ * has arrived and ready to read */
+ return setsockopt(sock, IPPROTO_TCP, TCP_DEFER_ACCEPT, &one,
+ (ev_socklen_t)sizeof(one));
+#endif
+ return 0;
+}
+
int
evutil_make_socket_closeonexec(evutil_socket_t fd)
{
/** Flag: Indicates that the listener should be created in disabled
* state. Use evconnlistener_enable() to enable it later. */
#define LEV_OPT_DISABLED (1u<<5)
+/** Flag: Indicates that the listener should defer accept() until data is
+ * available, if possible. Ignored on platforms that do not support this.
+ *
+ * This option can help performance for protocols where the client transmits
+ * immediately after connecting. */
+#define LEV_OPT_DEFERRED_ACCEPT (1u<<6)
/**
Allocate a new evconnlistener object to listen for incoming TCP connections
int evutil_closesocket(evutil_socket_t sock);
#define EVUTIL_CLOSESOCKET(s) evutil_closesocket(s)
+/** Do platform-specific operations, if possible, to make a tcp listener
+ * socket defer accept()s until there is data to read.
+ *
+ * Not all platforms support this. You don't want to do this for every
+ * listener socket: only the ones that implement a protocol where the
+ * client transmits before the server needs to respond.
+ *
+ * @param sock The listening socket to to make deferred
+ * @return 0 on success (whether the operation is supported or not),
+ * -1 on failure
+*/
+int evutil_make_tcp_listen_socket_deferred(evutil_socket_t sock);
#ifdef _WIN32
/** Return the most recent socket error. Not idempotent on all platforms. */
evutil_make_listen_socket_reuseable(fd);
}
+ if (flags & LEV_OPT_DEFERRED_ACCEPT) {
+ evutil_make_tcp_listen_socket_deferred(fd);
+ }
+
if (sa) {
if (bind(fd, sa, socklen)<0) {
evutil_closesocket(fd);