Finally find a clean ownership solution for resolve().
This commit is contained in:
@@ -24,8 +24,6 @@ struct incoming {
|
|||||||
uint8_t id[UUID_LEN];
|
uint8_t id[UUID_LEN];
|
||||||
char *node;
|
char *node;
|
||||||
char *service;
|
char *service;
|
||||||
struct addrinfo *addrs;
|
|
||||||
const char *error;
|
|
||||||
uint32_t attempt;
|
uint32_t attempt;
|
||||||
struct flow *flow;
|
struct flow *flow;
|
||||||
void *passthrough;
|
void *passthrough;
|
||||||
@@ -85,9 +83,19 @@ static void incoming_del(struct incoming *incoming) {
|
|||||||
free(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;
|
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];
|
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);
|
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);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
freeaddrinfo(incoming->addrs);
|
freeaddrinfo(addrs);
|
||||||
|
|
||||||
if (addr == NULL) {
|
if (addr == NULL) {
|
||||||
fprintf(stderr, "I %s: Failed to bind any addresses for %s/%s...\n", incoming->id, incoming->node, incoming->service);
|
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);
|
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) {
|
static void incoming_resolve(struct incoming *incoming) {
|
||||||
fprintf(stderr, "I %s: Resolving %s/%s...\n", incoming->id, incoming->node, incoming->service);
|
fprintf(stderr, "I %s: Resolving %s/%s...\n", incoming->id, incoming->node, incoming->service);
|
||||||
incoming->peer.fd = -1;
|
incoming->peer.event_handler = incoming_listen;
|
||||||
incoming->peer.event_handler = incoming_resolve_handler;
|
resolve((struct peer *) incoming, incoming->node, incoming->service, AI_PASSIVE);
|
||||||
resolve((struct peer *) incoming, incoming->node, incoming->service, AI_PASSIVE, &incoming->addrs, &incoming->error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void incoming_resolve_wrapper(struct peer *peer) {
|
static void incoming_resolve_wrapper(struct peer *peer) {
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ struct outgoing {
|
|||||||
char *service;
|
char *service;
|
||||||
struct addrinfo *addrs;
|
struct addrinfo *addrs;
|
||||||
struct addrinfo *addr;
|
struct addrinfo *addr;
|
||||||
const char *error;
|
|
||||||
uint32_t attempt;
|
uint32_t attempt;
|
||||||
struct flow *flow;
|
struct flow *flow;
|
||||||
void *passthrough;
|
void *passthrough;
|
||||||
@@ -122,20 +121,20 @@ static void outgoing_connect_result(struct outgoing *outgoing, int result) {
|
|||||||
|
|
||||||
static void outgoing_resolve_handler(struct peer *peer) {
|
static void outgoing_resolve_handler(struct peer *peer) {
|
||||||
struct outgoing *outgoing = (struct outgoing *) 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->addr = outgoing->addrs;
|
||||||
outgoing_connect_next(outgoing);
|
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) {
|
static void outgoing_resolve(struct outgoing *outgoing) {
|
||||||
fprintf(stderr, "O %s: Resolving %s/%s...\n", outgoing->id, outgoing->node, outgoing->service);
|
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;
|
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) {
|
static void outgoing_resolve_wrapper(struct peer *peer) {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
@@ -9,53 +10,39 @@
|
|||||||
|
|
||||||
#include "resolve.h"
|
#include "resolve.h"
|
||||||
|
|
||||||
struct resolve_request {
|
struct resolve {
|
||||||
int fd;
|
int fd;
|
||||||
const char *node;
|
|
||||||
const char *service;
|
|
||||||
int flags;
|
|
||||||
struct addrinfo **addrs;
|
|
||||||
const char **error;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct resolve_peer {
|
char *node;
|
||||||
struct peer peer;
|
char *service;
|
||||||
struct peer *inner_peer;
|
int flags;
|
||||||
|
|
||||||
|
int err;
|
||||||
|
struct addrinfo *addrs;
|
||||||
};
|
};
|
||||||
|
|
||||||
static pthread_t resolve_thread;
|
static pthread_t resolve_thread;
|
||||||
static int resolve_write_fd;
|
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) {
|
static void *resolve_main(void *arg) {
|
||||||
int fd = (int) (intptr_t) arg;
|
int fd = (int) (intptr_t) arg;
|
||||||
struct resolve_request *request;
|
struct resolve *res;
|
||||||
ssize_t ret;
|
ssize_t len;
|
||||||
while ((ret = read(fd, &request, sizeof(request))) == sizeof(request)) {
|
while ((len = read(fd, &res, sizeof(res))) == sizeof(res)) {
|
||||||
struct addrinfo hints = {
|
struct addrinfo hints = {
|
||||||
.ai_family = AF_UNSPEC,
|
.ai_family = AF_UNSPEC,
|
||||||
.ai_socktype = SOCK_STREAM,
|
.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);
|
res->err = getaddrinfo(res->node, res->service, &hints, &res->addrs);
|
||||||
if (err) {
|
free(res->node);
|
||||||
*request->addrs = NULL;
|
free(res->service);
|
||||||
*request->error = gai_strerror(err);
|
res->node = res->service = NULL;
|
||||||
} else {
|
assert(write(res->fd, &res, sizeof(res)) == sizeof(res));
|
||||||
*request->error = NULL;
|
close(res->fd);
|
||||||
}
|
res->fd = -1;
|
||||||
close(request->fd);
|
|
||||||
free(request);
|
|
||||||
}
|
}
|
||||||
assert(!ret);
|
assert(!len);
|
||||||
assert(!close(fd));
|
assert(!close(fd));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -72,22 +59,28 @@ void resolve_cleanup() {
|
|||||||
assert(!pthread_join(resolve_thread, NULL));
|
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];
|
int fds[2];
|
||||||
assert(!pipe2(fds, O_CLOEXEC));
|
assert(!pipe2(fds, O_CLOEXEC));
|
||||||
|
|
||||||
struct resolve_request *request = malloc(sizeof(*request));
|
struct resolve *res = malloc(sizeof(*res));
|
||||||
request->fd = fds[1];
|
res->fd = fds[1];
|
||||||
request->node = node;
|
res->node = strdup(node);
|
||||||
request->service = service;
|
res->service = strdup(service);
|
||||||
request->flags = flags;
|
res->flags = flags;
|
||||||
request->addrs = addrs;
|
assert(write(resolve_write_fd, &res, sizeof(res)) == sizeof(res));
|
||||||
request->error = error;
|
|
||||||
assert(write(resolve_write_fd, &request, sizeof(request)) == sizeof(request));
|
|
||||||
|
|
||||||
struct resolve_peer *resolve_peer = malloc(sizeof(*resolve_peer));
|
peer->fd = fds[0];
|
||||||
resolve_peer->peer.fd = fds[0];
|
peer_epoll_add(peer, EPOLLIN);
|
||||||
resolve_peer->peer.event_handler = resolve_handler;
|
}
|
||||||
resolve_peer->inner_peer = peer;
|
|
||||||
peer_epoll_add((struct peer *) resolve_peer, EPOLLRDHUP);
|
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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,4 +5,5 @@ struct addrinfo;
|
|||||||
|
|
||||||
void resolve_init(void);
|
void resolve_init(void);
|
||||||
void resolve_cleanup(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);
|
||||||
|
|||||||
Reference in New Issue
Block a user