summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--idle.c2
-rw-r--r--main.h1
-rw-r--r--proxy.c61
-rw-r--r--proxy.h1
-rw-r--r--rcon.c2
-rw-r--r--server.c2
-rw-r--r--utils.c94
-rw-r--r--utils.h101
8 files changed, 167 insertions, 97 deletions
diff --git a/idle.c b/idle.c
index 8f2530a..808c25f 100644
--- a/idle.c
+++ b/idle.c
@@ -361,7 +361,7 @@ again:
goto again;
}
- socket_set_gaming_options(cfg, sfd);
+ socket_set_low_latency(cfg, sfd);
uring_task_set_fd(&idle->idlecheck, sfd);
uring_connect(cfg, &idle->idlecheck, &idle->remote, idle_check_remote_connected);
diff --git a/main.h b/main.h
index 578c8d7..ec4cd2a 100644
--- a/main.h
+++ b/main.h
@@ -44,6 +44,7 @@ struct uring_task {
callback_t callback;
rcallback_t complete_callback; /* to check if tbuf processing is done */
callback_t final_callback; /* once tbuf processing is done */
+ void *priv;
};
struct cfg {
diff --git a/proxy.c b/proxy.c
index 6b724f2..58f81ca 100644
--- a/proxy.c
+++ b/proxy.c
@@ -179,70 +179,27 @@ proxy_server_data_in(struct cfg *cfg, struct uring_task *task, int res)
uring_tbuf_write(cfg, task, proxy_server_data_out);
}
-static void proxy_connect_next_remote(struct cfg *cfg, struct server_proxy *proxy);
-
static void
-proxy_server_connected(struct cfg *cfg, struct uring_task *task, int res)
+proxy_connected_cb(struct cfg *cfg, struct connection *conn, int res)
{
- struct server_proxy *proxy = container_of(task, struct server_proxy, servertask);
+ struct server_proxy *proxy = container_of(conn, struct server_proxy, server_conn);
- fprintf(stderr, "%s: connected %i\n", __func__, res);
if (res < 0) {
- uring_task_close_fd(cfg, task);
- proxy_connect_next_remote(cfg, proxy);
+ fprintf(stderr, "%s: proxy connection to remote server failed\n",
+ proxy->scfg->name);
+ proxy_delete(cfg, proxy);
return;
}
+ proxy->sfd = proxy->servertask.fd;
fprintf(stderr, "%s: proxy connection %s -> %s opened\n",
- proxy->scfg->name, proxy->clientstr, proxy->serverstr);
+ proxy->scfg->name, proxy->clientstr, proxy->server_conn.remotestr);
proxy->begin = time(NULL);
+
uring_tbuf_read(cfg, &proxy->clienttask, proxy_client_data_in);
uring_tbuf_read(cfg, &proxy->servertask, proxy_server_data_in);
}
-static void
-proxy_connect_next_remote(struct cfg *cfg, struct server_proxy *proxy)
-{
- struct sockaddr_in46 *remote, *tmp;
- struct server *scfg = proxy->scfg;
- int sfd;
- unsigned i = 0;
-
-again:
- remote = NULL;
- list_for_each_entry(tmp, &scfg->remotes, list) {
- if (i == proxy->next_remote) {
- remote = tmp;
- break;
- }
- i++;
- }
-
- if (!remote) {
- fprintf(stderr, "No more remote addresses to attempt\n");
- proxy_delete(cfg, proxy);
- return;
- }
-
- proxy->next_remote++;
- proxy->server = *remote;
- sockaddr_to_str(&proxy->server, proxy->serverstr, sizeof(proxy->serverstr));
- fprintf(stderr, "%s: attempting proxy connection to %s (len %u)\n",
- scfg->name, proxy->serverstr, proxy->server.addrlen);
-
- sfd = socket(proxy->server.storage.ss_family, SOCK_STREAM | SOCK_CLOEXEC, 0);
- if (sfd < 0) {
- perror("socket");
- goto again;
- }
-
- socket_set_gaming_options(cfg, sfd);
-
- proxy->sfd = sfd;
- uring_task_set_fd(&proxy->servertask, sfd);
- uring_connect(cfg, &proxy->servertask, &proxy->server, proxy_server_connected);
-}
-
struct server_proxy *
proxy_new(struct cfg *cfg, struct server *scfg, struct sockaddr_in46 *client, int fd)
{
@@ -269,7 +226,7 @@ proxy_new(struct cfg *cfg, struct server *scfg, struct sockaddr_in46 *client, in
uring_task_set_buf(&proxy->servertask, &proxy->serverbuf);
list_add(&proxy->list, &scfg->proxys);
- proxy_connect_next_remote(cfg, proxy);
+ connect_any(cfg, &proxy->servertask, &scfg->remotes, &proxy->server_conn, proxy_connected_cb);
return proxy;
}
diff --git a/proxy.h b/proxy.h
index 735a12e..6b6e265 100644
--- a/proxy.h
+++ b/proxy.h
@@ -9,6 +9,7 @@ struct server_proxy {
uint64_t client_bytes;
int cfd;
+ struct connection server_conn;
struct sockaddr_in46 server;
char serverstr[ADDRSTRLEN];
struct uring_task_buf serverbuf;
diff --git a/rcon.c b/rcon.c
index 4229527..5476160 100644
--- a/rcon.c
+++ b/rcon.c
@@ -372,7 +372,7 @@ again:
goto again;
}
- socket_set_gaming_options(cfg, sfd);
+ socket_set_low_latency(cfg, sfd);
uring_task_set_fd(&rcon->task, sfd);
uring_connect(cfg, &rcon->task, &rcon->rcon, rcon_connected);
diff --git a/server.c b/server.c
index 2469608..aa865ac 100644
--- a/server.c
+++ b/server.c
@@ -251,7 +251,7 @@ server_local_open(struct cfg *cfg, struct server *scfg, struct server_local *loc
if (setsockopt(sfd, IPPROTO_IP, IP_FREEBIND, &option, sizeof(option)) < 0)
perror("setsockopt");
- socket_set_gaming_options(cfg, sfd);
+ socket_set_low_latency(cfg, sfd);
r = bind(sfd, (struct sockaddr *)&local->addr.storage, local->addr.addrlen);
if (r < 0) {
diff --git a/utils.c b/utils.c
index 0718ea9..8749c75 100644
--- a/utils.c
+++ b/utils.c
@@ -164,7 +164,7 @@ debug_resource_usage()
}
void
-socket_set_gaming_options(struct cfg *cfg, int sfd)
+socket_set_low_latency(struct cfg *cfg, int sfd)
{
int option;
@@ -187,6 +187,98 @@ socket_set_gaming_options(struct cfg *cfg, int sfd)
perror("setsockopt");
}
+static void
+connection_set_local_addr(struct cfg *cfg, struct connection *conn, int fd)
+{
+ if (fd < 0 || getsockname(fd, (struct sockaddr *)&conn->local.storage,
+ &conn->local.addrlen) < 0)
+ sprintf(conn->localstr, "<unknown>");
+ else
+ sockaddr_to_str(&conn->local, conn->localstr, sizeof(conn->localstr));
+}
+
+static void connect_next(struct cfg *cfg, struct uring_task *task, struct connection *conn);
+
+static void
+connect_cb(struct cfg *cfg, struct uring_task *task, int res)
+{
+ struct connection *conn = task->priv;
+
+ if (res < 0) {
+ fprintf(stderr, "%s: connection to %s failed\n",
+ __func__, conn->remotestr);
+ uring_task_close_fd(cfg, task);
+ connect_next(cfg, task, conn);
+ return;
+ }
+
+ connection_set_local_addr(cfg, conn, task->fd);
+
+ fprintf(stderr, "%s: (%s) connection established %s -> %s\n",
+ __func__, task->name, conn->localstr, conn->remotestr);
+
+ conn->callback(cfg, conn, true);
+}
+
+static void
+connect_next(struct cfg *cfg, struct uring_task *task, struct connection *conn)
+{
+ struct sockaddr_in46 *remote, *tmp;
+ int sfd;
+ unsigned i;
+
+again:
+ i = 0;
+ remote = NULL;
+ list_for_each_entry(tmp, conn->addrs, list) {
+ if (i == conn->next_addr) {
+ remote = tmp;
+ break;
+ }
+ i++;
+ }
+
+ if (!remote) {
+ fprintf(stderr, "%s: no more remote addresses to attempt\n", __func__);
+ conn->callback(cfg, conn, false);
+ return;
+ }
+
+ conn->next_addr++;
+ conn->remote = *remote;
+ sockaddr_to_str(&conn->remote, conn->remotestr, sizeof(conn->remotestr));
+ fprintf(stderr, "%s: attempting to connect to %s\n",
+ task->name, conn->remotestr);
+
+ sfd = socket(conn->remote.storage.ss_family, SOCK_STREAM | SOCK_CLOEXEC, 0);
+ if (sfd < 0) {
+ perror("socket");
+ goto again;
+ }
+
+ socket_set_low_latency(cfg, sfd);
+
+ task->priv = conn;
+ uring_task_set_fd(task, sfd);
+ uring_connect(cfg, task, &conn->remote, connect_cb);
+}
+
+void
+connect_any(struct cfg *cfg, struct uring_task *task,
+ struct list_head *addrs, struct connection *conn,
+ void (*callback)(struct cfg *, struct connection *, int res))
+{
+ if (!cfg || !task || !addrs || !conn || !callback) {
+ fprintf(stderr, "%s: invalid arguments\n", __func__);
+ return;
+ }
+
+ conn->next_addr = 0;
+ conn->addrs = addrs;
+ conn->callback = callback;
+ connect_next(cfg, task, conn);
+}
+
uint16_t sockaddr_port(struct sockaddr_in46 *addr)
{
switch (addr->storage.ss_family) {
diff --git a/utils.h b/utils.h
index 8f8a153..5a6f69e 100644
--- a/utils.h
+++ b/utils.h
@@ -10,6 +10,66 @@ struct list_head {
struct list_head *prev;
};
+#define zmalloc(s) __zmalloc(__func__, __LINE__, s)
+void *__zmalloc(const char *fn, int line, size_t s);
+
+#define xstrdup(s) __xstrdup(__func__, __LINE__, s)
+char *__xstrdup(const char *fn, int line, const char *s);
+
+#define xstrndup(s, n) __xstrndup(__func__, __LINE__, s, n)
+char *__xstrndup(const char *fn, int line, const char *s, size_t n);
+
+#define xfree(s) __xfree(__func__, __LINE__, s)
+void __xfree(const char *fn, int line, void *ptr);
+
+void debug_resource_usage();
+
+#define ADDRSTRLEN (9 /*strlen("AF_INETX ")*/ + INET6_ADDRSTRLEN + 6 /*strlen(" 65535")*/ + 1)
+struct sockaddr_in46 {
+ union {
+ struct sockaddr_storage storage;
+ struct sockaddr_in in4;
+ struct sockaddr_in6 in6;
+ };
+ socklen_t addrlen;
+ struct list_head list;
+};
+
+struct connection {
+ struct sockaddr_in46 remote;
+ char remotestr[ADDRSTRLEN];
+
+ struct sockaddr_in46 local;
+ char localstr[ADDRSTRLEN];
+
+ struct list_head *addrs;
+ unsigned next_addr;
+
+ void (*callback)(struct cfg *, struct connection *, int res);
+};
+
+struct uring_task;
+
+void socket_set_low_latency(struct cfg *cfg, int sfd);
+
+void connect_any(struct cfg *cfg, struct uring_task *task,
+ struct list_head *addrs, struct connection *conn,
+ void (*callback)(struct cfg *, struct connection *, int res));
+
+uint16_t sockaddr_port(struct sockaddr_in46 *addr);
+
+char *sockaddr_to_str(struct sockaddr_in46 *addr, char *buf, size_t buflen);
+
+int strtou16_strict(const char *str, uint16_t *result);
+
+static inline bool empty_str(const char *str)
+{
+ if (!str || str[0] == '\0')
+ return true;
+ else
+ return false;
+}
+
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name)
@@ -79,47 +139,6 @@ static inline bool list_empty(struct list_head *list)
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
-#define zmalloc(s) __zmalloc(__func__, __LINE__, s)
-void *__zmalloc(const char *fn, int line, size_t s);
-
-#define xstrdup(s) __xstrdup(__func__, __LINE__, s)
-char *__xstrdup(const char *fn, int line, const char *s);
-
-#define xstrndup(s, n) __xstrndup(__func__, __LINE__, s, n)
-char *__xstrndup(const char *fn, int line, const char *s, size_t n);
-
-#define xfree(s) __xfree(__func__, __LINE__, s)
-void __xfree(const char *fn, int line, void *ptr);
-
-void debug_resource_usage();
-
-#define ADDRSTRLEN (9 /*strlen("AF_INETX ")*/ + INET6_ADDRSTRLEN + 6 /*strlen(" 65535")*/ + 1)
-struct sockaddr_in46 {
- union {
- struct sockaddr_storage storage;
- struct sockaddr_in in4;
- struct sockaddr_in6 in6;
- };
- socklen_t addrlen;
- struct list_head list;
-};
-
-void socket_set_gaming_options(struct cfg *cfg, int sfd);
-
-uint16_t sockaddr_port(struct sockaddr_in46 *addr);
-
-char *sockaddr_to_str(struct sockaddr_in46 *addr, char *buf, size_t buflen);
-
-int strtou16_strict(const char *str, uint16_t *result);
-
-static inline bool empty_str(const char *str)
-{
- if (!str || str[0] == '\0')
- return true;
- else
- return false;
-}
-
/*
#define _cleanup_(x) __attribute__((cleanup(x)))