From 04b927104fe2983875016fe565c352ee9517036a Mon Sep 17 00:00:00 2001 From: Simon Frei Date: Tue, 23 Apr 2019 21:47:11 +0200 Subject: [PATCH] lib/protocol: Don't send any messages before cluster config (#5646) * lib/model: Send cluster config before releasing pmut * reshuffle * add model.connReady to track cluster-config status * Corrected comments/strings * do it in protocol --- lib/protocol/protocol.go | 58 +++++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 19 deletions(-) diff --git a/lib/protocol/protocol.go b/lib/protocol/protocol.go index 21d1127d..e283db47 100644 --- a/lib/protocol/protocol.go +++ b/lib/protocol/protocol.go @@ -182,11 +182,12 @@ type rawConnection struct { nextID int32 nextIDMut sync.Mutex - outbox chan asyncMessage - closed chan struct{} - closeOnce sync.Once - sendCloseOnce sync.Once - compression Compression + sentClusterConfig chan struct{} + outbox chan asyncMessage + closed chan struct{} + closeOnce sync.Once + sendCloseOnce sync.Once + compression Compression } type asyncResult struct { @@ -220,15 +221,16 @@ func NewConnection(deviceID DeviceID, reader io.Reader, writer io.Writer, receiv cw := &countingWriter{Writer: writer} c := rawConnection{ - id: deviceID, - name: name, - receiver: nativeModel{receiver}, - cr: cr, - cw: cw, - awaiting: make(map[int32]chan asyncResult), - outbox: make(chan asyncMessage), - closed: make(chan struct{}), - compression: compress, + id: deviceID, + name: name, + receiver: nativeModel{receiver}, + cr: cr, + cw: cw, + awaiting: make(map[int32]chan asyncResult), + sentClusterConfig: make(chan struct{}), + outbox: make(chan asyncMessage), + closed: make(chan struct{}), + compression: compress, } return wireFormatConnection{&c} @@ -322,9 +324,20 @@ func (c *rawConnection) Request(folder string, name string, offset int64, size i return res.val, res.err } -// ClusterConfig send the cluster configuration message to the peer and returns any error +// ClusterConfig sends the cluster configuration message to the peer. +// It must be called just once (as per BEP). func (c *rawConnection) ClusterConfig(config ClusterConfig) { - c.send(&config, nil) + select { + case <-c.sentClusterConfig: + return + case <-c.closed: + return + default: + } + if err := c.writeMessage(asyncMessage{&config, nil}); err != nil { + c.internalClose(err) + } + close(c.sentClusterConfig) } func (c *rawConnection) Closed() bool { @@ -628,13 +641,20 @@ func (c *rawConnection) handleResponse(resp Response) { } func (c *rawConnection) send(msg message, done chan struct{}) bool { + defer func() { + if done != nil { + close(done) + } + }() + select { + case <-c.sentClusterConfig: + case <-c.closed: + return false + } select { case c.outbox <- asyncMessage{msg, done}: return true case <-c.closed: - if done != nil { - close(done) - } return false } }