From ee00c2c508cadd78f1b72b3fda1331bd612c622f Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Sat, 24 Jun 2017 16:20:23 +0930 Subject: [PATCH] lightningd: remove peer->gossip_client_fd We don't need to keep this around any more: by handing it to subdaemons we ensure we'll close it if the peer disconnects, and we also add code to get a new one on reconnection. Because getting a gossip_fd is async, we re-check the peer state after it gets back. This is kind of annoying: perhaps if we were to hand the reconnected peer through gossipd (with a flag to immediately return it) we could get the gossip fd that way and unify the paths? Signed-off-by: Rusty Russell --- lightningd/gossip_control.c | 4 +- lightningd/peer_control.c | 128 ++++++++++++++++++++++++++---------- lightningd/peer_control.h | 5 +- 3 files changed, 96 insertions(+), 41 deletions(-) diff --git a/lightningd/gossip_control.c b/lightningd/gossip_control.c index 0f8743fef..f26877311 100644 --- a/lightningd/gossip_control.c +++ b/lightningd/gossip_control.c @@ -80,12 +80,10 @@ static void peer_nongossip(struct subd *gossip, const u8 *msg, fatal("Gossip gave bad peerid %"PRIu64" (owner %s)", unique_id, peer->owner ? peer->owner->name : "(none)"); - peer->gossip_client_fd = gossip_fd; - log_info(peer->log, "Gossip ended up receipt of %s", wire_type_name(fromwire_peektype(inner))); - peer_fundee_open(peer, inner, &cs, peer_fd); + peer_fundee_open(peer, inner, &cs, peer_fd, gossip_fd); } static int gossip_msg(struct subd *gossip, const u8 *msg, const int *fds) diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index c5ca2ae77..64b478534 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -43,8 +43,6 @@ static void destroy_peer(struct peer *peer) { list_del_from(&peer->ld->peers, &peer->list); - if (peer->gossip_client_fd >= 0) - close(peer->gossip_client_fd); } /* Mutual recursion, sets timer. */ @@ -173,7 +171,7 @@ void peer_set_condition(struct peer *peer, enum peer_state old_state, static bool peer_start_channeld(struct peer *peer, enum peer_state old_state, const struct crypto_state *cs, - int peer_fd, + int peer_fd, int gossip_fd, const u8 *funding_signed); /* Send (encrypted) error message, then close. */ @@ -183,6 +181,87 @@ static struct io_plan *send_error(struct io_conn *conn, return peer_write_message(conn, pcs, pcs->peer->error, (void *)io_close_cb); } +struct getting_gossip_fd { + struct pubkey id; + int peer_fd; + struct crypto_state cs; +}; + +static bool get_peer_gossipfd_reply(struct subd *subd, const u8 *msg, + const int *fds, + struct getting_gossip_fd *ggf) +{ + struct peer *peer; + + if (!fromwire_gossipctl_get_peer_gossipfd_reply(msg, NULL)) { + if (!fromwire_gossipctl_get_peer_gossipfd_replyfail(msg, NULL)) + fatal("Gossipd gave bad get_peer_gossipfd reply %s", + tal_hex(subd, msg)); + + log_unusual(subd->log, "Gossipd could not get fds for peer %s", + type_to_string(ggf, struct pubkey, &ggf->id)); + + /* This is an internal error, but could be transient. + * Hang up and let them retry. */ + goto forget; + } + + /* Make sure it still needs gossipfd! */ + peer = peer_by_id(subd->ld, &ggf->id); + if (!peer) { + log_unusual(subd->log, "Gossipd gave fd, but peer %s gone", + type_to_string(ggf, struct pubkey, &ggf->id)); + goto close_gossipfd; + } + + if (peer->state != CHANNELD_AWAITING_LOCKIN + && peer->state != CHANNELD_NORMAL) { + log_unusual(subd->log, "Gossipd gave fd, but peer %s %s", + type_to_string(ggf, struct pubkey, &ggf->id), + peer_state_name(peer->state)); + goto close_gossipfd; + } + + /* Kill off current channeld, if any */ + if (peer->owner) { + peer->owner->peer = NULL; + peer->owner = tal_free(peer->owner); + } + + /* We never re-transmit funding_signed. */ + peer_start_channeld(peer, peer->state, &ggf->cs, ggf->peer_fd, fds[0], + NULL); + goto out; + +close_gossipfd: + close(fds[0]); + +forget: + close(ggf->peer_fd); +out: + tal_free(ggf); + return true; +} + +static void get_gossip_fd_for_reconnect(struct lightningd *ld, + const struct pubkey *id, + u64 unique_id, + int peer_fd, + const struct crypto_state *cs) +{ + struct getting_gossip_fd *ggf = tal(ld, struct getting_gossip_fd); + u8 *req; + + ggf->peer_fd = peer_fd; + ggf->id = *id; + ggf->cs = *cs; + + /* FIXME: set sync to `initial_routing_sync` */ + req = towire_gossipctl_get_peer_gossipfd(ggf, unique_id, true); + subd_req(ggf, ld->gossip, take(req), -1, 1, + get_peer_gossipfd_reply, ggf); +} + /* Returns true if we consider this a reconnection. */ static bool peer_reconnected(struct lightningd *ld, const struct pubkey *id, @@ -212,9 +291,6 @@ static bool peer_reconnected(struct lightningd *ld, /* We need this for init */ peer->reconnected = true; - /* FIXME: We should close peer->gossip_client_fd when we're not - * connected, and get a new one from gossipd when we reconnect. */ - switch (peer->state) { /* This can't happen. */ case UNINITIALIZED: @@ -240,15 +316,8 @@ static bool peer_reconnected(struct lightningd *ld, case CHANNELD_AWAITING_LOCKIN: case CHANNELD_NORMAL: - /* Kill off current channeld, if any */ - if (peer->owner) { - peer->owner->peer = NULL; - peer->owner = tal_free(peer->owner); - } - - /* We never re-transmit funding_signed. */ - peer_start_channeld(peer, peer->state, cs, - fd, NULL); + /* We need the gossipfd now */ + get_gossip_fd_for_reconnect(ld, id, peer->unique_id, fd, cs); return true; case SHUTDOWND_SENT: @@ -297,7 +366,6 @@ void add_peer(struct lightningd *ld, u64 unique_id, peer->unique_id = unique_id; peer->id = *id; peer->reconnected = false; - peer->gossip_client_fd = -1; peer->funding_txid = NULL; peer->remote_funding_locked = false; peer->scid = NULL; @@ -741,7 +809,7 @@ static enum watch_result funding_lockin_cb(struct peer *peer, } static void opening_got_hsm_funding_sig(struct funding_channel *fc, - int fd, + int peer_fd, int gossip_fd, const u8 *resp, const struct crypto_state *cs) { @@ -782,7 +850,7 @@ static void opening_got_hsm_funding_sig(struct funding_channel *fc, command_success(fc->cmd, null_response(fc->cmd)); /* Start normal channel daemon. */ - peer_start_channeld(fc->peer, OPENINGD, cs, fd, NULL); + peer_start_channeld(fc->peer, OPENINGD, cs, peer_fd, gossip_fd, NULL); wallet_confirm_utxos(fc->peer->ld->wallet, fc->utxomap); tal_free(fc); @@ -945,7 +1013,7 @@ static int channel_msg(struct subd *sd, const u8 *msg, const int *unused) static bool peer_start_channeld(struct peer *peer, enum peer_state old_state, const struct crypto_state *cs, - int fd, + int peer_fd, int gossip_fd, const u8 *funding_signed) { const tal_t *tmpctx = tal_tmpctx(peer); @@ -984,8 +1052,8 @@ static bool peer_start_channeld(struct peer *peer, channel_wire_type_name, channel_msg, peer_owner_finished, - take(&fd), - &peer->gossip_client_fd, + take(&peer_fd), + take(&gossip_fd), take(&hsmfd), NULL); if (!peer->owner) { log_unusual(peer->log, "Could not subdaemon channel: %s", @@ -1147,14 +1215,11 @@ static bool opening_funder_finished(struct subd *opening, const u8 *resp, fc->peer->owner = NULL; - close(peer->gossip_client_fd); - peer->gossip_client_fd = fds[1]; - if (!wire_sync_write(fc->peer->ld->hsm_fd, take(msg))) fatal("Could not write to HSM: %s", strerror(errno)); msg = hsm_sync_read(fc, fc->peer->ld); - opening_got_hsm_funding_sig(fc, fds[0], msg, &cs); + opening_got_hsm_funding_sig(fc, fds[0], fds[1], msg, &cs); /* Tell opening daemon to exit. */ return false; @@ -1208,11 +1273,8 @@ static bool opening_fundee_finished(struct subd *opening, /* Unowned. */ peer->owner = NULL; - close(peer->gossip_client_fd); - peer->gossip_client_fd = fds[1]; - /* On to normal operation! */ - peer_start_channeld(peer, OPENINGD, &cs, fds[0], funding_signed); + peer_start_channeld(peer, OPENINGD, &cs, fds[0], fds[1], funding_signed); /* Tell opening daemon to exit. */ return false; @@ -1264,7 +1326,7 @@ static void channel_config(struct lightningd *ld, /* Peer has spontaneously exited from gossip due to msg */ void peer_fundee_open(struct peer *peer, const u8 *from_peer, const struct crypto_state *cs, - int peer_fd) + int peer_fd, int gossip_fd) { struct lightningd *ld = peer->ld; u32 max_to_self_delay, max_minimum_depth; @@ -1287,7 +1349,7 @@ void peer_fundee_open(struct peer *peer, const u8 *from_peer, peer->owner = new_subd(ld, ld, "lightningd_opening", peer, opening_wire_type_name, NULL, peer_owner_finished, - take(&peer_fd), &peer->gossip_client_fd, + take(&peer_fd), take(&gossip_fd), NULL); if (!peer->owner) { peer_fail_transient(peer, "Failed to subdaemon opening: %s", @@ -1357,15 +1419,13 @@ static bool gossip_peer_released(struct subd *gossip, } assert(tal_count(fds) == 2); - fc->peer->gossip_client_fd = fds[1]; peer_set_condition(fc->peer, GOSSIPD, OPENINGD); opening = new_subd(fc->peer->ld, ld, "lightningd_opening", fc->peer, opening_wire_type_name, NULL, peer_owner_finished, - take(&fds[0]), - &fc->peer->gossip_client_fd, NULL); + take(&fds[0]), take(&fds[1]), NULL); if (!opening) { peer_fail_transient(fc->peer, "Failed to subdaemon opening: %s", strerror(errno)); diff --git a/lightningd/peer_control.h b/lightningd/peer_control.h index 1a8f76d50..daea9e73e 100644 --- a/lightningd/peer_control.h +++ b/lightningd/peer_control.h @@ -80,9 +80,6 @@ struct peer { /* Secret seed (FIXME: Move to hsm!) */ struct privkey *seed; - /* Gossip client fd, forwarded to the respective owner */ - int gossip_client_fd; - /* Reestablishment stuff: last sent commit and revocation details. */ bool last_was_revoke; struct changed_htlc *last_sent_commit; @@ -133,7 +130,7 @@ struct peer *peer_from_json(struct lightningd *ld, void peer_fundee_open(struct peer *peer, const u8 *msg, const struct crypto_state *cs, - int peer_fd); + int peer_fd, int gossip_fd); void add_peer(struct lightningd *ld, u64 unique_id, int fd, const struct pubkey *id,