mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 05:12:45 +01:00
peer_fail: handle incoming reconnections.
We kill the existing connection if possible; this may mean simply forgetting the prior peer altogether if it's in an early state. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
3126eed4de
commit
f4722e93a0
@ -144,6 +144,7 @@ static void send_peer_with_fds(struct peer *peer, const u8 *msg)
|
|||||||
|
|
||||||
/* Now we talk to socket to get to peer's owner daemon. */
|
/* Now we talk to socket to get to peer's owner daemon. */
|
||||||
peer->local = false;
|
peer->local = false;
|
||||||
|
/* FIXME: Forget peer if other end is closed. */
|
||||||
daemon_conn_init(peer, &peer->owner_conn, fds[0], owner_msg_in);
|
daemon_conn_init(peer, &peer->owner_conn, fds[0], owner_msg_in);
|
||||||
peer->owner_conn.msg_queue_cleared_cb = nonlocal_dump_gossip;
|
peer->owner_conn.msg_queue_cleared_cb = nonlocal_dump_gossip;
|
||||||
|
|
||||||
|
@ -69,13 +69,23 @@ void peer_fail(struct peer *peer, const char *fmt, ...)
|
|||||||
if (!peer_persists(peer)) {
|
if (!peer_persists(peer)) {
|
||||||
log_info(peer->log, "Only reached state %s: forgetting",
|
log_info(peer->log, "Only reached state %s: forgetting",
|
||||||
peer_state_name(peer->state));
|
peer_state_name(peer->state));
|
||||||
tal_free(peer);
|
goto dont_talk;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reconnect unless we've dropped to chain. */
|
/* Reconnect unless we've dropped to chain. */
|
||||||
if (!peer_on_chain(peer))
|
if (!peer_on_chain(peer)) {
|
||||||
peer_reconnect(peer);
|
peer_reconnect(peer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dont_talk:
|
||||||
|
/* In case we reconnected in the meantime. */
|
||||||
|
if (peer->fd != -1) {
|
||||||
|
/* FIXME: We should retransmit error if this happens. */
|
||||||
|
close(peer->fd);
|
||||||
|
}
|
||||||
|
tal_free(peer);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void peer_set_condition(struct peer *peer, enum peer_state old_state,
|
void peer_set_condition(struct peer *peer, enum peer_state old_state,
|
||||||
@ -90,14 +100,137 @@ void peer_set_condition(struct peer *peer, enum peer_state old_state,
|
|||||||
peer->state = state;
|
peer->state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool peer_start_channeld_hsmfd(struct subd *hsm, const u8 *resp,
|
||||||
|
const int *fds,
|
||||||
|
struct peer *peer);
|
||||||
|
|
||||||
|
/* Returns true if we consider this a reconnection. */
|
||||||
|
static bool peer_reconnected(struct lightningd *ld,
|
||||||
|
const struct pubkey *id,
|
||||||
|
int fd,
|
||||||
|
const struct crypto_state *cs)
|
||||||
|
{
|
||||||
|
struct peer *peer = peer_by_id(ld, id);
|
||||||
|
if (!peer)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
log_info(peer->log, "Peer has reconnected, state %s",
|
||||||
|
peer_state_name(peer->state));
|
||||||
|
|
||||||
|
/* Always copy cryptostate; at worst we'll throw it away. */
|
||||||
|
tal_free(peer->cs);
|
||||||
|
peer->cs = tal_dup(peer, struct crypto_state, cs);
|
||||||
|
|
||||||
|
switch (peer->state) {
|
||||||
|
/* This can't happen. */
|
||||||
|
case UNINITIALIZED:
|
||||||
|
abort();
|
||||||
|
|
||||||
|
case GOSSIPD:
|
||||||
|
/* Tell gossipd to kick that one out, will call peer_fail */
|
||||||
|
subd_send_msg(peer->ld->gossip,
|
||||||
|
take(towire_gossipctl_fail_peer(peer,
|
||||||
|
peer->unique_id)));
|
||||||
|
tal_free(peer);
|
||||||
|
/* Continue with a new peer. */
|
||||||
|
return false;
|
||||||
|
|
||||||
|
case OPENINGD:
|
||||||
|
/* Kill off openingd, forget old peer. */
|
||||||
|
peer->owner->peer = NULL;
|
||||||
|
tal_free(peer->owner);
|
||||||
|
tal_free(peer);
|
||||||
|
|
||||||
|
/* A fresh start. */
|
||||||
|
return false;
|
||||||
|
|
||||||
|
case GETTING_SIG_FROM_HSM:
|
||||||
|
/* BOLT #2:
|
||||||
|
*
|
||||||
|
* On disconnection, the funder MUST remember the channel for
|
||||||
|
* reconnection if it has broadcast the funding transaction,
|
||||||
|
* otherwise it MUST NOT.
|
||||||
|
*/
|
||||||
|
/* Free peer, which will discard HSM response. */
|
||||||
|
tal_free(peer);
|
||||||
|
|
||||||
|
/* Start afresh */
|
||||||
|
return false;
|
||||||
|
|
||||||
|
case GETTING_HSMFD:
|
||||||
|
/* Simply substitute old fd for new one. */
|
||||||
|
assert(peer->fd != -1);
|
||||||
|
close(peer->fd);
|
||||||
|
peer->fd = fd;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case CHANNELD_AWAITING_LOCKIN:
|
||||||
|
/* Kill off current channeld, if any. */
|
||||||
|
if (peer->owner) {
|
||||||
|
peer->owner->peer = NULL;
|
||||||
|
peer->owner = tal_free(peer->owner);
|
||||||
|
}
|
||||||
|
assert(peer->fd == -1);
|
||||||
|
peer->fd = fd;
|
||||||
|
|
||||||
|
/* Start a new one: first get fresh hsm fd. */
|
||||||
|
peer_set_condition(peer, CHANNELD_AWAITING_LOCKIN,
|
||||||
|
GETTING_HSMFD);
|
||||||
|
|
||||||
|
/* Get fd from hsm. */
|
||||||
|
subd_req(peer, peer->ld->hsm,
|
||||||
|
take(towire_hsmctl_hsmfd_channeld(peer,
|
||||||
|
peer->unique_id)),
|
||||||
|
-1, 1, peer_start_channeld_hsmfd, peer);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case CHANNELD_NORMAL:
|
||||||
|
/* Kill off current channeld, if any */
|
||||||
|
if (peer->owner) {
|
||||||
|
peer->owner->peer = NULL;
|
||||||
|
peer->owner = tal_free(peer->owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(peer->fd == -1);
|
||||||
|
peer->fd = fd;
|
||||||
|
|
||||||
|
/* Start a new one: first get fresh hsm fd. */
|
||||||
|
peer_set_condition(peer, CHANNELD_NORMAL, GETTING_HSMFD);
|
||||||
|
|
||||||
|
/* FIXME: Needs to reload state! */
|
||||||
|
/* Get fd from hsm. */
|
||||||
|
subd_req(peer, peer->ld->hsm,
|
||||||
|
take(towire_hsmctl_hsmfd_channeld(peer,
|
||||||
|
peer->unique_id)),
|
||||||
|
-1, 1, peer_start_channeld_hsmfd, peer);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case SHUTDOWND_SENT:
|
||||||
|
case SHUTDOWND_RCVD:
|
||||||
|
case CLOSINGD_SIGEXCHANGE:
|
||||||
|
case ONCHAIND_CHEATED:
|
||||||
|
case ONCHAIND_THEIR_UNILATERAL:
|
||||||
|
case ONCHAIND_OUR_UNILATERAL:
|
||||||
|
case ONCHAIND_MUTUAL:
|
||||||
|
; /* FIXME: Implement! */
|
||||||
|
}
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
void add_peer(struct lightningd *ld, u64 unique_id,
|
void add_peer(struct lightningd *ld, u64 unique_id,
|
||||||
int fd, const struct pubkey *id,
|
int fd, const struct pubkey *id,
|
||||||
const struct crypto_state *cs)
|
const struct crypto_state *cs)
|
||||||
{
|
{
|
||||||
struct peer *peer = tal(ld, struct peer);
|
struct peer *peer;
|
||||||
const char *netname, *idname;
|
const char *netname, *idname;
|
||||||
u8 *msg;
|
u8 *msg;
|
||||||
|
|
||||||
|
/* It's a reconnect? */
|
||||||
|
if (peer_reconnected(ld, id, fd, cs))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Fresh peer. */
|
||||||
|
peer = tal(ld, struct peer);
|
||||||
peer->ld = ld;
|
peer->ld = ld;
|
||||||
peer->unique_id = unique_id;
|
peer->unique_id = unique_id;
|
||||||
peer->owner = NULL;
|
peer->owner = NULL;
|
||||||
|
Loading…
Reference in New Issue
Block a user