+#ifdef SUPPORT_TLS
+/*****************************************************
+* Proxy TLS connection for another transport process *
+******************************************************/
+/*
+Use the given buffer as a staging area, and select on both the given fd
+and the TLS'd client-fd for data to read (per the coding in ip_recv() and
+fd_ready() this is legitimate). Do blocking full-size writes, and reads
+under a timeout.
+
+Arguments:
+ buf space to use for buffering
+ bufsiz size of buffer
+ proxy_fd comms to proxied process
+ timeout per-read timeout, seconds
+*/
+
+void
+smtp_proxy_tls(uschar * buf, size_t bsize, int proxy_fd, int timeout)
+{
+fd_set fds;
+int max_fd = MAX(proxy_fd, tls_out.active) + 1;
+int rc, i, fd_bits, nbytes;
+
+set_process_info("proxying TLS connection for continued transport");
+FD_ZERO(&fds);
+FD_SET(tls_out.active, &fds);
+FD_SET(proxy_fd, &fds);
+
+for (fd_bits = 3; fd_bits; )
+ {
+ time_t time_left = timeout;
+ time_t time_start = time(NULL);
+
+ /* wait for data */
+ do
+ {
+ struct timeval tv = { time_left, 0 };
+
+ rc = select(max_fd, (SELECT_ARG2_TYPE *)&fds, NULL, NULL, &tv);
+
+ if (rc < 0 && errno == EINTR)
+ if ((time_left -= time(NULL) - time_start) > 0) continue;
+
+ if (rc <= 0)
+ {
+ DEBUG(D_transport) if (rc == 0) debug_printf("%s: timed out\n", __FUNCTION__);
+ return;
+ }
+ }
+ while (rc < 0 || !(FD_ISSET(tls_out.active, &fds) || FD_ISSET(proxy_fd, &fds)));
+
+ /* handle inbound data */
+ if (FD_ISSET(tls_out.active, &fds))
+ if ((rc = tls_read(FALSE, buf, bsize)) <= 0)
+ {
+ fd_bits &= ~1;
+ FD_CLR(tls_out.active, &fds);
+ shutdown(proxy_fd, SHUT_WR);
+ }
+ else
+ {
+ for (nbytes = 0; rc - nbytes > 0; nbytes += i)
+ if ((i = write(proxy_fd, buf + nbytes, rc - nbytes)) < 0) return;
+ }
+ else if (fd_bits & 1)
+ FD_SET(tls_out.active, &fds);
+
+ /* handle outbound data */
+ if (FD_ISSET(proxy_fd, &fds))
+ if ((rc = read(proxy_fd, buf, bsize)) <= 0)
+ {
+ fd_bits &= ~2;
+ FD_CLR(proxy_fd, &fds);
+ shutdown(tls_out.active, SHUT_WR);
+ }
+ else
+ {
+ for (nbytes = 0; rc - nbytes > 0; nbytes += i)
+ if ((i = tls_write(FALSE, buf + nbytes, rc - nbytes)) < 0) return;
+ }
+ else if (fd_bits & 2)
+ FD_SET(proxy_fd, &fds);
+ }
+}
+#endif
+
+