Multiple port support
This commit is contained in:
@@ -27,7 +27,7 @@
|
||||
#include <swebs/responses.h>
|
||||
#include <swebs/connections.h>
|
||||
|
||||
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)
|
||||
|
||||
80
src/main.c
80
src/main.c
@@ -20,6 +20,7 @@
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <poll.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
67
src/runner.c
67
src/runner.c
@@ -31,33 +31,42 @@
|
||||
#include <swebs/sitefile.h>
|
||||
#include <swebs/connections.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
14
src/setup.c
14
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);
|
||||
|
||||
|
||||
149
src/sitefile.c
149
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:
|
||||
|
||||
@@ -66,6 +66,10 @@ error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int listenerfd(Listener *listener) {
|
||||
return listener->fd;
|
||||
}
|
||||
|
||||
Context *createContext(SocketType type, ...) {
|
||||
Context *ret;
|
||||
va_list ap;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -23,6 +23,14 @@
|
||||
#include <swebs/sitefile.h>
|
||||
#include <swebs/connections.h>
|
||||
|
||||
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
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
#include <swebs/sockets.h>
|
||||
#include <swebs/sitefile.h>
|
||||
|
||||
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. */
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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);
|
||||
|
||||
30
src/util.c
30
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;
|
||||
|
||||
Reference in New Issue
Block a user