mirror of
https://github.com/safing/portmaster
synced 2025-04-21 19:39:09 +00:00
* Move portbase into monorepo * Add new simple module mgr * [WIP] Switch to new simple module mgr * Add StateMgr and more worker variants * [WIP] Switch more modules * [WIP] Switch more modules * [WIP] swtich more modules * [WIP] switch all SPN modules * [WIP] switch all service modules * [WIP] Convert all workers to the new module system * [WIP] add new task system to module manager * [WIP] Add second take for scheduling workers * [WIP] Add FIXME for bugs in new scheduler * [WIP] Add minor improvements to scheduler * [WIP] Add new worker scheduler * [WIP] Fix more bug related to new module system * [WIP] Fix start handing of the new module system * [WIP] Improve startup process * [WIP] Fix minor issues * [WIP] Fix missing subsystem in settings * [WIP] Initialize managers in constructor * [WIP] Move module event initialization to constrictors * [WIP] Fix setting for enabling and disabling the SPN module * [WIP] Move API registeration into module construction * [WIP] Update states mgr for all modules * [WIP] Add CmdLine operation support * Add state helper methods to module group and instance * Add notification and module status handling to status package * Fix starting issues * Remove pilot widget and update security lock to new status data * Remove debug logs * Improve http server shutdown * Add workaround for cleanly shutting down firewall+netquery * Improve logging * Add syncing states with notifications for new module system * Improve starting, stopping, shutdown; resolve FIXMEs/TODOs * [WIP] Fix most unit tests * Review new module system and fix minor issues * Push shutdown and restart events again via API * Set sleep mode via interface * Update example/template module * [WIP] Fix spn/cabin unit test * Remove deprecated UI elements * Make log output more similar for the logging transition phase * Switch spn hub and observer cmds to new module system * Fix log sources * Make worker mgr less error prone * Fix tests and minor issues * Fix observation hub * Improve shutdown and restart handling * Split up big connection.go source file * Move varint and dsd packages to structures repo * Improve expansion test * Fix linter warnings * Fix interception module on windows * Fix linter errors --------- Co-authored-by: Vladimir Stoilov <vladimir@safing.io>
238 lines
5.8 KiB
Go
238 lines
5.8 KiB
Go
package updates
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
"strings"
|
|
"sync"
|
|
|
|
"github.com/safing/portmaster/base/database/record"
|
|
"github.com/safing/portmaster/base/info"
|
|
"github.com/safing/portmaster/base/log"
|
|
"github.com/safing/portmaster/base/updater"
|
|
"github.com/safing/portmaster/base/utils/debug"
|
|
"github.com/safing/portmaster/service/mgr"
|
|
"github.com/safing/portmaster/service/updates/helper"
|
|
)
|
|
|
|
const (
|
|
// versionsDBKey is the database key for update version information.
|
|
versionsDBKey = "core:status/versions"
|
|
|
|
// versionsDBKey is the database key for simple update version information.
|
|
simpleVersionsDBKey = "core:status/simple-versions"
|
|
|
|
// updateStatusDBKey is the database key for update status information.
|
|
updateStatusDBKey = "core:status/updates"
|
|
)
|
|
|
|
// Versions holds update versions and status information.
|
|
type Versions struct {
|
|
record.Base
|
|
sync.Mutex
|
|
|
|
Core *info.Info
|
|
Resources map[string]*updater.Resource
|
|
Channel string
|
|
Beta bool
|
|
Staging bool
|
|
}
|
|
|
|
// SimpleVersions holds simplified update versions and status information.
|
|
type SimpleVersions struct {
|
|
record.Base
|
|
sync.Mutex
|
|
|
|
Build *info.Info
|
|
Resources map[string]*SimplifiedResourceVersion
|
|
Channel string
|
|
}
|
|
|
|
// SimplifiedResourceVersion holds version information about one resource.
|
|
type SimplifiedResourceVersion struct {
|
|
Version string
|
|
}
|
|
|
|
// UpdateStateExport is a wrapper to export the updates state.
|
|
type UpdateStateExport struct {
|
|
record.Base
|
|
sync.Mutex
|
|
|
|
*updater.UpdateState
|
|
}
|
|
|
|
// GetVersions returns the update versions and status information.
|
|
// Resources must be locked when accessed.
|
|
func GetVersions() *Versions {
|
|
return &Versions{
|
|
Core: info.GetInfo(),
|
|
Resources: registry.Export(),
|
|
Channel: initialReleaseChannel,
|
|
Beta: initialReleaseChannel == helper.ReleaseChannelBeta,
|
|
Staging: initialReleaseChannel == helper.ReleaseChannelStaging,
|
|
}
|
|
}
|
|
|
|
// GetSimpleVersions returns the simplified update versions and status information.
|
|
func GetSimpleVersions() *SimpleVersions {
|
|
// Fill base info.
|
|
v := &SimpleVersions{
|
|
Build: info.GetInfo(),
|
|
Resources: make(map[string]*SimplifiedResourceVersion),
|
|
Channel: initialReleaseChannel,
|
|
}
|
|
|
|
// Iterate through all versions and add version info.
|
|
for id, resource := range registry.Export() {
|
|
func() {
|
|
resource.Lock()
|
|
defer resource.Unlock()
|
|
|
|
// Get current in-used or selected version.
|
|
var rv *updater.ResourceVersion
|
|
switch {
|
|
case resource.ActiveVersion != nil:
|
|
rv = resource.ActiveVersion
|
|
case resource.SelectedVersion != nil:
|
|
rv = resource.SelectedVersion
|
|
}
|
|
|
|
// Get information from resource.
|
|
if rv != nil {
|
|
v.Resources[id] = &SimplifiedResourceVersion{
|
|
Version: rv.VersionNumber,
|
|
}
|
|
}
|
|
}()
|
|
}
|
|
|
|
return v
|
|
}
|
|
|
|
// GetStateExport gets the update state from the registry and returns it in an
|
|
// exportable struct.
|
|
func GetStateExport() *UpdateStateExport {
|
|
export := registry.GetState()
|
|
return &UpdateStateExport{
|
|
UpdateState: &export.Updates,
|
|
}
|
|
}
|
|
|
|
// LoadStateExport loads the exported update state from the database.
|
|
func LoadStateExport() (*UpdateStateExport, error) {
|
|
r, err := db.Get(updateStatusDBKey)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// unwrap
|
|
if r.IsWrapped() {
|
|
// only allocate a new struct, if we need it
|
|
newRecord := &UpdateStateExport{}
|
|
err = record.Unwrap(r, newRecord)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return newRecord, nil
|
|
}
|
|
|
|
// or adjust type
|
|
newRecord, ok := r.(*UpdateStateExport)
|
|
if !ok {
|
|
return nil, fmt.Errorf("record not of type *UpdateStateExport, but %T", r)
|
|
}
|
|
return newRecord, nil
|
|
}
|
|
|
|
func initVersionExport() (err error) {
|
|
if err := GetVersions().save(); err != nil {
|
|
log.Warningf("updates: failed to export version information: %s", err)
|
|
}
|
|
if err := GetSimpleVersions().save(); err != nil {
|
|
log.Warningf("updates: failed to export version information: %s", err)
|
|
}
|
|
|
|
module.EventVersionsUpdated.AddCallback("export version status", export)
|
|
return nil
|
|
}
|
|
|
|
func (v *Versions) save() error {
|
|
if !v.KeyIsSet() {
|
|
v.SetKey(versionsDBKey)
|
|
}
|
|
return db.Put(v)
|
|
}
|
|
|
|
func (v *SimpleVersions) save() error {
|
|
if !v.KeyIsSet() {
|
|
v.SetKey(simpleVersionsDBKey)
|
|
}
|
|
return db.Put(v)
|
|
}
|
|
|
|
func (s *UpdateStateExport) save() error {
|
|
if !s.KeyIsSet() {
|
|
s.SetKey(updateStatusDBKey)
|
|
}
|
|
return db.Put(s)
|
|
}
|
|
|
|
// export is an event hook.
|
|
func export(_ *mgr.WorkerCtx, _ struct{}) (cancel bool, err error) {
|
|
// Export versions.
|
|
if err := GetVersions().save(); err != nil {
|
|
return false, err
|
|
}
|
|
if err := GetSimpleVersions().save(); err != nil {
|
|
return false, err
|
|
}
|
|
// Export udpate state.
|
|
if err := GetStateExport().save(); err != nil {
|
|
return false, err
|
|
}
|
|
|
|
return false, nil
|
|
}
|
|
|
|
// AddToDebugInfo adds the update system status to the given debug.Info.
|
|
func AddToDebugInfo(di *debug.Info) {
|
|
// Get resources from registry.
|
|
resources := registry.Export()
|
|
platformPrefix := helper.PlatformIdentifier("")
|
|
|
|
// Collect data for debug info.
|
|
var active, selected []string
|
|
var activeCnt, totalCnt int
|
|
for id, r := range resources {
|
|
// Ignore resources for other platforms.
|
|
if !strings.HasPrefix(id, "all/") && !strings.HasPrefix(id, platformPrefix) {
|
|
continue
|
|
}
|
|
|
|
totalCnt++
|
|
if r.ActiveVersion != nil {
|
|
activeCnt++
|
|
active = append(active, fmt.Sprintf("%s: %s", id, r.ActiveVersion.VersionNumber))
|
|
}
|
|
if r.SelectedVersion != nil {
|
|
selected = append(selected, fmt.Sprintf("%s: %s", id, r.SelectedVersion.VersionNumber))
|
|
}
|
|
}
|
|
sort.Strings(active)
|
|
sort.Strings(selected)
|
|
|
|
// Compile to one list.
|
|
lines := make([]string, 0, len(active)+len(selected)+3)
|
|
lines = append(lines, "Active:")
|
|
lines = append(lines, active...)
|
|
lines = append(lines, "")
|
|
lines = append(lines, "Selected:")
|
|
lines = append(lines, selected...)
|
|
|
|
// Add section.
|
|
di.AddSection(
|
|
fmt.Sprintf("Updates: %s (%d/%d)", initialReleaseChannel, activeCnt, totalCnt),
|
|
debug.UseCodeSection|debug.AddContentLineBreaks,
|
|
lines...,
|
|
)
|
|
}
|