#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define NUM_WORKAS 5 static void *get_in_addr(struct sockaddr *sa) { if (sa->sa_family == AF_INET) return &(((struct sockaddr_in*)sa)->sin_addr); return &(((struct sockaddr_in6*)sa)->sin6_addr); } struct msg { int pos; char ip[INET6_ADDRSTRLEN]; }; void killWorkas(); void childLife(int); void httpRequest(struct msg *request); pid_t workas_pid[NUM_WORKAS]; int workas_pipes[NUM_WORKAS]; pid_t root_pid; volatile sig_atomic_t deathTried = 0; void childLife(int pipe) { struct msg *m = (struct msg*) malloc(sizeof(struct msg)); pid_t p = getpid(); if (m == NULL) { printf("Couldn't allocate ram for malloc in child %d\n", p); exit(1); } while (read(pipe, (void*)m, sizeof(struct msg)) > 0) { httpRequest(m); } exit(0); } void httpRequest(struct msg *request) { pid_t p = getpid(); printf("Got connection from %s with socket %d on worker %d\n", request->ip, request->pos, p); char buffer[1024]; //char key[100]; //char val[100]; int r; while ((r = recv(request->pos, buffer, 1024, 0)) > 0) { printf("Got stuff: %d\n", r); } //printf("%d\n", r); if (r == -1) { printf("recv error on %d: %s\n", request->pos, strerror(errno)); } //printf("If I would have got stuff, it'd be thar^\n"); close(request->pos); } void sighandler (int signum) { if (getpid() != root_pid) return; if (deathTried == 1) { printf("Dying, as per your request...\n"); killWorkas(); exit(1); } printf("If you really want to die, do it again, \n"); deathTried = 1; } void killWorkas() { unsigned short i; for (i = 0; i < NUM_WORKAS; ++i) kill(workas_pid[i], 9); printf("Workas killed\n"); } int main(int argc, char **argv) { bool daemon = false; unsigned short i; for (i = 0; i < argc; ++i) { if (strcmp(argv[i], "-d") == 0) { daemon = true; } } if (daemon) { if (fork() > 0) { printf("Daemonizing..\n"); exit(1); } } root_pid = getpid(); pid_t j; int pipes[2]; for (i = 0; i < NUM_WORKAS; ++i) { if (pipe(pipes) != 0) { printf("Couldn't do pipess: %d\n", errno); exit(1); } j = fork(); if (j == 0) { close(pipes[1]); childLife(pipes[0]); } else if (j > 0) { workas_pid[i] = j; workas_pipes[i] = pipes[1]; close(pipes[0]); } else if (j < 0) { printf("Couldn't fork: %d\n", errno); exit(1); } } printf("Workas made\n"); if (signal (SIGINT, sighandler) == SIG_IGN) signal (SIGINT, SIG_IGN); if (signal (SIGHUP, sighandler) == SIG_IGN) signal (SIGHUP, SIG_IGN); if (signal (SIGTERM, sighandler) == SIG_IGN) signal (SIGTERM, SIG_IGN); struct addrinfo hints, *res; struct sockaddr_storage their_addr; socklen_t addr_size; int sockfd, clientfd; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; getaddrinfo(NULL, "8080", &hints, &res); sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); int optval = 1; setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval); bind(sockfd, res->ai_addr, res->ai_addrlen); listen(sockfd, 5); i = 0; struct msg *m = NULL; while (1) { m = (struct msg*) malloc(sizeof(struct msg)); i = i == NUM_WORKAS ? 0 : i + 1; addr_size = sizeof their_addr; clientfd = accept(sockfd, (struct sockaddr *)&their_addr, &addr_size); m->pos = clientfd; printf("fd: %d\n", clientfd); inet_ntop(their_addr.ss_family,get_in_addr((struct sockaddr *)&their_addr), m->ip, sizeof m->ip); write(workas_pipes[i], m, sizeof(struct msg)); free(m); m = NULL; } killWorkas(); return 0; }