main.go 33 KB

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