Update and improve events according to new system

This commit is contained in:
Daniel 2021-05-05 00:29:53 +02:00
parent 2e73d4fbe6
commit dfc1cdeb1c
9 changed files with 66 additions and 249 deletions

View file

@ -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.
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")
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
}

View file

@ -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
}

View file

@ -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

View file

@ -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
}

View file

@ -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 {

View file

@ -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,

View file

@ -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
}

View file

@ -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
}

View file

@ -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),
),
})
)
}
}