diff options
-rwxr-xr-x | configure | 19 | ||||
-rw-r--r-- | docs/conf/inspircd.conf.example | 11 | ||||
-rw-r--r-- | make/test/so_acceptfilter.cpp | 27 | ||||
-rw-r--r-- | make/test/tcp_defer_accept.cpp | 27 | ||||
-rw-r--r-- | src/listensocket.cpp | 17 |
5 files changed, 101 insertions, 0 deletions
@@ -346,6 +346,18 @@ if (test_file($config{CC}, "eventfd.cpp")) { print "no\n"; } +printf "Checking if a TCP deferring mechanism is available... "; +if (test_file($config{CC}, "tcp_defer_accept.cpp")) { + $config{HAS_DEFER} = "TCP_DEFER_ACCEPT"; + print "yes (TCP_DEFER_ACCEPT)\n"; +} elsif (test_file($config{CC}, "so_acceptfilter.cpp")) { + $config{HAS_DEFER} = "SO_ACCEPTFILTER"; + print "yes (SO_ACCEPTFILTER)\n"; +} else { + $config{HAS_DEFER} = "false"; + print "no\n"; +} + print "Checking whether epoll is available... "; $has_epoll = test_header($config{CC}, "sys/epoll.h"); print $has_epoll ? "yes\n" : "no\n"; @@ -875,6 +887,13 @@ print FILEHANDLE "#define MAXBUF " . ($config{MAXBUF}+2) . "\n"; $config{SOCKETENGINE} = "socketengine_select"; } } + + if ($config{HAS_DEFER} eq "TCP_DEFER_ACCEPT") { + print FILEHANDLE "#define USE_TCP_DEFER_ACCEPT"; + } elsif ($config{HAS_DEFER} eq "SO_ACCEPTFILTER") { + print FILEHANDLE "#define USE_SO_ACCEPTFILTER" + } + print FILEHANDLE "\n#include \"threadengines/threadengine_pthread.h\"\n"; close(FILEHANDLE); diff --git a/docs/conf/inspircd.conf.example b/docs/conf/inspircd.conf.example index eeed82237..f6dc96ecd 100644 --- a/docs/conf/inspircd.conf.example +++ b/docs/conf/inspircd.conf.example @@ -164,6 +164,17 @@ # for ssl to work. If you do not want this bind section to support ssl, # just remove or comment out this option. ssl="gnutls" + + # defer: When this is non-zero, connections will not be handed over to + # the daemon from the operating system before data is ready. + # In Linux, the value indicates the number of seconds we'll wait for a + # connection to come up with data. Don't set it too low! + # In BSD the value is ignored; only zero and non-zero is possible. + # Windows ignores this parameter completely. + # Note: This does not take effect on rehash. + # To change it on a running bind, you'll have to comment it out, + # rehash, comment it in and rehash again. + defer="0" > <bind address="" port="6660-6669" type="clients"> diff --git a/make/test/so_acceptfilter.cpp b/make/test/so_acceptfilter.cpp new file mode 100644 index 000000000..0fd4cda4f --- /dev/null +++ b/make/test/so_acceptfilter.cpp @@ -0,0 +1,27 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <sys/socket.h> + +#ifndef SO_ACCEPTFILTER + #error +#endif + +int main() +{ + return 0; +} diff --git a/make/test/tcp_defer_accept.cpp b/make/test/tcp_defer_accept.cpp new file mode 100644 index 000000000..191b1ac70 --- /dev/null +++ b/make/test/tcp_defer_accept.cpp @@ -0,0 +1,27 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <netinet/tcp.h> + +#ifndef TCP_DEFER_ACCEPT + #error +#endif + +int main() +{ + return 0; +} diff --git a/src/listensocket.cpp b/src/listensocket.cpp index 466b91c8b..f875bc646 100644 --- a/src/listensocket.cpp +++ b/src/listensocket.cpp @@ -22,6 +22,10 @@ #include "socket.h" #include "socketengine.h" +#ifdef USE_TCP_DEFER_ACCEPT +#include <netinet/tcp.h> +#endif + ListenSocket::ListenSocket(ConfigTag* tag, const irc::sockets::sockaddrs& bind_to) : bind_tag(tag) { @@ -38,6 +42,19 @@ ListenSocket::ListenSocket(ConfigTag* tag, const irc::sockets::sockaddrs& bind_t if (rv >= 0) rv = ServerInstance->SE->Listen(this->fd, ServerInstance->Config->MaxConn); + int timeout = tag->getInt("defer", 0); + if (timeout && !rv) + { +#ifdef USE_TCP_DEFER_ACCEPT + setsockopt(fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &timeout, sizeof(timeout)); +#elif defined USE_SO_ACCEPTFILTER + struct accept_filter_arg afa; + memset(&afa, 0, sizeof(afa)); + strcpy(afa.af_name, "dataready"); + setsockopt(fd, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(afa)); +#endif + } + #ifdef IPV6_V6ONLY /* This OS supports IPv6 sockets that can also listen for IPv4 * connections. If our address is "*" or empty, enable both v4 and v6 to |