chore(all): Providers containing all provider objects

- Share the same providers for updater and vpn
- Initialise all providers at start
- Get from `Providers` instead of constructing on every run
This commit is contained in:
Quentin McGaw
2022-06-10 00:47:56 +00:00
parent ebd94723c1
commit 0378fe4a7b
9 changed files with 136 additions and 112 deletions

View File

@@ -31,6 +31,7 @@ import (
"github.com/qdm12/gluetun/internal/openvpn" "github.com/qdm12/gluetun/internal/openvpn"
"github.com/qdm12/gluetun/internal/portforward" "github.com/qdm12/gluetun/internal/portforward"
"github.com/qdm12/gluetun/internal/pprof" "github.com/qdm12/gluetun/internal/pprof"
"github.com/qdm12/gluetun/internal/provider"
"github.com/qdm12/gluetun/internal/publicip" "github.com/qdm12/gluetun/internal/publicip"
"github.com/qdm12/gluetun/internal/routing" "github.com/qdm12/gluetun/internal/routing"
"github.com/qdm12/gluetun/internal/server" "github.com/qdm12/gluetun/internal/server"
@@ -38,6 +39,7 @@ import (
"github.com/qdm12/gluetun/internal/storage" "github.com/qdm12/gluetun/internal/storage"
"github.com/qdm12/gluetun/internal/tun" "github.com/qdm12/gluetun/internal/tun"
updater "github.com/qdm12/gluetun/internal/updater/loop" updater "github.com/qdm12/gluetun/internal/updater/loop"
"github.com/qdm12/gluetun/internal/updater/unzip"
"github.com/qdm12/gluetun/internal/vpn" "github.com/qdm12/gluetun/internal/vpn"
"github.com/qdm12/golibs/command" "github.com/qdm12/golibs/command"
"github.com/qdm12/goshutdown" "github.com/qdm12/goshutdown"
@@ -374,9 +376,14 @@ func _main(ctx context.Context, buildInfo models.BuildInformation,
go publicIPLooper.RunRestartTicker(pubIPTickerCtx, pubIPTickerDone) go publicIPLooper.RunRestartTicker(pubIPTickerCtx, pubIPTickerDone)
tickersGroupHandler.Add(pubIPTickerHandler) tickersGroupHandler.Add(pubIPTickerHandler)
updaterLogger := logger.New(log.SetComponent("updater"))
unzipper := unzip.New(httpClient)
providers := provider.NewProviders(storage, time.Now, updaterLogger, httpClient, unzipper)
vpnLogger := logger.New(log.SetComponent("vpn")) vpnLogger := logger.New(log.SetComponent("vpn"))
vpnLooper := vpn.NewLoop(allSettings.VPN, allSettings.Firewall.VPNInputPorts, vpnLooper := vpn.NewLoop(allSettings.VPN, allSettings.Firewall.VPNInputPorts,
storage, ovpnConf, netLinker, firewallConf, routingConf, portForwardLooper, providers, storage, ovpnConf, netLinker, firewallConf, routingConf, portForwardLooper,
cmder, publicIPLooper, unboundLooper, vpnLogger, httpClient, cmder, publicIPLooper, unboundLooper, vpnLogger, httpClient,
buildInfo, *allSettings.Version.Enabled) buildInfo, *allSettings.Version.Enabled)
vpnHandler, vpnCtx, vpnDone := goshutdown.NewGoRoutineHandler( vpnHandler, vpnCtx, vpnDone := goshutdown.NewGoRoutineHandler(
@@ -384,7 +391,7 @@ func _main(ctx context.Context, buildInfo models.BuildInformation,
go vpnLooper.Run(vpnCtx, vpnDone) go vpnLooper.Run(vpnCtx, vpnDone)
updaterLooper := updater.NewLooper(allSettings.Updater, updaterLooper := updater.NewLooper(allSettings.Updater,
storage, httpClient, logger.New(log.SetComponent("updater"))) providers, storage, httpClient, updaterLogger)
updaterHandler, updaterCtx, updaterDone := goshutdown.NewGoRoutineHandler( updaterHandler, updaterCtx, updaterDone := goshutdown.NewGoRoutineHandler(
"updater", goroutine.OptionTimeout(defaultShutdownTimeout)) "updater", goroutine.OptionTimeout(defaultShutdownTimeout))
// wait for updaterLooper.Restart() or its ticket launched with RunRestartTicker // wait for updaterLooper.Restart() or its ticket launched with RunRestartTicker

View File

@@ -42,8 +42,8 @@ func (c *CLI) OpenvpnConfig(logger OpenvpnConfigLogger, source sources.Source) e
client := (*http.Client)(nil) client := (*http.Client)(nil)
warner := (Warner)(nil) warner := (Warner)(nil)
providerConf := provider.New(*allSettings.VPN.Provider.Name, storage, time.Now, providers := provider.NewProviders(storage, time.Now, warner, client, unzipper)
warner, client, unzipper) providerConf := providers.Get(*allSettings.VPN.Provider.Name)
connection, err := providerConf.GetConnection(allSettings.VPN.Provider.ServerSelection) connection, err := providerConf.GetConnection(allSettings.VPN.Provider.ServerSelection)
if err != nil { if err != nil {
return err return err

View File

@@ -13,8 +13,10 @@ import (
"github.com/qdm12/gluetun/internal/configuration/settings" "github.com/qdm12/gluetun/internal/configuration/settings"
"github.com/qdm12/gluetun/internal/constants" "github.com/qdm12/gluetun/internal/constants"
"github.com/qdm12/gluetun/internal/constants/providers" "github.com/qdm12/gluetun/internal/constants/providers"
"github.com/qdm12/gluetun/internal/provider"
"github.com/qdm12/gluetun/internal/storage" "github.com/qdm12/gluetun/internal/storage"
"github.com/qdm12/gluetun/internal/updater" "github.com/qdm12/gluetun/internal/updater"
"github.com/qdm12/gluetun/internal/updater/unzip"
) )
var ( var (
@@ -81,7 +83,11 @@ func (c *CLI) Update(ctx context.Context, args []string, logger UpdaterLogger) e
return fmt.Errorf("cannot create servers storage: %w", err) return fmt.Errorf("cannot create servers storage: %w", err)
} }
updater := updater.New(httpClient, storage, logger) unzipper := unzip.New(httpClient)
providers := provider.NewProviders(storage, time.Now, logger, httpClient, unzipper)
updater := updater.New(httpClient, storage, providers, logger)
err = updater.UpdateServers(ctx, options.Providers) err = updater.UpdateServers(ctx, options.Providers)
if err != nil { if err != nil {
return fmt.Errorf("cannot update server information: %w", err) return fmt.Errorf("cannot update server information: %w", err)

View File

@@ -3,37 +3,12 @@ package provider
import ( import (
"context" "context"
"math/rand"
"net" "net"
"net/http" "net/http"
"time"
"github.com/qdm12/gluetun/internal/configuration/settings" "github.com/qdm12/gluetun/internal/configuration/settings"
"github.com/qdm12/gluetun/internal/constants/providers"
"github.com/qdm12/gluetun/internal/models" "github.com/qdm12/gluetun/internal/models"
"github.com/qdm12/gluetun/internal/provider/common"
"github.com/qdm12/gluetun/internal/provider/custom"
"github.com/qdm12/gluetun/internal/provider/cyberghost"
"github.com/qdm12/gluetun/internal/provider/expressvpn"
"github.com/qdm12/gluetun/internal/provider/fastestvpn"
"github.com/qdm12/gluetun/internal/provider/hidemyass"
"github.com/qdm12/gluetun/internal/provider/ipvanish"
"github.com/qdm12/gluetun/internal/provider/ivpn"
"github.com/qdm12/gluetun/internal/provider/mullvad"
"github.com/qdm12/gluetun/internal/provider/nordvpn"
"github.com/qdm12/gluetun/internal/provider/perfectprivacy"
"github.com/qdm12/gluetun/internal/provider/privado"
"github.com/qdm12/gluetun/internal/provider/privateinternetaccess"
"github.com/qdm12/gluetun/internal/provider/privatevpn"
"github.com/qdm12/gluetun/internal/provider/protonvpn"
"github.com/qdm12/gluetun/internal/provider/purevpn"
"github.com/qdm12/gluetun/internal/provider/surfshark"
"github.com/qdm12/gluetun/internal/provider/torguard"
"github.com/qdm12/gluetun/internal/provider/utils" "github.com/qdm12/gluetun/internal/provider/utils"
"github.com/qdm12/gluetun/internal/provider/vpnunlimited"
"github.com/qdm12/gluetun/internal/provider/vyprvpn"
"github.com/qdm12/gluetun/internal/provider/wevpn"
"github.com/qdm12/gluetun/internal/provider/windscribe"
) )
// Provider contains methods to read and modify the openvpn configuration to connect as a client. // Provider contains methods to read and modify the openvpn configuration to connect as a client.
@@ -53,60 +28,3 @@ type PortForwarder interface {
KeepPortForward(ctx context.Context, client *http.Client, KeepPortForward(ctx context.Context, client *http.Client,
port uint16, gateway net.IP, serverName string) (err error) port uint16, gateway net.IP, serverName string) (err error)
} }
type Storage interface {
FilterServers(provider string, selection settings.ServerSelection) (
servers []models.Server, err error)
GetServerByName(provider, name string) (server models.Server, ok bool)
}
func New(provider string, storage Storage, timeNow func() time.Time,
updaterWarner common.Warner, client *http.Client, unzipper common.Unzipper) Provider {
randSource := rand.NewSource(timeNow().UnixNano())
switch provider {
case providers.Custom:
return custom.New()
case providers.Cyberghost:
return cyberghost.New(storage, randSource)
case providers.Expressvpn:
return expressvpn.New(storage, randSource, unzipper, updaterWarner)
case providers.Fastestvpn:
return fastestvpn.New(storage, randSource, unzipper, updaterWarner)
case providers.HideMyAss:
return hidemyass.New(storage, randSource, client, updaterWarner)
case providers.Ipvanish:
return ipvanish.New(storage, randSource, unzipper, updaterWarner)
case providers.Ivpn:
return ivpn.New(storage, randSource, client, updaterWarner)
case providers.Mullvad:
return mullvad.New(storage, randSource, client)
case providers.Nordvpn:
return nordvpn.New(storage, randSource, client, updaterWarner)
case providers.Perfectprivacy:
return perfectprivacy.New(storage, randSource, unzipper, updaterWarner)
case providers.Privado:
return privado.New(storage, randSource, client, unzipper, updaterWarner)
case providers.PrivateInternetAccess:
return privateinternetaccess.New(storage, randSource, timeNow, client)
case providers.Privatevpn:
return privatevpn.New(storage, randSource, unzipper, updaterWarner)
case providers.Protonvpn:
return protonvpn.New(storage, randSource, client, updaterWarner)
case providers.Purevpn:
return purevpn.New(storage, randSource, client, unzipper, updaterWarner)
case providers.Surfshark:
return surfshark.New(storage, randSource, client, unzipper, updaterWarner)
case providers.Torguard:
return torguard.New(storage, randSource, unzipper, updaterWarner)
case providers.VPNUnlimited:
return vpnunlimited.New(storage, randSource, unzipper, updaterWarner)
case providers.Vyprvpn:
return vyprvpn.New(storage, randSource, unzipper, updaterWarner)
case providers.Wevpn:
return wevpn.New(storage, randSource, updaterWarner)
case providers.Windscribe:
return windscribe.New(storage, randSource, client, updaterWarner)
default:
panic("provider " + provider + " is unknown") // should never occur
}
}

View File

@@ -0,0 +1,91 @@
package provider
import (
"fmt"
"math/rand"
"net/http"
"time"
"github.com/qdm12/gluetun/internal/configuration/settings"
"github.com/qdm12/gluetun/internal/constants/providers"
"github.com/qdm12/gluetun/internal/models"
"github.com/qdm12/gluetun/internal/provider/common"
"github.com/qdm12/gluetun/internal/provider/custom"
"github.com/qdm12/gluetun/internal/provider/cyberghost"
"github.com/qdm12/gluetun/internal/provider/expressvpn"
"github.com/qdm12/gluetun/internal/provider/fastestvpn"
"github.com/qdm12/gluetun/internal/provider/hidemyass"
"github.com/qdm12/gluetun/internal/provider/ipvanish"
"github.com/qdm12/gluetun/internal/provider/ivpn"
"github.com/qdm12/gluetun/internal/provider/mullvad"
"github.com/qdm12/gluetun/internal/provider/nordvpn"
"github.com/qdm12/gluetun/internal/provider/perfectprivacy"
"github.com/qdm12/gluetun/internal/provider/privado"
"github.com/qdm12/gluetun/internal/provider/privateinternetaccess"
"github.com/qdm12/gluetun/internal/provider/privatevpn"
"github.com/qdm12/gluetun/internal/provider/protonvpn"
"github.com/qdm12/gluetun/internal/provider/purevpn"
"github.com/qdm12/gluetun/internal/provider/surfshark"
"github.com/qdm12/gluetun/internal/provider/torguard"
"github.com/qdm12/gluetun/internal/provider/vpnunlimited"
"github.com/qdm12/gluetun/internal/provider/vyprvpn"
"github.com/qdm12/gluetun/internal/provider/wevpn"
"github.com/qdm12/gluetun/internal/provider/windscribe"
)
type Providers struct {
providerNameToProvider map[string]Provider
}
type Storage interface {
FilterServers(provider string, selection settings.ServerSelection) (
servers []models.Server, err error)
GetServerByName(provider, name string) (server models.Server, ok bool)
}
func NewProviders(storage Storage, timeNow func() time.Time,
updaterWarner common.Warner, client *http.Client, unzipper common.Unzipper) *Providers {
randSource := rand.NewSource(timeNow().UnixNano())
targetLength := len(providers.AllWithCustom())
providerNameToProvider := make(map[string]Provider, targetLength)
providerNameToProvider[providers.Custom] = custom.New()
providerNameToProvider[providers.Cyberghost] = cyberghost.New(storage, randSource)
providerNameToProvider[providers.Expressvpn] = expressvpn.New(storage, randSource, unzipper, updaterWarner)
providerNameToProvider[providers.Fastestvpn] = fastestvpn.New(storage, randSource, unzipper, updaterWarner)
providerNameToProvider[providers.HideMyAss] = hidemyass.New(storage, randSource, client, updaterWarner)
providerNameToProvider[providers.Ipvanish] = ipvanish.New(storage, randSource, unzipper, updaterWarner)
providerNameToProvider[providers.Ivpn] = ivpn.New(storage, randSource, client, updaterWarner)
providerNameToProvider[providers.Mullvad] = mullvad.New(storage, randSource, client)
providerNameToProvider[providers.Nordvpn] = nordvpn.New(storage, randSource, client, updaterWarner)
providerNameToProvider[providers.Perfectprivacy] = perfectprivacy.New(storage, randSource, unzipper, updaterWarner)
providerNameToProvider[providers.Privado] = privado.New(storage, randSource, client, unzipper, updaterWarner)
providerNameToProvider[providers.PrivateInternetAccess] = privateinternetaccess.New(storage, randSource, timeNow, client) //nolint:lll
providerNameToProvider[providers.Privatevpn] = privatevpn.New(storage, randSource, unzipper, updaterWarner)
providerNameToProvider[providers.Protonvpn] = protonvpn.New(storage, randSource, client, updaterWarner)
providerNameToProvider[providers.Purevpn] = purevpn.New(storage, randSource, client, unzipper, updaterWarner)
providerNameToProvider[providers.Surfshark] = surfshark.New(storage, randSource, client, unzipper, updaterWarner)
providerNameToProvider[providers.Torguard] = torguard.New(storage, randSource, unzipper, updaterWarner)
providerNameToProvider[providers.VPNUnlimited] = vpnunlimited.New(storage, randSource, unzipper, updaterWarner)
providerNameToProvider[providers.Vyprvpn] = vyprvpn.New(storage, randSource, unzipper, updaterWarner)
providerNameToProvider[providers.Wevpn] = wevpn.New(storage, randSource, updaterWarner)
providerNameToProvider[providers.Windscribe] = windscribe.New(storage, randSource, client, updaterWarner)
if len(providerNameToProvider) != targetLength {
// Programming sanity check
panic(fmt.Sprintf("invalid number of providers, expected %d but got %d",
targetLength, len(providerNameToProvider)))
}
return &Providers{
providerNameToProvider: providerNameToProvider,
}
}
func (p *Providers) Get(providerName string) (provider Provider) {
provider, ok := p.providerNameToProvider[providerName]
if !ok {
panic(fmt.Sprintf("provider %q not found", providerName))
}
return provider
}

View File

@@ -52,14 +52,14 @@ type Logger interface {
Error(s string) Error(s string)
} }
func NewLooper(settings settings.Updater, storage updater.Storage, func NewLooper(settings settings.Updater, providers updater.Providers,
client *http.Client, logger Logger) Looper { storage updater.Storage, client *http.Client, logger Logger) Looper {
return &looper{ return &looper{
state: state{ state: state{
status: constants.Stopped, status: constants.Stopped,
settings: settings, settings: settings,
}, },
updater: updater.New(client, storage, logger), updater: updater.New(client, storage, providers, logger),
logger: logger, logger: logger,
start: make(chan struct{}), start: make(chan struct{}),
running: make(chan models.LoopStatus), running: make(chan models.LoopStatus),

View File

@@ -15,6 +15,8 @@ import (
) )
type Updater struct { type Updater struct {
providers Providers
// state // state
storage Storage storage Storage
@@ -25,6 +27,10 @@ type Updater struct {
unzipper unzip.Unzipper unzipper unzip.Unzipper
} }
type Providers interface {
Get(providerName string) provider.Provider
}
type Storage interface { type Storage interface {
SetServers(provider string, servers []models.Server) (err error) SetServers(provider string, servers []models.Server) (err error)
GetServersCount(provider string) (count int) GetServersCount(provider string) (count int)
@@ -40,10 +46,11 @@ type Logger interface {
Error(s string) Error(s string)
} }
func New(httpClient *http.Client, func New(httpClient *http.Client, storage Storage,
storage Storage, logger Logger) *Updater { providers Providers, logger Logger) *Updater {
unzipper := unzip.New(httpClient) unzipper := unzip.New(httpClient)
return &Updater{ return &Updater{
providers: providers,
storage: storage, storage: storage,
logger: logger, logger: logger,
timeNow: time.Now, timeNow: time.Now,
@@ -57,9 +64,7 @@ func (u *Updater) UpdateServers(ctx context.Context, providers []string) (err er
for _, providerName := range providers { for _, providerName := range providers {
u.logger.Info("updating " + caser.String(providerName) + " servers...") u.logger.Info("updating " + caser.String(providerName) + " servers...")
fetcherStorage := (Storage)(nil) // unused fetcher := u.providers.Get(providerName)
fetcher := provider.New(providerName, fetcherStorage, u.timeNow,
u.logger, u.client, u.unzipper)
// TODO support servers offering only TCP or only UDP // TODO support servers offering only TCP or only UDP
// for NordVPN and PureVPN // for NordVPN and PureVPN
err := u.updateProvider(ctx, fetcher) err := u.updateProvider(ctx, fetcher)

View File

@@ -13,6 +13,7 @@ import (
"github.com/qdm12/gluetun/internal/netlink" "github.com/qdm12/gluetun/internal/netlink"
"github.com/qdm12/gluetun/internal/openvpn" "github.com/qdm12/gluetun/internal/openvpn"
"github.com/qdm12/gluetun/internal/portforward" "github.com/qdm12/gluetun/internal/portforward"
"github.com/qdm12/gluetun/internal/provider"
"github.com/qdm12/gluetun/internal/publicip" "github.com/qdm12/gluetun/internal/publicip"
"github.com/qdm12/gluetun/internal/routing" "github.com/qdm12/gluetun/internal/routing"
"github.com/qdm12/gluetun/internal/vpn/state" "github.com/qdm12/gluetun/internal/vpn/state"
@@ -32,6 +33,7 @@ type Looper interface {
type Loop struct { type Loop struct {
statusManager loopstate.Manager statusManager loopstate.Manager
state state.Manager state state.Manager
providers Providers
storage Storage storage Storage
// Fixed parameters // Fixed parameters
buildInfo models.BuildInformation buildInfo models.BuildInformation
@@ -64,6 +66,10 @@ type firewallConfigurer interface {
firewall.PortAllower firewall.PortAllower
} }
type Providers interface {
Get(providerName string) provider.Provider
}
type Storage interface { type Storage interface {
FilterServers(provider string, selection settings.ServerSelection) (servers []models.Server, err error) FilterServers(provider string, selection settings.ServerSelection) (servers []models.Server, err error)
GetServerByName(provider, name string) (server models.Server, ok bool) GetServerByName(provider, name string) (server models.Server, ok bool)
@@ -74,7 +80,7 @@ const (
) )
func NewLoop(vpnSettings settings.VPN, vpnInputPorts []uint16, func NewLoop(vpnSettings settings.VPN, vpnInputPorts []uint16,
storage Storage, openvpnConf openvpn.Interface, providers Providers, storage Storage, openvpnConf openvpn.Interface,
netLinker netlink.NetLinker, fw firewallConfigurer, routing routing.VPNGetter, netLinker netlink.NetLinker, fw firewallConfigurer, routing routing.VPNGetter,
portForward portforward.StartStopper, starter command.Starter, portForward portforward.StartStopper, starter command.Starter,
publicip publicip.Looper, dnsLooper dns.Looper, publicip publicip.Looper, dnsLooper dns.Looper,
@@ -91,6 +97,7 @@ func NewLoop(vpnSettings settings.VPN, vpnInputPorts []uint16,
return &Loop{ return &Loop{
statusManager: statusManager, statusManager: statusManager,
state: state, state: state,
providers: providers,
storage: storage, storage: storage,
buildInfo: buildInfo, buildInfo: buildInfo,
versionInfo: versionInfo, versionInfo: versionInfo,

View File

@@ -2,13 +2,9 @@ package vpn
import ( import (
"context" "context"
"net/http"
"time"
"github.com/qdm12/gluetun/internal/constants" "github.com/qdm12/gluetun/internal/constants"
"github.com/qdm12/gluetun/internal/constants/vpn" "github.com/qdm12/gluetun/internal/constants/vpn"
"github.com/qdm12/gluetun/internal/provider"
"github.com/qdm12/gluetun/internal/updater/unzip"
"github.com/qdm12/log" "github.com/qdm12/log"
) )
@@ -29,16 +25,10 @@ func (l *Loop) Run(ctx context.Context, done chan<- struct{}) {
return return
} }
// Updater only objects which are unused in this loop
updaterWarner := (log.LoggerInterface)(nil)
updaterClient := (*http.Client)(nil)
updaterUnzipper := (unzip.Unzipper)(nil)
for ctx.Err() == nil { for ctx.Err() == nil {
settings := l.state.GetSettings() settings := l.state.GetSettings()
providerConf := provider.New(*settings.Provider.Name, l.storage, time.Now, providerConf := l.providers.Get(*settings.Provider.Name)
updaterWarner, updaterClient, updaterUnzipper)
portForwarding := *settings.Provider.PortForwarding.Enabled portForwarding := *settings.Provider.PortForwarding.Enabled
var vpnRunner vpnRunner var vpnRunner vpnRunner