mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-20 15:44:21 +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:
@@ -1299,6 +1299,31 @@ static struct io_plan *addr_hint(struct io_conn *conn,
|
|||||||
return daemon_conn_read_next(conn, &daemon->master);
|
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)
|
static struct io_plan *recv_req(struct io_conn *conn, struct daemon_conn *master)
|
||||||
{
|
{
|
||||||
struct daemon *daemon = container_of(master, struct daemon, 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:
|
case WIRE_GOSSIPCTL_PEER_ADDRHINT:
|
||||||
return addr_hint(conn, daemon, master->msg_in);
|
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_REPLY:
|
||||||
case WIRE_GOSSIPCTL_RELEASE_PEER_REPLYFAIL:
|
case WIRE_GOSSIPCTL_RELEASE_PEER_REPLYFAIL:
|
||||||
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_GETPEERS_REPLY:
|
||||||
case WIRE_GOSSIP_PING_REPLY:
|
case WIRE_GOSSIP_PING_REPLY:
|
||||||
case WIRE_GOSSIP_RESOLVE_CHANNEL_REPLY:
|
case WIRE_GOSSIP_RESOLVE_CHANNEL_REPLY:
|
||||||
case WIRE_GOSSIP_PEER_CONNECTED:
|
case WIRE_GOSSIP_PEER_CONNECTED:
|
||||||
|
|||||||
@@ -123,3 +123,10 @@ gossip_forwarded_msg,3010
|
|||||||
gossip_forwarded_msg,,msglen,u16
|
gossip_forwarded_msg,,msglen,u16
|
||||||
gossip_forwarded_msg,,msg,msglen*u8
|
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_GETNODES_REQUEST:
|
||||||
case WIRE_GOSSIP_GETROUTE_REQUEST:
|
case WIRE_GOSSIP_GETROUTE_REQUEST:
|
||||||
case WIRE_GOSSIP_GETCHANNELS_REQUEST:
|
case WIRE_GOSSIP_GETCHANNELS_REQUEST:
|
||||||
|
case WIRE_GOSSIP_GETPEERS_REQUEST:
|
||||||
case WIRE_GOSSIP_PING:
|
case WIRE_GOSSIP_PING:
|
||||||
case WIRE_GOSSIP_RESOLVE_CHANNEL_REQUEST:
|
case WIRE_GOSSIP_RESOLVE_CHANNEL_REQUEST:
|
||||||
case WIRE_GOSSIP_FORWARDED_MSG:
|
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_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_GETPEERS_REPLY:
|
||||||
case WIRE_GOSSIP_PING_REPLY:
|
case WIRE_GOSSIP_PING_REPLY:
|
||||||
case WIRE_GOSSIP_RESOLVE_CHANNEL_REPLY:
|
case WIRE_GOSSIP_RESOLVE_CHANNEL_REPLY:
|
||||||
case WIRE_GOSSIPCTL_RELEASE_PEER_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);
|
json_add_string(info->response, NULL, log);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void json_getpeers(struct command *cmd,
|
struct getpeers_args {
|
||||||
const char *buffer, const jsmntok_t *params)
|
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 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 (!fromwire_gossip_getpeers_reply(msg, msg, NULL, &ids, &addrs)) {
|
||||||
|
command_fail(gpa->cmd, "Bad response from gossipd");
|
||||||
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");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* First the peers not just gossiping. */
|
||||||
json_object_start(response, NULL);
|
json_object_start(response, NULL);
|
||||||
json_array_start(response, "peers");
|
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_object_start(response, NULL);
|
||||||
json_add_string(response, "state", peer_state_name(p->state));
|
json_add_string(response, "state", peer_state_name(p->state));
|
||||||
json_add_string(response, "netaddr",
|
json_add_string(response, "netaddr",
|
||||||
@@ -832,7 +829,9 @@ static void json_getpeers(struct command *cmd,
|
|||||||
p->funding_satoshi * 1000);
|
p->funding_satoshi * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (leveltok) {
|
if (gpa->ll) {
|
||||||
|
struct log_info info;
|
||||||
|
info.level = *gpa->ll;
|
||||||
info.response = response;
|
info.response = response;
|
||||||
json_array_start(response, "log");
|
json_array_start(response, "log");
|
||||||
log_each_line(p->log_book, log_to_json, &info);
|
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);
|
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_array_end(response);
|
||||||
json_object_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 = {
|
static const struct json_command getpeers_command = {
|
||||||
|
|||||||
@@ -279,9 +279,9 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
def test_connect(self):
|
def test_connect(self):
|
||||||
l1,l2 = self.connect()
|
l1,l2 = self.connect()
|
||||||
|
|
||||||
# Main daemon has no idea about these peers; they're in gossipd.
|
# These should be in gossipd.
|
||||||
assert l1.rpc.getpeer(l2.info['id'], 'info') == None
|
assert l1.rpc.getpeer(l2.info['id'])['state'] == 'GOSSIPING'
|
||||||
assert l2.rpc.getpeer(l1.info['id'], 'info') == None
|
assert l2.rpc.getpeer(l1.info['id'])['state'] == 'GOSSIPING'
|
||||||
|
|
||||||
# Both gossipds will have them as new peers once handed back.
|
# Both gossipds will have them as new peers once handed back.
|
||||||
l1.daemon.wait_for_log('handle_peer {}: new peer'.format(l2.info['id']))
|
l1.daemon.wait_for_log('handle_peer {}: new peer'.format(l2.info['id']))
|
||||||
|
|||||||
Reference in New Issue
Block a user