From 954707da7d4b96710965e44d8ca3bff24067e4df Mon Sep 17 00:00:00 2001 From: Curtis McEnroe Date: Wed, 23 Oct 2019 01:23:38 -0400 Subject: Add dynamic poll list --- Makefile | 1 + bounce.c | 55 +++++++++++++++++++++++++++++++++++++++++++------------ bounce.h | 12 ++++++++++-- client.c | 36 ++++++++++++++++++++++++++++++++++++ 4 files changed, 90 insertions(+), 14 deletions(-) create mode 100644 client.c diff --git a/Makefile b/Makefile index 72d0f05..9c1e805 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,7 @@ LDLIBS = -ltls -include config.mk OBJS += bounce.o +OBJS += client.o OBJS += listen.o OBJS += server.o OBJS += state.o diff --git a/bounce.c b/bounce.c index ec89945..3e30d0c 100644 --- a/bounce.c +++ b/bounce.c @@ -27,6 +27,32 @@ #include "bounce.h" +static struct { + size_t cap, len; + struct pollfd *fds; + struct Client **clients; +} loop; + +static void loopAdd(int fd, struct Client *client) { + if (loop.len == loop.cap) { + loop.cap *= 2; + loop.fds = realloc(loop.fds, sizeof(struct pollfd) * loop.cap); + loop.clients = realloc(loop.clients, sizeof(struct Client *) * loop.cap); + if (!loop.fds || !loop.clients) err(EX_OSERR, "realloc"); + } + + loop.fds[loop.len].fd = fd; + loop.fds[loop.len].events = POLLIN; + loop.clients[loop.len] = client; + loop.len++; +} + +static void loopRemove(size_t i) { + loop.fds[i] = loop.fds[loop.len - 1]; + loop.clients[i] = loop.clients[loop.len - 1]; + loop.len--; +} + static char *censor(char *arg) { char *dup = strdup(arg); if (!dup) err(EX_OSERR, "strdup"); @@ -103,20 +129,25 @@ int main(int argc, char *argv[]) { for (size_t i = 0; i < bindLen; ++i) { int error = listen(bind[i], 1); if (error) err(EX_IOERR, "listen"); + loopAdd(bind[i], NULL); } + loopAdd(server, NULL); - // Wishing for struct-of-arrays... - struct pollfd fds[BindCap]; - for (size_t i = 0; i < bindLen; ++i) { - fds[i].fd = bind[i]; - fds[i].events = POLLIN; - } - - while (0 < poll(fds, bindLen, -1)) { - for (size_t i = 0; i < bindLen; ++i) { - if (!fds[i].revents) continue; - struct tls *client; - int fd = listenAccept(&client, fds[i].fd); + while (0 < poll(loop.fds, loop.len, -1)) { + for (size_t i = 0; i < loop.len; ++i) { + if (!loop.fds[i].revents) continue; + if (i < bindLen) { + struct Client *client = clientAlloc(); + loopAdd(listenAccept(&client->tls, loop.fds[i].fd), client); + } else if (!loop.clients[i]) { + serverRecv(); + } else if (loop.fds[i].revents & POLLERR) { + close(loop.fds[i].fd); + clientFree(loop.clients[i]); + loopRemove(i); + } else { + clientRecv(loop.clients[i]); + } } } } diff --git a/bounce.h b/bounce.h index e442e47..2c3daa3 100644 --- a/bounce.h +++ b/bounce.h @@ -26,10 +26,17 @@ #define DEFAULT_PRIV_PATH "/usr/local/etc/letsencrypt/live/%s/privkey.pem" #endif +struct Client { + struct tls *tls; +}; + void listenConfig(const char *cert, const char *priv); size_t listenBind(int fds[], size_t cap, const char *host, const char *port); int listenAccept(struct tls **client, int fd); +bool stateReady(void); +void stateParse(char *line); + int serverConnect(const char *host, const char *port); void serverLogin( const char *pass, const char *auth, @@ -40,5 +47,6 @@ void serverJoin(const char *join); void serverSend(const char *ptr, size_t len); void serverRecv(void); -bool stateReady(void); -void stateParse(char *line); +struct Client *clientAlloc(void); +void clientFree(struct Client *client); +void clientRecv(struct Client *client); diff --git a/client.c b/client.c new file mode 100644 index 0000000..d012b28 --- /dev/null +++ b/client.c @@ -0,0 +1,36 @@ +/* Copyright (C) 2019 C. McEnroe + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +#include "bounce.h" + +struct Client *clientAlloc(void) { + struct Client *client = calloc(1, sizeof(*client)); + if (!client) err(EX_OSERR, "calloc"); + return client; +} + +void clientFree(struct Client *client) { + tls_free(client->tls); + free(client); +} + +void clientRecv(struct Client *client) { + // TODO... +} -- cgit 1.4.1