Initial pass at async resolving. This is ugly and leaks memory and I hate it, so dedicated thread incoming.
This commit is contained in:
@@ -1,11 +1,11 @@
|
|||||||
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
|
||||||
LDFLAGS ?= $(CFLAGS) -Wl,-z,relro -Wl,-z,now
|
LDFLAGS ?= $(CFLAGS) -Wl,-z,relro -Wl,-z,now
|
||||||
LIBS ?= -ljansson
|
LIBS ?= -ljansson -lanl
|
||||||
|
|
||||||
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
|
||||||
OBJ_UTIL = buf.o hex.o opts.o packet.o peer.o rand.o server.o uuid.o wakeup.o
|
OBJ_UTIL = buf.o hex.o opts.o packet.o peer.o rand.o resolve.o server.o uuid.o wakeup.o
|
||||||
|
|
||||||
all: adsbus
|
all: adsbus
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "peer.h"
|
#include "peer.h"
|
||||||
|
#include "resolve.h"
|
||||||
#include "wakeup.h"
|
#include "wakeup.h"
|
||||||
#include "uuid.h"
|
#include "uuid.h"
|
||||||
|
|
||||||
@@ -21,6 +22,8 @@ struct incoming {
|
|||||||
char id[UUID_LEN];
|
char id[UUID_LEN];
|
||||||
char *node;
|
char *node;
|
||||||
char *service;
|
char *service;
|
||||||
|
struct addrinfo *addrs;
|
||||||
|
const char *error;
|
||||||
uint32_t attempt;
|
uint32_t attempt;
|
||||||
incoming_connection_handler handler;
|
incoming_connection_handler handler;
|
||||||
void *passthrough;
|
void *passthrough;
|
||||||
@@ -71,25 +74,9 @@ static void incoming_del(struct incoming *incoming) {
|
|||||||
free(incoming);
|
free(incoming);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void incoming_resolve(struct incoming *incoming) {
|
static void incoming_listen(struct incoming *incoming) {
|
||||||
fprintf(stderr, "I %s: Resolving %s/%s...\n", incoming->id, incoming->node, incoming->service);
|
|
||||||
|
|
||||||
struct addrinfo hints = {
|
|
||||||
.ai_family = AF_UNSPEC,
|
|
||||||
.ai_socktype = SOCK_STREAM,
|
|
||||||
.ai_flags = AI_PASSIVE | AI_V4MAPPED | AI_ADDRCONFIG,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct addrinfo *addrs;
|
|
||||||
int gai_err = getaddrinfo(incoming->node, incoming->service, &hints, &addrs);
|
|
||||||
if (gai_err) {
|
|
||||||
fprintf(stderr, "I %s: Failed to resolve %s/%s: %s\n", incoming->id, incoming->node, incoming->service, gai_strerror(gai_err));
|
|
||||||
incoming_retry(incoming);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct addrinfo *addr;
|
struct addrinfo *addr;
|
||||||
for (addr = addrs; addr; addr = addr->ai_next) {
|
for (addr = incoming->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);
|
||||||
@@ -110,7 +97,7 @@ static void incoming_resolve(struct incoming *incoming) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
freeaddrinfo(addrs);
|
freeaddrinfo(incoming->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);
|
||||||
@@ -122,6 +109,23 @@ static void incoming_resolve(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) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
static void incoming_resolve_wrapper(struct peer *peer) {
|
static void incoming_resolve_wrapper(struct peer *peer) {
|
||||||
incoming_resolve((struct incoming *) peer);
|
incoming_resolve((struct incoming *) peer);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "peer.h"
|
#include "peer.h"
|
||||||
|
#include "resolve.h"
|
||||||
#include "wakeup.h"
|
#include "wakeup.h"
|
||||||
#include "uuid.h"
|
#include "uuid.h"
|
||||||
|
|
||||||
@@ -21,6 +22,7 @@ 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;
|
||||||
outgoing_connection_handler handler;
|
outgoing_connection_handler handler;
|
||||||
void *passthrough;
|
void *passthrough;
|
||||||
@@ -110,22 +112,22 @@ 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) {
|
||||||
|
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) {
|
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;
|
||||||
struct addrinfo hints = {
|
outgoing->peer.event_handler = outgoing_resolve_handler;
|
||||||
.ai_family = AF_UNSPEC,
|
resolve((struct peer *) outgoing, outgoing->node, outgoing->service, 0, &outgoing->addrs, &outgoing->error);
|
||||||
.ai_socktype = SOCK_STREAM,
|
|
||||||
};
|
|
||||||
|
|
||||||
int gai_err = getaddrinfo(outgoing->node, outgoing->service, &hints, &outgoing->addrs);
|
|
||||||
if (gai_err) {
|
|
||||||
fprintf(stderr, "O %s: Failed to resolve %s/%s: %s\n", outgoing->id, outgoing->node, outgoing->service, gai_strerror(gai_err));
|
|
||||||
outgoing_retry(outgoing);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
outgoing->addr = outgoing->addrs;
|
|
||||||
outgoing_connect_next(outgoing);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void outgoing_resolve_wrapper(struct peer *peer) {
|
static void outgoing_resolve_wrapper(struct peer *peer) {
|
||||||
|
|||||||
77
adsbus/resolve.c
Normal file
77
adsbus/resolve.c
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
#define _GNU_SOURCE
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "peer.h"
|
||||||
|
|
||||||
|
#include "resolve.h"
|
||||||
|
|
||||||
|
struct resolve {
|
||||||
|
struct peer peer;
|
||||||
|
|
||||||
|
struct addrinfo **addrs;
|
||||||
|
const char **error;
|
||||||
|
|
||||||
|
struct peer *inner_peer;
|
||||||
|
|
||||||
|
struct addrinfo ar_request;
|
||||||
|
struct gaicb gaicb;
|
||||||
|
struct gaicb *requests[1];
|
||||||
|
|
||||||
|
struct sigevent sev;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void resolve_handler(struct peer *peer) {
|
||||||
|
struct resolve *res = (struct resolve *) peer;
|
||||||
|
|
||||||
|
assert(!close(res->peer.fd));
|
||||||
|
|
||||||
|
int err = gai_error(&res->gaicb);
|
||||||
|
if (err == 0) {
|
||||||
|
*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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void resolve_callback(union sigval val) {
|
||||||
|
assert(!close(val.sival_int));
|
||||||
|
}
|
||||||
|
|
||||||
|
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];
|
||||||
|
assert(!pipe2(fds, O_NONBLOCK));
|
||||||
|
res->peer.fd = fds[0];
|
||||||
|
res->peer.event_handler = resolve_handler;
|
||||||
|
peer_epoll_add((struct peer *) res, EPOLLRDHUP);
|
||||||
|
|
||||||
|
res->requests[0] = &res->gaicb;
|
||||||
|
res->gaicb.ar_name = node;
|
||||||
|
res->gaicb.ar_service = service;
|
||||||
|
res->gaicb.ar_request = &res->ar_request;
|
||||||
|
res->ar_request.ai_family = AF_UNSPEC;
|
||||||
|
res->ar_request.ai_socktype = SOCK_STREAM;
|
||||||
|
res->ar_request.ai_protocol = 0;
|
||||||
|
res->ar_request.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG | flags;
|
||||||
|
|
||||||
|
res->sev.sigev_notify = SIGEV_THREAD;
|
||||||
|
res->sev.sigev_value.sival_int = fds[1];
|
||||||
|
res->sev.sigev_notify_function = resolve_callback;
|
||||||
|
res->sev.sigev_notify_attributes = NULL;
|
||||||
|
|
||||||
|
assert(!getaddrinfo_a(GAI_NOWAIT, res->requests, 1, &res->sev));
|
||||||
|
}
|
||||||
6
adsbus/resolve.h
Normal file
6
adsbus/resolve.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct peer;
|
||||||
|
struct addrinfo;
|
||||||
|
|
||||||
|
void resolve(struct peer *, const char *, const char *, int, struct addrinfo **, const char **);
|
||||||
Reference in New Issue
Block a user