ADDED .fossil-settings/ignore-glob Index: .fossil-settings/ignore-glob ================================================================== --- /dev/null +++ .fossil-settings/ignore-glob @@ -0,0 +1,2 @@ +filed +filed.o ADDED Makefile Index: Makefile ================================================================== --- /dev/null +++ Makefile @@ -0,0 +1,14 @@ +CC = gcc +CFLAGS = -Wall -Werror -W -pthread -O3 +LDFLAGS = -pthread +LIBS = -lpthread + +filed: filed.o +filed.o: filed.c + +clean: + rm -f filed filed.o + +distclean: clean + +.PHONY: clean distclean ADDED filed.c Index: filed.c ================================================================== --- /dev/null +++ filed.c @@ -0,0 +1,174 @@ +#include +#include +#include +#include +#include +#include +#include + +/* Default values */ +#define MAX_FAILURE_COUNT 30 +#define PORT 8080 +#define THREAD_COUNT 10 +#define BIND_ADDR "::" + +/* Arguments for worker threads */ +struct filed_worker_thread_args { + int fd; +}; + +static void filed_init(void) { + mlockall(MCL_CURRENT | MCL_FUTURE); +} + +static int filed_listen(const char *address, unsigned int port) { + struct sockaddr_in6 addr; + int pton_ret, bind_ret, listen_ret; + int fd; + + addr.sin6_family = AF_INET6; + addr.sin6_flowinfo = 0; + addr.sin6_scope_id = 0; + addr.sin6_port = htons(port); + pton_ret = inet_pton(AF_INET6, address, addr.sin6_addr.s6_addr); + if (pton_ret != 1) { + return(-1); + } + + fd = socket(AF_INET6, SOCK_STREAM, 0); + if (fd < 0) { + return(fd); + } + + bind_ret = bind(fd, (const struct sockaddr *) &addr, sizeof(addr)); + if (bind_ret < 0) { + close(fd); + + return(-1); + } + + listen_ret = listen(fd, 128); + if (listen_ret != 0) { + close(fd); + + return(-1); + } + + return(fd); +} + +static int filed_logging_thread_init(void) { + /* XXX:TODO: Unimplemented */ + return(0); +} + +static void filed_handle_client(int fd) { + /* XXX:TODO: Unimplemented */ + fd = fd; + return; +} + +static void *filed_worker_thread(void *arg_v) { + struct filed_worker_thread_args *arg; + struct sockaddr_in6 addr; + socklen_t addrlen; + int failure_count = 0, max_failure_count = MAX_FAILURE_COUNT; + int master_fd, fd; + + /* Read arguments */ + arg = arg_v; + + master_fd = arg->fd; + + while (1) { + /* Failure loop prevention */ + if (failure_count > max_failure_count) { + break; + } + + /* Accept a new client */ + addrlen = sizeof(addr); + fd = accept(master_fd, (struct sockaddr *) &addr, &addrlen); + + /* + * If we fail, make a note of it so we don't go into a loop of + * accept() failing + */ + if (fd < 0) { + failure_count++; + + continue; + } + + /* Reset failure count*/ + failure_count = 0; + + /* Handle socket */ + filed_handle_client(fd); + + /* Cleanup */ + close(fd); + } + + /* XXX:TODO: Report error */ + return(NULL); +} + +static int filed_worker_threads_init(int fd, int thread_count) { + struct filed_worker_thread_args *arg; + pthread_t threadid; + int pthread_ret; + int i; + + for (i = 0; i < thread_count; i++) { + arg = malloc(sizeof(*arg)); + + arg->fd = fd; + + pthread_ret = pthread_create(&threadid, NULL, filed_worker_thread, arg); + if (pthread_ret != 0) { + return(-1); + } + } + + return(0); +} + +int main(int argc, char **argv) { + int port = PORT, thread_count = THREAD_COUNT; + const char *bind_addr = BIND_ADDR; + int fd; + + /* Ignore */ + argc = argc; + argv = argv; + + /* Create listening socket */ + fd = filed_listen(bind_addr, port); + if (fd < 0) { + return(1); + } + + /* Become a daemon */ + /* XXX:TODO: Become a daemon */ + + /* Initialize */ + filed_init(); + + /* Create logging thread */ + /* XXX:TODO: Check for errors */ + filed_logging_thread_init(); + + /* Create worker threads */ + /* XXX:TODO: Check for errors */ + filed_worker_threads_init(fd, thread_count); + + /* Wait for threads to exit */ + /* XXX:TODO: Monitor thread usage */ + while (1) { + sleep(60); + } + + /* Return in failure */ + return(2); +}