mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-03-03 10:46:58 +01:00
plugin: Add connected
hook
This hook is used to let a plugin decide whether we should continue with the connection normally, or whether we should be dropping the connection. Possible use-cases include policy enforcement (dropping connections based on previous interactions), draining a node by allowing only peers with an active channel to reconnect, or temporarily preventing a channel from making progress. Signed-off-by: Christian Decker <decker.christian@gmail.com>
This commit is contained in:
parent
5f0b065622
commit
ca3db290ba
3 changed files with 103 additions and 30 deletions
|
@ -44,6 +44,7 @@
|
||||||
#include <lightningd/opening_control.h>
|
#include <lightningd/opening_control.h>
|
||||||
#include <lightningd/options.h>
|
#include <lightningd/options.h>
|
||||||
#include <lightningd/peer_htlcs.h>
|
#include <lightningd/peer_htlcs.h>
|
||||||
|
#include <lightningd/plugin_hook.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <wally_bip32.h>
|
#include <wally_bip32.h>
|
||||||
#include <wire/gen_onion_wire.h>
|
#include <wire/gen_onion_wire.h>
|
||||||
|
@ -411,39 +412,51 @@ void channel_errmsg(struct channel *channel,
|
||||||
err_for_them ? "sent" : "received", desc);
|
err_for_them ? "sent" : "received", desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Connectd tells us a peer has connected: it never hands us duplicates, since
|
/* Possible outcomes returned by the `connected` hook. */
|
||||||
* it holds them until we say peer_died. */
|
enum peer_connected_hook_result {
|
||||||
void peer_connected(struct lightningd *ld, const u8 *msg,
|
PEER_CONNECTED_CONTINUE,
|
||||||
int peer_fd, int gossip_fd)
|
PEER_CONNECTED_DISCONNECT,
|
||||||
{
|
};
|
||||||
struct pubkey id;
|
|
||||||
struct crypto_state cs;
|
struct peer_connected_hook_payload {
|
||||||
u8 *globalfeatures, *localfeatures;
|
struct lightningd *ld;
|
||||||
u8 *error;
|
struct crypto_state crypto_state;
|
||||||
struct channel *channel;
|
struct channel *channel;
|
||||||
struct wireaddr_internal addr;
|
struct wireaddr_internal addr;
|
||||||
struct peer *peer;
|
struct peer *peer;
|
||||||
|
int peer_fd;
|
||||||
|
int gossip_fd;
|
||||||
|
};
|
||||||
|
|
||||||
if (!fromwire_connect_peer_connected(msg, msg,
|
struct peer_connected_hook_response {
|
||||||
&id, &addr, &cs,
|
enum peer_connected_hook_result result;
|
||||||
&globalfeatures, &localfeatures))
|
};
|
||||||
fatal("Connectd gave bad CONNECT_PEER_CONNECTED message %s",
|
|
||||||
tal_hex(msg, msg));
|
|
||||||
|
|
||||||
/* Complete any outstanding connect commands. */
|
static void
|
||||||
connect_succeeded(ld, &id);
|
peer_connected_serialize(struct peer_connected_hook_payload *payload,
|
||||||
|
struct json_stream *stream)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/* If we're already dealing with this peer, hand off to correct
|
static struct peer_connected_hook_response *
|
||||||
* subdaemon. Otherwise, we'll hand to openingd to wait there. */
|
peer_connected_deserialize(const tal_t *ctx, const char *buffer,
|
||||||
peer = peer_by_id(ld, &id);
|
const jsmntok_t *toks)
|
||||||
if (!peer)
|
{
|
||||||
peer = new_peer(ld, 0, &id, &addr);
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
peer_update_features(peer, globalfeatures, localfeatures);
|
static void
|
||||||
|
peer_connected_hook_cb(struct peer_connected_hook_payload *payload,
|
||||||
/* Can't be opening, since we wouldn't have sent peer_disconnected. */
|
struct peer_connected_hook_response *response)
|
||||||
assert(!peer->uncommitted_channel);
|
{
|
||||||
channel = peer_active_channel(peer);
|
struct lightningd *ld = payload->ld;
|
||||||
|
struct crypto_state *cs = &payload->crypto_state;
|
||||||
|
struct channel *channel = payload->channel;
|
||||||
|
struct wireaddr_internal addr = payload->addr;
|
||||||
|
struct peer *peer = payload->peer;
|
||||||
|
int gossip_fd = payload->gossip_fd;
|
||||||
|
int peer_fd = payload->peer_fd;
|
||||||
|
u8 *error;
|
||||||
|
|
||||||
if (channel) {
|
if (channel) {
|
||||||
log_debug(channel->log, "Peer has reconnected, state %s",
|
log_debug(channel->log, "Peer has reconnected, state %s",
|
||||||
|
@ -490,30 +503,82 @@ void peer_connected(struct lightningd *ld, const u8 *msg,
|
||||||
assert(!channel->owner);
|
assert(!channel->owner);
|
||||||
|
|
||||||
channel->peer->addr = addr;
|
channel->peer->addr = addr;
|
||||||
peer_start_channeld(channel, &cs,
|
peer_start_channeld(channel, cs,
|
||||||
peer_fd, gossip_fd, NULL,
|
peer_fd, gossip_fd, NULL,
|
||||||
true);
|
true);
|
||||||
|
tal_free(payload);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case CLOSINGD_SIGEXCHANGE:
|
case CLOSINGD_SIGEXCHANGE:
|
||||||
assert(!channel->owner);
|
assert(!channel->owner);
|
||||||
|
|
||||||
channel->peer->addr = addr;
|
channel->peer->addr = addr;
|
||||||
peer_start_closingd(channel, &cs,
|
peer_start_closingd(channel, cs,
|
||||||
peer_fd, gossip_fd,
|
peer_fd, gossip_fd,
|
||||||
true, NULL);
|
true, NULL);
|
||||||
|
tal_free(payload);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
notify_connect(ld, &id, &addr);
|
notify_connect(ld, &peer->id, &addr);
|
||||||
|
|
||||||
/* No err, all good. */
|
/* No err, all good. */
|
||||||
error = NULL;
|
error = NULL;
|
||||||
|
|
||||||
send_error:
|
send_error:
|
||||||
peer_start_openingd(peer, &cs, peer_fd, gossip_fd, error);
|
peer_start_openingd(peer, cs, peer_fd, gossip_fd, error);
|
||||||
|
tal_free(payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_PLUGIN_HOOK(peer_connected, peer_connected_hook_cb,
|
||||||
|
struct peer_connected_hook_payload *,
|
||||||
|
peer_connected_serialize,
|
||||||
|
struct peer_connected_hook_payload *,
|
||||||
|
peer_connected_deserialize,
|
||||||
|
struct peer_connected_hook_response *);
|
||||||
|
|
||||||
|
/* Connectd tells us a peer has connected: it never hands us duplicates, since
|
||||||
|
* it holds them until we say peer_died. */
|
||||||
|
void peer_connected(struct lightningd *ld, const u8 *msg,
|
||||||
|
int peer_fd, int gossip_fd)
|
||||||
|
{
|
||||||
|
struct pubkey id;
|
||||||
|
u8 *globalfeatures, *localfeatures;
|
||||||
|
struct peer *peer;
|
||||||
|
struct peer_connected_hook_payload *hook_payload;
|
||||||
|
|
||||||
|
hook_payload = tal(NULL, struct peer_connected_hook_payload);
|
||||||
|
hook_payload->ld = ld;
|
||||||
|
hook_payload->gossip_fd = gossip_fd;
|
||||||
|
hook_payload->peer_fd = peer_fd;
|
||||||
|
|
||||||
|
if (!fromwire_connect_peer_connected(msg, msg,
|
||||||
|
&id, &hook_payload->addr, &hook_payload->crypto_state,
|
||||||
|
&globalfeatures, &localfeatures))
|
||||||
|
fatal("Connectd gave bad CONNECT_PEER_CONNECTED message %s",
|
||||||
|
tal_hex(msg, msg));
|
||||||
|
|
||||||
|
/* Complete any outstanding connect commands. */
|
||||||
|
connect_succeeded(ld, &id);
|
||||||
|
|
||||||
|
/* If we're already dealing with this peer, hand off to correct
|
||||||
|
* subdaemon. Otherwise, we'll hand to openingd to wait there. */
|
||||||
|
peer = peer_by_id(ld, &id);
|
||||||
|
if (!peer)
|
||||||
|
peer = new_peer(ld, 0, &id, &hook_payload->addr);
|
||||||
|
|
||||||
|
tal_steal(peer, hook_payload);
|
||||||
|
hook_payload->peer = peer;
|
||||||
|
|
||||||
|
peer_update_features(peer, globalfeatures, localfeatures);
|
||||||
|
|
||||||
|
/* Can't be opening, since we wouldn't have sent peer_disconnected. */
|
||||||
|
assert(!peer->uncommitted_channel);
|
||||||
|
hook_payload->channel = peer_active_channel(peer);
|
||||||
|
|
||||||
|
plugin_hook_call_peer_connected(ld, hook_payload, hook_payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum watch_result funding_lockin_cb(struct lightningd *ld,
|
static enum watch_result funding_lockin_cb(struct lightningd *ld,
|
||||||
|
|
|
@ -352,6 +352,10 @@ void peer_start_openingd(struct peer *peer UNNEEDED,
|
||||||
int peer_fd UNNEEDED, int gossip_fd UNNEEDED,
|
int peer_fd UNNEEDED, int gossip_fd UNNEEDED,
|
||||||
const u8 *msg UNNEEDED)
|
const u8 *msg UNNEEDED)
|
||||||
{ fprintf(stderr, "peer_start_openingd called!\n"); abort(); }
|
{ fprintf(stderr, "peer_start_openingd called!\n"); abort(); }
|
||||||
|
/* Generated stub for plugin_hook_call_ */
|
||||||
|
void plugin_hook_call_(struct lightningd *ld UNNEEDED, const struct plugin_hook *hook UNNEEDED,
|
||||||
|
void *payload UNNEEDED, void *cb_arg UNNEEDED)
|
||||||
|
{ fprintf(stderr, "plugin_hook_call_ called!\n"); abort(); }
|
||||||
/* Generated stub for set_log_outfn_ */
|
/* Generated stub for set_log_outfn_ */
|
||||||
void set_log_outfn_(struct log_book *lr UNNEEDED,
|
void set_log_outfn_(struct log_book *lr UNNEEDED,
|
||||||
void (*print)(const char *prefix UNNEEDED,
|
void (*print)(const char *prefix UNNEEDED,
|
||||||
|
|
|
@ -407,6 +407,10 @@ void peer_start_openingd(struct peer *peer UNNEEDED,
|
||||||
int peer_fd UNNEEDED, int gossip_fd UNNEEDED,
|
int peer_fd UNNEEDED, int gossip_fd UNNEEDED,
|
||||||
const u8 *msg UNNEEDED)
|
const u8 *msg UNNEEDED)
|
||||||
{ fprintf(stderr, "peer_start_openingd called!\n"); abort(); }
|
{ fprintf(stderr, "peer_start_openingd called!\n"); abort(); }
|
||||||
|
/* Generated stub for plugin_hook_call_ */
|
||||||
|
void plugin_hook_call_(struct lightningd *ld UNNEEDED, const struct plugin_hook *hook UNNEEDED,
|
||||||
|
void *payload UNNEEDED, void *cb_arg UNNEEDED)
|
||||||
|
{ fprintf(stderr, "plugin_hook_call_ called!\n"); abort(); }
|
||||||
/* Generated stub for process_onionpacket */
|
/* Generated stub for process_onionpacket */
|
||||||
struct route_step *process_onionpacket(
|
struct route_step *process_onionpacket(
|
||||||
const tal_t * ctx UNNEEDED,
|
const tal_t * ctx UNNEEDED,
|
||||||
|
|
Loading…
Add table
Reference in a new issue