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 package core
import ( import (
"context"
"net/http" "net/http"
"time"
"github.com/safing/portbase/api" "github.com/safing/portbase/api"
"github.com/safing/portbase/log" "github.com/safing/portbase/log"
@ -11,6 +13,16 @@ import (
"github.com/safing/portmaster/updates" "github.com/safing/portmaster/updates"
) )
const (
eventShutdown = "shutdown"
eventRestart = "restart"
)
func registerEvents() {
module.RegisterEvent(eventShutdown, true)
module.RegisterEvent(eventRestart, true)
}
func registerAPIEndpoints() error { func registerAPIEndpoints() error {
if err := api.RegisterEndpoint(api.Endpoint{ if err := api.RegisterEndpoint(api.Endpoint{
Path: "core/shutdown", Path: "core/shutdown",
@ -50,15 +62,35 @@ func registerAPIEndpoints() error {
// shutdown shuts the Portmaster down. // shutdown shuts the Portmaster down.
func shutdown(_ *api.Request) (msg string, err error) { func shutdown(_ *api.Request) (msg string, err error) {
log.Warning("core: user requested shutdown via action") 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 go modules.Shutdown() //nolint:errcheck
return nil
})
return "shutdown initiated", nil return "shutdown initiated", nil
} }
// restart restarts the Portmaster. // restart restarts the Portmaster.
func restart(_ *api.Request) (msg string, err error) { func restart(_ *api.Request) (msg string, err error) {
log.Info("core: user requested restart via action") 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() updates.RestartNow()
return nil
})
return "restart initiated", 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() registerEvents()
// init config // init config
logFlagOverrides()
err := registerConfig() err := registerConfig()
if err != nil { if err != nil {
return err return err
} }
if err := registerAPIEndpoints(); err != nil {
return err
}
return nil return nil
} }
@ -47,18 +50,6 @@ func start() error {
return fmt.Errorf("failed to start plattform-specific components: %s", err) 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() registerLogCleaner()
return nil 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() { func init() {
module = modules.Register("netenv", prep, start, nil) module = modules.Register("netenv", prep, start, nil)
module.RegisterEvent(NetworkChangedEvent) module.RegisterEvent(NetworkChangedEvent, true)
module.RegisterEvent(OnlineStatusChangedEvent) module.RegisterEvent(OnlineStatusChangedEvent, true)
} }
func prep() error { func prep() error {

View file

@ -15,15 +15,11 @@ import (
) )
var ( var (
// ClearNameCacheEvent is a triggerable event that clears the name record cache.
ClearNameCacheEvent = "clear name cache"
module *modules.Module module *modules.Module
) )
func init() { func init() {
module = modules.Register("resolver", prep, start, nil, "base", "netenv") module = modules.Register("resolver", prep, start, nil, "base", "netenv")
module.RegisterEvent(ClearNameCacheEvent)
} }
func prep() error { func prep() error {
@ -80,18 +76,6 @@ func start() error {
return err return err
} }
// DEPRECATED: remove in v0.7
// cache clearing
err = module.RegisterEventHook(
"resolver",
ClearNameCacheEvent,
ClearNameCacheEvent,
clearNameCacheEventHandler,
)
if err != nil {
return err
}
module.StartServiceWorker( module.StartServiceWorker(
"mdns handler", "mdns handler",
5*time.Second, 5*time.Second,

View file

@ -1,11 +1,8 @@
package ui package ui
import ( import (
"context"
"github.com/safing/portbase/dataroot" "github.com/safing/portbase/dataroot"
resources "github.com/cookieo9/resources-go"
"github.com/safing/portbase/log" "github.com/safing/portbase/log"
"github.com/safing/portbase/modules" "github.com/safing/portbase/modules"
) )
@ -23,7 +20,9 @@ func init() {
} }
func prep() error { func prep() error {
module.RegisterEvent(eventReload) if err := registerAPIEndpoints(); err != nil {
return err
}
return registerRoutes() return registerRoutes()
} }
@ -42,25 +41,5 @@ func start() error {
log.Warningf("ui: failed to create safe exec dir: %s", err) 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 return nil
} }

View file

@ -12,6 +12,7 @@ import (
"github.com/safing/portbase/dataroot" "github.com/safing/portbase/dataroot"
"github.com/safing/portbase/log" "github.com/safing/portbase/log"
"github.com/safing/portbase/modules" "github.com/safing/portbase/modules"
"github.com/safing/portbase/notifications"
"github.com/safing/portbase/updater" "github.com/safing/portbase/updater"
) )
@ -41,10 +42,6 @@ const (
// to check if new versions of their resources are // to check if new versions of their resources are
// available by checking File.UpgradeAvailable(). // available by checking File.UpgradeAvailable().
ResourceUpdateEvent = "resource update" ResourceUpdateEvent = "resource update"
// TriggerUpdateEvent is the event that can be emitted
// by the updates module to trigger an update.
TriggerUpdateEvent = "trigger update"
) )
var ( var (
@ -68,18 +65,17 @@ var (
) )
const ( const (
updateInProgress = "update-in-progress" updateInProgress = "updates:in-progress"
updateInProcessDescr = "Portmaster is currently checking and downloading updates." updateFailed = "updates:failed"
updateFailed = "update-failed"
) )
func init() { func init() {
module = modules.Register(ModuleName, prep, start, stop, "base") module = modules.Register(ModuleName, prep, start, stop, "base")
module.RegisterEvent(VersionUpdateEvent) module.RegisterEvent(VersionUpdateEvent, true)
module.RegisterEvent(ResourceUpdateEvent) module.RegisterEvent(ResourceUpdateEvent, true)
flag.StringVar(&userAgentFromFlag, "update-agent", "", "Sets the user agent for requests to the update server") 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)") flag.BoolVar(&staging, "staging", false, "use staging update channel; for testing only")
// initialize mandatory updates // initialize mandatory updates
if onWindows { if onWindows {
@ -109,7 +105,7 @@ func prep() error {
return err return err
} }
module.RegisterEvent(TriggerUpdateEvent) return registerAPIEndpoints()
return nil return nil
} }
@ -127,18 +123,6 @@ func start() error {
return err 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 // create registry
registry = &updater.ResourceRegistry{ registry = &updater.ResourceRegistry{
Name: ModuleName, Name: ModuleName,
@ -244,17 +228,21 @@ func start() error {
// TriggerUpdate queues the update task to execute ASAP. // TriggerUpdate queues the update task to execute ASAP.
func TriggerUpdate() error { func TriggerUpdate() error {
if !module.Online() { switch {
if !module.OnlineSoon() { case !module.OnlineSoon():
return fmt.Errorf("module not enabled") return fmt.Errorf("updates module is disabled")
}
case !module.Online():
updateASAP = true updateASAP = true
} else {
case !enableUpdates():
return fmt.Errorf("automatic updating is disabled")
default:
updateTask.StartASAP() 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 return nil
} }

View file

@ -135,18 +135,10 @@ func upgradeCoreNotify() error {
func upgradeCoreNotifyActionHandler(_ context.Context, n *notifications.Notification) error { func upgradeCoreNotifyActionHandler(_ context.Context, n *notifications.Notification) error {
switch n.SelectedActionID { switch n.SelectedActionID {
case "restart": case "restart":
// Cannot directly trigger due to import loop. log.Infof("updates: user triggered restart via core update notification")
err := module.InjectEvent( RestartNow()
"user triggered restart via notification",
"core",
"restart",
nil,
)
if err != nil {
return fmt.Errorf("failed to trigger restart via notification: %s", err)
}
case "later": case "later":
return n.Delete() n.Delete()
} }
return nil return nil
@ -266,7 +258,7 @@ func warnOnIncorrectParentPath() {
absPath, absPath,
filepath.Join(root, expectedFileName), filepath.Join(root, expectedFileName),
), ),
}) )
} }
} }