Refactor http_send_buf() and http_recv_header() and simplify buffer - quark - q… | |
git clone git://git.suckless.org/quark | |
Log | |
Files | |
Refs | |
LICENSE | |
--- | |
commit e67eddd517d3f20a24ee14e1eab92806ce5bb20c | |
parent 1a93e3b22f363a0a8dffcf3c47b8d30ff207401f | |
Author: Laslo Hunhold <[email protected]> | |
Date: Wed, 16 Sep 2020 10:56:45 +0200 | |
Refactor http_send_buf() and http_recv_header() and simplify buffer | |
The use of "off" was problematic, because it is state that has to be | |
handled carefully and could potentially hit edge-cases (e.g. being | |
larger than sizeof(buf->data)). | |
The real problem is finding a way to indicate function is "done" with | |
something (i.e. done filling or sending the buffer). Instead of playing | |
around with off, which is nothing but a dirty hack, http_send_buf() now | |
just "drains" the buffer, which also makes it idempotent on an empty | |
buffer. It indicates to be "done" as soon as the length of the buffer is | |
zero. | |
The function http_recv_header() gets an additional paramter "done" | |
(an int-pointer) which is used to indicate completeness. | |
As a result, we can drop the off-variable completely from the buffer. | |
Signed-off-by: Laslo Hunhold <[email protected]> | |
Diffstat: | |
M http.c | 41 +++++++++++------------------… | |
M http.h | 2 +- | |
M util.h | 1 - | |
3 files changed, 15 insertions(+), 29 deletions(-) | |
--- | |
diff --git a/http.c b/http.c | |
@@ -101,25 +101,20 @@ err: | |
enum status | |
http_send_buf(int fd, struct buffer *buf) | |
{ | |
- size_t remaining; | |
ssize_t r; | |
- if (buf == NULL || buf->off > sizeof(buf->data)) { | |
+ if (buf == NULL) { | |
return S_INTERNAL_SERVER_ERROR; | |
} | |
- remaining = buf->len - buf->off; | |
- while (remaining > 0) { | |
- if ((r = write(fd, buf->data + buf->off, remaining)) <= 0) { | |
+ while (buf->len > 0) { | |
+ if ((r = write(fd, buf->data, buf->len)) <= 0) { | |
return S_REQUEST_TIMEOUT; | |
} | |
- buf->off += r; | |
- remaining -= r; | |
+ memmove(buf->data, buf->data + r, buf->len - r); | |
+ buf->len -= r; | |
} | |
- /* set off to 0 to indicate that we have finished */ | |
- buf->off = 0; | |
- | |
return 0; | |
} | |
@@ -142,43 +137,35 @@ decode(const char src[PATH_MAX], char dest[PATH_MAX]) | |
} | |
enum status | |
-http_recv_header(int fd, struct buffer *buf) | |
+http_recv_header(int fd, struct buffer *buf, int *done) | |
{ | |
enum status s; | |
ssize_t r; | |
- if (buf->off > sizeof(buf->data)) { | |
- s = S_INTERNAL_SERVER_ERROR; | |
- goto err; | |
- } | |
- | |
while (1) { | |
- if ((r = read(fd, buf->data + buf->off, | |
- sizeof(buf->data) - buf->off)) <= 0) { | |
+ if ((r = read(fd, buf->data + buf->len, | |
+ sizeof(buf->data) - buf->len)) <= 0) { | |
s = S_REQUEST_TIMEOUT; | |
goto err; | |
} | |
- buf->off += r; | |
+ buf->len += r; | |
/* check if we are done (header terminated) */ | |
- if (buf->off >= 4 && !memcmp(buf->data + buf->off - 4, | |
+ if (buf->len >= 4 && !memcmp(buf->data + buf->len - 4, | |
"\r\n\r\n", 4)) { | |
break; | |
} | |
/* buffer is full or read over, but header is not terminated */ | |
- if (r == 0 || buf->off == sizeof(buf->data)) { | |
+ if (r == 0 || buf->len == sizeof(buf->data)) { | |
s = S_REQUEST_TOO_LARGE; | |
goto err; | |
} | |
} | |
- /* header is complete, remove last \r\n and null-terminate */ | |
- buf->data[buf->off - 2] = '\0'; | |
- | |
- /* set buffer length to length and offset to 0 to indicate success */ | |
- buf->len = buf->off - 2; | |
- buf->off = 0; | |
+ /* header is complete, remove last \r\n and set done */ | |
+ buf->len -= 2; | |
+ *done = 1; | |
return 0; | |
err: | |
diff --git a/http.h b/http.h | |
@@ -101,7 +101,7 @@ struct connection { | |
enum status http_prepare_header_buf(const struct response *, struct buffer *); | |
enum status http_send_buf(int, struct buffer *); | |
-enum status http_recv_header(int, struct buffer *); | |
+enum status http_recv_header(int, struct buffer *, int *); | |
enum status http_parse_header(const char *, struct request *); | |
void http_prepare_response(const struct request *, struct response *, | |
const struct server *); | |
diff --git a/util.h b/util.h | |
@@ -38,7 +38,6 @@ struct server { | |
struct buffer { | |
char data[BUFFER_SIZE]; | |
size_t len; | |
- size_t off; | |
}; | |
#undef MIN |