commit 0c78bacd8da3df3671010da5a81cda27102e1339
parent cf20294b6ff67daa92618843533aef1faa7b198a
Author: Santtu Lakkala <inz@inz.fi>
Date: Sat, 15 May 2021 21:46:04 +0300
Refactor to reduce duplicate code
Diffstat:
M | main.c | | | 315 | +++++++++++++++++++++++++++++++++---------------------------------------------- |
1 file changed, 133 insertions(+), 182 deletions(-)
diff --git a/main.c b/main.c
@@ -726,73 +726,85 @@ static void update_redirect(EV_P_ struct client *c, int revents)
client_close(EV_A_ c);
}
-static void update_text(EV_P_ struct client *c, int revents)
+static bool line_foreach(EV_P_ int fd, char *buffer, size_t buffer_size, size_t *buffer_used, bool (*line_cb)(EV_P_ struct client *c, char *line, size_t linelen), struct client *c)
{
int r;
char *nl;
- char *base;
- int n;
+ char *bp;
+
+ if (*buffer_used < buffer_size) {
+ r = read(fd, buffer + *buffer_used, buffer_size - *buffer_used);
+ if (r <= 0) {
+ if (*buffer_used)
+ return !line_cb(EV_A_ c, buffer, *buffer_used);
+ return false;
+ }
- (void)revents;
+ *buffer_used += r;
+ }
- if (c->task_data.tt.rfd < 0) {
- client_close(EV_A_ c);
- return;
+ nl = memchr(buffer, '\n', *buffer_used);
+
+ if (!nl) {
+ if (*buffer_used == buffer_size && line_cb(EV_A_ c, buffer, buffer_size))
+ *buffer_used = 0;
+ return true;
}
- r = read(c->task_data.tt.rfd, c->task_data.tt.linebuf + c->task_data.tt.used, sizeof(c->task_data.tt.linebuf) - c->task_data.tt.used);
+ bp = buffer;
+ do {
+ char *t = nl;
+ if (t > bp && t[-1] == '\r')
+ t--;
- if (r <= 0) {
- if (c->task_data.tt.used) {
- if (c->task_data.tt.linebuf[c->task_data.tt.used - 1] == '\r')
- c->task_data.tt.used--;
+ if (!line_cb(EV_A_ c, bp, t - bp))
+ break;
- n = snprintf(c->buffer + c->buffer_used, sizeof(c->buffer) - c->buffer_used, "%.*s\r\n", (int)c->task_data.tt.used, c->task_data.tt.linebuf);
- c->buffer_used += n;
- c->task_data.tt.used = 0;
- }
+ bp = nl + 1;
+ } while ((nl = memchr(bp, '\n', *buffer_used - (bp - buffer))));
- n = snprintf(c->buffer + c->buffer_used, sizeof(c->buffer) - c->buffer_used, ".\r\n");
- c->buffer_used += n;
+ memmove(buffer, bp, *buffer_used - (bp - buffer));
+ *buffer_used -= bp - buffer;
- close(c->task_data.tt.rfd);
- c->task_data.tt.rfd = -1;
+ return true;
+}
- return;
- }
+static bool process_text_line(EV_P_ struct client *c, char *line, size_t linelen)
+{
+ int n;
- c->task_data.tt.used += r;
- nl = memchr(c->task_data.tt.linebuf, '\n', c->task_data.tt.used);
-
- if (!nl) {
- if (c->task_data.tt.used == sizeof(c->task_data.tt.linebuf)) {
- c->buffer_used += sprintf(c->buffer + c->buffer_used, "%.*s\r\n", (int)c->task_data.tt.used, c->task_data.tt.linebuf);
- c->task_data.tt.used = 0;
- }
- return;
- }
+ if (linelen == 1 && *line == '.')
+ n = snprintf(c->buffer + c->buffer_used, sizeof(c->buffer) - c->buffer_used, "..\r\n");
+ else
+ n = snprintf(c->buffer + c->buffer_used, sizeof(c->buffer) - c->buffer_used, "%.*s\r\n", (int)linelen, line);
- base = c->task_data.tt.linebuf;
- do {
- char *t = nl;
+ if ((size_t)n > sizeof(c->buffer) - c->buffer_used)
+ return false;
- if (t > base && t[-1] == '\r')
- t--;
+ c->buffer_used += n;
+ return true;
+}
- if (t == base + 1 && *base == '.')
- n = snprintf(c->buffer + c->buffer_used, sizeof(c->buffer) - c->buffer_used, "..\r\n");
- else
- n = snprintf(c->buffer + c->buffer_used, sizeof(c->buffer) - c->buffer_used, "%.*s\r\n", (int)(t - base), base);
+static void update_text(EV_P_ struct client *c, int revents)
+{
+ (void)revents;
+
+ if (c->task_data.tt.rfd < 0) {
+ client_close(EV_A_ c);
+ return;
+ }
+
+ if (!line_foreach(EV_A_ c->task_data.tt.rfd, c->task_data.tt.linebuf, sizeof(c->task_data.tt.linebuf), &c->task_data.tt.used, process_text_line, c)) {
+ int n = snprintf(c->buffer + c->buffer_used, sizeof(c->buffer) - c->buffer_used, ".\r\n");
if ((size_t)n > sizeof(c->buffer) - c->buffer_used)
- break;
- c->buffer_used += n;
+ return;
- base = nl + 1;
- } while ((nl = memchr(base, '\n', c->task_data.tt.used - (base - c->task_data.tt.linebuf))));
+ c->buffer_used += n;
- memmove(c->task_data.tt.linebuf, base, c->task_data.tt.used - (base - c->task_data.tt.linebuf));
- c->task_data.tt.used -= base - c->task_data.tt.linebuf;
+ close(c->task_data.tt.rfd);
+ c->task_data.tt.rfd = -1;
+ }
}
static size_t strnchrcnt(const char *haystack, char needle, size_t hsl)
@@ -803,13 +815,34 @@ static size_t strnchrcnt(const char *haystack, char needle, size_t hsl)
return n;
}
-static void update_gophermap(EV_P_ struct client *c, int revents)
+static bool process_gophermap_line(EV_P_ struct client *c, char *line, size_t linelen)
{
- int r;
- char *nl;
- char *base;
int n;
+ if (*line == 'i' || *line == '3')
+ n = snprintf(c->buffer + c->buffer_used, sizeof(c->buffer) - c->buffer_used, "%.*s\t.\t.\t.\r\n", (int)linelen, line);
+ else {
+ size_t tabcount = strnchrcnt(line, '\t', linelen);
+
+ if (tabcount > 2)
+ n = snprintf(c->buffer + c->buffer_used, sizeof(c->buffer) - c->buffer_used, "%.*s\r\n", (int)linelen, line);
+ else if (tabcount > 1)
+ n = snprintf(c->buffer + c->buffer_used, sizeof(c->buffer) - c->buffer_used, "%.*s\t70\r\n", (int)linelen, line);
+ else if (tabcount)
+ n = snprintf(c->buffer + c->buffer_used, sizeof(c->buffer) - c->buffer_used, "%.*s\t%s\t%s\r\n", (int)linelen, line, hostname, oport);
+ else
+ n = snprintf(c->buffer + c->buffer_used, sizeof(c->buffer) - c->buffer_used, "i%.*s\t.\t.\t.\r\n", (int)linelen, line);
+ }
+
+ if ((size_t)n > sizeof(c->buffer) - c->buffer_used)
+ return false;
+
+ c->buffer_used += n;
+ return true;
+}
+
+static void update_gophermap(EV_P_ struct client *c, int revents)
+{
(void)revents;
if (c->task_data.tt.rfd < 0) {
@@ -817,69 +850,17 @@ static void update_gophermap(EV_P_ struct client *c, int revents)
return;
}
- r = read(c->task_data.tt.rfd, c->task_data.tt.linebuf + c->task_data.tt.used, sizeof(c->task_data.tt.linebuf) - c->task_data.tt.used);
+ if (!line_foreach(EV_A_ c->task_data.tt.rfd, c->task_data.tt.linebuf, sizeof(c->task_data.tt.linebuf), &c->task_data.tt.used, process_gophermap_line, c)) {
+ int n = snprintf(c->buffer + c->buffer_used, sizeof(c->buffer) - c->buffer_used, ".\r\n");
- if (r <= 0) {
- if (c->task_data.tt.used) {
- if (c->task_data.tt.linebuf[c->task_data.tt.used - 1] == '\r')
- c->task_data.tt.used--;
-
- n = snprintf(c->buffer + c->buffer_used, sizeof(c->buffer) - c->buffer_used, "%.*s\r\n", (int)c->task_data.tt.used, c->task_data.tt.linebuf);
- c->buffer_used += n;
- c->task_data.tt.used = 0;
- }
+ if ((size_t)n > sizeof(c->buffer) - c->buffer_used)
+ return;
- n = snprintf(c->buffer + c->buffer_used, sizeof(c->buffer) - c->buffer_used, ".\r\n");
c->buffer_used += n;
close(c->task_data.tt.rfd);
c->task_data.tt.rfd = -1;
-
- return;
- }
-
- c->task_data.tt.used += r;
- nl = memchr(c->task_data.tt.linebuf, '\n', c->task_data.tt.used);
-
- if (!nl) {
- if (c->task_data.tt.used == sizeof(c->task_data.tt.linebuf)) {
- c->buffer_used += sprintf(c->buffer + c->buffer_used, "%.*s\r\n", (int)c->task_data.tt.used, c->task_data.tt.linebuf);
- c->task_data.tt.used = 0;
- }
- return;
}
-
- base = c->task_data.tt.linebuf;
- do {
- char *t = nl;
-
- if (t > base && t[-1] == '\r')
- t--;
-
- if (*base == 'i' || *base == '3')
- n = snprintf(c->buffer + c->buffer_used, sizeof(c->buffer) - c->buffer_used, "%.*s\t.\t.\t.\r\n", (int)(t - base), base);
- else {
- size_t tabcount = strnchrcnt(base, '\t', t - base);
-
- if (tabcount > 2)
- n = snprintf(c->buffer + c->buffer_used, sizeof(c->buffer) - c->buffer_used, "%.*s\r\n", (int)(t - base), base);
- else if (tabcount > 1)
- n = snprintf(c->buffer + c->buffer_used, sizeof(c->buffer) - c->buffer_used, "%.*s\t70\r\n", (int)(t - base), base);
- else if (tabcount)
- n = snprintf(c->buffer + c->buffer_used, sizeof(c->buffer) - c->buffer_used, "%.*s\t%s\t%s\r\n", (int)(t - base), base, hostname, oport);
- else
- n = snprintf(c->buffer + c->buffer_used, sizeof(c->buffer) - c->buffer_used, "i%.*s\t.\t.\t.\r\n", (int)(t - base), base);
- }
-
- if ((size_t)n > sizeof(c->buffer) - c->buffer_used)
- break;
- c->buffer_used += n;
-
- base = nl + 1;
- } while ((nl = memchr(base, '\n', c->task_data.tt.used - (base - c->task_data.tt.linebuf))));
-
- memmove(c->task_data.tt.linebuf, base, c->task_data.tt.used - (base - c->task_data.tt.linebuf));
- c->task_data.tt.used -= base - c->task_data.tt.linebuf;
}
static char *strunesctok(char *str, char *delim, char esc)
@@ -913,99 +894,69 @@ static char *strunesctok(char *str, char *delim, char esc)
return rv;
}
-static void update_gph(EV_P_ struct client *c, int revents)
+static bool process_gph_line(EV_P_ struct client *c, char *line, size_t linelen)
{
- int r;
- char *nl;
- char *base;
int n;
- (void)revents;
+ line[linelen] = '\0';
- if (c->task_data.gpht.rfd < 0) {
- client_close(EV_A_ c);
- return;
- }
-
- r = read(c->task_data.gpht.rfd, c->task_data.gpht.linebuf + c->task_data.gpht.used, sizeof(c->task_data.gpht.linebuf) - c->task_data.gpht.used);
+ if (*line != '[' || *line == 't') {
+ if (*line == 't')
+ line++;
+ n = snprintf(c->buffer + c->buffer_used, sizeof(c->buffer) - c->buffer_used, "i%s\t.\t.\t.\r\n", line);
+ } else {
+ const char *type = strunesctok(line + 1, "|", '\\');
+ const char *desc = strunesctok(NULL, "|", '\\');
+ const char *resource = strunesctok(NULL, "|", '\\');
+ const char *server = strunesctok(NULL, "|", '\\');
+ const char *port = strunesctok(NULL, "|", '\\');
- if (r <= 0) {
- if (c->task_data.gpht.used) {
- if (c->task_data.gpht.linebuf[c->task_data.gpht.used - 1] == '\r')
- c->task_data.gpht.used--;
+ if (line[linelen - 1] == ']')
+ line[--linelen] = '\0';
- n = snprintf(c->buffer + c->buffer_used, sizeof(c->buffer) - c->buffer_used, "%.*s\r\n", (int)c->task_data.gpht.used, c->task_data.gpht.linebuf);
- c->buffer_used += n;
- c->task_data.gpht.used = 0;
+ if (!resource)
+ n = snprintf(c->buffer + c->buffer_used, sizeof(c->buffer) - c->buffer_used, "3Invalid line\r\n");
+ else {
+ if (!server || !strcmp(server, "server"))
+ server = hostname;
+ else if (!port)
+ port = dfl_port;
+ if (!port || !strcmp(port, "port"))
+ port = oport;
+ if (strpfx(resource, "URI:") || strpfx(resource, "URL:") || *resource == '/' || strcmp(server, hostname) || strcmp(port, oport))
+ n = snprintf(c->buffer + c->buffer_used, sizeof(c->buffer) - c->buffer_used, "%s%s\t%s\t%s\t%s\r\n", type, desc, resource, server, port);
+ else
+ n = snprintf(c->buffer + c->buffer_used, sizeof(c->buffer) - c->buffer_used, "%s%s\t/%s%s\t%s\t%s\r\n", type, desc, c->task_data.gpht.base, resource, server, port);
}
+ }
- n = snprintf(c->buffer + c->buffer_used, sizeof(c->buffer) - c->buffer_used, ".\r\n");
- c->buffer_used += n;
+ if ((size_t)n > sizeof(c->buffer) - c->buffer_used)
+ return false;
- close(c->task_data.gpht.rfd);
- c->task_data.gpht.rfd = -1;
+ c->buffer_used += n;
+ return true;
+}
- return;
- }
+static void update_gph(EV_P_ struct client *c, int revents)
+{
+ (void)revents;
- c->task_data.gpht.used += r;
- nl = memchr(c->task_data.gpht.linebuf, '\n', c->task_data.gpht.used);
-
- if (!nl) {
- if (c->task_data.gpht.used == sizeof(c->task_data.gpht.linebuf)) {
- c->buffer_used += sprintf(c->buffer + c->buffer_used, "%.*s\r\n", (int)c->task_data.gpht.used, c->task_data.gpht.linebuf);
- c->task_data.gpht.used = 0;
- }
+ if (c->task_data.tt.rfd < 0) {
+ client_close(EV_A_ c);
return;
}
- base = c->task_data.gpht.linebuf;
- do {
- char *t = nl;
-
- if (t > base && t[-1] == '\r')
- t--;
- *t = '\0';
-
- if (*base != '[' || *base == 't') {
- if (*base == 't')
- base++;
- n = snprintf(c->buffer + c->buffer_used, sizeof(c->buffer) - c->buffer_used, "i%s\t.\t.\t.\r\n", base);
- } else {
- const char *type = strunesctok(base + 1, "|", '\\');
- const char *desc = strunesctok(NULL, "|", '\\');
- const char *resource = strunesctok(NULL, "|", '\\');
- const char *server = strunesctok(NULL, "|", '\\');
- const char *port = strunesctok(NULL, "|", '\\');
-
- if (t[-1] == ']')
- *--t = '\0';
-
- if (!resource)
- n = snprintf(c->buffer + c->buffer_used, sizeof(c->buffer) - c->buffer_used, "3Invalid line\r\n");
- else {
- if (!server || !strcmp(server, "server"))
- server = hostname;
- else if (!port)
- port = dfl_port;
- if (!port || !strcmp(port, "port"))
- port = oport;
- if (strpfx(resource, "URI:") || strpfx(resource, "URL:") || *resource == '/' || strcmp(server, hostname) || strcmp(port, oport))
- n = snprintf(c->buffer + c->buffer_used, sizeof(c->buffer) - c->buffer_used, "%s%s\t%s\t%s\t%s\r\n", type, desc, resource, server, port);
- else
- n = snprintf(c->buffer + c->buffer_used, sizeof(c->buffer) - c->buffer_used, "%s%s\t/%s%s\t%s\t%s\r\n", type, desc, c->task_data.gpht.base, resource, server, port);
- }
- }
+ if (!line_foreach(EV_A_ c->task_data.gpht.rfd, c->task_data.gpht.linebuf, sizeof(c->task_data.gpht.linebuf) - 1, &c->task_data.gpht.used, process_gph_line, c)) {
+ int n = snprintf(c->buffer + c->buffer_used, sizeof(c->buffer) - c->buffer_used, ".\r\n");
if ((size_t)n > sizeof(c->buffer) - c->buffer_used)
- break;
- c->buffer_used += n;
+ return;
- base = nl + 1;
- } while ((nl = memchr(base, '\n', c->task_data.gpht.used - (base - c->task_data.gpht.linebuf))));
+ c->buffer_used += n;
- memmove(c->task_data.gpht.linebuf, base, c->task_data.gpht.used - (base - c->task_data.gpht.linebuf));
- c->task_data.gpht.used -= base - c->task_data.gpht.linebuf;
+ close(c->task_data.tt.rfd);
+ c->task_data.tt.rfd = -1;
+ }
}
static void update_read(EV_P_ struct client *c, int revents)