Change resolution to use a single resolve thread, and to clean up after itself.

This commit is contained in:
Ian Gulliver
2016-02-23 11:53:17 -08:00
parent c6a2150a7d
commit 289dcdbb54
4 changed files with 73 additions and 50 deletions

View File

@@ -1,7 +1,7 @@
CC ?= clang CC ?= clang
CFLAGS ?= -Wall -Werror -O4 -g --std=gnu11 --pedantic-errors -fPIE -pie -fstack-protector-strong CFLAGS ?= -Wall -Werror -O4 -g --std=gnu11 --pedantic-errors -fPIE -pie -fstack-protector-strong -pthread
LDFLAGS ?= $(CFLAGS) -Wl,-z,relro -Wl,-z,now LDFLAGS ?= $(CFLAGS) -Wl,-z,relro -Wl,-z,now
LIBS ?= -ljansson -lanl LIBS ?= -ljansson
OBJ_NETWORK = incoming.o outgoing.o receive.o send.o OBJ_NETWORK = incoming.o outgoing.o receive.o send.o
OBJ_PROTOCOL = airspy_adsb.o beast.o json.o raw.o stats.o OBJ_PROTOCOL = airspy_adsb.o beast.o json.o raw.o stats.o

View File

@@ -14,6 +14,7 @@
#include "peer.h" #include "peer.h"
#include "rand.h" #include "rand.h"
#include "receive.h" #include "receive.h"
#include "resolve.h"
#include "send.h" #include "send.h"
#include "server.h" #include "server.h"
#include "stats.h" #include "stats.h"
@@ -100,6 +101,7 @@ int main(int argc, char *argv[]) {
hex_init(); hex_init();
rand_init(); rand_init();
resolve_init();
server_init(); server_init();
wakeup_init(); wakeup_init();
peer_init(); peer_init();
@@ -117,6 +119,7 @@ int main(int argc, char *argv[]) {
peer_loop(); peer_loop();
rand_cleanup(); rand_cleanup();
resolve_cleanup();
wakeup_cleanup(); wakeup_cleanup();
send_cleanup(); send_cleanup();

View File

@@ -5,73 +5,91 @@
#include <netdb.h> #include <netdb.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <pthread.h>
#include "peer.h" #include "peer.h"
#include "resolve.h" #include "resolve.h"
struct resolve { struct resolve_request {
struct peer peer; int fd;
const char *node;
const char *service;
int flags;
struct addrinfo **addrs; struct addrinfo **addrs;
const char **error; const char **error;
struct peer *inner_peer;
struct addrinfo ar_request;
struct gaicb gaicb;
struct gaicb *requests[1];
struct sigevent sev;
}; };
struct resolve_peer {
struct peer peer;
struct peer *inner_peer;
};
static pthread_t resolve_thread;
static int resolve_write_fd;
static void resolve_handler(struct peer *peer) { static void resolve_handler(struct peer *peer) {
struct resolve *res = (struct resolve *) peer; struct resolve_peer *resolve_peer = (struct resolve_peer *) peer;
assert(!close(res->peer.fd)); assert(!close(resolve_peer->peer.fd));
int err = gai_error(&res->gaicb); struct peer *inner_peer = resolve_peer->inner_peer;
if (err == 0) { free(resolve_peer);
*res->addrs = res->gaicb.ar_result;
*res->error = NULL;
} else {
*res->addrs = NULL;
*res->error = gai_strerror(err);
}
struct peer *inner_peer = res->inner_peer;
free(res);
inner_peer->event_handler(inner_peer); inner_peer->event_handler(inner_peer);
} }
static void resolve_callback(union sigval val) { static void *resolve_main(void *arg) {
assert(!close(val.sival_int)); int fd = (intptr_t) arg;
struct resolve_request *request;
ssize_t ret;
while ((ret = read(fd, &request, sizeof(request))) == sizeof(request)) {
struct addrinfo hints = {
.ai_family = AF_UNSPEC,
.ai_socktype = SOCK_STREAM,
.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG | request->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);
}
assert(!ret);
return NULL;
}
void resolve_init() {
int fds[2];
assert(!pipe2(fds, O_CLOEXEC));
resolve_write_fd = fds[1];
assert(!pthread_create(&resolve_thread, NULL, resolve_main, (void *) (intptr_t) fds[0]));
}
void resolve_cleanup() {
assert(!close(resolve_write_fd));
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, struct addrinfo **addrs, const char **error) {
struct resolve *res = malloc(sizeof(*res));
res->addrs = addrs;
res->error = error;
res->inner_peer = peer;
int fds[2]; int fds[2];
assert(!pipe2(fds, O_NONBLOCK)); assert(!pipe2(fds, O_CLOEXEC));
res->peer.fd = fds[0];
res->peer.event_handler = resolve_handler;
peer_epoll_add((struct peer *) res, EPOLLRDHUP);
res->requests[0] = &res->gaicb; struct resolve_request *request = malloc(sizeof(*request));
res->gaicb.ar_name = node; request->fd = fds[1];
res->gaicb.ar_service = service; request->node = node;
res->gaicb.ar_request = &res->ar_request; request->service = service;
res->ar_request.ai_family = AF_UNSPEC; request->flags = flags;
res->ar_request.ai_socktype = SOCK_STREAM; request->addrs = addrs;
res->ar_request.ai_protocol = 0; request->error = error;
res->ar_request.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG | flags; assert(write(resolve_write_fd, &request, sizeof(request)) == sizeof(request));
res->sev.sigev_notify = SIGEV_THREAD; struct resolve_peer *resolve_peer = malloc(sizeof(*resolve_peer));
res->sev.sigev_value.sival_int = fds[1]; resolve_peer->peer.fd = fds[0];
res->sev.sigev_notify_function = resolve_callback; resolve_peer->peer.event_handler = resolve_handler;
res->sev.sigev_notify_attributes = NULL; resolve_peer->inner_peer = peer;
peer_epoll_add((struct peer *) resolve_peer, EPOLLRDHUP);
assert(!getaddrinfo_a(GAI_NOWAIT, res->requests, 1, &res->sev));
} }

View File

@@ -3,4 +3,6 @@
struct peer; struct peer;
struct addrinfo; struct addrinfo;
void resolve_init();
void resolve_cleanup();
void resolve(struct peer *, const char *, const char *, int, struct addrinfo **, const char **); void resolve(struct peer *, const char *, const char *, int, struct addrinfo **, const char **);