func NewService(cfg *config.Wrapper, myID protocol.DeviceID, mdl Model, tlsCfg *tls.Config, discoverer discover.Finder, bepProtocolName string, tlsDefaultCommonName string, lans []*net.IPNet) *Service { service := &Service{ Supervisor: suture.New("connections.Service", suture.Spec{ Log: func(line string) { l.Infoln(line) }, }), cfg: cfg, myID: myID, model: mdl, tlsCfg: tlsCfg, discoverer: discoverer, conns: make(chan internalConn), bepProtocolName: bepProtocolName, tlsDefaultCommonName: tlsDefaultCommonName, lans: lans, limiter: newLimiter(cfg), natService: nat.NewService(myID, cfg), listenersMut: sync.NewRWMutex(), listeners: make(map[string]genericListener), listenerTokens: make(map[string]suture.ServiceToken), // A listener can fail twice, rapidly. Any more than that and it // will be put on suspension for ten minutes. Restarts and changes // due to config are done by removing and adding services, so are // not subject to these limitations. listenerSupervisor: suture.New("c.S.listenerSupervisor", suture.Spec{ Log: func(line string) { l.Infoln(line) }, FailureThreshold: 2, FailureBackoff: 600 * time.Second, }), curConMut: sync.NewMutex(), currentConnection: make(map[protocol.DeviceID]completeConn), } cfg.Subscribe(service) // There are several moving parts here; one routine per listening address // (handled in configuration changing) to handle incoming connections, // one routine to periodically attempt outgoing connections, one routine to // the the common handling regardless of whether the connection was // incoming or outgoing. service.Add(serviceFunc(service.connect)) service.Add(serviceFunc(service.handle)) service.Add(service.listenerSupervisor) raw := cfg.RawCopy() // Actually starts the listeners and NAT service service.CommitConfiguration(raw, raw) return service }
func newLimiter(cfg *config.Wrapper) *limiter { l := &limiter{ write: rate.NewLimiter(rate.Inf, limiterBurstSize), read: rate.NewLimiter(rate.Inf, limiterBurstSize), } cfg.Subscribe(l) prev := config.Configuration{Options: config.OptionsConfiguration{MaxRecvKbps: -1, MaxSendKbps: -1}} l.CommitConfiguration(prev, cfg.RawCopy()) return l }
func archiveAndSaveConfig(cfg *config.Wrapper) error { // Copy the existing config to an archive copy archivePath := cfg.ConfigPath() + fmt.Sprintf(".v%d", cfg.RawCopy().OriginalVersion) l.Infoln("Archiving a copy of old config file format at:", archivePath) if err := copyFile(cfg.ConfigPath(), archivePath); err != nil { return err } // Do a regular atomic config sve return cfg.Save() }
func setPauseState(cfg *config.Wrapper, paused bool) { raw := cfg.RawCopy() for i := range raw.Devices { raw.Devices[i].Paused = paused } for i := range raw.Folders { raw.Folders[i].Paused = paused } if err := cfg.Replace(raw); err != nil { l.Fatalln("Cannot adjust paused state:", err) } }
// NewProgressEmitter creates a new progress emitter which emits // DownloadProgress events every interval. func NewProgressEmitter(cfg *config.Wrapper) *ProgressEmitter { t := &ProgressEmitter{ stop: make(chan struct{}), registry: make(map[string]*sharedPullerState), timer: time.NewTimer(time.Millisecond), sentDownloadStates: make(map[protocol.DeviceID]*sentDownloadState), connections: make(map[string][]protocol.Connection), mut: sync.NewMutex(), } t.CommitConfiguration(config.Configuration{}, cfg.RawCopy()) cfg.Subscribe(t) return t }
func newUsageReportingManager(cfg *config.Wrapper, m *model.Model) *usageReportingManager { mgr := &usageReportingManager{ cfg: cfg, model: m, } // Start UR if it's enabled. mgr.CommitConfiguration(config.Configuration{}, cfg.RawCopy()) // Listen to future config changes so that we can start and stop as // appropriate. cfg.Subscribe(mgr) return mgr }