diff --git a/connectd/connectd.c b/connectd/connectd.c index 0c0023536..9b6bc7206 100644 --- a/connectd/connectd.c +++ b/connectd/connectd.c @@ -1840,6 +1840,20 @@ static void peer_discard(struct daemon *daemon, const u8 *msg) tal_free(peer); } +static void start_shutdown(struct daemon *daemon, const u8 *msg) +{ + if (!fromwire_connectd_start_shutdown(msg)) + master_badmsg(WIRE_CONNECTD_START_SHUTDOWN, msg); + + daemon->shutting_down = true; + + /* No more incoming connections! */ + daemon->listeners = tal_free(daemon->listeners); + + daemon_conn_send(daemon->master, + take(towire_connectd_start_shutdown_reply(NULL))); +} + /* lightningd tells us to send a msg and disconnect. */ static void peer_final_msg(struct io_conn *conn, struct daemon *daemon, const u8 *msg) @@ -1940,6 +1954,10 @@ static struct io_plan *recv_req(struct io_conn *conn, return daemon_conn_read_with_fd(conn, daemon->master, recv_peer_connect_subd, daemon); + case WIRE_CONNECTD_START_SHUTDOWN: + start_shutdown(daemon, msg); + goto out; + case WIRE_CONNECTD_DEV_MEMLEAK: #if DEVELOPER dev_connect_memleak(daemon, msg); @@ -1961,6 +1979,7 @@ static struct io_plan *recv_req(struct io_conn *conn, case WIRE_CONNECTD_GOT_ONIONMSG_TO_US: case WIRE_CONNECTD_CUSTOMMSG_IN: case WIRE_CONNECTD_PEER_DISCONNECT_DONE: + case WIRE_CONNECTD_START_SHUTDOWN_REPLY: break; } @@ -2033,6 +2052,7 @@ int main(int argc, char *argv[]) list_head_init(&daemon->connecting); timers_init(&daemon->timers, time_mono()); daemon->gossip_store_fd = -1; + daemon->shutting_down = false; /* stdin == control */ daemon->master = daemon_conn_new(daemon, STDIN_FILENO, recv_req, NULL, diff --git a/connectd/connectd.h b/connectd/connectd.h index b901c7322..7b9141786 100644 --- a/connectd/connectd.h +++ b/connectd/connectd.h @@ -187,6 +187,9 @@ struct daemon { /* We only announce websocket addresses if !deprecated_apis */ bool announce_websocket; + /* Shutting down, don't send new stuff */ + bool shutting_down; + #if DEVELOPER /* Hack to speed up gossip timer */ bool dev_fast_gossip; diff --git a/connectd/connectd_wire.csv b/connectd/connectd_wire.csv index d8b77d0a4..e376eda09 100644 --- a/connectd/connectd_wire.csv +++ b/connectd/connectd_wire.csv @@ -144,6 +144,12 @@ msgdata,connectd_custommsg_out,id,node_id, msgdata,connectd_custommsg_out,msg_len,u16, msgdata,connectd_custommsg_out,msg,u8,msg_len +# master -> connectd: we're shutting down, no new connections. +msgtype,connectd_start_shutdown,2031 + +# connect - >master: acknowledged. +msgtype,connectd_start_shutdown_reply,2131 + # master -> connect: stop sending gossip. msgtype,connectd_dev_suppress_gossip,2032 diff --git a/connectd/multiplex.c b/connectd/multiplex.c index e2e50e96a..5623a4c6b 100644 --- a/connectd/multiplex.c +++ b/connectd/multiplex.c @@ -1133,6 +1133,14 @@ static struct io_plan *read_body_from_peer_done(struct io_conn *peer_conn, subd = find_subd(peer, &channel_id); if (!subd) { enum peer_wire t = fromwire_peektype(decrypted); + + /* Simplest to close on them at this point. */ + if (peer->daemon->shutting_down) { + status_peer_debug(&peer->id, + "Shutting down: hanging up for %s", + peer_wire_name(t)); + return io_close(peer_conn); + } status_peer_debug(&peer->id, "Activating for message %s", peer_wire_name(t)); subd = new_subd(peer, &channel_id); diff --git a/lightningd/connect_control.c b/lightningd/connect_control.c index 62b81fa73..553061c07 100644 --- a/lightningd/connect_control.c +++ b/lightningd/connect_control.c @@ -539,11 +539,13 @@ static unsigned connectd_msg(struct subd *connectd, const u8 *msg, const int *fd case WIRE_CONNECTD_PING: case WIRE_CONNECTD_SEND_ONIONMSG: case WIRE_CONNECTD_CUSTOMMSG_OUT: + case WIRE_CONNECTD_START_SHUTDOWN: /* This is a reply, so never gets through to here. */ case WIRE_CONNECTD_INIT_REPLY: case WIRE_CONNECTD_ACTIVATE_REPLY: case WIRE_CONNECTD_DEV_MEMLEAK_REPLY: case WIRE_CONNECTD_PING_REPLY: + case WIRE_CONNECTD_START_SHUTDOWN_REPLY: break; case WIRE_CONNECTD_PEER_CONNECTED: