From 314c8ed4704d6ba35fdd83fe783b1b6e674f63e5 Mon Sep 17 00:00:00 2001 From: Virgil Date: Tue, 31 Mar 2026 13:42:04 +0000 Subject: [PATCH] fix(transport): serialise graceful websocket close Co-Authored-By: Virgil --- node/transport.go | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/node/transport.go b/node/transport.go index 9d9c989..155d900 100644 --- a/node/transport.go +++ b/node/transport.go @@ -482,9 +482,9 @@ func (t *Transport) Send(peerID string, msg *Message) error { return pc.Send(msg) } -// for pc := range transport.Connections() { -// _ = pc -// } +// for pc := range transport.Connections() { +// _ = pc +// } func (t *Transport) Connections() iter.Seq[*PeerConnection] { return func(yield func(*PeerConnection) bool) { t.mutex.RLock() @@ -953,6 +953,10 @@ func (pc *PeerConnection) Send(msg *Message) error { pc.writeMutex.Lock() defer pc.writeMutex.Unlock() + return pc.sendLocked(msg) +} + +func (pc *PeerConnection) sendLocked(msg *Message) error { data, err := pc.transport.encryptMessage(msg, pc.SharedSecret) if err != nil { return err @@ -996,10 +1000,10 @@ const ( func (pc *PeerConnection) GracefulClose(reason string, code int) error { var err error pc.closeOnce.Do(func() { + pc.writeMutex.Lock() + defer pc.writeMutex.Unlock() + // Try to send disconnect message (best effort). - // Note: we must NOT call SetWriteDeadline outside writeMutex — Send() - // already manages write deadlines under the lock. Setting it here - // without the lock races with concurrent Send() calls (P2P-RACE-1). if pc.transport != nil && pc.SharedSecret != nil { identity := pc.transport.nodeManager.GetIdentity() if identity != nil { @@ -1009,7 +1013,7 @@ func (pc *PeerConnection) GracefulClose(reason string, code int) error { } msg, msgErr := NewMessage(MessageDisconnect, identity.ID, pc.Peer.ID, payload) if msgErr == nil { - pc.Send(msg) + _ = pc.sendLocked(msg) } } }