Browse Source

connectd: do socket binding during initial setup.

gossipd does a two-step initialization: it only tries to create the
listening sockets when it's activated.  This means it doesn't know the
addresses to announce until this point.

Now connectd is doing this, this would mean we'd have to tell gossipd
later ("oh, BTW here are your addresses") since we need to start gossipd
before connectd activation.

So make connectd do all the setup, but only actually listen on the fds
once we activate it.  We clone the gossip_init message into
connect_wire.csv.  The master daemon still waits for a reply from
connectd for the activate message, since it wants to be listening
before it prints "Server started".

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 6 years ago
parent
commit
b4ed954435
  1. 67
      connectd/connect.c
  2. 38
      connectd/connect_wire.csv

67
connectd/connect.c

@ -162,6 +162,9 @@ struct daemon {
/* The address that the broken response returns instead of
* NXDOMAIN. NULL if we have not detected a broken resolver. */
struct sockaddr *broken_resolver_response;
/* File descriptors to listen on once we're activated. */
int *listen_fds;
};
/* Peers we're trying to reach. */
@ -989,11 +992,6 @@ static int make_listen_fd(int domain, void *addr, socklen_t len, bool mayfail)
}
}
if (listen(fd, 5) != 0) {
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Failed to listen on %u socket: %s",
domain, strerror(errno));
}
return fd;
fail:
@ -1038,6 +1036,13 @@ static struct io_plan *connection_in(struct io_conn *conn, struct daemon *daemon
init_new_peer, daemon);
}
static void add_listen_fd(struct daemon *daemon, int fd)
{
size_t n = tal_count(daemon->listen_fds);
tal_resize(&daemon->listen_fds, n+1);
daemon->listen_fds[n] = fd;
}
/* Return true if it created socket successfully. */
static bool handle_wireaddr_listen(struct daemon *daemon,
const struct wireaddr *wireaddr,
@ -1055,7 +1060,7 @@ static bool handle_wireaddr_listen(struct daemon *daemon,
if (fd >= 0) {
status_trace("Created IPv4 listener on port %u",
wireaddr->port);
io_new_listener(daemon, fd, connection_in, daemon);
add_listen_fd(daemon, fd);
return true;
}
return false;
@ -1065,7 +1070,7 @@ static bool handle_wireaddr_listen(struct daemon *daemon,
if (fd >= 0) {
status_trace("Created IPv6 listener on port %u",
wireaddr->port);
io_new_listener(daemon, fd, connection_in, daemon);
add_listen_fd(daemon, fd);
return true;
}
return false;
@ -1276,8 +1281,9 @@ static struct io_plan *gossip_init(struct daemon_conn *master,
struct bitcoin_blkid chain_hash;
u32 update_channel_interval;
struct wireaddr *proxyaddr;
struct wireaddr_internal *binding;
if (!fromwire_gossipctl_init(
if (!fromwire_connectctl_init(
daemon, msg, &daemon->broadcast_interval, &chain_hash,
&daemon->id, &daemon->globalfeatures,
&daemon->localfeatures, &daemon->proposed_wireaddr,
@ -1286,7 +1292,7 @@ static struct io_plan *gossip_init(struct daemon_conn *master,
&proxyaddr, &daemon->use_proxy_always,
&daemon->dev_allow_localhost, &daemon->use_dns,
&daemon->tor_password)) {
master_badmsg(WIRE_GOSSIPCTL_INIT, msg);
master_badmsg(WIRE_CONNECTCTL_INIT, msg);
}
/* Resolve Tor proxy address if any */
@ -1302,6 +1308,13 @@ static struct io_plan *gossip_init(struct daemon_conn *master,
"dummy replies");
}
binding = setup_listeners(tmpctx, daemon);
daemon_conn_send(&daemon->master,
take(towire_connectctl_init_reply(NULL,
binding,
daemon->announcable)));
return daemon_conn_read_next(master->conn, master);
}
@ -1309,23 +1322,26 @@ static struct io_plan *gossip_activate(struct daemon_conn *master,
struct daemon *daemon,
const u8 *msg)
{
bool listen;
struct wireaddr_internal *binding;
bool do_listen;
if (!fromwire_gossipctl_activate(msg, &listen))
master_badmsg(WIRE_GOSSIPCTL_ACTIVATE, msg);
if (!fromwire_connectctl_activate(msg, &do_listen))
master_badmsg(WIRE_CONNECTCTL_ACTIVATE, msg);
if (listen)
binding = setup_listeners(tmpctx, daemon);
else
binding = NULL;
if (do_listen) {
for (size_t i = 0; i < tal_count(daemon->listen_fds); i++) {
if (listen(daemon->listen_fds[i], 5) != 0)
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Failed to listen on socket: %s",
strerror(errno));
io_new_listener(daemon, daemon->listen_fds[i],
connection_in, daemon);
}
}
daemon->listen_fds = tal_free(daemon->listen_fds);
/* OK, we're ready! */
daemon_conn_send(&daemon->master,
take(towire_gossipctl_activate_reply(NULL,
binding,
daemon->announcable)));
take(towire_connectctl_activate_reply(NULL)));
return daemon_conn_read_next(master->conn, master);
}
@ -1813,13 +1829,14 @@ static struct io_plan *recv_req(struct io_conn *conn, struct daemon_conn *master
struct daemon *daemon = container_of(master, struct daemon, master);
enum gossip_wire_type t= fromwire_peektype(master->msg_in);
/* FIXME: Move away from gossip wiretypes */
if (fromwire_peektype(master->msg_in) == WIRE_CONNECTCTL_ACTIVATE)
return gossip_activate(master, daemon, master->msg_in);
switch (t) {
case WIRE_GOSSIPCTL_INIT:
return gossip_init(master, daemon, master->msg_in);
case WIRE_GOSSIPCTL_ACTIVATE:
return gossip_activate(master, daemon, master->msg_in);
case WIRE_GOSSIPCTL_RELEASE_PEER:
return release_peer(conn, daemon, master->msg_in);
@ -1845,6 +1862,7 @@ static struct io_plan *recv_req(struct io_conn *conn, struct daemon_conn *master
return disconnect_peer(conn, daemon, master->msg_in);
/* FIXME: We don't really do these, gossipd does */
case WIRE_GOSSIPCTL_ACTIVATE:
case WIRE_GOSSIP_GETNODES_REQUEST:
case WIRE_GOSSIP_PING:
case WIRE_GOSSIP_QUERY_SCIDS:
@ -1917,6 +1935,7 @@ int main(int argc, char *argv[])
timers_init(&daemon->timers, time_mono());
daemon->broadcast_interval = 30000;
daemon->broken_resolver_response = NULL;
daemon->listen_fds = tal_arr(daemon, int, 0);
/* stdin == control */
daemon_conn_init(daemon, &daemon->master, STDIN_FILENO, recv_req,
master_gone);

38
connectd/connect_wire.csv

@ -1,3 +1,41 @@
#include <common/wireaddr.h>
connectctl_init,2000
connectctl_init,,broadcast_interval,u32
connectctl_init,,chain_hash,struct bitcoin_blkid
connectctl_init,,id,struct pubkey
connectctl_init,,gflen,u16
connectctl_init,,gfeatures,gflen*u8
connectctl_init,,lflen,u16
connectctl_init,,lfeatures,lflen*u8
connectctl_init,,num_wireaddrs,u16
connectctl_init,,wireaddrs,num_wireaddrs*struct wireaddr_internal
connectctl_init,,listen_announce,num_wireaddrs*enum addr_listen_announce
connectctl_init,,rgb,3*u8
connectctl_init,,alias,32*u8
connectctl_init,,update_channel_interval,u32
connectctl_init,,reconnect,bool
connectctl_init,,tor_proxyaddr,?struct wireaddr
connectctl_init,,use_tor_proxy_always,bool
connectctl_init,,dev_allow_localhost,bool
connectctl_init,,use_dns,bool
connectctl_init,,tor_password,wirestring
# Connectd->master, here are the addresses I bound, can announce.
connectctl_init_reply,2100
connectctl_init_reply,,num_bindings,u16
connectctl_init_reply,,bindings,num_bindings*struct wireaddr_internal
connectctl_init_reply,,num_announcable,u16
connectctl_init_reply,,announcable,num_announcable*struct wireaddr
# Activate the connect daemon, so others can connect.
connectctl_activate,2025
# Do we listen?
connectctl_activate,,listen,bool
# Connectd->master, I am ready.
connectctl_activate_reply,2125
# connectd->master: disconnect this peer please (due to reconnect).
connect_reconnected,2112
connect_reconnected,,id,struct pubkey

Can't render this file because it has a wrong number of fields in line 2.
Loading…
Cancel
Save