diff --git a/channeld/channel.c b/channeld/channel.c index 4ac546ea2..a789f8f86 100644 --- a/channeld/channel.c +++ b/channeld/channel.c @@ -298,29 +298,6 @@ static void enqueue_peer_msg(struct peer *peer, const u8 *msg TAKES) msg_enqueue(&peer->peer_out, msg); } -static void gossip_in(struct peer *peer, const u8 *msg) -{ - u8 *gossip; - - if (!fromwire_gossip_send_gossip(msg, msg, &gossip)) - status_failed(STATUS_FAIL_GOSSIP_IO, - "Got bad message from gossipd: %s", - tal_hex(msg, msg)); - - if (is_msg_for_gossipd(gossip)) - enqueue_peer_msg(peer, gossip); - else if (fromwire_peektype(gossip) == WIRE_ERROR) { - struct channel_id channel_id; - char *what = sanitize_error(msg, msg, &channel_id); - peer_failed(&peer->cs, &channel_id, - "gossipd said: %s", what); - } else - status_failed(STATUS_FAIL_GOSSIP_IO, - "Got bad message type %s from gossipd: %s", - wire_type_name(fromwire_peektype(gossip)), - tal_hex(msg, msg)); -} - /* Send a temporary `channel_announcement` and `channel_update`. These * are unsigned and mainly used to tell gossip about the channel * before we have reached the `announcement_depth`, not being signed @@ -2632,8 +2609,10 @@ int main(int argc, char *argv[]) if (msg) { status_trace("Now dealing with deferred gossip %u", fromwire_peektype(msg)); - gossip_in(peer, msg); - tal_free(msg); + handle_gossip_msg(take(msg), &peer->cs, + channeld_send_reply, + channeld_io_error, + peer); continue; } @@ -2687,7 +2666,10 @@ int main(int argc, char *argv[]) status_failed(STATUS_FAIL_GOSSIP_IO, "Can't read command: %s", strerror(errno)); - gossip_in(peer, msg); + handle_gossip_msg(msg, &peer->cs, + channeld_send_reply, + channeld_io_error, + peer); } else if (FD_ISSET(PEER_FD, &rfds)) { /* This could take forever, but who cares? */ msg = channeld_read_peer_msg(peer); diff --git a/closingd/Makefile b/closingd/Makefile index fb5d5c2a2..3834f5074 100644 --- a/closingd/Makefile +++ b/closingd/Makefile @@ -66,7 +66,10 @@ CLOSINGD_COMMON_OBJS := \ common/type_to_string.o \ common/utils.o \ common/version.o \ - common/wire_error.o + common/wire_error.o \ + common/wireaddr.o \ + gossipd/gen_gossip_wire.o \ + lightningd/gossip_msg.o closingd/gen_closing_wire.h: $(WIRE_GEN) closingd/closing_wire.csv $(WIRE_GEN) --header $@ closing_wire_type < closingd/closing_wire.csv > $@ diff --git a/common/read_peer_msg.c b/common/read_peer_msg.c index 9193efa76..a90952fd6 100644 --- a/common/read_peer_msg.c +++ b/common/read_peer_msg.c @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include #include @@ -38,6 +40,38 @@ static void handle_ping(const u8 *msg, io_error(arg); } +void handle_gossip_msg_(const u8 *msg TAKES, int peer_fd, + struct crypto_state *cs, + bool (*send_msg)(struct crypto_state *cs, int fd, + const u8 *TAKES, void *arg), + void (*io_error)(void *arg), + void *arg) +{ + u8 *gossip; + + if (!fromwire_gossip_send_gossip(tmpctx, msg, &gossip)) { + status_broken("Got bad message from gossipd: %s", + tal_hex(msg, msg)); + io_error(arg); + } + + /* Gossipd can send us gossip messages, OR errors */ + if (is_msg_for_gossipd(gossip)) { + if (!send_msg(cs, peer_fd, gossip, arg)) + io_error(arg); + } else if (fromwire_peektype(gossip) == WIRE_ERROR) { + status_debug("Gossipd old us to send error"); + send_msg(cs, peer_fd, gossip, arg); + io_error(arg); + } else { + status_broken("Gossipd gave us bad send_gossip message %s", + tal_hex(msg, msg)); + io_error(arg); + } + if (taken(msg)) + tal_free(msg); +} + u8 *read_peer_msg_(const tal_t *ctx, int peer_fd, int gossip_fd, struct crypto_state *cs, @@ -49,6 +83,27 @@ u8 *read_peer_msg_(const tal_t *ctx, { u8 *msg; struct channel_id chanid; + fd_set readfds; + + FD_ZERO(&readfds); + FD_SET(peer_fd, &readfds); + FD_SET(gossip_fd, &readfds); + + select(peer_fd > gossip_fd ? peer_fd + 1 : gossip_fd + 1, + &readfds, NULL, NULL, NULL); + + if (FD_ISSET(gossip_fd, &readfds)) { + /* gossipd uses this to kill us, so not a surprise if it + happens. */ + msg = wire_sync_read(NULL, gossip_fd); + if (!msg) { + status_debug("Error reading gossip msg"); + io_error(arg); + } + + handle_gossip_msg_(msg, peer_fd, cs, send_reply, io_error, arg); + return NULL; + } msg = sync_crypto_read(ctx, cs, peer_fd); if (!msg) diff --git a/common/read_peer_msg.h b/common/read_peer_msg.h index 83f50c394..78ee219db 100644 --- a/common/read_peer_msg.h +++ b/common/read_peer_msg.h @@ -36,6 +36,24 @@ bool sync_crypto_write_arg(struct crypto_state *cs, int fd, const u8 *TAKES, /* Helper: calls peer_failed_connection_lost. */ void status_fail_io(void *unused); +/* Handler for a gossip msg; used by channeld since it queues them. */ +#define handle_gossip_msg(msg, cs, send_reply, io_error, arg) \ + handle_gossip_msg_((msg), PEER_FD, (cs), \ + typesafe_cb_preargs(bool, void *, \ + (send_reply), (arg), \ + struct crypto_state *, int, \ + const u8 *), \ + typesafe_cb(void, void *, (io_error), (arg)), \ + arg) + +void handle_gossip_msg_(const u8 *msg TAKES, + int peer_fd, + struct crypto_state *cs, + bool (*send_msg)(struct crypto_state *cs, int fd, + const u8 *TAKES, void *arg), + void (*io_error)(void *arg), + void *arg); + u8 *read_peer_msg_(const tal_t *ctx, int peer_fd, int gossip_fd, struct crypto_state *cs, diff --git a/openingd/Makefile b/openingd/Makefile index d2245a44e..d4842f6bc 100644 --- a/openingd/Makefile +++ b/openingd/Makefile @@ -67,7 +67,10 @@ OPENINGD_COMMON_OBJS := \ common/utils.o \ common/utxo.o \ common/version.o \ - common/wire_error.o + common/wire_error.o \ + common/wireaddr.o \ + gossipd/gen_gossip_wire.o \ + lightningd/gossip_msg.o $(LIGHTNINGD_OPENING_OBJS): $(LIGHTNINGD_HEADERS)