# HG changeset patch # User Adam Chlipala # Date 1388500481 18000 # Node ID d7bec4e63415d0544701cd46e52553d487dc4e4c # Parent 6b80900ddc668c94818e2ef187d7b6027925dbdb Do a bit of extra userspace copying to send HTTP response with a single system call diff -r 6b80900ddc66 -r d7bec4e63415 src/c/urweb.c --- a/src/c/urweb.c Mon Dec 30 11:01:42 2013 -0500 +++ b/src/c/urweb.c Tue Dec 31 09:34:41 2013 -0500 @@ -474,6 +474,9 @@ char error_message[ERROR_BUF_LEN]; int usedSig, needsResig; + + char *output_buffer; + size_t output_buffer_size; }; size_t uw_headers_max = SIZE_MAX; @@ -554,6 +557,9 @@ ctx->usedSig = 0; ctx->needsResig = 0; + ctx->output_buffer = malloc(1); + ctx->output_buffer_size = 1; + return ctx; } @@ -612,6 +618,8 @@ ctx->globals[i].free(ctx->globals[i].data); free(ctx->globals); + free(ctx->output_buffer); + free(ctx); } @@ -1297,17 +1305,20 @@ } int uw_send(uw_context ctx, int sock) { - int n = uw_really_send(sock, ctx->outHeaders.start, ctx->outHeaders.front - ctx->outHeaders.start); - - if (n < 0) - return n; - - n = uw_really_send(sock, "\r\n", 2); - - if (n < 0) - return n; - - return uw_really_send(sock, ctx->page.start, ctx->page.front - ctx->page.start); + size_t target_length = (ctx->outHeaders.front - ctx->outHeaders.start) + 2 + (ctx->page.front - ctx->page.start); + + if (ctx->output_buffer_size < target_length) { + do { + ctx->output_buffer_size *= 2; + } while (ctx->output_buffer_size < target_length); + ctx->output_buffer = realloc(ctx->output_buffer, ctx->output_buffer_size); + } + + memcpy(ctx->output_buffer, ctx->outHeaders.start, ctx->outHeaders.front - ctx->outHeaders.start); + memcpy(ctx->output_buffer + (ctx->outHeaders.front - ctx->outHeaders.start), "\r\n", 2); + memcpy(ctx->output_buffer + (ctx->outHeaders.front - ctx->outHeaders.start) + 2, ctx->page.start, ctx->page.front - ctx->page.start); + + return uw_really_send(sock, ctx->output_buffer, target_length); } int uw_print(uw_context ctx, int fd) {