servedir: some line reading buffer optimizations - gopherproxy-c - Gopher HTTP proxy in C (CGI)
 (HTM) git clone git://git.codemadness.org/gopherproxy-c
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 00c13341a4b18c68b1ea0b157c84b840c5f89245
 (DIR) parent 407a5ede41c92b0b9b711bd376493a579995da36
 (HTM) Author: Hiltjo Posthuma <hiltjo@codemadness.org>
       Date:   Mon,  4 Aug 2025 13:31:21 +0200
       
       servedir: some line reading buffer optimizations
       
       Diffstat:
         M gopherproxy.c                       |      66 +++++++++++++++++++------------
       
       1 file changed, 41 insertions(+), 25 deletions(-)
       ---
 (DIR) diff --git a/gopherproxy.c b/gopherproxy.c
       @@ -26,6 +26,9 @@ static struct tls *t;
        static struct tls_config *tls_config;
        #endif
        
       +#define MAX_LINE_SIZ        2048    /* max size of a DirEntry in bytes */
       +#define READ_BUF_SIZ        16384   /* read buffer size in bytes */
       +
        #define MAX_RESPONSETIMEOUT 10      /* timeout in seconds */
        #define MAX_RESPONSESIZ     4000000 /* max download size in bytes */
        
       @@ -53,6 +56,19 @@ struct visited {
                char port[8];
        };
        
       +struct linebuf {
       +        /* line buffer */
       +        char *line;
       +        char linebuf[MAX_LINE_SIZ];
       +        size_t linelen;
       +        size_t lineoff;
       +        /* read buffer */
       +        char buf[READ_BUF_SIZ];
       +        char *bufoff, *bufend;
       +        int err;
       +        int eof;
       +};
       +
        /* parsed URI */
        static struct uri u;
        /* socket fd */
       @@ -338,21 +354,11 @@ plain_readbuf(char *buf, size_t bufsiz)
                return len;
        }
        
       -struct linebuf {
       -        /* line buffer */
       -        char line[2048];
       -        size_t linelen;
       -        size_t lineoff;
       -        /* read buffer */
       -        char buf[4096];
       -        char *bufoff, *bufend;
       -        int err;
       -};
       -
        void
        linebuf_init(struct linebuf *b)
        {
                memset(b, 0, sizeof(struct linebuf));
       +        b->line = b->linebuf;
        }
        
        ssize_t
       @@ -362,7 +368,8 @@ linebuf_get(struct linebuf *b)
                ssize_t n;
                char *p;
        
       -        while (!(b->err)) {
       +        b->line = b->linebuf;
       +        while (!(b->err) && !(b->eof)) {
                        /* need to read more */
                        if (b->bufoff >= b->bufend) {
                                b->bufoff = b->buf;
       @@ -372,8 +379,10 @@ linebuf_get(struct linebuf *b)
                                        b->err = EIO;
        
                                /* use remaining data even if not terminated by a newline */
       -                        if (n == 0 && b->linelen > 0)
       -                                return b->linelen;
       +                        if (n == 0 && b->lineoff > 0) {
       +                                b->eof = 1;
       +                                return b->lineoff;
       +                        }
        
                                if (n > 0)
                                        b->bufend = b->buf + n;
       @@ -384,16 +393,22 @@ linebuf_get(struct linebuf *b)
                        /* search first newline */
                        if ((p = memchr(b->bufoff, '\n', b->bufend - b->bufoff))) {
                                len = (p - b->bufoff);
       +                        /* full line in buffer, no need to copy to line buffer */
       +                        if (b->lineoff == 0)
       +                                b->line = b->bufoff; /* just point to buffer, no copy */
                        } else {
       -                        /* copy remaining data into line buffer and read more */
       +                        /* use remaining data into line buffer and read more */
                                len = (b->bufend - b->bufoff);
                        }
        
       -                if (b->lineoff + len + 1 >= sizeof(b->line)) {
       -                        b->err = ENOMEM;
       -                        return -1;
       +                if (b->line == b->linebuf) {
       +                        if (b->lineoff + len + 1 >= sizeof(b->linebuf)) {
       +                                b->err = ENOMEM;
       +                                return -1;
       +                        }
       +                        memcpy(b->linebuf + b->lineoff, b->bufoff, len);
                        }
       -                memcpy(b->line + b->lineoff, b->bufoff, len);
       +
                        b->lineoff += len;
                        b->linelen = b->lineoff;
                        b->line[b->linelen] = '\0';
       @@ -453,7 +468,7 @@ typestr(int c)
        void
        servefile(const char *server, const char *port, const char *path, const char *query)
        {
       -        char buf[1024];
       +        char buf[READ_BUF_SIZ];
                int r, w;
                size_t totalsiz = 0;
        
       @@ -484,7 +499,7 @@ servedir(const char *server, const char *port, const char *path, const char *que
                struct visited v;
                struct linebuf lb;
                const char *prefix = "";
       -        char buf[1024], uri[2048];
       +        char buf[1024], *uri;
                char *line;
                size_t totalsiz, linenr;
                ssize_t n;
       @@ -507,11 +522,11 @@ servedir(const char *server, const char *port, const char *path, const char *que
                        die(500, "servedir: writebuf failed\n");
        
                linebuf_init(&lb);
       -        line = lb.line;
        
                totalsiz = 0;
       -
                for (linenr = 1; (n = linebuf_get(&lb)) > 0; linenr++) {
       +                line = lb.line;
       +
                        /* too big total response */
                        if (n > 0)
                                totalsiz += n;
       @@ -593,11 +608,12 @@ servedir(const char *server, const char *port, const char *path, const char *que
                        }
        
                        if (!strcmp(v.port, "70"))
       -                        snprintf(uri, sizeof(uri), "%s%s/%c%s",
       +                        snprintf(buf, sizeof(buf), "%s%s/%c%s",
                                        prefix, v.server, primarytype, v.path);
                        else
       -                        snprintf(uri, sizeof(uri), "%s%s:%s/%c%s",
       +                        snprintf(buf, sizeof(buf), "%s%s:%s/%c%s",
                                        prefix, v.server, v.port, primarytype, v.path);
       +                uri = buf;
        
                        switch (primarytype) {
                        case 'i': /* info */