mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 21:35:11 +01:00
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>
This commit is contained in:
parent
a7d6326bef
commit
0c7ca9ab7c
@ -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:
|
||||
|
@ -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
|
||||
|
|
@ -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:
|
||||
|
@ -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 = {
|
||||
|
@ -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…
Reference in New Issue
Block a user