safing-portmaster/spn/captain/status.go
Daniel Hååvi 80664d1a27
Restructure modules (#1572)
* 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>
2024-08-09 18:15:48 +03:00

154 lines
4.4 KiB
Go

package captain
import (
"fmt"
"sort"
"sync"
"time"
"github.com/safing/portmaster/base/config"
"github.com/safing/portmaster/base/database/record"
"github.com/safing/portmaster/base/runtime"
"github.com/safing/portmaster/base/utils/debug"
"github.com/safing/portmaster/service/intel/geoip"
"github.com/safing/portmaster/spn/conf"
"github.com/safing/portmaster/spn/navigator"
)
// SPNStatus holds SPN status information.
type SPNStatus struct {
record.Base
sync.Mutex
Status SPNStatusName
HomeHubID string
HomeHubName string
ConnectedIP string
ConnectedTransport string
ConnectedCountry *geoip.CountryInfo
ConnectedSince *time.Time
}
// SPNStatusName is a SPN status.
type SPNStatusName string
// SPN Stati.
const (
StatusFailed SPNStatusName = "failed"
StatusDisabled SPNStatusName = "disabled"
StatusConnecting SPNStatusName = "connecting"
StatusConnected SPNStatusName = "connected"
)
var (
spnStatus = &SPNStatus{
Status: StatusDisabled,
}
spnStatusPushFunc runtime.PushFunc
)
func registerSPNStatusProvider() (err error) {
spnStatus.SetKey("runtime:spn/status")
spnStatus.UpdateMeta()
spnStatusPushFunc, err = runtime.Register("spn/status", runtime.ProvideRecord(spnStatus))
return
}
func resetSPNStatus(statusName SPNStatusName, overrideEvenIfConnected bool) {
// Lock for updating values.
spnStatus.Lock()
defer spnStatus.Unlock()
// Ignore when connected and not overriding
if !overrideEvenIfConnected && spnStatus.Status == StatusConnected {
return
}
// Reset status.
spnStatus.Status = statusName
spnStatus.HomeHubID = ""
spnStatus.HomeHubName = ""
spnStatus.ConnectedIP = ""
spnStatus.ConnectedTransport = ""
spnStatus.ConnectedCountry = nil
spnStatus.ConnectedSince = nil
// Push new status.
pushSPNStatusUpdate()
}
// pushSPNStatusUpdate pushes an update of spnStatus, which must be locked.
func pushSPNStatusUpdate() {
spnStatus.UpdateMeta()
spnStatusPushFunc(spnStatus)
}
// GetSPNStatus returns the current SPN status.
func GetSPNStatus() *SPNStatus {
spnStatus.Lock()
defer spnStatus.Unlock()
return &SPNStatus{
Status: spnStatus.Status,
HomeHubID: spnStatus.HomeHubID,
HomeHubName: spnStatus.HomeHubName,
ConnectedIP: spnStatus.ConnectedIP,
ConnectedTransport: spnStatus.ConnectedTransport,
ConnectedCountry: spnStatus.ConnectedCountry,
ConnectedSince: spnStatus.ConnectedSince,
}
}
// AddToDebugInfo adds the SPN status to the given debug.Info.
func AddToDebugInfo(di *debug.Info) {
spnStatus.Lock()
defer spnStatus.Unlock()
// Check if SPN module is enabled.
var moduleStatus string
spnEnabled := config.GetAsBool(CfgOptionEnableSPNKey, false)
if spnEnabled() {
moduleStatus = "enabled"
} else {
moduleStatus = "disabled"
}
// Collect status data.
lines := make([]string, 0, 20)
lines = append(lines, fmt.Sprintf("HomeHubID: %v", spnStatus.HomeHubID))
lines = append(lines, fmt.Sprintf("HomeHubName: %v", spnStatus.HomeHubName))
lines = append(lines, fmt.Sprintf("HomeHubIP: %v", spnStatus.ConnectedIP))
lines = append(lines, fmt.Sprintf("Transport: %v", spnStatus.ConnectedTransport))
if spnStatus.ConnectedSince != nil {
lines = append(lines, fmt.Sprintf("Connected: %v ago", time.Since(*spnStatus.ConnectedSince).Round(time.Minute)))
}
lines = append(lines, "---")
lines = append(lines, fmt.Sprintf("Client: %v", conf.Client()))
lines = append(lines, fmt.Sprintf("PublicHub: %v", conf.PublicHub()))
lines = append(lines, fmt.Sprintf("HubHasIPv4: %v", conf.HubHasIPv4()))
lines = append(lines, fmt.Sprintf("HubHasIPv6: %v", conf.HubHasIPv6()))
// Collect status data of map.
if navigator.Main != nil {
lines = append(lines, "---")
mainMapStats := navigator.Main.Stats()
lines = append(lines, fmt.Sprintf("Map %s:", navigator.Main.Name))
lines = append(lines, fmt.Sprintf("Active Terminals: %d Hubs", mainMapStats.ActiveTerminals))
// Collect hub states.
mapStateSummary := make([]string, 0, len(mainMapStats.States))
for state, cnt := range mainMapStats.States {
if cnt > 0 {
mapStateSummary = append(mapStateSummary, fmt.Sprintf("State %s: %d Hubs", state, cnt))
}
}
sort.Strings(mapStateSummary)
lines = append(lines, mapStateSummary...)
}
// Add all data as section.
di.AddSection(
fmt.Sprintf("SPN: %s (module %s)", spnStatus.Status, moduleStatus),
debug.UseCodeSection|debug.AddContentLineBreaks,
lines...,
)
}