diff --git a/core/api.go b/core/api.go index 49cb1428..00f07425 100644 --- a/core/api.go +++ b/core/api.go @@ -1,7 +1,9 @@ package core import ( + "context" "net/http" + "time" "github.com/safing/portbase/api" "github.com/safing/portbase/log" @@ -11,6 +13,16 @@ import ( "github.com/safing/portmaster/updates" ) +const ( + eventShutdown = "shutdown" + eventRestart = "restart" +) + +func registerEvents() { + module.RegisterEvent(eventShutdown, true) + module.RegisterEvent(eventRestart, true) +} + func registerAPIEndpoints() error { if err := api.RegisterEndpoint(api.Endpoint{ Path: "core/shutdown", @@ -50,15 +62,35 @@ func registerAPIEndpoints() error { // shutdown shuts the Portmaster down. func shutdown(_ *api.Request) (msg string, err error) { log.Warning("core: user requested shutdown via action") - // Do not use a worker, as this would block itself here. - go modules.Shutdown() //nolint:errcheck + + module.StartWorker("shutdown", func(context.Context) error { + // Notify everyone of the shutdown. + module.TriggerEvent(eventShutdown, nil) + // Wait a bit for the event to propagate. + time.Sleep(1 * time.Second) + + // Do not run in worker, as this would block itself here. + go modules.Shutdown() //nolint:errcheck + return nil + }) + return "shutdown initiated", nil } // restart restarts the Portmaster. func restart(_ *api.Request) (msg string, err error) { log.Info("core: user requested restart via action") - updates.RestartNow() + + module.StartWorker("restart", func(context.Context) error { + // Notify everyone of the shutdown. + module.TriggerEvent(eventRestart, nil) + // Wait a bit for the event to propagate. + time.Sleep(1 * time.Second) + + updates.RestartNow() + return nil + }) + return "restart initiated", nil } diff --git a/core/control.go b/core/control.go deleted file mode 100644 index 32898a85..00000000 --- a/core/control.go +++ /dev/null @@ -1,99 +0,0 @@ -package core - -import ( - "fmt" - "strings" - "sync" - - "github.com/safing/portbase/database" - "github.com/safing/portbase/database/record" - "github.com/safing/portbase/database/storage" -) - -// StorageInterface provices a storage.Interface to the storage manager. -type StorageInterface struct { - storage.InjectBase -} - -// Get returns a database record. -func (s *StorageInterface) Get(key string) (record.Record, error) { - msg := newMessage(key) - splittedKey := strings.Split(key, "/") - - switch splittedKey[0] { - case "module": - return controlModule(msg, splittedKey) - default: - return nil, storage.ErrNotFound - } -} - -func controlModule(msg *MessageRecord, splittedKey []string) (record.Record, error) { - // format: module/moduleName/action/param - var moduleName string - var action string - var param string - var err error - - // parse elements - switch len(splittedKey) { - case 4: - param = splittedKey[3] - fallthrough - case 3: - moduleName = splittedKey[1] - action = splittedKey[2] - default: - return nil, storage.ErrNotFound - } - - // execute - switch action { - case "trigger": - err = module.InjectEvent(fmt.Sprintf("user triggered the '%s/%s' event", moduleName, param), moduleName, param, nil) - default: - return nil, storage.ErrNotFound - } - - if err != nil { - msg.Message = err.Error() - } else { - msg.Success = true - } - - return msg, nil -} - -func registerControlDatabase() error { - _, err := database.Register(&database.Database{ - Name: "control", - Description: "Control Interface for the Portmaster", - StorageType: "injected", - }) - if err != nil { - return err - } - - _, err = database.InjectDatabase("control", &StorageInterface{}) - if err != nil { - return err - } - - return nil -} - -// MessageRecord is a simple record used for control database feedback -type MessageRecord struct { - record.Base - sync.Mutex - - Success bool - Message string -} - -func newMessage(key string) *MessageRecord { - m := &MessageRecord{} - m.SetKey("control:" + key) - m.UpdateMeta() - return m -} diff --git a/core/core.go b/core/core.go index 8674c2a7..9acd4dad 100644 --- a/core/core.go +++ b/core/core.go @@ -33,12 +33,15 @@ func prep() error { registerEvents() // init config - logFlagOverrides() err := registerConfig() if err != nil { return err } + if err := registerAPIEndpoints(); err != nil { + return err + } + return nil } @@ -47,18 +50,6 @@ func start() error { return fmt.Errorf("failed to start plattform-specific components: %s", err) } - if err := registerEventHooks(); err != nil { - return err - } - - if err := registerControlDatabase(); err != nil { - return err - } - - if err := registerAPIEndpoints(); err != nil { - return err - } - registerLogCleaner() return nil diff --git a/core/events.go b/core/events.go deleted file mode 100644 index 608eb3c5..00000000 --- a/core/events.go +++ /dev/null @@ -1,50 +0,0 @@ -// DEPRECATED: remove in v0.7 - -package core - -import ( - "context" - - "github.com/safing/portbase/log" - "github.com/safing/portbase/modules" - "github.com/safing/portmaster/updates" -) - -const ( - eventShutdown = "shutdown" - eventRestart = "restart" -) - -func registerEvents() { - module.RegisterEvent(eventShutdown) - module.RegisterEvent(eventRestart) -} - -func registerEventHooks() error { - err := module.RegisterEventHook("core", eventShutdown, "execute shutdown", shutdownHook) - if err != nil { - return err - } - - err = module.RegisterEventHook("core", eventRestart, "execute shutdown", restartHook) - if err != nil { - return err - } - - return nil -} - -// shutdownHook shuts the Portmaster down. -func shutdownHook(ctx context.Context, _ interface{}) error { - log.Warning("core: user requested shutdown") - // Do not use a worker, as this would block itself here. - go modules.Shutdown() //nolint:errcheck - return nil -} - -// restartHook restarts the Portmaster. -func restartHook(ctx context.Context, data interface{}) error { - log.Info("core: user requested restart") - updates.RestartNow() - return nil -} diff --git a/netenv/main.go b/netenv/main.go index 1fca17c6..e06f0f0d 100644 --- a/netenv/main.go +++ b/netenv/main.go @@ -16,8 +16,8 @@ var ( func init() { module = modules.Register("netenv", prep, start, nil) - module.RegisterEvent(NetworkChangedEvent) - module.RegisterEvent(OnlineStatusChangedEvent) + module.RegisterEvent(NetworkChangedEvent, true) + module.RegisterEvent(OnlineStatusChangedEvent, true) } func prep() error { diff --git a/resolver/main.go b/resolver/main.go index bb1825c6..9d327be1 100644 --- a/resolver/main.go +++ b/resolver/main.go @@ -15,15 +15,11 @@ import ( ) var ( - // ClearNameCacheEvent is a triggerable event that clears the name record cache. - ClearNameCacheEvent = "clear name cache" - module *modules.Module ) func init() { module = modules.Register("resolver", prep, start, nil, "base", "netenv") - module.RegisterEvent(ClearNameCacheEvent) } func prep() error { @@ -80,18 +76,6 @@ func start() error { return err } - // DEPRECATED: remove in v0.7 - // cache clearing - err = module.RegisterEventHook( - "resolver", - ClearNameCacheEvent, - ClearNameCacheEvent, - clearNameCacheEventHandler, - ) - if err != nil { - return err - } - module.StartServiceWorker( "mdns handler", 5*time.Second, diff --git a/ui/module.go b/ui/module.go index 8fdfed9d..80494ca7 100644 --- a/ui/module.go +++ b/ui/module.go @@ -1,11 +1,8 @@ package ui import ( - "context" - "github.com/safing/portbase/dataroot" - resources "github.com/cookieo9/resources-go" "github.com/safing/portbase/log" "github.com/safing/portbase/modules" ) @@ -23,7 +20,9 @@ func init() { } func prep() error { - module.RegisterEvent(eventReload) + if err := registerAPIEndpoints(); err != nil { + return err + } return registerRoutes() } @@ -42,25 +41,5 @@ func start() error { log.Warningf("ui: failed to create safe exec dir: %s", err) } - return module.RegisterEventHook("ui", eventReload, "reload assets", reloadUI) -} - -func reloadUI(ctx context.Context, _ interface{}) error { - log.Info("core: user/UI requested UI reload") - - appsLock.Lock() - defer appsLock.Unlock() - - // close all bundles - for id, bundle := range apps { - err := bundle.Close() - if err != nil { - log.Warningf("ui: failed to close bundle %s: %s", id, err) - } - } - - // reset index - apps = make(map[string]*resources.BundleSequence) - return nil } diff --git a/updates/main.go b/updates/main.go index 5d73a529..73f4ec63 100644 --- a/updates/main.go +++ b/updates/main.go @@ -12,6 +12,7 @@ import ( "github.com/safing/portbase/dataroot" "github.com/safing/portbase/log" "github.com/safing/portbase/modules" + "github.com/safing/portbase/notifications" "github.com/safing/portbase/updater" ) @@ -41,10 +42,6 @@ const ( // to check if new versions of their resources are // available by checking File.UpgradeAvailable(). ResourceUpdateEvent = "resource update" - - // TriggerUpdateEvent is the event that can be emitted - // by the updates module to trigger an update. - TriggerUpdateEvent = "trigger update" ) var ( @@ -68,18 +65,17 @@ var ( ) const ( - updateInProgress = "update-in-progress" - updateInProcessDescr = "Portmaster is currently checking and downloading updates." - updateFailed = "update-failed" + updateInProgress = "updates:in-progress" + updateFailed = "updates:failed" ) func init() { module = modules.Register(ModuleName, prep, start, stop, "base") - module.RegisterEvent(VersionUpdateEvent) - module.RegisterEvent(ResourceUpdateEvent) + module.RegisterEvent(VersionUpdateEvent, true) + module.RegisterEvent(ResourceUpdateEvent, true) - flag.StringVar(&userAgentFromFlag, "update-agent", "", "Sets the user agent for requests to the update server") - flag.BoolVar(&staging, "staging", false, "Use staging update channel (for testing only)") + flag.StringVar(&userAgentFromFlag, "update-agent", "", "set the user agent for requests to the update server") + flag.BoolVar(&staging, "staging", false, "use staging update channel; for testing only") // initialize mandatory updates if onWindows { @@ -109,7 +105,7 @@ func prep() error { return err } - module.RegisterEvent(TriggerUpdateEvent) + return registerAPIEndpoints() return nil } @@ -127,18 +123,6 @@ func start() error { return err } - if err := module.RegisterEventHook( - module.Name, - TriggerUpdateEvent, - "Check for and download available updates", - func(context.Context, interface{}) error { - _ = TriggerUpdate() - return nil - }, - ); err != nil { - return err - } - // create registry registry = &updater.ResourceRegistry{ Name: ModuleName, @@ -244,17 +228,21 @@ func start() error { // TriggerUpdate queues the update task to execute ASAP. func TriggerUpdate() error { - if !module.Online() { - if !module.OnlineSoon() { - return fmt.Errorf("module not enabled") - } + switch { + case !module.OnlineSoon(): + return fmt.Errorf("updates module is disabled") + case !module.Online(): updateASAP = true - } else { + + case !enableUpdates(): + return fmt.Errorf("automatic updating is disabled") + + default: updateTask.StartASAP() - log.Debugf("updates: triggering update to run as soon as possible") } + log.Debugf("updates: triggering update to run as soon as possible") return nil } diff --git a/updates/upgrader.go b/updates/upgrader.go index 7414f693..c1016bf5 100644 --- a/updates/upgrader.go +++ b/updates/upgrader.go @@ -135,18 +135,10 @@ func upgradeCoreNotify() error { func upgradeCoreNotifyActionHandler(_ context.Context, n *notifications.Notification) error { switch n.SelectedActionID { case "restart": - // Cannot directly trigger due to import loop. - err := module.InjectEvent( - "user triggered restart via notification", - "core", - "restart", - nil, - ) - if err != nil { - return fmt.Errorf("failed to trigger restart via notification: %s", err) - } + log.Infof("updates: user triggered restart via core update notification") + RestartNow() case "later": - return n.Delete() + n.Delete() } return nil @@ -266,7 +258,7 @@ func warnOnIncorrectParentPath() { absPath, filepath.Join(root, expectedFileName), ), - }) + ) } }