connectd: new command to make us send message and close.

Currently we abuse openingd and dualopend to do this, but connectd already
has the ability to talk to peers, so it's more efficient.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2021-06-03 11:31:16 +09:30
parent e424180058
commit 7cffea10ce
5 changed files with 124 additions and 12 deletions

View file

@ -1591,23 +1591,19 @@ static struct io_plan *connect_to_peer(struct io_conn *conn,
return daemon_conn_read_next(conn, daemon->master);
}
/* lightningd tells us a peer has disconnected. */
static struct io_plan *peer_disconnected(struct io_conn *conn,
struct daemon *daemon, const u8 *msg)
/* A peer is gone: clean things up. */
static void cleanup_dead_peer(struct daemon *daemon, const struct node_id *id)
{
struct node_id id, *node;
if (!fromwire_connectd_peer_disconnected(msg, &id))
master_badmsg(WIRE_CONNECTD_PEER_DISCONNECTED, msg);
struct node_id *node;
/* We should stay in sync with lightningd at all times. */
node = node_set_get(&daemon->peers, &id);
node = node_set_get(&daemon->peers, id);
if (!node)
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"peer_disconnected unknown peer: %s",
type_to_string(tmpctx, struct node_id, &id));
type_to_string(tmpctx, struct node_id, id));
node_set_del(&daemon->peers, node);
status_peer_debug(&id, "disconnect");
status_peer_debug(id, "disconnect");
/* Wake up in case there's a reconnecting peer waiting in io_wait. */
io_wake(node);
@ -1615,6 +1611,69 @@ static struct io_plan *peer_disconnected(struct io_conn *conn,
/* Note: deleting from a htable (a-la node_set_del) does not free it:
* htable doesn't assume it's a tal object at all. */
tal_free(node);
}
/* lightningd tells us a peer has disconnected. */
static struct io_plan *peer_disconnected(struct io_conn *conn,
struct daemon *daemon, const u8 *msg)
{
struct node_id id;
if (!fromwire_connectd_peer_disconnected(msg, &id))
master_badmsg(WIRE_CONNECTD_PEER_DISCONNECTED, msg);
cleanup_dead_peer(daemon, &id);
/* Read the next message from lightningd. */
return daemon_conn_read_next(conn, daemon->master);
}
/* lightningd tells us to send a final (usually error) message to peer, then
* disconnect. */
struct final_msg_data {
struct daemon *daemon;
struct node_id id;
};
static void destroy_final_msg_data(struct final_msg_data *f)
{
cleanup_dead_peer(f->daemon, &f->id);
}
static struct io_plan *send_final_msg(struct io_conn *conn, u8 *msg)
{
return io_write(conn, msg, tal_bytelen(msg), io_close_cb, NULL);
}
/* lightningd tells us to send a msg and disconnect. */
static struct io_plan *peer_final_msg(struct io_conn *conn,
struct daemon *daemon, const u8 *msg)
{
struct per_peer_state *pps;
struct final_msg_data *f = tal(NULL, struct final_msg_data);
u8 *finalmsg;
int fds[3];
/* pps is allocated off f, so fds are closed when f freed. */
if (!fromwire_connectd_peer_final_msg(f, msg, &f->id, &pps, &finalmsg))
master_badmsg(WIRE_CONNECTD_PEER_FINAL_MSG, msg);
/* When f is freed, we want to mark node as dead. */
tal_add_destructor(f, destroy_final_msg_data);
/* Get the fds for this peer. */
for (size_t i = 0; i < ARRAY_SIZE(fds); i++)
fds[i] = fdpass_recv(io_conn_fd(conn));
/* We put peer fd into conn, but pps needs to free the rest */
per_peer_state_set_fds(pps, -1, fds[1], fds[2]);
/* Log and encrypt message for peer. */
status_peer_io(LOG_IO_OUT, &f->id, finalmsg);
finalmsg = cryptomsg_encrypt_msg(f, &pps->cs, take(finalmsg));
/* Organize io loop to write out that message, it will free f
* once closed */
tal_steal(io_new_conn(daemon, fds[0], send_final_msg, finalmsg), f);
/* Read the next message from lightningd. */
return daemon_conn_read_next(conn, daemon->master);
@ -1662,6 +1721,9 @@ static struct io_plan *recv_req(struct io_conn *conn,
case WIRE_CONNECTD_PEER_DISCONNECTED:
return peer_disconnected(conn, daemon, msg);
case WIRE_CONNECTD_PEER_FINAL_MSG:
return peer_final_msg(conn, daemon, msg);
case WIRE_CONNECTD_DEV_MEMLEAK:
#if DEVELOPER
return dev_connect_memleak(conn, daemon, msg);

View file

@ -65,6 +65,13 @@ msgdata,connectd_peer_connected,features,u8,flen
msgtype,connectd_peer_disconnected,2015
msgdata,connectd_peer_disconnected,id,node_id,
# master -> connectd: give message to peer and disconnect. Three fds: peer, gossip and gossip_store
msgtype,connectd_peer_final_msg,2003
msgdata,connectd_peer_final_msg,id,node_id,
msgdata,connectd_peer_final_msg,pps,per_peer_state,
msgdata,connectd_peer_final_msg,len,u16,
msgdata,connectd_peer_final_msg,msg,u8,len
# master -> connectd: do you have a memleak?
msgtype,connectd_dev_memleak,2033

1 #include <common/cryptomsg.h>
65 msgtype,connectd_dev_memleak,2033
66 msgtype,connectd_dev_memleak_reply,2133
67 msgdata,connectd_dev_memleak_reply,leak,bool,
68
69
70
71
72
73
74
75
76
77

View file

@ -29,6 +29,7 @@ const char *connectd_wire_name(int e)
case WIRE_CONNECTD_CONNECT_FAILED: return "WIRE_CONNECTD_CONNECT_FAILED";
case WIRE_CONNECTD_PEER_CONNECTED: return "WIRE_CONNECTD_PEER_CONNECTED";
case WIRE_CONNECTD_PEER_DISCONNECTED: return "WIRE_CONNECTD_PEER_DISCONNECTED";
case WIRE_CONNECTD_PEER_FINAL_MSG: return "WIRE_CONNECTD_PEER_FINAL_MSG";
case WIRE_CONNECTD_DEV_MEMLEAK: return "WIRE_CONNECTD_DEV_MEMLEAK";
case WIRE_CONNECTD_DEV_MEMLEAK_REPLY: return "WIRE_CONNECTD_DEV_MEMLEAK_REPLY";
}
@ -49,6 +50,7 @@ bool connectd_wire_is_defined(u16 type)
case WIRE_CONNECTD_CONNECT_FAILED:;
case WIRE_CONNECTD_PEER_CONNECTED:;
case WIRE_CONNECTD_PEER_DISCONNECTED:;
case WIRE_CONNECTD_PEER_FINAL_MSG:;
case WIRE_CONNECTD_DEV_MEMLEAK:;
case WIRE_CONNECTD_DEV_MEMLEAK_REPLY:;
return true;
@ -368,6 +370,39 @@ bool fromwire_connectd_peer_disconnected(const void *p, struct node_id *id)
return cursor != NULL;
}
/* WIRE: CONNECTD_PEER_FINAL_MSG */
/* master -> connectd: give message to peer and disconnect. Three fds: peer */
u8 *towire_connectd_peer_final_msg(const tal_t *ctx, const struct node_id *id, const struct per_peer_state *pps, const u8 *msg)
{
u16 len = tal_count(msg);
u8 *p = tal_arr(ctx, u8, 0);
towire_u16(&p, WIRE_CONNECTD_PEER_FINAL_MSG);
towire_node_id(&p, id);
towire_per_peer_state(&p, pps);
towire_u16(&p, len);
towire_u8_array(&p, msg, len);
return memcheck(p, tal_count(p));
}
bool fromwire_connectd_peer_final_msg(const tal_t *ctx, const void *p, struct node_id *id, struct per_peer_state **pps, u8 **msg)
{
u16 len;
const u8 *cursor = p;
size_t plen = tal_count(p);
if (fromwire_u16(&cursor, &plen) != WIRE_CONNECTD_PEER_FINAL_MSG)
return false;
fromwire_node_id(&cursor, &plen, id);
*pps = fromwire_per_peer_state(ctx, &cursor, &plen);
len = fromwire_u16(&cursor, &plen);
// 2nd case msg
*msg = len ? tal_arr(ctx, u8, len) : NULL;
fromwire_u8_array(&cursor, &plen, *msg, len);
return cursor != NULL;
}
/* WIRE: CONNECTD_DEV_MEMLEAK */
/* master -> connectd: do you have a memleak? */
u8 *towire_connectd_dev_memleak(const tal_t *ctx)
@ -408,4 +443,4 @@ bool fromwire_connectd_dev_memleak_reply(const void *p, bool *leak)
*leak = fromwire_bool(&cursor, &plen);
return cursor != NULL;
}
// SHA256STAMP:9bbb0b97a226bd5c85a21bafde42c7fd438b8107d6d30b7c7b17c16a6cbd3557
// SHA256STAMP:7c9585941825eab65d734eb1c233eee5c78b5792e19ec68f0a9986abca2b0ffe

