servedir: some line reading buffer optimizations - gopherproxy-c - Gopher HTTP … | |
git clone git://git.codemadness.org/gopherproxy-c | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 00c13341a4b18c68b1ea0b157c84b840c5f89245 | |
parent 407a5ede41c92b0b9b711bd376493a579995da36 | |
Author: Hiltjo Posthuma <[email protected]> | |
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(-) | |
--- | |
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 newl… | |
- 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, … | |
} 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 *… | |
{ | |
- 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 *… | |
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… | |
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… | |
} | |
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 */ |