Browse Source

gossipd: call to return all connected peers.

And we report these through the getpeers JSON RPC again (carefully: in
our reconnect tests we can get duplicates which this patch now filters
out).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 7 years ago
parent
commit
0c7ca9ab7c
  1. 29
      gossipd/gossip.c
  2. 7
      gossipd/gossip_wire.csv
  3. 2
      lightningd/gossip_control.c
  4. 94
      lightningd/peer_control.c
  5. 6
      tests/test_lightningd.py

29
gossipd/gossip.c

@ -1299,6 +1299,31 @@ static struct io_plan *addr_hint(struct io_conn *conn,
return daemon_conn_read_next(conn, &daemon->master);
}
static struct io_plan *get_peers(struct io_conn *conn,
struct daemon *daemon, const u8 *msg)
{
struct peer *peer;
size_t n = 0;
struct pubkey *id = tal_arr(conn, struct pubkey, n);
struct wireaddr *wireaddr = tal_arr(conn, struct wireaddr, n);
if (!fromwire_gossip_getpeers_request(msg, NULL))
master_badmsg(WIRE_GOSSIPCTL_PEER_ADDRHINT, msg);
list_for_each(&daemon->peers, peer, list) {
tal_resize(&id, n+1);
tal_resize(&wireaddr, n+1);
id[n] = peer->id;
wireaddr[n] = peer->addr;
n++;
}
daemon_conn_send(&daemon->master,
take(towire_gossip_getpeers_reply(conn, id, wireaddr)));
return daemon_conn_read_next(conn, &daemon->master);
}
static struct io_plan *recv_req(struct io_conn *conn, struct daemon_conn *master)
{
struct daemon *daemon = container_of(master, struct daemon, master);
@ -1342,11 +1367,15 @@ static struct io_plan *recv_req(struct io_conn *conn, struct daemon_conn *master
case WIRE_GOSSIPCTL_PEER_ADDRHINT:
return addr_hint(conn, daemon, master->msg_in);
case WIRE_GOSSIP_GETPEERS_REQUEST:
return get_peers(conn, daemon, master->msg_in);
case WIRE_GOSSIPCTL_RELEASE_PEER_REPLY:
case WIRE_GOSSIPCTL_RELEASE_PEER_REPLYFAIL:
case WIRE_GOSSIP_GETNODES_REPLY:
case WIRE_GOSSIP_GETROUTE_REPLY:
case WIRE_GOSSIP_GETCHANNELS_REPLY:
case WIRE_GOSSIP_GETPEERS_REPLY:
case WIRE_GOSSIP_PING_REPLY:
case WIRE_GOSSIP_RESOLVE_CHANNEL_REPLY:
case WIRE_GOSSIP_PEER_CONNECTED:

7
gossipd/gossip_wire.csv

@ -123,3 +123,10 @@ gossip_forwarded_msg,3010
gossip_forwarded_msg,,msglen,u16
gossip_forwarded_msg,,msg,msglen*u8
# The main daemon asks for peers
gossip_getpeers_request,3011
gossip_getpeers_reply,3111
gossip_getpeers_reply,,num,u16
gossip_getpeers_reply,,id,num*struct pubkey
gossip_getpeers_reply,,addr,num*struct wireaddr

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

2
lightningd/gossip_control.c

@ -60,6 +60,7 @@ static unsigned gossip_msg(struct subd *gossip, const u8 *msg, const int *fds)
case WIRE_GOSSIP_GETNODES_REQUEST:
case WIRE_GOSSIP_GETROUTE_REQUEST:
case WIRE_GOSSIP_GETCHANNELS_REQUEST:
case WIRE_GOSSIP_GETPEERS_REQUEST:
case WIRE_GOSSIP_PING:
case WIRE_GOSSIP_RESOLVE_CHANNEL_REQUEST:
case WIRE_GOSSIP_FORWARDED_MSG:
@ -71,6 +72,7 @@ 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_GETPEERS_REPLY:
case WIRE_GOSSIP_PING_REPLY:
case WIRE_GOSSIP_RESOLVE_CHANNEL_REPLY:
case WIRE_GOSSIPCTL_RELEASE_PEER_REPLY:

94
lightningd/peer_control.c

@ -786,34 +786,31 @@ static void log_to_json(unsigned int skipped,
json_add_string(info->response, NULL, log);
}
static void json_getpeers(struct command *cmd,
const char *buffer, const jsmntok_t *params)
struct getpeers_args {
struct command *cmd;
/* If non-NULL, they want logs too */
enum log_level *ll;
};
static void gossipd_getpeers_complete(struct subd *gossip, const u8 *msg,
const int *fds,
struct getpeers_args *gpa)
{
/* This is a little sneaky... */
struct pubkey *ids;
struct wireaddr *addrs;
struct json_result *response = new_json_result(gpa->cmd);
struct peer *p;
struct json_result *response = new_json_result(cmd);
jsmntok_t *leveltok;
struct log_info info;
json_get_params(buffer, params, "?level", &leveltok, NULL);
if (!leveltok)
;
else if (json_tok_streq(buffer, leveltok, "debug"))
info.level = LOG_DBG;
else if (json_tok_streq(buffer, leveltok, "info"))
info.level = LOG_INFORM;
else if (json_tok_streq(buffer, leveltok, "unusual"))
info.level = LOG_UNUSUAL;
else if (json_tok_streq(buffer, leveltok, "broken"))
info.level = LOG_BROKEN;
else {
command_fail(cmd, "Invalid level param");
if (!fromwire_gossip_getpeers_reply(msg, msg, NULL, &ids, &addrs)) {
command_fail(gpa->cmd, "Bad response from gossipd");
return;
}
/* First the peers not just gossiping. */
json_object_start(response, NULL);
json_array_start(response, "peers");
list_for_each(&cmd->ld->peers, p, list) {
list_for_each(&gpa->cmd->ld->peers, p, list) {
json_object_start(response, NULL);
json_add_string(response, "state", peer_state_name(p->state));
json_add_string(response, "netaddr",
@ -832,7 +829,9 @@ static void json_getpeers(struct command *cmd,
p->funding_satoshi * 1000);
}
if (leveltok) {
if (gpa->ll) {
struct log_info info;
info.level = *gpa->ll;
info.response = response;
json_array_start(response, "log");
log_each_line(p->log_book, log_to_json, &info);
@ -840,9 +839,60 @@ static void json_getpeers(struct command *cmd,
}
json_object_end(response);
}
for (size_t i = 0; i < tal_count(ids); i++) {
/* Don't report peers in both, which can happen if they're
* reconnecting */
if (peer_by_id(gpa->cmd->ld, ids + i))
continue;
json_object_start(response, NULL);
/* Fake state. */
json_add_string(response, "state", "GOSSIPING");
json_add_pubkey(response, "peerid", ids+i);
json_add_string(response, "netaddr",
type_to_string(response, struct wireaddr,
addrs + i));
json_add_bool(response, "connected", "true");
json_add_string(response, "owner", gossip->name);
json_object_end(response);
}
json_array_end(response);
json_object_end(response);
command_success(cmd, response);
command_success(gpa->cmd, response);
}
static void json_getpeers(struct command *cmd,
const char *buffer, const jsmntok_t *params)
{
jsmntok_t *leveltok;
struct getpeers_args *gpa = tal(cmd, struct getpeers_args);
gpa->cmd = cmd;
json_get_params(buffer, params, "?level", &leveltok, NULL);
if (leveltok) {
gpa->ll = tal(gpa, enum log_level);
if (json_tok_streq(buffer, leveltok, "debug"))
*gpa->ll = LOG_DBG;
else if (json_tok_streq(buffer, leveltok, "info"))
*gpa->ll = LOG_INFORM;
else if (json_tok_streq(buffer, leveltok, "unusual"))
*gpa->ll = LOG_UNUSUAL;
else if (json_tok_streq(buffer, leveltok, "broken"))
*gpa->ll = LOG_BROKEN;
else {
command_fail(cmd, "Invalid level param");
return;
}
} else
gpa->ll = NULL;
/* Get peers from gossipd. */
subd_req(cmd, cmd->ld->gossip,
take(towire_gossip_getpeers_request(cmd)),
-1, 0, gossipd_getpeers_complete, gpa);
}
static const struct json_command getpeers_command = {

6
tests/test_lightningd.py

@ -279,9 +279,9 @@ class LightningDTests(BaseLightningDTests):
def test_connect(self):
l1,l2 = self.connect()
# Main daemon has no idea about these peers; they're in gossipd.
assert l1.rpc.getpeer(l2.info['id'], 'info') == None
assert l2.rpc.getpeer(l1.info['id'], 'info') == None
# These should be in gossipd.
assert l1.rpc.getpeer(l2.info['id'])['state'] == 'GOSSIPING'
assert l2.rpc.getpeer(l1.info['id'])['state'] == 'GOSSIPING'
# Both gossipds will have them as new peers once handed back.
l1.daemon.wait_for_log('handle_peer {}: new peer'.format(l2.info['id']))

Loading…
Cancel
Save