mirror of
https://github.com/aljazceru/lightning.git
synced 2026-01-08 08:34:31 +01:00
connectd: handle custom messages.
This is neater than what we had before, and slightly more general. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Changelog-Changed: JSON_RPC: `sendcustommsg` now works with any connected peer, even when shutting down a channel.
This commit is contained in:
@@ -41,7 +41,6 @@
|
||||
#include <gossipd/gossip_store_wiregen.h>
|
||||
#include <gossipd/gossipd_peerd_wiregen.h>
|
||||
#include <hsmd/hsmd_wiregen.h>
|
||||
#include <wire/common_wiregen.h>
|
||||
#include <wire/peer_wire.h>
|
||||
#include <wire/wire_sync.h>
|
||||
|
||||
@@ -2049,23 +2048,6 @@ static void handle_peer_shutdown(struct peer *peer, const u8 *shutdown)
|
||||
billboard_update(peer);
|
||||
}
|
||||
|
||||
/* Try to handle a custommsg Returns true if it was a custom message and has
|
||||
* been handled, false if the message was not handled.
|
||||
*/
|
||||
static bool channeld_handle_custommsg(const u8 *msg)
|
||||
{
|
||||
enum peer_wire type = fromwire_peektype(msg);
|
||||
if (type % 2 == 1 && !peer_wire_is_defined(type)) {
|
||||
/* The message is not part of the messages we know how to
|
||||
* handle. Assuming this is a custommsg, we just forward it to the
|
||||
* master. */
|
||||
wire_sync_write(MASTER_FD, take(towire_custommsg_in(NULL, msg)));
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_unexpected_tx_sigs(struct peer *peer, const u8 *msg)
|
||||
{
|
||||
const struct witness_stack **ws;
|
||||
@@ -2155,9 +2137,6 @@ static void peer_in(struct peer *peer, const u8 *msg)
|
||||
{
|
||||
enum peer_wire type = fromwire_peektype(msg);
|
||||
|
||||
if (channeld_handle_custommsg(msg))
|
||||
return;
|
||||
|
||||
if (handle_peer_gossip_or_error(peer->pps, &peer->channel_id, msg))
|
||||
return;
|
||||
|
||||
@@ -2824,8 +2803,7 @@ skip_tlvs:
|
||||
do {
|
||||
clean_tmpctx();
|
||||
msg = peer_read(tmpctx, peer->pps);
|
||||
} while (channeld_handle_custommsg(msg) ||
|
||||
handle_peer_gossip_or_error(peer->pps, &peer->channel_id, msg) ||
|
||||
} while (handle_peer_gossip_or_error(peer->pps, &peer->channel_id, msg) ||
|
||||
capture_premature_msg(&premature_msgs, msg));
|
||||
|
||||
got_reestablish:
|
||||
@@ -3577,17 +3555,6 @@ static void handle_dev_quiesce(struct peer *peer, const u8 *msg)
|
||||
#endif /* EXPERIMENTAL_FEATURES */
|
||||
#endif /* DEVELOPER */
|
||||
|
||||
/* We were told to send a custommsg to the peer by `lightningd`. All the
|
||||
* verification is done on the side of `lightningd` so we should be good to
|
||||
* just forward it here. */
|
||||
static void channeld_send_custommsg(struct peer *peer, const u8 *msg)
|
||||
{
|
||||
u8 *inner;
|
||||
if (!fromwire_custommsg_out(tmpctx, msg, &inner))
|
||||
master_badmsg(WIRE_CUSTOMMSG_OUT, msg);
|
||||
peer_write(peer->pps, take(inner));
|
||||
}
|
||||
|
||||
static void req_in(struct peer *peer, const u8 *msg)
|
||||
{
|
||||
enum channeld_wire t = fromwire_peektype(msg);
|
||||
@@ -3676,17 +3643,6 @@ static void req_in(struct peer *peer, const u8 *msg)
|
||||
case WIRE_CHANNELD_LOCAL_PRIVATE_CHANNEL:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Now handle common messages. */
|
||||
switch ((enum common_wire)t) {
|
||||
case WIRE_CUSTOMMSG_OUT:
|
||||
channeld_send_custommsg(peer, msg);
|
||||
return;
|
||||
/* We send these. */
|
||||
case WIRE_CUSTOMMSG_IN:
|
||||
break;
|
||||
}
|
||||
|
||||
master_badmsg(-1, msg);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <wire/common_wiregen.h>
|
||||
#include <wire/peer_wire.h>
|
||||
#include <wire/wire_sync.h>
|
||||
|
||||
@@ -126,15 +125,6 @@ static u8 *closing_read_peer_msg(const tal_t *ctx,
|
||||
handle_gossip_msg(pps, take(msg));
|
||||
continue;
|
||||
}
|
||||
/* Handle custommsgs */
|
||||
enum peer_wire type = fromwire_peektype(msg);
|
||||
if (type % 2 == 1 && !peer_wire_is_defined(type)) {
|
||||
/* The message is not part of the messages we know
|
||||
* how to handle. Assume is custommsg, forward it
|
||||
* to master. */
|
||||
wire_sync_write(REQ_FD, take(towire_custommsg_in(NULL, msg)));
|
||||
continue;
|
||||
}
|
||||
if (!handle_peer_gossip_or_error(pps, channel_id, msg))
|
||||
return msg;
|
||||
}
|
||||
|
||||
@@ -1975,6 +1975,10 @@ static struct io_plan *recv_req(struct io_conn *conn,
|
||||
onionmsg_req(daemon, msg);
|
||||
goto out;
|
||||
|
||||
case WIRE_CONNECTD_CUSTOMMSG_OUT:
|
||||
send_custommsg(daemon, msg);
|
||||
goto out;
|
||||
|
||||
case WIRE_CONNECTD_DEV_MEMLEAK:
|
||||
#if DEVELOPER
|
||||
dev_connect_memleak(daemon, msg);
|
||||
@@ -1989,6 +1993,7 @@ static struct io_plan *recv_req(struct io_conn *conn,
|
||||
case WIRE_CONNECTD_DEV_MEMLEAK_REPLY:
|
||||
case WIRE_CONNECTD_PING_REPLY:
|
||||
case WIRE_CONNECTD_GOT_ONIONMSG_TO_US:
|
||||
case WIRE_CONNECTD_CUSTOMMSG_IN:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -116,3 +116,15 @@ msgdata,connectd_send_onionmsg,onion_len,u16,
|
||||
msgdata,connectd_send_onionmsg,onion,u8,onion_len
|
||||
msgdata,connectd_send_onionmsg,blinding,pubkey,
|
||||
|
||||
# A custom message that we got from a peer and don't know how to handle, so we
|
||||
# forward it to the master for further handling.
|
||||
msgtype,connectd_custommsg_in,2110
|
||||
msgdata,connectd_custommsg_in,id,node_id,
|
||||
msgdata,connectd_custommsg_in,msg_len,u16,
|
||||
msgdata,connectd_custommsg_in,msg,u8,msg_len
|
||||
|
||||
# A custom message that the lightningd tells us to send to the peer.
|
||||
msgtype,connectd_custommsg_out,2011
|
||||
msgdata,connectd_custommsg_out,id,node_id,
|
||||
msgdata,connectd_custommsg_out,msg_len,u16,
|
||||
msgdata,connectd_custommsg_out,msg,u8,msg_len
|
||||
|
||||
|
@@ -366,6 +366,21 @@ static void send_ping(struct peer *peer)
|
||||
set_ping_timer(peer);
|
||||
}
|
||||
|
||||
void send_custommsg(struct daemon *daemon, const u8 *msg)
|
||||
{
|
||||
struct node_id id;
|
||||
u8 *custommsg;
|
||||
struct peer *peer;
|
||||
|
||||
if (!fromwire_connectd_custommsg_out(tmpctx, msg, &id, &custommsg))
|
||||
master_badmsg(WIRE_CONNECTD_CUSTOMMSG_OUT, msg);
|
||||
|
||||
/* Races can happen: this might be gone by now. */
|
||||
peer = peer_htable_get(&daemon->peers, &id);
|
||||
if (peer)
|
||||
inject_peer_msg(peer, take(custommsg));
|
||||
}
|
||||
|
||||
static void handle_ping_in(struct peer *peer, const u8 *msg)
|
||||
{
|
||||
u8 *pong;
|
||||
@@ -472,6 +487,26 @@ static void handle_gossip_timetamp_filter_in(struct peer *peer, const u8 *msg)
|
||||
wake_gossip(peer);
|
||||
}
|
||||
|
||||
static bool handle_custommsg(struct daemon *daemon,
|
||||
struct peer *peer,
|
||||
const u8 *msg)
|
||||
{
|
||||
enum peer_wire type = fromwire_peektype(msg);
|
||||
if (type % 2 == 1 && !peer_wire_is_defined(type)) {
|
||||
/* The message is not part of the messages we know how to
|
||||
* handle. Assuming this is a custommsg, we just forward it to the
|
||||
* master. */
|
||||
status_peer_io(LOG_IO_IN, &peer->id, msg);
|
||||
daemon_conn_send(daemon->master,
|
||||
take(towire_connectd_custommsg_in(NULL,
|
||||
&peer->id,
|
||||
msg)));
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* We handle pings and gossip messages. */
|
||||
static bool handle_message_locally(struct peer *peer, const u8 *msg)
|
||||
{
|
||||
@@ -496,6 +531,8 @@ static bool handle_message_locally(struct peer *peer, const u8 *msg)
|
||||
} else if (type == WIRE_ONION_MESSAGE) {
|
||||
handle_onion_message(peer->daemon, peer, msg);
|
||||
return true;
|
||||
} else if (handle_custommsg(peer->daemon, peer, msg)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Do we want to divert to gossipd? */
|
||||
|
||||
@@ -34,4 +34,7 @@ void close_peer_conn(struct peer *peer);
|
||||
|
||||
/* When lightningd says to send a ping */
|
||||
void send_manual_ping(struct daemon *daemon, const u8 *msg);
|
||||
|
||||
/* When lightningd says to send a custom message (from a plugin) */
|
||||
void send_custommsg(struct daemon *daemon, const u8 *msg);
|
||||
#endif /* LIGHTNING_CONNECTD_MULTIPLEX_H */
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include <lightningd/notification.h>
|
||||
#include <lightningd/peer_control.h>
|
||||
#include <lightningd/peer_fd.h>
|
||||
#include <wire/common_wiregen.h>
|
||||
|
||||
static void update_feerates(struct lightningd *ld, struct channel *channel)
|
||||
{
|
||||
@@ -564,15 +563,6 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds)
|
||||
break;
|
||||
}
|
||||
|
||||
switch ((enum common_wire)t) {
|
||||
case WIRE_CUSTOMMSG_IN:
|
||||
handle_custommsg_in(sd->ld, sd->node_id, msg);
|
||||
break;
|
||||
/* We send these. */
|
||||
case WIRE_CUSTOMMSG_OUT:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
#include <lightningd/peer_fd.h>
|
||||
#include <lightningd/subd.h>
|
||||
#include <openingd/dualopend_wiregen.h>
|
||||
#include <wire/common_wiregen.h>
|
||||
|
||||
struct close_command {
|
||||
/* Inside struct lightningd close_commands. */
|
||||
@@ -339,15 +338,6 @@ static unsigned closing_msg(struct subd *sd, const u8 *msg, const int *fds UNUSE
|
||||
break;
|
||||
}
|
||||
|
||||
switch ((enum common_wire)t) {
|
||||
case WIRE_CUSTOMMSG_IN:
|
||||
handle_custommsg_in(sd->ld, sd->node_id, msg);
|
||||
break;
|
||||
/* We send these. */
|
||||
case WIRE_CUSTOMMSG_OUT:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,9 @@
|
||||
#include <lightningd/lightningd.h>
|
||||
#include <lightningd/onion_message.h>
|
||||
#include <lightningd/opening_common.h>
|
||||
#include <lightningd/opening_control.h>
|
||||
#include <lightningd/peer_control.h>
|
||||
#include <lightningd/plugin_hook.h>
|
||||
|
||||
struct connect {
|
||||
struct list_node list;
|
||||
@@ -352,6 +354,63 @@ static void peer_please_disconnect(struct lightningd *ld, const u8 *msg)
|
||||
}
|
||||
}
|
||||
|
||||
struct custommsg_payload {
|
||||
struct node_id peer_id;
|
||||
u8 *msg;
|
||||
};
|
||||
|
||||
static bool custommsg_cb(struct custommsg_payload *payload,
|
||||
const char *buffer, const jsmntok_t *toks)
|
||||
{
|
||||
const jsmntok_t *t_res;
|
||||
|
||||
if (!toks || !buffer)
|
||||
return true;
|
||||
|
||||
t_res = json_get_member(buffer, toks, "result");
|
||||
|
||||
/* fail */
|
||||
if (!t_res || !json_tok_streq(buffer, t_res, "continue"))
|
||||
fatal("Plugin returned an invalid response to the "
|
||||
"custommsg hook: %s", buffer);
|
||||
|
||||
/* call next hook */
|
||||
return true;
|
||||
}
|
||||
|
||||
static void custommsg_final(struct custommsg_payload *payload STEALS)
|
||||
{
|
||||
tal_steal(tmpctx, payload);
|
||||
}
|
||||
|
||||
static void custommsg_payload_serialize(struct custommsg_payload *payload,
|
||||
struct json_stream *stream,
|
||||
struct plugin *plugin)
|
||||
{
|
||||
json_add_hex_talarr(stream, "payload", payload->msg);
|
||||
json_add_node_id(stream, "peer_id", &payload->peer_id);
|
||||
}
|
||||
|
||||
REGISTER_PLUGIN_HOOK(custommsg,
|
||||
custommsg_cb,
|
||||
custommsg_final,
|
||||
custommsg_payload_serialize,
|
||||
struct custommsg_payload *);
|
||||
|
||||
static void handle_custommsg_in(struct lightningd *ld, const u8 *msg)
|
||||
{
|
||||
struct custommsg_payload *p = tal(NULL, struct custommsg_payload);
|
||||
|
||||
if (!fromwire_connectd_custommsg_in(p, msg, &p->peer_id, &p->msg)) {
|
||||
log_broken(ld->log, "Malformed custommsg: %s",
|
||||
tal_hex(tmpctx, msg));
|
||||
tal_free(p);
|
||||
return;
|
||||
}
|
||||
|
||||
plugin_hook_call_custommsg(ld, p);
|
||||
}
|
||||
|
||||
static unsigned connectd_msg(struct subd *connectd, const u8 *msg, const int *fds)
|
||||
{
|
||||
enum connectd_wire t = fromwire_peektype(msg);
|
||||
@@ -366,6 +425,7 @@ static unsigned connectd_msg(struct subd *connectd, const u8 *msg, const int *fd
|
||||
case WIRE_CONNECTD_PEER_FINAL_MSG:
|
||||
case WIRE_CONNECTD_PING:
|
||||
case WIRE_CONNECTD_SEND_ONIONMSG:
|
||||
case WIRE_CONNECTD_CUSTOMMSG_OUT:
|
||||
/* This is a reply, so never gets through to here. */
|
||||
case WIRE_CONNECTD_INIT_REPLY:
|
||||
case WIRE_CONNECTD_ACTIVATE_REPLY:
|
||||
@@ -390,6 +450,10 @@ static unsigned connectd_msg(struct subd *connectd, const u8 *msg, const int *fd
|
||||
case WIRE_CONNECTD_GOT_ONIONMSG_TO_US:
|
||||
handle_onionmsg_to_us(connectd->ld, msg);
|
||||
break;
|
||||
|
||||
case WIRE_CONNECTD_CUSTOMMSG_IN:
|
||||
handle_custommsg_in(connectd->ld, msg);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -500,3 +564,88 @@ void connectd_activate(struct lightningd *ld)
|
||||
io_loop(NULL, 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;
|
||||
u8 *msg;
|
||||
int type;
|
||||
|
||||
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();
|
||||
|
||||
type = fromwire_peektype(msg);
|
||||
if (peer_wire_is_defined(type)) {
|
||||
return command_fail(
|
||||
cmd, JSONRPC2_INVALID_REQUEST,
|
||||
"Cannot send messages of type %d (%s). It is not possible "
|
||||
"to send messages that have a type managed internally "
|
||||
"since that might cause issues with the internal state "
|
||||
"tracking.",
|
||||
type, peer_wire_name(type));
|
||||
}
|
||||
|
||||
if (type % 2 == 0) {
|
||||
return command_fail(
|
||||
cmd, JSONRPC2_INVALID_REQUEST,
|
||||
"Cannot send even-typed %d custom message. Currently "
|
||||
"custom messages are limited to odd-numbered message "
|
||||
"types, as even-numbered types might result in "
|
||||
"disconnections.",
|
||||
type);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
/* FIXME: This won't work once connectd keeps peers */
|
||||
if (!peer_get_owning_subd(peer)) {
|
||||
return command_fail(cmd, JSONRPC2_INVALID_REQUEST,
|
||||
"Peer is not connected: %s",
|
||||
type_to_string(cmd, struct node_id, dest));
|
||||
}
|
||||
|
||||
subd_send_msg(cmd->ld->connectd,
|
||||
take(towire_connectd_custommsg_out(cmd, dest, msg)));
|
||||
|
||||
response = json_stream_success(cmd);
|
||||
json_add_string(response, "status",
|
||||
"Message sent to connectd for delivery");
|
||||
|
||||
return command_success(cmd, response);
|
||||
}
|
||||
|
||||
static const struct json_command sendcustommsg_command = {
|
||||
"sendcustommsg",
|
||||
"utility",
|
||||
json_sendcustommsg,
|
||||
"Send a custom message to the peer with the given {node_id}",
|
||||
.verbose = "sendcustommsg node_id hexcustommsg",
|
||||
};
|
||||
|
||||
AUTODATA(json_command, &sendcustommsg_command);
|
||||
|
||||
#ifdef COMPAT_V0100
|
||||
#ifdef DEVELOPER
|
||||
static const struct json_command dev_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, &dev_sendcustommsg_command);
|
||||
#endif /* DEVELOPER */
|
||||
#endif /* COMPAT_V0100 */
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#include <lightningd/peer_fd.h>
|
||||
#include <lightningd/plugin_hook.h>
|
||||
#include <openingd/dualopend_wiregen.h>
|
||||
#include <wire/common_wiregen.h>
|
||||
|
||||
struct commit_rcvd {
|
||||
struct channel *channel;
|
||||
@@ -3030,15 +3029,6 @@ static unsigned int dual_opend_msg(struct subd *dualopend,
|
||||
break;
|
||||
}
|
||||
|
||||
switch ((enum common_wire)t) {
|
||||
case WIRE_CUSTOMMSG_IN:
|
||||
handle_custommsg_in(dualopend->ld, dualopend->node_id, msg);
|
||||
return 0;
|
||||
/* We send these. */
|
||||
case WIRE_CUSTOMMSG_OUT:
|
||||
break;
|
||||
}
|
||||
|
||||
log_broken(dualopend->log, "Unexpected msg %s: %s",
|
||||
dualopend_wire_name(t), tal_hex(tmpctx, msg));
|
||||
tal_free(dualopend);
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include <lightningd/subd.h>
|
||||
#include <openingd/openingd_wiregen.h>
|
||||
#include <wally_psbt.h>
|
||||
#include <wire/common_wiregen.h>
|
||||
|
||||
void json_add_uncommitted_channel(struct json_stream *response,
|
||||
const struct uncommitted_channel *uc)
|
||||
@@ -890,15 +889,6 @@ static unsigned int openingd_msg(struct subd *openingd,
|
||||
break;
|
||||
}
|
||||
|
||||
switch ((enum common_wire)t) {
|
||||
case WIRE_CUSTOMMSG_IN:
|
||||
handle_custommsg_in(openingd->ld, openingd->node_id, msg);
|
||||
return 0;
|
||||
/* We send these. */
|
||||
case WIRE_CUSTOMMSG_OUT:
|
||||
break;
|
||||
}
|
||||
|
||||
log_broken(openingd->log, "Unexpected msg %s: %s",
|
||||
openingd_wire_name(t), tal_hex(tmpctx, msg));
|
||||
tal_free(openingd);
|
||||
|
||||
@@ -65,7 +65,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <wally_bip32.h>
|
||||
#include <wire/common_wiregen.h>
|
||||
#include <wire/onion_wire.h>
|
||||
#include <wire/wire_sync.h>
|
||||
|
||||
@@ -2404,167 +2403,4 @@ void peer_dev_memleak(struct command *cmd)
|
||||
{
|
||||
peer_memleak_req_next(cmd, NULL);
|
||||
}
|
||||
|
||||
#endif /* DEVELOPER */
|
||||
|
||||
struct custommsg_payload {
|
||||
struct node_id peer_id;
|
||||
const u8 *msg;
|
||||
};
|
||||
|
||||
static bool custommsg_cb(struct custommsg_payload *payload,
|
||||
const char *buffer, const jsmntok_t *toks)
|
||||
{
|
||||
const jsmntok_t *t_res;
|
||||
|
||||
if (!toks || !buffer)
|
||||
return true;
|
||||
|
||||
t_res = json_get_member(buffer, toks, "result");
|
||||
|
||||
/* fail */
|
||||
if (!t_res || !json_tok_streq(buffer, t_res, "continue"))
|
||||
fatal("Plugin returned an invalid response to the "
|
||||
"custommsg hook: %s", buffer);
|
||||
|
||||
/* call next hook */
|
||||
return true;
|
||||
}
|
||||
|
||||
static void custommsg_final(struct custommsg_payload *payload STEALS)
|
||||
{
|
||||
tal_steal(tmpctx, payload);
|
||||
}
|
||||
|
||||
static void custommsg_payload_serialize(struct custommsg_payload *payload,
|
||||
struct json_stream *stream,
|
||||
struct plugin *plugin)
|
||||
{
|
||||
json_add_hex_talarr(stream, "payload", payload->msg);
|
||||
json_add_node_id(stream, "peer_id", &payload->peer_id);
|
||||
}
|
||||
|
||||
REGISTER_PLUGIN_HOOK(custommsg,
|
||||
custommsg_cb,
|
||||
custommsg_final,
|
||||
custommsg_payload_serialize,
|
||||
struct custommsg_payload *);
|
||||
|
||||
void handle_custommsg_in(struct lightningd *ld, const struct node_id *peer_id,
|
||||
const u8 *msg)
|
||||
{
|
||||
struct custommsg_payload *p = tal(NULL, struct custommsg_payload);
|
||||
u8 *custommsg;
|
||||
|
||||
if (!fromwire_custommsg_in(NULL, msg, &custommsg)) {
|
||||
log_broken(ld->log, "Malformed custommsg from peer %s: %s",
|
||||
type_to_string(tmpctx, struct node_id, peer_id),
|
||||
tal_hex(tmpctx, msg));
|
||||
return;
|
||||
}
|
||||
|
||||
p->peer_id = *peer_id;
|
||||
p->msg = tal_steal(p, custommsg);
|
||||
plugin_hook_call_custommsg(ld, p);
|
||||
}
|
||||
|
||||
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;
|
||||
int type;
|
||||
|
||||
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();
|
||||
|
||||
type = fromwire_peektype(msg);
|
||||
if (peer_wire_is_defined(type)) {
|
||||
return command_fail(
|
||||
cmd, JSONRPC2_INVALID_REQUEST,
|
||||
"Cannot send messages of type %d (%s). It is not possible "
|
||||
"to send messages that have a type managed internally "
|
||||
"since that might cause issues with the internal state "
|
||||
"tracking.",
|
||||
type, peer_wire_name(type));
|
||||
}
|
||||
|
||||
if (type % 2 == 0) {
|
||||
return command_fail(
|
||||
cmd, JSONRPC2_INVALID_REQUEST,
|
||||
"Cannot send even-typed %d custom message. Currently "
|
||||
"custom messages are limited to odd-numbered message "
|
||||
"types, as even-numbered types might result in "
|
||||
"disconnections.",
|
||||
type);
|
||||
}
|
||||
|
||||
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 = {
|
||||
"sendcustommsg",
|
||||
"utility",
|
||||
json_sendcustommsg,
|
||||
"Send a custom message to the peer with the given {node_id}",
|
||||
.verbose = "sendcustommsg node_id hexcustommsg",
|
||||
};
|
||||
|
||||
AUTODATA(json_command, &sendcustommsg_command);
|
||||
|
||||
#ifdef COMPAT_V0100
|
||||
#ifdef DEVELOPER
|
||||
static const struct json_command dev_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, &dev_sendcustommsg_command);
|
||||
#endif /* DEVELOPER */
|
||||
#endif /* COMPAT_V0100 */
|
||||
|
||||
@@ -98,9 +98,6 @@ struct htlc_in_map *load_channels_from_wallet(struct lightningd *ld);
|
||||
void peer_dev_memleak(struct command *cmd);
|
||||
#endif /* DEVELOPER */
|
||||
|
||||
void handle_custommsg_in(struct lightningd *ld, const struct node_id *peer_id,
|
||||
const u8 *msg);
|
||||
|
||||
/* Triggered at each new block. */
|
||||
void waitblockheight_notify_new_block(struct lightningd *ld,
|
||||
u32 block_height);
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#include <lightningd/subd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/wait.h>
|
||||
#include <wire/common_wiregen.h>
|
||||
#include <wire/wire_io.h>
|
||||
|
||||
void maybe_subd_child(struct lightningd *ld, int childpid, int wstatus)
|
||||
@@ -831,8 +830,7 @@ void subd_send_msg(struct subd *sd, const u8 *msg_out)
|
||||
u16 type = fromwire_peektype(msg_out);
|
||||
/* FIXME: We should use unique upper bits for each daemon, then
|
||||
* have generate-wire.py add them, just assert here. */
|
||||
assert(!strstarts(common_wire_name(type), "INVALID") ||
|
||||
!strstarts(sd->msgname(type), "INVALID"));
|
||||
assert(!strstarts(sd->msgname(type), "INVALID"));
|
||||
msg_enqueue(sd->outq, msg_out);
|
||||
}
|
||||
|
||||
|
||||
@@ -482,11 +482,6 @@ struct command_result *param_array(struct command *cmd UNNEEDED, const char *nam
|
||||
const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
|
||||
const jsmntok_t **arr UNNEEDED)
|
||||
{ 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_bool */
|
||||
struct command_result *param_bool(struct command *cmd UNNEEDED, const char *name UNNEEDED,
|
||||
const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
|
||||
@@ -560,9 +555,6 @@ struct command_result *param_u64(struct command *cmd UNNEEDED, const char *name
|
||||
/* Generated stub for peer_active_channel */
|
||||
struct channel *peer_active_channel(struct peer *peer UNNEEDED)
|
||||
{ fprintf(stderr, "peer_active_channel 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 */
|
||||
void peer_memleak_done(struct command *cmd UNNEEDED, struct subd *leaker UNNEEDED)
|
||||
{ fprintf(stderr, "peer_memleak_done called!\n"); abort(); }
|
||||
|
||||
@@ -42,7 +42,6 @@
|
||||
#include <openingd/common.h>
|
||||
#include <openingd/dualopend_wiregen.h>
|
||||
#include <unistd.h>
|
||||
#include <wire/common_wiregen.h>
|
||||
#include <wire/wire_sync.h>
|
||||
|
||||
/* stdin == lightningd, 3 == peer, 4 == gossipd, 5 = hsmd */
|
||||
@@ -897,17 +896,6 @@ static void dualopend_dev_memleak(struct state *state)
|
||||
}
|
||||
#endif /* DEVELOPER */
|
||||
|
||||
/* We were told to send a custommsg to the peer by `lightningd`. All the
|
||||
* verification is done on the side of `lightningd` so we should be good to
|
||||
* just forward it here. */
|
||||
static void dualopend_send_custommsg(struct state *state, const u8 *msg)
|
||||
{
|
||||
u8 *inner;
|
||||
if (!fromwire_custommsg_out(tmpctx, msg, &inner))
|
||||
master_badmsg(WIRE_CUSTOMMSG_OUT, msg);
|
||||
peer_write(state->pps, take(inner));
|
||||
}
|
||||
|
||||
static u8 *psbt_to_tx_sigs_msg(const tal_t *ctx,
|
||||
struct state *state,
|
||||
const struct wally_psbt *psbt)
|
||||
@@ -3465,23 +3453,6 @@ static void handle_gossip_in(struct state *state)
|
||||
handle_gossip_msg(state->pps, take(msg));
|
||||
}
|
||||
|
||||
/* Try to handle a custommsg Returns true if it was a custom message and has
|
||||
* been handled, false if the message was not handled.
|
||||
*/
|
||||
static bool dualopend_handle_custommsg(const u8 *msg)
|
||||
{
|
||||
enum peer_wire type = fromwire_peektype(msg);
|
||||
if (type % 2 == 1 && !peer_wire_is_defined(type)) {
|
||||
/* The message is not part of the messages we know how to
|
||||
* handle. Assuming this is a custommsg, we just forward it to the
|
||||
* master. */
|
||||
wire_sync_write(REQ_FD, take(towire_custommsg_in(NULL, msg)));
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* BOLT #2:
|
||||
*
|
||||
* A receiving node:
|
||||
@@ -3582,10 +3553,9 @@ static void do_reconnect_dance(struct state *state)
|
||||
do {
|
||||
clean_tmpctx();
|
||||
msg = peer_read(tmpctx, state->pps);
|
||||
} while (dualopend_handle_custommsg(msg)
|
||||
|| handle_peer_gossip_or_error(state->pps,
|
||||
&state->channel_id,
|
||||
msg));
|
||||
} while (handle_peer_gossip_or_error(state->pps,
|
||||
&state->channel_id,
|
||||
msg));
|
||||
|
||||
if (!fromwire_channel_reestablish
|
||||
(msg, &cid,
|
||||
@@ -3703,16 +3673,6 @@ static u8 *handle_master_in(struct state *state)
|
||||
case WIRE_DUALOPEND_LOCAL_PRIVATE_CHANNEL:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Now handle common messages. */
|
||||
switch ((enum common_wire)t) {
|
||||
case WIRE_CUSTOMMSG_OUT:
|
||||
dualopend_send_custommsg(state, msg);
|
||||
/* We send these. */
|
||||
case WIRE_CUSTOMMSG_IN:
|
||||
break;
|
||||
}
|
||||
|
||||
status_failed(STATUS_FAIL_MASTER_IO,
|
||||
"Unknown msg %s", tal_hex(tmpctx, msg));
|
||||
}
|
||||
@@ -3790,16 +3750,6 @@ static u8 *handle_peer_in(struct state *state)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Handle custommsgs */
|
||||
enum peer_wire type = fromwire_peektype(msg);
|
||||
if (type % 2 == 1 && !peer_wire_is_defined(type)) {
|
||||
/* The message is not part of the messages we know how to
|
||||
* handle. Assuming this is a custommsg, we just
|
||||
* forward it to master. */
|
||||
wire_sync_write(REQ_FD, take(towire_custommsg_in(NULL, msg)));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Handles standard cases, and legal unknown ones. */
|
||||
if (handle_peer_gossip_or_error(state->pps,
|
||||
&state->channel_id, msg))
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
#include <hsmd/hsmd_wiregen.h>
|
||||
#include <openingd/common.h>
|
||||
#include <openingd/openingd_wiregen.h>
|
||||
#include <wire/common_wiregen.h>
|
||||
#include <wire/peer_wire.h>
|
||||
#include <wire/wire_sync.h>
|
||||
|
||||
@@ -1260,16 +1259,6 @@ static u8 *handle_peer_in(struct state *state)
|
||||
if (t == WIRE_OPEN_CHANNEL)
|
||||
return fundee_channel(state, msg);
|
||||
|
||||
/* Handle custommsgs */
|
||||
enum peer_wire type = fromwire_peektype(msg);
|
||||
if (type % 2 == 1 && !peer_wire_is_defined(type)) {
|
||||
/* The message is not part of the messages we know how to
|
||||
* handle. Assuming this is a custommsg, we just forward it to the
|
||||
* master. */
|
||||
wire_sync_write(REQ_FD, take(towire_custommsg_in(NULL, msg)));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Handles standard cases, and legal unknown ones. */
|
||||
if (handle_peer_gossip_or_error(state->pps,
|
||||
&state->channel_id, msg))
|
||||
@@ -1334,17 +1323,6 @@ static void handle_dev_memleak(struct state *state, const u8 *msg)
|
||||
}
|
||||
#endif /* DEVELOPER */
|
||||
|
||||
/* We were told to send a custommsg to the peer by `lightningd`. All the
|
||||
* verification is done on the side of `lightningd` so we should be good to
|
||||
* just forward it here. */
|
||||
static void openingd_send_custommsg(struct state *state, const u8 *msg)
|
||||
{
|
||||
u8 *inner;
|
||||
if (!fromwire_custommsg_out(tmpctx, msg, &inner))
|
||||
master_badmsg(WIRE_CUSTOMMSG_OUT, msg);
|
||||
peer_write(state->pps, take(inner));
|
||||
}
|
||||
|
||||
/* Standard lightningd-fd-is-ready-to-read demux code. Again, we could hang
|
||||
* here, but if we can't trust our parent, who can we trust? */
|
||||
static u8 *handle_master_in(struct state *state)
|
||||
@@ -1406,16 +1384,6 @@ static u8 *handle_master_in(struct state *state)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Now handle common messages. */
|
||||
switch ((enum common_wire)t) {
|
||||
case WIRE_CUSTOMMSG_OUT:
|
||||
openingd_send_custommsg(state, msg);
|
||||
return NULL;
|
||||
/* We send these. */
|
||||
case WIRE_CUSTOMMSG_IN:
|
||||
break;
|
||||
}
|
||||
|
||||
status_failed(STATUS_FAIL_MASTER_IO,
|
||||
"Unknown msg %s", tal_hex(tmpctx, msg));
|
||||
}
|
||||
|
||||
@@ -2178,8 +2178,8 @@ def test_sendcustommsg(node_factory):
|
||||
# This should work since the peer is currently owned by `channeld`
|
||||
l2.rpc.sendcustommsg(l1.info['id'], msg)
|
||||
l2.daemon.wait_for_log(
|
||||
r'{peer_id}-{owner}-chan#[0-9]: \[OUT\] {msg}'.format(
|
||||
owner='channeld', msg=msg, peer_id=l1.info['id']
|
||||
r'{peer_id}-{owner}: \[OUT\] {msg}'.format(
|
||||
owner='connectd', msg=msg, peer_id=l1.info['id']
|
||||
)
|
||||
)
|
||||
l1.daemon.wait_for_log(r'\[IN\] {}'.format(msg))
|
||||
@@ -2193,8 +2193,8 @@ def test_sendcustommsg(node_factory):
|
||||
# This should work since the peer is currently owned by `openingd`
|
||||
l2.rpc.sendcustommsg(l4.info['id'], msg)
|
||||
l2.daemon.wait_for_log(
|
||||
r'{peer_id}-{owner}-chan#[0-9]: \[OUT\] {msg}'.format(
|
||||
owner='openingd', msg=msg, peer_id=l4.info['id']
|
||||
r'{peer_id}-{owner}: \[OUT\] {msg}'.format(
|
||||
owner='connectd', msg=msg, peer_id=l4.info['id']
|
||||
)
|
||||
)
|
||||
l4.daemon.wait_for_log(r'\[IN\] {}'.format(msg))
|
||||
|
||||
@@ -128,9 +128,6 @@ bool fromwire_channeld_sending_commitsig(const tal_t *ctx UNNEEDED, const void *
|
||||
/* Generated stub for fromwire_connectd_peer_connected */
|
||||
bool fromwire_connectd_peer_connected(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct node_id *id UNNEEDED, struct wireaddr_internal *addr UNNEEDED, bool *incoming UNNEEDED, u8 **features UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_connectd_peer_connected called!\n"); abort(); }
|
||||
/* Generated stub for fromwire_custommsg_in */
|
||||
bool fromwire_custommsg_in(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u8 **msg UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_custommsg_in called!\n"); abort(); }
|
||||
/* Generated stub for fromwire_hsmd_get_output_scriptpubkey_reply */
|
||||
bool fromwire_hsmd_get_output_scriptpubkey_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u8 **script UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_hsmd_get_output_scriptpubkey_reply called!\n"); abort(); }
|
||||
@@ -524,11 +521,6 @@ void outpointfilter_remove(struct outpointfilter *of UNNEEDED,
|
||||
bool param(struct command *cmd UNNEEDED, const char *buffer UNNEEDED,
|
||||
const jsmntok_t params[] UNNEEDED, ...)
|
||||
{ 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_bool */
|
||||
struct command_result *param_bool(struct command *cmd UNNEEDED, const char *name UNNEEDED,
|
||||
const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
|
||||
@@ -594,9 +586,6 @@ void payment_store(struct lightningd *ld UNNEEDED, struct wallet_payment *paymen
|
||||
void payment_succeeded(struct lightningd *ld UNNEEDED, struct htlc_out *hout UNNEEDED,
|
||||
const struct preimage *rval UNNEEDED)
|
||||
{ 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 */
|
||||
void peer_memleak_done(struct command *cmd UNNEEDED, struct subd *leaker UNNEEDED)
|
||||
{ fprintf(stderr, "peer_memleak_done called!\n"); abort(); }
|
||||
@@ -619,12 +608,6 @@ void peer_start_dualopend(struct peer *peer UNNEEDED, struct peer_fd *peer_fd UN
|
||||
void peer_start_openingd(struct peer *peer UNNEEDED,
|
||||
struct peer_fd *peer_fd UNNEEDED)
|
||||
{ fprintf(stderr, "peer_start_openingd called!\n"); abort(); }
|
||||
/* Generated stub for peer_wire_is_defined */
|
||||
bool peer_wire_is_defined(u16 type UNNEEDED)
|
||||
{ fprintf(stderr, "peer_wire_is_defined called!\n"); abort(); }
|
||||
/* Generated stub for peer_wire_name */
|
||||
const char *peer_wire_name(int e UNNEEDED)
|
||||
{ fprintf(stderr, "peer_wire_name called!\n"); abort(); }
|
||||
/* Generated stub for plugin_hook_call_ */
|
||||
bool plugin_hook_call_(struct lightningd *ld UNNEEDED, const struct plugin_hook *hook UNNEEDED,
|
||||
tal_t *cb_arg STEALS UNNEEDED)
|
||||
@@ -713,9 +696,6 @@ u8 *towire_connectd_peer_disconnected(const tal_t *ctx UNNEEDED, const struct no
|
||||
/* Generated stub for towire_connectd_peer_final_msg */
|
||||
u8 *towire_connectd_peer_final_msg(const tal_t *ctx UNNEEDED, const struct node_id *id UNNEEDED, const u8 *msg UNNEEDED)
|
||||
{ fprintf(stderr, "towire_connectd_peer_final_msg 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 */
|
||||
u8 *towire_errorfmt(const tal_t *ctx UNNEEDED,
|
||||
const struct channel_id *channel UNNEEDED,
|
||||
|
||||
@@ -10,7 +10,6 @@ WIRE_HEADERS := wire/onion_defs.h \
|
||||
wire/peer$(EXP)_wiregen.h \
|
||||
wire/onion$(EXP)_wiregen.h \
|
||||
wire/bolt12$(EXP)_wiregen.h \
|
||||
wire/common_wiregen.h \
|
||||
wire/channel_type_wiregen.h \
|
||||
wire/peer$(EXP)_printgen.h \
|
||||
wire/onion$(EXP)_printgen.h
|
||||
@@ -22,7 +21,6 @@ WIRE_SRC := wire/wire_sync.c \
|
||||
wire/peer_wire.c \
|
||||
wire/tlvstream.c \
|
||||
wire/towire.c \
|
||||
wire/common_wiregen.c \
|
||||
wire/bolt12$(EXP)_wiregen.c \
|
||||
wire/peer$(EXP)_wiregen.c \
|
||||
wire/channel_type_wiregen.c \
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
# A custom message that we got from a peer and don't know how to handle, so we
|
||||
# forward it to the master for further handling.
|
||||
msgtype,custommsg_in,1030
|
||||
msgdata,custommsg_in,msg_len,u16,
|
||||
msgdata,custommsg_in,msg,u8,msg_len
|
||||
|
||||
# A custom message that the master tells us to send to the peer.
|
||||
msgtype,custommsg_out,1031
|
||||
msgdata,custommsg_out,msg_len,u16,
|
||||
msgdata,custommsg_out,msg,u8,msg_len
|
||||
|
Reference in New Issue
Block a user