connectd: refactor outgoing loop.
What changed, and why it matters
This is a routine internal code cleanup in Core Lightning's connection handling. It moves the logic for picking the next message to send into a new helper function, with no intended behavior change. There is no indication this fixes or introduces a security issue.
No security action required. Treat as normal maintenance/refactoring.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit refactors connectd/multiplex.c by extracting message selection (queue drain + optional gossip + dev_disconnect write suppression) into a new static helper next_msg_for_peer(). The previous inline logic in write_to_peer() is replaced by a call to this helper. The behavior appears equivalent: it still prefers queued peer messages, falls back to gossip when not draining, and still drops messages when dev_writes_enabled reaches zero. The only observable difference is that dev_writes_enabled now returns NULL instead of recursing into write_to_peer when the counter hits zero; the caller then encrypts and sends the next available message normally. This is a pure refactor preparing for future multi-message writes.
Changed components
connectd/multiplex.cInspect captured patch +34 / −24
diff --git a/connectd/multiplex.c b/connectd/multiplex.c
index a59b7ad3..4135ad5f 100644
--- a/connectd/multiplex.c
+++ b/connectd/multiplex.c
@@ -1085,6 +1085,33 @@ static void maybe_update_channelid(struct subd *subd, const u8 *msg)
}
}
+static const u8 *next_msg_for_peer(struct peer *peer)
+{
+ const u8 *msg;
+
+ msg = msg_dequeue(peer->peer_outq);
+ if (!msg) {
+ /* Draining? Don't send gossip. */
+ if (peer->draining_state == WRITING_TO_PEER)
+ return NULL;
+
+ /* If they want us to send gossip, do so now. */
+ msg = maybe_gossip_msg(NULL, peer);
+ if (!msg)
+ return NULL;
+ }
+
+ /* dev_disconnect can disable writes (discard everything) */
+ if (peer->dev_writes_enabled) {
+ if (*peer->dev_writes_enabled == 0) {
+ return tal_free(msg);
+ }
+ (*peer->dev_writes_enabled)--;
+ }
+
+ return msg;
+}
+
static struct io_plan *write_to_peer(struct io_conn *peer_conn,
struct peer *peer)
{
@@ -1094,10 +1121,8 @@ static struct io_plan *write_to_peer(struct io_conn *peer_conn,
/* Free last sent one (if any) */
peer->sent_to_peer = tal_free(peer->sent_to_peer);
- /* Pop tail of send queue */
- msg = msg_dequeue(peer->peer_outq);
-
- /* Still nothing to send? */
+ /* Pop tail of send queue (or gossip) */
+ msg = next_msg_for_peer(peer);
if (!msg) {
/* Draining? Shutdown socket (to avoid losing msgs) */
if (peer->draining_state == WRITING_TO_PEER) {
@@ -1106,33 +1131,18 @@ static struct io_plan *write_to_peer(struct io_conn *peer_conn,
return io_sock_shutdown(peer_conn);
}
- /* If they want us to send gossip, do so now. */
- msg = maybe_gossip_msg(NULL, peer);
- if (!msg) {
- /* Tell them to read again, */
- io_wake(&peer->subds);
- io_wake(&peer->peer_in);
+ /* Tell them to read again, */
+ io_wake(&peer->subds);
+ io_wake(&peer->peer_in);
- /* Wait for them to wake us */
- return msg_queue_wait(peer_conn, peer->peer_outq,
- write_to_peer, peer);
- }
+ /* Wait for them to wake us */
+ return msg_queue_wait(peer_conn, peer->peer_outq, write_to_peer, peer);
}
if (peer->draining_state == WRITING_TO_PEER)
status_peer_debug(&peer->id, "draining, but sending %s.",
peer_wire_name(fromwire_peektype(msg)));
- /* dev_disconnect can disable writes */
- if (peer->dev_writes_enabled) {
- if (*peer->dev_writes_enabled == 0) {
- tal_free(msg);
- /* Continue, to drain queue */
- return write_to_peer(peer_conn, peer);
- }
- (*peer->dev_writes_enabled)--;
- }
-
return encrypt_and_send(peer, take(msg));
}
Why this scored 13/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.