mirror of
https://github.com/safing/portmaster
synced 2025-04-08 13:09:11 +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>
156 lines
4.5 KiB
Go
156 lines
4.5 KiB
Go
package record
|
|
|
|
import (
|
|
"errors"
|
|
|
|
"github.com/safing/portmaster/base/database/accessor"
|
|
"github.com/safing/portmaster/base/log"
|
|
"github.com/safing/structures/container"
|
|
"github.com/safing/structures/dsd"
|
|
)
|
|
|
|
// TODO(ppacher):
|
|
// we can reduce the record.Record interface a lot by moving
|
|
// most of those functions that require the Record as it's first
|
|
// parameter to static package functions
|
|
// (i.e. Marshal, MarshalRecord, GetAccessor, ...).
|
|
// We should also consider given Base a GetBase() *Base method
|
|
// that returns itself. This way we can remove almost all Base
|
|
// only methods from the record.Record interface. That is, we can
|
|
// remove all those CreateMeta, UpdateMeta, ... stuff from the
|
|
// interface definition (not the actual functions!). This would make
|
|
// the record.Record interface slim and only provide methods that
|
|
// most users actually need. All those database/storage related methods
|
|
// can still be accessed by using GetBase().XXX() instead. We can also
|
|
// expose the dbName and dbKey and meta properties directly which would
|
|
// make a nice JSON blob when marshalled.
|
|
|
|
// Base provides a quick way to comply with the Model interface.
|
|
type Base struct {
|
|
dbName string
|
|
dbKey string
|
|
meta *Meta
|
|
}
|
|
|
|
// SetKey sets the key on the database record. The key may only be set once and
|
|
// future calls to SetKey will be ignored. If you want to copy/move the record
|
|
// to another database key, you will need to create a copy and assign a new key.
|
|
// A key must be set before the record is used in any database operation.
|
|
func (b *Base) SetKey(key string) {
|
|
if !b.KeyIsSet() {
|
|
b.dbName, b.dbKey = ParseKey(key)
|
|
} else {
|
|
log.Errorf("database: key is already set: tried to replace %q with %q", b.Key(), key)
|
|
}
|
|
}
|
|
|
|
// ResetKey resets the database name and key.
|
|
// Use with caution!
|
|
func (b *Base) ResetKey() {
|
|
b.dbName = ""
|
|
b.dbKey = ""
|
|
}
|
|
|
|
// Key returns the key of the database record.
|
|
// As the key must be set before any usage and can only be set once, this
|
|
// function may be used without locking the record.
|
|
func (b *Base) Key() string {
|
|
return b.dbName + ":" + b.dbKey
|
|
}
|
|
|
|
// KeyIsSet returns true if the database key is set.
|
|
// As the key must be set before any usage and can only be set once, this
|
|
// function may be used without locking the record.
|
|
func (b *Base) KeyIsSet() bool {
|
|
return b.dbName != ""
|
|
}
|
|
|
|
// DatabaseName returns the name of the database.
|
|
// As the key must be set before any usage and can only be set once, this
|
|
// function may be used without locking the record.
|
|
func (b *Base) DatabaseName() string {
|
|
return b.dbName
|
|
}
|
|
|
|
// DatabaseKey returns the database key of the database record.
|
|
// As the key must be set before any usage and can only be set once, this
|
|
// function may be used without locking the record.
|
|
func (b *Base) DatabaseKey() string {
|
|
return b.dbKey
|
|
}
|
|
|
|
// Meta returns the metadata object for this record.
|
|
func (b *Base) Meta() *Meta {
|
|
return b.meta
|
|
}
|
|
|
|
// CreateMeta sets a default metadata object for this record.
|
|
func (b *Base) CreateMeta() {
|
|
b.meta = &Meta{}
|
|
}
|
|
|
|
// UpdateMeta creates the metadata if it does not exist and updates it.
|
|
func (b *Base) UpdateMeta() {
|
|
if b.meta == nil {
|
|
b.CreateMeta()
|
|
}
|
|
b.meta.Update()
|
|
}
|
|
|
|
// SetMeta sets the metadata on the database record, it should only be called after loading the record. Use MoveTo to save the record with another key.
|
|
func (b *Base) SetMeta(meta *Meta) {
|
|
b.meta = meta
|
|
}
|
|
|
|
// Marshal marshals the object, without the database key or metadata. It returns nil if the record is deleted.
|
|
func (b *Base) Marshal(self Record, format uint8) ([]byte, error) {
|
|
if b.Meta() == nil {
|
|
return nil, errors.New("missing meta")
|
|
}
|
|
|
|
if b.Meta().Deleted > 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
dumped, err := dsd.Dump(self, format)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return dumped, nil
|
|
}
|
|
|
|
// MarshalRecord packs the object, including metadata, into a byte array for saving in a database.
|
|
func (b *Base) MarshalRecord(self Record) ([]byte, error) {
|
|
if b.Meta() == nil {
|
|
return nil, errors.New("missing meta")
|
|
}
|
|
|
|
// version
|
|
c := container.New([]byte{1})
|
|
|
|
// meta encoding
|
|
metaSection, err := dsd.Dump(b.meta, dsd.GenCode)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
c.AppendAsBlock(metaSection)
|
|
|
|
// data
|
|
dataSection, err := b.Marshal(self, dsd.JSON)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
c.Append(dataSection)
|
|
|
|
return c.CompileData(), nil
|
|
}
|
|
|
|
// IsWrapped returns whether the record is a Wrapper.
|
|
func (b *Base) IsWrapped() bool {
|
|
return false
|
|
}
|
|
|
|
// GetAccessor returns an accessor for this record, if available.
|
|
func (b *Base) GetAccessor(self Record) accessor.Accessor {
|
|
return accessor.NewStructAccessor(self)
|
|
}
|