uschar *iface;
int sep = 0;
-if (istring == NULL) return TRUE;
+if (!istring) return TRUE;
-expint = expand_string(istring);
-if (expint == NULL)
+if (!(expint = expand_string(istring)))
{
if (expand_string_forcedfail) return TRUE;
addr->transport_return = PANIC;
if (*expint == 0) return TRUE;
while ((iface = string_nextinlist(&expint, &sep, big_buffer,
- big_buffer_size)) != NULL)
+ big_buffer_size)))
{
if (string_is_ip_address(iface, NULL) == 0)
{
break;
}
-if (iface != NULL) *interface = string_copy(iface);
+if (iface) *interface = string_copy(iface);
return TRUE;
}
int dscp_level;
int dscp_option;
int sock;
-int on = 1;
int save_errno = 0;
+BOOL fastopen = FALSE;
#ifndef DISABLE_EVENT
deliver_host_address = host->address;
if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, US &on, sizeof(on)))
HDEBUG(D_transport|D_acl|D_v)
- debug_printf("failed to set NODELAY: %s ", strerror(errno));
+ debug_printf_indent("failed to set NODELAY: %s ", strerror(errno));
/* Set DSCP value, if we can. For now, if we fail to set the value, we don't
bomb out, just log it and continue in default traffic class. */
if (dscp && dscp_lookup(dscp, host_af, &dscp_level, &dscp_option, &dscp_value))
{
HDEBUG(D_transport|D_acl|D_v)
- debug_printf("DSCP \"%s\"=%x ", dscp, dscp_value);
+ debug_printf_indent("DSCP \"%s\"=%x ", dscp, dscp_value);
if (setsockopt(sock, dscp_level, dscp_option, &dscp_value, sizeof(dscp_value)) < 0)
HDEBUG(D_transport|D_acl|D_v)
- debug_printf("failed to set DSCP: %s ", strerror(errno));
+ debug_printf_indent("failed to set DSCP: %s ", strerror(errno));
/* If the kernel supports IPv4 and IPv6 on an IPv6 socket, we need to set the
option for both; ignore failures here */
if (host_af == AF_INET6 &&
(void) setsockopt(sock, dscp_level, dscp_option, &dscp_value, sizeof(dscp_value));
}
+#ifdef TCP_FASTOPEN
+if (verify_check_given_host (&ob->hosts_try_fastopen, host) == OK) fastopen = TRUE;
+#endif
+
/* Bind to a specific interface if requested. Caller must ensure the interface
is the same type (IPv4 or IPv6) as the outgoing address. */
{
save_errno = errno;
HDEBUG(D_transport|D_acl|D_v)
- debug_printf("unable to bind outgoing SMTP call to %s: %s", interface,
+ debug_printf_indent("unable to bind outgoing SMTP call to %s: %s", interface,
strerror(errno));
}
/* Connect to the remote host, and add keepalive to the socket before returning
it, if requested. */
-else if (ip_connect(sock, host_af, host->address, port, timeout) < 0)
+else if (ip_connect(sock, host_af, host->address, port, timeout, fastopen) < 0)
save_errno = errno;
/* Either bind() or connect() failed */
{
HDEBUG(D_transport|D_acl|D_v)
{
- debug_printf("failed: %s", CUstrerror(save_errno));
+ debug_printf_indent("failed: %s", CUstrerror(save_errno));
if (save_errno == ETIMEDOUT)
debug_printf(" (timeout=%s)", readconf_printtime(timeout));
debug_printf("\n");
{
union sockaddr_46 interface_sock;
EXIM_SOCKLEN_T size = sizeof(interface_sock);
- HDEBUG(D_transport|D_acl|D_v) debug_printf("connected\n");
+ HDEBUG(D_transport|D_acl|D_v) debug_printf_indent("connected\n");
if (getsockname(sock, (struct sockaddr *)(&interface_sock), &size) == 0)
sending_ip_address = host_ntoa(-1, &interface_sock, NULL, &sending_port);
else
if (host->port != PORT_NONE)
{
HDEBUG(D_transport|D_acl|D_v)
- debug_printf("Transport port=%d replaced by host-specific port=%d\n", port,
+ debug_printf_indent("Transport port=%d replaced by host-specific port=%d\n", port,
host->port);
port = host->port;
}
#ifdef SUPPORT_SOCKS
if (ob->socks_proxy) s = string_sprintf("%svia proxy ", s);
#endif
- debug_printf("Connecting to %s %s%s... ", host->name, callout_address, s);
+ debug_printf_indent("Connecting to %s %s%s... ", host->name, callout_address, s);
}
/* Create and connect the socket */
flush_buffer(smtp_outblock *outblock)
{
int rc;
+int n = outblock->ptr - outblock->buffer;
+HDEBUG(D_transport|D_acl) debug_printf_indent("cmd buf flush %d bytes\n", n);
#ifdef SUPPORT_TLS
if (tls_out.active == outblock->sock)
- rc = tls_write(FALSE, outblock->buffer, outblock->ptr - outblock->buffer);
+ rc = tls_write(FALSE, outblock->buffer, n);
else
#endif
+ rc = send(outblock->sock, outblock->buffer, n, 0);
-rc = send(outblock->sock, outblock->buffer, outblock->ptr - outblock->buffer, 0);
if (rc <= 0)
{
- HDEBUG(D_transport|D_acl) debug_printf("send failed: %s\n", strerror(errno));
+ HDEBUG(D_transport|D_acl) debug_printf_indent("send failed: %s\n", strerror(errno));
return FALSE;
}
while (*p != 0) *p++ = '*';
}
- HDEBUG(D_transport|D_acl|D_v) debug_printf(" SMTP>> %s\n", big_buffer);
+ HDEBUG(D_transport|D_acl|D_v) debug_printf_indent(" SMTP>> %s\n", big_buffer);
}
if (!noflush)
/* Need to read a new input packet. */
- rc = ip_recv(sock, inblock->buffer, inblock->buffersize, timeout);
- if (rc <= 0) break;
+ if((rc = ip_recv(sock, inblock->buffer, inblock->buffersize, timeout)) <= 0)
+ {
+ if (!errno)
+ DEBUG(D_deliver|D_transport|D_acl) debug_printf_indent(" SMTP(closed)<<\n");
+ break;
+ }
/* Another block of data has been successfully read. Set up the pointers
and let the loop continue. */
ptrend = inblock->ptrend = inblock->buffer + rc;
ptr = inblock->buffer;
- DEBUG(D_transport|D_acl) debug_printf("read response data: size=%d\n", rc);
+ DEBUG(D_transport|D_acl) debug_printf_indent("read response data: size=%d\n", rc);
}
/* Get here if there has been some kind of recv() error; errno is set, but we
buffer where to put the response
size the size of the buffer
okdigit the expected first digit of the response
- timeout the timeout to use
+ timeout the timeout to use, in seconds
Returns: TRUE if a valid, non-error response was received; else FALSE
*/
errno = 0; /* Ensure errno starts out zero */
-/* This is a loop to read and concatentate the lines that make up a multi-line
+/* This is a loop to read and concatenate the lines that make up a multi-line
response. */
for (;;)
return FALSE;
HDEBUG(D_transport|D_acl|D_v)
- debug_printf(" %s %s\n", (ptr == buffer)? "SMTP<<" : " ", ptr);
+ debug_printf_indent(" %s %s\n", (ptr == buffer)? "SMTP<<" : " ", ptr);
/* Check the format of the response: it must start with three digits; if
these are followed by a space or end of line, the response is complete. If