diff --git a/cmd/syncthing/main.go b/cmd/syncthing/main.go index 499bb6fa..efedcb87 100644 --- a/cmd/syncthing/main.go +++ b/cmd/syncthing/main.go @@ -1068,45 +1068,15 @@ func setupGUI(mainService *suture.Supervisor, cfg *config.Wrapper, m *model.Mode } func defaultConfig(cfgFile string) *config.Wrapper { - myName, _ := os.Hostname() + newCfg := config.NewWithFreePorts(myID) - var defaultFolder config.FolderConfiguration - - if !noDefaultFolder { - l.Infoln("Default folder created and/or linked to new config") - defaultFolder = config.NewFolderConfiguration(myID, "default", "Default Folder", fs.FilesystemTypeBasic, locations[locDefFolder]) - } else { + if noDefaultFolder { l.Infoln("We will skip creation of a default folder on first start since the proper envvar is set") + return config.Wrap(cfgFile, newCfg) } - thisDevice := config.NewDeviceConfiguration(myID, myName) - thisDevice.Addresses = []string{"dynamic"} - - newCfg := config.New(myID) - if !noDefaultFolder { - newCfg.Folders = []config.FolderConfiguration{defaultFolder} - } - newCfg.Devices = []config.DeviceConfiguration{thisDevice} - - port, err := getFreePort("127.0.0.1", 8384) - if err != nil { - l.Fatalln("get free port (GUI):", err) - } - newCfg.GUI.RawAddress = fmt.Sprintf("127.0.0.1:%d", port) - - port, err = getFreePort("0.0.0.0", 22000) - if err != nil { - l.Fatalln("get free port (BEP):", err) - } - if port == 22000 { - newCfg.Options.ListenAddresses = []string{"default"} - } else { - newCfg.Options.ListenAddresses = []string{ - fmt.Sprintf("tcp://%s", net.JoinHostPort("0.0.0.0", strconv.Itoa(port))), - "dynamic+https://relays.syncthing.net/endpoint", - } - } - + newCfg.Folders = append(newCfg.Folders, config.NewFolderConfiguration(myID, "default", "Default Folder", fs.FilesystemTypeBasic, locations[locDefFolder])) + l.Infoln("Default folder created and/or linked to new config") return config.Wrap(cfgFile, newCfg) } @@ -1146,27 +1116,6 @@ func ensureDir(dir string, mode fs.FileMode) { } } -// getFreePort returns a free TCP port fort listening on. The ports given are -// tried in succession and the first to succeed is returned. If none succeed, -// a random high port is returned. -func getFreePort(host string, ports ...int) (int, error) { - for _, port := range ports { - c, err := net.Listen("tcp", fmt.Sprintf("%s:%d", host, port)) - if err == nil { - c.Close() - return port, nil - } - } - - c, err := net.Listen("tcp", host+":0") - if err != nil { - return 0, err - } - addr := c.Addr().(*net.TCPAddr) - c.Close() - return addr.Port, nil -} - func standbyMonitor() { restartDelay := 60 * time.Second now := time.Now() diff --git a/lib/config/config.go b/lib/config/config.go index 0b2186dd..35626c38 100644 --- a/lib/config/config.go +++ b/lib/config/config.go @@ -47,6 +47,7 @@ var ( util.Address("tcp", net.JoinHostPort("0.0.0.0", strconv.Itoa(DefaultTCPPort))), "dynamic+https://relays.syncthing.net/endpoint", } + DefaultGUIPort = 8384 // DefaultDiscoveryServersV4 should be substituted when the configuration // contains default-v4. DefaultDiscoveryServersV4 = []string{ @@ -83,6 +84,31 @@ func New(myID protocol.DeviceID) Configuration { return cfg } +func NewWithFreePorts(myID protocol.DeviceID) Configuration { + cfg := New(myID) + + port, err := getFreePort("127.0.0.1", DefaultGUIPort) + if err != nil { + l.Fatalln("get free port (GUI):", err) + } + cfg.GUI.RawAddress = fmt.Sprintf("127.0.0.1:%d", port) + + port, err = getFreePort("0.0.0.0", DefaultTCPPort) + if err != nil { + l.Fatalln("get free port (BEP):", err) + } + if port == DefaultTCPPort { + cfg.Options.ListenAddresses = []string{"default"} + } else { + cfg.Options.ListenAddresses = []string{ + fmt.Sprintf("tcp://%s", net.JoinHostPort("0.0.0.0", strconv.Itoa(port))), + "dynamic+https://relays.syncthing.net/endpoint", + } + } + + return cfg +} + func ReadXML(r io.Reader, myID protocol.DeviceID) (Configuration, error) { var cfg Configuration @@ -840,3 +866,23 @@ func filterURLSchemePrefix(addrs []string, prefix string) []string { } return addrs } + +// tried in succession and the first to succeed is returned. If none succeed, +// a random high port is returned. +func getFreePort(host string, ports ...int) (int, error) { + for _, port := range ports { + c, err := net.Listen("tcp", fmt.Sprintf("%s:%d", host, port)) + if err == nil { + c.Close() + return port, nil + } + } + + c, err := net.Listen("tcp", host+":0") + if err != nil { + return 0, err + } + addr := c.Addr().(*net.TCPAddr) + c.Close() + return addr.Port, nil +} diff --git a/lib/config/wrapper.go b/lib/config/wrapper.go index 543464af..827ad06b 100644 --- a/lib/config/wrapper.go +++ b/lib/config/wrapper.go @@ -64,7 +64,6 @@ type Wrapper struct { deviceMap map[protocol.DeviceID]DeviceConfiguration folderMap map[string]FolderConfiguration - replaces chan Configuration subs []Committer mut sync.Mutex @@ -79,7 +78,6 @@ func Wrap(path string, cfg Configuration) *Wrapper { path: path, mut: sync.NewMutex(), } - w.replaces = make(chan Configuration) return w } @@ -104,12 +102,6 @@ func (w *Wrapper) ConfigPath() string { return w.path } -// Stop stops the Serve() loop. Set and Replace operations will panic after a -// Stop. -func (w *Wrapper) Stop() { - close(w.replaces) -} - // Subscribe registers the given handler to be called on any future // configuration changes. func (w *Wrapper) Subscribe(c Committer) {