main.go 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118
  1. // Copyright (C) 2014 The Syncthing Authors.
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  5. // You can obtain one at http://mozilla.org/MPL/2.0/.
  6. package main
  7. import (
  8. "bytes"
  9. "crypto/tls"
  10. "errors"
  11. "flag"
  12. "fmt"
  13. "io/ioutil"
  14. "log"
  15. "net"
  16. "net/http"
  17. _ "net/http/pprof"
  18. "net/url"
  19. "os"
  20. "path/filepath"
  21. "regexp"
  22. "runtime"
  23. "runtime/pprof"
  24. "sort"
  25. "strconv"
  26. "strings"
  27. "time"
  28. "github.com/syncthing/syncthing/lib/config"
  29. "github.com/syncthing/syncthing/lib/connections"
  30. "github.com/syncthing/syncthing/lib/db"
  31. "github.com/syncthing/syncthing/lib/dialer"
  32. "github.com/syncthing/syncthing/lib/discover"
  33. "github.com/syncthing/syncthing/lib/events"
  34. "github.com/syncthing/syncthing/lib/logger"
  35. "github.com/syncthing/syncthing/lib/model"
  36. "github.com/syncthing/syncthing/lib/osutil"
  37. "github.com/syncthing/syncthing/lib/protocol"
  38. "github.com/syncthing/syncthing/lib/relay"
  39. "github.com/syncthing/syncthing/lib/symlinks"
  40. "github.com/syncthing/syncthing/lib/tlsutil"
  41. "github.com/syncthing/syncthing/lib/upgrade"
  42. "github.com/thejerf/suture"
  43. )
  44. var (
  45. Version = "unknown-dev"
  46. Codename = "Beryllium Bedbug"
  47. BuildEnv = "default"
  48. BuildStamp = "0"
  49. BuildDate time.Time
  50. BuildHost = "unknown"
  51. BuildUser = "unknown"
  52. IsRelease bool
  53. IsBeta bool
  54. LongVersion string
  55. )
  56. const (
  57. exitSuccess = 0
  58. exitError = 1
  59. exitNoUpgradeAvailable = 2
  60. exitRestarting = 3
  61. exitUpgrading = 4
  62. )
  63. const (
  64. bepProtocolName = "bep/1.0"
  65. tlsDefaultCommonName = "syncthing"
  66. tlsRSABits = 3072
  67. pingEventInterval = time.Minute
  68. maxSystemErrors = 5
  69. initialSystemLog = 10
  70. maxSystemLog = 250
  71. )
  72. // The discovery results are sorted by their source priority.
  73. const (
  74. ipv6LocalDiscoveryPriority = iota
  75. ipv4LocalDiscoveryPriority
  76. globalDiscoveryPriority
  77. )
  78. func init() {
  79. if Version != "unknown-dev" {
  80. // If not a generic dev build, version string should come from git describe
  81. exp := regexp.MustCompile(`^v\d+\.\d+\.\d+(-[a-z0-9]+)*(\+\d+-g[0-9a-f]+)?(-dirty)?$`)
  82. if !exp.MatchString(Version) {
  83. l.Fatalf("Invalid version string %q;\n\tdoes not match regexp %v", Version, exp)
  84. }
  85. }
  86. // Check for a clean release build. A release is something like "v0.1.2",
  87. // with an optional suffix of letters and dot separated numbers like
  88. // "-beta3.47". If there's more stuff, like a plus sign and a commit hash
  89. // and so on, then it's not a release. If there's a dash anywhere in
  90. // there, it's some kind of beta or prerelease version.
  91. exp := regexp.MustCompile(`^v\d+\.\d+\.\d+(-[a-z]+[\d\.]+)?$`)
  92. IsRelease = exp.MatchString(Version)
  93. IsBeta = strings.Contains(Version, "-")
  94. stamp, _ := strconv.Atoi(BuildStamp)
  95. BuildDate = time.Unix(int64(stamp), 0)
  96. date := BuildDate.UTC().Format("2006-01-02 15:04:05 MST")
  97. LongVersion = fmt.Sprintf(`syncthing %s "%s" (%s %s-%s %s) %s@%s %s`, Version, Codename, runtime.Version(), runtime.GOOS, runtime.GOARCH, BuildEnv, BuildUser, BuildHost, date)
  98. if os.Getenv("STTRACE") != "" {
  99. logFlags = log.Ltime | log.Ldate | log.Lmicroseconds | log.Lshortfile
  100. }
  101. }
  102. var (
  103. myID protocol.DeviceID
  104. confDir string
  105. logFlags = log.Ltime
  106. stop = make(chan int)
  107. cert tls.Certificate
  108. lans []*net.IPNet
  109. )
  110. const (
  111. usage = "syncthing [options]"
  112. extraUsage = `
  113. The default configuration directory is:
  114. %s
  115. The -logflags value is a sum of the following:
  116. 1 Date
  117. 2 Time
  118. 4 Microsecond time
  119. 8 Long filename
  120. 16 Short filename
  121. I.e. to prefix each log line with date and time, set -logflags=3 (1 + 2 from
  122. above). The value 0 is used to disable all of the above. The default is to
  123. show time only (2).
  124. Development Settings
  125. --------------------
  126. The following environment variables modify syncthing's behavior in ways that
  127. are mostly useful for developers. Use with care.
  128. STGUIASSETS Directory to load GUI assets from. Overrides compiled in
  129. assets.
  130. STTRACE A comma separated string of facilities to trace. The valid
  131. facility strings listed below.
  132. STPROFILER Set to a listen address such as "127.0.0.1:9090" to start the
  133. profiler with HTTP access.
  134. STCPUPROFILE Write a CPU profile to cpu-$pid.pprof on exit.
  135. STHEAPPROFILE Write heap profiles to heap-$pid-$timestamp.pprof each time
  136. heap usage increases.
  137. STBLOCKPROFILE Write block profiles to block-$pid-$timestamp.pprof every 20
  138. seconds.
  139. STPERFSTATS Write running performance statistics to perf-$pid.csv. Not
  140. supported on Windows.
  141. STNOUPGRADE Disable automatic upgrades.
  142. GOMAXPROCS Set the maximum number of CPU cores to use. Defaults to all
  143. available CPU cores.
  144. GOGC Percentage of heap growth at which to trigger GC. Default is
  145. 100. Lower numbers keep peak memory usage down, at the price
  146. of CPU usage (ie. performance).
  147. Debugging Facilities
  148. --------------------
  149. The following are valid values for the STTRACE variable:
  150. %s`
  151. )
  152. // Command line and environment options
  153. var (
  154. reset bool
  155. showVersion bool
  156. doUpgrade bool
  157. doUpgradeCheck bool
  158. upgradeTo string
  159. noBrowser bool
  160. noConsole bool
  161. generateDir string
  162. logFile string
  163. auditEnabled bool
  164. verbose bool
  165. paused bool
  166. noRestart = os.Getenv("STNORESTART") != ""
  167. noUpgrade = os.Getenv("STNOUPGRADE") != ""
  168. profiler = os.Getenv("STPROFILER")
  169. guiAssets = os.Getenv("STGUIASSETS")
  170. cpuProfile = os.Getenv("STCPUPROFILE") != ""
  171. stRestarting = os.Getenv("STRESTART") != ""
  172. innerProcess = os.Getenv("STNORESTART") != "" || os.Getenv("STMONITORED") != ""
  173. )
  174. func main() {
  175. if runtime.GOOS == "windows" {
  176. // On Windows, we use a log file by default. Setting the -logfile flag
  177. // to "-" disables this behavior.
  178. flag.StringVar(&logFile, "logfile", "", "Log file name (use \"-\" for stdout)")
  179. // We also add an option to hide the console window
  180. flag.BoolVar(&noConsole, "no-console", false, "Hide console window")
  181. } else {
  182. flag.StringVar(&logFile, "logfile", "-", "Log file name (use \"-\" for stdout)")
  183. }
  184. var guiAddress, guiAPIKey string
  185. flag.StringVar(&generateDir, "generate", "", "Generate key and config in specified dir, then exit")
  186. flag.StringVar(&guiAddress, "gui-address", guiAddress, "Override GUI address")
  187. flag.StringVar(&guiAPIKey, "gui-apikey", guiAPIKey, "Override GUI API key")
  188. flag.StringVar(&confDir, "home", "", "Set configuration directory")
  189. flag.IntVar(&logFlags, "logflags", logFlags, "Select information in log line prefix")
  190. flag.BoolVar(&noBrowser, "no-browser", false, "Do not start browser")
  191. flag.BoolVar(&noRestart, "no-restart", noRestart, "Do not restart; just exit")
  192. flag.BoolVar(&reset, "reset", false, "Reset the database")
  193. flag.BoolVar(&doUpgrade, "upgrade", false, "Perform upgrade")
  194. flag.BoolVar(&doUpgradeCheck, "upgrade-check", false, "Check for available upgrade")
  195. flag.BoolVar(&showVersion, "version", false, "Show version")
  196. flag.StringVar(&upgradeTo, "upgrade-to", upgradeTo, "Force upgrade directly from specified URL")
  197. flag.BoolVar(&auditEnabled, "audit", false, "Write events to audit file")
  198. flag.BoolVar(&verbose, "verbose", false, "Print verbose log output")
  199. flag.BoolVar(&paused, "paused", false, "Start with all devices paused")
  200. longUsage := fmt.Sprintf(extraUsage, baseDirs["config"], debugFacilities())
  201. flag.Usage = usageFor(flag.CommandLine, usage, longUsage)
  202. flag.Parse()
  203. if guiAddress != "" {
  204. // The config picks this up from the environment.
  205. os.Setenv("STGUIADDRESS", guiAddress)
  206. }
  207. if guiAPIKey != "" {
  208. // The config picks this up from the environment.
  209. os.Setenv("STGUIAPIKEY", guiAPIKey)
  210. }
  211. if noConsole {
  212. osutil.HideConsole()
  213. }
  214. if confDir != "" {
  215. // Not set as default above because the string can be really long.
  216. baseDirs["config"] = confDir
  217. }
  218. if err := expandLocations(); err != nil {
  219. l.Fatalln(err)
  220. }
  221. if guiAssets == "" {
  222. guiAssets = locations[locGUIAssets]
  223. }
  224. if logFile == "" {
  225. // Use the default log file location
  226. logFile = locations[locLogFile]
  227. }
  228. if showVersion {
  229. fmt.Println(LongVersion)
  230. return
  231. }
  232. l.SetFlags(logFlags)
  233. if generateDir != "" {
  234. dir, err := osutil.ExpandTilde(generateDir)
  235. if err != nil {
  236. l.Fatalln("generate:", err)
  237. }
  238. info, err := os.Stat(dir)
  239. if err == nil && !info.IsDir() {
  240. l.Fatalln(dir, "is not a directory")
  241. }
  242. if err != nil && os.IsNotExist(err) {
  243. err = osutil.MkdirAll(dir, 0700)
  244. if err != nil {
  245. l.Fatalln("generate:", err)
  246. }
  247. }
  248. certFile, keyFile := filepath.Join(dir, "cert.pem"), filepath.Join(dir, "key.pem")
  249. cert, err := tls.LoadX509KeyPair(certFile, keyFile)
  250. if err == nil {
  251. l.Warnln("Key exists; will not overwrite.")
  252. l.Infoln("Device ID:", protocol.NewDeviceID(cert.Certificate[0]))
  253. } else {
  254. cert, err = tlsutil.NewCertificate(certFile, keyFile, tlsDefaultCommonName, tlsRSABits)
  255. if err != nil {
  256. l.Fatalln("Create certificate:", err)
  257. }
  258. myID = protocol.NewDeviceID(cert.Certificate[0])
  259. if err != nil {
  260. l.Fatalln("Load certificate:", err)
  261. }
  262. if err == nil {
  263. l.Infoln("Device ID:", protocol.NewDeviceID(cert.Certificate[0]))
  264. }
  265. }
  266. cfgFile := filepath.Join(dir, "config.xml")
  267. if _, err := os.Stat(cfgFile); err == nil {
  268. l.Warnln("Config exists; will not overwrite.")
  269. return
  270. }
  271. var myName, _ = os.Hostname()
  272. var newCfg = defaultConfig(myName)
  273. var cfg = config.Wrap(cfgFile, newCfg)
  274. err = cfg.Save()
  275. if err != nil {
  276. l.Warnln("Failed to save config", err)
  277. }
  278. return
  279. }
  280. if info, err := os.Stat(baseDirs["config"]); err == nil && !info.IsDir() {
  281. l.Fatalln("Config directory", baseDirs["config"], "is not a directory")
  282. }
  283. // Ensure that our home directory exists.
  284. ensureDir(baseDirs["config"], 0700)
  285. if upgradeTo != "" {
  286. err := upgrade.ToURL(upgradeTo)
  287. if err != nil {
  288. l.Fatalln("Upgrade:", err) // exits 1
  289. }
  290. l.Okln("Upgraded from", upgradeTo)
  291. return
  292. }
  293. if doUpgrade || doUpgradeCheck {
  294. releasesURL := "https://api.github.com/repos/syncthing/syncthing/releases?per_page=30"
  295. if cfg, _, err := loadConfig(locations[locConfigFile]); err == nil {
  296. releasesURL = cfg.Options().ReleasesURL
  297. }
  298. rel, err := upgrade.LatestRelease(releasesURL, Version)
  299. if err != nil {
  300. l.Fatalln("Upgrade:", err) // exits 1
  301. }
  302. if upgrade.CompareVersions(rel.Tag, Version) <= 0 {
  303. l.Infof("No upgrade available (current %q >= latest %q).", Version, rel.Tag)
  304. os.Exit(exitNoUpgradeAvailable)
  305. }
  306. l.Infof("Upgrade available (current %q < latest %q)", Version, rel.Tag)
  307. if doUpgrade {
  308. // Use leveldb database locks to protect against concurrent upgrades
  309. _, err = db.Open(locations[locDatabase])
  310. if err != nil {
  311. l.Infoln("Attempting upgrade through running Syncthing...")
  312. err = upgradeViaRest()
  313. if err != nil {
  314. l.Fatalln("Upgrade:", err)
  315. }
  316. l.Okln("Syncthing upgrading")
  317. return
  318. }
  319. err = upgrade.To(rel)
  320. if err != nil {
  321. l.Fatalln("Upgrade:", err) // exits 1
  322. }
  323. l.Okf("Upgraded to %q", rel.Tag)
  324. }
  325. return
  326. }
  327. if reset {
  328. resetDB()
  329. return
  330. }
  331. if noRestart {
  332. syncthingMain()
  333. } else {
  334. monitorMain()
  335. }
  336. }
  337. func debugFacilities() string {
  338. facilities := l.Facilities()
  339. // Get a sorted list of names
  340. var names []string
  341. maxLen := 0
  342. for name := range facilities {
  343. names = append(names, name)
  344. if len(name) > maxLen {
  345. maxLen = len(name)
  346. }
  347. }
  348. sort.Strings(names)
  349. // Format the choices
  350. b := new(bytes.Buffer)
  351. for _, name := range names {
  352. fmt.Fprintf(b, " %-*s - %s\n", maxLen, name, facilities[name])
  353. }
  354. return b.String()
  355. }
  356. func upgradeViaRest() error {
  357. cfg, err := config.Load(locations[locConfigFile], protocol.LocalDeviceID)
  358. if err != nil {
  359. return err
  360. }
  361. target := cfg.GUI().URL()
  362. r, _ := http.NewRequest("POST", target+"/rest/system/upgrade", nil)
  363. r.Header.Set("X-API-Key", cfg.GUI().APIKey())
  364. tr := &http.Transport{
  365. Dial: dialer.Dial,
  366. Proxy: http.ProxyFromEnvironment,
  367. TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
  368. }
  369. client := &http.Client{
  370. Transport: tr,
  371. Timeout: 60 * time.Second,
  372. }
  373. resp, err := client.Do(r)
  374. if err != nil {
  375. return err
  376. }
  377. if resp.StatusCode != 200 {
  378. bs, err := ioutil.ReadAll(resp.Body)
  379. defer resp.Body.Close()
  380. if err != nil {
  381. return err
  382. }
  383. return errors.New(string(bs))
  384. }
  385. return err
  386. }
  387. func syncthingMain() {
  388. // Create a main service manager. We'll add things to this as we go along.
  389. // We want any logging it does to go through our log system.
  390. mainSvc := suture.New("main", suture.Spec{
  391. Log: func(line string) {
  392. l.Debugln(line)
  393. },
  394. })
  395. mainSvc.ServeBackground()
  396. // Set a log prefix similar to the ID we will have later on, or early log
  397. // lines look ugly.
  398. l.SetPrefix("[start] ")
  399. if auditEnabled {
  400. startAuditing(mainSvc)
  401. }
  402. if verbose {
  403. mainSvc.Add(newVerboseSvc())
  404. }
  405. errors := logger.NewRecorder(l, logger.LevelWarn, maxSystemErrors, 0)
  406. systemLog := logger.NewRecorder(l, logger.LevelDebug, maxSystemLog, initialSystemLog)
  407. // Event subscription for the API; must start early to catch the early events.
  408. apiSub := events.NewBufferedSubscription(events.Default.Subscribe(events.AllEvents), 1000)
  409. if len(os.Getenv("GOMAXPROCS")) == 0 {
  410. runtime.GOMAXPROCS(runtime.NumCPU())
  411. }
  412. // Attempt to increase the limit on number of open files to the maximum
  413. // allowed, in case we have many peers. We don't really care enough to
  414. // report the error if there is one.
  415. osutil.MaximizeOpenFileLimit()
  416. // Ensure that that we have a certificate and key.
  417. cert, err := tls.LoadX509KeyPair(locations[locCertFile], locations[locKeyFile])
  418. if err != nil {
  419. l.Infof("Generating RSA key and certificate for %s...", tlsDefaultCommonName)
  420. cert, err = tlsutil.NewCertificate(locations[locCertFile], locations[locKeyFile], tlsDefaultCommonName, tlsRSABits)
  421. if err != nil {
  422. l.Fatalln(err)
  423. }
  424. }
  425. // We reinitialize the predictable RNG with our device ID, to get a
  426. // sequence that is always the same but unique to this syncthing instance.
  427. predictableRandom.Seed(seedFromBytes(cert.Certificate[0]))
  428. myID = protocol.NewDeviceID(cert.Certificate[0])
  429. l.SetPrefix(fmt.Sprintf("[%s] ", myID.String()[:5]))
  430. l.Infoln(LongVersion)
  431. l.Infoln("My ID:", myID)
  432. printHashRate()
  433. // Emit the Starting event, now that we know who we are.
  434. events.Default.Log(events.Starting, map[string]string{
  435. "home": baseDirs["config"],
  436. "myID": myID.String(),
  437. })
  438. // Prepare to be able to save configuration
  439. cfgFile := locations[locConfigFile]
  440. // Load the configuration file, if it exists.
  441. // If it does not, create a template.
  442. cfg, myName, err := loadConfig(cfgFile)
  443. if err != nil {
  444. if os.IsNotExist(err) {
  445. l.Infoln("No config file; starting with empty defaults")
  446. myName, _ = os.Hostname()
  447. newCfg := defaultConfig(myName)
  448. cfg = config.Wrap(cfgFile, newCfg)
  449. cfg.Save()
  450. l.Infof("Edit %s to taste or use the GUI\n", cfgFile)
  451. } else {
  452. l.Fatalln("Loading config:", err)
  453. }
  454. }
  455. if cfg.Raw().OriginalVersion != config.CurrentVersion {
  456. l.Infoln("Archiving a copy of old config file format")
  457. // Archive a copy
  458. osutil.Rename(cfgFile, cfgFile+fmt.Sprintf(".v%d", cfg.Raw().OriginalVersion))
  459. // Save the new version
  460. cfg.Save()
  461. }
  462. if err := checkShortIDs(cfg); err != nil {
  463. l.Fatalln("Short device IDs are in conflict. Unlucky!\n Regenerate the device ID of one if the following:\n ", err)
  464. }
  465. if len(profiler) > 0 {
  466. go func() {
  467. l.Debugln("Starting profiler on", profiler)
  468. runtime.SetBlockProfileRate(1)
  469. err := http.ListenAndServe(profiler, nil)
  470. if err != nil {
  471. l.Fatalln(err)
  472. }
  473. }()
  474. }
  475. // The TLS configuration is used for both the listening socket and outgoing
  476. // connections.
  477. tlsCfg := &tls.Config{
  478. Certificates: []tls.Certificate{cert},
  479. NextProtos: []string{bepProtocolName},
  480. ClientAuth: tls.RequestClientCert,
  481. SessionTicketsDisabled: true,
  482. InsecureSkipVerify: true,
  483. MinVersion: tls.VersionTLS12,
  484. CipherSuites: []uint16{
  485. tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
  486. tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
  487. tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
  488. tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
  489. tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
  490. tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
  491. },
  492. }
  493. // If the read or write rate should be limited, set up a rate limiter for it.
  494. // This will be used on connections created in the connect and listen routines.
  495. opts := cfg.Options()
  496. if !opts.SymlinksEnabled {
  497. symlinks.Supported = false
  498. }
  499. if (opts.MaxRecvKbps > 0 || opts.MaxSendKbps > 0) && !opts.LimitBandwidthInLan {
  500. lans, _ = osutil.GetLans()
  501. for _, lan := range opts.AlwaysLocalNets {
  502. _, ipnet, err := net.ParseCIDR(lan)
  503. if err != nil {
  504. l.Infoln("Network", lan, "is malformed:", err)
  505. continue
  506. }
  507. lans = append(lans, ipnet)
  508. }
  509. networks := make([]string, len(lans))
  510. for i, lan := range lans {
  511. networks[i] = lan.String()
  512. }
  513. l.Infoln("Local networks:", strings.Join(networks, ", "))
  514. }
  515. dbFile := locations[locDatabase]
  516. ldb, err := db.Open(dbFile)
  517. if err != nil {
  518. l.Fatalln("Cannot open database:", err, "- Is another copy of Syncthing already running?")
  519. }
  520. protectedFiles := []string{
  521. locations[locDatabase], locations[locConfigFile], locations[locCertFile], locations[locKeyFile],
  522. }
  523. // Remove database entries for folders that no longer exist in the config
  524. folders := cfg.Folders()
  525. for _, folder := range ldb.ListFolders() {
  526. if _, ok := folders[folder]; !ok {
  527. l.Infof("Cleaning data for dropped folder %q", folder)
  528. db.DropFolder(ldb, folder)
  529. }
  530. }
  531. m := model.NewModel(cfg, myID, myName, "syncthing", Version, ldb, protectedFiles)
  532. cfg.Subscribe(m)
  533. if t := os.Getenv("STDEADLOCKTIMEOUT"); len(t) > 0 {
  534. it, err := strconv.Atoi(t)
  535. if err == nil {
  536. m.StartDeadlockDetector(time.Duration(it) * time.Second)
  537. }
  538. } else if !IsRelease || IsBeta {
  539. m.StartDeadlockDetector(20 * time.Minute)
  540. }
  541. if paused {
  542. for device := range cfg.Devices() {
  543. m.PauseDevice(device)
  544. }
  545. }
  546. // Clear out old indexes for other devices. Otherwise we'll start up and
  547. // start needing a bunch of files which are nowhere to be found. This
  548. // needs to be changed when we correctly do persistent indexes.
  549. for _, folderCfg := range cfg.Folders() {
  550. m.AddFolder(folderCfg)
  551. for _, device := range folderCfg.DeviceIDs() {
  552. if device == myID {
  553. continue
  554. }
  555. m.Index(device, folderCfg.ID, nil, 0, nil)
  556. }
  557. // Routine to pull blocks from other devices to synchronize the local
  558. // folder. Does not run when we are in read only (publish only) mode.
  559. if folderCfg.ReadOnly {
  560. m.StartFolderRO(folderCfg.ID)
  561. } else {
  562. m.StartFolderRW(folderCfg.ID)
  563. }
  564. }
  565. mainSvc.Add(m)
  566. // The default port we announce, possibly modified by setupUPnP next.
  567. uri, err := url.Parse(opts.ListenAddress[0])
  568. if err != nil {
  569. l.Fatalf("Failed to parse listen address %s: %v", opts.ListenAddress[0], err)
  570. }
  571. addr, err := net.ResolveTCPAddr("tcp", uri.Host)
  572. if err != nil {
  573. l.Fatalln("Bad listen address:", err)
  574. }
  575. // The externalAddr tracks our external addresses for discovery purposes.
  576. var addrList *addressLister
  577. // Start UPnP
  578. if opts.UPnPEnabled {
  579. upnpSvc := newUPnPSvc(cfg, addr.Port)
  580. mainSvc.Add(upnpSvc)
  581. // The external address tracker needs to know about the UPnP service
  582. // so it can check for an external mapped port.
  583. addrList = newAddressLister(upnpSvc, cfg)
  584. } else {
  585. addrList = newAddressLister(nil, cfg)
  586. }
  587. // Start relay management
  588. var relaySvc *relay.Svc
  589. if opts.RelaysEnabled && (opts.GlobalAnnEnabled || opts.RelayWithoutGlobalAnn) {
  590. relaySvc = relay.NewSvc(cfg, tlsCfg)
  591. mainSvc.Add(relaySvc)
  592. }
  593. // Start discovery
  594. cachedDiscovery := discover.NewCachingMux()
  595. mainSvc.Add(cachedDiscovery)
  596. if cfg.Options().GlobalAnnEnabled {
  597. for _, srv := range cfg.GlobalDiscoveryServers() {
  598. l.Infoln("Using discovery server", srv)
  599. gd, err := discover.NewGlobal(srv, cert, addrList, relaySvc)
  600. if err != nil {
  601. l.Warnln("Global discovery:", err)
  602. continue
  603. }
  604. // Each global discovery server gets its results cached for five
  605. // minutes, and is not asked again for a minute when it's returned
  606. // unsuccessfully.
  607. cachedDiscovery.Add(gd, 5*time.Minute, time.Minute, globalDiscoveryPriority)
  608. }
  609. }
  610. if cfg.Options().LocalAnnEnabled {
  611. // v4 broadcasts
  612. bcd, err := discover.NewLocal(myID, fmt.Sprintf(":%d", cfg.Options().LocalAnnPort), addrList, relaySvc)
  613. if err != nil {
  614. l.Warnln("IPv4 local discovery:", err)
  615. } else {
  616. cachedDiscovery.Add(bcd, 0, 0, ipv4LocalDiscoveryPriority)
  617. }
  618. // v6 multicasts
  619. mcd, err := discover.NewLocal(myID, cfg.Options().LocalAnnMCAddr, addrList, relaySvc)
  620. if err != nil {
  621. l.Warnln("IPv6 local discovery:", err)
  622. } else {
  623. cachedDiscovery.Add(mcd, 0, 0, ipv6LocalDiscoveryPriority)
  624. }
  625. }
  626. // GUI
  627. setupGUI(mainSvc, cfg, m, apiSub, cachedDiscovery, relaySvc, errors, systemLog)
  628. // Start connection management
  629. connectionSvc := connections.NewConnectionSvc(cfg, myID, m, tlsCfg, cachedDiscovery, relaySvc, bepProtocolName, tlsDefaultCommonName, lans)
  630. mainSvc.Add(connectionSvc)
  631. if cpuProfile {
  632. f, err := os.Create(fmt.Sprintf("cpu-%d.pprof", os.Getpid()))
  633. if err != nil {
  634. log.Fatal(err)
  635. }
  636. pprof.StartCPUProfile(f)
  637. }
  638. for _, device := range cfg.Devices() {
  639. if len(device.Name) > 0 {
  640. l.Infof("Device %s is %q at %v", device.DeviceID, device.Name, device.Addresses)
  641. }
  642. }
  643. if opts.URAccepted > 0 && opts.URAccepted < usageReportVersion {
  644. l.Infoln("Anonymous usage report has changed; revoking acceptance")
  645. opts.URAccepted = 0
  646. opts.URUniqueID = ""
  647. cfg.SetOptions(opts)
  648. }
  649. if opts.URAccepted >= usageReportVersion {
  650. if opts.URUniqueID == "" {
  651. // Previously the ID was generated from the node ID. We now need
  652. // to generate a new one.
  653. opts.URUniqueID = randomString(8)
  654. cfg.SetOptions(opts)
  655. cfg.Save()
  656. }
  657. }
  658. // The usageReportingManager registers itself to listen to configuration
  659. // changes, and there's nothing more we need to tell it from the outside.
  660. // Hence we don't keep the returned pointer.
  661. newUsageReportingManager(cfg, m)
  662. if opts.RestartOnWakeup {
  663. go standbyMonitor()
  664. }
  665. if opts.AutoUpgradeIntervalH > 0 {
  666. if noUpgrade {
  667. l.Infof("No automatic upgrades; STNOUPGRADE environment variable defined.")
  668. } else if IsRelease {
  669. go autoUpgrade(cfg)
  670. } else {
  671. l.Infof("No automatic upgrades; %s is not a release version.", Version)
  672. }
  673. }
  674. events.Default.Log(events.StartupComplete, map[string]string{
  675. "myID": myID.String(),
  676. })
  677. go generatePingEvents()
  678. cleanConfigDirectory()
  679. code := <-stop
  680. mainSvc.Stop()
  681. l.Okln("Exiting")
  682. if cpuProfile {
  683. pprof.StopCPUProfile()
  684. }
  685. os.Exit(code)
  686. }
  687. // printHashRate prints the hashing performance in MB/s, formatting it with
  688. // appropriate precision for the value, i.e. 182 MB/s, 18 MB/s, 1.8 MB/s, 0.18
  689. // MB/s.
  690. func printHashRate() {
  691. hashRate := cpuBench(3, 100*time.Millisecond)
  692. decimals := 0
  693. if hashRate < 1 {
  694. decimals = 2
  695. } else if hashRate < 10 {
  696. decimals = 1
  697. }
  698. l.Infof("Single thread hash performance is ~%.*f MB/s", decimals, hashRate)
  699. }
  700. func loadConfig(cfgFile string) (*config.Wrapper, string, error) {
  701. info, err := os.Stat(cfgFile)
  702. if err != nil {
  703. return nil, "", err
  704. }
  705. if !info.Mode().IsRegular() {
  706. return nil, "", errors.New("configuration is not a file")
  707. }
  708. cfg, err := config.Load(cfgFile, myID)
  709. if err != nil {
  710. return nil, "", err
  711. }
  712. myCfg := cfg.Devices()[myID]
  713. myName := myCfg.Name
  714. if myName == "" {
  715. myName, _ = os.Hostname()
  716. }
  717. return cfg, myName, nil
  718. }
  719. func startAuditing(mainSvc *suture.Supervisor) {
  720. auditFile := timestampedLoc(locAuditLog)
  721. fd, err := os.OpenFile(auditFile, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0600)
  722. if err != nil {
  723. l.Fatalln("Audit:", err)
  724. }
  725. auditSvc := newAuditSvc(fd)
  726. mainSvc.Add(auditSvc)
  727. // We wait for the audit service to fully start before we return, to
  728. // ensure we capture all events from the start.
  729. auditSvc.WaitForStart()
  730. l.Infoln("Audit log in", auditFile)
  731. }
  732. func setupGUI(mainSvc *suture.Supervisor, cfg *config.Wrapper, m *model.Model, apiSub *events.BufferedSubscription, discoverer *discover.CachingMux, relaySvc *relay.Svc, errors, systemLog *logger.Recorder) {
  733. guiCfg := cfg.GUI()
  734. if !guiCfg.Enabled {
  735. return
  736. }
  737. api, err := newAPISvc(myID, cfg, guiAssets, m, apiSub, discoverer, relaySvc, errors, systemLog)
  738. if err != nil {
  739. l.Fatalln("Cannot start GUI:", err)
  740. }
  741. cfg.Subscribe(api)
  742. mainSvc.Add(api)
  743. if cfg.Options().StartBrowser && !noBrowser && !stRestarting {
  744. // Can potentially block if the utility we are invoking doesn't
  745. // fork, and just execs, hence keep it in it's own routine.
  746. go openURL(guiCfg.URL())
  747. }
  748. }
  749. func defaultConfig(myName string) config.Configuration {
  750. newCfg := config.New(myID)
  751. newCfg.Folders = []config.FolderConfiguration{
  752. {
  753. ID: "default",
  754. RawPath: locations[locDefFolder],
  755. RescanIntervalS: 60,
  756. MinDiskFreePct: 1,
  757. Devices: []config.FolderDeviceConfiguration{{DeviceID: myID}},
  758. AutoNormalize: true,
  759. MaxConflicts: -1,
  760. },
  761. }
  762. newCfg.Devices = []config.DeviceConfiguration{
  763. {
  764. DeviceID: myID,
  765. Addresses: []string{"dynamic"},
  766. Name: myName,
  767. },
  768. }
  769. port, err := getFreePort("127.0.0.1", 8384)
  770. if err != nil {
  771. l.Fatalln("get free port (GUI):", err)
  772. }
  773. newCfg.GUI.RawAddress = fmt.Sprintf("127.0.0.1:%d", port)
  774. port, err = getFreePort("0.0.0.0", 22000)
  775. if err != nil {
  776. l.Fatalln("get free port (BEP):", err)
  777. }
  778. newCfg.Options.ListenAddress = []string{fmt.Sprintf("tcp://0.0.0.0:%d", port)}
  779. return newCfg
  780. }
  781. func generatePingEvents() {
  782. for {
  783. time.Sleep(pingEventInterval)
  784. events.Default.Log(events.Ping, nil)
  785. }
  786. }
  787. func resetDB() error {
  788. return os.RemoveAll(locations[locDatabase])
  789. }
  790. func restart() {
  791. l.Infoln("Restarting")
  792. stop <- exitRestarting
  793. }
  794. func shutdown() {
  795. l.Infoln("Shutting down")
  796. stop <- exitSuccess
  797. }
  798. func ensureDir(dir string, mode int) {
  799. fi, err := os.Stat(dir)
  800. if os.IsNotExist(err) {
  801. err := osutil.MkdirAll(dir, 0700)
  802. if err != nil {
  803. l.Fatalln(err)
  804. }
  805. } else if mode >= 0 && err == nil && int(fi.Mode()&0777) != mode {
  806. err := os.Chmod(dir, os.FileMode(mode))
  807. // This can fail on crappy filesystems, nothing we can do about it.
  808. if err != nil {
  809. l.Warnln(err)
  810. }
  811. }
  812. }
  813. // getFreePort returns a free TCP port fort listening on. The ports given are
  814. // tried in succession and the first to succeed is returned. If none succeed,
  815. // a random high port is returned.
  816. func getFreePort(host string, ports ...int) (int, error) {
  817. for _, port := range ports {
  818. c, err := net.Listen("tcp", fmt.Sprintf("%s:%d", host, port))
  819. if err == nil {
  820. c.Close()
  821. return port, nil
  822. }
  823. }
  824. c, err := net.Listen("tcp", host+":0")
  825. if err != nil {
  826. return 0, err
  827. }
  828. addr := c.Addr().(*net.TCPAddr)
  829. c.Close()
  830. return addr.Port, nil
  831. }
  832. func standbyMonitor() {
  833. restartDelay := time.Duration(60 * time.Second)
  834. now := time.Now()
  835. for {
  836. time.Sleep(10 * time.Second)
  837. if time.Since(now) > 2*time.Minute {
  838. l.Infof("Paused state detected, possibly woke up from standby. Restarting in %v.", restartDelay)
  839. // We most likely just woke from standby. If we restart
  840. // immediately chances are we won't have networking ready. Give
  841. // things a moment to stabilize.
  842. time.Sleep(restartDelay)
  843. restart()
  844. return
  845. }
  846. now = time.Now()
  847. }
  848. }
  849. func autoUpgrade(cfg *config.Wrapper) {
  850. timer := time.NewTimer(0)
  851. sub := events.Default.Subscribe(events.DeviceConnected)
  852. for {
  853. select {
  854. case event := <-sub.C():
  855. data, ok := event.Data.(map[string]string)
  856. if !ok || data["clientName"] != "syncthing" || upgrade.CompareVersions(data["clientVersion"], Version) != upgrade.Newer {
  857. continue
  858. }
  859. l.Infof("Connected to device %s with a newer version (current %q < remote %q). Checking for upgrades.", data["id"], Version, data["clientVersion"])
  860. case <-timer.C:
  861. }
  862. rel, err := upgrade.LatestRelease(cfg.Options().ReleasesURL, Version)
  863. if err == upgrade.ErrUpgradeUnsupported {
  864. events.Default.Unsubscribe(sub)
  865. return
  866. }
  867. if err != nil {
  868. // Don't complain too loudly here; we might simply not have
  869. // internet connectivity, or the upgrade server might be down.
  870. l.Infoln("Automatic upgrade:", err)
  871. timer.Reset(time.Duration(cfg.Options().AutoUpgradeIntervalH) * time.Hour)
  872. continue
  873. }
  874. if upgrade.CompareVersions(rel.Tag, Version) != upgrade.Newer {
  875. // Skip equal, older or majorly newer (incompatible) versions
  876. timer.Reset(time.Duration(cfg.Options().AutoUpgradeIntervalH) * time.Hour)
  877. continue
  878. }
  879. l.Infof("Automatic upgrade (current %q < latest %q)", Version, rel.Tag)
  880. err = upgrade.To(rel)
  881. if err != nil {
  882. l.Warnln("Automatic upgrade:", err)
  883. timer.Reset(time.Duration(cfg.Options().AutoUpgradeIntervalH) * time.Hour)
  884. continue
  885. }
  886. events.Default.Unsubscribe(sub)
  887. l.Warnf("Automatically upgraded to version %q. Restarting in 1 minute.", rel.Tag)
  888. time.Sleep(time.Minute)
  889. stop <- exitUpgrading
  890. return
  891. }
  892. }
  893. // cleanConfigDirectory removes old, unused configuration and index formats, a
  894. // suitable time after they have gone out of fashion.
  895. func cleanConfigDirectory() {
  896. patterns := map[string]time.Duration{
  897. "panic-*.log": 7 * 24 * time.Hour, // keep panic logs for a week
  898. "audit-*.log": 7 * 24 * time.Hour, // keep audit logs for a week
  899. "index": 14 * 24 * time.Hour, // keep old index format for two weeks
  900. "config.xml.v*": 30 * 24 * time.Hour, // old config versions for a month
  901. "*.idx.gz": 30 * 24 * time.Hour, // these should for sure no longer exist
  902. "backup-of-v0.8": 30 * 24 * time.Hour, // these neither
  903. }
  904. for pat, dur := range patterns {
  905. pat = filepath.Join(baseDirs["config"], pat)
  906. files, err := osutil.Glob(pat)
  907. if err != nil {
  908. l.Infoln("Cleaning:", err)
  909. continue
  910. }
  911. for _, file := range files {
  912. info, err := osutil.Lstat(file)
  913. if err != nil {
  914. l.Infoln("Cleaning:", err)
  915. continue
  916. }
  917. if time.Since(info.ModTime()) > dur {
  918. if err = os.RemoveAll(file); err != nil {
  919. l.Infoln("Cleaning:", err)
  920. } else {
  921. l.Infoln("Cleaned away old file", filepath.Base(file))
  922. }
  923. }
  924. }
  925. }
  926. }
  927. // checkShortIDs verifies that the configuration won't result in duplicate
  928. // short ID:s; that is, that the devices in the cluster all have unique
  929. // initial 64 bits.
  930. func checkShortIDs(cfg *config.Wrapper) error {
  931. exists := make(map[uint64]protocol.DeviceID)
  932. for deviceID := range cfg.Devices() {
  933. shortID := deviceID.Short()
  934. if otherID, ok := exists[shortID]; ok {
  935. return fmt.Errorf("%v in conflict with %v", deviceID, otherID)
  936. }
  937. exists[shortID] = deviceID
  938. }
  939. return nil
  940. }