diff --git a/connectd/connectd.c b/connectd/connectd.c index 64dac1035..babdd5c00 100644 --- a/connectd/connectd.c +++ b/connectd/connectd.c @@ -2007,7 +2007,18 @@ static struct io_plan *recv_gossip(struct io_conn *conn, const u8 *msg, struct daemon *daemon) { - /* FIXME! */ + struct node_id dst; + u8 *gossip_msg; + struct peer *peer; + + if (!fromwire_gossipd_send_gossip(msg, msg, &dst, &gossip_msg)) + status_failed(STATUS_FAIL_GOSSIP_IO, "Unknown msg %i", + fromwire_peektype(msg)); + + peer = peer_htable_get(&daemon->peers, &dst); + if (peer) + queue_peer_msg(peer, take(gossip_msg)); + return daemon_conn_read_next(conn, daemon->gossipd); } diff --git a/connectd/connectd_gossipd_wire.csv b/connectd/connectd_gossipd_wire.csv index 5517b450a..bdb9a75f5 100644 --- a/connectd/connectd_gossipd_wire.csv +++ b/connectd/connectd_gossipd_wire.csv @@ -11,3 +11,15 @@ msgdata,gossipd_new_peer,gossip_queries_feature,bool, # if success: + gossip fd msgtype,gossipd_new_peer_reply,4100 msgdata,gossipd_new_peer_reply,success,bool, + +# connectd tells gossipd a gossip msg it received for peer. +msgtype,gossipd_recv_gossip,4002 +msgdata,gossipd_recv_gossip,id,node_id, +msgdata,gossipd_recv_gossip,len,u16, +msgdata,gossipd_recv_gossip,msg,byte,len + +# Gossipd asks connectd to send a gossip msg for peer. +msgtype,gossipd_send_gossip,4102 +msgdata,gossipd_send_gossip,id,node_id, +msgdata,gossipd_send_gossip,len,u16, +msgdata,gossipd_send_gossip,msg,byte,len diff --git a/gossipd/gossipd.c b/gossipd/gossipd.c index a27e6ccb8..3e90a2dae 100644 --- a/gossipd/gossipd.c +++ b/gossipd/gossipd.c @@ -118,10 +118,14 @@ void peer_supplied_good_gossip(struct peer *peer, size_t amount) peer->gossip_counter += amount; } -/* Queue a gossip message for the peer: the subdaemon on the other end simply - * forwards it to the peer. */ +/* Queue a gossip message for the peer: connectd simply forwards it to + * the peer. */ void queue_peer_msg(struct peer *peer, const u8 *msg TAKES) { + u8 *outermsg = towire_gossipd_send_gossip(NULL, &peer->id, msg); + daemon_conn_send(peer->daemon->connectd2, take(outermsg)); + + /* FIXME: backwards compat! */ daemon_conn_send(peer->dc, msg); } @@ -857,6 +861,108 @@ static struct io_plan *handle_get_address(struct io_conn *conn, return daemon_conn_read_next(conn, daemon->master); } +static void handle_recv_gossip(struct daemon *daemon, const u8 *outermsg) +{ + struct node_id id; + u8 *msg; + const u8 *err; + struct peer *peer; + + if (!fromwire_gossipd_recv_gossip(outermsg, outermsg, &id, &msg)) { + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Bad gossipd_recv_gossip msg from connectd: %s", + tal_hex(tmpctx, outermsg)); + } + + /* FIXME: happens when peer closes! */ + peer = find_peer(daemon, &id); + if (!peer) { + status_debug("connectd sent gossip msg %s for unknown peer %s", + peer_wire_name(fromwire_peektype(msg)), + type_to_string(tmpctx, struct node_id, &id)); + return; + } + + /* These are messages relayed from peer */ + switch ((enum peer_wire)fromwire_peektype(msg)) { + case WIRE_CHANNEL_ANNOUNCEMENT: + err = handle_channel_announcement_msg(peer->daemon, peer, msg); + goto handled_msg; + case WIRE_CHANNEL_UPDATE: + err = handle_channel_update_msg(peer, msg); + goto handled_msg; + case WIRE_NODE_ANNOUNCEMENT: + err = handle_node_announce(peer, msg); + goto handled_msg; + case WIRE_QUERY_CHANNEL_RANGE: + err = handle_query_channel_range(peer, msg); + goto handled_msg; + case WIRE_REPLY_CHANNEL_RANGE: + err = handle_reply_channel_range(peer, msg); + goto handled_msg; + case WIRE_QUERY_SHORT_CHANNEL_IDS: + err = handle_query_short_channel_ids(peer, msg); + goto handled_msg; + case WIRE_REPLY_SHORT_CHANNEL_IDS_END: + err = handle_reply_short_channel_ids_end(peer, msg); + goto handled_msg; + case WIRE_OBS2_ONION_MESSAGE: + err = handle_obs2_onion_message(peer, msg); + goto handled_msg; + case WIRE_ONION_MESSAGE: + err = handle_onion_message(peer, msg); + goto handled_msg; + + /* These are non-gossip messages (!is_msg_for_gossipd()) */ + case WIRE_WARNING: + case WIRE_INIT: + case WIRE_ERROR: + case WIRE_PING: + case WIRE_PONG: + case WIRE_OPEN_CHANNEL: + case WIRE_ACCEPT_CHANNEL: + case WIRE_FUNDING_CREATED: + case WIRE_FUNDING_SIGNED: + case WIRE_FUNDING_LOCKED: + case WIRE_SHUTDOWN: + case WIRE_CLOSING_SIGNED: + case WIRE_UPDATE_ADD_HTLC: + case WIRE_UPDATE_FULFILL_HTLC: + case WIRE_UPDATE_FAIL_HTLC: + case WIRE_UPDATE_FAIL_MALFORMED_HTLC: + case WIRE_COMMITMENT_SIGNED: + case WIRE_REVOKE_AND_ACK: + case WIRE_UPDATE_FEE: + case WIRE_UPDATE_BLOCKHEIGHT: + case WIRE_CHANNEL_REESTABLISH: + case WIRE_ANNOUNCEMENT_SIGNATURES: + case WIRE_GOSSIP_TIMESTAMP_FILTER: + case WIRE_TX_ADD_INPUT: + case WIRE_TX_REMOVE_INPUT: + case WIRE_TX_ADD_OUTPUT: + case WIRE_TX_REMOVE_OUTPUT: + case WIRE_TX_COMPLETE: + case WIRE_TX_SIGNATURES: + case WIRE_OPEN_CHANNEL2: + case WIRE_ACCEPT_CHANNEL2: + case WIRE_INIT_RBF: + case WIRE_ACK_RBF: +#if EXPERIMENTAL_FEATURES + case WIRE_STFU: +#endif + break; + } + + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "connectd sent unexpected gossip msg %s for peer %s", + peer_wire_name(fromwire_peektype(msg)), + type_to_string(tmpctx, struct node_id, &peer->id)); + +handled_msg: + if (err) + queue_peer_msg(peer, take(err)); +} + /*~ connectd's input handler is very simple. */ static struct io_plan *connectd_req(struct io_conn *conn, const u8 *msg, @@ -868,8 +974,11 @@ static struct io_plan *connectd_req(struct io_conn *conn, case WIRE_GOSSIPD_NEW_PEER: return connectd_new_peer(conn, daemon, msg); + /* This is not for this fd! */ + case WIRE_GOSSIPD_RECV_GOSSIP: /* We send these, don't receive them. */ case WIRE_GOSSIPD_NEW_PEER_REPLY: + case WIRE_GOSSIPD_SEND_GOSSIP: break; } @@ -878,6 +987,33 @@ static struct io_plan *connectd_req(struct io_conn *conn, return io_close(conn); } +/*~ connectd's input handler is very simple. */ +static struct io_plan *connectd_gossip_req(struct io_conn *conn, + const u8 *msg, + struct daemon *daemon) +{ + enum connectd_gossipd_wire t = fromwire_peektype(msg); + + switch (t) { + case WIRE_GOSSIPD_RECV_GOSSIP: + handle_recv_gossip(daemon, msg); + goto handled; + + /* This is not for this fd! */ + case WIRE_GOSSIPD_NEW_PEER: + /* We send these, don't receive them. */ + case WIRE_GOSSIPD_NEW_PEER_REPLY: + case WIRE_GOSSIPD_SEND_GOSSIP: + break; + } + + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Bad msg from connectd2: %s", tal_hex(tmpctx, msg)); + +handled: + return daemon_conn_read_next(conn, daemon->connectd2); +} + /* BOLT #7: * * A node: @@ -1037,6 +1173,9 @@ static void gossip_init(struct daemon *daemon, const u8 *msg) daemon->connectd = daemon_conn_new(daemon, CONNECTD_FD, connectd_req, NULL, daemon); + daemon->connectd2 = daemon_conn_new(daemon, CONNECTD2_FD, + connectd_gossip_req, NULL, daemon); + /* OK, we are ready. */ daemon_conn_send(daemon->master, take(towire_gossipd_init_reply(NULL))); diff --git a/gossipd/gossipd.h b/gossipd/gossipd.h index af1d435ae..75b39b8c6 100644 --- a/gossipd/gossipd.h +++ b/gossipd/gossipd.h @@ -9,6 +9,7 @@ #define HSM_FD 3 /* connectd asks us for help finding nodes, and gossip fds for new peers */ #define CONNECTD_FD 4 +#define CONNECTD2_FD 5 struct chan; struct channel_update_timestamps; @@ -32,6 +33,7 @@ struct daemon { /* Connection to connect daemon. */ struct daemon_conn *connectd; + struct daemon_conn *connectd2; /* Routing information */ struct routing_state *rstate; diff --git a/gossipd/test/run-onion_message.c b/gossipd/test/run-onion_message.c index 2ad7a2f3e..f1bedb5c7 100644 --- a/gossipd/test/run-onion_message.c +++ b/gossipd/test/run-onion_message.c @@ -112,6 +112,9 @@ bool fromwire_gossipd_new_peer(const void *p UNNEEDED, struct node_id *id UNNEED /* Generated stub for fromwire_gossipd_outpoint_spent */ bool fromwire_gossipd_outpoint_spent(const void *p UNNEEDED, struct short_channel_id *short_channel_id UNNEEDED) { fprintf(stderr, "fromwire_gossipd_outpoint_spent called!\n"); abort(); } +/* Generated stub for fromwire_gossipd_recv_gossip */ +bool fromwire_gossipd_recv_gossip(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct node_id *id UNNEEDED, u8 **msg UNNEEDED) +{ fprintf(stderr, "fromwire_gossipd_recv_gossip called!\n"); abort(); } /* Generated stub for fromwire_gossipd_send_onionmsg */ bool fromwire_gossipd_send_onionmsg(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, bool *obs2 UNNEEDED, struct node_id *id UNNEEDED, u8 **onion UNNEEDED, struct pubkey *blinding UNNEEDED) { fprintf(stderr, "fromwire_gossipd_send_onionmsg called!\n"); abort(); } @@ -335,6 +338,9 @@ u8 *towire_gossipd_new_blockheight_reply(const tal_t *ctx UNNEEDED) /* Generated stub for towire_gossipd_new_peer_reply */ u8 *towire_gossipd_new_peer_reply(const tal_t *ctx UNNEEDED, bool success UNNEEDED) { fprintf(stderr, "towire_gossipd_new_peer_reply called!\n"); abort(); } +/* Generated stub for towire_gossipd_send_gossip */ +u8 *towire_gossipd_send_gossip(const tal_t *ctx UNNEEDED, const struct node_id *id UNNEEDED, const u8 *msg UNNEEDED) +{ fprintf(stderr, "towire_gossipd_send_gossip called!\n"); abort(); } /* Generated stub for towire_warningfmt */ u8 *towire_warningfmt(const tal_t *ctx UNNEEDED, const struct channel_id *channel UNNEEDED,