mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-24 01:24:26 +01:00
dns: add failure callback.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
44
daemon/dns.c
44
daemon/dns.c
@@ -16,11 +16,13 @@
|
||||
#include <sys/wait.h>
|
||||
|
||||
struct dns_async {
|
||||
size_t use;
|
||||
struct lightningd_state *state;
|
||||
struct io_plan *(*init)(struct io_conn *,
|
||||
struct lightningd_state *,
|
||||
const char *name, const char *port);
|
||||
const char *name, *port;
|
||||
struct io_plan *(*init)(struct io_conn *, struct lightningd_state *,
|
||||
void *);
|
||||
void (*fail)(struct lightningd_state *, void *arg);
|
||||
const char *name;
|
||||
void *arg;
|
||||
int pid;
|
||||
size_t num_addresses;
|
||||
struct netaddr *addresses;
|
||||
@@ -67,7 +69,9 @@ static struct io_plan *connected(struct io_conn *conn, struct dns_async *d)
|
||||
{
|
||||
/* No longer need to try more connections. */
|
||||
io_set_finish(conn, NULL, NULL);
|
||||
return d->init(conn, d->state, d->name, d->port);
|
||||
|
||||
/* Keep use count, so reap_child won't fail. */
|
||||
return d->init(conn, d->state, d->arg);
|
||||
}
|
||||
|
||||
static void try_connect_one(struct dns_async *d);
|
||||
@@ -104,25 +108,32 @@ static void try_connect_one(struct dns_async *d)
|
||||
/* Now we can warn if it's overlength */
|
||||
if (a->addrlen > sizeof(a->saddr)) {
|
||||
log_broken(d->state->base_log,
|
||||
"DNS lookup gave overlength address for %s:%s"
|
||||
"DNS lookup gave overlength address for %s"
|
||||
" for family %u, len=%u",
|
||||
d->name, d->port,
|
||||
a->saddr.s.sa_family, a->addrlen);
|
||||
d->name, a->saddr.s.sa_family, a->addrlen);
|
||||
} else {
|
||||
/* Might not even be able to create eg. IPv6 sockets */
|
||||
fd = socket(a->saddr.s.sa_family, a->type, a->protocol);
|
||||
if (fd >= 0) {
|
||||
io_new_conn(d->state, fd, init_conn, d);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* We're out of things to try. Fail. */
|
||||
if (--d->use == 0)
|
||||
d->fail(d->state, d->arg);
|
||||
}
|
||||
|
||||
static struct io_plan *start_connecting(struct io_conn *conn,
|
||||
struct dns_async *d)
|
||||
{
|
||||
assert(d->num_addresses);
|
||||
|
||||
/* reap_child and our connections can race: only last one should call
|
||||
* fail. */
|
||||
d->use++;
|
||||
try_connect_one(d);
|
||||
return io_close(conn);
|
||||
}
|
||||
@@ -144,13 +155,18 @@ static struct io_plan *init_dns_conn(struct io_conn *conn, struct dns_async *d)
|
||||
static void reap_child(struct io_conn *conn, struct dns_async *d)
|
||||
{
|
||||
waitpid(d->pid, NULL, 0);
|
||||
/* Last user calls fail. */
|
||||
if (--d->use == 0)
|
||||
d->fail(d->state, d->arg);
|
||||
}
|
||||
|
||||
struct dns_async *dns_resolve_and_connect(struct lightningd_state *state,
|
||||
struct dns_async *dns_resolve_and_connect_(struct lightningd_state *state,
|
||||
const char *name, const char *port,
|
||||
struct io_plan *(*init)(struct io_conn *,
|
||||
struct lightningd_state *,
|
||||
const char *name, const char *port))
|
||||
void *arg),
|
||||
void (*fail)(struct lightningd_state *, void *arg),
|
||||
void *arg)
|
||||
{
|
||||
int pfds[2];
|
||||
struct dns_async *d = tal(NULL, struct dns_async);
|
||||
@@ -158,8 +174,9 @@ struct dns_async *dns_resolve_and_connect(struct lightningd_state *state,
|
||||
|
||||
d->state = state;
|
||||
d->init = init;
|
||||
d->name = tal_strdup(d, name);
|
||||
d->port = tal_strdup(d, port);
|
||||
d->fail = fail;
|
||||
d->arg = arg;
|
||||
d->name = tal_fmt(d, "%s:%s", name, port);
|
||||
|
||||
/* First fork child to get addresses. */
|
||||
if (pipe(pfds) != 0) {
|
||||
@@ -184,6 +201,7 @@ struct dns_async *dns_resolve_and_connect(struct lightningd_state *state,
|
||||
}
|
||||
|
||||
close(pfds[1]);
|
||||
d->use = 1;
|
||||
conn = io_new_conn(state, pfds[0], init_dns_conn, d);
|
||||
io_set_finish(conn, reap_child, d);
|
||||
tal_steal(conn, d);
|
||||
|
||||
Reference in New Issue
Block a user