From f2489c89e95c07495768b5401b63ba31ec39d72d Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Mon, 22 Jun 2020 11:29:11 +0200 Subject: Move local handling from server to proxy --- proxy.c | 166 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- proxy.h | 17 +++++++ server.c | 134 +++------------------------------------------------ 3 files changed, 179 insertions(+), 138 deletions(-) diff --git a/proxy.c b/proxy.c index 28a207d..7edfffd 100644 --- a/proxy.c +++ b/proxy.c @@ -1,5 +1,9 @@ #include +#include #include +#include +#include +#include #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; +} + diff --git a/proxy.h b/proxy.h index 0726351..75c078d 100644 --- a/proxy.h +++ b/proxy.h @@ -28,4 +28,21 @@ void proxy_delete(struct server_proxy *proxy); struct server_proxy *proxy_new(struct server *server, struct saddr *client, int fd); +struct server_local { + struct saddr local; + struct saddr client; + struct uring_task task; + + struct server *server; + struct list_head list; +}; + +bool local_open(struct server_local *local); + +void local_refdump(struct server_local *local); + +void local_delete(struct server_local *local); + +struct server_local *local_new(struct server *server, struct saddr *saddr); + #endif diff --git a/server.c b/server.c index ddd4ad4..9290a96 100644 --- a/server.c +++ b/server.c @@ -10,9 +10,6 @@ #include #include #include -#include -#include -#include #include "main.h" #include "uring.h" @@ -24,13 +21,6 @@ #include "rcon.h" #include "systemd.h" -struct server_local { - struct saddr local; - struct saddr client; - struct uring_task task; - struct list_head list; -}; - static bool set_property(struct server *server, char **property, const char *value) { @@ -58,7 +48,7 @@ server_refdump(struct server *server) uring_task_refdump(&server->ann_task); uring_task_refdump(&server->idle_task); list_for_each_entry(local, &server->locals, list) - uring_task_refdump(&local->task); + local_refdump(local); list_for_each_entry(proxy, &server->proxys, list) proxy_refdump(proxy); rcon_refdump(server->rcon); @@ -101,7 +91,7 @@ server_delete(struct server *server) rcon_delete(server); list_for_each_entry_safe(local, ltmp, &server->locals, list) - uring_task_destroy(&local->task); + local_delete(local); list_for_each_entry_safe(proxy, ptmp, &server->proxys, list) proxy_delete(proxy); @@ -186,111 +176,6 @@ server_dump(struct server *server) verbose(""); } -static void -server_local_free(struct uring_task *task) -{ - struct server_local *local = container_of(task, struct server_local, task); - - assert_return(task); - - debug(DBG_SRV, "task %p, local %p", task, local); - list_del(&local->list); - xfree(local); -} - -static void -server_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_SRV, task); - - debug(DBG_SRV, "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, server_local_accept); -} - -static bool -server_local_open(struct server *server, struct server_local *local) -{ - int sfd; - int option; - int r; - - assert_return(server && local, 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, server_local_accept); - return true; - -error: - if (sfd >= 0) - close(sfd); - return false; -} - static void server_exec_free(struct uring_task *task) { @@ -731,9 +616,8 @@ server_commit(struct server *server) /* FIXME: config, dont reread config if server running, make sure fd is available before this is called */ server_dump(server); - list_for_each_entry(local, &server->locals, list) { - server_local_open(server, local); - } + list_for_each_entry(local, &server->locals, list) + local_open(local); server->state = SERVER_STATE_CFG_OK; @@ -762,17 +646,11 @@ server_add_local(struct server *server, struct saddr *saddr) assert_return(server && saddr, false); assert_task_alive_or(DBG_SRV, &server->task, return false); - local = zmalloc(sizeof(*local)); - if (!local) { - error("malloc: %m"); + local = local_new(server, saddr); + if (!local) return false; - } - debug(DBG_SRV, "adding local: %s", saddr->addrstr); - local->local = *saddr; - uring_task_init(&local->task, "local", &server->task, server_local_free); list_add(&local->list, &server->locals); - xfree(saddr); return true; } -- cgit v1.2.3