---
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.0
Received 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