mirror of
https://github.com/safing/portmaster
synced 2025-04-23 20:39:10 +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>
165 lines
3.7 KiB
Go
165 lines
3.7 KiB
Go
package navigator
|
|
|
|
import (
|
|
"sort"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/safing/portmaster/base/database"
|
|
"github.com/safing/portmaster/base/log"
|
|
"github.com/safing/portmaster/service/intel/geoip"
|
|
"github.com/safing/portmaster/spn/docks"
|
|
"github.com/safing/portmaster/spn/hub"
|
|
)
|
|
|
|
// Map represent a collection of Pins and their relationship and status.
|
|
type Map struct {
|
|
sync.RWMutex
|
|
Name string
|
|
|
|
all map[string]*Pin
|
|
intel *hub.Intel
|
|
regions []*Region
|
|
|
|
home *Pin
|
|
homeTerminal *docks.CraneTerminal
|
|
|
|
measuringEnabled bool
|
|
hubUpdateHook *database.RegisteredHook
|
|
|
|
// analysisLock guards access to all of this map's Pin.analysis,
|
|
// regardedPins and the lastDesegrationAttempt fields.
|
|
analysisLock sync.Mutex
|
|
regardedPins []*Pin
|
|
lastDesegrationAttempt time.Time
|
|
}
|
|
|
|
// NewMap returns a new and empty Map.
|
|
func NewMap(name string, enableMeasuring bool) *Map {
|
|
m := &Map{
|
|
Name: name,
|
|
all: make(map[string]*Pin),
|
|
measuringEnabled: enableMeasuring,
|
|
}
|
|
addMapToAPI(m)
|
|
|
|
return m
|
|
}
|
|
|
|
// Close removes the map's integration, taking it "offline".
|
|
func (m *Map) Close() {
|
|
removeMapFromAPI(m.Name)
|
|
}
|
|
|
|
// GetPin returns the Pin of the Hub with the given ID.
|
|
func (m *Map) GetPin(hubID string) (pin *Pin, ok bool) {
|
|
m.RLock()
|
|
defer m.RUnlock()
|
|
|
|
pin, ok = m.all[hubID]
|
|
return
|
|
}
|
|
|
|
// GetHome returns the current home and it's accompanying terminal.
|
|
// Both may be nil.
|
|
func (m *Map) GetHome() (*Pin, *docks.CraneTerminal) {
|
|
m.RLock()
|
|
defer m.RUnlock()
|
|
|
|
return m.home, m.homeTerminal
|
|
}
|
|
|
|
// SetHome sets the given hub as the new home. Optionally, a terminal may be
|
|
// supplied to accompany the home hub.
|
|
func (m *Map) SetHome(id string, t *docks.CraneTerminal) (ok bool) {
|
|
m.Lock()
|
|
defer m.Unlock()
|
|
|
|
// Get pin from map.
|
|
newHome, ok := m.all[id]
|
|
if !ok {
|
|
return false
|
|
}
|
|
|
|
// Remove home hub state from all pins.
|
|
for _, pin := range m.all {
|
|
pin.removeStates(StateIsHomeHub)
|
|
}
|
|
|
|
// Set pin as home.
|
|
m.home = newHome
|
|
m.homeTerminal = t
|
|
m.home.addStates(StateIsHomeHub)
|
|
|
|
// Recalculate reachable.
|
|
err := m.recalculateReachableHubs()
|
|
if err != nil {
|
|
log.Warningf("spn/navigator: failed to recalculate reachable hubs: %s", err)
|
|
}
|
|
|
|
m.PushPinChanges()
|
|
return true
|
|
}
|
|
|
|
// GetAvailableCountries returns a map of countries including their information
|
|
// where the map has pins suitable for the given type.
|
|
func (m *Map) GetAvailableCountries(opts *Options, forType HubType) map[string]*geoip.CountryInfo {
|
|
if opts == nil {
|
|
opts = m.defaultOptions()
|
|
}
|
|
|
|
m.RLock()
|
|
defer m.RUnlock()
|
|
|
|
matcher := opts.Matcher(forType, m.intel)
|
|
countries := make(map[string]*geoip.CountryInfo)
|
|
for _, pin := range m.all {
|
|
if !matcher(pin) {
|
|
continue
|
|
}
|
|
if pin.LocationV4 != nil && countries[pin.LocationV4.Country.Code] == nil {
|
|
countries[pin.LocationV4.Country.Code] = &pin.LocationV4.Country
|
|
}
|
|
if pin.LocationV6 != nil && countries[pin.LocationV6.Country.Code] == nil {
|
|
countries[pin.LocationV6.Country.Code] = &pin.LocationV6.Country
|
|
}
|
|
}
|
|
|
|
return countries
|
|
}
|
|
|
|
// isEmpty returns whether the Map is regarded as empty.
|
|
func (m *Map) isEmpty() bool {
|
|
if m.home != nil {
|
|
// When a home hub is set, we also regard a map with only one entry to be
|
|
// empty, as this will be the case for Hubs, which will have their own
|
|
// entry in the Map.
|
|
return len(m.all) <= 1
|
|
}
|
|
|
|
return len(m.all) == 0
|
|
}
|
|
|
|
func (m *Map) pinList(lockMap bool) []*Pin {
|
|
if lockMap {
|
|
m.RLock()
|
|
defer m.RUnlock()
|
|
}
|
|
|
|
// Copy into slice.
|
|
list := make([]*Pin, 0, len(m.all))
|
|
for _, pin := range m.all {
|
|
list = append(list, pin)
|
|
}
|
|
|
|
return list
|
|
}
|
|
|
|
func (m *Map) sortedPins(lockMap bool) []*Pin {
|
|
// Get list.
|
|
list := m.pinList(lockMap)
|
|
|
|
// Sort list.
|
|
sort.Sort(sortByPinID(list))
|
|
return list
|
|
}
|