main.go 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097
  1. // Copyright (C) 2014 Jakob Borg and Contributors (see the CONTRIBUTORS file).
  2. // All rights reserved. Use of this source code is governed by an MIT-style
  3. // license that can be found in the LICENSE file.
  4. package main
  5. import (
  6. "crypto/sha1"
  7. "crypto/tls"
  8. "flag"
  9. "fmt"
  10. "io"
  11. "log"
  12. "math/rand"
  13. "net"
  14. "net/http"
  15. _ "net/http/pprof"
  16. "os"
  17. "os/exec"
  18. "path/filepath"
  19. "regexp"
  20. "runtime"
  21. "runtime/debug"
  22. "runtime/pprof"
  23. "strconv"
  24. "strings"
  25. "time"
  26. "github.com/juju/ratelimit"
  27. "github.com/syncthing/syncthing/config"
  28. "github.com/syncthing/syncthing/discover"
  29. "github.com/syncthing/syncthing/events"
  30. "github.com/syncthing/syncthing/logger"
  31. "github.com/syncthing/syncthing/model"
  32. "github.com/syncthing/syncthing/osutil"
  33. "github.com/syncthing/syncthing/protocol"
  34. "github.com/syncthing/syncthing/upgrade"
  35. "github.com/syncthing/syncthing/upnp"
  36. "github.com/syndtr/goleveldb/leveldb"
  37. )
  38. var (
  39. Version = "unknown-dev"
  40. BuildEnv = "default"
  41. BuildStamp = "0"
  42. BuildDate time.Time
  43. BuildHost = "unknown"
  44. BuildUser = "unknown"
  45. LongVersion string
  46. GoArchExtra string // "", "v5", "v6", "v7"
  47. )
  48. var l = logger.DefaultLogger
  49. func init() {
  50. if Version != "unknown-dev" {
  51. // If not a generic dev build, version string should come from git describe
  52. exp := regexp.MustCompile(`^v\d+\.\d+\.\d+(-[a-z0-9]+)*(\+\d+-g[0-9a-f]+)?(-dirty)?$`)
  53. if !exp.MatchString(Version) {
  54. l.Fatalf("Invalid version string %q;\n\tdoes not match regexp %v", Version, exp)
  55. }
  56. }
  57. stamp, _ := strconv.Atoi(BuildStamp)
  58. BuildDate = time.Unix(int64(stamp), 0)
  59. date := BuildDate.UTC().Format("2006-01-02 15:04:05 MST")
  60. LongVersion = fmt.Sprintf("syncthing %s (%s %s-%s %s) %s@%s %s", Version, runtime.Version(), runtime.GOOS, runtime.GOARCH, BuildEnv, BuildUser, BuildHost, date)
  61. if os.Getenv("STTRACE") != "" {
  62. logFlags = log.Ltime | log.Ldate | log.Lmicroseconds | log.Lshortfile
  63. }
  64. }
  65. var (
  66. cfg config.Configuration
  67. myID protocol.NodeID
  68. confDir string
  69. logFlags int = log.Ltime
  70. rateBucket *ratelimit.Bucket
  71. stop = make(chan bool)
  72. discoverer *discover.Discoverer
  73. lockConn *net.TCPListener
  74. lockPort int
  75. externalPort int
  76. cert tls.Certificate
  77. )
  78. const (
  79. usage = "syncthing [options]"
  80. extraUsage = `The value for the -logflags option is a sum of the following:
  81. 1 Date
  82. 2 Time
  83. 4 Microsecond time
  84. 8 Long filename
  85. 16 Short filename
  86. I.e. to prefix each log line with date and time, set -logflags=3 (1 + 2 from
  87. above). The value 0 is used to disable all of the above. The default is to
  88. show time only (2).
  89. The following enviroment variables are interpreted by syncthing:
  90. STNORESTART Do not attempt to restart when requested to, instead just exit.
  91. Set this variable when running under a service manager such as
  92. runit, launchd, etc.
  93. STTRACE A comma separated string of facilities to trace. The valid
  94. facility strings:
  95. - "beacon" (the beacon package)
  96. - "discover" (the discover package)
  97. - "events" (the events package)
  98. - "files" (the files package)
  99. - "net" (the main package; connections & network messages)
  100. - "model" (the model package)
  101. - "scanner" (the scanner package)
  102. - "upnp" (the upnp package)
  103. - "xdr" (the xdr package)
  104. - "all" (all of the above)
  105. STGUIASSETS Directory to load GUI assets from. Overrides compiled in assets.
  106. STPROFILER Set to a listen address such as "127.0.0.1:9090" to start the
  107. profiler with HTTP access.
  108. STCPUPROFILE Write a CPU profile to cpu-$pid.pprof on exit.
  109. STHEAPPROFILE Write heap profiles to heap-$pid-$timestamp.pprof each time
  110. heap usage increases.
  111. STPERFSTATS Write running performance statistics to perf-$pid.csv. Not
  112. supported on Windows.
  113. STDEADLOCKTIMEOUT Alter deadlock detection timeout (seconds; default 1200).`
  114. )
  115. func init() {
  116. rand.Seed(time.Now().UnixNano())
  117. }
  118. func main() {
  119. var reset bool
  120. var showVersion bool
  121. var doUpgrade bool
  122. var doUpgradeCheck bool
  123. var generateDir string
  124. var noBrowser bool
  125. flag.StringVar(&confDir, "home", getDefaultConfDir(), "Set configuration directory")
  126. flag.BoolVar(&reset, "reset", false, "Prepare to resync from cluster")
  127. flag.BoolVar(&showVersion, "version", false, "Show version")
  128. flag.BoolVar(&doUpgrade, "upgrade", false, "Perform upgrade")
  129. flag.BoolVar(&doUpgradeCheck, "upgrade-check", false, "Check for available upgrade")
  130. flag.BoolVar(&noBrowser, "no-browser", false, "Do not start browser")
  131. flag.IntVar(&logFlags, "logflags", logFlags, "Set log flags")
  132. flag.StringVar(&generateDir, "generate", "", "Generate key in specified dir")
  133. flag.Usage = usageFor(flag.CommandLine, usage, extraUsage)
  134. flag.Parse()
  135. if showVersion {
  136. fmt.Println(LongVersion)
  137. return
  138. }
  139. l.SetFlags(logFlags)
  140. if generateDir != "" {
  141. dir := expandTilde(generateDir)
  142. info, err := os.Stat(dir)
  143. l.FatalErr(err)
  144. if !info.IsDir() {
  145. l.Fatalln(dir, "is not a directory")
  146. }
  147. cert, err := loadCert(dir, "")
  148. if err == nil {
  149. l.Warnln("Key exists; will not overwrite.")
  150. l.Infoln("Node ID:", protocol.NewNodeID(cert.Certificate[0]))
  151. return
  152. }
  153. newCertificate(dir, "")
  154. cert, err = loadCert(dir, "")
  155. l.FatalErr(err)
  156. if err == nil {
  157. l.Infoln("Node ID:", protocol.NewNodeID(cert.Certificate[0]))
  158. }
  159. return
  160. }
  161. if doUpgrade || doUpgradeCheck {
  162. rel, err := upgrade.LatestRelease(strings.Contains(Version, "-beta"))
  163. if err != nil {
  164. l.Fatalln("Upgrade:", err) // exits 1
  165. }
  166. if upgrade.CompareVersions(rel.Tag, Version) <= 0 {
  167. l.Infof("No upgrade available (current %q >= latest %q).", Version, rel.Tag)
  168. os.Exit(2)
  169. }
  170. l.Infof("Upgrade available (current %q < latest %q)", Version, rel.Tag)
  171. if doUpgrade {
  172. err = upgrade.UpgradeTo(rel, GoArchExtra)
  173. if err != nil {
  174. l.Fatalln("Upgrade:", err) // exits 1
  175. }
  176. l.Okf("Upgraded to %q", rel.Tag)
  177. return
  178. } else {
  179. return
  180. }
  181. }
  182. var err error
  183. lockPort, err = getLockPort()
  184. if err != nil {
  185. l.Fatalln("Opening lock port:", err)
  186. }
  187. if len(os.Getenv("GOGC")) == 0 {
  188. debug.SetGCPercent(25)
  189. }
  190. if len(os.Getenv("GOMAXPROCS")) == 0 {
  191. runtime.GOMAXPROCS(runtime.NumCPU())
  192. }
  193. confDir = expandTilde(confDir)
  194. events.Default.Log(events.Starting, map[string]string{"home": confDir})
  195. if _, err := os.Stat(confDir); err != nil && confDir == getDefaultConfDir() {
  196. // We are supposed to use the default configuration directory. It
  197. // doesn't exist. In the past our default has been ~/.syncthing, so if
  198. // that directory exists we move it to the new default location and
  199. // continue. We don't much care if this fails at this point, we will
  200. // be checking that later.
  201. var oldDefault string
  202. if runtime.GOOS == "windows" {
  203. oldDefault = filepath.Join(os.Getenv("AppData"), "Syncthing")
  204. } else {
  205. oldDefault = expandTilde("~/.syncthing")
  206. }
  207. if _, err := os.Stat(oldDefault); err == nil {
  208. os.MkdirAll(filepath.Dir(confDir), 0700)
  209. if err := os.Rename(oldDefault, confDir); err == nil {
  210. l.Infoln("Moved config dir", oldDefault, "to", confDir)
  211. }
  212. }
  213. }
  214. // Ensure that our home directory exists and that we have a certificate and key.
  215. ensureDir(confDir, 0700)
  216. cert, err = loadCert(confDir, "")
  217. if err != nil {
  218. newCertificate(confDir, "")
  219. cert, err = loadCert(confDir, "")
  220. l.FatalErr(err)
  221. }
  222. myID = protocol.NewNodeID(cert.Certificate[0])
  223. l.SetPrefix(fmt.Sprintf("[%s] ", myID.String()[:5]))
  224. l.Infoln(LongVersion)
  225. l.Infoln("My ID:", myID)
  226. // Prepare to be able to save configuration
  227. cfgFile := filepath.Join(confDir, "config.xml")
  228. go saveConfigLoop(cfgFile)
  229. var myName string
  230. // Load the configuration file, if it exists.
  231. // If it does not, create a template.
  232. cf, err := os.Open(cfgFile)
  233. if err == nil {
  234. // Read config.xml
  235. cfg, err = config.Load(cf, myID)
  236. if err != nil {
  237. l.Fatalln(err)
  238. }
  239. cf.Close()
  240. myCfg := cfg.GetNodeConfiguration(myID)
  241. if myCfg == nil || myCfg.Name == "" {
  242. myName, _ = os.Hostname()
  243. } else {
  244. myName = myCfg.Name
  245. }
  246. } else {
  247. l.Infoln("No config file; starting with empty defaults")
  248. myName, _ = os.Hostname()
  249. defaultRepo := filepath.Join(getHomeDir(), "Sync")
  250. cfg, err = config.Load(nil, myID)
  251. cfg.Repositories = []config.RepositoryConfiguration{
  252. {
  253. ID: "default",
  254. Directory: defaultRepo,
  255. Nodes: []config.RepositoryNodeConfiguration{{NodeID: myID}},
  256. },
  257. }
  258. cfg.Nodes = []config.NodeConfiguration{
  259. {
  260. NodeID: myID,
  261. Addresses: []string{"dynamic"},
  262. Name: myName,
  263. },
  264. }
  265. port, err := getFreePort("127.0.0.1", 8080)
  266. l.FatalErr(err)
  267. cfg.GUI.Address = fmt.Sprintf("127.0.0.1:%d", port)
  268. port, err = getFreePort("0.0.0.0", 22000)
  269. l.FatalErr(err)
  270. cfg.Options.ListenAddress = []string{fmt.Sprintf("0.0.0.0:%d", port)}
  271. saveConfig()
  272. l.Infof("Edit %s to taste or use the GUI\n", cfgFile)
  273. }
  274. if reset {
  275. resetRepositories()
  276. return
  277. }
  278. if len(os.Getenv("STRESTART")) > 0 {
  279. waitForParentExit()
  280. }
  281. if profiler := os.Getenv("STPROFILER"); len(profiler) > 0 {
  282. go func() {
  283. l.Debugln("Starting profiler on", profiler)
  284. runtime.SetBlockProfileRate(1)
  285. err := http.ListenAndServe(profiler, nil)
  286. if err != nil {
  287. l.Fatalln(err)
  288. }
  289. }()
  290. }
  291. // The TLS configuration is used for both the listening socket and outgoing
  292. // connections.
  293. tlsCfg := &tls.Config{
  294. Certificates: []tls.Certificate{cert},
  295. NextProtos: []string{"bep/1.0"},
  296. ServerName: myID.String(),
  297. ClientAuth: tls.RequestClientCert,
  298. SessionTicketsDisabled: true,
  299. InsecureSkipVerify: true,
  300. MinVersion: tls.VersionTLS12,
  301. }
  302. // If the write rate should be limited, set up a rate limiter for it.
  303. // This will be used on connections created in the connect and listen routines.
  304. if cfg.Options.MaxSendKbps > 0 {
  305. rateBucket = ratelimit.NewBucketWithRate(float64(1000*cfg.Options.MaxSendKbps), int64(5*1000*cfg.Options.MaxSendKbps))
  306. }
  307. // If this is the first time the user runs v0.9, archive the old indexes and config.
  308. archiveLegacyConfig()
  309. db, err := leveldb.OpenFile(filepath.Join(confDir, "index"), nil)
  310. if err != nil {
  311. l.Fatalln("Cannot open database:", err, "- Is another copy of Syncthing already running?")
  312. }
  313. m := model.NewModel(confDir, &cfg, myName, "syncthing", Version, db)
  314. nextRepo:
  315. for i, repo := range cfg.Repositories {
  316. if repo.Invalid != "" {
  317. continue
  318. }
  319. repo.Directory = expandTilde(repo.Directory)
  320. fi, err := os.Stat(repo.Directory)
  321. if m.LocalVersion(repo.ID) > 0 {
  322. // Safety check. If the cached index contains files but the
  323. // repository doesn't exist, we have a problem. We would assume
  324. // that all files have been deleted which might not be the case,
  325. // so mark it as invalid instead.
  326. if err != nil || !fi.IsDir() {
  327. cfg.Repositories[i].Invalid = "repo directory missing"
  328. continue nextRepo
  329. }
  330. } else if os.IsNotExist(err) {
  331. // If we don't have ny files in the index, and the directory does
  332. // exist, try creating it.
  333. err = os.MkdirAll(repo.Directory, 0700)
  334. }
  335. if err != nil {
  336. // If there was another error or we could not create the
  337. // directory, the repository is invalid.
  338. cfg.Repositories[i].Invalid = err.Error()
  339. continue nextRepo
  340. }
  341. m.AddRepo(repo)
  342. }
  343. // GUI
  344. if cfg.GUI.Enabled && cfg.GUI.Address != "" {
  345. addr, err := net.ResolveTCPAddr("tcp", cfg.GUI.Address)
  346. if err != nil {
  347. l.Fatalf("Cannot start GUI on %q: %v", cfg.GUI.Address, err)
  348. } else {
  349. var hostOpen, hostShow string
  350. switch {
  351. case addr.IP == nil:
  352. hostOpen = "localhost"
  353. hostShow = "0.0.0.0"
  354. case addr.IP.IsUnspecified():
  355. hostOpen = "localhost"
  356. hostShow = addr.IP.String()
  357. default:
  358. hostOpen = addr.IP.String()
  359. hostShow = hostOpen
  360. }
  361. var proto = "http"
  362. if cfg.GUI.UseTLS {
  363. proto = "https"
  364. }
  365. l.Infof("Starting web GUI on %s://%s:%d/", proto, hostShow, addr.Port)
  366. err := startGUI(cfg.GUI, os.Getenv("STGUIASSETS"), m)
  367. if err != nil {
  368. l.Fatalln("Cannot start GUI:", err)
  369. }
  370. if !noBrowser && cfg.Options.StartBrowser && len(os.Getenv("STRESTART")) == 0 {
  371. openURL(fmt.Sprintf("%s://%s:%d", proto, hostOpen, addr.Port))
  372. }
  373. }
  374. }
  375. // Clear out old indexes for other nodes. Otherwise we'll start up and
  376. // start needing a bunch of files which are nowhere to be found. This
  377. // needs to be changed when we correctly do persistent indexes.
  378. for _, repoCfg := range cfg.Repositories {
  379. for _, node := range repoCfg.NodeIDs() {
  380. m.Index(node, repoCfg.ID, nil)
  381. }
  382. }
  383. // Walk the repository and update the local model before establishing any
  384. // connections to other nodes.
  385. m.CleanRepos()
  386. l.Infoln("Performing initial repository scan")
  387. m.ScanRepos()
  388. // Remove all .idx* files that don't belong to an active repo.
  389. validIndexes := make(map[string]bool)
  390. for _, repo := range cfg.Repositories {
  391. dir := expandTilde(repo.Directory)
  392. id := fmt.Sprintf("%x", sha1.Sum([]byte(dir)))
  393. validIndexes[id] = true
  394. }
  395. allIndexes, err := filepath.Glob(filepath.Join(confDir, "*.idx*"))
  396. if err == nil {
  397. for _, idx := range allIndexes {
  398. bn := filepath.Base(idx)
  399. fs := strings.Split(bn, ".")
  400. if len(fs) > 1 {
  401. if _, ok := validIndexes[fs[0]]; !ok {
  402. l.Infoln("Removing old index", bn)
  403. os.Remove(idx)
  404. }
  405. }
  406. }
  407. }
  408. // UPnP
  409. if cfg.Options.UPnPEnabled {
  410. setupUPnP()
  411. }
  412. // Routine to connect out to configured nodes
  413. discoverer = discovery(externalPort)
  414. go listenConnect(myID, m, tlsCfg)
  415. for _, repo := range cfg.Repositories {
  416. if repo.Invalid != "" {
  417. continue
  418. }
  419. // Routine to pull blocks from other nodes to synchronize the local
  420. // repository. Does not run when we are in read only (publish only) mode.
  421. if repo.ReadOnly {
  422. l.Okf("Ready to synchronize %s (read only; no external updates accepted)", repo.ID)
  423. m.StartRepoRO(repo.ID)
  424. } else {
  425. l.Okf("Ready to synchronize %s (read-write)", repo.ID)
  426. m.StartRepoRW(repo.ID, cfg.Options.ParallelRequests)
  427. }
  428. }
  429. if cpuprof := os.Getenv("STCPUPROFILE"); len(cpuprof) > 0 {
  430. f, err := os.Create(fmt.Sprintf("cpu-%d.pprof", os.Getpid()))
  431. if err != nil {
  432. log.Fatal(err)
  433. }
  434. pprof.StartCPUProfile(f)
  435. defer pprof.StopCPUProfile()
  436. }
  437. for _, node := range cfg.Nodes {
  438. if len(node.Name) > 0 {
  439. l.Infof("Node %s is %q at %v", node.NodeID, node.Name, node.Addresses)
  440. }
  441. }
  442. if cfg.Options.URAccepted > 0 && cfg.Options.URAccepted < usageReportVersion {
  443. l.Infoln("Anonymous usage report has changed; revoking acceptance")
  444. cfg.Options.URAccepted = 0
  445. }
  446. if cfg.Options.URAccepted >= usageReportVersion {
  447. go usageReportingLoop(m)
  448. go func() {
  449. time.Sleep(10 * time.Minute)
  450. err := sendUsageReport(m)
  451. if err != nil {
  452. l.Infoln("Usage report:", err)
  453. }
  454. }()
  455. }
  456. events.Default.Log(events.StartupComplete, nil)
  457. go generateEvents()
  458. <-stop
  459. l.Okln("Exiting")
  460. }
  461. func generateEvents() {
  462. for {
  463. time.Sleep(300 * time.Second)
  464. events.Default.Log(events.Ping, nil)
  465. }
  466. }
  467. func waitForParentExit() {
  468. l.Infoln("Waiting for parent to exit...")
  469. lockPortStr := os.Getenv("STRESTART")
  470. lockPort, err := strconv.Atoi(lockPortStr)
  471. if err != nil {
  472. l.Warnln("Invalid lock port %q: %v", lockPortStr, err)
  473. }
  474. // Wait for the listen address to become free, indicating that the parent has exited.
  475. for {
  476. ln, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", lockPort))
  477. if err == nil {
  478. ln.Close()
  479. break
  480. }
  481. time.Sleep(250 * time.Millisecond)
  482. }
  483. l.Infoln("Continuing")
  484. }
  485. func setupUPnP() {
  486. if len(cfg.Options.ListenAddress) == 1 {
  487. _, portStr, err := net.SplitHostPort(cfg.Options.ListenAddress[0])
  488. if err != nil {
  489. l.Warnln("Bad listen address:", err)
  490. } else {
  491. // Set up incoming port forwarding, if necessary and possible
  492. port, _ := strconv.Atoi(portStr)
  493. igd, err := upnp.Discover()
  494. if err == nil {
  495. externalPort = setupExternalPort(igd, port)
  496. if externalPort == 0 {
  497. l.Warnln("Failed to create UPnP port mapping")
  498. } else {
  499. l.Infoln("Created UPnP port mapping - external port", externalPort)
  500. }
  501. } else {
  502. l.Infof("No UPnP gateway detected")
  503. if debugNet {
  504. l.Debugf("UPnP: %v", err)
  505. }
  506. }
  507. if cfg.Options.UPnPRenewal > 0 {
  508. go renewUPnP(port)
  509. }
  510. }
  511. } else {
  512. l.Warnln("Multiple listening addresses; not attempting UPnP port mapping")
  513. }
  514. }
  515. func setupExternalPort(igd *upnp.IGD, port int) int {
  516. // We seed the random number generator with the node ID to get a
  517. // repeatable sequence of random external ports.
  518. rnd := rand.NewSource(certSeed(cert.Certificate[0]))
  519. for i := 0; i < 10; i++ {
  520. r := 1024 + int(rnd.Int63()%(65535-1024))
  521. err := igd.AddPortMapping(upnp.TCP, r, port, "syncthing", cfg.Options.UPnPLease*60)
  522. if err == nil {
  523. return r
  524. }
  525. }
  526. return 0
  527. }
  528. func renewUPnP(port int) {
  529. for {
  530. time.Sleep(time.Duration(cfg.Options.UPnPRenewal) * time.Minute)
  531. igd, err := upnp.Discover()
  532. if err != nil {
  533. continue
  534. }
  535. // Just renew the same port that we already have
  536. err = igd.AddPortMapping(upnp.TCP, externalPort, port, "syncthing", cfg.Options.UPnPLease*60)
  537. if err == nil {
  538. l.Infoln("Renewed UPnP port mapping - external port", externalPort)
  539. continue
  540. }
  541. // Something strange has happened. Perhaps the gateway has changed?
  542. // Retry the same port sequence from the beginning.
  543. r := setupExternalPort(igd, port)
  544. if r != 0 {
  545. externalPort = r
  546. l.Infoln("Updated UPnP port mapping - external port", externalPort)
  547. discoverer.StopGlobal()
  548. discoverer.StartGlobal(cfg.Options.GlobalAnnServer, uint16(r))
  549. continue
  550. }
  551. l.Warnln("Failed to update UPnP port mapping - external port", externalPort)
  552. }
  553. }
  554. func resetRepositories() {
  555. suffix := fmt.Sprintf(".syncthing-reset-%d", time.Now().UnixNano())
  556. for _, repo := range cfg.Repositories {
  557. if _, err := os.Stat(repo.Directory); err == nil {
  558. l.Infof("Reset: Moving %s -> %s", repo.Directory, repo.Directory+suffix)
  559. os.Rename(repo.Directory, repo.Directory+suffix)
  560. }
  561. }
  562. idx := filepath.Join(confDir, "index")
  563. os.RemoveAll(idx)
  564. }
  565. func archiveLegacyConfig() {
  566. pat := filepath.Join(confDir, "*.idx.gz*")
  567. idxs, err := filepath.Glob(pat)
  568. if err == nil && len(idxs) > 0 {
  569. // There are legacy indexes. This is probably the first time we run as v0.9.
  570. backupDir := filepath.Join(confDir, "backup-of-v0.8")
  571. err = os.MkdirAll(backupDir, 0700)
  572. if err != nil {
  573. l.Warnln("Cannot archive config/indexes:", err)
  574. return
  575. }
  576. for _, idx := range idxs {
  577. l.Infof("Archiving %s", filepath.Base(idx))
  578. os.Rename(idx, filepath.Join(backupDir, filepath.Base(idx)))
  579. }
  580. src, err := os.Open(filepath.Join(confDir, "config.xml"))
  581. if err != nil {
  582. l.Warnf("Cannot archive config:", err)
  583. return
  584. }
  585. defer src.Close()
  586. dst, err := os.Create(filepath.Join(backupDir, "config.xml"))
  587. if err != nil {
  588. l.Warnf("Cannot archive config:", err)
  589. return
  590. }
  591. defer src.Close()
  592. l.Infoln("Archiving config.xml")
  593. io.Copy(dst, src)
  594. }
  595. }
  596. func restart() {
  597. l.Infoln("Restarting")
  598. if os.Getenv("SMF_FMRI") != "" || os.Getenv("STNORESTART") != "" {
  599. // Solaris SMF
  600. l.Infoln("Service manager detected; exit instead of restart")
  601. stop <- true
  602. return
  603. }
  604. env := os.Environ()
  605. newEnv := make([]string, 0, len(env))
  606. for _, s := range env {
  607. if !strings.HasPrefix(s, "STRESTART=") {
  608. newEnv = append(newEnv, s)
  609. }
  610. }
  611. newEnv = append(newEnv, fmt.Sprintf("STRESTART=%d", lockPort))
  612. pgm, err := exec.LookPath(os.Args[0])
  613. if err != nil {
  614. l.Warnln("Cannot restart:", err)
  615. return
  616. }
  617. proc, err := os.StartProcess(pgm, os.Args, &os.ProcAttr{
  618. Env: newEnv,
  619. Files: []*os.File{os.Stdin, os.Stdout, os.Stderr},
  620. })
  621. if err != nil {
  622. l.Fatalln(err)
  623. }
  624. proc.Release()
  625. stop <- true
  626. }
  627. func shutdown() {
  628. stop <- true
  629. }
  630. var saveConfigCh = make(chan struct{})
  631. func saveConfigLoop(cfgFile string) {
  632. for _ = range saveConfigCh {
  633. fd, err := os.Create(cfgFile + ".tmp")
  634. if err != nil {
  635. l.Warnln("Saving config:", err)
  636. continue
  637. }
  638. err = config.Save(fd, cfg)
  639. if err != nil {
  640. l.Warnln("Saving config:", err)
  641. fd.Close()
  642. continue
  643. }
  644. err = fd.Close()
  645. if err != nil {
  646. l.Warnln("Saving config:", err)
  647. continue
  648. }
  649. err = osutil.Rename(cfgFile+".tmp", cfgFile)
  650. if err != nil {
  651. l.Warnln("Saving config:", err)
  652. }
  653. }
  654. }
  655. func saveConfig() {
  656. saveConfigCh <- struct{}{}
  657. }
  658. func listenConnect(myID protocol.NodeID, m *model.Model, tlsCfg *tls.Config) {
  659. var conns = make(chan *tls.Conn)
  660. // Listen
  661. for _, addr := range cfg.Options.ListenAddress {
  662. go listenTLS(conns, addr, tlsCfg)
  663. }
  664. // Connect
  665. go dialTLS(m, conns, tlsCfg)
  666. next:
  667. for conn := range conns {
  668. certs := conn.ConnectionState().PeerCertificates
  669. if cl := len(certs); cl != 1 {
  670. l.Infof("Got peer certificate list of length %d != 1 from %s; protocol error", cl, conn.RemoteAddr())
  671. conn.Close()
  672. continue
  673. }
  674. remoteCert := certs[0]
  675. remoteID := protocol.NewNodeID(remoteCert.Raw)
  676. if remoteID == myID {
  677. l.Infof("Connected to myself (%s) - should not happen", remoteID)
  678. conn.Close()
  679. continue
  680. }
  681. if m.ConnectedTo(remoteID) {
  682. l.Infof("Connected to already connected node (%s)", remoteID)
  683. conn.Close()
  684. continue
  685. }
  686. for _, nodeCfg := range cfg.Nodes {
  687. if nodeCfg.NodeID == remoteID {
  688. // Verify the name on the certificate. By default we set it to
  689. // "syncthing" when generating, but the user may have replaced
  690. // the certificate and used another name.
  691. certName := nodeCfg.CertName
  692. if certName == "" {
  693. certName = "syncthing"
  694. }
  695. err := remoteCert.VerifyHostname(certName)
  696. if err != nil {
  697. // Incorrect certificate name is something the user most
  698. // likely wants to know about, since it's an advanced
  699. // config. Warn instead of Info.
  700. l.Warnf("Bad certificate from %s (%v): %v", remoteID, conn.RemoteAddr(), err)
  701. conn.Close()
  702. continue next
  703. }
  704. // If rate limiting is set, we wrap the write side of the
  705. // connection in a limiter.
  706. var wr io.Writer = conn
  707. if rateBucket != nil {
  708. wr = &limitedWriter{conn, rateBucket}
  709. }
  710. name := fmt.Sprintf("%s-%s", conn.LocalAddr(), conn.RemoteAddr())
  711. protoConn := protocol.NewConnection(remoteID, conn, wr, m, name, nodeCfg.Compression)
  712. l.Infof("Established secure connection to %s at %s", remoteID, name)
  713. if debugNet {
  714. l.Debugf("cipher suite %04X", conn.ConnectionState().CipherSuite)
  715. }
  716. events.Default.Log(events.NodeConnected, map[string]string{
  717. "id": remoteID.String(),
  718. "addr": conn.RemoteAddr().String(),
  719. })
  720. m.AddConnection(conn, protoConn)
  721. continue next
  722. }
  723. }
  724. events.Default.Log(events.NodeRejected, map[string]string{
  725. "node": remoteID.String(),
  726. "address": conn.RemoteAddr().String(),
  727. })
  728. l.Infof("Connection from %s with unknown node ID %s; ignoring", conn.RemoteAddr(), remoteID)
  729. conn.Close()
  730. }
  731. }
  732. func listenTLS(conns chan *tls.Conn, addr string, tlsCfg *tls.Config) {
  733. if debugNet {
  734. l.Debugln("listening on", addr)
  735. }
  736. tcaddr, err := net.ResolveTCPAddr("tcp", addr)
  737. l.FatalErr(err)
  738. listener, err := net.ListenTCP("tcp", tcaddr)
  739. l.FatalErr(err)
  740. for {
  741. conn, err := listener.Accept()
  742. if err != nil {
  743. l.Warnln("Accepting connection:", err)
  744. continue
  745. }
  746. if debugNet {
  747. l.Debugln("connect from", conn.RemoteAddr())
  748. }
  749. tcpConn := conn.(*net.TCPConn)
  750. setTCPOptions(tcpConn)
  751. tc := tls.Server(conn, tlsCfg)
  752. err = tc.Handshake()
  753. if err != nil {
  754. l.Infoln("TLS handshake:", err)
  755. tc.Close()
  756. continue
  757. }
  758. conns <- tc
  759. }
  760. }
  761. func dialTLS(m *model.Model, conns chan *tls.Conn, tlsCfg *tls.Config) {
  762. var delay time.Duration = 1 * time.Second
  763. for {
  764. nextNode:
  765. for _, nodeCfg := range cfg.Nodes {
  766. if nodeCfg.NodeID == myID {
  767. continue
  768. }
  769. if m.ConnectedTo(nodeCfg.NodeID) {
  770. continue
  771. }
  772. var addrs []string
  773. for _, addr := range nodeCfg.Addresses {
  774. if addr == "dynamic" {
  775. if discoverer != nil {
  776. t := discoverer.Lookup(nodeCfg.NodeID)
  777. if len(t) == 0 {
  778. continue
  779. }
  780. addrs = append(addrs, t...)
  781. }
  782. } else {
  783. addrs = append(addrs, addr)
  784. }
  785. }
  786. for _, addr := range addrs {
  787. host, port, err := net.SplitHostPort(addr)
  788. if err != nil && strings.HasPrefix(err.Error(), "missing port") {
  789. // addr is on the form "1.2.3.4"
  790. addr = net.JoinHostPort(addr, "22000")
  791. } else if err == nil && port == "" {
  792. // addr is on the form "1.2.3.4:"
  793. addr = net.JoinHostPort(host, "22000")
  794. }
  795. if debugNet {
  796. l.Debugln("dial", nodeCfg.NodeID, addr)
  797. }
  798. raddr, err := net.ResolveTCPAddr("tcp", addr)
  799. if err != nil {
  800. if debugNet {
  801. l.Debugln(err)
  802. }
  803. continue
  804. }
  805. conn, err := net.DialTCP("tcp", nil, raddr)
  806. if err != nil {
  807. if debugNet {
  808. l.Debugln(err)
  809. }
  810. continue
  811. }
  812. setTCPOptions(conn)
  813. tc := tls.Client(conn, tlsCfg)
  814. err = tc.Handshake()
  815. if err != nil {
  816. l.Infoln("TLS handshake:", err)
  817. tc.Close()
  818. continue
  819. }
  820. conns <- tc
  821. continue nextNode
  822. }
  823. }
  824. time.Sleep(delay)
  825. delay *= 2
  826. if maxD := time.Duration(cfg.Options.ReconnectIntervalS) * time.Second; delay > maxD {
  827. delay = maxD
  828. }
  829. }
  830. }
  831. func setTCPOptions(conn *net.TCPConn) {
  832. var err error
  833. if err = conn.SetLinger(0); err != nil {
  834. l.Infoln(err)
  835. }
  836. if err = conn.SetNoDelay(false); err != nil {
  837. l.Infoln(err)
  838. }
  839. if err = conn.SetKeepAlivePeriod(60 * time.Second); err != nil {
  840. l.Infoln(err)
  841. }
  842. if err = conn.SetKeepAlive(true); err != nil {
  843. l.Infoln(err)
  844. }
  845. }
  846. func discovery(extPort int) *discover.Discoverer {
  847. disc := discover.NewDiscoverer(myID, cfg.Options.ListenAddress)
  848. if cfg.Options.LocalAnnEnabled {
  849. l.Infoln("Starting local discovery announcements")
  850. disc.StartLocal(cfg.Options.LocalAnnPort, cfg.Options.LocalAnnMCAddr)
  851. }
  852. if cfg.Options.GlobalAnnEnabled {
  853. l.Infoln("Starting global discovery announcements")
  854. disc.StartGlobal(cfg.Options.GlobalAnnServer, uint16(extPort))
  855. }
  856. return disc
  857. }
  858. func ensureDir(dir string, mode int) {
  859. fi, err := os.Stat(dir)
  860. if os.IsNotExist(err) {
  861. err := os.MkdirAll(dir, 0700)
  862. l.FatalErr(err)
  863. } else if mode >= 0 && err == nil && int(fi.Mode()&0777) != mode {
  864. err := os.Chmod(dir, os.FileMode(mode))
  865. l.FatalErr(err)
  866. }
  867. }
  868. func getDefaultConfDir() string {
  869. switch runtime.GOOS {
  870. case "windows":
  871. return filepath.Join(os.Getenv("LocalAppData"), "Syncthing")
  872. case "darwin":
  873. return expandTilde("~/Library/Application Support/Syncthing")
  874. default:
  875. if xdgCfg := os.Getenv("XDG_CONFIG_HOME"); xdgCfg != "" {
  876. return filepath.Join(xdgCfg, "syncthing")
  877. } else {
  878. return expandTilde("~/.config/syncthing")
  879. }
  880. }
  881. }
  882. func expandTilde(p string) string {
  883. if p == "~" {
  884. return getHomeDir()
  885. }
  886. p = filepath.FromSlash(p)
  887. if !strings.HasPrefix(p, fmt.Sprintf("~%c", os.PathSeparator)) {
  888. return p
  889. }
  890. return filepath.Join(getHomeDir(), p[2:])
  891. }
  892. func getHomeDir() string {
  893. var home string
  894. switch runtime.GOOS {
  895. case "windows":
  896. home = filepath.Join(os.Getenv("HomeDrive"), os.Getenv("HomePath"))
  897. if home == "" {
  898. home = os.Getenv("UserProfile")
  899. }
  900. default:
  901. home = os.Getenv("HOME")
  902. }
  903. if home == "" {
  904. l.Fatalln("No home directory found - set $HOME (or the platform equivalent).")
  905. }
  906. return home
  907. }
  908. // getFreePort returns a free TCP port fort listening on. The ports given are
  909. // tried in succession and the first to succeed is returned. If none succeed,
  910. // a random high port is returned.
  911. func getFreePort(host string, ports ...int) (int, error) {
  912. for _, port := range ports {
  913. c, err := net.Listen("tcp", fmt.Sprintf("%s:%d", host, port))
  914. if err == nil {
  915. c.Close()
  916. return port, nil
  917. }
  918. }
  919. c, err := net.Listen("tcp", host+":0")
  920. if err != nil {
  921. return 0, err
  922. }
  923. addr := c.Addr().(*net.TCPAddr)
  924. c.Close()
  925. return addr.Port, nil
  926. }
  927. func getLockPort() (int, error) {
  928. var err error
  929. lockConn, err = net.ListenTCP("tcp", &net.TCPAddr{IP: net.IP{127, 0, 0, 1}})
  930. if err != nil {
  931. return 0, err
  932. }
  933. addr := lockConn.Addr().(*net.TCPAddr)
  934. return addr.Port, nil
  935. }