From 8d330698b5121d75af35b62b420314f68026d1e5 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Tue, 18 Oct 2016 23:35:35 +0100 Subject: [PATCH] Avoid pure-ACK TCP segments during command phase --- src/src/smtp_in.c | 13 +++++++++++++ src/src/transports/smtp.c | 10 ++++++++-- src/src/verify.c | 5 +++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c index 17dd78cd8..9282352ac 100644 --- a/src/src/smtp_in.c +++ b/src/src/smtp_in.c @@ -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 */ diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c index af2d40fa0..c64439786 100644 --- a/src/src/transports/smtp.c +++ b/src/src/transports/smtp.c @@ -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); diff --git a/src/src/verify.c b/src/src/verify.c index ff9a5a5c0..f8f1809cb 100644 --- a/src/src/verify.c +++ b/src/src/verify.c @@ -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; -- 2.30.2