View file

@ -31,6 +31,8 @@ enum connectd_wire {
WIRE_CONNECTD_PEER_CONNECTED = 2002,
/* master -> connectd: peer has disconnected. */
WIRE_CONNECTD_PEER_DISCONNECTED = 2015,
/* master -> connectd: give message to peer and disconnect. Three fds: peer */
WIRE_CONNECTD_PEER_FINAL_MSG = 2003,
/* master -> connectd: do you have a memleak? */
WIRE_CONNECTD_DEV_MEMLEAK = 2033,
WIRE_CONNECTD_DEV_MEMLEAK_REPLY = 2133,
@ -92,6 +94,11 @@ bool fromwire_connectd_peer_connected(const tal_t *ctx, const void *p, struct no
u8 *towire_connectd_peer_disconnected(const tal_t *ctx, const struct node_id *id);
bool fromwire_connectd_peer_disconnected(const void *p, struct node_id *id);
/* WIRE: CONNECTD_PEER_FINAL_MSG */
/* master -> connectd: give message to peer and disconnect. Three fds: peer */
u8 *towire_connectd_peer_final_msg(const tal_t *ctx, const struct node_id *id, const struct per_peer_state *pps, const u8 *msg);
bool fromwire_connectd_peer_final_msg(const tal_t *ctx, const void *p, struct node_id *id, struct per_peer_state **pps, u8 **msg);
/* WIRE: CONNECTD_DEV_MEMLEAK */
/* master -> connectd: do you have a memleak? */
u8 *towire_connectd_dev_memleak(const tal_t *ctx);
@ -103,4 +110,4 @@ bool fromwire_connectd_dev_memleak_reply(const void *p, bool *leak);
#endif /* LIGHTNING_CONNECTD_CONNECTD_WIREGEN_H */
// SHA256STAMP:9bbb0b97a226bd5c85a21bafde42c7fd438b8107d6d30b7c7b17c16a6cbd3557
// SHA256STAMP:7c9585941825eab65d734eb1c233eee5c78b5792e19ec68f0a9986abca2b0ffe

View file

@ -315,6 +315,7 @@ static unsigned connectd_msg(struct subd *connectd, const u8 *msg, const int *fd
case WIRE_CONNECTD_CONNECT_TO_PEER:
case WIRE_CONNECTD_PEER_DISCONNECTED:
case WIRE_CONNECTD_DEV_MEMLEAK:
case WIRE_CONNECTD_PEER_FINAL_MSG:
/* This is a reply, so never gets through to here. */
case WIRE_CONNECTD_INIT_REPLY:
case WIRE_CONNECTD_ACTIVATE_REPLY: