From 47cf044858a3381421bbe79094271892421667c3 Mon Sep 17 00:00:00 2001 From: Nate Choe Date: Tue, 21 Jun 2022 23:34:13 -0500 Subject: [PATCH] Multiple port support --- Makefile | 2 +- documentation/sitefiles.md | 12 ++- site/https.html | 7 ++ site/run.sh | 2 +- site/site/8001.html | 1 + site/sitefile | 42 +++++++++-- src/connections.c | 9 ++- src/main.c | 80 ++++++++++++++------ src/runner.c | 67 ++++++++++------- src/setup.c | 14 +--- src/sitefile.c | 149 +++++++++++++++++++++++++------------ src/sockets.c | 4 + src/swebs/connections.h | 4 +- src/swebs/runner.h | 12 ++- src/swebs/setup.h | 4 +- src/swebs/sitefile.h | 23 ++++-- src/swebs/sockets.h | 1 + src/swebs/util.h | 6 ++ src/util.c | 30 ++++++++ 19 files changed, 333 insertions(+), 136 deletions(-) create mode 100644 site/https.html create mode 100644 site/site/8001.html diff --git a/Makefile b/Makefile index 572a0a1..d05cb72 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ SRC = $(wildcard src/*.c) OBJ = $(subst .c,.o,$(subst src,work,$(SRC))) LIBS = gnutls LDFLAGS = -pie -lrt -ldl $(shell pkg-config --libs $(LIBS)) -CFLAGS := -O2 -pipe -Wall -Wpedantic -Wshadow -ansi -D_XOPEN_SOURCE=500 +CFLAGS := -O2 -pipe -Wall -Wpedantic -Wshadow -ansi -D_XOPEN_SOURCE=500 -ggdb CFLAGS += -Isrc/ -fpie -D_POSIX_C_SOURCE=200809L $(shell pkg-config --cflags $(LIBS)) INSTALLDIR := /usr/sbin HEADERDIR := /usr/include/ diff --git a/documentation/sitefiles.md b/documentation/sitefiles.md index 2d0e4d7..1bc3b20 100644 --- a/documentation/sitefiles.md +++ b/documentation/sitefiles.md @@ -16,6 +16,10 @@ sitefiles also allow comments with # * ```read [http path] [file path]``` - if the requested path matches ```[http path]```, return the contents of ```[file path]```. If [file path] is a directory, then the http path is appended to [file path] and that is read instead. * ```linked``` - Run getResponse() from the library loaded from the library global variable * ```throw [http path] [error code]``` - If the requested path matches ```[http path]```, send back the http error code ```[error code]```. For standardization purposes, these error codes are just the number. +* ```declare [transport] [port]``` - Declares that port ```[port]``` will be used with transport ```[transport]``` where ```[transport]``` is one of ```TCP```, ```TLS``` +* ```key [key file] [port]``` - Sets the key file for port ```[port]``` to ```[key file]``` +* ```cert [cert file] [port]``` - Sets the certificate file for port ```[port]``` to ```[cert file]``` +* ```timeout [timeout] [port]``` - Sets the connection timeout for port ```[port]``` to ```[timeout]``` milliseconds ##### Other than set, commands should take in a regex as argument 1 and operate on a file specified in argument 2. @@ -25,14 +29,8 @@ sitefiles also allow comments with # * GET (defualt) * POST * ```host``` - The hostname to respond to. Case insensitive regex, default: .* +* ```port``` - The port to respond to, default: 80 # Part 4: Global variables -* ```port``` - the port to use. Note that this is a global variable, and so one instance of swebs cannot use multiple ports. -* ```transport``` - the type of connection to use. One of: - * TCP (default) - * TLS -* ```key``` - The filepath of the private key to use if transport == TLS -* ```cert``` - The filepath of the certificate to use if transport == TLS -* ```timeout``` - The amount of time to wait for data before closing the connection in ms. A timeout of 0 means to wait infinitely. (default: 2000) * ```library``` - the path of a library that is linked in during runtime if ```DYNAMIC_LINKED_PAGES```is set. diff --git a/site/https.html b/site/https.html new file mode 100644 index 0000000..521fed3 --- /dev/null +++ b/site/https.html @@ -0,0 +1,7 @@ + + + +

You are a brave soul for trusting a self signed HTTPS + certificate. Don't do it again.

+ + diff --git a/site/run.sh b/site/run.sh index 93d405d..1e5b65f 100755 --- a/site/run.sh +++ b/site/run.sh @@ -1,3 +1,3 @@ #!/bin/sh -../build/swebs -p swebs.pid -s sitefile -o logs -b 100 -j2 +../build/swebs -p swebs.pid -s sitefile -o /dev/stdout -b 100 -j2 diff --git a/site/site/8001.html b/site/site/8001.html new file mode 100644 index 0000000..31cfb47 --- /dev/null +++ b/site/site/8001.html @@ -0,0 +1 @@ +

Welcome to port 8001!

diff --git a/site/sitefile b/site/sitefile index 0b0eac1..6bfd67b 100644 --- a/site/sitefile +++ b/site/sitefile @@ -1,21 +1,49 @@ -define port 8000 +declare TCP 8000 +declare TLS 8001 +# We will use ports 8000 and 8001 with TCP and TLS respectively + +key domain.key 8001 +cert domain.crt 8001 +# Port 8001 can have TLS, but it's self signed and very bad. + +timeout 2000 8000 +timeout 2000 8001 +# Set these values for the ports + +set port 8000 +# The following pages will respond to port 8000 -define transport TLS -define transport TCP -define key domain.key -define cert domain.crt -define timeout 2000 define library ./library.so +# Library calls should use ./library.so set host localhost:8000 +# The following pages will respond to the host localhost:8000 read / site/index.html +# The path / should be read from site/index.html read /hello site/hello.html +# The path /hello should be read from site/hello.html + throw /blog/forbidden 403 +# The path /blog/forbidden should throw error code 403 read /blog/.* site/blog/ -#/blog/2021-1-25.html turns into site/blog//blog/2021-1-25.html +# /blog/2021-1-25.html turns into site/blog//blog/2021-1-25.html linked /library +# The path /library should be dynamically loaded from the library (library.so) + set host 127.0.0.1:8000 +# The following pages will respond to the host 127.0.0.1:8000 + read / site/easteregg.html +# The path / should be read from site/easteregg.html read /egg.png site/egg.png +# The path /egg.png should be read from site/egg.png set host .* +# The following pages will respond to all hosts (regex) read /alldomains site/alldomains.html +# The path /alldomains should be read from /site/alldomains.html + +set port 8001 +# The following pages will respond to port 8001 + +read / site/8001.html +# The path / should be read from site/8001.html diff --git a/src/connections.c b/src/connections.c index 5f05004..c6b9bb8 100644 --- a/src/connections.c +++ b/src/connections.c @@ -27,7 +27,7 @@ #include #include -int newConnection(Stream *stream, Connection *ret) { +int newConnection(Stream *stream, Connection *ret, int portind) { struct timespec currentTime; ret->stream = stream; @@ -68,6 +68,8 @@ int newConnection(Stream *stream, Connection *ret) { return 1; } memcpy(&ret->lastdata, ¤tTime, sizeof(struct timespec)); + + ret->portind = portind; return 0; } @@ -360,10 +362,11 @@ int updateConnection(Connection *conn, Sitefile *site) { ssize_t received; unsigned long i; struct timespec currentTime; + const Port *port = site->ports + conn->portind; if (clock_gettime(CLOCK_MONOTONIC, ¤tTime) < 0) return 1; - if (site->timeout > 0 && - diff(&conn->lastdata, ¤tTime) > site->timeout) + if (port->timeout > 0 && + diff(&conn->lastdata, ¤tTime) > port->timeout) return 1; received = recvStream(conn->stream, buff, sizeof(buff)); if (received < 0) diff --git a/src/main.c b/src/main.c index 1f68011..354ec8c 100644 --- a/src/main.c +++ b/src/main.c @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -41,11 +42,11 @@ typedef struct { static Runner *runners; static int processes; -static int mainfd; static int *pending; -static Listener *listener; static Sitefile *site; +static int mainfd; /* fd of the UNIX socket */ static struct sockaddr_un addr; +static ConnInfo *conninfo; /* We want to be able to handle a signal at any time, so some global variables * are needed. */ static const int signals[] = { @@ -54,7 +55,6 @@ static const int signals[] = { }; static void exitClean(int signal) { - freeListener(listener); close(mainfd); remove(addr.sun_path); exit(EXIT_SUCCESS); @@ -109,14 +109,16 @@ static void createProcess(int id) { unsetsignal(SIGCHLD); connfd = socket(AF_UNIX, SOCK_STREAM, 0); - if (connfd < 0) + if (connfd < 0) { + createErrorLog("socket() failed, killing child", errno); exit(EXIT_FAILURE); + } if (connect(connfd, (struct sockaddr *) &addr, sizeof(addr))) { createErrorLog("connect() failed, killing child", errno); exit(EXIT_FAILURE); } close(mainfd); - runServer(connfd, site, listener, pending, id); + runServer(connfd, site, pending, id, conninfo); createLog("child runServer() finished"); exit(EXIT_SUCCESS); } @@ -138,8 +140,24 @@ static void remakeChild(int signal) { int main(int argc, char **argv) { int i; int pendingid; + int backlog; + int conninfoid; + Listener **listeners; + struct pollfd *pollfds; - setup(argc, argv, &site, &listener, &processes); + setup(argc, argv, &site, &processes, &backlog); + + listeners = xmalloc(site->portcount * sizeof *listeners); + pollfds = xmalloc(site->portcount * sizeof *pollfds); + for (i = 0; i < site->portcount; ++i) { + listeners[i] = createListener(site->ports[i].num, backlog); + if (listeners[i] == NULL) { + fprintf(stderr, "Failed to listen on port %hu\n", + site->ports[i].num); + } + pollfds[i].fd = listenerfd(listeners[i]); + pollfds[i].events = POLLIN; + } pendingid = smalloc(sizeof(int) * (processes - 1)); if (pendingid < 0) { @@ -151,6 +169,18 @@ int main(int argc, char **argv) { createErrorLog("saddr() failed", errno); exit(EXIT_FAILURE); } + + conninfoid = smalloc(sizeof *conninfo); + if (conninfoid < 0) { + createErrorLog("smalloc() failed", errno); + exit(EXIT_FAILURE); + } + conninfo = saddr(conninfoid); + if (conninfo == NULL) { + createErrorLog("saddr() failed", errno); + exit(EXIT_FAILURE); + } + memset(pending, 0, sizeof(int) * (processes - 1)); mainfd = socket(AF_UNIX, SOCK_STREAM, 0); @@ -175,25 +205,29 @@ int main(int argc, char **argv) { createLog("swebs started"); for (;;) { - int fd; - int lowestProc; - - fd = acceptConnection(listener); - if (fd < 0) { - if (errno == ENOTSOCK || errno == EOPNOTSUPP || - errno == EINVAL) { - createErrorLog("You've majorly screwed up. Good luck", - errno); - exit(EXIT_FAILURE); - } - continue; + if (poll(pollfds, site->portcount, -1) < 0) { + if (errno == EINTR) + continue; + createErrorLog("You've majorly screwed up. Good luck", + errno); + exit(EXIT_FAILURE); } + createLog("Accepted stream"); - lowestProc = 0; - for (i = 1; i < processes - 1; i++) - if (pending[i] < pending[lowestProc]) - lowestProc = i; - sendFd(fd, runners[lowestProc].fd); + for (i = 0; i < site->portcount; ++i) { + if (pollfds[i].revents & POLLIN) { + int j, lowestproc, fd; + fd = acceptConnection(listeners[i]); + while (conninfo->valid) ; + lowestproc = 0; + for (j = 0; j < processes - 1; j++) + if (pending[j] < pending[lowestproc]) + lowestproc = j; + conninfo->portind = i; + conninfo->valid = 1; + sendFd(fd, runners[lowestproc].fd); + } + } } } diff --git a/src/runner.c b/src/runner.c index 5f294a6..f880412 100644 --- a/src/runner.c +++ b/src/runner.c @@ -31,33 +31,42 @@ #include #include -void runServer(int connfd, Sitefile *site, Listener *listener, - int *pending, int id) { +void runServer(int connfd, Sitefile *site, int *pending, int id, + ConnInfo *conninfo) { int allocConns = 100; - struct pollfd *fds = malloc(sizeof(struct pollfd) * allocConns); - Connection *connections = malloc(sizeof(Connection) * allocConns); - int connCount = 1; - /* connections are 1 indexed because fds[0] is the notify fd. */ - Context *context; - assert(fds != NULL); - assert(connections != NULL); + struct pollfd *fds; + Connection *connections; + int connCount; + Context **contexts; + int i; + + connCount = 1; + fds = xmalloc(allocConns * sizeof *fds); + connections = xmalloc(allocConns * sizeof *connections); fds[0].fd = connfd; fds[0].events = POLLIN; + /* connections are 1 indexed because fds[0] is the notify fd. I hate + * that poll() forces us to do these hacks. */ - switch (site->type) { - case TCP: - context = createContext(TCP); - break; - case TLS: - context = createContext(TLS, site->key, site->cert); - break; - default: - createLog("Socket type is somehow invalid"); - return; - } - if (context == NULL) { - createErrorLog("Failed to create context", errno); - exit(EXIT_FAILURE); + contexts = xmalloc(site->portcount * sizeof *contexts); + + for (i = 0; i < site->portcount; ++i) { + Port *port = site->ports + i; + switch (port->type) { + case TCP: + contexts[i] = createContext(TCP); + break; + case TLS: + contexts[i] = createContext(TLS, port->key, port->cert); + break; + default: + createLog("Socket type is somehow invalid"); + return; + } + if (contexts[i] == NULL) { + createErrorLog("Failed to create context", errno); + exit(EXIT_FAILURE); + } } { @@ -78,7 +87,6 @@ void runServer(int connfd, Sitefile *site, Listener *listener, } for (;;) { - int i; poll(fds, connCount, -1); { char log[200]; @@ -105,17 +113,22 @@ remove: if (fds[0].revents & POLLIN) { Stream *newstream; int newfd; + int portind; newfd = recvFd(connfd); if (newfd < 0) { createLog("Message received that included an invalid fd"); continue; } + while (conninfo->valid == 0) ; + portind = conninfo->portind; + conninfo->valid = 0; createLog("Obtained file descriptor from child"); - newstream = createStream(context, O_NONBLOCK, newfd); + newstream = createStream(contexts[portind], O_NONBLOCK, newfd); if (newstream == NULL) { - createLog("Stream couldn't be created from file descriptor"); + createLog( +"Stream couldn't be created from file descriptor"); close(newfd); continue; } @@ -141,7 +154,7 @@ remove: connections = newconns; } - if (newConnection(newstream, connections + connCount)) { + if (newConnection(newstream, connections + connCount, portind)) { createLog("Couldn't initialize connection from stream"); continue; } diff --git a/src/setup.c b/src/setup.c index 04962b3..8b2a3a3 100644 --- a/src/setup.c +++ b/src/setup.c @@ -58,15 +58,15 @@ static void printLongMessage(char *first, ...) { va_end(ap); } -void setup(int argc, char **argv, - Sitefile **site, Listener **listener, int *processes) { +void setup(int argc, char **argv, Sitefile **site, int *processes, + int *backlog) { char *logout = "/var/log/swebs.log"; char *sitefile = NULL; - int backlog = 100; char shouldDaemonize = 0; char *pidfile = "/run/swebs.pid"; *processes = sysconf(_SC_NPROCESSORS_ONLN) + 1; + *backlog = 100; for (;;) { int c = getopt(argc, argv, "o:j:s:b:c:Bp:hl"); @@ -83,7 +83,7 @@ void setup(int argc, char **argv, sitefile = optarg; break; case 'b': - backlog = atoi(optarg); + *backlog = atoi(optarg); break; case 'B': shouldDaemonize = 1; @@ -139,12 +139,6 @@ NULL exit(EXIT_FAILURE); } - *listener = createListener((*site)->port, backlog); - if (*listener == NULL) { - fprintf(stderr, "Failed to create socket\n"); - exit(EXIT_FAILURE); - } - if (shouldDaemonize) daemonize(pidfile); diff --git a/src/sitefile.c b/src/sitefile.c index 991fdfe..f02712c 100644 --- a/src/sitefile.c +++ b/src/sitefile.c @@ -175,40 +175,46 @@ error: } Sitefile *parseSitefile(char *path) { - FILE *file = fopen(path, "r"); + FILE *file; RequestType respondto = GET; const int cflags = REG_EXTENDED | REG_ICASE; char *host = NULL; int argc; char **argv; - int allocatedLength = 50; - char gotPort = 0; Sitefile *ret; + unsigned short currport; + currport = 80; + file = fopen(path, "r"); if (file == NULL) return NULL; - ret = malloc(sizeof(Sitefile)); - if (ret == NULL) - return NULL; - ret->type = TCP; - ret->key = NULL; - ret->cert = NULL; - ret->timeout = 2000; + ret = xmalloc(sizeof *ret); + ret->size = 0; - ret->content = malloc(allocatedLength * sizeof(SiteCommand)); + ret->alloc = 50; + ret->content = xmalloc(ret->alloc * sizeof *ret->content); + ret->portcount = 0; + ret->portalloc = 5; + ret->ports = xmalloc(ret->portalloc * sizeof *ret->ports); #if DYNAMIC_LINKED_PAGES ret->getResponse = NULL; #endif - if (ret->content == NULL) { - free(ret); - return NULL; - } + for (;;) { ReturnCode status = getCommand(file, &argc, &argv); switch (status) { + int i; case FILE_END: - if (!gotPort) - goto nterror; + for (i = 0; i < ret->portcount; ++i) { + Port *port = ret->ports + i; + if (port->type == TLS && + (port->key == NULL || + port->cert == NULL)) { + fprintf(stderr, +"Port %hu declared as TLS without proper TLS files\n", port->num); + goto nterror; + } + } fclose(file); return ret; case ERROR: case LINE_END: @@ -225,7 +231,9 @@ Sitefile *parseSitefile(char *path) { goto error; } else if (strcmp(argv[1], "host") == 0) - host = strdup(argv[2]); + host = xstrdup(argv[2]); + else if (strcmp(argv[1], "port") == 0) + currport = atoi(argv[2]); else goto error; continue; @@ -233,31 +241,12 @@ Sitefile *parseSitefile(char *path) { else if (strcmp(argv[0], "define") == 0) { if (argc < 3) goto error; - if (strcmp(argv[1], "transport") == 0) { - if (strcmp(argv[2], "TCP") == 0) - ret->type = TCP; - else if (strcmp(argv[2], "TLS") == 0) - ret->type = TLS; - else - goto error; - } - else if (strcmp(argv[1], "port") == 0) { - ret->port = atoi(argv[2]); - gotPort = 1; - } - else if (strcmp(argv[1], "key") == 0) - ret->key = strdup(argv[2]); - else if (strcmp(argv[1], "cert") == 0) - ret->cert = strdup(argv[2]); - else if (strcmp(argv[1], "timeout") == 0) - ret->timeout = atoi(argv[2]); else if (strcmp(argv[1], "library") == 0) { #if DYNAMIC_LINKED_PAGES ret->getResponse = loadGetResponse(argv[2]); #else - fprintf(stderr, -"This version of swebs has no dynamic page support\n" - ); + fputs( +"This version of swebs has no dynamic page support\n", stderr); exit(EXIT_FAILURE); #endif } @@ -265,11 +254,69 @@ Sitefile *parseSitefile(char *path) { goto error; continue; } - if (ret->size >= allocatedLength) { + else if (strcmp(argv[0], "declare") == 0) { + Port newport; + int i; + if (argc < 3) { + fputs( +"Usage: declare [transport] [port]\n", stderr); + goto error; + } + newport.num = atoi(argv[2]); + + for (i = 0; i < ret->portcount; ++i) { + if (ret->ports[i].num == newport.num) { + fprintf(stderr, +"Port %hu declared multiple times\n", newport.num); + goto error; + } + } + + if (strcmp(argv[1], "TCP") == 0) + newport.type = TCP; + else if (strcmp(argv[1], "TLS") == 0) + newport.type = TLS; + else { + fprintf(stderr, "Invalid transport %s\n", + argv[1]); + goto error; + } + newport.timeout = 2000; + newport.key = newport.cert = NULL; + if (ret->portcount >= ret->portalloc) { + ret->portalloc *= 2; + ret->ports = xrealloc(ret->ports, + ret->portalloc * sizeof *ret->ports); + } + memcpy(ret->ports + ret->portcount, &newport, + sizeof newport); + ++ret->portcount; + continue; + } +#define PORT_ATTRIBUTE(name, func) \ + else if (strcmp(argv[0], #name) == 0) { \ + int i; \ + unsigned short port; \ + if (argc < 3) { \ + fputs("Usage: " #name " [" #name "] [port]\n", \ + stderr); \ + goto error; \ + } \ + port = atoi(argv[2]); \ + for (i = 0; i < ret->portcount; ++i) \ + if (ret->ports[i].num == port) \ + ret->ports[i].name = func(argv[1]); \ + continue; \ + } + PORT_ATTRIBUTE(key, xstrdup) + PORT_ATTRIBUTE(cert, xstrdup) + PORT_ATTRIBUTE(timeout, atoi) +#undef PORT_ATTRIBUTE + if (ret->size >= ret->alloc) { SiteCommand *newcontent; - allocatedLength *= 2; - newcontent = realloc(ret->content, - allocatedLength * sizeof(SiteCommand)); + ret->alloc *= 2; + newcontent = realloc(ret->content, ret->alloc * + sizeof *newcontent); if (newcontent == NULL) goto error; ret->content = newcontent; @@ -282,7 +329,7 @@ Sitefile *parseSitefile(char *path) { if (strcmp(argv[0], "read") == 0) { if (argc < 3) goto error; - ret->content[ret->size].arg = strdup(argv[2]); + ret->content[ret->size].arg = xstrdup(argv[2]); if (ret->content[ret->size].arg == NULL) goto error; ret->content[ret->size].command = READ; @@ -295,16 +342,26 @@ Sitefile *parseSitefile(char *path) { goto error; ret->content[ret->size].command = THROW; } - else if (strcmp(argv[0], "linked") == 0) + else if (strcmp(argv[0], "linked") == 0) { +#if DYNAMIC_LINKED_PAGES ret->content[ret->size].command = LINKED; - else +#else + fputs( +"This version of swebs doesn't have linked page support", stderr); goto error; +#endif + } + else { + fprintf(stderr, "Unknown sitefile command %s", argv[0]); + goto error; + } freeTokens(argc, argv); ret->content[ret->size].respondto = respondto; if (host == NULL) regcomp(&ret->content[ret->size].host, ".*", cflags); else regcomp(&ret->content[ret->size].host, host, cflags); + ret->content[ret->size].port = currport; ret->size++; } error: diff --git a/src/sockets.c b/src/sockets.c index 4e0b600..f113389 100644 --- a/src/sockets.c +++ b/src/sockets.c @@ -66,6 +66,10 @@ error: return NULL; } +int listenerfd(Listener *listener) { + return listener->fd; +} + Context *createContext(SocketType type, ...) { Context *ret; va_list ap; diff --git a/src/swebs/connections.h b/src/swebs/connections.h index 438e6a3..f467a4e 100644 --- a/src/swebs/connections.h +++ b/src/swebs/connections.h @@ -57,6 +57,8 @@ typedef struct Connection { /* persistent */ size_t currLineAlloc; size_t currLineLen; + + int portind; } Connection; /* * The 2 types of fields: @@ -65,7 +67,7 @@ typedef struct Connection { * request, path, body * */ -int newConnection(Stream *stream, Connection *ret); +int newConnection(Stream *stream, Connection *ret, int portind); /* returns non-zero on error. */ void resetConnection(Connection *conn); void freeConnection(Connection *conn); diff --git a/src/swebs/runner.h b/src/swebs/runner.h index 77f21f4..9a7b2cc 100644 --- a/src/swebs/runner.h +++ b/src/swebs/runner.h @@ -23,6 +23,14 @@ #include #include -void runServer(int connfd, Sitefile *site, Listener *listener, - int *pending, int id); +typedef struct { + int valid; + int portind; +} ConnInfo; + +void runServer(int connfd, Sitefile *site, int *pending, int id, + ConnInfo *info); +/* pending and info are shared memory. pending[id] is the amount of connections + * that are being processed by that process, and info contains info about the + * connection being sent through. */ #endif diff --git a/src/swebs/setup.h b/src/swebs/setup.h index 42d098d..8a74ff4 100644 --- a/src/swebs/setup.h +++ b/src/swebs/setup.h @@ -21,8 +21,8 @@ #include #include -void setup(int argc, char **argv, - Sitefile **site, Listener **listener, int *processes); +void setup(int argc, char **argv, Sitefile **site, int *processes, + int *backlog); /* Setup parses args, utilizes them, and returns only what is needed in the * main loop. */ diff --git a/src/swebs/sitefile.h b/src/swebs/sitefile.h index 56ed686..0030f0b 100644 --- a/src/swebs/sitefile.h +++ b/src/swebs/sitefile.h @@ -28,22 +28,33 @@ typedef enum { LINKED } Command; +typedef struct { + SocketType type; + unsigned short num; + int timeout; + char *key; + char *cert; + /* key and cert are possible unused */ +} Port; + typedef struct { RequestType respondto; regex_t host; Command command; regex_t path; char *arg; + unsigned short port; } SiteCommand; typedef struct { - int size; + size_t size; + size_t alloc; SiteCommand *content; - SocketType type; - char *key; - char *cert; - int timeout; - unsigned short port; + + size_t portcount; + size_t portalloc; + Port *ports; + #if DYNAMIC_LINKED_PAGES int (*getResponse)(Request *, Response *); #endif diff --git a/src/swebs/sockets.h b/src/swebs/sockets.h index 8d09952..2ef8a35 100644 --- a/src/swebs/sockets.h +++ b/src/swebs/sockets.h @@ -45,6 +45,7 @@ typedef struct { int initTLS(); Listener *createListener(uint16_t port, int backlog); +int listenerfd(Listener *listener); Context *createContext(SocketType type, ...); /* * extra arguments depend on type (similar to fcntl): diff --git a/src/swebs/util.h b/src/swebs/util.h index 2cc2267..8622910 100644 --- a/src/swebs/util.h +++ b/src/swebs/util.h @@ -28,6 +28,12 @@ void *saddr(int id); void sfree(void *addr); void sdestroy(int id); +void *xmalloc(size_t size); +void *xrealloc(void *ptr, size_t size); +char *xstrdup(char *str); +/* These functions should only be used during setup (reading sitefiles and such) + * and not real runtime. */ + int createLog(char *msg); int createErrorLog(char *msg, int err); int istrcmp(char *s1, char *s2); diff --git a/src/util.c b/src/util.c index edc203e..dfadf0e 100644 --- a/src/util.c +++ b/src/util.c @@ -57,6 +57,36 @@ void sdestroy(int id) { shmctl(id, IPC_RMID, 0); } +void *xmalloc(size_t size) { + void *ret; + ret = malloc(size); + if (ret == NULL) { + fputs("xmalloc() failed\n", stderr); + exit(EXIT_FAILURE); + } + return ret; +} + +void *xrealloc(void *ptr, size_t size) { + void *ret; + ret = realloc(ptr, size); + if (ret == NULL) { + fputs("xrealloc() failed\n", stderr); + exit(EXIT_FAILURE); + } + return ret; +} + +char *xstrdup(char *str) { + char *ret; + ret = strdup(str); + if (ret == NULL) { + fputs("xstrdup() failed\n", stderr); + exit(EXIT_FAILURE); + } + return ret; +} + int createLog(char *msg) { time_t currenttime; struct tm *timeinfo;