Browse Source

ping: complete JSON RPC ping commands even if one ping gets no response.

We would never complete further ping commands if we had < responses
than pings.  Oops.

Fixes: #1928
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
json-streaming
Rusty Russell 6 years ago
committed by Christian Decker
parent
commit
704d30edce
  1. 1
      gossipd/gossip_wire.csv
  2. 8
      gossipd/gossipd.c
  3. 2
      lightningd/Makefile
  4. 6
      lightningd/gossip_control.c
  5. 1
      lightningd/lightningd.c
  6. 2
      lightningd/lightningd.h
  7. 63
      lightningd/ping.c
  8. 9
      lightningd/ping.h

1
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

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

8
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++;

2
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)

6
lightningd/gossip_control.c

@ -27,6 +27,7 @@
#include <lightningd/jsonrpc_errors.h>
#include <lightningd/log.h>
#include <lightningd/param.h>
#include <lightningd/ping.h>
#include <sodium/randombytes.h>
#include <string.h>
#include <wire/gen_peer_wire.h>
@ -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;

1
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()

2
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;

63
lightningd/ping.c

@ -10,28 +10,71 @@
#include <lightningd/log.h>
#include <lightningd/param.h>
#include <lightningd/peer_control.h>
#include <lightningd/ping.h>
#include <lightningd/subd.h>
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);
}

9
lightningd/ping.h

@ -0,0 +1,9 @@
#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 */
Loading…
Cancel
Save