summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Vassdal <shutter@canternet.org>2013-05-22 12:48:58 -0700
committerattilamolnar <attilamolnar@hush.com>2013-06-03 18:45:46 +0200
commit263c2efd960057f1cfafd40fce338605c39b0ad4 (patch)
treebd953e551f1f184b3725da2cf9656a4bb302983b
parentca4c4a67988419b9eb479ffcf82238dc1648b0ad (diff)
Added option for using TCP_DEFER_ACCEPT. Prevents the connection from being handed over to the daemon before data is ready from the client.
-rwxr-xr-xconfigure19
-rw-r--r--docs/conf/inspircd.conf.example11
-rw-r--r--make/test/so_acceptfilter.cpp27
-rw-r--r--make/test/tcp_defer_accept.cpp27
-rw-r--r--src/listensocket.cpp17
5 files changed, 101 insertions, 0 deletions
diff --git a/configure b/configure
index ccb487372..5a0bbd4e9 100755
--- a/configure
+++ b/configure
@@ -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