mirror of
https://github.com/octoleo/syncthing.git
synced 2025-02-14 01:30:20 +00:00
Merge pull request #2333 from calmh/brokenupgrade
Remove global cfg variable (fixes #2294)
This commit is contained in:
commit
6f6c1cd330
@ -55,7 +55,7 @@ var (
|
|||||||
|
|
||||||
type apiSvc struct {
|
type apiSvc struct {
|
||||||
id protocol.DeviceID
|
id protocol.DeviceID
|
||||||
cfg config.GUIConfiguration
|
cfg *config.Wrapper
|
||||||
assetDir string
|
assetDir string
|
||||||
model *model.Model
|
model *model.Model
|
||||||
eventSub *events.BufferedSubscription
|
eventSub *events.BufferedSubscription
|
||||||
@ -67,7 +67,7 @@ type apiSvc struct {
|
|||||||
systemConfigMut sync.Mutex
|
systemConfigMut sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAPISvc(id protocol.DeviceID, cfg config.GUIConfiguration, assetDir string, m *model.Model, eventSub *events.BufferedSubscription, discoverer *discover.CachingMux, relaySvc *relay.Svc) (*apiSvc, error) {
|
func newAPISvc(id protocol.DeviceID, cfg *config.Wrapper, assetDir string, m *model.Model, eventSub *events.BufferedSubscription, discoverer *discover.CachingMux, relaySvc *relay.Svc) (*apiSvc, error) {
|
||||||
svc := &apiSvc{
|
svc := &apiSvc{
|
||||||
id: id,
|
id: id,
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
@ -80,7 +80,7 @@ func newAPISvc(id protocol.DeviceID, cfg config.GUIConfiguration, assetDir strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
svc.listener, err = svc.getListener(cfg)
|
svc.listener, err = svc.getListener(cfg.GUI())
|
||||||
return svc, err
|
return svc, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,20 +195,22 @@ func (s *apiSvc) Serve() {
|
|||||||
assets: auto.Assets(),
|
assets: auto.Assets(),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
guiCfg := s.cfg.GUI()
|
||||||
|
|
||||||
// Wrap everything in CSRF protection. The /rest prefix should be
|
// Wrap everything in CSRF protection. The /rest prefix should be
|
||||||
// protected, other requests will grant cookies.
|
// protected, other requests will grant cookies.
|
||||||
handler := csrfMiddleware(s.id.String()[:5], "/rest", s.cfg.APIKey, mux)
|
handler := csrfMiddleware(s.id.String()[:5], "/rest", guiCfg.APIKey, mux)
|
||||||
|
|
||||||
// Add our version and ID as a header to responses
|
// Add our version and ID as a header to responses
|
||||||
handler = withDetailsMiddleware(s.id, handler)
|
handler = withDetailsMiddleware(s.id, handler)
|
||||||
|
|
||||||
// Wrap everything in basic auth, if user/password is set.
|
// Wrap everything in basic auth, if user/password is set.
|
||||||
if len(s.cfg.User) > 0 && len(s.cfg.Password) > 0 {
|
if len(guiCfg.User) > 0 && len(guiCfg.Password) > 0 {
|
||||||
handler = basicAuthAndSessionMiddleware("sessionid-"+s.id.String()[:5], s.cfg, handler)
|
handler = basicAuthAndSessionMiddleware("sessionid-"+s.id.String()[:5], guiCfg, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Redirect to HTTPS if we are supposed to
|
// Redirect to HTTPS if we are supposed to
|
||||||
if s.cfg.UseTLS {
|
if guiCfg.UseTLS {
|
||||||
handler = redirectToHTTPSMiddleware(handler)
|
handler = redirectToHTTPSMiddleware(handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,7 +223,7 @@ func (s *apiSvc) Serve() {
|
|||||||
ReadTimeout: 10 * time.Second,
|
ReadTimeout: 10 * time.Second,
|
||||||
}
|
}
|
||||||
|
|
||||||
s.fss = newFolderSummarySvc(s.model)
|
s.fss = newFolderSummarySvc(s.cfg, s.model)
|
||||||
defer s.fss.Stop()
|
defer s.fss.Stop()
|
||||||
s.fss.ServeBackground()
|
s.fss.ServeBackground()
|
||||||
|
|
||||||
@ -273,7 +275,6 @@ func (s *apiSvc) CommitConfiguration(from, to config.Configuration) bool {
|
|||||||
// method.
|
// method.
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
s.cfg = to.GUI
|
|
||||||
|
|
||||||
close(s.stop)
|
close(s.stop)
|
||||||
|
|
||||||
@ -409,12 +410,12 @@ func (s *apiSvc) getDBCompletion(w http.ResponseWriter, r *http.Request) {
|
|||||||
func (s *apiSvc) getDBStatus(w http.ResponseWriter, r *http.Request) {
|
func (s *apiSvc) getDBStatus(w http.ResponseWriter, r *http.Request) {
|
||||||
qs := r.URL.Query()
|
qs := r.URL.Query()
|
||||||
folder := qs.Get("folder")
|
folder := qs.Get("folder")
|
||||||
res := folderSummary(s.model, folder)
|
res := folderSummary(s.cfg, s.model, folder)
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
json.NewEncoder(w).Encode(res)
|
json.NewEncoder(w).Encode(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
func folderSummary(m *model.Model, folder string) map[string]interface{} {
|
func folderSummary(cfg *config.Wrapper, m *model.Model, folder string) map[string]interface{} {
|
||||||
var res = make(map[string]interface{})
|
var res = make(map[string]interface{})
|
||||||
|
|
||||||
res["invalid"] = cfg.Folders()[folder].Invalid
|
res["invalid"] = cfg.Folders()[folder].Invalid
|
||||||
@ -524,7 +525,7 @@ func (s *apiSvc) getDBFile(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
func (s *apiSvc) getSystemConfig(w http.ResponseWriter, r *http.Request) {
|
func (s *apiSvc) getSystemConfig(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
json.NewEncoder(w).Encode(cfg.Raw())
|
json.NewEncoder(w).Encode(s.cfg.Raw())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) postSystemConfig(w http.ResponseWriter, r *http.Request) {
|
func (s *apiSvc) postSystemConfig(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -539,7 +540,7 @@ func (s *apiSvc) postSystemConfig(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if to.GUI.Password != cfg.GUI().Password {
|
if to.GUI.Password != s.cfg.GUI().Password {
|
||||||
if to.GUI.Password != "" {
|
if to.GUI.Password != "" {
|
||||||
hash, err := bcrypt.GenerateFromPassword([]byte(to.GUI.Password), 0)
|
hash, err := bcrypt.GenerateFromPassword([]byte(to.GUI.Password), 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -554,7 +555,7 @@ func (s *apiSvc) postSystemConfig(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
// Fixup usage reporting settings
|
// Fixup usage reporting settings
|
||||||
|
|
||||||
if curAcc := cfg.Options().URAccepted; to.Options.URAccepted > curAcc {
|
if curAcc := s.cfg.Options().URAccepted; to.Options.URAccepted > curAcc {
|
||||||
// UR was enabled
|
// UR was enabled
|
||||||
to.Options.URAccepted = usageReportVersion
|
to.Options.URAccepted = usageReportVersion
|
||||||
to.Options.URUniqueID = randomString(8)
|
to.Options.URUniqueID = randomString(8)
|
||||||
@ -566,9 +567,9 @@ func (s *apiSvc) postSystemConfig(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
// Activate and save
|
// Activate and save
|
||||||
|
|
||||||
resp := cfg.Replace(to)
|
resp := s.cfg.Replace(to)
|
||||||
configInSync = !resp.RequiresRestart
|
configInSync = !resp.RequiresRestart
|
||||||
cfg.Save()
|
s.cfg.Save()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getSystemConfigInsync(w http.ResponseWriter, r *http.Request) {
|
func (s *apiSvc) getSystemConfigInsync(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -586,7 +587,7 @@ func (s *apiSvc) postSystemReset(w http.ResponseWriter, r *http.Request) {
|
|||||||
folder := qs.Get("folder")
|
folder := qs.Get("folder")
|
||||||
|
|
||||||
if len(folder) > 0 {
|
if len(folder) > 0 {
|
||||||
if _, ok := cfg.Folders()[folder]; !ok {
|
if _, ok := s.cfg.Folders()[folder]; !ok {
|
||||||
http.Error(w, "Invalid folder ID", 500)
|
http.Error(w, "Invalid folder ID", 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -594,7 +595,7 @@ func (s *apiSvc) postSystemReset(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
if len(folder) == 0 {
|
if len(folder) == 0 {
|
||||||
// Reset all folders.
|
// Reset all folders.
|
||||||
for folder := range cfg.Folders() {
|
for folder := range s.cfg.Folders() {
|
||||||
s.model.ResetFolder(folder)
|
s.model.ResetFolder(folder)
|
||||||
}
|
}
|
||||||
s.flushResponse(`{"ok": "resetting database"}`, w)
|
s.flushResponse(`{"ok": "resetting database"}`, w)
|
||||||
@ -632,7 +633,7 @@ func (s *apiSvc) getSystemStatus(w http.ResponseWriter, r *http.Request) {
|
|||||||
res["alloc"] = m.Alloc
|
res["alloc"] = m.Alloc
|
||||||
res["sys"] = m.Sys - m.HeapReleased
|
res["sys"] = m.Sys - m.HeapReleased
|
||||||
res["tilde"] = tilde
|
res["tilde"] = tilde
|
||||||
if cfg.Options().LocalAnnEnabled || cfg.Options().GlobalAnnEnabled {
|
if s.cfg.Options().LocalAnnEnabled || s.cfg.Options().GlobalAnnEnabled {
|
||||||
res["discoveryEnabled"] = true
|
res["discoveryEnabled"] = true
|
||||||
discoErrors := make(map[string]string)
|
discoErrors := make(map[string]string)
|
||||||
discoMethods := 0
|
discoMethods := 0
|
||||||
@ -718,7 +719,7 @@ func (s *apiSvc) getSystemDiscovery(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
func (s *apiSvc) getReport(w http.ResponseWriter, r *http.Request) {
|
func (s *apiSvc) getReport(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
json.NewEncoder(w).Encode(reportData(s.model))
|
json.NewEncoder(w).Encode(reportData(s.cfg, s.model))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getDBIgnores(w http.ResponseWriter, r *http.Request) {
|
func (s *apiSvc) getDBIgnores(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -787,7 +788,7 @@ func (s *apiSvc) getSystemUpgrade(w http.ResponseWriter, r *http.Request) {
|
|||||||
http.Error(w, upgrade.ErrUpgradeUnsupported.Error(), 500)
|
http.Error(w, upgrade.ErrUpgradeUnsupported.Error(), 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
rel, err := upgrade.LatestRelease(cfg.Options().ReleasesURL, Version)
|
rel, err := upgrade.LatestRelease(s.cfg.Options().ReleasesURL, Version)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, err.Error(), 500)
|
http.Error(w, err.Error(), 500)
|
||||||
return
|
return
|
||||||
@ -830,7 +831,7 @@ func (s *apiSvc) getLang(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) postSystemUpgrade(w http.ResponseWriter, r *http.Request) {
|
func (s *apiSvc) postSystemUpgrade(w http.ResponseWriter, r *http.Request) {
|
||||||
rel, err := upgrade.LatestRelease(cfg.Options().ReleasesURL, Version)
|
rel, err := upgrade.LatestRelease(s.cfg.Options().ReleasesURL, Version)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Warnln("getting latest release:", err)
|
l.Warnln("getting latest release:", err)
|
||||||
http.Error(w, err.Error(), 500)
|
http.Error(w, err.Error(), 500)
|
||||||
@ -928,7 +929,7 @@ func (s *apiSvc) getPeerCompletion(w http.ResponseWriter, r *http.Request) {
|
|||||||
tot := map[string]float64{}
|
tot := map[string]float64{}
|
||||||
count := map[string]float64{}
|
count := map[string]float64{}
|
||||||
|
|
||||||
for _, folder := range cfg.Folders() {
|
for _, folder := range s.cfg.Folders() {
|
||||||
for _, device := range folder.DeviceIDs() {
|
for _, device := range folder.DeviceIDs() {
|
||||||
deviceStr := device.String()
|
deviceStr := device.String()
|
||||||
if s.model.ConnectedTo(device) {
|
if s.model.ConnectedTo(device) {
|
||||||
|
@ -26,7 +26,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/calmh/logger"
|
"github.com/calmh/logger"
|
||||||
"github.com/juju/ratelimit"
|
|
||||||
"github.com/syncthing/syncthing/lib/config"
|
"github.com/syncthing/syncthing/lib/config"
|
||||||
"github.com/syncthing/syncthing/lib/connections"
|
"github.com/syncthing/syncthing/lib/connections"
|
||||||
"github.com/syncthing/syncthing/lib/db"
|
"github.com/syncthing/syncthing/lib/db"
|
||||||
@ -108,12 +107,9 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
cfg *config.Wrapper
|
|
||||||
myID protocol.DeviceID
|
myID protocol.DeviceID
|
||||||
confDir string
|
confDir string
|
||||||
logFlags = log.Ltime
|
logFlags = log.Ltime
|
||||||
writeRateLimit *ratelimit.Bucket
|
|
||||||
readRateLimit *ratelimit.Bucket
|
|
||||||
stop = make(chan int)
|
stop = make(chan int)
|
||||||
cert tls.Certificate
|
cert tls.Certificate
|
||||||
lans []*net.IPNet
|
lans []*net.IPNet
|
||||||
@ -346,7 +342,11 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if doUpgrade || doUpgradeCheck {
|
if doUpgrade || doUpgradeCheck {
|
||||||
rel, err := upgrade.LatestRelease(cfg.Options().ReleasesURL, Version)
|
releasesURL := "https://api.github.com/repos/syncthing/syncthing/releases?per_page=30"
|
||||||
|
if cfg, _, err := loadConfig(locations[locConfigFile]); err == nil {
|
||||||
|
releasesURL = cfg.Options().ReleasesURL
|
||||||
|
}
|
||||||
|
rel, err := upgrade.LatestRelease(releasesURL, Version)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Fatalln("Upgrade:", err) // exits 1
|
l.Fatalln("Upgrade:", err) // exits 1
|
||||||
}
|
}
|
||||||
@ -497,33 +497,21 @@ func syncthingMain() {
|
|||||||
|
|
||||||
cfgFile := locations[locConfigFile]
|
cfgFile := locations[locConfigFile]
|
||||||
|
|
||||||
var myName string
|
|
||||||
|
|
||||||
// Load the configuration file, if it exists.
|
// Load the configuration file, if it exists.
|
||||||
// If it does not, create a template.
|
// If it does not, create a template.
|
||||||
|
|
||||||
if info, err := os.Stat(cfgFile); err == nil {
|
cfg, myName, err := loadConfig(cfgFile)
|
||||||
if !info.Mode().IsRegular() {
|
if err != nil {
|
||||||
l.Fatalln("Config file is not a file?")
|
if os.IsNotExist(err) {
|
||||||
}
|
|
||||||
cfg, err = config.Load(cfgFile, myID)
|
|
||||||
if err == nil {
|
|
||||||
myCfg := cfg.Devices()[myID]
|
|
||||||
if myCfg.Name == "" {
|
|
||||||
myName, _ = os.Hostname()
|
|
||||||
} else {
|
|
||||||
myName = myCfg.Name
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
l.Fatalln("Configuration:", err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
l.Infoln("No config file; starting with empty defaults")
|
l.Infoln("No config file; starting with empty defaults")
|
||||||
myName, _ = os.Hostname()
|
myName, _ = os.Hostname()
|
||||||
newCfg := defaultConfig(myName)
|
newCfg := defaultConfig(myName)
|
||||||
cfg = config.Wrap(cfgFile, newCfg)
|
cfg = config.Wrap(cfgFile, newCfg)
|
||||||
cfg.Save()
|
cfg.Save()
|
||||||
l.Infof("Edit %s to taste or use the GUI\n", cfgFile)
|
l.Infof("Edit %s to taste or use the GUI\n", cfgFile)
|
||||||
|
} else {
|
||||||
|
l.Fatalln("Loading config:", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg.Raw().OriginalVersion != config.CurrentVersion {
|
if cfg.Raw().OriginalVersion != config.CurrentVersion {
|
||||||
@ -596,9 +584,10 @@ func syncthingMain() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dbFile := locations[locDatabase]
|
dbFile := locations[locDatabase]
|
||||||
ldb, err := leveldb.OpenFile(dbFile, dbOpts())
|
dbOpts := dbOpts(cfg)
|
||||||
|
ldb, err := leveldb.OpenFile(dbFile, dbOpts)
|
||||||
if leveldbIsCorrupted(err) {
|
if leveldbIsCorrupted(err) {
|
||||||
ldb, err = leveldb.RecoverFile(dbFile, dbOpts())
|
ldb, err = leveldb.RecoverFile(dbFile, dbOpts)
|
||||||
}
|
}
|
||||||
if leveldbIsCorrupted(err) {
|
if leveldbIsCorrupted(err) {
|
||||||
// The database is corrupted, and we've tried to recover it but it
|
// The database is corrupted, and we've tried to recover it but it
|
||||||
@ -608,7 +597,7 @@ func syncthingMain() {
|
|||||||
if err := resetDB(); err != nil {
|
if err := resetDB(); err != nil {
|
||||||
l.Fatalln("Remove database:", err)
|
l.Fatalln("Remove database:", err)
|
||||||
}
|
}
|
||||||
ldb, err = leveldb.OpenFile(dbFile, dbOpts())
|
ldb, err = leveldb.OpenFile(dbFile, dbOpts)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Fatalln("Cannot open database:", err, "- Is another copy of Syncthing already running?")
|
l.Fatalln("Cannot open database:", err, "- Is another copy of Syncthing already running?")
|
||||||
@ -780,7 +769,7 @@ func syncthingMain() {
|
|||||||
// The usageReportingManager registers itself to listen to configuration
|
// The usageReportingManager registers itself to listen to configuration
|
||||||
// changes, and there's nothing more we need to tell it from the outside.
|
// changes, and there's nothing more we need to tell it from the outside.
|
||||||
// Hence we don't keep the returned pointer.
|
// Hence we don't keep the returned pointer.
|
||||||
newUsageReportingManager(m, cfg)
|
newUsageReportingManager(cfg, m)
|
||||||
|
|
||||||
if opts.RestartOnWakeup {
|
if opts.RestartOnWakeup {
|
||||||
go standbyMonitor()
|
go standbyMonitor()
|
||||||
@ -790,7 +779,7 @@ func syncthingMain() {
|
|||||||
if noUpgrade {
|
if noUpgrade {
|
||||||
l.Infof("No automatic upgrades; STNOUPGRADE environment variable defined.")
|
l.Infof("No automatic upgrades; STNOUPGRADE environment variable defined.")
|
||||||
} else if IsRelease {
|
} else if IsRelease {
|
||||||
go autoUpgrade()
|
go autoUpgrade(cfg)
|
||||||
} else {
|
} else {
|
||||||
l.Infof("No automatic upgrades; %s is not a release version.", Version)
|
l.Infof("No automatic upgrades; %s is not a release version.", Version)
|
||||||
}
|
}
|
||||||
@ -816,7 +805,30 @@ func syncthingMain() {
|
|||||||
os.Exit(code)
|
os.Exit(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
func dbOpts() *opt.Options {
|
func loadConfig(cfgFile string) (*config.Wrapper, string, error) {
|
||||||
|
info, err := os.Stat(cfgFile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
if !info.Mode().IsRegular() {
|
||||||
|
return nil, "", errors.New("configuration is not a file")
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg, err := config.Load(cfgFile, myID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
myCfg := cfg.Devices()[myID]
|
||||||
|
myName := myCfg.Name
|
||||||
|
if myName == "" {
|
||||||
|
myName, _ = os.Hostname()
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfg, myName, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func dbOpts(cfg *config.Wrapper) *opt.Options {
|
||||||
// Calculate a suitable database block cache capacity.
|
// Calculate a suitable database block cache capacity.
|
||||||
|
|
||||||
// Default is 8 MiB.
|
// Default is 8 MiB.
|
||||||
@ -896,7 +908,7 @@ func setupGUI(mainSvc *suture.Supervisor, cfg *config.Wrapper, m *model.Model, a
|
|||||||
|
|
||||||
urlShow := fmt.Sprintf("%s://%s/", proto, net.JoinHostPort(hostShow, strconv.Itoa(addr.Port)))
|
urlShow := fmt.Sprintf("%s://%s/", proto, net.JoinHostPort(hostShow, strconv.Itoa(addr.Port)))
|
||||||
l.Infoln("Starting web GUI on", urlShow)
|
l.Infoln("Starting web GUI on", urlShow)
|
||||||
api, err := newAPISvc(myID, guiCfg, guiAssets, m, apiSub, discoverer, relaySvc)
|
api, err := newAPISvc(myID, cfg, guiAssets, m, apiSub, discoverer, relaySvc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Fatalln("Cannot start GUI:", err)
|
l.Fatalln("Cannot start GUI:", err)
|
||||||
}
|
}
|
||||||
@ -1066,7 +1078,7 @@ func standbyMonitor() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func autoUpgrade() {
|
func autoUpgrade(cfg *config.Wrapper) {
|
||||||
timer := time.NewTimer(0)
|
timer := time.NewTimer(0)
|
||||||
sub := events.Default.Subscribe(events.DeviceConnected)
|
sub := events.Default.Subscribe(events.DeviceConnected)
|
||||||
for {
|
for {
|
||||||
|
@ -9,6 +9,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/syncthing/syncthing/lib/config"
|
||||||
"github.com/syncthing/syncthing/lib/events"
|
"github.com/syncthing/syncthing/lib/events"
|
||||||
"github.com/syncthing/syncthing/lib/model"
|
"github.com/syncthing/syncthing/lib/model"
|
||||||
"github.com/syncthing/syncthing/lib/sync"
|
"github.com/syncthing/syncthing/lib/sync"
|
||||||
@ -20,6 +21,7 @@ import (
|
|||||||
type folderSummarySvc struct {
|
type folderSummarySvc struct {
|
||||||
*suture.Supervisor
|
*suture.Supervisor
|
||||||
|
|
||||||
|
cfg *config.Wrapper
|
||||||
model *model.Model
|
model *model.Model
|
||||||
stop chan struct{}
|
stop chan struct{}
|
||||||
immediate chan string
|
immediate chan string
|
||||||
@ -33,9 +35,10 @@ type folderSummarySvc struct {
|
|||||||
lastEventReqMut sync.Mutex
|
lastEventReqMut sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func newFolderSummarySvc(m *model.Model) *folderSummarySvc {
|
func newFolderSummarySvc(cfg *config.Wrapper, m *model.Model) *folderSummarySvc {
|
||||||
svc := &folderSummarySvc{
|
svc := &folderSummarySvc{
|
||||||
Supervisor: suture.NewSimple("folderSummarySvc"),
|
Supervisor: suture.NewSimple("folderSummarySvc"),
|
||||||
|
cfg: cfg,
|
||||||
model: m,
|
model: m,
|
||||||
stop: make(chan struct{}),
|
stop: make(chan struct{}),
|
||||||
immediate: make(chan string),
|
immediate: make(chan string),
|
||||||
@ -162,13 +165,13 @@ func (c *folderSummarySvc) foldersToHandle() []string {
|
|||||||
func (c *folderSummarySvc) sendSummary(folder string) {
|
func (c *folderSummarySvc) sendSummary(folder string) {
|
||||||
// The folder summary contains how many bytes, files etc
|
// The folder summary contains how many bytes, files etc
|
||||||
// are in the folder and how in sync we are.
|
// are in the folder and how in sync we are.
|
||||||
data := folderSummary(c.model, folder)
|
data := folderSummary(c.cfg, c.model, folder)
|
||||||
events.Default.Log(events.FolderSummary, map[string]interface{}{
|
events.Default.Log(events.FolderSummary, map[string]interface{}{
|
||||||
"folder": folder,
|
"folder": folder,
|
||||||
"summary": data,
|
"summary": data,
|
||||||
})
|
})
|
||||||
|
|
||||||
for _, devCfg := range cfg.Folders()[folder].Devices {
|
for _, devCfg := range c.cfg.Folders()[folder].Devices {
|
||||||
if devCfg.DeviceID.Equals(myID) {
|
if devCfg.DeviceID.Equals(myID) {
|
||||||
// We already know about ourselves.
|
// We already know about ourselves.
|
||||||
continue
|
continue
|
||||||
|
@ -32,12 +32,14 @@ import (
|
|||||||
const usageReportVersion = 2
|
const usageReportVersion = 2
|
||||||
|
|
||||||
type usageReportingManager struct {
|
type usageReportingManager struct {
|
||||||
|
cfg *config.Wrapper
|
||||||
model *model.Model
|
model *model.Model
|
||||||
sup *suture.Supervisor
|
sup *suture.Supervisor
|
||||||
}
|
}
|
||||||
|
|
||||||
func newUsageReportingManager(m *model.Model, cfg *config.Wrapper) *usageReportingManager {
|
func newUsageReportingManager(cfg *config.Wrapper, m *model.Model) *usageReportingManager {
|
||||||
mgr := &usageReportingManager{
|
mgr := &usageReportingManager{
|
||||||
|
cfg: cfg,
|
||||||
model: m,
|
model: m,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,9 +60,7 @@ func (m *usageReportingManager) VerifyConfiguration(from, to config.Configuratio
|
|||||||
func (m *usageReportingManager) CommitConfiguration(from, to config.Configuration) bool {
|
func (m *usageReportingManager) CommitConfiguration(from, to config.Configuration) bool {
|
||||||
if to.Options.URAccepted >= usageReportVersion && m.sup == nil {
|
if to.Options.URAccepted >= usageReportVersion && m.sup == nil {
|
||||||
// Usage reporting was turned on; lets start it.
|
// Usage reporting was turned on; lets start it.
|
||||||
svc := &usageReportingService{
|
svc := newUsageReportingService(m.cfg, m.model)
|
||||||
model: m.model,
|
|
||||||
}
|
|
||||||
m.sup = suture.NewSimple("usageReporting")
|
m.sup = suture.NewSimple("usageReporting")
|
||||||
m.sup.Add(svc)
|
m.sup.Add(svc)
|
||||||
m.sup.ServeBackground()
|
m.sup.ServeBackground()
|
||||||
@ -79,7 +79,7 @@ func (m *usageReportingManager) String() string {
|
|||||||
|
|
||||||
// reportData returns the data to be sent in a usage report. It's used in
|
// reportData returns the data to be sent in a usage report. It's used in
|
||||||
// various places, so not part of the usageReportingSvc object.
|
// various places, so not part of the usageReportingSvc object.
|
||||||
func reportData(m *model.Model) map[string]interface{} {
|
func reportData(cfg *config.Wrapper, m *model.Model) map[string]interface{} {
|
||||||
res := make(map[string]interface{})
|
res := make(map[string]interface{})
|
||||||
res["urVersion"] = usageReportVersion
|
res["urVersion"] = usageReportVersion
|
||||||
res["uniqueID"] = cfg.Options().URUniqueID
|
res["uniqueID"] = cfg.Options().URUniqueID
|
||||||
@ -238,12 +238,21 @@ func stringIn(needle string, haystack []string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type usageReportingService struct {
|
type usageReportingService struct {
|
||||||
|
cfg *config.Wrapper
|
||||||
model *model.Model
|
model *model.Model
|
||||||
stop chan struct{}
|
stop chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newUsageReportingService(cfg *config.Wrapper, model *model.Model) *usageReportingService {
|
||||||
|
return &usageReportingService{
|
||||||
|
cfg: cfg,
|
||||||
|
model: model,
|
||||||
|
stop: make(chan struct{}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *usageReportingService) sendUsageReport() error {
|
func (s *usageReportingService) sendUsageReport() error {
|
||||||
d := reportData(s.model)
|
d := reportData(s.cfg, s.model)
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
json.NewEncoder(&b).Encode(d)
|
json.NewEncoder(&b).Encode(d)
|
||||||
|
|
||||||
@ -256,12 +265,12 @@ func (s *usageReportingService) sendUsageReport() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg.Options().URPostInsecurely {
|
if s.cfg.Options().URPostInsecurely {
|
||||||
transp.TLSClientConfig = &tls.Config{
|
transp.TLSClientConfig = &tls.Config{
|
||||||
InsecureSkipVerify: true,
|
InsecureSkipVerify: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_, err := client.Post(cfg.Options().URURL, "application/json", &b)
|
_, err := client.Post(s.cfg.Options().URURL, "application/json", &b)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,7 +280,7 @@ func (s *usageReportingService) Serve() {
|
|||||||
l.Infoln("Starting usage reporting")
|
l.Infoln("Starting usage reporting")
|
||||||
defer l.Infoln("Stopping usage reporting")
|
defer l.Infoln("Stopping usage reporting")
|
||||||
|
|
||||||
t := time.NewTimer(time.Duration(cfg.Options().URInitialDelayS) * time.Second) // time to initial report at start
|
t := time.NewTimer(time.Duration(s.cfg.Options().URInitialDelayS) * time.Second) // time to initial report at start
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-s.stop:
|
case <-s.stop:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user