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 --- utils.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 93 insertions(+), 1 deletion(-) (limited to 'utils.c') 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) { -- cgit v1.2.3