+/* When doing RFC3030 CHUNKING output, work out how much data will be in the
+last BDAT, consisting of the current write_chunk() output buffer fill
+(optimally, all of the headers - but it does not matter if we already had to
+flush that buffer with non-last BDAT prependix) plus the amount of body data
+(as expanded for CRLF lines). Then create and write the BDAT, and ensure
+that further use of write_chunk() will not prepend BDATs.
+The first BDAT written will also first flush any outstanding MAIL and RCPT
+commands which were buffered thans to PIPELINING.
+Commands go out (using a send()) from a different buffer to data (using a
+write()). They might not end up in the same TCP segment, which is
+suboptimal. */
+
+if (tctx->options & topt_use_bdat)
+ {
+ off_t fsize;
+ int hsize, size;
+
+ if ((hsize = chunk_ptr - deliver_out_buffer) < 0)
+ hsize = 0;
+ if (!(tctx->options & topt_no_body))
+ {
+ if ((fsize = lseek(deliver_datafile, 0, SEEK_END)) < 0) return FALSE;
+ fsize -= SPOOL_DATA_START_OFFSET;
+ if (size_limit > 0 && fsize > size_limit)
+ fsize = size_limit;
+ size = hsize + fsize;
+ if (tctx->options & topt_use_crlf)
+ size += body_linecount; /* account for CRLF-expansion */
+ }
+
+ /* If the message is large, emit first a non-LAST chunk with just the
+ headers, and reap the command responses. This lets us error out early
+ on RCPT rejects rather than sending megabytes of data. Include headers
+ on the assumption they are cheap enough and some clever implementations
+ might errorcheck them too, on-the-fly, and reject that chunk. */
+
+ if (size > DELIVER_OUT_BUFFER_SIZE && hsize > 0)
+ {
+ if ( tctx->chunk_cb(fd, tctx, hsize, 0) != OK
+ || !transport_write_block(fd, deliver_out_buffer, hsize)
+ || tctx->chunk_cb(fd, tctx, 0, tc_reap_prev) != OK
+ )
+ return FALSE;
+ chunk_ptr = deliver_out_buffer;
+ size -= hsize;
+ }
+
+ /* Emit a LAST datachunk command. */
+
+ if (tctx->chunk_cb(fd, tctx, size, tc_chunk_last) != OK)
+ return FALSE;
+
+ tctx->options &= ~topt_use_bdat;
+ }
+