559
559
* XXX No need to do this before and after STARTTLS, but it's not a big deal
562
* XXX This critically depends on VSTREAM buffers to never be smaller than
562
* XXX When TLS is turned on, the SMTP-level writes will be encapsulated as
563
* TLS messages. Thus, the TCP-level payload will be larger than the
564
* SMTP-level payload. This has implications for the PIPELINING engine.
566
* To avoid deadlock, the PIPELINING engine needs to request a TCP send
567
* buffer size that can hold the unacknowledged commands plus the TLS
568
* encapsulation overhead.
570
* The PIPELINING engine keeps the unacknowledged command size <= the
571
* default VSTREAM buffer size (to avoid small-write performance issues
572
* when the VSTREAM buffer size is at its default size). With a default
573
* VSTREAM buffer size of 4096 there is no reason to increase the
574
* unacknowledged command size as the TCP MSS increases. It's safer to
575
* spread the remote SMTP server's recipient processing load over time,
576
* than dumping a very large recipient list all at once.
578
* For TLS encapsulation overhead we make a conservative guess: take the
579
* current protocol overhead of ~40 bytes, double the number for future
580
* proofing (~80 bytes), then round up the result to the nearest power of
581
* 2 (128 bytes). Plus, be prepared for worst-case compression that
582
* expands data by 1 kbyte, so that the worst-case SMTP payload per TLS
583
* message becomes 15 kbytes.
585
#define PIPELINING_BUFSIZE VSTREAM_BUFSIZE
587
#define TLS_WORST_PAYLOAD 16384
588
#define TLS_WORST_COMP_OVERHD 1024
589
#define TLS_WORST_PROTO_OVERHD 128
590
#define TLS_WORST_SMTP_PAYLOAD (TLS_WORST_PAYLOAD - TLS_WORST_COMP_OVERHD)
591
#define TLS_WORST_TOTAL_OVERHD (TLS_WORST_COMP_OVERHD + TLS_WORST_PROTO_OVERHD)
565
594
if (session->features & SMTP_FEATURE_PIPELINING) {
566
optlen = sizeof(sndbufsize);
597
int enc_overhead = 0;
599
optlen = sizeof(tcp_bufsize);
567
600
if (getsockopt(vstream_fileno(session->stream), SOL_SOCKET,
568
SO_SNDBUF, (char *) &sndbufsize, &optlen) < 0)
601
SO_SNDBUF, (char *) &tcp_bufsize, &optlen) < 0)
569
602
msg_fatal("%s: getsockopt: %m", myname);
570
if (sndbufsize > VSTREAM_BUFSIZE)
571
sndbufsize = VSTREAM_BUFSIZE;
572
if (sndbufsize < VSTREAM_BUFSIZE) {
573
sndbufsize = VSTREAM_BUFSIZE;
604
if (state->misc_flags & SMTP_MISC_FLAG_IN_STARTTLS)
606
(1 + (PIPELINING_BUFSIZE - 1)
607
/ TLS_WORST_SMTP_PAYLOAD) * TLS_WORST_TOTAL_OVERHD;
609
if (tcp_bufsize < PIPELINING_BUFSIZE + enc_overhead) {
610
tcp_bufsize = PIPELINING_BUFSIZE + enc_overhead;
574
611
if (setsockopt(vstream_fileno(session->stream), SOL_SOCKET,
575
SO_SNDBUF, (char *) &sndbufsize, optlen) < 0)
612
SO_SNDBUF, (char *) &tcp_bufsize, optlen) < 0)
576
613
msg_fatal("%s: setsockopt: %m", myname);
579
msg_info("Using %s PIPELINING, TCP send buffer size is %d",
581
SMTP_MISC_FLAG_USE_LMTP) ? "LMTP" : "ESMTP",
616
msg_info("Using %s PIPELINING, TCP send buffer size is %d, "
617
"PIPELINING buffer size is %d", (state->misc_flags &
618
SMTP_MISC_FLAG_USE_LMTP) ? "LMTP" : "ESMTP",
619
tcp_bufsize, PIPELINING_BUFSIZE);
1258
1300
vstring_strcat(next_command, " " XFORWARD_HELO "=");
1259
1301
xtext_quote_append(next_command, request->client_helo, "");
1303
if ((session->features & SMTP_FEATURE_XFORWARD_IDENT)
1304
&& CAN_FORWARD_IDENT_NAME(request->log_ident)) {
1305
vstring_strcat(next_command, " " XFORWARD_IDENT "=");
1306
xtext_quote_append(next_command, request->log_ident, "");
1261
1308
if ((session->features & SMTP_FEATURE_XFORWARD_DOMAIN)
1262
1309
&& CAN_FORWARD_RWR_CONTEXT(request->rewrite_context)) {
1263
1310
vstring_strcat(next_command, " " XFORWARD_DOMAIN "=");
1463
1510
* Flush unsent output if command pipelining is off or if no I/O
1464
1511
* happened for a while. This limits the accumulation of client-side
1465
1512
* delays in pipelined sessions.
1514
* The PIPELINING engine will flush the VSTREAM buffer if the sender
1515
* could otherwise produce more output than fits the PIPELINING
1516
* buffer. This generally works because we know exactly how much
1517
* output we produced since the last time that the sender and
1518
* receiver synchronized the SMTP state. However this logic is not
1519
* applicable after the sender enters the DATA phase, where it does
1520
* not synchronize with the receiver until the <CR><LF>.<CR><LF>.
1521
* Thus, the PIPELINING engine no longer knows how much data is
1522
* pending in the TCP send buffer. For this reason, if PIPELINING is
1523
* enabled, we always pipeline QUIT after <CR><LF>.<CR><LF>. This is
1524
* safe because once the receiver reads <CR><LF>.<CR><LF>, its TCP
1525
* stack either has already received the QUIT<CR><LF>, or else it
1526
* acknowledges all bytes up to and including <CR><LF>.<CR><LF>,
1527
* making room in the sender's TCP stack for QUIT<CR><LF>.
1529
#define CHECK_PIPELINING_BUFSIZE \
1530
(recv_state != SMTP_STATE_DOT || send_state != SMTP_STATE_QUIT)
1467
1532
if (SENDER_IN_WAIT_STATE
1468
1533
|| (SENDER_IS_AHEAD
1469
1534
&& ((session->features & SMTP_FEATURE_PIPELINING) == 0
1470
|| (VSTRING_LEN(next_command) + 2
1535
|| (CHECK_PIPELINING_BUFSIZE
1536
&& (VSTRING_LEN(next_command) + 2
1471
1537
+ vstream_bufstat(session->stream, VSTREAM_BST_OUT_PEND)
1538
> PIPELINING_BUFSIZE))
1473
1539
|| time((time_t *) 0)
1474
1540
- vstream_ftime(session->stream) > 10))) {
1475
1541
while (SENDER_IS_AHEAD) {