Move infd and header into request-struct - quark - quark web server
git clone git://git.suckless.org/quark
Log
Files
Refs
LICENSE
---
commit 6d2fe7f29e12190d9be062852cf3f21b7f695369
parent ce77dd79624177387dbfc95cabae7c851b51b7fb
Author: Laslo Hunhold 
Date:   Fri, 21 Aug 2020 19:38:29 +0200

Move infd and header into request-struct

This compacts the connection state into one struct.

Signed-off-by: Laslo Hunhold 

Diffstat:
  M http.c                              |      86 +++++++++++++++---------------
  M http.h                              |       6 ++++--
  M main.c                              |       6 ++++--

3 files changed, 51 insertions(+), 47 deletions(-)
---
diff --git a/http.c b/http.c
@@ -144,12 +144,12 @@ decode(const char src[PATH_MAX], char dest[PATH_MAX])
 }
 
 int
-http_get_request(int fd, struct request *req)
+http_get_request(struct request *req)
 {
         struct in6_addr addr;
         size_t hlen, i, mlen;
         ssize_t off;
-        char h[HEADER_MAX], *p, *q;
+        char *h = req->header, *p, *q;
 
         /* empty all fields */
         memset(req, 0, sizeof(*req));
@@ -158,8 +158,8 @@ http_get_request(int fd, struct request *req)
          * receive header
          */
         for (hlen = 0; ;) {
-                if ((off = read(fd, h + hlen, sizeof(h) - hlen)) < 0) {
-                        return http_send_status(fd, S_REQUEST_TIMEOUT);
+                if ((off = read(req->fd, h + hlen, sizeof(h) - hlen)) < 0) {
+                        return http_send_status(req->fd, S_REQUEST_TIMEOUT);
                 } else if (off == 0) {
                         break;
                 }
@@ -168,13 +168,13 @@ http_get_request(int fd, struct request *req)
                         break;
                 }
                 if (hlen == sizeof(h)) {
-                        return http_send_status(fd, S_REQUEST_TOO_LARGE);
+                        return http_send_status(req->fd, S_REQUEST_TOO_LARGE);
                 }
         }
 
         /* remove terminating empty line */
         if (hlen < 2) {
-                return http_send_status(fd, S_BAD_REQUEST);
+                return http_send_status(req->fd, S_BAD_REQUEST);
         }
         hlen -= 2;
 
@@ -194,12 +194,12 @@ http_get_request(int fd, struct request *req)
                 }
         }
         if (i == NUM_REQ_METHODS) {
-                return http_send_status(fd, S_METHOD_NOT_ALLOWED);
+                return http_send_status(req->fd, S_METHOD_NOT_ALLOWED);
         }
 
         /* a single space must follow the method */
         if (h[mlen] != ' ') {
-                return http_send_status(fd, S_BAD_REQUEST);
+                return http_send_status(req->fd, S_BAD_REQUEST);
         }
 
         /* basis for next step */
@@ -207,11 +207,11 @@ http_get_request(int fd, struct request *req)
 
         /* TARGET */
         if (!(q = strchr(p, ' '))) {
-                return http_send_status(fd, S_BAD_REQUEST);
+                return http_send_status(req->fd, S_BAD_REQUEST);
         }
         *q = '\0';
         if (q - p + 1 > PATH_MAX) {
-                return http_send_status(fd, S_REQUEST_TOO_LARGE);
+                return http_send_status(req->fd, S_REQUEST_TOO_LARGE);
         }
         memcpy(req->target, p, q - p + 1);
         decode(req->target, req->target);
@@ -221,18 +221,18 @@ http_get_request(int fd, struct request *req)
 
         /* HTTP-VERSION */
         if (strncmp(p, "HTTP/", sizeof("HTTP/") - 1)) {
-                return http_send_status(fd, S_BAD_REQUEST);
+                return http_send_status(req->fd, S_BAD_REQUEST);
         }
         p += sizeof("HTTP/") - 1;
         if (strncmp(p, "1.0", sizeof("1.0") - 1) &&
             strncmp(p, "1.1", sizeof("1.1") - 1)) {
-                return http_send_status(fd, S_VERSION_NOT_SUPPORTED);
+                return http_send_status(req->fd, S_VERSION_NOT_SUPPORTED);
         }
         p += sizeof("1.*") - 1;
 
         /* check terminator */
         if (strncmp(p, "\r\n", sizeof("\r\n") - 1)) {
-                return http_send_status(fd, S_BAD_REQUEST);
+                return http_send_status(req->fd, S_BAD_REQUEST);
         }
 
         /* basis for next step */
