main.go 33 KB

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