summaryrefslogtreecommitdiff
path: root/src/c/http.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/c/http.c')
-rw-r--r--src/c/http.c135
1 files changed, 87 insertions, 48 deletions
diff --git a/src/c/http.c b/src/c/http.c
index f954a879..25d2a320 100644
--- a/src/c/http.c
+++ b/src/c/http.c
@@ -21,7 +21,7 @@
extern uw_app uw_application;
int uw_backlog = SOMAXCONN;
-static int keepalive = 0;
+static int keepalive = 0, quiet = 0;
static char *get_header(void *data, const char *h) {
char *s = data;
@@ -62,16 +62,18 @@ static void log_error(void *data, const char *fmt, ...) {
}
static void log_debug(void *data, const char *fmt, ...) {
- va_list ap;
- va_start(ap, fmt);
+ if (!quiet) {
+ va_list ap;
+ va_start(ap, fmt);
- vprintf(fmt, ap);
+ vprintf(fmt, ap);
+ }
}
static void *worker(void *data) {
int me = *(int *)data;
uw_context ctx = uw_request_new_context(me, &uw_application, NULL, log_error, log_debug);
- size_t buf_size = 2;
+ size_t buf_size = 1024;
char *buf = malloc(buf_size), *back = buf;
uw_request_context rc = uw_new_request_context();
int sock = 0;
@@ -82,7 +84,8 @@ static void *worker(void *data) {
sock = uw_dequeue();
}
- printf("Handling connection with thread #%d.\n", me);
+ if (!quiet)
+ printf("Handling connection with thread #%d.\n", me);
while (1) {
int r;
@@ -96,26 +99,32 @@ static void *worker(void *data) {
buf = new_buf;
}
- r = recv(sock, back, buf_size - 1 - (back - buf), 0);
+ *back = 0;
+ body = strstr(buf, "\r\n\r\n");
+ if (body == NULL) {
+ r = recv(sock, back, buf_size - 1 - (back - buf), 0);
- if (r < 0) {
- fprintf(stderr, "Recv failed\n");
- close(sock);
- sock = 0;
- break;
- }
+ if (r < 0) {
+ if (!quiet)
+ fprintf(stderr, "Recv failed\n");
+ close(sock);
+ sock = 0;
+ break;
+ }
- if (r == 0) {
- printf("Connection closed.\n");
- close(sock);
- sock = 0;
- break;
- }
+ if (r == 0) {
+ if (!quiet)
+ printf("Connection closed.\n");
+ close(sock);
+ sock = 0;
+ break;
+ }
- back += r;
- *back = 0;
+ back += r;
+ *back = 0;
+ }
- if ((body = strstr(buf, "\r\n\r\n"))) {
+ if (body != NULL || (body = strstr(buf, "\r\n\r\n"))) {
request_result rr;
int should_keepalive = 0;
@@ -148,14 +157,16 @@ static void *worker(void *data) {
r = recv(sock, back, buf_size - 1 - (back - buf), 0);
if (r < 0) {
- fprintf(stderr, "Recv failed\n");
+ if (!quiet)
+ fprintf(stderr, "Recv failed\n");
close(sock);
sock = 0;
goto done;
}
if (r == 0) {
- fprintf(stderr, "Connection closed.\n");
+ if (!quiet)
+ fprintf(stderr, "Connection closed.\n");
close(sock);
sock = 0;
goto done;
@@ -206,6 +217,11 @@ static void *worker(void *data) {
s = headers;
while ((s2 = strchr(s, '\r'))) {
+ if (s2 == s) {
+ *s = 0;
+ break;
+ }
+
s = s2;
if (s[1] == 0)
@@ -218,15 +234,14 @@ static void *worker(void *data) {
uw_set_headers(ctx, get_header, headers);
uw_set_env(ctx, get_env, NULL);
- printf("Serving URI %s....\n", path);
+ if (!quiet)
+ printf("Serving URI %s....\n", path);
rr = uw_request(rc, ctx, method, path, query_string, body, back - body,
on_success, on_failure,
NULL, log_error, log_debug,
sock, uw_really_send, close);
if (rr != KEEP_OPEN) {
- char clen[100];
-
if (keepalive) {
char *connection = uw_Basis_requestHeader(ctx, "Connection");
@@ -236,8 +251,13 @@ static void *worker(void *data) {
if (!should_keepalive)
uw_write_header(ctx, "Connection: close\r\n");
- sprintf(clen, "Content-length: %d\r\n", uw_pagelen(ctx));
- uw_write_header(ctx, clen);
+ if (!uw_has_contentLength(ctx)) {
+ char clen[100];
+
+ sprintf(clen, "Content-length: %d\r\n", uw_pagelen(ctx));
+ uw_write_header(ctx, clen);
+ }
+
uw_send(ctx, sock);
}
@@ -246,13 +266,25 @@ static void *worker(void *data) {
// In case any other requests are queued up, shift
// unprocessed part of buffer to front.
int kept = back - after;
- memmove(buf, after, kept);
- back = buf + kept;
+
+ if (kept == 0) {
+ // No pipelining going on here.
+ // We'd might as well try to switch to a different connection,
+ // while we wait for more input on this one.
+ uw_enqueue(sock);
+ sock = 0;
+ } else {
+ // More input! Move it to the front and continue in this loop.
+ memmove(buf, after, kept);
+ back = buf + kept;
+ }
} else {
close(sock);
sock = 0;
}
- } else if (rr != KEEP_OPEN)
+ } else if (rr == KEEP_OPEN)
+ sock = 0;
+ else
fprintf(stderr, "Illegal uw_request return code: %d\n", rr);
break;
@@ -267,7 +299,7 @@ static void *worker(void *data) {
}
static void help(char *cmd) {
- printf("Usage: %s [-p <port>] [-a <IP address>] [-t <thread count>] [-k]\nThe '-k' option turns on HTTP keepalive.\n", cmd);
+ printf("Usage: %s [-p <port>] [-a <IP address>] [-t <thread count>] [-k] [-q]\nThe '-k' option turns on HTTP keepalive.\nThe '-q' option turns off some chatter on stdout.\n", cmd);
}
static void sigint(int signum) {
@@ -291,10 +323,10 @@ int main(int argc, char *argv[]) {
my_addr.sin_addr.s_addr = INADDR_ANY; // auto-fill with my IP
memset(my_addr.sin_zero, '\0', sizeof my_addr.sin_zero);
- while ((opt = getopt(argc, argv, "hp:a:t:k")) != -1) {
+ while ((opt = getopt(argc, argv, "hp:a:t:kq")) != -1) {
switch (opt) {
case '?':
- fprintf(stderr, "Unknown command-line option");
+ fprintf(stderr, "Unknown command-line option\n");
help(argv[0]);
return 1;
@@ -332,6 +364,10 @@ int main(int argc, char *argv[]) {
keepalive = 1;
break;
+ case 'q':
+ quiet = 1;
+ break;
+
default:
fprintf(stderr, "Unexpected getopt() behavior\n");
return 1;
@@ -369,7 +405,8 @@ int main(int argc, char *argv[]) {
sin_size = sizeof their_addr;
- printf("Listening on port %d....\n", uw_port);
+ if (!quiet)
+ printf("Listening on port %d....\n", uw_port);
{
pthread_t thread;
@@ -393,18 +430,19 @@ int main(int argc, char *argv[]) {
int new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
if (new_fd < 0) {
- fprintf(stderr, "Socket accept failed\n");
- return 1;
- }
+ if (!quiet)
+ fprintf(stderr, "Socket accept failed\n");
+ } else {
+ if (!quiet)
+ printf("Accepted connection.\n");
- printf("Accepted connection.\n");
+ if (keepalive) {
+ int flag = 1;
+ setsockopt(new_fd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
+ }
- if (keepalive) {
- int flag = 1;
- setsockopt(new_fd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
+ uw_enqueue(new_fd);
}
-
- uw_enqueue(new_fd);
}
}
@@ -419,10 +457,11 @@ void uw_copy_client_data(void *dst, void *src) {
}
void uw_do_expunge(uw_context ctx, uw_Basis_client cli, void *data) {
- if (uw_get_app(ctx)->db_begin(ctx))
- uw_error(ctx, FATAL, "Error running SQL BEGIN");
+ uw_ensure_transaction(ctx);
uw_get_app(ctx)->expunger(ctx, cli);
- uw_commit(ctx);
+
+ if (uw_commit(ctx))
+ uw_error(ctx, UNLIMITED_RETRY, "Rerunning expunge transaction");
}
void uw_post_expunge(uw_context ctx, void *data) {