From b9d4f7c0ab03c43ebff16d4644751f4c318d4d14 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 26 May 2016 15:25:24 +0930 Subject: [PATCH] daemon: dev-output command. Useful for controlling conversations between two nodes, by blocking one's output. Signed-off-by: Rusty Russell --- daemon/json.c | 17 ++++++++++++++ daemon/json.h | 3 +++ daemon/jsonrpc.c | 1 + daemon/jsonrpc.h | 1 + daemon/lightning-cli.c | 5 +++- daemon/peer.c | 53 ++++++++++++++++++++++++++++++++++++++++-- daemon/peer.h | 3 ++- 7 files changed, 79 insertions(+), 4 deletions(-) diff --git a/daemon/json.c b/daemon/json.c index 5b6834b7d..dfcdd34ce 100644 --- a/daemon/json.c +++ b/daemon/json.c @@ -114,6 +114,23 @@ bool json_tok_is_null(const char *buffer, const jsmntok_t *tok) return buffer[tok->start] == 'n'; } +bool json_tok_bool(const char *buffer, const jsmntok_t *tok, bool *b) +{ + if (tok->type != JSMN_PRIMITIVE) + return false; + if (tok->end - tok->start == strlen("true") + && memcmp(buffer + tok->start, "true", strlen("true")) == 0) { + *b = true; + return true; + } + if (tok->end - tok->start == strlen("false") + && memcmp(buffer + tok->start, "false", strlen("false")) == 0) { + *b = false; + return true; + } + return false; +} + const jsmntok_t *json_next(const jsmntok_t *tok) { const jsmntok_t *t; diff --git a/daemon/json.h b/daemon/json.h index 025d43686..532fece92 100644 --- a/daemon/json.h +++ b/daemon/json.h @@ -32,6 +32,9 @@ bool json_tok_u64(const char *buffer, const jsmntok_t *tok, bool json_tok_bitcoin_amount(const char *buffer, const jsmntok_t *tok, uint64_t *satoshi); +/* Extract boolean this (must be a true or false) */ +bool json_tok_bool(const char *buffer, const jsmntok_t *tok, bool *b); + /* Is this the null primitive? */ bool json_tok_is_null(const char *buffer, const jsmntok_t *tok); diff --git a/daemon/jsonrpc.c b/daemon/jsonrpc.c index 1f3e54483..5c17a6ba5 100644 --- a/daemon/jsonrpc.c +++ b/daemon/jsonrpc.c @@ -262,6 +262,7 @@ static const struct json_command *cmdlist[] = { &crash_command, &disconnect_command, &signcommit_command, + &output_command, }; static void json_help(struct command *cmd, diff --git a/daemon/jsonrpc.h b/daemon/jsonrpc.h index ee54714c1..79e56639b 100644 --- a/daemon/jsonrpc.h +++ b/daemon/jsonrpc.h @@ -67,4 +67,5 @@ extern const struct json_command close_command; extern const struct json_command newaddr_command; extern const struct json_command disconnect_command; extern const struct json_command signcommit_command; +extern const struct json_command output_command; #endif /* LIGHTNING_DAEMON_JSONRPC_H */ diff --git a/daemon/lightning-cli.c b/daemon/lightning-cli.c index 4c236920e..65693982b 100644 --- a/daemon/lightning-cli.c +++ b/daemon/lightning-cli.c @@ -96,8 +96,11 @@ int main(int argc, char *argv[]) method, idstr); for (i = 2; i < argc; i++) { - /* Numbers are left unquoted, and quoted things left alone. */ + /* Numbers and bools are left unquoted, + * and quoted things left alone. */ if (strspn(argv[i], "0123456789") == strlen(argv[i]) + || streq(argv[i], "true") + || streq(argv[i], "false") || argv[i][0] == '"') tal_append_fmt(&cmd, "%s", argv[i]); else diff --git a/daemon/peer.c b/daemon/peer.c index dba1d9c0a..8efe7cc25 100644 --- a/daemon/peer.c +++ b/daemon/peer.c @@ -675,9 +675,9 @@ static struct io_plan *pkt_out(struct io_conn *conn, struct peer *peer) Pkt *out; size_t n = tal_count(peer->outpkt); - if (peer->fake_close) + if (peer->fake_close || !peer->output_enabled) return io_out_wait(conn, peer, pkt_out, peer); - + if (n == 0) { /* We close the connection once we've sent everything. */ if (peer->cond == PEER_CLOSED) @@ -861,6 +861,7 @@ static struct peer *new_peer(struct lightningd_state *dstate, * immediately so don't make peer a parent. */ peer->conn = conn; peer->fake_close = false; + peer->output_enabled = true; io_set_finish(conn, peer_disconnect, peer); peer->local.offer_anchor = offer_anchor; @@ -2911,6 +2912,54 @@ static void json_signcommit(struct command *cmd, command_success(cmd, response); } +static void json_output(struct command *cmd, + const char *buffer, const jsmntok_t *params) +{ + struct peer *peer; + jsmntok_t *peeridtok, *enabletok; + bool enable; + + if (!json_get_params(buffer, params, + "peerid", &peeridtok, + "enable", &enabletok, + NULL)) { + command_fail(cmd, "Need peerid and enable"); + return; + } + + peer = find_peer(cmd->dstate, buffer, peeridtok); + if (!peer) { + command_fail(cmd, "Could not find peer with that peerid"); + return; + } + + if (!peer->conn) { + command_fail(cmd, "Peer is already disconnected"); + return; + } + + if (!json_tok_bool(buffer, enabletok, &enable)) { + command_fail(cmd, "enable must be true or false"); + return; + } + + log_debug(peer->log, "dev-output: output %s", + enable ? "enabled" : "disabled"); + peer->output_enabled = enable; + + /* Flush any outstanding output */ + if (peer->output_enabled) + io_wake(peer); + + command_success(cmd, null_response(cmd)); +} +const struct json_command output_command = { + "dev-output", + json_output, + "Enable/disable any messages to peer {peerid} depending on {enable}", + "Returns an empty result on success" +}; + const struct json_command disconnect_command = { "dev-disconnect", json_disconnect, diff --git a/daemon/peer.h b/daemon/peer.h index 8fb0fbc17..9ec3b785e 100644 --- a/daemon/peer.h +++ b/daemon/peer.h @@ -223,7 +223,8 @@ struct peer { /* For testing. */ bool fake_close; - + bool output_enabled; + /* Stuff we have in common. */ struct peer_visible_state local, remote; };