From cfc9776baefd28210239e958c68ce4d9b7230b4f Mon Sep 17 00:00:00 2001 From: Jakob Borg Date: Thu, 9 Apr 2015 12:53:13 +0200 Subject: [PATCH] Check for short ID conflict at startup --- cmd/syncthing/main.go | 19 +++++++++++++++++++ cmd/syncthing/main_test.go | 24 ++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/cmd/syncthing/main.go b/cmd/syncthing/main.go index 14fa8660a..c2ea0a088 100644 --- a/cmd/syncthing/main.go +++ b/cmd/syncthing/main.go @@ -435,6 +435,10 @@ func syncthingMain() { cfg.Save() } + if err := checkShortIDs(cfg); err != nil { + l.Fatalln("Short device IDs are in conflict. Unlucky!\n Regenerate the device ID of one if the following:\n ", err) + } + if len(profiler) > 0 { go func() { l.Debugln("Starting profiler on", profiler) @@ -1031,3 +1035,18 @@ func cleanConfigDirectory() { } } } + +// checkShortIDs verifies that the configuration won't result in duplicate +// short ID:s; that is, that the devices in the cluster all have unique +// initial 64 bits. +func checkShortIDs(cfg *config.Wrapper) error { + exists := make(map[uint64]protocol.DeviceID) + for deviceID := range cfg.Devices() { + shortID := deviceID.Short() + if otherID, ok := exists[shortID]; ok { + return fmt.Errorf("%v in conflict with %v", deviceID, otherID) + } + exists[shortID] = deviceID + } + return nil +} diff --git a/cmd/syncthing/main_test.go b/cmd/syncthing/main_test.go index a3ef5ee7a..b64a10274 100644 --- a/cmd/syncthing/main_test.go +++ b/cmd/syncthing/main_test.go @@ -140,3 +140,27 @@ func TestFolderErrors(t *testing.T) { t.Error("Unexpected error", cfg.Folders()["folder"].Invalid) } } + +func TestShortIDCheck(t *testing.T) { + cfg := config.Wrap("/tmp/test", config.Configuration{ + Devices: []config.DeviceConfiguration{ + {DeviceID: protocol.DeviceID{8, 16, 24, 32, 40, 48, 56, 0, 0}}, + {DeviceID: protocol.DeviceID{8, 16, 24, 32, 40, 48, 56, 1, 1}}, // first 56 bits same, differ in the first 64 bits + }, + }) + + if err := checkShortIDs(cfg); err != nil { + t.Error("Unexpected error:", err) + } + + cfg = config.Wrap("/tmp/test", config.Configuration{ + Devices: []config.DeviceConfiguration{ + {DeviceID: protocol.DeviceID{8, 16, 24, 32, 40, 48, 56, 64, 0}}, + {DeviceID: protocol.DeviceID{8, 16, 24, 32, 40, 48, 56, 64, 1}}, // first 64 bits same + }, + }) + + if err := checkShortIDs(cfg); err == nil { + t.Error("Should have gotten an error") + } +}