@@ -253,7 +253,7 @@ http_get_request(int fd, struct request *req)
                 if (i == NUM_REQ_FIELDS) {
                         /* unmatched field, skip this line */
                         if (!(q = strstr(p, "\r\n"))) {
-                                return http_send_status(fd, S_BAD_REQUEST);
+                                return http_send_status(req->fd, S_BAD_REQUEST);
                         }
                         p = q + (sizeof("\r\n") - 1);
                         continue;
@@ -263,7 +263,7 @@ http_get_request(int fd, struct request *req)
 
                 /* a single colon must follow the field name */
                 if (*p != ':') {
-                        return http_send_status(fd, S_BAD_REQUEST);
+                        return http_send_status(req->fd, S_BAD_REQUEST);
                 }
 
                 /* skip whitespace */
@@ -272,11 +272,11 @@ http_get_request(int fd, struct request *req)
 
                 /* extract field content */
                 if (!(q = strstr(p, "\r\n"))) {
-                        return http_send_status(fd, S_BAD_REQUEST);
+                        return http_send_status(req->fd, S_BAD_REQUEST);
                 }
                 *q = '\0';
                 if (q - p + 1 > FIELD_MAX) {
-                        return http_send_status(fd, S_REQUEST_TOO_LARGE);
+                        return http_send_status(req->fd, S_REQUEST_TOO_LARGE);
                 }
                 memcpy(req->field[i], p, q - p + 1);
 
@@ -296,7 +296,7 @@ http_get_request(int fd, struct request *req)
         if (p && (!q || p > q)) {
                 /* port suffix must not be empty */
                 if (*(p + 1) == '\0') {
-                        return http_send_status(fd, S_BAD_REQUEST);
+                        return http_send_status(req->fd, S_BAD_REQUEST);
                 }
                 *p = '\0';
         }
@@ -305,7 +305,7 @@ http_get_request(int fd, struct request *req)
         if (q) {
                 /* brackets must be on the outside */
                 if (req->field[REQ_HOST][0] != '[' || *(q + 1) != '\0') {
-                        return http_send_status(fd, S_BAD_REQUEST);
+                        return http_send_status(req->fd, S_BAD_REQUEST);
                 }
 
                 /* remove the right bracket */
@@ -314,7 +314,7 @@ http_get_request(int fd, struct request *req)
 
                 /* validate the contained IPv6 address */
                 if (inet_pton(AF_INET6, p, &addr) != 1) {
-                        return http_send_status(fd, S_BAD_REQUEST);
+                        return http_send_status(req->fd, S_BAD_REQUEST);
                 }
 
                 /* copy it into the host field */
@@ -528,7 +528,7 @@ parse_range(const char *str, size_t size, size_t *lower, size_t *upper)
 #define RELPATH(x) ((!*(x) || !strcmp(x, "/")) ? "." : ((x) + 1))
 
 enum status
-http_send_response(int fd, const struct request *req, const struct server *s)
+http_send_response(const struct request *req, const struct server *s)
 {
         enum status returnstatus;
         struct in6_addr addr;
@@ -553,7 +553,7 @@ http_send_response(int fd, const struct request *req, const struct server *s)
                         if (!regexec(&(s->vhost[i].re), req->field[REQ_HOST], 0,
                                      NULL, 0)) {
                                 if (chdir(s->vhost[i].dir) < 0) {
-                                        return http_send_status(fd, (errno == EACCES) ?
+                                        return http_send_status(req->fd, (errno == EACCES) ?
                                                                 S_FORBIDDEN : S_NOT_FOUND);
                                 }
                                 vhostmatch = s->vhost[i].chost;
@@ -561,14 +561,14 @@ http_send_response(int fd, const struct request *req, const struct server *s)
                         }
                 }
                 if (i == s->vhost_len) {
-                        return http_send_status(fd, S_NOT_FOUND);
+                        return http_send_status(req->fd, S_NOT_FOUND);
                 }
 
                 /* if we have a vhost prefix, prepend it to the target */
                 if (s->vhost[i].prefix) {
                         if (esnprintf(tmptarget, sizeof(tmptarget), "%s%s",
                                       s->vhost[i].prefix, realtarget)) {
-                                return http_send_status(fd, S_REQUEST_TOO_LARGE);
+                                return http_send_status(req->fd, S_REQUEST_TOO_LARGE);
                         }
                         memcpy(realtarget, tmptarget, sizeof(realtarget));
                 }
@@ -588,7 +588,7 @@ http_send_response(int fd, const struct request *req, const struct server *s)
                         /* swap out target prefix */
                         if (esnprintf(tmptarget, sizeof(tmptarget), "%s%s",
                                       s->map[i].to, realtarget + len)) {
-                                return http_send_status(fd, S_REQUEST_TOO_LARGE);
+                                return http_send_status(req->fd, S_REQUEST_TOO_LARGE);
                         }
                         memcpy(realtarget, tmptarget, sizeof(realtarget));
                         break;
@@ -597,12 +597,12 @@ http_send_response(int fd, const struct request *req, const struct server *s)
 
         /* normalize target */
         if (normabspath(realtarget)) {
-                return http_send_status(fd, S_BAD_REQUEST);
+                return http_send_status(req->fd, S_BAD_REQUEST);
         }
 
         /* stat the target */
         if (stat(RELPATH(realtarget), &st) < 0) {
-                return http_send_status(fd, (errno == EACCES) ?
+                return http_send_status(req->fd, (errno == EACCES) ?
                                         S_FORBIDDEN : S_NOT_FOUND);
         }
 
@@ -610,7 +610,7 @@ http_send_response(int fd, const struct request *req, const struct server *s)
                 /* add / to target if not present */
                 len = strlen(realtarget);
                 if (len >= PATH_MAX - 2) {
-                        return http_send_status(fd, S_REQUEST_TOO_LARGE);
+                        return http_send_status(req->fd, S_REQUEST_TOO_LARGE);
                 }
                 if (len && realtarget[len - 1] != '/') {
                         realtarget[len] = '/';
@@ -624,7 +624,7 @@ http_send_response(int fd, const struct request *req, const struct server *s)
          */
         if (strstr(realtarget, "/.") && strncmp(realtarget,
             "/.well-known/", sizeof("/.well-known/") - 1)) {
-                return http_send_status(fd, S_FORBIDDEN);
+                return http_send_status(req->fd, S_FORBIDDEN);
         }
 
         /* redirect if targets differ, host is non-canonical or we prefixed */
@@ -650,7 +650,7 @@ http_send_response(int fd, const struct request *req, const struct server *s)
                          * honor that later when we fill the "Location"-field */
                         if ((ipv6host = inet_pton(AF_INET6, targethost,
                                                   &addr)) < 0) {
-                                return http_send_status(fd,
+                                return http_send_status(req->fd,
                                                         S_INTERNAL_SERVER_ERROR);
                         }
 
@@ -662,25 +662,25 @@ http_send_response(int fd, const struct request *req, const struct server *s)
                                       targethost,
                                       ipv6host ? "]" : "", hasport ? ":" : "",
                                       hasport ? s->port : "", tmptarget)) {
-                                return http_send_status(fd, S_REQUEST_TOO_LARGE);
+                                return http_send_status(req->fd, S_REQUEST_TOO_LARGE);
                         }
                 } else {
                         /* write relative redirection URL to response struct */
                         if (esnprintf(res.field[RES_LOCATION],
                                       sizeof(res.field[RES_LOCATION]),
                                       tmptarget)) {
-                                return http_send_status(fd, S_REQUEST_TOO_LARGE);
+                                return http_send_status(req->fd, S_REQUEST_TOO_LARGE);
                         }
                 }
 
-                return http_send_header(fd, &res);
+                return http_send_header(req->fd, &res);
         }
 
         if (S_ISDIR(st.st_mode)) {
                 /* append docindex to target */
                 if (esnprintf(realtarget, sizeof(realtarget), "%s%s",
                               req->target, s->docindex)) {
-                        return http_send_status(fd, S_REQUEST_TOO_LARGE);
+                        return http_send_status(req->fd, S_REQUEST_TOO_LARGE);
                 }
 
                 /* stat the docindex, which must be a regular file */
@@ -689,13 +689,13 @@ http_send_response(int fd, const struct request *req, const struct server *s)
                                 /* remove index suffix and serve dir */
                                 realtarget[strlen(realtarget) -
                                            strlen(s->docindex)] = '\0';
-                                return resp_dir(fd, RELPATH(realtarget), req);
+                                return resp_dir(req->fd, RELPATH(realtarget), req);
                         } else {
                                 /* reject */
                                 if (!S_ISREG(st.st_mode) || errno == EACCES) {
-                                        return http_send_status(fd, S_FORBIDDEN);
+                                        return http_send_status(req->fd, S_FORBIDDEN);
                                 } else {
-                                        return http_send_status(fd, S_NOT_FOUND);
+                                        return http_send_status(req->fd, S_NOT_FOUND);
                                 }
                         }
                 }
@@ -706,13 +706,13 @@ http_send_response(int fd, const struct request *req, const struct server *s)
                 /* parse field */
                 if (!strptime(req->field[REQ_IF_MODIFIED_SINCE],
                               "%a, %d %b %Y %T GMT", &tm)) {
-                        return http_send_status(fd, S_BAD_REQUEST);
+                        return http_send_status(req->fd, S_BAD_REQUEST);
                 }
 
                 /* compare with last modification date of the file */
                 if (difftime(st.st_mtim.tv_sec, timegm(&tm)) <= 0) {
                         res.status = S_NOT_MODIFIED;
-                        return http_send_header(fd, &res);
+                        return http_send_header(req->fd, &res);
                 }
         }
 
