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;