diff --git a/gossipd/gossip_wire.csv b/gossipd/gossip_wire.csv index 5e2abc5a4..45e11c494 100644 --- a/gossipd/gossip_wire.csv +++ b/gossipd/gossip_wire.csv @@ -52,6 +52,7 @@ gossip_ping,,num_pong_bytes,u16 gossip_ping,,len,u16 gossip_ping_reply,3108 +gossip_ping_reply,,id,struct pubkey # False if id in gossip_ping was unknown. gossip_ping_reply,,sent,bool # 0 == no pong expected diff --git a/gossipd/gossipd.c b/gossipd/gossipd.c index e2dcfcad0..45c00be6a 100644 --- a/gossipd/gossipd.c +++ b/gossipd/gossipd.c @@ -648,7 +648,7 @@ static void handle_pong(struct peer *peer, const u8 *pong) } daemon_conn_send(&peer->daemon->master, - take(towire_gossip_ping_reply(NULL, true, + take(towire_gossip_ping_reply(NULL, &peer->id, true, tal_count(pong)))); } @@ -1557,7 +1557,8 @@ static struct io_plan *ping_req(struct io_conn *conn, struct daemon *daemon, peer = find_peer(daemon, &id); if (!peer) { daemon_conn_send(&daemon->master, - take(towire_gossip_ping_reply(NULL, false, 0))); + take(towire_gossip_ping_reply(NULL, &id, + false, 0))); goto out; } @@ -1581,7 +1582,8 @@ static struct io_plan *ping_req(struct io_conn *conn, struct daemon *daemon, */ if (num_pong_bytes >= 65532) daemon_conn_send(&daemon->master, - take(towire_gossip_ping_reply(NULL, true, 0))); + take(towire_gossip_ping_reply(NULL, &id, + true, 0))); else peer->num_pings_outstanding++; diff --git a/lightningd/Makefile b/lightningd/Makefile index 540c2cf37..ce554d776 100644 --- a/lightningd/Makefile +++ b/lightningd/Makefile @@ -75,12 +75,12 @@ LIGHTNINGD_SRC := \ lightningd/payalgo.c \ lightningd/peer_control.c \ lightningd/peer_htlcs.c \ + lightningd/ping.c \ lightningd/subd.c \ lightningd/watch.c # Source files without corresponding headers LIGHTNINGD_SRC_NOHDR := \ - lightningd/ping.c \ lightningd/memdump.c LIGHTNINGD_OBJS := $(LIGHTNINGD_SRC:.c=.o) $(LIGHTNINGD_SRC_NOHDR:.c=.o) diff --git a/lightningd/gossip_control.c b/lightningd/gossip_control.c index f75de7001..83357b59e 100644 --- a/lightningd/gossip_control.c +++ b/lightningd/gossip_control.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -121,7 +122,6 @@ static unsigned gossip_msg(struct subd *gossip, const u8 *msg, const int *fds) case WIRE_GOSSIP_GETNODES_REPLY: case WIRE_GOSSIP_GETROUTE_REPLY: case WIRE_GOSSIP_GETCHANNELS_REPLY: - case WIRE_GOSSIP_PING_REPLY: case WIRE_GOSSIP_SCIDS_REPLY: case WIRE_GOSSIP_QUERY_CHANNEL_RANGE_REPLY: case WIRE_GOSSIP_RESOLVE_CHANNEL_REPLY: @@ -131,6 +131,10 @@ static unsigned gossip_msg(struct subd *gossip, const u8 *msg, const int *fds) case WIRE_GOSSIP_LOCAL_CHANNEL_CLOSE: break; + case WIRE_GOSSIP_PING_REPLY: + ping_reply(gossip, msg); + break; + case WIRE_GOSSIP_GET_TXOUT: get_txout(gossip, msg); break; diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index fc9c74645..336ce6e77 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -176,6 +176,7 @@ static struct lightningd *new_lightningd(const tal_t *ctx) list_head_init(&ld->waitsendpay_commands); list_head_init(&ld->sendpay_commands); list_head_init(&ld->close_commands); + list_head_init(&ld->ping_commands); /*~ Tal also explicitly supports arrays: it stores the number of * elements, which can be accessed with tal_count() (or tal_bytelen() diff --git a/lightningd/lightningd.h b/lightningd/lightningd.h index cdd90b188..bfc2b58a3 100644 --- a/lightningd/lightningd.h +++ b/lightningd/lightningd.h @@ -162,6 +162,8 @@ struct lightningd { struct list_head sendpay_commands; /* Outstanding close commands. */ struct list_head close_commands; + /* Outstanding ping commands. */ + struct list_head ping_commands; /* Maintained by invoices.c */ struct invoices *invoices; diff --git a/lightningd/ping.c b/lightningd/ping.c index c533e96b0..23cb4f251 100644 --- a/lightningd/ping.c +++ b/lightningd/ping.c @@ -10,28 +10,71 @@ #include #include #include +#include #include -static void ping_reply(struct subd *subd, const u8 *msg, const int *fds UNUSED, - struct command *cmd) +struct ping_command { + struct list_node list; + struct pubkey id; + struct command *cmd; +}; + +static struct ping_command *find_ping_cmd(struct lightningd *ld, + const struct pubkey *id) +{ + struct ping_command *i; + + list_for_each(&ld->ping_commands, i, list) { + if (pubkey_eq(id, &i->id)) + return i; + } + return NULL; +} + +static void destroy_ping_command(struct ping_command *pc) +{ + list_del(&pc->list); +} + +static struct ping_command *new_ping_command(const tal_t *ctx, + struct lightningd *ld, + const struct pubkey *peer_id, + struct command *cmd) +{ + struct ping_command *pc = tal(ctx, struct ping_command); + + pc->id = *peer_id; + pc->cmd = cmd; + list_add_tail(&ld->ping_commands, &pc->list); + tal_add_destructor(pc, destroy_ping_command); + + return pc; +} + +void ping_reply(struct subd *subd, const u8 *msg) { u16 totlen; bool ok, sent = true; + struct pubkey id; + struct ping_command *pc; log_debug(subd->ld->log, "Got ping reply!"); - ok = fromwire_gossip_ping_reply(msg, &sent, &totlen); + ok = fromwire_gossip_ping_reply(msg, &id, &sent, &totlen); + + pc = find_ping_cmd(subd->ld, &id); + assert(pc); if (!ok) - command_fail(cmd, LIGHTNINGD, "Bad reply message"); + command_fail(pc->cmd, LIGHTNINGD, "Bad reply message"); else if (!sent) - command_fail(cmd, LIGHTNINGD, "Unknown peer"); + command_fail(pc->cmd, LIGHTNINGD, "Unknown peer"); else { - struct json_result *response = new_json_result(cmd); + struct json_result *response = new_json_result(pc->cmd); json_object_start(response, NULL); json_add_num(response, "totlen", totlen); json_object_end(response); - command_success(cmd, response); + command_success(pc->cmd, response); } } @@ -76,10 +119,12 @@ static void json_ping(struct command *cmd, return; } + /* parent is cmd, so when we complete cmd, we free this. */ + new_ping_command(cmd, cmd->ld, id, cmd); + /* gossipd handles all pinging, even if it's in another daemon. */ msg = towire_gossip_ping(NULL, id, *pongbytes, *len); - subd_req(cmd->ld->gossip, cmd->ld->gossip, - take(msg), -1, 0, ping_reply, cmd); + subd_send_msg(cmd->ld->gossip, take(msg)); command_still_pending(cmd); } diff --git a/lightningd/ping.h b/lightningd/ping.h new file mode 100644 index 000000000..fec5c90ee --- /dev/null +++ b/lightningd/ping.h @@ -0,0 +1,9 @@ +#ifndef LIGHTNING_LIGHTNINGD_PING_H +#define LIGHTNING_LIGHTNINGD_PING_H +#include "config.h" +#include + +struct subd; +void ping_reply(struct subd *subd, const u8 *msg); + +#endif /* LIGHTNING_LIGHTNINGD_PING_H */