+#ifdef TCP_FASTOPEN
+static void
+tfo_out_check(int sock)
+{
+# if defined(TCP_INFO) && defined(EXIM_HAVE_TCPI_UNACKED)
+struct tcp_info tinfo;
+socklen_t len = sizeof(tinfo);
+
+if (getsockopt(sock, IPPROTO_TCP, TCP_INFO, &tinfo, &len) == 0)
+ {
+ /* This is a somewhat dubious detection method; totally undocumented so likely
+ to fail in future kernels. There seems to be no documented way. */
+
+ if (tinfo.tcpi_unacked > 1)
+ {
+ DEBUG(D_transport|D_v) debug_printf("TCP_FASTOPEN mode connection\n");
+ tcp_out_fastopen = TRUE;
+ }
+ }
+# endif
+}
+#endif
+
+
int
smtp_sock_connect(host_item * host, int host_af, int port, uschar * interface,
transport_instance * tb, int timeout)
return -1;
}
if (ob->keepalive) ip_keepalive(sock, host->address, TRUE);
+#ifdef TCP_FASTOPEN
+ tfo_out_check(sock);
+#endif
return sock;
}
}
+
+
+
+
+void
+smtp_port_for_connect(host_item * host, int port)
+{
+if (host->port != PORT_NONE)
+ {
+ HDEBUG(D_transport|D_acl|D_v)
+ debug_printf_indent("Transport port=%d replaced by host-specific port=%d\n", port,
+ host->port);
+ port = host->port;
+ }
+else host->port = port; /* Set the port actually used */
+}
+
+
/*************************************************
* Connect to remote host *
*************************************************/
non-IPv6 systems, to enable the code to be less messy. However, on such systems
host->address will always be an IPv4 address.
-The port field in the host item is used if it is set (usually router from SRV
-records or elsewhere). In other cases, the default passed as an argument is
-used, and the host item is updated with its value.
-
Arguments:
- host host item containing name and address (and sometimes port)
+ host host item containing name and address and port
host_af AF_INET or AF_INET6
- port default remote port to connect to, in host byte order, for those
- hosts whose port setting is PORT_NONE
interface outgoing interface address or NULL
timeout timeout value or 0
tb transport
*/
int
-smtp_connect(host_item *host, int host_af, int port, uschar *interface,
+smtp_connect(host_item *host, int host_af, uschar *interface,
int timeout, transport_instance * tb)
{
+int port = host->port;
#ifdef SUPPORT_SOCKS
smtp_transport_options_block * ob =
(smtp_transport_options_block *)tb->options_block;
#endif
-if (host->port != PORT_NONE)
- {
- HDEBUG(D_transport|D_acl|D_v)
- debug_printf_indent("Transport port=%d replaced by host-specific port=%d\n", port,
- host->port);
- port = host->port;
- }
-else host->port = port; /* Set the port actually used */
-
callout_address = string_sprintf("[%s]:%d", host->address, port);
HDEBUG(D_transport|D_acl|D_v)
Argument:
outblock the SMTP output block
- mode more-expected, or plain
+ mode further data expected, or plain
Returns: TRUE if OK, FALSE on error, with errno set
*/
{
int rc;
int n = outblock->ptr - outblock->buffer;
+BOOL more = mode == SCMD_MORE;
HDEBUG(D_transport|D_acl) debug_printf_indent("cmd buf flush %d bytes%s\n", n,
- mode == SCMD_MORE ? " (more expected)" : "");
+ more ? " (more expected)" : "");
#ifdef SUPPORT_TLS
if (tls_out.active == outblock->sock)
- rc = tls_write(FALSE, outblock->buffer, n);
+ rc = tls_write(FALSE, outblock->buffer, n, more);
else
#endif
rc = send(outblock->sock, outblock->buffer, n,
#ifdef MSG_MORE
- mode == SCMD_MORE ? MSG_MORE : 0
+ more ? MSG_MORE : 0
#else
0
#endif