Avoid pure-ACK TCP segments during command phase
authorJeremy Harris <jgh146exb@wizmail.org>
Tue, 18 Oct 2016 22:35:35 +0000 (23:35 +0100)
committerJeremy Harris <jgh146exb@wizmail.org>
Tue, 18 Oct 2016 22:35:35 +0000 (23:35 +0100)
src/src/smtp_in.c
src/src/transports/smtp.c
src/src/verify.c

index 17dd78c..9282352 100644 (file)
@@ -143,6 +143,8 @@ static BOOL pipelining_advertised;
 static BOOL rcpt_smtp_response_same;
 static BOOL rcpt_in_progress;
 static int  nonmail_command_count;
+static int  off = 0;
+static int  on = 1;
 static BOOL smtp_exit_function_called = 0;
 #ifdef SUPPORT_I18N
 static BOOL smtputf8_advertised;
@@ -3544,6 +3546,12 @@ while (done <= 0)
     }
 #endif
 
+#ifdef TCP_QUICKACK
+  if (smtp_in)         /* Avoid pure-ACKs while in cmd pingpong phase */
+    (void) setsockopt(fileno(smtp_in), IPPROTO_TCP, TCP_QUICKACK,
+           US &off, sizeof(off));
+#endif
+
   switch(smtp_read_command(TRUE))
     {
     /* The AUTH command is not permitted to occur inside a transaction, and may
@@ -4826,6 +4834,11 @@ while (done <= 0)
          "354 Enter message, ending with \".\" on a line by itself\r\n");
       }
 
+#ifdef TCP_QUICKACK
+    if (smtp_in)       /* all ACKs needed to ramp window up for bulk data */
+      (void) setsockopt(fileno(smtp_in), IPPROTO_TCP, TCP_QUICKACK,
+             US &on, sizeof(on));
+#endif
     done = 3;
     message_ended = END_NOTENDED;   /* Indicate in middle of data */
 
index af2d40f..c644397 100644 (file)
@@ -286,6 +286,7 @@ static uschar *smtp_command;   /* Points to last cmd for error messages */
 static uschar *mail_command;   /* Points to MAIL cmd for error messages */
 static BOOL    update_waiting; /* TRUE to update the "wait" database */
 static BOOL    pipelining_active; /* current transaction is in pipe mode */
+static int     off = 0;       /* for use by setsockopt */
 
 
 /*************************************************
@@ -1705,7 +1706,12 @@ if (continue_hostname == NULL)
 
   if (!lflags.smtps)
     {
-    BOOL good_response = smtp_read_response(&inblock, buffer, sizeof(buffer),
+    BOOL good_response;
+
+#ifdef TCP_QUICKACK
+    (void) setsockopt(inblock.sock, IPPROTO_TCP, TCP_QUICKACK, US &off, sizeof(off));
+#endif
+    good_response = smtp_read_response(&inblock, buffer, sizeof(buffer),
       '2', ob->command_timeout);
 #ifdef EXPERIMENTAL_DSN_INFO
     smtp_greeting = string_copy(buffer);
@@ -1732,7 +1738,7 @@ if (continue_hostname == NULL)
     /* Now check if the helo_data expansion went well, and sign off cleanly if
     it didn't. */
 
-    if (helo_data == NULL)
+    if (!helo_data)
       {
       uschar *message = string_sprintf("failed to expand helo_data: %s",
         expand_string_message);
index ff9a5a5..f8f1809 100644 (file)
@@ -41,6 +41,8 @@ static tree_node *dnsbl_cache = NULL;
 
 static uschar cutthrough_response(char, uschar **);
 
+static int     off = 0;       /* for use by setsockopt */
+
 
 /*************************************************
 *          Retrieve a callout cache record       *
@@ -683,6 +685,9 @@ can do it there for the non-rcpt-verify case.  For this we keep an addresscount.
     if (!smtps || (smtps && tls_out.active >= 0))
 #endif
       {
+#ifdef TCP_QUICKACK
+      (void) setsockopt(inblock.sock, IPPROTO_TCP, TCP_QUICKACK, US &off, sizeof(off));
+#endif
       if (!(done= smtp_read_response(&inblock, responsebuffer, sizeof(responsebuffer), '2', callout)))
         goto RESPONSE_FAILED;