summaryrefslogtreecommitdiff
path: root/proxy.c
diff options
context:
space:
mode:
authorDavid Härdeman <david@hardeman.nu>2020-06-22 11:29:11 +0200
committerDavid Härdeman <david@hardeman.nu>2020-06-22 11:29:11 +0200
commitf2489c89e95c07495768b5401b63ba31ec39d72d (patch)
tree214d29dffaa20c2fff2fd6672168da83508b1f39 /proxy.c
parent4f9bedb603c772880248914617cee0b44f848290 (diff)
Move local handling from server to proxy
Diffstat (limited to 'proxy.c')
-rw-r--r--proxy.c166
1 files changed, 156 insertions, 10 deletions
diff --git a/proxy.c b/proxy.c
index 28a207d..7edfffd 100644
--- a/proxy.c
+++ b/proxy.c
@@ -1,5 +1,9 @@
#include <stdio.h>
+#include <unistd.h>
#include <time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
#include "main.h"
#include "uring.h"
@@ -7,16 +11,6 @@
#include "proxy.h"
#include "utils.h"
-void
-proxy_refdump(struct server_proxy *proxy)
-{
- assert_return(proxy);
-
- uring_task_refdump(&proxy->task);
- uring_task_refdump(&proxy->clienttask);
- uring_task_refdump(&proxy->servertask);
-}
-
static void
format_bytes(char *buf, size_t len, uint64_t val)
{
@@ -239,6 +233,16 @@ proxy_connected_cb(struct connection *conn, bool connected)
uring_tbuf_read(&proxy->servertask, proxy_server_data_in);
}
+void
+proxy_refdump(struct server_proxy *proxy)
+{
+ assert_return(proxy);
+
+ uring_task_refdump(&proxy->task);
+ uring_task_refdump(&proxy->clienttask);
+ uring_task_refdump(&proxy->servertask);
+}
+
struct server_proxy *
proxy_new(struct server *server, struct saddr *client, int fd)
{
@@ -276,3 +280,145 @@ proxy_new(struct server *server, struct saddr *client, int fd)
return proxy;
}
+static void
+local_accept(struct uring_task *task, int res)
+{
+ struct server_local *local = container_of(task, struct server_local, task);
+ struct server *server = container_of(task->parent, struct server, task);
+ struct server_proxy *proxy;
+
+ assert_return(task);
+ assert_task_alive(DBG_PROXY, task);
+
+ debug(DBG_PROXY, "task %p, res %i, server %s", task, res, server->name);
+
+ if (res < 0) {
+ error("result was %i", res);
+ goto out;
+ }
+
+ saddr_set_addrstr(&local->client);
+
+ verbose("%s: incoming proxy connection: %s -> %s",
+ server->name, local->client.addrstr, local->local.addrstr);
+
+ if (list_empty(&server->remotes)) {
+ /* This shouldn't be possible, checked before opening local */
+ error("server->remotes empty!");
+ uring_close(&local->task, res);
+ goto out;
+ }
+
+ proxy = proxy_new(server, &local->client, res);
+ if (!proxy)
+ uring_close(&local->task, res);
+
+out:
+ uring_accept(&local->task, &local->client, local_accept);
+}
+
+bool
+local_open(struct server_local *local)
+{
+ int sfd;
+ int option;
+ int r;
+
+ assert_return(local && local->server, false);
+
+ sfd = socket(local->local.storage.ss_family, SOCK_STREAM | SOCK_CLOEXEC, 0);
+ if (sfd < 0) {
+ error("socket: %m");
+ goto error;
+ }
+
+ option = true;
+ if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option)) < 0) {
+ error("setsockopt: %m");
+ goto error;
+ }
+
+ /* The MC protocol expects the client to send data first */
+ /* FIXME: could make this configurable */
+ option = true;
+ if (setsockopt(sfd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &option, sizeof(option)) < 0)
+ error("setsockopt: %m");
+
+ /* FIXME: could make this configurable */
+ option = true;
+ if (setsockopt(sfd, IPPROTO_IP, IP_FREEBIND, &option, sizeof(option)) < 0)
+ error("setsockopt: %m");
+
+ socket_set_low_latency(sfd);
+
+ r = bind(sfd, (struct sockaddr *)&local->local.storage, local->local.addrlen);
+ if (r < 0) {
+ error("bind: %m");
+ goto error;
+ }
+
+ r = listen(sfd, 100);
+ if (r < 0) {
+ error("listen: %m");
+ goto error;
+ }
+
+ uring_task_set_fd(&local->task, sfd);
+ uring_accept(&local->task, &local->client, local_accept);
+ return true;
+
+error:
+ if (sfd >= 0)
+ uring_close(&local->task, sfd);
+ return false;
+}
+
+void
+local_refdump(struct server_local *local)
+{
+ assert_return(local);
+
+ uring_task_refdump(&local->task);
+}
+
+static void
+local_free(struct uring_task *task)
+{
+ struct server_local *local = container_of(task, struct server_local, task);
+
+ assert_return(task);
+
+ debug(DBG_PROXY, "task %p, local %p", task, local);
+ list_del(&local->list);
+ xfree(local);
+}
+
+void
+local_delete(struct server_local *local)
+{
+ assert_return(local);
+
+ uring_task_destroy(&local->task);
+}
+
+struct server_local *
+local_new(struct server *server, struct saddr *saddr)
+{
+ struct server_local *local;
+
+ assert_return(server && saddr, NULL);
+
+ local = zmalloc(sizeof(*local));
+ if (!local) {
+ error("malloc: %m");
+ return NULL;
+ }
+
+ debug(DBG_PROXY, "%s adding local: %s", server->name, saddr->addrstr);
+ local->local = *saddr;
+ local->server = server;
+ uring_task_init(&local->task, "local", &server->task, local_free);
+ xfree(saddr);
+ return local;
+}
+