// 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), last: make(map[string]map[string]*pullerProgress), timer: time.NewTimer(time.Millisecond), mut: sync.NewMutex(), } t.CommitConfiguration(config.Configuration{}, cfg.Raw()) 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.Raw()) // Listen to future config changes so that we can start and stop as // appropriate. cfg.Subscribe(mgr) return mgr }
func NewService(cfg *config.Wrapper, tlsCfg *tls.Config) *Service { conns := make(chan *tls.Conn) service := &Service{ Supervisor: suture.New("Service", suture.Spec{ Log: func(log string) { l.Debugln(log) }, FailureBackoff: 5 * time.Minute, FailureDecay: float64((10 * time.Minute) / time.Second), FailureThreshold: 5, }), cfg: cfg, tlsCfg: tlsCfg, tokens: make(map[string]suture.ServiceToken), clients: make(map[string]client.RelayClient), mut: sync.NewRWMutex(), invitations: make(chan protocol.SessionInvitation), conns: conns, } rcfg := cfg.Raw() service.CommitConfiguration(rcfg, rcfg) cfg.Subscribe(service) receiver := &invitationReceiver{ tlsCfg: tlsCfg, conns: conns, invitations: service.invitations, stop: make(chan struct{}), } eventBc := &eventBroadcaster{ Service: service, stop: make(chan struct{}), } service.Add(receiver) service.Add(eventBc) return service }
func setupGUI(mainService *suture.Supervisor, cfg *config.Wrapper, m *model.Model, apiSub *events.BufferedSubscription, discoverer *discover.CachingMux, relayService *relay.Service, errors, systemLog *logger.Recorder, runtimeOptions RuntimeOptions) { guiCfg := cfg.GUI() if !guiCfg.Enabled { return } if guiCfg.InsecureAdminAccess { l.Warnln("Insecure admin access is enabled.") } api, err := newAPIService(myID, cfg, runtimeOptions.assetDir, m, apiSub, discoverer, relayService, errors, systemLog) if err != nil { l.Fatalln("Cannot start GUI:", err) } cfg.Subscribe(api) mainService.Add(api) if cfg.Options().StartBrowser && !runtimeOptions.noBrowser && !runtimeOptions.stRestarting { // Can potentially block if the utility we are invoking doesn't // fork, and just execs, hence keep it in it's own routine. go openURL(guiCfg.URL()) } }
func NewConnectionService(cfg *config.Wrapper, myID protocol.DeviceID, mdl Model, tlsCfg *tls.Config, discoverer discover.Finder, relayService *relay.Service, bepProtocolName string, tlsDefaultCommonName string, lans []*net.IPNet) suture.Service { service := &connectionService{ Supervisor: suture.NewSimple("connectionService"), cfg: cfg, myID: myID, model: mdl, tlsCfg: tlsCfg, discoverer: discoverer, relayService: relayService, conns: make(chan model.IntermediateConnection), bepProtocolName: bepProtocolName, tlsDefaultCommonName: tlsDefaultCommonName, lans: lans, connType: make(map[protocol.DeviceID]model.ConnectionType), relaysEnabled: cfg.Options().RelaysEnabled, lastRelayCheck: make(map[protocol.DeviceID]time.Time), } cfg.Subscribe(service) if service.cfg.Options().MaxSendKbps > 0 { service.writeRateLimit = ratelimit.NewBucketWithRate(float64(1000*service.cfg.Options().MaxSendKbps), int64(5*1000*service.cfg.Options().MaxSendKbps)) } if service.cfg.Options().MaxRecvKbps > 0 { service.readRateLimit = ratelimit.NewBucketWithRate(float64(1000*service.cfg.Options().MaxRecvKbps), int64(5*1000*service.cfg.Options().MaxRecvKbps)) } // There are several moving parts here; one routine per listening address // 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. // Furthermore, a relay connectionService which handles incoming requests to connect // via the relays. // // TODO: Clean shutdown, and/or handling config changes on the fly. We // partly do this now - new devices and addresses will be picked up, but // not new listen addresses and we don't support disconnecting devices // that are removed and so on... service.Add(serviceFunc(service.connect)) for _, addr := range service.cfg.Options().ListenAddress { uri, err := url.Parse(addr) if err != nil { l.Infoln("Failed to parse listen address:", addr, err) continue } listener, ok := listeners[uri.Scheme] if !ok { l.Infoln("Unknown listen address scheme:", uri.String()) continue } l.Debugln("listening on", uri) service.Add(serviceFunc(func() { listener(uri, service.tlsCfg, service.conns) })) } service.Add(serviceFunc(service.handle)) if service.relayService != nil { service.Add(serviceFunc(service.acceptRelayConns)) } return service }