From 0a1351fd513618ec69a201a56df7dcb562a029f8 Mon Sep 17 00:00:00 2001 From: John Barboza Date: Mon, 5 Mar 2018 11:16:20 -0500 Subject: [PATCH] gossipd: command to disconnect from a gossiping peer lightning-cli disconnect --- gossipd/gossip.c | 30 +++++++++++++++++++++++ gossipd/gossip_wire.csv | 10 ++++++++ lightningd/gossip_control.c | 3 +++ lightningd/peer_control.c | 49 +++++++++++++++++++++++++++++++++++++ wallet/test/run-wallet.c | 9 +++++++ 5 files changed, 101 insertions(+) diff --git a/gossipd/gossip.c b/gossipd/gossip.c index c613c13e1..37092998a 100644 --- a/gossipd/gossip.c +++ b/gossipd/gossip.c @@ -1011,6 +1011,31 @@ static struct io_plan *hand_back_peer(struct io_conn *conn, read_returning_gossipfd, rpeer); } +static struct io_plan *disconnect_peer(struct io_conn *conn, struct daemon *daemon, + const u8 *msg) +{ + struct pubkey id; + struct peer *peer; + + if (!fromwire_gossipctl_peer_disconnect(msg, &id)) + master_badmsg(WIRE_GOSSIPCTL_PEER_DISCONNECT, msg); + + peer = find_peer(daemon, &id); + if (peer && peer->local) { + /* This peer is local to this (gossipd) dameon */ + io_close(peer->local->conn); + msg = towire_gossipctl_peer_disconnect_reply(msg); + daemon_conn_send(&daemon->master, take(msg)); + } else { + status_trace("disconnect_peer: peer %s %s", + type_to_string(trc, struct pubkey, &id), + !peer ? "not found" : "not local to this daemon"); + msg = towire_gossipctl_peer_disconnect_replyfail(msg); + daemon_conn_send(&daemon->master, take(msg)); + } + return daemon_conn_read_next(conn, &daemon->master); +} + static struct io_plan *release_peer(struct io_conn *conn, struct daemon *daemon, const u8 *msg) { @@ -1976,6 +2001,9 @@ static struct io_plan *recv_req(struct io_conn *conn, struct daemon_conn *master case WIRE_GOSSIP_MARK_CHANNEL_UNROUTABLE: return handle_mark_channel_unroutable(conn, daemon, master->msg_in); + case WIRE_GOSSIPCTL_PEER_DISCONNECT: + return disconnect_peer(conn, daemon, master->msg_in); + /* We send these, we don't receive them */ case WIRE_GOSSIPCTL_RELEASE_PEER_REPLY: case WIRE_GOSSIPCTL_RELEASE_PEER_REPLYFAIL: @@ -1994,6 +2022,8 @@ static struct io_plan *recv_req(struct io_conn *conn, struct daemon_conn *master case WIRE_GOSSIP_SEND_GOSSIP: case WIRE_GOSSIP_LOCAL_ADD_CHANNEL: case WIRE_GOSSIP_GET_TXOUT: + case WIRE_GOSSIPCTL_PEER_DISCONNECT_REPLY: + case WIRE_GOSSIPCTL_PEER_DISCONNECT_REPLYFAIL: break; } diff --git a/gossipd/gossip_wire.csv b/gossipd/gossip_wire.csv index a2cde59da..857b07c08 100644 --- a/gossipd/gossip_wire.csv +++ b/gossipd/gossip_wire.csv @@ -212,3 +212,13 @@ gossip_routing_failure,,channel_update,len*u8 # (used in case of unparseable onion reply) gossip_mark_channel_unroutable,3022 gossip_mark_channel_unroutable,,channel,struct short_channel_id + +# master->gossipd: Request to disconnect from a peer. +gossipctl_peer_disconnect,3023 +gossipctl_peer_disconnect,,id,struct pubkey + +# Gossipd -> master: reply to gossip_peer_disconnect with peer id. +gossipctl_peer_disconnect_reply,3123 + +# Gossipd -> master: reply to gossip_peer_disconnect if we couldn't find the peer. +gossipctl_peer_disconnect_replyfail,3223 diff --git a/lightningd/gossip_control.c b/lightningd/gossip_control.c index 0fcb06852..12312c2ba 100644 --- a/lightningd/gossip_control.c +++ b/lightningd/gossip_control.c @@ -118,6 +118,7 @@ static unsigned gossip_msg(struct subd *gossip, const u8 *msg, const int *fds) case WIRE_GOSSIP_DISABLE_CHANNEL: case WIRE_GOSSIP_ROUTING_FAILURE: case WIRE_GOSSIP_MARK_CHANNEL_UNROUTABLE: + case WIRE_GOSSIPCTL_PEER_DISCONNECT: /* This is a reply, so never gets through to here. */ case WIRE_GOSSIP_GET_UPDATE_REPLY: case WIRE_GOSSIP_GETNODES_REPLY: @@ -128,6 +129,8 @@ static unsigned gossip_msg(struct subd *gossip, const u8 *msg, const int *fds) case WIRE_GOSSIP_RESOLVE_CHANNEL_REPLY: case WIRE_GOSSIPCTL_RELEASE_PEER_REPLY: case WIRE_GOSSIPCTL_RELEASE_PEER_REPLYFAIL: + case WIRE_GOSSIPCTL_PEER_DISCONNECT_REPLY: + case WIRE_GOSSIPCTL_PEER_DISCONNECT_REPLYFAIL: break; /* These are inter-daemon messages, not received by us */ case WIRE_GOSSIP_LOCAL_ADD_CHANNEL: diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 287b45e1b..d3ef8a389 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -875,6 +875,55 @@ void activate_peers(struct lightningd *ld) activate_peer(p); } +/* Peer has been released from gossip. */ +static void gossip_peer_disconnected (struct subd *gossip, + const u8 *resp, + const int *fds, + struct command *cmd) { + if (!fromwire_gossipctl_peer_disconnect_reply(resp)) { + if (!fromwire_gossipctl_peer_disconnect_replyfail(resp)) + fatal("Gossip daemon gave invalid reply %s", + tal_hex(gossip, resp)); + command_fail(cmd, "Peer not connected"); + } else { + /* Successfully disconnected */ + command_success(cmd, null_response(cmd)); + } + return; +} + +static void json_disconnect(struct command *cmd, + const char *buffer, const jsmntok_t *params) +{ + jsmntok_t *idtok; + struct pubkey id; + u8 *msg; + + if (!json_get_params(cmd, buffer, params, + "id", &idtok, + NULL)) { + return; + } + + if (!json_tok_pubkey(buffer, idtok, &id)) { + command_fail(cmd, "id %.*s not valid", + idtok->end - idtok->start, + buffer + idtok->start); + return; + } + + msg = towire_gossipctl_peer_disconnect(cmd, &id); + subd_req(cmd, cmd->ld->gossip, msg, -1, 0, gossip_peer_disconnected, cmd); + command_still_pending(cmd); +} + +static const struct json_command disconnect_command = { + "disconnect", + json_disconnect, + "Disconnect from {id} that has previously been connected to using connect" +}; +AUTODATA(json_command, &disconnect_command); + #if DEVELOPER static void json_sign_last_tx(struct command *cmd, const char *buffer, const jsmntok_t *params) diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 55d8d2bae..fbbf82fa5 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -376,6 +376,15 @@ struct txowatch *watch_txo(const tal_t *ctx UNNEEDED, /* Generated stub for json_add_string_escape */ void json_add_string_escape(struct json_result *result UNNEEDED, const char *fieldname UNNEEDED, const char *value UNNEEDED) { fprintf(stderr, "json_add_string_escape called!\n"); abort(); } +/* Generated stub for towire_gossipctl_peer_disconnect */ +u8 *towire_gossipctl_peer_disconnect(const tal_t *ctx UNNEEDED, const struct pubkey *id UNNEEDED) +{ fprintf(stderr, "towire_gossipctl_peer_disconnect called!\n"); abort(); } +/* Generated stub for fromwire_gossipctl_peer_disconnect_reply */ +bool fromwire_gossipctl_peer_disconnect_reply(const void *p UNNEEDED) +{ fprintf(stderr, "fromwire_gossipctl_peer_disconnect_reply called!\n"); abort(); } +/* Generated stub for fromwire_gossipctl_peer_disconnect_replyfail*/ +bool fromwire_gossipctl_peer_disconnect_replyfail(const void *p UNNEEDED) +{ fprintf(stderr, "fromwire_gossipctl_peer_disconnect_replyfail called!\n"); abort(); } /* AUTOGENERATED MOCKS END */ #if DEVELOPER