From dcb3af7d7cb2362b4a14428c0e17beeafa01b29b Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 20 Jun 2017 15:19:03 +0930 Subject: [PATCH] channeld: allow waiting for a specific reply from master. We're about to change to a batch interface, where we tell the master before we send certain packets (eg. commit, revoke). We need to wait for it to respond before doing anything else, but it might cross-over and be sending us commands at the same time. This queues those requests until we're ready. Signed-off-by: Rusty Russell --- lightningd/channel/channel.c | 39 ++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/lightningd/channel/channel.c b/lightningd/channel/channel.c index c9b252aee..558c33caf 100644 --- a/lightningd/channel/channel.c +++ b/lightningd/channel/channel.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -83,6 +84,11 @@ struct peer { struct daemon_conn gossip_client; struct daemon_conn master; + /* If we're waiting for a specific reply, defer other messages. */ + enum channel_wire_type master_reply_type; + void (*handle_master_reply)(struct peer *peer, const u8 *msg); + struct msg_queue master_deferred; + struct timers timers; struct oneshot *commit_timer; u32 commit_msec; @@ -1295,6 +1301,25 @@ static struct io_plan *req_in(struct io_conn *conn, struct daemon_conn *master) else { enum channel_wire_type t = fromwire_peektype(master->msg_in); + /* Waiting for something specific? Defer others. */ + if (peer->handle_master_reply) { + void (*handle)(struct peer *peer, const u8 *msg); + + if (t != peer->master_reply_type) { + msg_enqueue(&peer->master_deferred, + take(master->msg_in)); + master->msg_in = NULL; + goto out_next; + } + + /* Just in case it resets this. */ + handle = peer->handle_master_reply; + peer->handle_master_reply = NULL; + + handle(peer, master->msg_in); + goto out; + } + switch (t) { case WIRE_CHANNEL_FUNDING_LOCKED: handle_funding_locked(peer, master->msg_in); @@ -1339,6 +1364,18 @@ static struct io_plan *req_in(struct io_conn *conn, struct daemon_conn *master) } out: + /* In case we've now processed reply, process packet backlog. */ + if (!peer->handle_master_reply) { + const u8 *msg = msg_dequeue(&peer->master_deferred); + if (msg) { + /* Free old packet exactly like daemon_conn_read_next */ + master->msg_in = tal_free(master->msg_in); + master->msg_in = cast_const(u8 *, tal_steal(master,msg)); + return req_in(conn, master); + } + } + +out_next: return daemon_conn_read_next(conn, master); } @@ -1380,6 +1417,8 @@ int main(int argc, char *argv[]) peer->commit_timer = NULL; peer->commit_index[LOCAL] = peer->commit_index[REMOTE] = 0; peer->have_sigs[LOCAL] = peer->have_sigs[REMOTE] = false; + peer->handle_master_reply = NULL; + msg_queue_init(&peer->master_deferred, peer); /* We send these to HSM to get real signatures; don't have valgrind * complain. */