summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--bounce.c55
-rw-r--r--bounce.h12
-rw-r--r--client.c36
4 files changed, 90 insertions, 14 deletions
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 <june@causal.agency>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <err.h>
+#include <stdlib.h>
+#include <sysexits.h>
+
+#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...
+}