diff options
author | David Härdeman <david@hardeman.nu> | 2020-06-11 23:08:45 +0200 |
---|---|---|
committer | David Härdeman <david@hardeman.nu> | 2020-06-11 23:08:45 +0200 |
commit | 76e6067e13831569deca05dbb557d921998e3eb2 (patch) | |
tree | 0b2b1e9f24628d60b4d1ee6682a850eed19c569a | |
parent | 79354a389890a7ee4b6cd5b7d7044b521fb133a6 (diff) |
Create a helper function to loop through different possible connections and convert proxy to use it
-rw-r--r-- | idle.c | 2 | ||||
-rw-r--r-- | main.h | 1 | ||||
-rw-r--r-- | proxy.c | 61 | ||||
-rw-r--r-- | proxy.h | 1 | ||||
-rw-r--r-- | rcon.c | 2 | ||||
-rw-r--r-- | server.c | 2 | ||||
-rw-r--r-- | utils.c | 94 | ||||
-rw-r--r-- | utils.h | 101 |
8 files changed, 167 insertions, 97 deletions
@@ -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); @@ -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 { @@ -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; } @@ -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; @@ -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); @@ -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) { @@ -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) { @@ -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))) |