changeset 1949:d7bec4e63415

Do a bit of extra userspace copying to send HTTP response with a single system call
author Adam Chlipala <adam@chlipala.net>
date Tue, 31 Dec 2013 09:34:41 -0500
parents 6b80900ddc66
children b3c8860508ea
files src/c/urweb.c
diffstat 1 files changed, 22 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- 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) {