2016-02-23 10:46:40 -08:00
|
|
|
#include <assert.h>
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
#include <netdb.h>
|
|
|
|
|
#include <stdlib.h>
|
2016-02-29 22:37:41 -08:00
|
|
|
#include <string.h>
|
2016-02-23 10:46:40 -08:00
|
|
|
#include <unistd.h>
|
2016-02-23 11:53:17 -08:00
|
|
|
#include <pthread.h>
|
2016-02-23 10:46:40 -08:00
|
|
|
|
|
|
|
|
#include "peer.h"
|
|
|
|
|
|
|
|
|
|
#include "resolve.h"
|
|
|
|
|
|
2016-02-29 22:37:41 -08:00
|
|
|
struct resolve {
|
2016-02-23 11:53:17 -08:00
|
|
|
int fd;
|
2016-02-29 22:37:41 -08:00
|
|
|
|
|
|
|
|
char *node;
|
|
|
|
|
char *service;
|
2016-02-23 11:53:17 -08:00
|
|
|
int flags;
|
2016-02-23 10:46:40 -08:00
|
|
|
|
2016-02-29 22:37:41 -08:00
|
|
|
int err;
|
|
|
|
|
struct addrinfo *addrs;
|
2016-02-23 10:46:40 -08:00
|
|
|
};
|
|
|
|
|
|
2016-02-23 11:53:17 -08:00
|
|
|
static pthread_t resolve_thread;
|
|
|
|
|
static int resolve_write_fd;
|
|
|
|
|
|
|
|
|
|
static void *resolve_main(void *arg) {
|
2016-02-25 23:37:37 -08:00
|
|
|
int fd = (int) (intptr_t) arg;
|
2016-02-29 22:37:41 -08:00
|
|
|
struct resolve *res;
|
|
|
|
|
ssize_t len;
|
|
|
|
|
while ((len = read(fd, &res, sizeof(res))) == sizeof(res)) {
|
2016-02-23 11:53:17 -08:00
|
|
|
struct addrinfo hints = {
|
|
|
|
|
.ai_family = AF_UNSPEC,
|
|
|
|
|
.ai_socktype = SOCK_STREAM,
|
2016-02-29 22:37:41 -08:00
|
|
|
.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG | res->flags,
|
2016-02-23 11:53:17 -08:00
|
|
|
};
|
2016-02-29 22:37:41 -08:00
|
|
|
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;
|
2016-02-23 11:53:17 -08:00
|
|
|
}
|
2016-02-29 22:37:41 -08:00
|
|
|
assert(!len);
|
2016-02-23 11:57:40 -08:00
|
|
|
assert(!close(fd));
|
2016-02-23 11:53:17 -08:00
|
|
|
return NULL;
|
2016-02-23 10:46:40 -08:00
|
|
|
}
|
|
|
|
|
|
2016-02-23 11:53:17 -08:00
|
|
|
void resolve_init() {
|
2016-02-23 10:46:40 -08:00
|
|
|
int fds[2];
|
2016-02-23 11:53:17 -08:00
|
|
|
assert(!pipe2(fds, O_CLOEXEC));
|
|
|
|
|
resolve_write_fd = fds[1];
|
|
|
|
|
assert(!pthread_create(&resolve_thread, NULL, resolve_main, (void *) (intptr_t) fds[0]));
|
|
|
|
|
}
|
2016-02-23 10:46:40 -08:00
|
|
|
|
2016-02-23 11:53:17 -08:00
|
|
|
void resolve_cleanup() {
|
|
|
|
|
assert(!close(resolve_write_fd));
|
|
|
|
|
assert(!pthread_join(resolve_thread, NULL));
|
|
|
|
|
}
|
2016-02-23 10:46:40 -08:00
|
|
|
|
2016-02-29 22:37:41 -08:00
|
|
|
void resolve(struct peer *peer, const char *node, const char *service, int flags) {
|
2016-02-23 11:53:17 -08:00
|
|
|
int fds[2];
|
|
|
|
|
assert(!pipe2(fds, O_CLOEXEC));
|
|
|
|
|
|
2016-02-29 22:37:41 -08:00
|
|
|
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));
|
|
|
|
|
|
|
|
|
|
peer->fd = fds[0];
|
|
|
|
|
peer_epoll_add(peer, EPOLLIN);
|
|
|
|
|
}
|
2016-02-23 11:53:17 -08:00
|
|
|
|
2016-02-29 22:37:41 -08:00
|
|
|
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;
|
2016-02-23 10:46:40 -08:00
|
|
|
}
|