mirror of
https://github.com/octoleo/syncthing.git
synced 2024-11-08 22:31:04 +00:00
lib/config: Do introductions in a single config change (#6162)
This commit is contained in:
parent
90d85fd0a2
commit
57d668ed1d
@ -1252,14 +1252,20 @@ func (m *model) ClusterConfig(deviceID protocol.DeviceID, cm protocol.ClusterCon
|
||||
}
|
||||
|
||||
if deviceCfg.Introducer {
|
||||
foldersDevices, introduced := m.handleIntroductions(deviceCfg, cm)
|
||||
if introduced {
|
||||
changed = true
|
||||
}
|
||||
// If permitted, check if the introducer has unshare devices/folders with
|
||||
// some of the devices/folders that we know were introduced to us by him.
|
||||
if !deviceCfg.SkipIntroductionRemovals && m.handleDeintroductions(deviceCfg, cm, foldersDevices) {
|
||||
folders, devices, foldersDevices, introduced := m.handleIntroductions(deviceCfg, cm)
|
||||
folders, devices, deintroduced := m.handleDeintroductions(deviceCfg, foldersDevices, folders, devices)
|
||||
if introduced || deintroduced {
|
||||
changed = true
|
||||
cfg := m.cfg.RawCopy()
|
||||
cfg.Folders = make([]config.FolderConfiguration, 0, len(folders))
|
||||
for _, fcfg := range folders {
|
||||
cfg.Folders = append(cfg.Folders, fcfg)
|
||||
}
|
||||
cfg.Devices = make([]config.DeviceConfiguration, len(devices))
|
||||
for _, dcfg := range devices {
|
||||
cfg.Devices = append(cfg.Devices, dcfg)
|
||||
}
|
||||
m.cfg.Replace(cfg)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1270,12 +1276,11 @@ func (m *model) ClusterConfig(deviceID protocol.DeviceID, cm protocol.ClusterCon
|
||||
}
|
||||
}
|
||||
|
||||
// handleIntroductions handles adding devices/shares that are shared by an introducer device
|
||||
func (m *model) handleIntroductions(introducerCfg config.DeviceConfiguration, cm protocol.ClusterConfig) (folderDeviceSet, bool) {
|
||||
// This device is an introducer. Go through the announced lists of folders
|
||||
// and devices and add what we are missing, remove what we have extra that
|
||||
// has been introducer by the introducer.
|
||||
// handleIntroductions handles adding devices/folders that are shared by an introducer device
|
||||
func (m *model) handleIntroductions(introducerCfg config.DeviceConfiguration, cm protocol.ClusterConfig) (map[string]config.FolderConfiguration, map[protocol.DeviceID]config.DeviceConfiguration, folderDeviceSet, bool) {
|
||||
changed := false
|
||||
folders := m.cfg.Folders()
|
||||
devices := m.cfg.Devices()
|
||||
|
||||
foldersDevices := make(folderDeviceSet)
|
||||
|
||||
@ -1285,12 +1290,14 @@ func (m *model) handleIntroductions(introducerCfg config.DeviceConfiguration, cm
|
||||
// with devices that we have in common, yet are currently not sharing
|
||||
// the folder.
|
||||
|
||||
fcfg, ok := m.cfg.Folder(folder.ID)
|
||||
fcfg, ok := folders[folder.ID]
|
||||
if !ok {
|
||||
// Don't have this folder, carry on.
|
||||
continue
|
||||
}
|
||||
|
||||
folderChanged := false
|
||||
|
||||
for _, device := range folder.Devices {
|
||||
// No need to share with self.
|
||||
if device.ID == m.id {
|
||||
@ -1301,7 +1308,7 @@ func (m *model) handleIntroductions(introducerCfg config.DeviceConfiguration, cm
|
||||
|
||||
if _, ok := m.cfg.Devices()[device.ID]; !ok {
|
||||
// The device is currently unknown. Add it to the config.
|
||||
m.introduceDevice(device, introducerCfg)
|
||||
devices[device.ID] = m.introduceDevice(device, introducerCfg)
|
||||
} else if fcfg.SharedWith(device.ID) {
|
||||
// We already share the folder with this device, so
|
||||
// nothing to do.
|
||||
@ -1315,36 +1322,41 @@ func (m *model) handleIntroductions(introducerCfg config.DeviceConfiguration, cm
|
||||
DeviceID: device.ID,
|
||||
IntroducedBy: introducerCfg.DeviceID,
|
||||
})
|
||||
changed = true
|
||||
folderChanged = true
|
||||
}
|
||||
|
||||
if changed {
|
||||
m.cfg.SetFolder(fcfg)
|
||||
if folderChanged {
|
||||
folders[fcfg.ID] = fcfg
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
|
||||
return foldersDevices, changed
|
||||
return folders, devices, foldersDevices, changed
|
||||
}
|
||||
|
||||
// handleDeintroductions handles removals of devices/shares that are removed by an introducer device
|
||||
func (m *model) handleDeintroductions(introducerCfg config.DeviceConfiguration, cm protocol.ClusterConfig, foldersDevices folderDeviceSet) bool {
|
||||
func (m *model) handleDeintroductions(introducerCfg config.DeviceConfiguration, foldersDevices folderDeviceSet, folders map[string]config.FolderConfiguration, devices map[protocol.DeviceID]config.DeviceConfiguration) (map[string]config.FolderConfiguration, map[protocol.DeviceID]config.DeviceConfiguration, bool) {
|
||||
if introducerCfg.SkipIntroductionRemovals {
|
||||
return folders, devices, false
|
||||
}
|
||||
|
||||
changed := false
|
||||
devicesNotIntroduced := make(map[protocol.DeviceID]struct{})
|
||||
|
||||
folders := m.cfg.FolderList()
|
||||
// Check if we should unshare some folders, if the introducer has unshared them.
|
||||
for i := range folders {
|
||||
for k := 0; k < len(folders[i].Devices); k++ {
|
||||
if folders[i].Devices[k].IntroducedBy != introducerCfg.DeviceID {
|
||||
devicesNotIntroduced[folders[i].Devices[k].DeviceID] = struct{}{}
|
||||
for folderID, folderCfg := range folders {
|
||||
for k := 0; k < len(folderCfg.Devices); k++ {
|
||||
if folderCfg.Devices[k].IntroducedBy != introducerCfg.DeviceID {
|
||||
devicesNotIntroduced[folderCfg.Devices[k].DeviceID] = struct{}{}
|
||||
continue
|
||||
}
|
||||
if !foldersDevices.has(folders[i].Devices[k].DeviceID, folders[i].ID) {
|
||||
if !foldersDevices.has(folderCfg.Devices[k].DeviceID, folderCfg.ID) {
|
||||
// We could not find that folder shared on the
|
||||
// introducer with the device that was introduced to us.
|
||||
// We should follow and unshare as well.
|
||||
l.Infof("Unsharing folder %s with %v as introducer %v no longer shares the folder with that device", folders[i].Description(), folders[i].Devices[k].DeviceID, folders[i].Devices[k].IntroducedBy)
|
||||
folders[i].Devices = append(folders[i].Devices[:k], folders[i].Devices[k+1:]...)
|
||||
l.Infof("Unsharing folder %s with %v as introducer %v no longer shares the folder with that device", folderCfg.Description(), folderCfg.Devices[k].DeviceID, folderCfg.Devices[k].IntroducedBy)
|
||||
folderCfg.Devices = append(folderCfg.Devices[:k], folderCfg.Devices[k+1:]...)
|
||||
folders[folderID] = folderCfg
|
||||
k--
|
||||
changed = true
|
||||
}
|
||||
@ -1354,9 +1366,7 @@ func (m *model) handleDeintroductions(introducerCfg config.DeviceConfiguration,
|
||||
// Check if we should remove some devices, if the introducer no longer
|
||||
// shares any folder with them. Yet do not remove if we share other
|
||||
// folders that haven't been introduced by the introducer.
|
||||
devMap := m.cfg.Devices()
|
||||
devices := make([]config.DeviceConfiguration, 0, len(devMap))
|
||||
for deviceID, device := range devMap {
|
||||
for deviceID, device := range devices {
|
||||
if device.IntroducedBy == introducerCfg.DeviceID {
|
||||
if !foldersDevices.hasDevice(deviceID) {
|
||||
if _, ok := devicesNotIntroduced[deviceID]; !ok {
|
||||
@ -1364,22 +1374,15 @@ func (m *model) handleDeintroductions(introducerCfg config.DeviceConfiguration,
|
||||
// device, remove the device.
|
||||
l.Infof("Removing device %v as introducer %v no longer shares any folders with that device", deviceID, device.IntroducedBy)
|
||||
changed = true
|
||||
delete(devices, deviceID)
|
||||
continue
|
||||
}
|
||||
l.Infof("Would have removed %v as %v no longer shares any folders, yet there are other folders that are shared with this device that haven't been introduced by this introducer.", deviceID, device.IntroducedBy)
|
||||
}
|
||||
}
|
||||
devices = append(devices, device)
|
||||
}
|
||||
|
||||
if changed {
|
||||
cfg := m.cfg.RawCopy()
|
||||
cfg.Folders = folders
|
||||
cfg.Devices = devices
|
||||
m.cfg.Replace(cfg)
|
||||
}
|
||||
|
||||
return changed
|
||||
return folders, devices, changed
|
||||
}
|
||||
|
||||
// handleAutoAccepts handles adding and sharing folders for devices that have
|
||||
@ -1430,7 +1433,7 @@ func (m *model) handleAutoAccepts(deviceCfg config.DeviceConfiguration, folder p
|
||||
}
|
||||
}
|
||||
|
||||
func (m *model) introduceDevice(device protocol.Device, introducerCfg config.DeviceConfiguration) {
|
||||
func (m *model) introduceDevice(device protocol.Device, introducerCfg config.DeviceConfiguration) config.DeviceConfiguration {
|
||||
addresses := []string{"dynamic"}
|
||||
for _, addr := range device.Addresses {
|
||||
if addr != "dynamic" {
|
||||
@ -1455,7 +1458,7 @@ func (m *model) introduceDevice(device protocol.Device, introducerCfg config.Dev
|
||||
newDeviceCfg.SkipIntroductionRemovals = device.SkipIntroductionRemovals
|
||||
}
|
||||
|
||||
m.cfg.SetDevice(newDeviceCfg)
|
||||
return newDeviceCfg
|
||||
}
|
||||
|
||||
// Closed is called when a connection has been closed
|
||||
|
Loading…
Reference in New Issue
Block a user