# HG changeset patch # User Timo Sirainen # Date 1031190906 -10800 # Node ID 2dcabe0fd1cb3d15d2794aaccce706e08e6c038b # Parent 9660df1ca44f751eff8028012c450b318b1692a6 io_buffer_send_iobuffer() was buggy with non-sendfile() method. diff -r 9660df1ca44f -r 2dcabe0fd1cb src/lib/iobuffer.c --- a/src/lib/iobuffer.c Wed Sep 04 19:17:11 2002 +0300 +++ b/src/lib/iobuffer.c Thu Sep 05 04:55:06 2002 +0300 @@ -272,6 +272,7 @@ IOBuffer *inbuf; int timeout; + int last_block; } IOBufferBlockContext; static void block_loop_send(IOBufferBlockContext *ctx) @@ -296,7 +297,7 @@ } } - if (ctx->outbuf->closed || ctx->size == 0) + if (ctx->outbuf->closed || (ctx->size == 0 && ctx->last_block)) io_loop_stop(ctx->ioloop); } @@ -363,6 +364,7 @@ ctx.data = data; ctx.size = size; + ctx.last_block = TRUE; return io_buffer_ioloop(buf, &ctx, block_loop_send); } @@ -538,7 +540,7 @@ static void block_loop_copy(IOBufferBlockContext *ctx) { unsigned char *in_data; - unsigned int size; + unsigned int size, full_size, sent_size, data_size; int ret; while ((ret = io_buffer_read_data(ctx->inbuf, &in_data, @@ -550,20 +552,26 @@ } } + full_size = ctx->size; + data_size = size < full_size ? size : full_size; + /* send the data */ + ctx->size = data_size; ctx->data = (const char *) in_data; - ctx->size = size; + ctx->last_block = data_size == full_size; block_loop_send(ctx); - io_buffer_skip(ctx->inbuf, size - ctx->size); + /* ctx->size now contains number of bytes unsent */ + sent_size = data_size - ctx->size; + ctx->size = full_size - sent_size; + + io_buffer_skip(ctx->inbuf, sent_size); } int io_buffer_send_iobuffer(IOBuffer *outbuf, IOBuffer *inbuf, unsigned int size) { IOBufferBlockContext ctx; - unsigned char *in_data; - unsigned int in_size; int ret; i_assert(size < INT_MAX); @@ -575,26 +583,6 @@ /* sendfile() not supported (with this fd), fallback to regular sending */ - /* see if we can do it at one go */ - ret = io_buffer_read_data(inbuf, &in_data, &in_size, 0); - if (ret == -1) - return -1; - - ret = !outbuf->file ? - net_transmit(outbuf->fd, in_data, in_size) : - my_write(outbuf->fd, in_data, in_size); - if (ret < 0) { - outbuf->buf_errno = errno; - return -1; - } - - outbuf->offset += ret; - io_buffer_skip(inbuf, (unsigned int)ret); - if ((unsigned int) ret == size) { - /* all sent */ - return 1; - } - /* create blocking send loop */ memset(&ctx, 0, sizeof(ctx));