diff --git a/adsbus/incoming.c b/adsbus/incoming.c index 1b93991..6ee0c54 100644 --- a/adsbus/incoming.c +++ b/adsbus/incoming.c @@ -24,8 +24,6 @@ struct incoming { uint8_t id[UUID_LEN]; char *node; char *service; - struct addrinfo *addrs; - const char *error; uint32_t attempt; struct flow *flow; void *passthrough; @@ -85,9 +83,19 @@ static void incoming_del(struct incoming *incoming) { free(incoming); } -static void incoming_listen(struct incoming *incoming) { +static void incoming_listen(struct peer *peer) { + struct incoming *incoming = (struct incoming *) peer; + + struct addrinfo *addrs; + int err = resolve_result(peer, &addrs); + if (err) { + fprintf(stderr, "I %s: Failed to resolve %s/%s: %s\n", incoming->id, incoming->node, incoming->service, gai_strerror(err)); + incoming_retry(incoming); + return; + } + struct addrinfo *addr; - for (addr = incoming->addrs; addr; addr = addr->ai_next) { + for (addr = addrs; addr; addr = addr->ai_next) { char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; assert(getnameinfo(addr->ai_addr, addr->ai_addrlen, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV) == 0); fprintf(stderr, "I %s: Listening on %s/%s...\n", incoming->id, hbuf, sbuf); @@ -111,7 +119,7 @@ static void incoming_listen(struct incoming *incoming) { break; } - freeaddrinfo(incoming->addrs); + freeaddrinfo(addrs); if (addr == NULL) { fprintf(stderr, "I %s: Failed to bind any addresses for %s/%s...\n", incoming->id, incoming->node, incoming->service); @@ -124,21 +132,10 @@ static void incoming_listen(struct incoming *incoming) { peer_epoll_add((struct peer *) incoming, EPOLLIN); } -static void incoming_resolve_handler(struct peer *peer) { - struct incoming *incoming = (struct incoming *) peer; - if (incoming->addrs) { - incoming_listen(incoming); - } else { - fprintf(stderr, "I %s: Failed to resolve %s/%s: %s\n", incoming->id, incoming->node, incoming->service, incoming->error); - incoming_retry(incoming); - } -} - static void incoming_resolve(struct incoming *incoming) { fprintf(stderr, "I %s: Resolving %s/%s...\n", incoming->id, incoming->node, incoming->service); - incoming->peer.fd = -1; - incoming->peer.event_handler = incoming_resolve_handler; - resolve((struct peer *) incoming, incoming->node, incoming->service, AI_PASSIVE, &incoming->addrs, &incoming->error); + incoming->peer.event_handler = incoming_listen; + resolve((struct peer *) incoming, incoming->node, incoming->service, AI_PASSIVE); } static void incoming_resolve_wrapper(struct peer *peer) { diff --git a/adsbus/outgoing.c b/adsbus/outgoing.c index ce37b9f..9f30c40 100644 --- a/adsbus/outgoing.c +++ b/adsbus/outgoing.c @@ -26,7 +26,6 @@ struct outgoing { char *service; struct addrinfo *addrs; struct addrinfo *addr; - const char *error; uint32_t attempt; struct flow *flow; void *passthrough; @@ -122,20 +121,20 @@ static void outgoing_connect_result(struct outgoing *outgoing, int result) { static void outgoing_resolve_handler(struct peer *peer) { struct outgoing *outgoing = (struct outgoing *) peer; - if (outgoing->addrs) { + int err = resolve_result(peer, &outgoing->addrs); + if (err) { + fprintf(stderr, "O %s: Failed to resolve %s/%s: %s\n", outgoing->id, outgoing->node, outgoing->service, gai_strerror(err)); + outgoing_retry(outgoing); + } else { outgoing->addr = outgoing->addrs; outgoing_connect_next(outgoing); - } else { - fprintf(stderr, "O %s: Failed to resolve %s/%s: %s\n", outgoing->id, outgoing->node, outgoing->service, outgoing->error); - outgoing_retry(outgoing); } } static void outgoing_resolve(struct outgoing *outgoing) { fprintf(stderr, "O %s: Resolving %s/%s...\n", outgoing->id, outgoing->node, outgoing->service); - outgoing->peer.fd = -1; outgoing->peer.event_handler = outgoing_resolve_handler; - resolve((struct peer *) outgoing, outgoing->node, outgoing->service, 0, &outgoing->addrs, &outgoing->error); + resolve((struct peer *) outgoing, outgoing->node, outgoing->service, 0); } static void outgoing_resolve_wrapper(struct peer *peer) { diff --git a/adsbus/resolve.c b/adsbus/resolve.c index 1b20a9c..51990a2 100644 --- a/adsbus/resolve.c +++ b/adsbus/resolve.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -9,53 +10,39 @@ #include "resolve.h" -struct resolve_request { +struct resolve { int fd; - const char *node; - const char *service; - int flags; - struct addrinfo **addrs; - const char **error; -}; -struct resolve_peer { - struct peer peer; - struct peer *inner_peer; + char *node; + char *service; + int flags; + + int err; + struct addrinfo *addrs; }; static pthread_t resolve_thread; static int resolve_write_fd; -static void resolve_handler(struct peer *peer) { - struct resolve_peer *resolve_peer = (struct resolve_peer *) peer; - - assert(!close(resolve_peer->peer.fd)); - - peer_call(resolve_peer->inner_peer); - free(resolve_peer); -} - static void *resolve_main(void *arg) { int fd = (int) (intptr_t) arg; - struct resolve_request *request; - ssize_t ret; - while ((ret = read(fd, &request, sizeof(request))) == sizeof(request)) { + struct resolve *res; + ssize_t len; + while ((len = read(fd, &res, sizeof(res))) == sizeof(res)) { struct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM, - .ai_flags = AI_V4MAPPED | AI_ADDRCONFIG | request->flags, + .ai_flags = AI_V4MAPPED | AI_ADDRCONFIG | res->flags, }; - int err = getaddrinfo(request->node, request->service, &hints, request->addrs); - if (err) { - *request->addrs = NULL; - *request->error = gai_strerror(err); - } else { - *request->error = NULL; - } - close(request->fd); - free(request); + res->err = getaddrinfo(res->node, res->service, &hints, &res->addrs); + free(res->node); + free(res->service); + res->node = res->service = NULL; + assert(write(res->fd, &res, sizeof(res)) == sizeof(res)); + close(res->fd); + res->fd = -1; } - assert(!ret); + assert(!len); assert(!close(fd)); return NULL; } @@ -72,22 +59,28 @@ void resolve_cleanup() { assert(!pthread_join(resolve_thread, NULL)); } -void resolve(struct peer *peer, const char *node, const char *service, int flags, struct addrinfo **addrs, const char **error) { +void resolve(struct peer *peer, const char *node, const char *service, int flags) { int fds[2]; assert(!pipe2(fds, O_CLOEXEC)); - struct resolve_request *request = malloc(sizeof(*request)); - request->fd = fds[1]; - request->node = node; - request->service = service; - request->flags = flags; - request->addrs = addrs; - request->error = error; - assert(write(resolve_write_fd, &request, sizeof(request)) == sizeof(request)); + struct resolve *res = malloc(sizeof(*res)); + res->fd = fds[1]; + res->node = strdup(node); + res->service = strdup(service); + res->flags = flags; + assert(write(resolve_write_fd, &res, sizeof(res)) == sizeof(res)); - struct resolve_peer *resolve_peer = malloc(sizeof(*resolve_peer)); - resolve_peer->peer.fd = fds[0]; - resolve_peer->peer.event_handler = resolve_handler; - resolve_peer->inner_peer = peer; - peer_epoll_add((struct peer *) resolve_peer, EPOLLRDHUP); + peer->fd = fds[0]; + peer_epoll_add(peer, EPOLLIN); +} + +int resolve_result(struct peer *peer, struct addrinfo **addrs) { + struct resolve *res; + assert(read(peer->fd, &res, sizeof(res)) == sizeof(res)); + assert(!close(peer->fd)); + peer->fd = -1; + *addrs = res->addrs; + int err = res->err; + free(res); + return err; } diff --git a/adsbus/resolve.h b/adsbus/resolve.h index 92afb8c..8e91df5 100644 --- a/adsbus/resolve.h +++ b/adsbus/resolve.h @@ -5,4 +5,5 @@ struct addrinfo; void resolve_init(void); void resolve_cleanup(void); -void resolve(struct peer *, const char *, const char *, int, struct addrinfo **, const char **); +void resolve(struct peer *, const char *, const char *, int); +int resolve_result(struct peer *, struct addrinfo **addrs);