[MEDIUM] implement tcp-smart-connect option at the backend

This new option enables combining of request buffer data with
the initial ACK of an outgoing TCP connection. Doing so saves
one packet per connection which is quite noticeable on workloads
mostly consisting in small objects. The option is not enabled by
default.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 3266a44..ce2a02b 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -2789,6 +2789,35 @@
   of doubt, consider setting it back to automatic values by prepending the
   "default" keyword before it, or disabling it using the "no" keyword.
 
+  See also : "option tcp-smart-connect"
+
+
+option tcp-smart-connect
+no option tcp-smart-connect
+  Enable or disable the saving of one ACK packet during the connect sequence
+  May be used in sections :   defaults | frontend | listen | backend
+                                 yes   |    no    |   yes  |   yes
+  Arguments : none
+
+  On certain systems (at least Linux), HAProxy can ask the kernel not to
+  immediately send an empty ACK upon a connection request, but to directly
+  send the buffer request instead. This saves one packet on the network and
+  thus boosts performance. It can also be useful for some servers, because they
+  immediately get the request along with the incoming connection.
+
+  This feature is enabled when "option tcp-smart-connect" is set in a backend.
+  It is not enabled by default because it makes network troubleshooting more
+  complex.
+
+  It only makes sense to enable it with protocols where the client speaks first
+  such as HTTP. In other situations, if there is no data to send in place of
+  the ACK, a normal ACK is sent.
+
+  If this option has been enabled in a "defaults" section, it can be disabled
+  in a specific instance by prepending the "no" keyword before it.
+
+  See also : "option tcp-smart-accept"
+
 
 option tcpka
   Enable or disable the sending of TCP keepalive packets on both sides
diff --git a/include/types/proxy.h b/include/types/proxy.h
index 7664618..715f21d 100644
--- a/include/types/proxy.h
+++ b/include/types/proxy.h
@@ -118,6 +118,7 @@
 #define PR_O2_NOLOGNORM	0x00000020      /* don't log normal traffic, only errors and retries */
 #define PR_O2_LOGERRORS	0x00000040      /* log errors and retries at level LOG_ERR */
 #define PR_O2_SMARTACC 	0x00000080      /* don't immediately ACK request after accept */
+#define PR_O2_SMARTCON 	0x00000100      /* don't immediately send empty ACK after connect */
 
 /* This structure is used to apply fast weighted round robin on a server group */
 struct fwrr_group {
diff --git a/src/backend.c b/src/backend.c
index 5e78fd8..58de35e 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -18,6 +18,8 @@
 #include <string.h>
 #include <ctype.h>
 
+#include <netinet/tcp.h>
+
 #include <common/compat.h>
 #include <common/config.h>
 #include <common/debug.h>
@@ -1912,6 +1914,15 @@
 		}
 	}
 
+#ifdef TCP_QUICKACK
+	/* disabling tcp quick ack now allows the first request to leave the
+	 * machine with the first ACK. We only do this if there are pending
+	 * data in the buffer.
+	 */
+	if ((s->be->options2 & PR_O2_SMARTCON) && s->req->send_max)
+                setsockopt(fd, SOL_TCP, TCP_QUICKACK, (char *) &zero, sizeof(zero));
+#endif
+
 	if ((connect(fd, (struct sockaddr *)&s->srv_addr, sizeof(s->srv_addr)) == -1) &&
 	    (errno != EINPROGRESS) && (errno != EALREADY) && (errno != EISCONN)) {
 
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 03a5303..9ec869e 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -136,6 +136,7 @@
 	{ "dontlog-normal",               PR_O2_NOLOGNORM, PR_CAP_FE, 0 },
 	{ "log-separate-errors",          PR_O2_LOGERRORS, PR_CAP_FE, 0 },
 	{ "tcp-smart-accept",             PR_O2_SMARTACC,  PR_CAP_FE, 0 },
+	{ "tcp-smart-connect",            PR_O2_SMARTCON,  PR_CAP_BE, 0 },
 	{ NULL, 0, 0, 0 }
 };