ostream-crlf.c revision e8eb96edcfe8cff7839f1258ab6e871e41a4785e
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2004 Timo Sirainen */
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen/* The code is quite ugly because we want the send functions to return correcly
df8046c9a4f6bc2a478ad1e74504d50f3110c906Timo Sirainen the number of input bytes consumed, not number of bytes actually sent. */
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainenstatic const struct const_iovec cr_iov = { "\r", 1 };
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainenstatic void _close(struct _iostream *stream __attr_unused__)
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen struct crlf_ostream *cstream = (struct crlf_ostream *)stream;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainenstatic void _set_max_buffer_size(struct _iostream *stream, size_t max_size)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen struct crlf_ostream *cstream = (struct crlf_ostream *)stream;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen o_stream_set_max_buffer_size(cstream->output, max_size);
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainenstatic void _cork(struct _ostream *stream, bool set)
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen struct crlf_ostream *cstream = (struct crlf_ostream *)stream;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen struct crlf_ostream *cstream = (struct crlf_ostream *)stream;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainenstatic void _flush_pending(struct _ostream *stream, bool set)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen struct crlf_ostream *cstream = (struct crlf_ostream *)stream;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen o_stream_set_flush_pending(cstream->output, set);
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainenstatic size_t _get_used_size(struct _ostream *stream)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen struct crlf_ostream *cstream = (struct crlf_ostream *)stream;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen return o_stream_get_buffer_used_size(cstream->output);
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainenstatic int _seek(struct _ostream *stream, uoff_t offset)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen struct crlf_ostream *cstream = (struct crlf_ostream *)stream;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen stream->ostream.offset = cstream->output->offset;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainensendv_crlf(struct crlf_ostream *cstream, const struct const_iovec *iov,
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen size_t iov_count, const char *diff, ssize_t *total_r)
92f9871ac981201fe0a47f6c909f790cce14b240Timo Sirainen ret = o_stream_sendv(cstream->output, iov, iov_count);
92f9871ac981201fe0a47f6c909f790cce14b240Timo Sirainen for (i = 0; i < iov_count && pos >= iov[i].iov_len; i++) {
92f9871ac981201fe0a47f6c909f790cce14b240Timo Sirainen *((const char *)iov[i].iov_base + pos) == '\r';
92f9871ac981201fe0a47f6c909f790cce14b240Timo Sirainen cstream->ostream.ostream.offset = cstream->output->offset;
92f9871ac981201fe0a47f6c909f790cce14b240Timo Sirainen_sendv_crlf(struct _ostream *stream, const struct const_iovec *iov,
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen struct crlf_ostream *cstream = (struct crlf_ostream *)stream;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen const unsigned char *data;
cc23ad7b8ab96d93d5ab5139c431fcdd8d9e1d72Timo Sirainen unsigned int vec, i, len, start, new_iov_count = 0, new_iov_size = 0;
1c0020171b04d14adc4966ed963361abc9a86787Timo Sirainen iov_buf = buffer_create_dynamic(unsafe_data_stack_pool,
1c0020171b04d14adc4966ed963361abc9a86787Timo Sirainen sizeof(struct const_iovec *) *
1c0020171b04d14adc4966ed963361abc9a86787Timo Sirainen diff_buf = buffer_create_dynamic(unsafe_data_stack_pool, IOVBUF_COUNT);
df8046c9a4f6bc2a478ad1e74504d50f3110c906Timo Sirainen for (i = start = 0;; i++) {
df8046c9a4f6bc2a478ad1e74504d50f3110c906Timo Sirainen /* need to insert CR */
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen buffer_append(iov_buf, &cr_iov, sizeof(cr_iov));
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen ret = sendv_crlf(cstream, iov_buf->data, new_iov_count,
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainensendv_lf(struct crlf_ostream *cstream, const struct const_iovec *iov,
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen size_t iov_count, const char *diff, ssize_t *total_r)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen ret = o_stream_sendv(cstream->output, iov, iov_count);
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen for (i = 0; i < iov_count && left >= iov[i].iov_len; i++) {
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen cstream->ostream.ostream.stream_errno = cstream->output->stream_errno;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen cstream->ostream.ostream.offset = cstream->output->offset;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen_sendv_lf(struct _ostream *stream, const struct const_iovec *iov,
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen struct crlf_ostream *cstream = (struct crlf_ostream *)stream;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen const unsigned char *data;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen unsigned int new_iov_count = 0, new_iov_size = 0;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen iov_buf = buffer_create_dynamic(unsafe_data_stack_pool,
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen sizeof(struct const_iovec *) *
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen diff_buf = buffer_create_dynamic(unsafe_data_stack_pool, IOVBUF_COUNT);
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen for (i = start = 0;; i++) {
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen /* bare CR, keep it */
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen buffer_append(iov_buf, &cr_iov, sizeof(cr_iov));
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen /* skipping an CR */
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen /* data ends with CR, don't add it yet */
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen /* data doesn't end with CR */
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen buffer_append(iov_buf, &new_iov, sizeof(new_iov));
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen /* Tried to send only CR. */
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen ret = sendv_lf(cstream, iov_buf->data, new_iov_count,
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen stream->ostream.offset = cstream->output->offset;
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen_send_istream(struct _ostream *outstream, struct istream *instream)
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen const unsigned char *data;
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen while ((ret = i_stream_read_data(instream, &data,
fccd110b494a7e31f23d31d9e3bc3e986c9bb1a8Timo Sirainen ret = o_stream_sendv(&outstream->ostream, &iov, 1);
632018810af689442569cbb0139c55868923ccfeTimo Sirainen return ret < 0 && sent == 0 ? -1 : (ssize_t)sent;
632018810af689442569cbb0139c55868923ccfeTimo Sirainen return sent == 0 && instream->stream_errno != 0 ? -1 : (ssize_t)sent;
fccd110b494a7e31f23d31d9e3bc3e986c9bb1a8Timo Siraineno_stream_create_common(pool_t pool, struct ostream *output)
632018810af689442569cbb0139c55868923ccfeTimo Sirainen cstream = p_new(pool, struct crlf_ostream, 1);
632018810af689442569cbb0139c55868923ccfeTimo Sirainen cstream->ostream.iostream.set_max_buffer_size = _set_max_buffer_size;
632018810af689442569cbb0139c55868923ccfeTimo Sirainen cstream->ostream.flush_pending = _flush_pending;
632018810af689442569cbb0139c55868923ccfeTimo Sirainen cstream->ostream.get_used_size = _get_used_size;
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen cstream->ostream.send_istream = _send_istream;
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainenstruct ostream *o_stream_create_crlf(pool_t pool, struct ostream *output)
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen cstream = o_stream_create_common(pool, output);
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen return _o_stream_create(&cstream->ostream, pool);
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainenstruct ostream *o_stream_create_lf(pool_t pool, struct ostream *output)
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen cstream = o_stream_create_common(pool, output);