connectd: handle pings and pongs.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Changed: JSON_RPC: `ping` now works with connected peers, even without a channel.
This commit is contained in:
Rusty Russell 2022-01-29 14:01:32 +10:30
parent 0ac5c4f8df
commit 50eccb6a12
13 changed files with 249 additions and 247 deletions

View File

@ -29,7 +29,6 @@
#include <common/peer_failed.h>
#include <common/peer_io.h>
#include <common/per_peer_state.h>
#include <common/ping.h>
#include <common/private_channel_announcement.h>
#include <common/read_peer_msg.h>
#include <common/status.h>
@ -50,15 +49,6 @@
#define MASTER_FD STDIN_FILENO
#define HSM_FD 5
enum pong_expect_type {
/* We weren't expecting a ping reply */
PONG_UNEXPECTED = 0,
/* We were expecting a ping reply due to ping command */
PONG_EXPECTED_COMMAND = 1,
/* We were expecting a ping reply due to ping timer */
PONG_EXPECTED_PROBING = 2,
};
struct peer {
struct per_peer_state *pps;
bool funding_locked[NUM_SIDES];
@ -110,12 +100,6 @@ struct peer {
u64 commit_timer_attempts;
u32 commit_msec;
/* Random ping timer, to detect dead connections. */
struct oneshot *ping_timer;
/* Are we expecting a pong? */
enum pong_expect_type expecting_pong;
/* The feerate we want. */
u32 desired_feerate;
@ -1095,29 +1079,6 @@ static struct bitcoin_signature *calc_commitsigs(const tal_t *ctx,
return htlc_sigs;
}
/* Mutual recursion */
static void send_ping(struct peer *peer);
static void set_ping_timer(struct peer *peer)
{
peer->ping_timer = new_reltimer(&peer->timers, peer,
time_from_sec(15 + pseudorand(30)),
send_ping, peer);
}
static void send_ping(struct peer *peer)
{
/* Already have a ping in flight? */
if (peer->expecting_pong != PONG_UNEXPECTED) {
status_debug("Last ping unreturned: hanging up");
exit(0);
}
peer_write(peer->pps, take(make_ping(NULL, 1, 0)));
peer->expecting_pong = PONG_EXPECTED_PROBING;
set_ping_timer(peer);
}
/* Peer protocol doesn't want sighash flags. */
static secp256k1_ecdsa_signature *raw_sigs(const tal_t *ctx,
const struct bitcoin_signature *sigs)
@ -2190,29 +2151,6 @@ static void handle_unexpected_reestablish(struct peer *peer, const u8 *msg)
&channel_id));
}
static void handle_ping_reply(struct peer *peer, const u8 *msg)
{
u8 *ignored;
size_t i;
/* We print this out because we asked for pong, so can't spam us... */
if (!fromwire_pong(msg, msg, &ignored))
status_unusual("Got malformed ping reply %s",
tal_hex(tmpctx, msg));
/* We print this because dev versions of c-lightning embed
* version here: see check_ping_make_pong! */
for (i = 0; i < tal_count(ignored); i++) {
if (ignored[i] < ' ' || ignored[i] == 127)
break;
}
status_debug("Got pong %zu bytes (%.*s...)",
tal_count(ignored), (int)i, (char *)ignored);
wire_sync_write(MASTER_FD,
take(towire_channeld_ping_reply(NULL, true,
tal_bytelen(msg))));
}
static void peer_in(struct peer *peer, const u8 *msg)
{
enum peer_wire type = fromwire_peektype(msg);
@ -2298,19 +2236,6 @@ static void peer_in(struct peer *peer, const u8 *msg)
case WIRE_INIT_RBF:
case WIRE_ACK_RBF:
break;
case WIRE_PONG:
switch (peer->expecting_pong) {
case PONG_EXPECTED_COMMAND:
handle_ping_reply(peer, msg);
/* fall thru */
case PONG_EXPECTED_PROBING:
peer->expecting_pong = PONG_UNEXPECTED;
return;
case PONG_UNEXPECTED:
status_debug("Unexpected pong?");
return;
}
abort();
case WIRE_CHANNEL_REESTABLISH:
handle_unexpected_reestablish(peer, msg);
@ -2326,6 +2251,7 @@ static void peer_in(struct peer *peer, const u8 *msg)
case WIRE_GOSSIP_TIMESTAMP_FILTER:
case WIRE_REPLY_SHORT_CHANNEL_IDS_END:
case WIRE_PING:
case WIRE_PONG:
case WIRE_WARNING:
case WIRE_ERROR:
case WIRE_OBS2_ONION_MESSAGE:
@ -3608,57 +3534,6 @@ static void handle_send_error(struct peer *peer, const u8 *msg)
take(towire_channeld_send_error_reply(NULL)));
}
static void handle_send_ping(struct peer *peer, const u8 *msg)
{
u8 *ping;
u16 len, num_pong_bytes;
if (!fromwire_channeld_ping(msg, &num_pong_bytes, &len))
master_badmsg(WIRE_CHANNELD_PING, msg);
/* We're not supposed to send another ping until previous replied */
if (peer->expecting_pong != PONG_UNEXPECTED) {
wire_sync_write(MASTER_FD,
take(towire_channeld_ping_reply(NULL, false, 0)));
return;
}
/* It should never ask for an oversize ping. */
ping = make_ping(NULL, num_pong_bytes, len);
if (tal_count(ping) > 65535)
status_failed(STATUS_FAIL_MASTER_IO, "Oversize ping");
peer_write(peer->pps, take(ping));
/* Since we're doing this manually, kill and restart timer. */
status_debug("sending ping expecting %sresponse",
num_pong_bytes >= 65532 ? "no " : "");
/* BOLT #1:
*
* A node receiving a `ping` message:
*...
* - if `num_pong_bytes` is less than 65532:
* - MUST respond by sending a `pong` message, with `byteslen` equal
* to `num_pong_bytes`.
* - otherwise (`num_pong_bytes` is **not** less than 65532):
* - MUST ignore the `ping`.
*/
if (num_pong_bytes >= 65532) {
wire_sync_write(MASTER_FD,
take(towire_channeld_ping_reply(NULL,
true, 0)));
return;
}
/* We'll respond to lightningd once the pong comes in */
peer->expecting_pong = PONG_EXPECTED_COMMAND;
/* Restart our timed pings now. */
tal_free(peer->ping_timer);
set_ping_timer(peer);
}
#if DEVELOPER
static void handle_dev_reenable_commit(struct peer *peer)
{
@ -3757,9 +3632,6 @@ static void req_in(struct peer *peer, const u8 *msg)
case WIRE_CHANNELD_SEND_ERROR:
handle_send_error(peer, msg);
return;
case WIRE_CHANNELD_PING:
handle_send_ping(peer, msg);
return;
case WIRE_CHANNELD_CHANNEL_UPDATE:
handle_channel_update(peer, msg);
return;
@ -3798,7 +3670,6 @@ static void req_in(struct peer *peer, const u8 *msg)
case WIRE_CHANNELD_SEND_ERROR_REPLY:
case WIRE_CHANNELD_DEV_QUIESCE_REPLY:
case WIRE_CHANNELD_UPGRADED:
case WIRE_CHANNELD_PING_REPLY:
case WIRE_CHANNELD_USED_CHANNEL_UPDATE:
case WIRE_CHANNELD_LOCAL_CHANNEL_UPDATE:
case WIRE_CHANNELD_LOCAL_CHANNEL_ANNOUNCEMENT:
@ -4039,10 +3910,8 @@ int main(int argc, char *argv[])
status_setup_sync(MASTER_FD);
peer = tal(NULL, struct peer);
peer->expecting_pong = PONG_UNEXPECTED;
timers_init(&peer->timers, time_mono());
peer->commit_timer = NULL;
set_ping_timer(peer);
peer->have_sigs[LOCAL] = peer->have_sigs[REMOTE] = false;
peer->announce_depth_reached = false;
peer->channel_local_active = false;

View File

@ -266,14 +266,3 @@ msgdata,channeld_upgraded,new_type,channel_type,
# Tell peer about our latest and greatest blockheight.
msgtype,channeld_blockheight,1012
msgdata,channeld_blockheight,blockheight,u32,
# Ping/pong test. Waits for a reply if it expects one.
msgtype,channeld_ping,1030
msgdata,channeld_ping,num_pong_bytes,u16,
msgdata,channeld_ping,len,u16,
msgtype,channeld_ping_reply,1130
# False if we there was already a ping in progress.
msgdata,channeld_ping_reply,sent,bool,
# 0 == no pong expected, otherwise length of pong.
msgdata,channeld_ping_reply,totlen,u16,

Can't render this file because it has a wrong number of fields in line 13.

View File

@ -57,6 +57,7 @@ CONNECTD_COMMON_OBJS := \
common/msg_queue.o \
common/node_id.o \
common/onionreply.o \
common/ping.o \
common/per_peer_state.o \
common/psbt_open.o \
common/pseudorand.o \

View File

@ -1966,6 +1966,10 @@ static struct io_plan *recv_req(struct io_conn *conn,
peer_final_msg(conn, daemon, msg);
goto out;
case WIRE_CONNECTD_PING:
send_manual_ping(daemon, msg);
goto out;
case WIRE_CONNECTD_DEV_MEMLEAK:
#if DEVELOPER
dev_connect_memleak(daemon, msg);
@ -1978,6 +1982,7 @@ static struct io_plan *recv_req(struct io_conn *conn,
case WIRE_CONNECTD_RECONNECTED:
case WIRE_CONNECTD_CONNECT_FAILED:
case WIRE_CONNECTD_DEV_MEMLEAK_REPLY:
case WIRE_CONNECTD_PING_REPLY:
break;
}

View File

@ -27,6 +27,16 @@ struct gossip_state {
size_t off;
};
/*~ We need to know if we were expecting a pong, and why */
enum pong_expect_type {
/* We weren't expecting a ping reply */
PONG_UNEXPECTED = 0,
/* We were expecting a ping reply due to ping command */
PONG_EXPECTED_COMMAND = 1,
/* We were expecting a ping reply due to ping timer */
PONG_EXPECTED_PROBING = 2,
};
/*~ We keep a hash table (ccan/htable) of peers, which tells us what peers are
* already connected (by peer->id). */
struct peer {
@ -65,6 +75,12 @@ struct peer {
/* We stream from the gossip_store for them, when idle */
struct gossip_state gs;
/* Are we expecting a pong? */
enum pong_expect_type expecting_pong;
/* Random ping timer, to detect dead connections. */
struct oneshot *ping_timer;
#if DEVELOPER
bool dev_read_enabled;
/* If non-NULL, this counts down; 0 means disable */

View File

@ -82,3 +82,15 @@ msgtype,connectd_dev_memleak,2033
msgtype,connectd_dev_memleak_reply,2133
msgdata,connectd_dev_memleak_reply,leak,bool,
# Ping/pong test. Waits for a reply if it expects one.
msgtype,connectd_ping,2030
msgdata,connectd_ping,id,node_id,
msgdata,connectd_ping,num_pong_bytes,u16,
msgdata,connectd_ping,len,u16,
msgtype,connectd_ping_reply,2130
# False if we there was already a ping in progress.
msgdata,connectd_ping_reply,sent,bool,
# 0 == no pong expected, otherwise length of pong.
msgdata,connectd_ping_reply,totlen,u16,

1 #include <bitcoin/block.h>
82 msgdata,connectd_ping_reply,totlen,u16,
83
84
85
86
87
88
89
90
91
92
93
94
95
96

View File

@ -14,12 +14,14 @@
#include <common/gossip_store.h>
#include <common/memleak.h>
#include <common/per_peer_state.h>
#include <common/ping.h>
#include <common/status.h>
#include <common/timeout.h>
#include <common/utils.h>
#include <common/wire_error.h>
#include <connectd/connectd.h>
#include <connectd/connectd_gossipd_wiregen.h>
#include <connectd/connectd_wiregen.h>
#include <connectd/multiplex.h>
#include <errno.h>
#include <fcntl.h>
@ -337,32 +339,110 @@ again:
return NULL;
}
/* We handle gossip_timestamp_filter, and divert other gossip msgs to gossipd */
static bool handle_message_locally(struct peer *peer, const u8 *msg)
/* Mutual recursion */
static void send_ping(struct peer *peer);
static void set_ping_timer(struct peer *peer)
{
peer->ping_timer = new_reltimer(&peer->daemon->timers, peer,
time_from_sec(15 + pseudorand(30)),
send_ping, peer);
}
static void send_ping(struct peer *peer)
{
/* Already have a ping in flight? */
if (peer->expecting_pong != PONG_UNEXPECTED) {
status_peer_debug(&peer->id, "Last ping unreturned: hanging up");
if (peer->to_peer)
io_close(peer->to_peer);
return;
}
queue_peer_msg(peer, take(make_ping(NULL, 1, 0)));
peer->expecting_pong = PONG_EXPECTED_PROBING;
set_ping_timer(peer);
}
static void handle_ping_in(struct peer *peer, const u8 *msg)
{
u8 *pong;
/* gossipd doesn't log IO, so we log it here. */
status_peer_io(LOG_IO_IN, &peer->id, msg);
if (!check_ping_make_pong(NULL, msg, &pong)) {
send_warning(peer, "Invalid ping %s", tal_hex(msg, msg));
return;
}
if (pong)
queue_peer_msg(peer, take(pong));
}
static void handle_ping_reply(struct peer *peer, const u8 *msg)
{
u8 *ignored;
size_t i;
/* We print this out because we asked for pong, so can't spam us... */
if (!fromwire_pong(msg, msg, &ignored))
status_peer_unusual(&peer->id, "Got malformed ping reply %s",
tal_hex(tmpctx, msg));
/* We print this because dev versions of c-lightning embed
* version here: see check_ping_make_pong! */
for (i = 0; i < tal_count(ignored); i++) {
if (ignored[i] < ' ' || ignored[i] == 127)
break;
}
status_debug("Got pong %zu bytes (%.*s...)",
tal_count(ignored), (int)i, (char *)ignored);
daemon_conn_send(peer->daemon->master,
take(towire_connectd_ping_reply(NULL, true,
tal_bytelen(msg))));
}
static void handle_pong_in(struct peer *peer, const u8 *msg)
{
/* gossipd doesn't log IO, so we log it here. */
status_peer_io(LOG_IO_IN, &peer->id, msg);
switch (peer->expecting_pong) {
case PONG_EXPECTED_COMMAND:
handle_ping_reply(peer, msg);
/* fall thru */
case PONG_EXPECTED_PROBING:
peer->expecting_pong = PONG_UNEXPECTED;
return;
case PONG_UNEXPECTED:
status_debug("Unexpected pong?");
return;
}
abort();
}
/* Forward to gossipd */
static void handle_gossip_in(struct peer *peer, const u8 *msg)
{
u8 *gmsg = towire_gossipd_recv_gossip(NULL, &peer->id, msg);
/* gossipd doesn't log IO, so we log it here. */
status_peer_io(LOG_IO_IN, &peer->id, msg);
daemon_conn_send(peer->daemon->gossipd, take(gmsg));
}
static void handle_gossip_timetamp_filter_in(struct peer *peer, const u8 *msg)
{
struct bitcoin_blkid chain_hash;
u32 first_timestamp, timestamp_range;
/* We remember these so we don't rexmit them */
if (is_msg_gossip_broadcast(msg))
gossip_rcvd_filter_add(peer->gs.grf, msg);
if (!fromwire_gossip_timestamp_filter(msg, &chain_hash,
&first_timestamp,
&timestamp_range)) {
/* Do we want to divert to gossipd? */
if (is_msg_for_gossipd(msg)) {
u8 *gmsg = towire_gossipd_recv_gossip(NULL,
&peer->id, msg);
/* gossipd doesn't log IO, so we log it here. */
status_peer_io(LOG_IO_IN, &peer->id, msg);
daemon_conn_send(peer->daemon->gossipd, take(gmsg));
return true;
}
return false;
send_warning(peer, "gossip_timestamp_filter invalid: %s",
tal_hex(tmpctx, msg));
return;
}
/* gossipd doesn't log IO, so we log it here. */
@ -371,7 +451,7 @@ static bool handle_message_locally(struct peer *peer, const u8 *msg)
if (!bitcoin_blkid_eq(&chainparams->genesis_blockhash, &chain_hash)) {
send_warning(peer, "gossip_timestamp_filter for bad chain: %s",
tal_hex(tmpctx, msg));
return true;
return;
}
peer->gs.timestamp_min = first_timestamp;
@ -388,8 +468,35 @@ static bool handle_message_locally(struct peer *peer, const u8 *msg)
/* We send immediately the first time, after that we wait. */
if (!peer->gs.gossip_timer)
wake_gossip(peer);
}
return true;
/* We handle pings and gossip messages. */
static bool handle_message_locally(struct peer *peer, const u8 *msg)
{
enum peer_wire type = fromwire_peektype(msg);
/* We remember these so we don't rexmit them */
if (is_msg_gossip_broadcast(msg))
gossip_rcvd_filter_add(peer->gs.grf, msg);
if (type == WIRE_GOSSIP_TIMESTAMP_FILTER) {
handle_gossip_timetamp_filter_in(peer, msg);
return true;
} else if (type == WIRE_PING) {
handle_ping_in(peer, msg);
return true;
} else if (type == WIRE_PONG) {
handle_pong_in(peer, msg);
return true;
}
/* Do we want to divert to gossipd? */
if (is_msg_for_gossipd(msg)) {
handle_gossip_in(peer, msg);
return true;
}
return false;
}
static void close_timeout(struct peer *peer)
@ -665,6 +772,10 @@ struct io_plan *multiplex_peer_setup(struct io_conn *peer_conn,
* lightningd to tell us to close with the peer */
tal_add_destructor2(peer_conn, destroy_peer_conn, peer);
/* Start keepalives */
peer->expecting_pong = PONG_UNEXPECTED;
set_ping_timer(peer);
return io_duplex(peer_conn,
read_hdr_from_peer(peer_conn, peer),
write_to_peer(peer_conn, peer));
@ -677,3 +788,65 @@ void multiplex_final_msg(struct peer *peer, const u8 *final_msg TAKES)
if (!peer->to_subd)
io_wake(peer->peer_outq);
}
/* Lightningd says to send a ping */
void send_manual_ping(struct daemon *daemon, const u8 *msg)
{
u8 *ping;
struct node_id id;
u16 len, num_pong_bytes;
struct peer *peer;
if (!fromwire_connectd_ping(msg, &id, &num_pong_bytes, &len))
master_badmsg(WIRE_CONNECTD_PING, msg);
peer = peer_htable_get(&daemon->peers, &id);
if (!peer) {
daemon_conn_send(daemon->master,
take(towire_connectd_ping_reply(NULL,
false, 0)));
return;
}
/* We're not supposed to send another ping until previous replied */
if (peer->expecting_pong != PONG_UNEXPECTED) {
daemon_conn_send(daemon->master,
take(towire_connectd_ping_reply(NULL,
false, 0)));
return;
}
/* It should never ask for an oversize ping. */
ping = make_ping(NULL, num_pong_bytes, len);
if (tal_count(ping) > 65535)
status_failed(STATUS_FAIL_MASTER_IO, "Oversize ping");
queue_peer_msg(peer, take(ping));
status_debug("sending ping expecting %sresponse",
num_pong_bytes >= 65532 ? "no " : "");
/* BOLT #1:
*
* A node receiving a `ping` message:
*...
* - if `num_pong_bytes` is less than 65532:
* - MUST respond by sending a `pong` message, with `byteslen` equal
* to `num_pong_bytes`.
* - otherwise (`num_pong_bytes` is **not** less than 65532):
* - MUST ignore the `ping`.
*/
if (num_pong_bytes >= 65532) {
daemon_conn_send(daemon->master,
take(towire_connectd_ping_reply(NULL,
true, 0)));
return;
}
/* We'll respond to lightningd once the pong comes in */
peer->expecting_pong = PONG_EXPECTED_COMMAND;
/* Since we're doing this manually, kill and restart timer. */
tal_free(peer->ping_timer);
set_ping_timer(peer);
}

View File

@ -30,4 +30,7 @@ void setup_peer_gossip_store(struct peer *peer,
/* Start the process of flushing and closing the peer_conn */
void close_peer_conn(struct peer *peer);
/* When lightningd says to send a ping */
void send_manual_ping(struct daemon *daemon, const u8 *msg);
#endif /* LIGHTNING_CONNECTD_MULTIPLEX_H */

View File

@ -31,7 +31,6 @@ LIGHTNINGD_SRC := \
lightningd/peer_control.c \
lightningd/peer_fd.c \
lightningd/peer_htlcs.c \
lightningd/ping.c \
lightningd/plugin.c \
lightningd/plugin_control.c \
lightningd/plugin_hook.c \
@ -42,6 +41,7 @@ LIGHTNINGD_SRC := \
LIGHTNINGD_SRC_NOHDR := \
lightningd/datastore.c \
lightningd/ping.c \
lightningd/offer.c \
lightningd/signmessage.c

View File

@ -22,7 +22,6 @@
#include <lightningd/notification.h>
#include <lightningd/peer_control.h>
#include <lightningd/peer_fd.h>
#include <lightningd/ping.h>
#include <wire/common_wiregen.h>
static void update_feerates(struct lightningd *ld, struct channel *channel)
@ -519,9 +518,6 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds)
case WIRE_CHANNELD_SEND_ERROR_REPLY:
handle_error_channel(sd->channel, msg);
break;
case WIRE_CHANNELD_PING_REPLY:
ping_reply(sd, msg);
break;
case WIRE_CHANNELD_USED_CHANNEL_UPDATE:
/* This tells gossipd we used it. */
get_channel_update(sd->channel);
@ -565,7 +561,6 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds)
case WIRE_CHANNELD_DEV_MEMLEAK_REPLY:
case WIRE_CHANNELD_SEND_ERROR:
case WIRE_CHANNELD_DEV_QUIESCE_REPLY:
case WIRE_CHANNELD_PING:
break;
}

View File

@ -363,10 +363,12 @@ static unsigned connectd_msg(struct subd *connectd, const u8 *msg, const int *fd
case WIRE_CONNECTD_PEER_DISCONNECTED:
case WIRE_CONNECTD_DEV_MEMLEAK:
case WIRE_CONNECTD_PEER_FINAL_MSG:
case WIRE_CONNECTD_PING:
/* This is a reply, so never gets through to here. */
case WIRE_CONNECTD_INIT_REPLY:
case WIRE_CONNECTD_ACTIVATE_REPLY:
case WIRE_CONNECTD_DEV_MEMLEAK_REPLY:
case WIRE_CONNECTD_PING_REPLY:
break;
case WIRE_CONNECTD_RECONNECTED:

View File

@ -1,83 +1,39 @@
#include "config.h"
#include <channeld/channeld_wiregen.h>
#include <common/json_command.h>
#include <common/json_tok.h>
#include <common/param.h>
#include <connectd/connectd_wiregen.h>
#include <lightningd/channel.h>
#include <lightningd/jsonrpc.h>
#include <lightningd/lightningd.h>
#include <lightningd/peer_control.h>
#include <lightningd/ping.h>
#include <lightningd/subd.h>
struct ping_command {
struct list_node list;
struct node_id id;
struct command *cmd;
};
static struct ping_command *find_ping_cmd(struct lightningd *ld,
const struct node_id *id)
{
struct ping_command *i;
list_for_each(&ld->ping_commands, i, list) {
if (node_id_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 node_id *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 *channeld, const u8 *msg)
static void ping_reply(struct subd *connectd,
const u8 *msg, const int *fds,
struct command *cmd)
{
u16 totlen;
bool sent;
struct ping_command *pc;
struct channel *c = channeld->channel;
log_debug(channeld->log, "Got ping reply!");
pc = find_ping_cmd(channeld->ld, &c->peer->id);
if (!pc) {
log_broken(channeld->log, "Unexpected ping reply?");
return;
}
log_debug(connectd->log, "Got ping reply!");
if (!fromwire_channeld_ping_reply(msg, &sent, &totlen)) {
log_broken(channeld->log, "Malformed ping reply %s",
if (!fromwire_connectd_ping_reply(msg, &sent, &totlen)) {
log_broken(connectd->log, "Malformed ping reply %s",
tal_hex(tmpctx, msg));
was_pending(command_fail(pc->cmd, LIGHTNINGD,
was_pending(command_fail(cmd, LIGHTNINGD,
"Bad reply message"));
return;
}
if (!sent)
was_pending(command_fail(pc->cmd, LIGHTNINGD,
was_pending(command_fail(cmd, LIGHTNINGD,
"Ping already pending"));
else {
struct json_stream *response = json_stream_success(pc->cmd);
struct json_stream *response = json_stream_success(cmd);
json_add_num(response, "totlen", totlen);
was_pending(command_success(pc->cmd, response));
was_pending(command_success(cmd, response));
}
}
@ -88,8 +44,6 @@ static struct command_result *json_ping(struct command *cmd,
{
unsigned int *len, *pongbytes;
struct node_id *id;
struct peer *peer;
struct channel *channel;
u8 *msg;
if (!param(cmd, buffer, params,
@ -124,19 +78,11 @@ static struct command_result *json_ping(struct command *cmd,
"pongbytes %u > 65535", *pongbytes);
}
peer = peer_by_id(cmd->ld, id);
if (!peer)
if (!peer_by_id(cmd->ld, id))
return command_fail(cmd, LIGHTNINGD, "Peer not connected");
channel = peer_active_channel(peer);
if (!channel || !channel->owner || channel->state != CHANNELD_NORMAL)
return command_fail(cmd, LIGHTNINGD, "Peer bad state");
/* parent is cmd, so when we complete cmd, we free this. */
new_ping_command(cmd, cmd->ld, id, cmd);
msg = towire_channeld_ping(NULL, *pongbytes, *len);
subd_send_msg(channel->owner, take(msg));
msg = towire_connectd_ping(NULL, id, *pongbytes, *len);
subd_req(cmd, cmd->ld->connectd, take(msg), -1, 0, ping_reply, cmd);
return command_still_pending(cmd);
}

View File

@ -1,9 +0,0 @@
#ifndef LIGHTNING_LIGHTNINGD_PING_H
#define LIGHTNING_LIGHTNINGD_PING_H
#include "config.h"
#include <ccan/short_types/short_types.h>
struct subd;
void ping_reply(struct subd *subd, const u8 *msg);
#endif /* LIGHTNING_LIGHTNINGD_PING_H */