mirror of
https://github.com/aljazceru/lightning.git
synced 2026-02-18 20:44:27 +01:00
gossipd: fail peer for the master daemon.
This fixes the only case where the master currently has to write directly to the peer: re-sending an error. We make gossipd do it, by adding a new gossipctl_fail_peer message. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
committed by
Christian Decker
parent
2394c9a2e7
commit
f172be71dc
@@ -99,14 +99,15 @@ static void destroy_peer(struct peer *peer)
|
||||
}
|
||||
}
|
||||
|
||||
static struct peer *setup_new_peer(struct daemon *daemon, const u8 *msg)
|
||||
static struct peer *setup_new_peer(struct daemon *daemon,
|
||||
u64 unique_id,
|
||||
const struct crypto_state *cs)
|
||||
{
|
||||
struct peer *peer = tal(daemon, struct peer);
|
||||
|
||||
init_peer_crypto_state(peer, &peer->pcs);
|
||||
if (!fromwire_gossipctl_new_peer(msg, NULL, &peer->unique_id,
|
||||
&peer->pcs.cs))
|
||||
return tal_free(peer);
|
||||
peer->pcs.cs = *cs;
|
||||
peer->unique_id = unique_id;
|
||||
peer->daemon = daemon;
|
||||
peer->error = NULL;
|
||||
peer->local = true;
|
||||
@@ -115,6 +116,7 @@ static struct peer *setup_new_peer(struct daemon *daemon, const u8 *msg)
|
||||
msg_queue_init(&peer->peer_out, peer);
|
||||
list_add_tail(&daemon->peers, &peer->list);
|
||||
tal_add_destructor(peer, destroy_peer);
|
||||
|
||||
wake_pkt_out(peer);
|
||||
return peer;
|
||||
}
|
||||
@@ -416,10 +418,14 @@ static struct io_plan *new_peer_got_fd(struct io_conn *conn, struct peer *peer)
|
||||
static struct io_plan *new_peer(struct io_conn *conn, struct daemon *daemon,
|
||||
const u8 *msg)
|
||||
{
|
||||
struct peer *peer = setup_new_peer(daemon, msg);
|
||||
if (!peer)
|
||||
status_failed(STATUS_FAIL_MASTER_IO,
|
||||
"bad gossipctl_new_peer: %s", tal_hex(trc, msg));
|
||||
struct peer *peer;
|
||||
struct crypto_state cs;
|
||||
u64 unique_id;
|
||||
|
||||
if (!fromwire_gossipctl_new_peer(msg, NULL, &unique_id, &cs))
|
||||
master_badmsg(WIRE_GOSSIPCTL_NEW_PEER, msg);
|
||||
|
||||
peer = setup_new_peer(daemon, unique_id, &cs);
|
||||
return io_recv_fd(conn, &peer->fd, new_peer_got_fd, peer);
|
||||
}
|
||||
|
||||
@@ -433,6 +439,45 @@ static struct peer *find_peer(struct daemon *daemon, u64 unique_id)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* We send error, then close. */
|
||||
static struct io_plan *peer_send_error(struct io_conn *conn, struct peer *peer)
|
||||
{
|
||||
const u8 *out = msg_dequeue(&peer->peer_out);
|
||||
return peer_write_message(conn, &peer->pcs, take(out),
|
||||
(void *)io_close_cb);
|
||||
}
|
||||
|
||||
static struct io_plan *fail_peer_got_fd(struct io_conn *conn, struct peer *peer)
|
||||
{
|
||||
peer->conn = io_new_conn(conn, peer->fd, peer_send_error, peer);
|
||||
if (!peer->conn) {
|
||||
peer->error = "Could not create connection";
|
||||
tal_free(peer);
|
||||
} else {
|
||||
/* If conn dies, we forget peer. */
|
||||
tal_steal(peer->conn, peer);
|
||||
}
|
||||
return daemon_conn_read_next(conn, &peer->daemon->master);
|
||||
}
|
||||
|
||||
static struct io_plan *fail_peer(struct io_conn *conn, struct daemon *daemon,
|
||||
const u8 *msg)
|
||||
{
|
||||
struct peer *peer;
|
||||
struct crypto_state cs;
|
||||
u64 unique_id;
|
||||
u8 *failmsg;
|
||||
|
||||
if (!fromwire_gossipctl_fail_peer(msg, msg, NULL, &unique_id, &cs,
|
||||
&failmsg))
|
||||
master_badmsg(WIRE_GOSSIPCTL_FAIL_PEER, msg);
|
||||
|
||||
peer = setup_new_peer(daemon, unique_id, &cs);
|
||||
msg_enqueue(&peer->peer_out, take(failmsg));
|
||||
|
||||
return io_recv_fd(conn, &peer->fd, fail_peer_got_fd, peer);
|
||||
}
|
||||
|
||||
static struct io_plan *release_peer(struct io_conn *conn, struct daemon *daemon,
|
||||
const u8 *msg)
|
||||
{
|
||||
@@ -742,6 +787,10 @@ static struct io_plan *recv_req(struct io_conn *conn, struct daemon_conn *master
|
||||
case WIRE_GOSSIP_FORWARDED_MSG:
|
||||
handle_forwarded_msg(conn, daemon, daemon->master.msg_in);
|
||||
return daemon_conn_read_next(conn, &daemon->master);
|
||||
|
||||
case WIRE_GOSSIPCTL_FAIL_PEER:
|
||||
return fail_peer(conn, daemon, master->msg_in);
|
||||
|
||||
case WIRE_GOSSIPCTL_RELEASE_PEER_REPLY:
|
||||
case WIRE_GOSSIPCTL_RELEASE_PEER_REPLYFAIL:
|
||||
case WIRE_GOSSIPCTL_GET_PEER_GOSSIPFD_REPLY:
|
||||
|
||||
@@ -18,7 +18,6 @@ gossipctl_init,,broadcast_interval,u32
|
||||
gossipctl_init,,chain_hash,struct sha256_double
|
||||
|
||||
# These take an fd, but have no response
|
||||
# (if it is to move onto a channel, we get a status msg).
|
||||
gossipctl_new_peer,3001
|
||||
gossipctl_new_peer,,unique_id,u64
|
||||
gossipctl_new_peer,,crypto_state,struct crypto_state
|
||||
@@ -112,3 +111,10 @@ gossipctl_get_peer_gossipfd_reply,3112
|
||||
|
||||
# Failure (can't make new socket)
|
||||
gossipctl_get_peer_gossipfd_replyfail,3212
|
||||
|
||||
# Send canned message to peer and fail it.
|
||||
gossipctl_fail_peer,3013
|
||||
gossipctl_fail_peer,,unique_id,u64
|
||||
gossipctl_fail_peer,,crypto_state,struct crypto_state
|
||||
gossipctl_fail_peer,,len,u16
|
||||
gossipctl_fail_peer,,failmsg,len*u8
|
||||
|
||||
|
@@ -18,7 +18,6 @@ LIGHTNINGD_COMMON_OBJS := \
|
||||
common/channel_config.o \
|
||||
common/configdir.o \
|
||||
common/crypto_state.o \
|
||||
common/cryptomsg.o \
|
||||
common/derive_basepoints.o \
|
||||
common/funding_tx.o \
|
||||
common/htlc_state.o \
|
||||
|
||||
@@ -95,6 +95,7 @@ static int gossip_msg(struct subd *gossip, const u8 *msg, const int *fds)
|
||||
/* These are messages we send, not them. */
|
||||
case WIRE_GOSSIPCTL_INIT:
|
||||
case WIRE_GOSSIPCTL_NEW_PEER:
|
||||
case WIRE_GOSSIPCTL_FAIL_PEER:
|
||||
case WIRE_GOSSIPCTL_RELEASE_PEER:
|
||||
case WIRE_GOSSIPCTL_DROP_PEER:
|
||||
case WIRE_GOSSIPCTL_GET_PEER_GOSSIPFD:
|
||||
|
||||
@@ -262,34 +262,6 @@ static void peer_start_closingd(struct peer *peer,
|
||||
int peer_fd, int gossip_fd,
|
||||
bool reconnected);
|
||||
|
||||
/* FIXME: Fake NOP dev_disconnect/dev_sabotage_fd for below. */
|
||||
enum dev_disconnect dev_disconnect(int pkt_type)
|
||||
{
|
||||
return DEV_DISCONNECT_NORMAL;
|
||||
}
|
||||
|
||||
void dev_sabotage_fd(int fd)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
void dev_blackhole_fd(int fd)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
/* Send (encrypted) error message, then close. */
|
||||
static struct io_plan *send_error(struct io_conn *conn,
|
||||
struct peer_crypto_state *pcs)
|
||||
{
|
||||
log_debug(pcs->peer->log, "Sending canned error");
|
||||
/* FIXME: This is the only place where master talks directly to peer;
|
||||
* and pulls in quite a lot of code to do so. If we got a subdaemon
|
||||
* to do this work, we'd avoid pulling in cryptomsg.o and the fake
|
||||
* dev_disconnect. */
|
||||
return peer_write_message(conn, pcs, pcs->peer->error, (void *)io_close_cb);
|
||||
}
|
||||
|
||||
/* FIXME:
|
||||
*
|
||||
* This is a lot of code duplication! We should turn gossipd into welcomed(?):
|
||||
@@ -483,10 +455,14 @@ static bool peer_reconnected(struct lightningd *ld,
|
||||
* retransmit the error packet and ignore any other packets for that
|
||||
* channel, and the following requirements do not apply. */
|
||||
if (peer->error) {
|
||||
struct peer_crypto_state *pcs = tal(peer, struct peer_crypto_state);
|
||||
init_peer_crypto_state(peer, pcs);
|
||||
pcs->cs = *cs;
|
||||
tal_steal(io_new_conn(peer, fd, send_error, pcs), pcs);
|
||||
/* FIXME: we should do this in response to reestablish, unless
|
||||
* global error */
|
||||
log_debug(peer->log, "Sending canned error");
|
||||
subd_send_msg(peer->ld->gossip,
|
||||
take(towire_gossipctl_fail_peer(peer,
|
||||
peer->unique_id,
|
||||
cs, peer->error)));
|
||||
subd_send_fd(peer->ld->gossip, fd);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user