higgs

httpd experiment
git clone git@git.2f30.org/higgs.git
Log | Files | Refs

commit 8826009e9807a15f96ede86b1355106f56e4155f
parent 6e62158577100f0e2f7715a75e30e5a38b66284e
Author: FRIGN <dev@frign.de>
Date:   Sat,  5 Dec 2015 23:08:16 +0100

Remove readline() and rather use fdopen+getline()

Drops a lot of LOC and boilerplate, even though readline() worked just
fine.
However, I was feeling bad about the 1-byte-reads, which are obviously
better handled in the libc-implementations.

Diffstat:
Mconfig.h | 7++++---
Mhiggs.c | 67+++++++++++++++----------------------------------------------------
2 files changed, 19 insertions(+), 55 deletions(-)

diff --git a/config.h b/config.h @@ -1,5 +1,6 @@ /* higgs settings */ static const char *servername = "127.0.0.1"; -static const char *serverport = "8081"; -static const int maxnprocs = 512; -static const int timeout = 2000; /* in ms */ +static const char *serverport = "8080"; + +static const int maxnprocs = 512; +static const struct timeval timeout = { 30, 0 }; diff --git a/higgs.c b/higgs.c @@ -16,64 +16,16 @@ #include "config.h" -int -readline(char **buf, size_t *buflen, int fd) -{ - /* todo: properly return I/O and internal errors differently, so it's - * possible to give a 500-error when we have a malloc-problem - * but a timeout error when the user timed out */ - struct pollfd pollit = { .fd = fd, .events = POLLIN | POLLPRI }; - size_t off = 0; - int ret; - char c; - - if (!*buf) { - if (!(*buf = malloc(BUFSIZ))) - return -1; - *buflen = BUFSIZ; - } -again: - switch (ret = poll(&pollit, 1, timeout)) { - case 0: /* timeout */ - return -1; - case -1: /* error */ - return -1; - default: /* state change */ - if (!(pollit.revents & (POLLIN | POLLPRI))) - return -1; - - while (read(fd, &c, 1) == 1) { - if (c == '\n') - goto end; - if (c == '\r') - continue; - (*buf)[off] = c; - off++; - if (off >= *buflen) { - if (!(*buf = realloc(*buf, *buflen + BUFSIZ))) - return -1; - *buflen += BUFSIZ; - } - } - - if (errno == EAGAIN || errno == EWOULDBLOCK) - goto again; - return -1; - } -end: - (*buf)[off] = '\0'; - return off; -} - void handle(int fd) { + FILE *fp; size_t buflen = 0; char *buf = NULL, *p, *url; readline: /* check "METHOD URL HTTP-VERSION" */ - if (readline(&buf, &buflen, fd) < 0) + if (!(fp = fdopen(fd, "r")) || getline(&buf, &buflen, fp) < 0) goto servererr; if (strncmp(buf, "GET ", 4)) goto clienterr; @@ -84,7 +36,10 @@ readline: if (strncmp(p + 1, "HTTP/", 5)) goto clienterr; - printf("200 |%s|\n", url); + /* read other headers and pick those we care about */ + while (getline(&buf, &buflen, fp) >= 0 && strcmp(buf, "\r\n")) { + printf("%s", buf); + } return; servererr: /* 500 internal server error */ @@ -102,7 +57,6 @@ main() struct addrinfo hints, *ai = NULL; struct rlimit rlim; struct sockaddr sa; - struct timeval tv; pid_t pid; socklen_t salen; int i, listenfd, reqfd, running = 1; @@ -156,7 +110,16 @@ main() continue; } else if (pid == 0) { close(listenfd); + + /* close socket after timeout */ + if (setsockopt(reqfd, SOL_SOCKET, SO_RCVTIMEO, + &timeout, sizeof(timeout)) < 0) { + fprintf(stderr, "error\tsetsockopt SO_RCVTIMEO" + "failed: %s\n", strerror(errno)); + } + handle(reqfd); + shutdown(reqfd, SHUT_RD); shutdown(reqfd, SHUT_WR); close(reqfd);