From 76e6067e13831569deca05dbb557d921998e3eb2 Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Thu, 11 Jun 2020 23:08:45 +0200 Subject: Create a helper function to loop through different possible connections and convert proxy to use it --- idle.c | 2 +- main.h | 1 + proxy.c | 61 ++++++-------------------------------- proxy.h | 1 + rcon.c | 2 +- server.c | 2 +- utils.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- utils.h | 101 +++++++++++++++++++++++++++++++++++++-------------------------- 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, ""); + 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))) -- cgit v1.2.3