lib: Handle adding enc folders on an existing conn (fixes #7509) (#7510)

This commit is contained in:
Simon Frei
2021-03-22 21:50:19 +01:00
committed by GitHub
parent f7929229c8
commit 924b96856f
11 changed files with 160 additions and 87 deletions
+1 -1
View File
@@ -33,7 +33,7 @@ func newFakeConnection(id protocol.DeviceID, model Model) *fakeConnection {
})
f.IDReturns(id)
f.CloseCalls(func(err error) {
model.Closed(f, err)
model.Closed(id, err)
f.ClosedReturns(true)
})
return f
+6 -6
View File
@@ -43,10 +43,10 @@ type Model struct {
arg1 string
arg2 string
}
ClosedStub func(protocol.Connection, error)
ClosedStub func(protocol.DeviceID, error)
closedMutex sync.RWMutex
closedArgsForCall []struct {
arg1 protocol.Connection
arg1 protocol.DeviceID
arg2 error
}
ClusterConfigStub func(protocol.DeviceID, protocol.ClusterConfig) error
@@ -684,10 +684,10 @@ func (fake *Model) BringToFrontArgsForCall(i int) (string, string) {
return argsForCall.arg1, argsForCall.arg2
}
func (fake *Model) Closed(arg1 protocol.Connection, arg2 error) {
func (fake *Model) Closed(arg1 protocol.DeviceID, arg2 error) {
fake.closedMutex.Lock()
fake.closedArgsForCall = append(fake.closedArgsForCall, struct {
arg1 protocol.Connection
arg1 protocol.DeviceID
arg2 error
}{arg1, arg2})
stub := fake.ClosedStub
@@ -704,13 +704,13 @@ func (fake *Model) ClosedCallCount() int {
return len(fake.closedArgsForCall)
}
func (fake *Model) ClosedCalls(stub func(protocol.Connection, error)) {
func (fake *Model) ClosedCalls(stub func(protocol.DeviceID, error)) {
fake.closedMutex.Lock()
defer fake.closedMutex.Unlock()
fake.ClosedStub = stub
}
func (fake *Model) ClosedArgsForCall(i int) (protocol.Connection, error) {
func (fake *Model) ClosedArgsForCall(i int) (protocol.DeviceID, error) {
fake.closedMutex.RLock()
defer fake.closedMutex.RUnlock()
argsForCall := fake.closedArgsForCall[i]
+23 -18
View File
@@ -293,7 +293,7 @@ func (m *model) initFolders(cfg config.Configuration) error {
ignoredDevices := observedDeviceSet(m.cfg.IgnoredDevices())
m.cleanPending(cfg.DeviceMap(), cfg.FolderMap(), ignoredDevices, nil)
m.resendClusterConfig(clusterConfigDevices.AsSlice())
m.sendClusterConfig(clusterConfigDevices.AsSlice())
return nil
}
@@ -1510,7 +1510,7 @@ func (m *model) ccCheckEncryption(fcfg config.FolderConfiguration, folderDevice
m.fmut.Unlock()
// We can only announce ourselfs once we have the token,
// thus we need to resend CCs now that we have it.
m.resendClusterConfig(fcfg.DeviceIDs())
m.sendClusterConfig(fcfg.DeviceIDs())
return nil
}
}
@@ -1520,7 +1520,7 @@ func (m *model) ccCheckEncryption(fcfg config.FolderConfiguration, folderDevice
return nil
}
func (m *model) resendClusterConfig(ids []protocol.DeviceID) {
func (m *model) sendClusterConfig(ids []protocol.DeviceID) {
if len(ids) == 0 {
return
}
@@ -1534,7 +1534,8 @@ func (m *model) resendClusterConfig(ids []protocol.DeviceID) {
m.pmut.RUnlock()
// Generating cluster-configs acquires fmut -> must happen outside of pmut.
for _, conn := range ccConns {
cm := m.generateClusterConfig(conn.ID())
cm, passwords := m.generateClusterConfig(conn.ID())
conn.SetFolderPasswords(passwords)
go conn.ClusterConfig(cm)
}
}
@@ -1728,9 +1729,7 @@ func (m *model) introduceDevice(device protocol.Device, introducerCfg config.Dev
}
// Closed is called when a connection has been closed
func (m *model) Closed(conn protocol.Connection, err error) {
device := conn.ID()
func (m *model) Closed(device protocol.DeviceID, err error) {
m.pmut.Lock()
conn, ok := m.conn[device]
if !ok {
@@ -2247,7 +2246,8 @@ func (m *model) AddConnection(conn protocol.Connection, hello protocol.Hello) {
m.pmut.Unlock()
// Acquires fmut, so has to be done outside of pmut.
cm := m.generateClusterConfig(deviceID)
cm, passwords := m.generateClusterConfig(deviceID)
conn.SetFolderPasswords(passwords)
conn.ClusterConfig(cm)
if (device.Name == "" || m.cfg.Options().OverwriteRemoteDevNames) && hello.DeviceName != "" {
@@ -2407,15 +2407,17 @@ func (m *model) numHashers(folder string) int {
return 1
}
// generateClusterConfig returns a ClusterConfigMessage that is correct for
// the given peer device
func (m *model) generateClusterConfig(device protocol.DeviceID) protocol.ClusterConfig {
// generateClusterConfig returns a ClusterConfigMessage that is correct and the
// set of folder passwords for the given peer device
func (m *model) generateClusterConfig(device protocol.DeviceID) (protocol.ClusterConfig, map[string]string) {
var message protocol.ClusterConfig
m.fmut.RLock()
defer m.fmut.RUnlock()
for _, folderCfg := range m.cfg.FolderList() {
folders := m.cfg.FolderList()
passwords := make(map[string]string, len(folders))
for _, folderCfg := range folders {
if !folderCfg.SharedWith(device) {
continue
}
@@ -2448,8 +2450,8 @@ func (m *model) generateClusterConfig(device protocol.DeviceID) protocol.Cluster
// another cluster config once the folder is started.
protocolFolder.Paused = folderCfg.Paused || fs == nil
for _, device := range folderCfg.Devices {
deviceCfg, _ := m.cfg.Device(device.DeviceID)
for _, folderDevice := range folderCfg.Devices {
deviceCfg, _ := m.cfg.Device(folderDevice.DeviceID)
protocolDevice := protocol.Device{
ID: deviceCfg.DeviceID,
@@ -2462,8 +2464,11 @@ func (m *model) generateClusterConfig(device protocol.DeviceID) protocol.Cluster
if deviceCfg.DeviceID == m.id && hasEncryptionToken {
protocolDevice.EncryptionPasswordToken = encryptionToken
} else if device.EncryptionPassword != "" {
protocolDevice.EncryptionPasswordToken = protocol.PasswordToken(folderCfg.ID, device.EncryptionPassword)
} else if folderDevice.EncryptionPassword != "" {
protocolDevice.EncryptionPasswordToken = protocol.PasswordToken(folderCfg.ID, folderDevice.EncryptionPassword)
if folderDevice.DeviceID == device {
passwords[folderCfg.ID] = folderDevice.EncryptionPassword
}
}
if fs != nil {
@@ -2482,7 +2487,7 @@ func (m *model) generateClusterConfig(device protocol.DeviceID) protocol.Cluster
message.Folders = append(message.Folders, protocolFolder)
}
return message
return message, passwords
}
func (m *model) State(folder string) (string, time.Time, error) {
@@ -2891,7 +2896,7 @@ func (m *model) CommitConfiguration(from, to config.Configuration) bool {
}
m.pmut.RUnlock()
// Generating cluster-configs acquires fmut -> must happen outside of pmut.
m.resendClusterConfig(clusterConfigDevices.AsSlice())
m.sendClusterConfig(clusterConfigDevices.AsSlice())
ignoredDevices := observedDeviceSet(to.IgnoredDevices)
m.cleanPending(toDevices, toFolders, ignoredDevices, removedFolders)
+10 -10
View File
@@ -341,7 +341,7 @@ func TestDeviceRename(t *testing.T) {
t.Errorf("Device already has a name")
}
m.Closed(conn, protocol.ErrTimeout)
m.Closed(conn.ID(), protocol.ErrTimeout)
hello.DeviceName = "tester"
m.AddConnection(conn, hello)
@@ -349,7 +349,7 @@ func TestDeviceRename(t *testing.T) {
t.Errorf("Device did not get a name")
}
m.Closed(conn, protocol.ErrTimeout)
m.Closed(conn.ID(), protocol.ErrTimeout)
hello.DeviceName = "tester2"
m.AddConnection(conn, hello)
@@ -367,7 +367,7 @@ func TestDeviceRename(t *testing.T) {
t.Errorf("Device name not saved in config")
}
m.Closed(conn, protocol.ErrTimeout)
m.Closed(conn.ID(), protocol.ErrTimeout)
waiter, err := cfg.Modify(func(cfg *config.Configuration) {
cfg.Options.OverwriteRemoteDevNames = true
@@ -428,7 +428,7 @@ func TestClusterConfig(t *testing.T) {
m.ServeBackground()
defer cleanupModel(m)
cm := m.generateClusterConfig(device2)
cm, _ := m.generateClusterConfig(device2)
if l := len(cm.Folders); l != 2 {
t.Fatalf("Incorrect number of folders %d != 2", l)
@@ -853,7 +853,7 @@ func TestIssue4897(t *testing.T) {
defer cleanupModel(m)
cancel()
cm := m.generateClusterConfig(device1)
cm, _ := m.generateClusterConfig(device1)
if l := len(cm.Folders); l != 1 {
t.Errorf("Cluster config contains %v folders, expected 1", l)
}
@@ -873,7 +873,7 @@ func TestIssue5063(t *testing.T) {
for _, c := range m.conn {
conn := c.(*fakeConnection)
conn.CloseCalls(func(_ error) {})
defer m.Closed(c, errStopped) // to unblock deferred m.Stop()
defer m.Closed(c.ID(), errStopped) // to unblock deferred m.Stop()
}
m.pmut.Unlock()
@@ -2428,8 +2428,8 @@ func TestNoRequestsFromPausedDevices(t *testing.T) {
t.Errorf("should have two available")
}
m.Closed(newFakeConnection(device1, m), errDeviceUnknown)
m.Closed(newFakeConnection(device2, m), errDeviceUnknown)
m.Closed(device1, errDeviceUnknown)
m.Closed(device2, errDeviceUnknown)
avail = m.testAvailability("default", file, file.Blocks[0])
if len(avail) != 0 {
@@ -3171,7 +3171,7 @@ func TestConnCloseOnRestart(t *testing.T) {
br := &testutils.BlockingRW{}
nw := &testutils.NoopRW{}
m.AddConnection(protocol.NewConnection(device1, br, nw, testutils.NoopCloser{}, m, new(protocolmocks.ConnectionInfo), protocol.CompressionNever), protocol.Hello{})
m.AddConnection(protocol.NewConnection(device1, br, nw, testutils.NoopCloser{}, m, new(protocolmocks.ConnectionInfo), protocol.CompressionNever, nil), protocol.Hello{})
m.pmut.RLock()
if len(m.closed) != 1 {
t.Fatalf("Expected just one conn (len(m.conn) == %v)", len(m.conn))
@@ -4142,7 +4142,7 @@ func TestCCFolderNotRunning(t *testing.T) {
defer cleanupModelAndRemoveDir(m, tfs.URI())
// A connection can happen before all the folders are started.
cc := m.generateClusterConfig(device1)
cc, _ := m.generateClusterConfig(device1)
if l := len(cc.Folders); l != 1 {
t.Fatalf("Expected 1 folder in CC, got %v", l)
}