changeset 1016:257f7d5fca97

piggyback data on acks when making connections on linux
author Matt Johnston <matt@ucc.asn.au>
date Fri, 13 Feb 2015 22:49:15 +0800
parents cb7b510b4dd2
children cb148f8d3d22
files cli-main.c dbutil.c
diffstat 2 files changed, 40 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/cli-main.c	Fri Feb 13 21:45:15 2015 +0800
+++ b/cli-main.c	Fri Feb 13 22:49:15 2015 +0800
@@ -73,7 +73,7 @@
 #endif
 	{
 		int sock = connect_remote(cli_opts.remotehost, cli_opts.remoteport, 
-				0, &error);
+				1, &error);
 		sock_in = sock_out = sock;
 	}
 
--- a/dbutil.c	Fri Feb 13 21:45:15 2015 +0800
+++ b/dbutil.c	Fri Feb 13 22:49:15 2015 +0800
@@ -150,18 +150,31 @@
 
 
 #ifdef DEBUG_TRACE
+
+static double time_since_start()
+{
+    static double start_time = -1;
+    double nowf;
+    struct timeval tv;
+    gettimeofday(&tv, NULL);
+    nowf = tv.tv_sec + (tv.tv_usec / 1000000.0);
+    if (start_time < 0)
+    {
+        start_time = nowf;
+        return 0;
+    }
+    return nowf - start_time;
+}
+
 void dropbear_trace(const char* format, ...) {
 	va_list param;
-	struct timeval tv;
 
 	if (!debug_trace) {
 		return;
 	}
 
-	gettimeofday(&tv, NULL);
-
 	va_start(param, format);
-	fprintf(stderr, "TRACE  (%d) %d.%d: ", getpid(), (int)tv.tv_sec, (int)tv.tv_usec);
+	fprintf(stderr, "TRACE  (%d) %f: ", getpid(), time_since_start());
 	vfprintf(stderr, format, param);
 	fprintf(stderr, "\n");
 	va_end(param);
@@ -170,7 +183,6 @@
 void dropbear_trace2(const char* format, ...) {
 	static int trace_env = -1;
 	va_list param;
-	struct timeval tv;
 
 	if (trace_env == -1) {
 		trace_env = getenv("DROPBEAR_TRACE2") ? 1 : 0;
@@ -180,10 +192,8 @@
 		return;
 	}
 
-	gettimeofday(&tv, NULL);
-
 	va_start(param, format);
-	fprintf(stderr, "TRACE2 (%d) %d.%d: ", getpid(), (int)tv.tv_sec, (int)tv.tv_usec);
+	fprintf(stderr, "TRACE2 (%d) %f: ", getpid(), time_since_start());
 	vfprintf(stderr, format, param);
 	fprintf(stderr, "\n");
 	va_end(param);
@@ -390,6 +400,23 @@
 }
 #endif
 
+#if defined(__linux__) && defined(TCP_DEFER_ACCEPT)
+static void set_piggyback_ack(int sock) {
+	/* Undocumented Linux feature - set TCP_DEFER_ACCEPT and data will be piggybacked
+	on the 3rd packet (ack) of the TCP handshake. Saves a IP packet.
+	http://thread.gmane.org/gmane.linux.network/224627/focus=224727
+	"Piggyback the final ACK of the three way TCP connection establishment with the data" */
+	int val = 1;
+	/* No error checking, this is opportunistic */
+	int err = setsockopt(sock, IPPROTO_TCP, TCP_DEFER_ACCEPT, (void*)&val, sizeof(val));
+	if (err)
+	{
+		DEBUG_TRACE(("Failed setsockopt TCP_DEFER_ACCEPT: %s", strerror(errno)))
+	}
+}
+#endif
+
+
 /* Connect via TCP to a host. Connection will try ipv4 or ipv6, will
  * return immediately if nonblocking is set. On failure, if errstring
  * wasn't null, it will be a newly malloced error message */
@@ -437,6 +464,10 @@
 
 		if (nonblocking) {
 			setnonblocking(sock);
+
+#if defined(__linux__) && defined(TCP_DEFER_ACCEPT)
+			set_piggyback_ack(sock);
+#endif
 		}
 
 		if (connect(sock, res->ai_addr, res->ai_addrlen) < 0) {