mirror of
https://github.com/safing/portmaster
synced 2025-09-01 10:09:11 +00:00
Update and improve events according to new system
This commit is contained in:
parent
2e73d4fbe6
commit
dfc1cdeb1c
9 changed files with 66 additions and 249 deletions
38
core/api.go
38
core/api.go
|
@ -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.
|
|
||||||
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
|
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")
|
||||||
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
|
return "restart initiated", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
17
core/core.go
17
core/core.go
|
@ -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
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
27
ui/module.go
27
ui/module.go
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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),
|
||||||
),
|
),
|
||||||
})
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue