Browse Source

json-rpc: Add sendcustommsg command

This command injects a custom message into the encrypted transport stream to
the peer, allowing users to build custom protocols on top of c-lightning
without requiring any changes to c-lightning itself.
travis-debug
Christian Decker 5 years ago
parent
commit
3ad8438d91
  1. 67
      lightningd/peer_control.c
  2. 8
      lightningd/test/run-invoice-select-inchan.c
  3. 11
      wallet/test/run-wallet.c

67
lightningd/peer_control.c

@ -54,6 +54,7 @@
#include <lightningd/plugin_hook.h> #include <lightningd/plugin_hook.h>
#include <unistd.h> #include <unistd.h>
#include <wally_bip32.h> #include <wally_bip32.h>
#include <wire/gen_common_wire.h>
#include <wire/gen_onion_wire.h> #include <wire/gen_onion_wire.h>
#include <wire/wire_sync.h> #include <wire/wire_sync.h>
@ -2373,5 +2374,71 @@ void peer_dev_memleak(struct command *cmd)
{ {
peer_memleak_req_next(cmd, NULL); peer_memleak_req_next(cmd, NULL);
} }
static struct command_result *json_sendcustommsg(struct command *cmd,
const char *buffer,
const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params)
{
struct json_stream *response;
struct node_id *dest;
struct peer *peer;
struct subd *owner;
u8 *msg;
if (!param(cmd, buffer, params,
p_req("node_id", param_node_id, &dest),
p_req("msg", param_bin_from_hex, &msg),
NULL))
return command_param_failed();
peer = peer_by_id(cmd->ld, dest);
if (!peer) {
return command_fail(cmd, JSONRPC2_INVALID_REQUEST,
"No such peer: %s",
type_to_string(cmd, struct node_id, dest));
}
owner = peer_get_owning_subd(peer);
if (owner == NULL) {
return command_fail(cmd, JSONRPC2_INVALID_REQUEST,
"Peer is not connected: %s",
type_to_string(cmd, struct node_id, dest));
}
/* Only a couple of subdaemons have the ability to send custom
* messages. We whitelist those, and error if the current owner is not
* in the whitelist. The reason is that some subdaemons do not handle
* spontaneous messages from the master well (I'm looking at you
* `closingd`...). */
if (!streq(owner->name, "channeld") &&
!streq(owner->name, "openingd")) {
return command_fail(cmd, JSONRPC2_INVALID_REQUEST,
"Peer is currently owned by %s which does "
"not support injecting custom messages.",
owner->name);
}
subd_send_msg(owner, take(towire_custommsg_out(cmd, msg)));
response = json_stream_success(cmd);
json_add_string(response, "status",
tal_fmt(cmd,
"Message sent to subdaemon %s for delivery",
owner->name));
return command_success(cmd, response);
}
static const struct json_command sendcustommsg_command = {
"dev-sendcustommsg",
"utility",
json_sendcustommsg,
"Send a custom message to the peer with the given {node_id}",
.verbose = "dev-sendcustommsg node_id hexcustommsg",
};
AUTODATA(json_command, &sendcustommsg_command);
#endif /* DEVELOPER */ #endif /* DEVELOPER */

8
lightningd/test/run-invoice-select-inchan.c

@ -330,6 +330,11 @@ struct command_result *param_array(struct command *cmd UNNEEDED, const char *nam
const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
const jsmntok_t **arr UNNEEDED) const jsmntok_t **arr UNNEEDED)
{ fprintf(stderr, "param_array called!\n"); abort(); } { fprintf(stderr, "param_array called!\n"); abort(); }
/* Generated stub for param_bin_from_hex */
struct command_result *param_bin_from_hex(struct command *cmd UNNEEDED, const char *name UNNEEDED,
const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
u8 **bin UNNEEDED)
{ fprintf(stderr, "param_bin_from_hex called!\n"); abort(); }
/* Generated stub for param_bitcoin_address */ /* Generated stub for param_bitcoin_address */
struct command_result *param_bitcoin_address(struct command *cmd UNNEEDED, struct command_result *param_bitcoin_address(struct command *cmd UNNEEDED,
const char *name UNNEEDED, const char *name UNNEEDED,
@ -407,6 +412,9 @@ struct command_result *param_u64(struct command *cmd UNNEEDED, const char *name
const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
uint64_t **num UNNEEDED) uint64_t **num UNNEEDED)
{ fprintf(stderr, "param_u64 called!\n"); abort(); } { fprintf(stderr, "param_u64 called!\n"); abort(); }
/* Generated stub for peer_get_owning_subd */
struct subd *peer_get_owning_subd(struct peer *peer UNNEEDED)
{ fprintf(stderr, "peer_get_owning_subd called!\n"); abort(); }
/* Generated stub for peer_memleak_done */ /* Generated stub for peer_memleak_done */
void peer_memleak_done(struct command *cmd UNNEEDED, struct subd *leaker UNNEEDED) void peer_memleak_done(struct command *cmd UNNEEDED, struct subd *leaker UNNEEDED)
{ fprintf(stderr, "peer_memleak_done called!\n"); abort(); } { fprintf(stderr, "peer_memleak_done called!\n"); abort(); }

11
wallet/test/run-wallet.c

@ -420,6 +420,11 @@ void outpointfilter_remove(struct outpointfilter *of UNNEEDED,
bool param(struct command *cmd UNNEEDED, const char *buffer UNNEEDED, bool param(struct command *cmd UNNEEDED, const char *buffer UNNEEDED,
const jsmntok_t params[] UNNEEDED, ...) const jsmntok_t params[] UNNEEDED, ...)
{ fprintf(stderr, "param called!\n"); abort(); } { fprintf(stderr, "param called!\n"); abort(); }
/* Generated stub for param_bin_from_hex */
struct command_result *param_bin_from_hex(struct command *cmd UNNEEDED, const char *name UNNEEDED,
const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
u8 **bin UNNEEDED)
{ fprintf(stderr, "param_bin_from_hex called!\n"); abort(); }
/* Generated stub for param_bitcoin_address */ /* Generated stub for param_bitcoin_address */
struct command_result *param_bitcoin_address(struct command *cmd UNNEEDED, struct command_result *param_bitcoin_address(struct command *cmd UNNEEDED,
const char *name UNNEEDED, const char *name UNNEEDED,
@ -491,6 +496,9 @@ void payment_store(struct lightningd *ld UNNEEDED, struct wallet_payment *paymen
void payment_succeeded(struct lightningd *ld UNNEEDED, struct htlc_out *hout UNNEEDED, void payment_succeeded(struct lightningd *ld UNNEEDED, struct htlc_out *hout UNNEEDED,
const struct preimage *rval UNNEEDED) const struct preimage *rval UNNEEDED)
{ fprintf(stderr, "payment_succeeded called!\n"); abort(); } { fprintf(stderr, "payment_succeeded called!\n"); abort(); }
/* Generated stub for peer_get_owning_subd */
struct subd *peer_get_owning_subd(struct peer *peer UNNEEDED)
{ fprintf(stderr, "peer_get_owning_subd called!\n"); abort(); }
/* Generated stub for peer_memleak_done */ /* Generated stub for peer_memleak_done */
void peer_memleak_done(struct command *cmd UNNEEDED, struct subd *leaker UNNEEDED) void peer_memleak_done(struct command *cmd UNNEEDED, struct subd *leaker UNNEEDED)
{ fprintf(stderr, "peer_memleak_done called!\n"); abort(); } { fprintf(stderr, "peer_memleak_done called!\n"); abort(); }
@ -590,6 +598,9 @@ u8 *towire_connectctl_connect_to_peer(const tal_t *ctx UNNEEDED, const struct no
/* Generated stub for towire_connectctl_peer_disconnected */ /* Generated stub for towire_connectctl_peer_disconnected */
u8 *towire_connectctl_peer_disconnected(const tal_t *ctx UNNEEDED, const struct node_id *id UNNEEDED) u8 *towire_connectctl_peer_disconnected(const tal_t *ctx UNNEEDED, const struct node_id *id UNNEEDED)
{ fprintf(stderr, "towire_connectctl_peer_disconnected called!\n"); abort(); } { fprintf(stderr, "towire_connectctl_peer_disconnected called!\n"); abort(); }
/* Generated stub for towire_custommsg_out */
u8 *towire_custommsg_out(const tal_t *ctx UNNEEDED, const u8 *msg UNNEEDED)
{ fprintf(stderr, "towire_custommsg_out called!\n"); abort(); }
/* Generated stub for towire_errorfmt */ /* Generated stub for towire_errorfmt */
u8 *towire_errorfmt(const tal_t *ctx UNNEEDED, u8 *towire_errorfmt(const tal_t *ctx UNNEEDED,
const struct channel_id *channel UNNEEDED, const struct channel_id *channel UNNEEDED,

Loading…
Cancel
Save