Got it working for http
This commit is contained in:
165
src/main.c
165
src/main.c
@@ -20,10 +20,13 @@
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/un.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <swebs/util.h>
|
||||
#include <swebs/setup.h>
|
||||
@@ -31,15 +34,91 @@
|
||||
#include <swebs/sockets.h>
|
||||
#include <swebs/sitefile.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
Sitefile *site;
|
||||
Listener *listener;
|
||||
int processes;
|
||||
typedef struct {
|
||||
pid_t pid;
|
||||
int fd;
|
||||
} Runner;
|
||||
|
||||
int *pending, pendingid, (*notify)[2];
|
||||
pthread_t *threads;
|
||||
static Runner *runners;
|
||||
static int processes;
|
||||
static int mainfd;
|
||||
static int *pending;
|
||||
static Listener *listener;
|
||||
static Sitefile *site;
|
||||
static struct sockaddr_un addr;
|
||||
/* We want to be able to handle a signal at any time, so some global variables
|
||||
* are needed. */
|
||||
|
||||
static void createProcess(int id) {
|
||||
pid_t pid;
|
||||
int connfd;
|
||||
socklen_t addrlen;
|
||||
|
||||
createLog("Creating a new process");
|
||||
pending[id] = 0;
|
||||
|
||||
pid = fork();
|
||||
switch (pid) {
|
||||
case -1:
|
||||
createLog("fork() failed");
|
||||
exit(EXIT_FAILURE);
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
addrlen = sizeof(addr);
|
||||
runners[id].pid = pid;
|
||||
runners[id].fd = accept(mainfd,
|
||||
(struct sockaddr *) &addr, &addrlen);
|
||||
return;
|
||||
}
|
||||
|
||||
connfd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (connfd < 0)
|
||||
exit(EXIT_FAILURE);
|
||||
if (connect(connfd, (struct sockaddr *) &addr, sizeof(addr))) {
|
||||
createLog("connect() failed, killing child");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
close(mainfd);
|
||||
runServer(connfd, site, listener, pending, id);
|
||||
createLog("child runServer() finished");
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
static void remakeChild(int signal) {
|
||||
pid_t pid;
|
||||
int i;
|
||||
pid = wait(NULL);
|
||||
createLog("A child has died, recreating");
|
||||
for (i = 0; i < processes - 1; i++) {
|
||||
if (runners[i].pid == pid) {
|
||||
close(runners[i].fd);
|
||||
createProcess(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void exitClean(int signal) {
|
||||
freeListener(listener);
|
||||
close(mainfd);
|
||||
remove(addr.sun_path);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
static void setsignal(int signal, void (*handler)(int)) {
|
||||
struct sigaction action;
|
||||
sigset_t sigset;
|
||||
sigemptyset(&sigset);
|
||||
action.sa_handler = handler;
|
||||
action.sa_mask = sigset;
|
||||
action.sa_flags = SA_NODEFER;
|
||||
sigaction(SIGCHLD, &action, NULL);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int i;
|
||||
int pendingid;
|
||||
|
||||
setup(argc, argv, &site, &listener, &processes);
|
||||
|
||||
@@ -48,63 +127,53 @@ int main(int argc, char **argv) {
|
||||
createLog("smalloc() failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
pending = saddr(pendingid);;
|
||||
pending = saddr(pendingid);
|
||||
if (pending == NULL) {
|
||||
createLog("saddr() failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
memset(pending, 0, sizeof(int) * (processes - 1));
|
||||
|
||||
notify = malloc(sizeof(int[2]) * (processes - 1));
|
||||
if (notify == NULL) {
|
||||
createLog("malloc() failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
mainfd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
addr.sun_family = AF_UNIX;
|
||||
strncpy(addr.sun_path, tmpnam(NULL), sizeof(addr.sun_path) - 1);
|
||||
/* I know that tmpname is deprecated, I think this usage is safe
|
||||
* though. */
|
||||
addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
|
||||
bind(mainfd, (struct sockaddr *) &addr, sizeof(addr));
|
||||
listen(mainfd, processes);
|
||||
|
||||
threads = malloc(sizeof(pthread_t) * (processes - 1));
|
||||
if (threads == NULL) {
|
||||
createLog("malloc() failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
runners = malloc(sizeof(Runner) * (processes - 1));
|
||||
for (i = 0; i < processes - 1; i++)
|
||||
createProcess(i);
|
||||
|
||||
for (i = 0; i < processes - 1; i++) {
|
||||
RunnerArgs *args = malloc(sizeof(RunnerArgs));
|
||||
if (args == NULL) {
|
||||
createLog("malloc() failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (pipe(notify[i])) {
|
||||
createLog("pipe() failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
args->site = site;
|
||||
args->pendingid = pendingid;
|
||||
args->notify = notify[i][0];
|
||||
args->id = i;
|
||||
pthread_create(threads + i, NULL,
|
||||
(void*(*)(void*)) runServer, args);
|
||||
}
|
||||
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
setsignal(SIGPIPE, SIG_IGN);
|
||||
setsignal(SIGKILL, exitClean);
|
||||
setsignal(SIGINT, exitClean);
|
||||
setsignal(SIGCHLD, remakeChild);
|
||||
|
||||
createLog("swebs started");
|
||||
|
||||
for (;;) {
|
||||
Stream *stream = acceptStream(listener, O_NONBLOCK);
|
||||
int lowestThread;
|
||||
createLog("Accepted stream");
|
||||
if (stream == NULL) {
|
||||
createLog("Accepting a stream failed");
|
||||
int fd;
|
||||
int lowestProc;
|
||||
|
||||
fd = accept(listener->fd, (struct sockaddr *) &listener->addr,
|
||||
&listener->addrlen);
|
||||
if (fd < 0) {
|
||||
if (errno == ENOTSOCK || errno == EOPNOTSUPP ||
|
||||
errno == EINVAL) {
|
||||
createLog("You've majorly screwed up");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
createLog("Accepted stream");
|
||||
|
||||
lowestThread = 0;
|
||||
lowestProc = 0;
|
||||
for (i = 1; i < processes - 1; i++)
|
||||
if (pending[i] < pending[lowestThread])
|
||||
lowestThread = i;
|
||||
if (write(notify[lowestThread][1], &stream, sizeof(&stream))
|
||||
< sizeof(&stream))
|
||||
continue;
|
||||
if (pending[i] < pending[lowestProc])
|
||||
lowestProc = i;
|
||||
sendFd(fd, runners[lowestProc].fd);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user