diff options
| author | Xavier Del Campo Romero <xavi.dcr@tutanota.com> | 2023-07-21 01:07:57 +0200 |
|---|---|---|
| committer | Xavier Del Campo Romero <xavi.dcr@tutanota.com> | 2023-07-21 01:40:55 +0200 |
| commit | 7fe639b3ba7a253627d2cd34f3b97bd95b0a90b3 (patch) | |
| tree | ab50067686bfdc87b35ddfa29112af5ca0440574 /server.c | |
| parent | 1d4480c0f36f9d4e75c00e58c065b4c43e53b4f3 (diff) | |
| download | slcl-7fe639b3ba7a253627d2cd34f3b97bd95b0a90b3.tar.gz | |
Remove files now provided by slweb
Diffstat (limited to 'server.c')
| -rw-r--r-- | server.c | 373 |
1 files changed, 0 insertions, 373 deletions
diff --git a/server.c b/server.c deleted file mode 100644 index 22615b2..0000000 --- a/server.c +++ /dev/null @@ -1,373 +0,0 @@ -#define _POSIX_C_SOURCE 200809L - -#include "server.h" -#include <fcntl.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <poll.h> -#include <unistd.h> -#include <errno.h> -#include <signal.h> -#include <stdbool.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -struct server -{ - int fd; - - struct server_client - { - int fd; - bool write; - struct server_client *prev, *next; - } *c; -}; - -int server_close(struct server *const s) -{ - int ret = 0; - - if (!s) - return 0; - else if (s->fd >= 0) - ret = close(s->fd); - - free(s); - return ret; -} - -int server_client_close(struct server *const s, struct server_client *const c) -{ - int ret = 0; - - for (struct server_client *ref = s->c; ref; ref = ref->next) - { - if (c == ref) - { - struct server_client *const next = ref->next; - - if ((ret = close(c->fd))) - { - fprintf(stderr, "%s: close(2): %s\n", - __func__, strerror(errno)); - return -1; - } - else if (ref->prev) - ref->prev->next = next; - else - s->c = next; - - if (next) - next->prev = ref->prev; - - free(ref); - break; - } - } - - return ret; -} - -int server_read(void *const buf, const size_t n, struct server_client *const c) -{ - const ssize_t r = read(c->fd, buf, n); - - if (r < 0) - fprintf(stderr, "%s: read(2): %s\n", __func__, strerror(errno)); - - return r; -} - -int server_write(const void *const buf, const size_t n, - struct server_client *const c) -{ - const ssize_t w = write(c->fd, buf, n); - - if (w < 0) - fprintf(stderr, "%s: write(2): %s\n", __func__, strerror(errno)); - - return w; -} - -static struct server_client *alloc_client(struct server *const s) -{ - struct sockaddr_in addr; - socklen_t sz = sizeof addr; - const int fd = accept(s->fd, (struct sockaddr *)&addr, &sz); - - if (fd < 0) - { - fprintf(stderr, "%s: accept(2): %s\n", - __func__, strerror(errno)); - return NULL; - } - - const int flags = fcntl(fd, F_GETFL); - - if (flags < 0) - { - fprintf(stderr, "%s: fcntl(2) F_GETFL: %s\n", - __func__, strerror(errno)); - return NULL; - } - else if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) - { - fprintf(stderr, "%s: fcntl(2) F_SETFL: %s\n", - __func__, strerror(errno)); - return NULL; - } - - struct server_client *const c = malloc(sizeof *c); - - if (!c) - { - fprintf(stderr, "%s: malloc(3): %s\n", __func__, strerror(errno)); - return NULL; - } - - *c = (const struct server_client) - { - .fd = fd - }; - - if (!s->c) - s->c = c; - else - for (struct server_client *ref = s->c; ref; ref = ref->next) - if (!ref->next) - { - ref->next = c; - c->prev = ref; - break; - } - - return c; -} - -void server_client_write_pending(struct server_client *const c, - const bool write) -{ - c->write = write; -} - -static volatile sig_atomic_t do_exit; - -static void handle_signal(const int signum) -{ - switch (signum) - { - case SIGINT: - /* Fall through. */ - case SIGTERM: - do_exit = 1; - break; - - default: - break; - } -} - -static size_t get_clients(const struct server *const s) -{ - size_t ret = 0; - - for (const struct server_client *c = s->c; c; c = c->next) - ret++; - - return ret; -} - -struct server_client *server_poll(struct server *const s, bool *const io, - bool *const exit) -{ - struct server_client *ret = NULL; - const size_t n_clients = get_clients(s); - const nfds_t n = n_clients + 1; - struct pollfd *const fds = malloc(n * sizeof *fds); - - if (!fds) - { - fprintf(stderr, "%s: malloc(3): %s\n", __func__, strerror(errno)); - goto end; - } - - struct pollfd *const sfd = &fds[0]; - - *io = *exit = false; - *sfd = (const struct pollfd) - { - .fd = s->fd, - .events = POLLIN - }; - - for (struct {const struct server_client *c; size_t j;} - _ = {.c = s->c, .j = 1}; _.c; _.c = _.c->next, _.j++) - { - struct pollfd *const p = &fds[_.j]; - const int fd = _.c->fd; - - *p = (const struct pollfd) - { - .fd = fd, - .events = POLLIN - }; - - if (_.c->write) - p->events |= POLLOUT; - } - - int res; - -again: - - res = poll(fds, n, -1); - - if (res < 0) - { - if (do_exit) - { - *exit = true; - goto end; - } - - switch (errno) - { - case EAGAIN: - /* Fall through. */ - case EINTR: - goto again; - - default: - fprintf(stderr, "%s: poll(2): %s\n", __func__, strerror(errno)); - break; - } - - goto end; - } - else if (!res) - { - fprintf(stderr, "%s: poll(2) returned zero\n", __func__); - goto end; - } - else if (sfd->revents) - { - ret = alloc_client(s); - goto end; - } - - for (struct {struct server_client *c; size_t j;} - _ = {.c = s->c, .j = 1}; _.c; _.c = _.c->next, _.j++) - { - const struct pollfd *const p = &fds[_.j]; - - if (p->revents) - { - *io = true; - ret = _.c; - goto end; - } - } - - fprintf(stderr, "%s: unlisted fd\n", __func__); - -end: - free(fds); - return ret; -} - -static int init_signals(void) -{ - struct sigaction sa = - { - .sa_handler = handle_signal, - .sa_flags = SA_RESTART - }; - - sigemptyset(&sa.sa_mask); - - if (sigaction(SIGINT, &sa, NULL)) - { - fprintf(stderr, "%s: sigaction(2) SIGINT: %s\n", - __func__, strerror(errno)); - return -1; - } - else if (sigaction(SIGTERM, &sa, NULL)) - { - fprintf(stderr, "%s: sigaction(2) SIGTERM: %s\n", - __func__, strerror(errno)); - return -1; - } - else if (sigaction(SIGPIPE, &sa, NULL)) - { - fprintf(stderr, "%s: sigaction(2) SIGPIPE: %s\n", - __func__, strerror(errno)); - return -1; - } - - return 0; -} - -struct server *server_init(const unsigned short port) -{ - struct server *const s = malloc(sizeof *s); - - if (!s) - { - fprintf(stderr, "%s: malloc(3): %s\n", __func__, strerror(errno)); - goto failure; - } - - *s = (const struct server) - { - .fd = socket(AF_INET, SOCK_STREAM, 0) - }; - - if (s->fd < 0) - { - fprintf(stderr, "%s: socket(2): %s\n", __func__, strerror(errno)); - goto failure; - } - else if (init_signals()) - { - fprintf(stderr, "%s: init_signals failed\n", __func__); - goto failure; - } - - const struct sockaddr_in addr = - { - .sin_family = AF_INET, - .sin_port = htons(port) - }; - - enum {QUEUE_LEN = 10}; - - if (bind(s->fd, (const struct sockaddr *)&addr, sizeof addr)) - { - fprintf(stderr, "%s: bind(2): %s\n", __func__, strerror(errno)); - goto failure; - } - else if (listen(s->fd, QUEUE_LEN)) - { - fprintf(stderr, "%s: listen(2): %s\n", __func__, strerror(errno)); - goto failure; - } - - struct sockaddr_in in; - socklen_t sz = sizeof in; - - if (getsockname(s->fd, (struct sockaddr *)&in, &sz)) - { - fprintf(stderr, "%s: getsockname(2): %s\n", __func__, strerror(errno)); - goto failure; - } - - printf("Listening on port %hu\n", ntohs(in.sin_port)); - return s; - -failure: - server_close(s); - return NULL; -} |