@@ -725,13 +725,13 @@ http_send_response(int fd, const struct request *req, const struct server *s)
                         if (esnprintf(res.field[RES_CONTENT_RANGE],
                                       sizeof(res.field[RES_CONTENT_RANGE]),
                                       "bytes */%zu", st.st_size)) {
-                                return http_send_status(fd,
+                                return http_send_status(req->fd,
                                                         S_INTERNAL_SERVER_ERROR);
                         }
 
-                        return http_send_header(fd, &res);
+                        return http_send_header(req->fd, &res);
                 } else {
-                        return http_send_status(fd, returnstatus);
+                        return http_send_status(req->fd, returnstatus);
                 }
         }
 
@@ -746,5 +746,5 @@ http_send_response(int fd, const struct request *req, const struct server *s)
                 }
         }
 
-        return resp_file(fd, RELPATH(realtarget), req, &st, mime, lower, upper);
+        return resp_file(req->fd, RELPATH(realtarget), req, &st, mime, lower, upper);
 }
diff --git a/http.h b/http.h
@@ -27,6 +27,8 @@ enum req_method {
 extern const char *req_method_str[];
 
 struct request {
+        int fd;
+        char header[HEADER_MAX];
         enum req_method method;
         char target[PATH_MAX];
         char field[NUM_REQ_FIELDS][FIELD_MAX];
@@ -70,8 +72,8 @@ struct response {
 
 enum status http_send_header(int, const struct response *);
 enum status http_send_status(int, enum status);
-int http_get_request(int, struct request *);
-enum status http_send_response(int, const struct request *,
+int http_get_request(struct request *);
+enum status http_send_response(const struct request *,
                                const struct server *);
 
 #endif /* HTTP_H */
diff --git a/main.c b/main.c
@@ -37,8 +37,10 @@ serve(int infd, const struct sockaddr_storage *in_sa, const struct server *s)
         }
 
         /* handle request */
-        if (!(status = http_get_request(infd, &req))) {
-                status = http_send_response(infd, &req, s);
+        req.fd = infd;
+
+        if (!(status = http_get_request(&req))) {
+                status = http_send_response(&req, s);
         }
 
         /* write output to log */