[hackers] [quark] Refactor http_send_buf() and http_recv_header() and simplify buffer || Laslo Hunhold

From: <git_AT_suckless.org>
Date: Wed, 16 Sep 2020 12:15:49 +0200 (CEST)

commit e67eddd517d3f20a24ee14e1eab92806ce5bb20c
Author: Laslo Hunhold <dev_AT_frign.de>
AuthorDate: Wed Sep 16 10:56:45 2020 +0200
Commit: Laslo Hunhold <dev_AT_frign.de>
CommitDate: Wed Sep 16 10:56:45 2020 +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 <dev_AT_frign.de>

diff --git a/http.c b/http.c
index 36ed5ef..f1e15a4 100644
--- a/http.c
+++ b/http.c
_AT_@ -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;
 }
 
_AT_@ -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
index a7255b4..bfaa807 100644
--- a/http.h
+++ b/http.h
_AT_@ -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
index 27de3b1..983abd2 100644
--- a/util.h
+++ b/util.h
_AT_@ -38,7 +38,6 @@ struct server {
 struct buffer {
         char data[BUFFER_SIZE];
         size_t len;
- size_t off;
 };
 
 #undef MIN
Received on Wed Sep 16 2020 - 12:15:49 CEST

This archive was generated by hypermail 2.3.0 : Wed Sep 16 2020 - 12:24:29 CEST