main.go 32 KB

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