package core import ( "errors" "flag" "fmt" "sync/atomic" "github.com/safing/portmaster/base/config" "github.com/safing/portmaster/base/database" "github.com/safing/portmaster/base/log" "github.com/safing/portmaster/base/metrics" "github.com/safing/portmaster/base/utils/debug" "github.com/safing/portmaster/service/mgr" _ "github.com/safing/portmaster/service/netenv" _ "github.com/safing/portmaster/service/netquery" _ "github.com/safing/portmaster/service/status" _ "github.com/safing/portmaster/service/sync" _ "github.com/safing/portmaster/service/ui" "github.com/safing/portmaster/service/updates" ) var db = database.NewInterface(&database.Options{ Local: true, Internal: true, }) // Core is the core service module. type Core struct { m *mgr.Manager instance instance EventShutdown *mgr.EventMgr[struct{}] EventRestart *mgr.EventMgr[struct{}] } // Manager returns the manager. func (c *Core) Manager() *mgr.Manager { return c.m } // Start starts the module. func (c *Core) Start() error { return start() } // Stop stops the module. func (c *Core) Stop() error { return nil } var disableShutdownEvent bool func init() { flag.BoolVar( &disableShutdownEvent, "disable-shutdown-event", false, "disable shutdown event to keep app and notifier open when core shuts down", ) } func prep() error { // init config if err := registerConfig(); err != nil { return err } if err := registerUpdateConfig(); err != nil { return err } if err := registerAPIEndpoints(); err != nil { return err } if err := initModulesIntegration(); err != nil { return err } return nil } func start() error { if err := startPlatformSpecific(); err != nil { return fmt.Errorf("failed to start plattform-specific components: %w", err) } // Setup update system. initUpdateConfig() initVersionExport() // Enable persistent metrics. if err := metrics.EnableMetricPersistence("core:metrics/storage"); err != nil { log.Warningf("core: failed to enable persisted metrics: %s", err) } return nil } var ( module *Core shimLoaded atomic.Bool ) // New returns a new NetEnv module. func New(instance instance) (*Core, error) { if !shimLoaded.CompareAndSwap(false, true) { return nil, errors.New("only one instance allowed") } m := mgr.New("Core") module = &Core{ m: m, instance: instance, EventShutdown: mgr.NewEventMgr[struct{}]("shutdown", m), EventRestart: mgr.NewEventMgr[struct{}]("restart", m), } if err := prep(); err != nil { return nil, err } return module, nil } type instance interface { Shutdown() Restart() AddWorkerInfoToDebugInfo(di *debug.Info) Config() *config.Config BinaryUpdates() *updates.Updater IntelUpdates() *updates.Updater }