|
|
@@ -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
|
|
|
}
|
|
|
}
|