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>
This commit is contained in:
Daniel Hååvi
2024-08-09 17:15:48 +02:00
committed by GitHub
parent 10a77498f4
commit 80664d1a27
647 changed files with 37690 additions and 3366 deletions

View File

@@ -8,7 +8,7 @@ import (
"github.com/miekg/dns"
"github.com/safing/portbase/log"
"github.com/safing/portmaster/base/log"
"github.com/safing/portmaster/service/nameserver/nsutil"
)

View File

@@ -1,7 +1,7 @@
package customlists
import (
"github.com/safing/portbase/config"
"github.com/safing/portmaster/base/config"
)
var (

View File

@@ -10,8 +10,9 @@ import (
"github.com/miekg/dns"
"github.com/safing/portbase/log"
"github.com/safing/portbase/notifications"
"github.com/safing/portmaster/base/log"
"github.com/safing/portmaster/base/notifications"
"github.com/safing/portmaster/service/mgr"
"github.com/safing/portmaster/service/network/netutils"
)
@@ -79,8 +80,15 @@ func parseFile(filePath string) error {
file, err := os.Open(filePath)
if err != nil {
log.Warningf("intel/customlists: failed to parse file %s", err)
module.Warning(parseWarningNotificationID, "Failed to open custom filter list", err.Error())
module.states.Add(mgr.State{
ID: parseWarningNotificationID,
Name: "Failed to open custom filter list",
Message: err.Error(),
Type: mgr.StateTypeWarning,
})
return err
} else {
module.states.Remove(parseWarningNotificationID)
}
defer func() { _ = file.Close() }()
@@ -107,11 +115,15 @@ func parseFile(filePath string) error {
if invalidLinesRation > rationForInvalidLinesUntilWarning {
log.Warning("intel/customlists: Too many invalid lines")
module.Warning(zeroIPNotificationID, "Custom filter list has many invalid lines",
fmt.Sprintf(`%d out of %d lines are invalid.
Check if you are using the correct file format and if the path to the custom filter list is correct.`, invalidLinesCount, allLinesCount))
module.states.Add(mgr.State{
ID: zeroIPNotificationID,
Name: "Custom filter list has many invalid lines",
Message: fmt.Sprintf(`%d out of %d lines are invalid.
Check if you are using the correct file format and if the path to the custom filter list is correct.`, invalidLinesCount, allLinesCount),
Type: mgr.StateTypeWarning,
})
} else {
module.Resolve(zeroIPNotificationID)
module.states.Remove(zeroIPNotificationID)
}
allEntriesCount := len(domainsFilterList) + len(ipAddressesFilterList) + len(autonomousSystemsFilterList) + len(countryCodesFilterList)
@@ -130,8 +142,6 @@ func parseFile(filePath string) error {
len(autonomousSystemsFilterList),
len(countryCodesFilterList)))
module.Resolve(parseWarningNotificationID)
return nil
}

View File

@@ -1,27 +1,46 @@
package customlists
import (
"context"
"errors"
"net"
"os"
"regexp"
"strings"
"sync"
"sync/atomic"
"time"
"golang.org/x/net/publicsuffix"
"github.com/safing/portbase/api"
"github.com/safing/portbase/modules"
"github.com/safing/portmaster/base/api"
"github.com/safing/portmaster/base/config"
"github.com/safing/portmaster/service/mgr"
)
var module *modules.Module
type CustomList struct {
mgr *mgr.Manager
instance instance
const (
configModuleName = "config"
configChangeEvent = "config change"
)
updateFilterListWorkerMgr *mgr.WorkerMgr
states *mgr.StateMgr
}
func (cl *CustomList) Manager() *mgr.Manager {
return cl.mgr
}
func (cl *CustomList) States() *mgr.StateMgr {
return cl.states
}
func (cl *CustomList) Start() error {
return start()
}
func (cl *CustomList) Stop() error {
return nil
}
// Helper variables for parsing the input file.
var (
@@ -34,17 +53,12 @@ var (
filterListFileModifiedTime time.Time
filterListLock sync.RWMutex
parserTask *modules.Task
// ErrNotConfigured is returned when updating the custom filter list, but it
// is not configured.
ErrNotConfigured = errors.New("custom filter list not configured")
)
func init() {
module = modules.Register("customlists", prep, start, nil, "base")
}
func prep() error {
initFilterLists()
@@ -56,11 +70,10 @@ func prep() error {
// Register api endpoint for updating the filter list.
if err := api.RegisterEndpoint(api.Endpoint{
Path: "customlists/update",
Write: api.PermitUser,
BelongsTo: module,
Path: "customlists/update",
Write: api.PermitUser,
ActionFunc: func(ar *api.Request) (msg string, err error) {
errCheck := checkAndUpdateFilterList()
errCheck := checkAndUpdateFilterList(nil)
if errCheck != nil {
return "", errCheck
}
@@ -77,30 +90,23 @@ func prep() error {
func start() error {
// Register to hook to update after config change.
if err := module.RegisterEventHook(
configModuleName,
configChangeEvent,
module.instance.Config().EventConfigChange.AddCallback(
"update custom filter list",
func(ctx context.Context, obj interface{}) error {
if err := checkAndUpdateFilterList(); !errors.Is(err, ErrNotConfigured) {
return err
func(wc *mgr.WorkerCtx, _ struct{}) (bool, error) {
if err := checkAndUpdateFilterList(wc); !errors.Is(err, ErrNotConfigured) {
return false, err
}
return nil
return false, nil
},
); err != nil {
return err
}
)
// Create parser task and enqueue for execution. "checkAndUpdateFilterList" will schedule the next execution.
parserTask = module.NewTask("intel/customlists:file-update-check", func(context.Context, *modules.Task) error {
_ = checkAndUpdateFilterList()
return nil
}).Schedule(time.Now().Add(20 * time.Second))
module.updateFilterListWorkerMgr.Delay(20 * time.Second).Repeat(1 * time.Minute)
return nil
}
func checkAndUpdateFilterList() error {
func checkAndUpdateFilterList(_ *mgr.WorkerCtx) error {
filterListLock.Lock()
defer filterListLock.Unlock()
@@ -110,9 +116,6 @@ func checkAndUpdateFilterList() error {
return ErrNotConfigured
}
// Schedule next update check
parserTask.Schedule(time.Now().Add(1 * time.Minute))
// Try to get file info
modifiedTime := time.Now()
if fileInfo, err := os.Stat(filePath); err == nil {
@@ -205,3 +208,33 @@ func splitDomain(domain string) []string {
}
return domains
}
var (
module *CustomList
shimLoaded atomic.Bool
)
// New returns a new CustomList module.
func New(instance instance) (*CustomList, error) {
if !shimLoaded.CompareAndSwap(false, true) {
return nil, errors.New("only one instance allowed")
}
m := mgr.New("CustomList")
module = &CustomList{
mgr: m,
instance: instance,
states: mgr.NewStateMgr(m),
updateFilterListWorkerMgr: m.NewWorkerMgr("update custom filter list", checkAndUpdateFilterList, nil),
}
if err := prep(); err != nil {
return nil, err
}
return module, nil
}
type instance interface {
Config() *config.Config
}

View File

@@ -10,7 +10,7 @@ import (
"golang.org/x/net/publicsuffix"
"github.com/safing/portbase/log"
"github.com/safing/portmaster/base/log"
"github.com/safing/portmaster/service/intel/filterlists"
"github.com/safing/portmaster/service/intel/geoip"
"github.com/safing/portmaster/service/network/netutils"

View File

@@ -8,8 +8,8 @@ import (
"github.com/tannerryan/ring"
"github.com/safing/portbase/database/record"
"github.com/safing/portbase/log"
"github.com/safing/portmaster/base/database/record"
"github.com/safing/portmaster/base/log"
)
var defaultFilter = newScopedBloom()

View File

@@ -6,8 +6,8 @@ import (
"github.com/hashicorp/go-version"
"github.com/safing/portbase/database"
"github.com/safing/portbase/database/record"
"github.com/safing/portmaster/base/database"
"github.com/safing/portmaster/base/database/record"
)
const resetVersion = "v0.6.0"

View File

@@ -11,10 +11,10 @@ import (
"golang.org/x/sync/errgroup"
"github.com/safing/portbase/database"
"github.com/safing/portbase/database/record"
"github.com/safing/portbase/log"
"github.com/safing/portbase/updater"
"github.com/safing/portmaster/base/database"
"github.com/safing/portmaster/base/database/record"
"github.com/safing/portmaster/base/log"
"github.com/safing/portmaster/base/updater"
"github.com/safing/portmaster/service/updates"
)

View File

@@ -8,8 +8,8 @@ import (
"fmt"
"io"
"github.com/safing/portbase/formats/dsd"
"github.com/safing/portbase/utils"
"github.com/safing/portmaster/base/utils"
"github.com/safing/structures/dsd"
)
type listEntry struct {

View File

@@ -7,12 +7,12 @@ import (
"strings"
"sync"
"github.com/safing/portbase/database"
"github.com/safing/portbase/database/record"
"github.com/safing/portbase/formats/dsd"
"github.com/safing/portbase/log"
"github.com/safing/portbase/updater"
"github.com/safing/portmaster/base/database"
"github.com/safing/portmaster/base/database/record"
"github.com/safing/portmaster/base/log"
"github.com/safing/portmaster/base/updater"
"github.com/safing/portmaster/service/updates"
"github.com/safing/structures/dsd"
)
// the following definitions are copied from the intelhub repository

View File

@@ -4,8 +4,8 @@ import (
"errors"
"net"
"github.com/safing/portbase/database"
"github.com/safing/portbase/log"
"github.com/safing/portmaster/base/database"
"github.com/safing/portmaster/base/log"
)
// lookupBlockLists loads the entity record for key from

View File

@@ -1,25 +1,50 @@
package filterlists
import (
"context"
"errors"
"fmt"
"sync/atomic"
"github.com/tevino/abool"
"github.com/safing/portbase/log"
"github.com/safing/portbase/modules"
"github.com/safing/portmaster/base/log"
"github.com/safing/portmaster/service/mgr"
"github.com/safing/portmaster/service/netenv"
"github.com/safing/portmaster/service/updates"
)
var module *modules.Module
const (
filterlistsDisabled = "filterlists:disabled"
filterlistsUpdateFailed = "filterlists:update-failed"
filterlistsStaleDataSurvived = "filterlists:staledata"
)
type FilterLists struct {
mgr *mgr.Manager
instance instance
states *mgr.StateMgr
}
func (fl *FilterLists) Manager() *mgr.Manager {
return fl.mgr
}
func (fl *FilterLists) States() *mgr.StateMgr {
return fl.states
}
func (fl *FilterLists) Start() error {
if err := prep(); err != nil {
return err
}
return start()
}
func (fl *FilterLists) Stop() error {
return stop()
}
// booleans mainly used to decouple the module
// during testing.
var (
@@ -29,45 +54,30 @@ var (
func init() {
ignoreNetEnvEvents.Set()
module = modules.Register("filterlists", prep, start, stop, "base", "updates")
}
func prep() error {
if err := module.RegisterEventHook(
updates.ModuleName,
updates.ResourceUpdateEvent,
"Check for blocklist updates",
func(ctx context.Context, _ interface{}) error {
module.instance.Updates().EventResourcesUpdated.AddCallback("Check for blocklist updates",
func(wc *mgr.WorkerCtx, s struct{}) (bool, error) {
if ignoreUpdateEvents.IsSet() {
return nil
return false, nil
}
return tryListUpdate(ctx)
},
); err != nil {
return fmt.Errorf("failed to register resource update event handler: %w", err)
}
return false, tryListUpdate(wc.Ctx())
})
if err := module.RegisterEventHook(
netenv.ModuleName,
netenv.OnlineStatusChangedEvent,
"Check for blocklist updates",
func(ctx context.Context, _ interface{}) error {
module.instance.NetEnv().EventOnlineStatusChange.AddCallback("Check for blocklist updates",
func(wc *mgr.WorkerCtx, s netenv.OnlineStatus) (bool, error) {
if ignoreNetEnvEvents.IsSet() {
return nil
return false, nil
}
// Nothing to do if we went offline.
if !netenv.Online() {
return nil
if s == netenv.StatusOffline {
return false, nil
}
return tryListUpdate(ctx)
},
); err != nil {
return fmt.Errorf("failed to register online status changed event handler: %w", err)
}
return false, tryListUpdate(wc.Ctx())
})
return nil
}
@@ -102,9 +112,35 @@ func stop() error {
}
func warnAboutDisabledFilterLists() {
module.Warning(
filterlistsDisabled,
"Filter Lists Are Initializing",
"Filter lists are being downloaded and set up in the background. They will be activated as configured when finished.",
)
module.states.Add(mgr.State{
ID: filterlistsDisabled,
Name: "Filter Lists Are Initializing",
Message: "Filter lists are being downloaded and set up in the background. They will be activated as configured when finished.",
Type: mgr.StateTypeWarning,
})
}
var (
module *FilterLists
shimLoaded atomic.Bool
)
// New returns a new FilterLists module.
func New(instance instance) (*FilterLists, error) {
if !shimLoaded.CompareAndSwap(false, true) {
return nil, errors.New("only one instance allowed")
}
m := mgr.New("FilterLists")
module = &FilterLists{
mgr: m,
instance: instance,
states: mgr.NewStateMgr(m),
}
return module, nil
}
type instance interface {
Updates() *updates.Updates
NetEnv() *netenv.NetEnv
}

View File

@@ -4,7 +4,7 @@ import (
"fmt"
"sync"
"github.com/safing/portbase/database/record"
"github.com/safing/portmaster/base/database/record"
)
type entityRecord struct {

View File

@@ -10,11 +10,11 @@ import (
"github.com/hashicorp/go-version"
"github.com/tevino/abool"
"github.com/safing/portbase/database"
"github.com/safing/portbase/database/query"
"github.com/safing/portbase/log"
"github.com/safing/portbase/modules"
"github.com/safing/portbase/updater"
"github.com/safing/portmaster/base/database"
"github.com/safing/portmaster/base/database/query"
"github.com/safing/portmaster/base/log"
"github.com/safing/portmaster/base/updater"
"github.com/safing/portmaster/service/mgr"
)
var updateInProgress = abool.New()
@@ -24,20 +24,27 @@ var updateInProgress = abool.New()
func tryListUpdate(ctx context.Context) error {
err := performUpdate(ctx)
if err != nil {
// Check if we are shutting down.
if module.IsStopping() {
// Check if we are shutting down, as to not raise a false alarm.
if module.mgr.IsDone() {
return nil
}
// Check if the module already has a failure status set. If not, set a
// generic one with the returned error.
failureStatus, _, _ := module.FailureStatus()
if failureStatus < modules.FailureWarning {
module.Warning(
filterlistsUpdateFailed,
"Filter Lists Update Failed",
fmt.Sprintf("The Portmaster failed to process a filter lists update. Filtering capabilities are currently either impaired or not available at all. Error: %s", err.Error()),
)
hasWarningState := false
for _, state := range module.states.Export().States {
if state.Type == mgr.StateTypeWarning {
hasWarningState = true
}
}
if !hasWarningState {
module.states.Add(mgr.State{
ID: filterlistsUpdateFailed,
Name: "Filter Lists Update Failed",
Message: fmt.Sprintf("The Portmaster failed to process a filter lists update. Filtering capabilities are currently either impaired or not available at all. Error: %s", err.Error()),
Type: mgr.StateTypeWarning,
})
}
return err
@@ -122,15 +129,16 @@ func performUpdate(ctx context.Context) error {
// been updated now. Once we are done, start a worker
// for that purpose.
if cleanupRequired {
if err := module.RunWorker("filterlists:cleanup", removeAllObsoleteFilterEntries); err != nil {
if err := module.mgr.Do("filterlists:cleanup", removeAllObsoleteFilterEntries); err != nil {
// if we failed to remove all stale cache entries
// we abort now WITHOUT updating the database version. This means
// we'll try again during the next update.
module.Warning(
filterlistsStaleDataSurvived,
"Filter Lists May Overblock",
fmt.Sprintf("The Portmaster failed to delete outdated filter list data. Filtering capabilities are fully available, but overblocking may occur. Error: %s", err.Error()), //nolint:misspell // overblocking != overclocking
)
module.states.Add(mgr.State{
ID: filterlistsStaleDataSurvived,
Name: "Filter Lists May Overblock",
Message: fmt.Sprintf("The Portmaster failed to delete outdated filter list data. Filtering capabilities are fully available, but overblocking may occur. Error: %s", err.Error()), //nolint:misspell // overblocking != overclocking
Type: mgr.StateTypeWarning,
})
return fmt.Errorf("failed to cleanup stale cache records: %w", err)
}
}
@@ -144,13 +152,13 @@ func performUpdate(ctx context.Context) error {
}
// The list update succeeded, resolve any states.
module.Resolve("")
module.states.Clear()
return nil
}
func removeAllObsoleteFilterEntries(ctx context.Context) error {
func removeAllObsoleteFilterEntries(wc *mgr.WorkerCtx) error {
log.Debugf("intel/filterlists: cleanup task started, removing obsolete filter list entries ...")
n, err := cache.Purge(ctx, query.New(filterListKeyPrefix).Where(
n, err := cache.Purge(wc.Ctx(), query.New(filterListKeyPrefix).Where(
// TODO(ppacher): remember the timestamp we started the last update
// and use that rather than "one hour ago"
query.Where("UpdatedAt", query.LessThan, time.Now().Add(-time.Hour).Unix()),

View File

@@ -1,15 +1,15 @@
package geoip
import (
"context"
"fmt"
"sync"
"time"
maxminddb "github.com/oschwald/maxminddb-golang"
"github.com/safing/portbase/log"
"github.com/safing/portbase/updater"
"github.com/safing/portmaster/base/log"
"github.com/safing/portmaster/base/updater"
"github.com/safing/portmaster/service/mgr"
"github.com/safing/portmaster/service/updates"
)
@@ -148,11 +148,11 @@ func (upd *updateWorker) triggerUpdate() {
func (upd *updateWorker) start() {
upd.once.Do(func() {
module.StartServiceWorker("geoip-updater", time.Second*10, upd.run)
module.mgr.Go("geoip-updater", upd.run)
})
}
func (upd *updateWorker) run(ctx context.Context) error {
func (upd *updateWorker) run(ctx *mgr.WorkerCtx) error {
for {
if upd.v4.NeedsUpdate() {
if v4, err := getGeoIPDB(v4MMDBResource); err == nil {

View File

@@ -0,0 +1,109 @@
package geoip
import (
"fmt"
"os"
"testing"
"github.com/safing/portmaster/base/api"
"github.com/safing/portmaster/base/config"
"github.com/safing/portmaster/base/database/dbmodule"
"github.com/safing/portmaster/base/notifications"
"github.com/safing/portmaster/service/updates"
)
type testInstance struct {
db *dbmodule.DBModule
api *api.API
config *config.Config
updates *updates.Updates
}
var _ instance = &testInstance{}
func (stub *testInstance) Updates() *updates.Updates {
return stub.updates
}
func (stub *testInstance) API() *api.API {
return stub.api
}
func (stub *testInstance) Config() *config.Config {
return stub.config
}
func (stub *testInstance) Notifications() *notifications.Notifications {
return nil
}
func (stub *testInstance) Ready() bool {
return true
}
func (stub *testInstance) Restart() {}
func (stub *testInstance) Shutdown() {}
func (stub *testInstance) SetCmdLineOperation(f func() error) {}
func runTest(m *testing.M) error {
api.SetDefaultAPIListenAddress("0.0.0.0:8080")
ds, err := config.InitializeUnitTestDataroot("test-geoip")
if err != nil {
return fmt.Errorf("failed to initialize dataroot: %w", err)
}
defer func() { _ = os.RemoveAll(ds) }()
stub := &testInstance{}
stub.db, err = dbmodule.New(stub)
if err != nil {
return fmt.Errorf("failed to create database: %w", err)
}
stub.config, err = config.New(stub)
if err != nil {
return fmt.Errorf("failed to create config: %w", err)
}
stub.api, err = api.New(stub)
if err != nil {
return fmt.Errorf("failed to create api: %w", err)
}
stub.updates, err = updates.New(stub)
if err != nil {
return fmt.Errorf("failed to create updates: %w", err)
}
module, err = New(stub)
if err != nil {
return fmt.Errorf("failed to initialize module: %w", err)
}
err = stub.db.Start()
if err != nil {
return fmt.Errorf("Failed to start database: %w", err)
}
err = stub.config.Start()
if err != nil {
return fmt.Errorf("Failed to start config: %w", err)
}
err = stub.api.Start()
if err != nil {
return fmt.Errorf("Failed to start api: %w", err)
}
err = stub.updates.Start()
if err != nil {
return fmt.Errorf("Failed to start updates: %w", err)
}
err = module.Start()
if err != nil {
return fmt.Errorf("failed to start module: %w", err)
}
m.Run()
return nil
}
func TestMain(m *testing.M) {
if err := runTest(m); err != nil {
fmt.Printf("%s\n", err)
os.Exit(1)
}
}

View File

@@ -7,7 +7,7 @@ import (
"github.com/umahmood/haversine"
"github.com/safing/portbase/utils"
"github.com/safing/portmaster/base/utils"
)
const (

View File

@@ -3,6 +3,7 @@ package geoip
import (
"net"
"testing"
"time"
)
func TestLocationLookup(t *testing.T) {
@@ -12,6 +13,17 @@ func TestLocationLookup(t *testing.T) {
}
t.Parallel()
// Wait for db to be initialized
worker.v4.rw.Lock()
waiter := worker.v4.getWaiter()
worker.v4.rw.Unlock()
worker.triggerUpdate()
select {
case <-waiter:
case <-time.After(15 * time.Second):
}
ip1 := net.ParseIP("81.2.69.142")
loc1, err := GetLocation(ip1)
if err != nil {

View File

@@ -1,20 +1,54 @@
package geoip
import (
"context"
"errors"
"sync/atomic"
"github.com/safing/portbase/api"
"github.com/safing/portbase/modules"
"github.com/safing/portmaster/base/api"
"github.com/safing/portmaster/service/mgr"
"github.com/safing/portmaster/service/updates"
)
var module *modules.Module
func init() {
module = modules.Register("geoip", prep, nil, nil, "base", "updates")
type GeoIP struct {
mgr *mgr.Manager
instance instance
}
func prep() error {
func (g *GeoIP) Manager() *mgr.Manager {
return g.mgr
}
func (g *GeoIP) Start() error {
module.instance.Updates().EventResourcesUpdated.AddCallback(
"Check for GeoIP database updates",
func(_ *mgr.WorkerCtx, _ struct{}) (bool, error) {
worker.triggerUpdate()
return false, nil
})
return nil
}
func (g *GeoIP) Stop() error {
return nil
}
var (
module *GeoIP
shimLoaded atomic.Bool
)
// New returns a new GeoIP module.
func New(instance instance) (*GeoIP, error) {
if !shimLoaded.CompareAndSwap(false, true) {
return nil, errors.New("only one instance allowed")
}
m := mgr.New("geoip")
module = &GeoIP{
mgr: m,
instance: instance,
}
if err := api.RegisterEndpoint(api.Endpoint{
Path: "intel/geoip/countries",
Read: api.PermitUser,
@@ -25,16 +59,12 @@ func prep() error {
Name: "Get Country Information",
Description: "Returns a map of country information centers indexed by ISO-A2 country code",
}); err != nil {
return err
return nil, err
}
return module.RegisterEventHook(
updates.ModuleName,
updates.ResourceUpdateEvent,
"Check for GeoIP database updates",
func(c context.Context, i interface{}) error {
worker.triggerUpdate()
return nil
},
)
return module, nil
}
type instance interface {
Updates() *updates.Updates
}

View File

@@ -1,11 +0,0 @@
package geoip
import (
"testing"
"github.com/safing/portmaster/service/core/pmtesting"
)
func TestMain(m *testing.M) {
pmtesting.TestMain(m, module)
}

View File

@@ -1,7 +1,7 @@
package geoip
import (
"github.com/safing/portbase/utils"
"github.com/safing/portmaster/base/utils"
)
// IsRegionalNeighbor returns whether the supplied location is a regional neighbor.

View File

@@ -3,7 +3,7 @@ package geoip
import (
"testing"
"github.com/safing/portbase/utils"
"github.com/safing/portmaster/base/utils"
)
func TestRegions(t *testing.T) {

View File

@@ -1,13 +0,0 @@
package intel
import (
"github.com/safing/portbase/modules"
_ "github.com/safing/portmaster/service/intel/customlists"
)
// Module of this package. Export needed for testing of the endpoints package.
var Module *modules.Module
func init() {
Module = modules.Register("intel", nil, nil, nil, "geoip", "filterlists", "customlists")
}