--- http.c | 21 +++++++++++++++++++-- http.h | 9 +++++++++ main.c | 23 +++++++++++++++++++++-- 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/http.c b/http.c index f1e15a4..5b8848e 100644 --- a/http.c +++ b/http.c _AT_@ -17,6 +17,7 @@ #include <unistd.h> #include "config.h" +#include "data.h" #include "http.h" #include "util.h" _AT_@ -57,6 +58,11 @@ const char *res_field_str[] = { [RES_CONTENT_TYPE] = "Content-Type", }; +const char *lifetime_str[] = { + [LT_CLOSE] = "close", + [LT_KEEP_ALIVE] = "keep-alive", +}; + enum status http_prepare_header_buf(const struct response *res, struct buffer *buf) { _AT_@ -75,8 +81,9 @@ http_prepare_header_buf(const struct response *res, struct buffer *buf) if (buffer_appendf(buf, "HTTP/1.1 %d %s\r\n" "Date: %s\r\n" - "Connection: close\r\n", - res->status, status_str[res->status], tstmp)) { + "Connection: %s\r\n", + res->status, status_str[res->status], tstmp, + lifetime_str[res->lifetime])) { goto err; } _AT_@ -839,6 +846,9 @@ void http_prepare_error_response(const struct request *req, struct response *res, enum status s) { + struct buffer buf; + size_t progress; + /* used later */ (void)req; _AT_@ -861,4 +871,11 @@ http_prepare_error_response(const struct request *req, res->status = S_INTERNAL_SERVER_ERROR; } } + + if (data_prepare_error_buf(res, &buf, &progress) + || esnprintf(res->field[RES_CONTENT_LENGTH], + sizeof(res->field[RES_CONTENT_LENGTH]), + "%zu", buf.len)) { + s = S_INTERNAL_SERVER_ERROR; + } } diff --git a/http.h b/http.h index bfaa807..0e2367b 100644 --- a/http.h +++ b/http.h _AT_@ -69,9 +69,17 @@ enum res_type { NUM_RES_TYPES, }; +enum lifetime { + LT_CLOSE, + LT_KEEP_ALIVE, +}; + +extern const char *lifetime_str[]; + struct response { enum res_type type; enum status status; + enum lifetime lifetime; char field[NUM_RES_FIELDS][FIELD_MAX]; char uri[PATH_MAX]; char path[PATH_MAX]; _AT_@ -83,6 +91,7 @@ struct response { enum conn_state { C_VACANT, + C_START, C_RECV_HEADER, C_SEND_HEADER, C_SEND_BODY, diff --git a/main.c b/main.c index d64774b..8917138 100644 --- a/main.c +++ b/main.c _AT_@ -60,9 +60,14 @@ serve(struct connection *c, const struct server *srv) switch (c->state) { case C_VACANT: + /* we were passed a "fresh" connection, reset all state */ + + c->state = C_START; + /* fallthrough */ + case C_START: /* - * we were passed a "fresh" connection which should now - * try to receive the header, reset buf beforehand + * we start handling a request, so we first must try to + * receive the header, reset buf beforehand */ memset(&c->buf, 0, sizeof(c->buf)); _AT_@ -146,6 +151,20 @@ response: err: logmsg(c); + /* don't cleanup if we keep the connection alive */ + if (c->res.lifetime == LT_KEEP_ALIVE) { + /* + * if the length is unspecified, a keep-alive connection will + * wait timeout: kill the connection to avoid it + */ + if (c->res.field[RES_CONTENT_LENGTH][0] == '\0') { + c->res.status = S_INTERNAL_SERVER_ERROR; + } else { + c->state = C_START; + return; + } + } + /* clean up and finish */ shutdown(c->fd, SHUT_RD); shutdown(c->fd, SHUT_WR); -- 2.29.0Received on Thu Oct 29 2020 - 11:16:36 CET
This archive was generated by hypermail 2.3.0 : Thu Oct 29 2020 - 11:36:32 CET