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,,len,u16
gossip_ping_reply,3108 gossip_ping_reply,3108
gossip_ping_reply,,id,struct pubkey
# False if id in gossip_ping was unknown. # False if id in gossip_ping was unknown.
gossip_ping_reply,,sent,bool gossip_ping_reply,,sent,bool
# 0 == no pong expected # 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, 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)))); 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); peer = find_peer(daemon, &id);
if (!peer) { if (!peer) {
daemon_conn_send(&daemon->master, daemon_conn_send(&daemon->master,
take(towire_gossip_ping_reply(NULL, false, 0))); take(towire_gossip_ping_reply(NULL, &id,
false, 0)));
goto out; goto out;
} }
@ -1581,7 +1582,8 @@ static struct io_plan *ping_req(struct io_conn *conn, struct daemon *daemon,
*/ */
if (num_pong_bytes >= 65532) if (num_pong_bytes >= 65532)
daemon_conn_send(&daemon->master, daemon_conn_send(&daemon->master,
take(towire_gossip_ping_reply(NULL, true, 0))); take(towire_gossip_ping_reply(NULL, &id,
true, 0)));
else else
peer->num_pings_outstanding++; peer->num_pings_outstanding++;

2
lightningd/Makefile

@ -75,12 +75,12 @@ LIGHTNINGD_SRC := \
lightningd/payalgo.c \ lightningd/payalgo.c \
lightningd/peer_control.c \ lightningd/peer_control.c \
lightningd/peer_htlcs.c \ lightningd/peer_htlcs.c \
lightningd/ping.c \
lightningd/subd.c \ lightningd/subd.c \
lightningd/watch.c lightningd/watch.c
# Source files without corresponding headers # Source files without corresponding headers
LIGHTNINGD_SRC_NOHDR := \ LIGHTNINGD_SRC_NOHDR := \
lightningd/ping.c \
lightningd/memdump.c lightningd/memdump.c
LIGHTNINGD_OBJS := $(LIGHTNINGD_SRC:.c=.o) $(LIGHTNINGD_SRC_NOHDR:.c=.o) 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/jsonrpc_errors.h>
#include <lightningd/log.h> #include <lightningd/log.h>
#include <lightningd/param.h> #include <lightningd/param.h>
#include <lightningd/ping.h>
#include <sodium/randombytes.h> #include <sodium/randombytes.h>
#include <string.h> #include <string.h>
#include <wire/gen_peer_wire.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_GETNODES_REPLY:
case WIRE_GOSSIP_GETROUTE_REPLY: case WIRE_GOSSIP_GETROUTE_REPLY:
case WIRE_GOSSIP_GETCHANNELS_REPLY: case WIRE_GOSSIP_GETCHANNELS_REPLY:
case WIRE_GOSSIP_PING_REPLY:
case WIRE_GOSSIP_SCIDS_REPLY: case WIRE_GOSSIP_SCIDS_REPLY:
case WIRE_GOSSIP_QUERY_CHANNEL_RANGE_REPLY: case WIRE_GOSSIP_QUERY_CHANNEL_RANGE_REPLY:
case WIRE_GOSSIP_RESOLVE_CHANNEL_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: case WIRE_GOSSIP_LOCAL_CHANNEL_CLOSE:
break; break;
case WIRE_GOSSIP_PING_REPLY:
ping_reply(gossip, msg);
break;
case WIRE_GOSSIP_GET_TXOUT: case WIRE_GOSSIP_GET_TXOUT:
get_txout(gossip, msg); get_txout(gossip, msg);
break; 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->waitsendpay_commands);
list_head_init(&ld->sendpay_commands); list_head_init(&ld->sendpay_commands);
list_head_init(&ld->close_commands); list_head_init(&ld->close_commands);
list_head_init(&ld->ping_commands);
/*~ Tal also explicitly supports arrays: it stores the number of /*~ Tal also explicitly supports arrays: it stores the number of
* elements, which can be accessed with tal_count() (or tal_bytelen() * 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; struct list_head sendpay_commands;
/* Outstanding close commands. */ /* Outstanding close commands. */
struct list_head close_commands; struct list_head close_commands;
/* Outstanding ping commands. */
struct list_head ping_commands;
/* Maintained by invoices.c */ /* Maintained by invoices.c */
struct invoices *invoices; struct invoices *invoices;

63
lightningd/ping.c

@ -10,28 +10,71 @@
#include <lightningd/log.h> #include <lightningd/log.h>
#include <lightningd/param.h> #include <lightningd/param.h>
#include <lightningd/peer_control.h> #include <lightningd/peer_control.h>
#include <lightningd/ping.h>
#include <lightningd/subd.h> #include <lightningd/subd.h>
static void ping_reply(struct subd *subd, const u8 *msg, const int *fds UNUSED, struct ping_command {
struct command *cmd) 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; u16 totlen;
bool ok, sent = true; bool ok, sent = true;
struct pubkey id;
struct ping_command *pc;
log_debug(subd->ld->log, "Got ping reply!"); 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) if (!ok)
command_fail(cmd, LIGHTNINGD, "Bad reply message"); command_fail(pc->cmd, LIGHTNINGD, "Bad reply message");
else if (!sent) else if (!sent)
command_fail(cmd, LIGHTNINGD, "Unknown peer"); command_fail(pc->cmd, LIGHTNINGD, "Unknown peer");
else { else {
struct json_result *response = new_json_result(cmd); struct json_result *response = new_json_result(pc->cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
json_add_num(response, "totlen", totlen); json_add_num(response, "totlen", totlen);
json_object_end(response); 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; 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. */ /* gossipd handles all pinging, even if it's in another daemon. */
msg = towire_gossip_ping(NULL, id, *pongbytes, *len); msg = towire_gossip_ping(NULL, id, *pongbytes, *len);
subd_req(cmd->ld->gossip, cmd->ld->gossip, subd_send_msg(cmd->ld->gossip, take(msg));
take(msg), -1, 0, ping_reply, cmd);
command_still_pending(cmd); 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