From 8939a5001b0e68e07370526c3ed16abdcccdc3ae Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 9 Aug 2018 09:55:29 +0930 Subject: [PATCH] connectd: rely on the master to tell us to reconnect. connectd tells master about every disconnection, and master knows whether it's important to reconnect. Just get the master to invoke a new connect command if it considers the peer important! The only twist is timeouts: we don't want to immediately reconnect if we've failed to connect. To solve this, connectd passes a 'delaytime' to the master when a connection fails, and the master passes it back when it asks for a connection. Signed-off-by: Rusty Russell --- connectd/connect.c | 160 ++++++----------------------------- connectd/connect_wire.csv | 8 +- lightningd/channel.c | 17 ++-- lightningd/channel.h | 3 +- lightningd/channel_control.c | 3 +- lightningd/closing_control.c | 6 +- lightningd/connect_control.c | 53 +++++++++++- lightningd/connect_control.h | 1 + lightningd/onchain_control.c | 7 +- lightningd/opening_control.c | 14 --- lightningd/opening_control.h | 2 - lightningd/peer_control.c | 17 ++-- tests/test_connection.py | 2 +- wallet/test/run-wallet.c | 13 ++- 14 files changed, 116 insertions(+), 190 deletions(-) diff --git a/connectd/connect.c b/connectd/connect.c index fe39fc9cf..ebf9b5cfc 100644 --- a/connectd/connect.c +++ b/connectd/connect.c @@ -67,43 +67,6 @@ #define INITIAL_WAIT_SECONDS 1 #define MAX_WAIT_SECONDS 300 -/* We put everything in this struct (redundantly) to pass it to timer cb */ -struct important_peerid { - struct daemon *daemon; - - struct pubkey id; - - /* How long to wait after failed connect */ - unsigned int wait_seconds; - - /* The timer we're using to reconnect */ - struct oneshot *reconnect_timer; -}; - -/* We keep a set of peer ids we're always trying to reach. */ -static const struct pubkey * -important_peerid_keyof(const struct important_peerid *imp) -{ - return &imp->id; -} - -static bool important_peerid_eq(const struct important_peerid *imp, - const struct pubkey *key) -{ - return pubkey_eq(&imp->id, key); -} - -static size_t important_peerid_hash(const struct pubkey *id) -{ - return siphash24(siphash_seed(), id, sizeof(*id)); -} - -HTABLE_DEFINE_TYPE(struct important_peerid, - important_peerid_keyof, - important_peerid_hash, - important_peerid_eq, - important_peerid_map); - struct listen_fd { int fd; /* If we bind() IPv6 then IPv4 to same port, we *may* fail to listen() @@ -151,15 +114,9 @@ struct daemon { struct timers timers; - /* Important peers */ - struct important_peerid_map important_peerids; - /* Local and global features to offer to peers. */ u8 *localfeatures, *globalfeatures; - /* Automatically reconnect. */ - bool reconnect; - /* Allow localhost to be considered "public" */ bool dev_allow_localhost; @@ -192,6 +149,9 @@ struct reaching { /* How far did we get? */ const char *connstate; + + /* How many seconds did we wait this time? */ + u32 seconds_waited; }; struct peer { @@ -225,9 +185,6 @@ struct addrhint { struct wireaddr_internal addr; }; -/* FIXME: Reorder */ -static void retry_important(struct important_peerid *imp); - static struct peer *find_reconnecting_peer(struct daemon *daemon, const struct pubkey *id) { @@ -865,7 +822,7 @@ static struct io_plan *connect_init(struct daemon_conn *master, daemon, msg, &daemon->id, &daemon->globalfeatures, &daemon->localfeatures, &proposed_wireaddr, - &proposed_listen_announce, &daemon->reconnect, + &proposed_listen_announce, &proxyaddr, &daemon->use_proxy_always, &daemon->dev_allow_localhost, &daemon->use_dns, &tor_password)) { @@ -955,48 +912,40 @@ struct io_plan *connection_out(struct io_conn *conn, struct reaching *reach) handshake_out_success, reach); } -static void PRINTF_FMT(3,4) +static void PRINTF_FMT(4,5) connect_failed(struct daemon *daemon, const struct pubkey *id, + u32 seconds_waited, const char *errfmt, ...) { u8 *msg; - struct important_peerid *imp; va_list ap; char *err; + u32 wait_seconds; va_start(ap, errfmt); err = tal_vfmt(tmpctx, errfmt, ap); va_end(ap); + /* Wait twice as long to reconnect, between min and max. */ + wait_seconds = seconds_waited * 2; + if (wait_seconds > MAX_WAIT_SECONDS) + wait_seconds = MAX_WAIT_SECONDS; + if (wait_seconds < INITIAL_WAIT_SECONDS) + wait_seconds = INITIAL_WAIT_SECONDS; + /* Tell any connect command what happened. */ - msg = towire_connectctl_connect_failed(NULL, id, err); + msg = towire_connectctl_connect_failed(NULL, id, err, wait_seconds); daemon_conn_send(&daemon->master, take(msg)); status_trace("Failed connected out for %s: %s", type_to_string(tmpctx, struct pubkey, id), err); - - /* If we want to keep trying, do so. */ - imp = important_peerid_map_get(&daemon->important_peerids, id); - if (imp) { - imp->wait_seconds *= 2; - if (imp->wait_seconds > MAX_WAIT_SECONDS) - imp->wait_seconds = MAX_WAIT_SECONDS; - - status_trace("...will try again in %u seconds", - imp->wait_seconds); - /* If important_id freed, this will be removed too */ - imp->reconnect_timer - = new_reltimer(&daemon->timers, imp, - time_from_sec(imp->wait_seconds), - retry_important, imp); - } } static void destroy_io_conn(struct io_conn *conn, struct reaching *reach) { - connect_failed(reach->daemon, &reach->id, + connect_failed(reach->daemon, &reach->id, reach->seconds_waited, "%s: %s", reach->connstate, strerror(errno)); tal_free(reach); } @@ -1128,7 +1077,9 @@ gossip_resolve_addr(const tal_t *ctx, const struct pubkey *id) return addr; } -static void try_reach_peer(struct daemon *daemon, const struct pubkey *id) +static void try_reach_peer(struct daemon *daemon, + const struct pubkey *id, + u32 seconds_waited) { struct wireaddr_internal *a; struct addrhint *hint; @@ -1166,7 +1117,7 @@ static void try_reach_peer(struct daemon *daemon, const struct pubkey *id) } if (!a) { - connect_failed(daemon, id, "No address known"); + connect_failed(daemon, id, seconds_waited, "No address known"); return; } @@ -1221,7 +1172,7 @@ static void try_reach_peer(struct daemon *daemon, const struct pubkey *id) fd = socket(af, SOCK_STREAM, 0); if (fd < 0) { - connect_failed(daemon, id, + connect_failed(daemon, id, seconds_waited, "Can't open %i socket for %s (%s)", af, type_to_string(tmpctx, struct pubkey, id), @@ -1235,6 +1186,7 @@ static void try_reach_peer(struct daemon *daemon, const struct pubkey *id) reach->id = *id; reach->addr = *a; reach->connstate = "Connection establishment"; + reach->seconds_waited = seconds_waited; list_add_tail(&daemon->reaching, &reach->list); tal_add_destructor(reach, destroy_reaching); @@ -1244,34 +1196,16 @@ static void try_reach_peer(struct daemon *daemon, const struct pubkey *id) io_new_conn(reach, fd, conn_init, reach); } -/* Called from timer, so needs single-arg declaration */ -static void retry_important(struct important_peerid *imp) -{ - /* In case we've come off a timer, don't leave dangling pointer */ - imp->reconnect_timer = NULL; - - /* With --dev-no-reconnect or --offline, we only want explicit - * connects */ - if (!imp->daemon->reconnect) - return; - - try_reach_peer(imp->daemon, &imp->id); -} - static struct io_plan *connect_to_peer(struct io_conn *conn, struct daemon *daemon, const u8 *msg) { struct pubkey id; - struct important_peerid *imp; + u32 seconds_waited; - if (!fromwire_connectctl_connect_to_peer(msg, &id)) + if (!fromwire_connectctl_connect_to_peer(msg, &id, &seconds_waited)) master_badmsg(WIRE_CONNECTCTL_CONNECT_TO_PEER, msg); - /* If this is an important peer, free any outstanding timer */ - imp = important_peerid_map_get(&daemon->important_peerids, &id); - if (imp) - imp->reconnect_timer = tal_free(imp->reconnect_timer); - try_reach_peer(daemon, &id); + try_reach_peer(daemon, &id, seconds_waited); return daemon_conn_read_next(conn, &daemon->master); } @@ -1292,46 +1226,11 @@ static struct io_plan *addr_hint(struct io_conn *conn, return daemon_conn_read_next(conn, &daemon->master); } -static struct io_plan *peer_important(struct io_conn *conn, - struct daemon *daemon, const u8 *msg) -{ - struct pubkey id; - bool important; - struct important_peerid *imp; - - if (!fromwire_connectctl_peer_important(msg, &id, &important)) - master_badmsg(WIRE_CONNECTCTL_PEER_IMPORTANT, msg); - - imp = important_peerid_map_get(&daemon->important_peerids, &id); - if (important) { - if (!imp) { - imp = tal(daemon, struct important_peerid); - imp->id = id; - imp->daemon = daemon; - imp->wait_seconds = INITIAL_WAIT_SECONDS; - important_peerid_map_add(&daemon->important_peerids, - imp); - /* Start trying to reaching it now. */ - retry_important(imp); - } - } else { - if (imp) { - important_peerid_map_del(&daemon->important_peerids, - imp); - /* Stop trying to reach it (if we are) */ - tal_free(find_reaching(daemon, &imp->id)); - } - } - - return daemon_conn_read_next(conn, &daemon->master); -} - static struct io_plan *peer_disconnected(struct io_conn *conn, struct daemon *daemon, const u8 *msg) { struct pubkey id, *key; struct peer *peer; - struct important_peerid *imp; if (!fromwire_connectctl_peer_disconnected(msg, &id)) master_badmsg(WIRE_CONNECTCTL_PEER_DISCONNECTED, msg); @@ -1352,11 +1251,6 @@ static struct io_plan *peer_disconnected(struct io_conn *conn, if (peer) io_wake(peer); - imp = important_peerid_map_get(&daemon->important_peerids, &id); - if (imp) { - imp->wait_seconds = INITIAL_WAIT_SECONDS; - retry_important(imp); - } return daemon_conn_read_next(conn, &daemon->master); } @@ -1378,9 +1272,6 @@ static struct io_plan *recv_req(struct io_conn *conn, struct daemon_conn *master case WIRE_CONNECTCTL_PEER_ADDRHINT: return addr_hint(conn, daemon, master->msg_in); - case WIRE_CONNECTCTL_PEER_IMPORTANT: - return peer_important(conn, daemon, master->msg_in); - case WIRE_CONNECTCTL_PEER_DISCONNECTED: return peer_disconnected(conn, daemon, master->msg_in); @@ -1418,7 +1309,6 @@ int main(int argc, char *argv[]) list_head_init(&daemon->reconnecting); list_head_init(&daemon->reaching); list_head_init(&daemon->addrhints); - important_peerid_map_init(&daemon->important_peerids); timers_init(&daemon->timers, time_mono()); daemon->broken_resolver_response = NULL; daemon->listen_fds = tal_arr(daemon, struct listen_fd, 0); diff --git a/connectd/connect_wire.csv b/connectd/connect_wire.csv index f374cb200..6b9f62b62 100644 --- a/connectd/connect_wire.csv +++ b/connectd/connect_wire.csv @@ -11,7 +11,6 @@ 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,,reconnect,bool connectctl_init,,tor_proxyaddr,?struct wireaddr connectctl_init,,use_tor_proxy_always,bool connectctl_init,,dev_allow_localhost,bool @@ -45,16 +44,13 @@ connectctl_peer_addrhint,,addr,struct wireaddr_internal # Master -> connectd: connect to a peer. connectctl_connect_to_peer,2001 connectctl_connect_to_peer,,id,struct pubkey +connectctl_connect_to_peer,,seconds_waited,u32 # Connectd->master: connect failed. connectctl_connect_failed,2020 connectctl_connect_failed,,id,struct pubkey connectctl_connect_failed,,failreason,wirestring - -# Master -> connectd: try to always maintain connection to this peer (or not) -connectctl_peer_important,2010 -connectctl_peer_important,,id,struct pubkey -connectctl_peer_important,,important,bool +connectctl_connect_failed,,seconds_to_delay,u32 # Connectd -> master: we got a peer. Two fds: peer and gossip connect_peer_connected,2002 diff --git a/lightningd/channel.c b/lightningd/channel.c index a0a41b644..628cc4ac9 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -22,7 +23,8 @@ static bool connects_to_peer(struct subd *owner) return owner && owner->talks_to_peer; } -void channel_set_owner(struct channel *channel, struct subd *owner) +void channel_set_owner(struct channel *channel, struct subd *owner, + bool reconnect) { struct subd *old_owner = channel->owner; channel->owner = owner; @@ -33,7 +35,12 @@ void channel_set_owner(struct channel *channel, struct subd *owner) u8 *msg = towire_connectctl_peer_disconnected(NULL, &channel->peer->id); subd_send_msg(channel->peer->ld->connectd, take(msg)); - channel->connected = false; + } + + if (reconnect) { + /* Reconnect after 1 second: prevents some spurious + * reconnects during tests. */ + delay_then_reconnect(channel, 1); } } channel->connected = connects_to_peer(owner); @@ -88,7 +95,7 @@ static void destroy_channel(struct channel *channel) htlc_state_name(hin->hstate)); /* Free any old owner still hanging around. */ - channel_set_owner(channel, NULL); + channel_set_owner(channel, NULL, false); list_del_from(&channel->peer->channels, &channel->list); } @@ -342,7 +349,7 @@ void channel_fail_permanent(struct channel *channel, const char *fmt, ...) channel->error = towire_errorfmt(channel, &cid, "%s", why); } - channel_set_owner(channel, NULL); + channel_set_owner(channel, NULL, false); /* Drop non-cooperatively (unilateral) to chain. */ drop_to_chain(ld, channel, false); tal_free(why); @@ -405,5 +412,5 @@ void channel_fail_transient(struct channel *channel, const char *fmt, ...) } #endif - channel_set_owner(channel, NULL); + channel_set_owner(channel, NULL, true); } diff --git a/lightningd/channel.h b/lightningd/channel.h index 72c844c5d..d9c964d3e 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -152,7 +152,8 @@ void delete_channel(struct channel *channel); const char *channel_state_name(const struct channel *channel); const char *channel_state_str(enum channel_state state); -void channel_set_owner(struct channel *channel, struct subd *owner); +void channel_set_owner(struct channel *channel, struct subd *owner, + bool reconnect); /* Channel has failed, but can try again. */ PRINTF_FMT(2,3) void channel_fail_transient(struct channel *channel, diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index 9c16ce982..4e6982a67 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -206,7 +206,8 @@ bool peer_start_channeld(struct channel *channel, channel_set_billboard, take(&peer_fd), take(&gossip_fd), - take(&hsmfd), NULL)); + take(&hsmfd), NULL), + false); if (!channel->owner) { log_unusual(channel->log, "Could not subdaemon channel: %s", diff --git a/lightningd/closing_control.c b/lightningd/closing_control.c index fbe6c71a0..b29054cef 100644 --- a/lightningd/closing_control.c +++ b/lightningd/closing_control.c @@ -89,7 +89,7 @@ static void peer_closing_complete(struct channel *channel, const u8 *msg) } /* Don't report spurious failure when closingd exits. */ - channel_set_owner(channel, NULL); + channel_set_owner(channel, NULL, false); /* Clear any transient negotiation messages */ channel_set_billboard(channel, false, NULL); @@ -155,7 +155,9 @@ void peer_start_closingd(struct channel *channel, channel_set_billboard, take(&peer_fd), take(&gossip_fd), take(&hsmfd), - NULL)); + NULL), + false); + if (!channel->owner) { log_unusual(channel->log, "Could not subdaemon closing: %s", strerror(errno)); diff --git a/lightningd/connect_control.c b/lightningd/connect_control.c index 62c2cacde..8cbcb8b36 100644 --- a/lightningd/connect_control.c +++ b/lightningd/connect_control.c @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include #include @@ -174,7 +176,7 @@ static void json_connect(struct command *cmd, subd_send_msg(cmd->ld->connectd, take(msg)); } - msg = towire_connectctl_connect_to_peer(NULL, &id); + msg = towire_connectctl_connect_to_peer(NULL, &id, 0); subd_send_msg(cmd->ld->connectd, take(msg)); /* Leave this here for peer_connected or connect_failed. */ @@ -190,13 +192,52 @@ static const struct json_command connect_command = { }; AUTODATA(json_command, &connect_command); +struct delayed_reconnect { + struct channel *channel; + u32 seconds_delayed; +}; + +static void maybe_reconnect(struct delayed_reconnect *d) +{ + struct peer *peer = d->channel->peer; + + /* Might have gone onchain since we started timer. */ + if (channel_active(d->channel)) { + u8 *msg = towire_connectctl_connect_to_peer(NULL, &peer->id, + d->seconds_delayed); + subd_send_msg(peer->ld->connectd, take(msg)); + } + tal_free(d); +} + +void delay_then_reconnect(struct channel *channel, u32 seconds_delay) +{ + struct delayed_reconnect *d; + struct lightningd *ld = channel->peer->ld; + + if (!ld->reconnect) + return; + + d = tal(channel, struct delayed_reconnect); + d->channel = channel; + d->seconds_delayed = seconds_delay; + + log_debug(channel->log, "Will try reconnect in %u seconds", + seconds_delay); + notleak(new_reltimer(&ld->timers, d, time_from_sec(seconds_delay), + maybe_reconnect, d)); +} + static void connect_failed(struct lightningd *ld, const u8 *msg) { struct pubkey id; char *err; struct connect *c; + u32 seconds_to_delay; + struct channel *channel; - if (!fromwire_connectctl_connect_failed(tmpctx, msg, &id, &err)) + if (!fromwire_connectctl_connect_failed(tmpctx, msg, &id, &err, + &seconds_to_delay)) fatal("Connect gave bad CONNECTCTL_CONNECT_FAILED message %s", tal_hex(msg, msg)); @@ -205,6 +246,11 @@ static void connect_failed(struct lightningd *ld, const u8 *msg) /* They delete themselves from list */ command_fail(c->cmd, LIGHTNINGD, "%s", err); } + + /* If we have an active channel, then reconnect. */ + channel = active_channel_by_id(ld, &id, NULL); + if (channel) + delay_then_reconnect(channel, seconds_to_delay); } void connect_succeeded(struct lightningd *ld, const struct pubkey *id) @@ -244,7 +290,6 @@ static unsigned connectd_msg(struct subd *connectd, const u8 *msg, const int *fd case WIRE_CONNECTCTL_ACTIVATE: case WIRE_CONNECTCTL_PEER_ADDRHINT: case WIRE_CONNECTCTL_CONNECT_TO_PEER: - case WIRE_CONNECTCTL_PEER_IMPORTANT: case WIRE_CONNECTCTL_PEER_DISCONNECTED: /* This is a reply, so never gets through to here. */ case WIRE_CONNECTCTL_INIT_REPLY: @@ -333,7 +378,7 @@ int connectd_init(struct lightningd *ld) tmpctx, &ld->id, get_offered_global_features(tmpctx), get_offered_local_features(tmpctx), wireaddrs, - listen_announce, ld->reconnect, + listen_announce, ld->proxyaddr, ld->use_proxy_always || ld->pure_tor_setup, allow_localhost, ld->config.use_dns, ld->tor_service_password ? ld->tor_service_password : ""); diff --git a/lightningd/connect_control.h b/lightningd/connect_control.h index 16babfc2f..054595bf8 100644 --- a/lightningd/connect_control.h +++ b/lightningd/connect_control.h @@ -9,6 +9,7 @@ struct pubkey; int connectd_init(struct lightningd *ld); void connectd_activate(struct lightningd *ld); +void delay_then_reconnect(struct channel *channel, u32 seconds_delay); void connect_succeeded(struct lightningd *ld, const struct pubkey *id); void gossip_connect_result(struct lightningd *ld, const u8 *msg); diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index 7ff81563b..1065ae71e 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -82,7 +82,7 @@ static enum watch_result onchain_tx_watched(struct channel *channel, u32 blockheight = channel->peer->ld->topology->tip->height; if (depth == 0) { log_unusual(channel->log, "Chain reorganization!"); - channel_set_owner(channel, NULL); + channel_set_owner(channel, NULL, false); /* FIXME! topology_rescan(peer->ld->topology, peer->funding_txid); @@ -377,7 +377,7 @@ static void onchain_error(struct channel *channel, /* FIXME: re-launch? */ log_broken(channel->log, "%s", desc); channel_set_billboard(channel, true, desc); - channel_set_owner(channel, NULL); + channel_set_owner(channel, NULL, false); } /* With a reorg, this can get called multiple times; each time we'll kill @@ -412,7 +412,8 @@ enum watch_result onchaind_funding_spent(struct channel *channel, onchain_error, channel_set_billboard, take(&hsmfd), - NULL)); + NULL), + false); if (!channel->owner) { log_broken(channel->log, "Could not subdaemon onchain: %s", diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index a270ab3ab..e66ac8b10 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -218,16 +218,6 @@ static void funding_broadcast_failed(struct channel *channel, exitstatus, err); } -void tell_connectd_peer_is_important(struct lightningd *ld, - const struct channel *channel) -{ - u8 *msg; - - /* Tell connectd we need to keep connection to this peer */ - msg = towire_connectctl_peer_important(NULL, &channel->peer->id, true); - subd_send_msg(ld->connectd, take(msg)); -} - static void opening_funder_finished(struct subd *openingd, const u8 *resp, const int *fds, struct funding_channel *fc) @@ -380,8 +370,6 @@ static void opening_funder_finished(struct subd *openingd, const u8 *resp, channel_watch_funding(ld, channel); - tell_connectd_peer_is_important(ld, channel); - /* Start normal channel daemon. */ peer_start_channeld(channel, &cs, fds[0], fds[1], NULL, false); @@ -492,8 +480,6 @@ static void opening_fundee_finished(struct subd *openingd, channel_watch_funding(ld, channel); - tell_connectd_peer_is_important(ld, channel); - /* On to normal operation! */ peer_start_channeld(channel, &cs, fds[0], fds[1], funding_signed, false); diff --git a/lightningd/opening_control.h b/lightningd/opening_control.h index 59bb059ad..3db0909e2 100644 --- a/lightningd/opening_control.h +++ b/lightningd/opening_control.h @@ -22,6 +22,4 @@ void opening_peer_no_active_channels(struct peer *peer); void kill_uncommitted_channel(struct uncommitted_channel *uc, const char *why); -void tell_connectd_peer_is_important(struct lightningd *ld, - const struct channel *channel); #endif /* LIGHTNING_LIGHTNINGD_OPENING_CONTROL_H */ diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 7a1d477e1..adc101b45 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -360,12 +360,6 @@ register_close_command(struct lightningd *ld, void drop_to_chain(struct lightningd *ld, struct channel *channel, bool cooperative) { - u8 *msg; - - /* Tell connectd we no longer need to keep connection to this peer */ - msg = towire_connectctl_peer_important(NULL, &channel->peer->id, false); - subd_send_msg(ld->connectd, take(msg)); - sign_last_tx(channel); /* Keep broadcasting until we say stop (can fail due to dup, @@ -929,10 +923,12 @@ static void activate_peer(struct peer *peer) subd_send_msg(peer->ld->connectd, take(msg)); /* We can only have one active channel: make sure connectd - * knows to reconnect. */ + * knows to try reconnecting. */ channel = peer_active_channel(peer); - if (channel) - tell_connectd_peer_is_important(ld, channel); + if (channel && ld->reconnect) { + msg = towire_connectctl_connect_to_peer(NULL, &peer->id, 0); + subd_send_msg(ld->connectd, take(msg)); + } list_for_each(&peer->channels, channel, list) { /* Watching lockin may be unnecessary, but it's harmless. */ @@ -1161,6 +1157,9 @@ static void process_dev_forget_channel(struct bitcoind *bitcoind UNUSED, json_add_txid(response, "funding_txid", &forget->channel->funding_txid); json_object_end(response); + /* Set error so we don't try to reconnect. */ + forget->channel->error = towire_errorfmt(forget->channel, NULL, + "dev_forget_channel"); delete_channel(forget->channel); command_success(forget->cmd, response); diff --git a/tests/test_connection.py b/tests/test_connection.py index 03061fc1c..1d763adc5 100644 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -82,7 +82,7 @@ def test_reconnect_channel_peers(node_factory, executor): l1.rpc.connect(l2.info['id'], 'localhost', l2.port) # Wait for exponential backoff to give us a 2 second window. - l1.daemon.wait_for_log('...will try again in 2 seconds') + l1.daemon.wait_for_log('Will try reconnect in 2 seconds') # It should now succeed when it restarts. l2.start() diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index a164bf845..99c3171a3 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -62,6 +62,9 @@ void command_success(struct command *cmd UNNEEDED, struct json_result *response /* Generated stub for connect_succeeded */ void connect_succeeded(struct lightningd *ld UNNEEDED, const struct pubkey *id UNNEEDED) { fprintf(stderr, "connect_succeeded called!\n"); abort(); } +/* Generated stub for delay_then_reconnect */ +void delay_then_reconnect(struct channel *channel UNNEEDED, u32 seconds_delay UNNEEDED) +{ fprintf(stderr, "delay_then_reconnect called!\n"); abort(); } /* Generated stub for fromwire_connect_peer_connected */ bool fromwire_connect_peer_connected(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct pubkey *id UNNEEDED, struct wireaddr_internal *addr UNNEEDED, struct crypto_state *crypto_state UNNEEDED, u8 **gfeatures UNNEEDED, u8 **lfeatures UNNEEDED) { fprintf(stderr, "fromwire_connect_peer_connected called!\n"); abort(); } @@ -315,25 +318,21 @@ void subd_req_(const tal_t *ctx UNNEEDED, /* Generated stub for subd_send_msg */ void subd_send_msg(struct subd *sd UNNEEDED, const u8 *msg_out UNNEEDED) { fprintf(stderr, "subd_send_msg called!\n"); abort(); } -/* Generated stub for tell_connectd_peer_is_important */ -void tell_connectd_peer_is_important(struct lightningd *ld UNNEEDED, - const struct channel *channel UNNEEDED) -{ fprintf(stderr, "tell_connectd_peer_is_important called!\n"); abort(); } /* Generated stub for towire_channel_dev_reenable_commit */ u8 *towire_channel_dev_reenable_commit(const tal_t *ctx UNNEEDED) { fprintf(stderr, "towire_channel_dev_reenable_commit called!\n"); abort(); } /* Generated stub for towire_channel_send_shutdown */ u8 *towire_channel_send_shutdown(const tal_t *ctx UNNEEDED) { fprintf(stderr, "towire_channel_send_shutdown called!\n"); abort(); } +/* Generated stub for towire_connectctl_connect_to_peer */ +u8 *towire_connectctl_connect_to_peer(const tal_t *ctx UNNEEDED, const struct pubkey *id UNNEEDED, u32 seconds_waited UNNEEDED) +{ fprintf(stderr, "towire_connectctl_connect_to_peer called!\n"); abort(); } /* Generated stub for towire_connectctl_peer_addrhint */ u8 *towire_connectctl_peer_addrhint(const tal_t *ctx UNNEEDED, const struct pubkey *id UNNEEDED, const struct wireaddr_internal *addr UNNEEDED) { fprintf(stderr, "towire_connectctl_peer_addrhint called!\n"); abort(); } /* Generated stub for towire_connectctl_peer_disconnected */ u8 *towire_connectctl_peer_disconnected(const tal_t *ctx UNNEEDED, const struct pubkey *id UNNEEDED) { fprintf(stderr, "towire_connectctl_peer_disconnected called!\n"); abort(); } -/* Generated stub for towire_connectctl_peer_important */ -u8 *towire_connectctl_peer_important(const tal_t *ctx UNNEEDED, const struct pubkey *id UNNEEDED, bool important UNNEEDED) -{ fprintf(stderr, "towire_connectctl_peer_important called!\n"); abort(); } /* Generated stub for towire_errorfmt */ u8 *towire_errorfmt(const tal_t *ctx UNNEEDED, const struct channel_id *channel UNNEEDED,