chore(updater): create resolver in provider updater

- Pass min servers to resolve call
- Set settings when constructing resolver
- Construct resolver in each provider updater
- No more common resolver for all providers
This commit is contained in:
Quentin McGaw
2022-06-09 02:54:39 +00:00
parent e37f557cd5
commit 415cb7a945
53 changed files with 155 additions and 483 deletions

View File

@@ -1,16 +1,12 @@
package cyberghost package cyberghost
import ( import (
"context"
"net"
"time" "time"
"github.com/qdm12/gluetun/internal/updater/resolver" "github.com/qdm12/gluetun/internal/updater/resolver"
) )
func resolveHosts(ctx context.Context, presolver resolver.Parallel, func newParallelResolver() (parallelResolver resolver.Parallel) {
possibleHosts []string, minServers int) (
hostToIPs map[string][]net.IP, err error) {
const ( const (
maxFailRatio = 1 maxFailRatio = 1
maxDuration = 20 * time.Second maxDuration = 20 * time.Second
@@ -20,7 +16,6 @@ func resolveHosts(ctx context.Context, presolver resolver.Parallel,
) )
settings := resolver.ParallelSettings{ settings := resolver.ParallelSettings{
MaxFailRatio: maxFailRatio, MaxFailRatio: maxFailRatio,
MinFound: minServers,
Repeat: resolver.RepeatSettings{ Repeat: resolver.RepeatSettings{
MaxDuration: maxDuration, MaxDuration: maxDuration,
BetweenDuration: betweenDuration, BetweenDuration: betweenDuration,
@@ -29,10 +24,5 @@ func resolveHosts(ctx context.Context, presolver resolver.Parallel,
SortIPs: true, SortIPs: true,
}, },
} }
hostToIPs, _, err = presolver.Resolve(ctx, possibleHosts, settings) return resolver.NewParallelResolver(settings)
if err != nil {
return nil, err
}
return hostToIPs, nil
} }

View File

@@ -14,7 +14,7 @@ func (u *Updater) FetchServers(ctx context.Context, minServers int) (
possibleServers := getPossibleServers() possibleServers := getPossibleServers()
possibleHosts := possibleServers.hostsSlice() possibleHosts := possibleServers.hostsSlice()
hostToIPs, err := resolveHosts(ctx, u.presolver, possibleHosts, minServers) hostToIPs, _, err := u.presolver.Resolve(ctx, possibleHosts, minServers)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -6,8 +6,8 @@ type Updater struct {
presolver resolver.Parallel presolver resolver.Parallel
} }
func New(presolver resolver.Parallel) *Updater { func New() *Updater {
return &Updater{ return &Updater{
presolver: presolver, presolver: newParallelResolver(),
} }
} }

View File

@@ -1,16 +1,12 @@
package expressvpn package expressvpn
import ( import (
"context"
"net"
"time" "time"
"github.com/qdm12/gluetun/internal/updater/resolver" "github.com/qdm12/gluetun/internal/updater/resolver"
) )
func resolveHosts(ctx context.Context, presolver resolver.Parallel, func newParallelResolver() resolver.Parallel {
hosts []string, minServers int) (hostToIPs map[string][]net.IP,
warnings []string, err error) {
const ( const (
maxFailRatio = 0.1 maxFailRatio = 0.1
maxNoNew = 1 maxNoNew = 1
@@ -18,7 +14,6 @@ func resolveHosts(ctx context.Context, presolver resolver.Parallel,
) )
settings := resolver.ParallelSettings{ settings := resolver.ParallelSettings{
MaxFailRatio: maxFailRatio, MaxFailRatio: maxFailRatio,
MinFound: minServers,
Repeat: resolver.RepeatSettings{ Repeat: resolver.RepeatSettings{
MaxDuration: time.Second, MaxDuration: time.Second,
MaxNoNew: maxNoNew, MaxNoNew: maxNoNew,
@@ -26,5 +21,5 @@ func resolveHosts(ctx context.Context, presolver resolver.Parallel,
SortIPs: true, SortIPs: true,
}, },
} }
return presolver.Resolve(ctx, hosts, settings) return resolver.NewParallelResolver(settings)
} }

View File

@@ -21,7 +21,7 @@ func (u *Updater) FetchServers(ctx context.Context, minServers int) (
hosts[i] = servers[i].Hostname hosts[i] = servers[i].Hostname
} }
hostToIPs, warnings, err := resolveHosts(ctx, u.presolver, hosts, minServers) hostToIPs, warnings, err := u.presolver.Resolve(ctx, hosts, minServers)
for _, warning := range warnings { for _, warning := range warnings {
u.warner.Warn(warning) u.warner.Warn(warning)
} }

View File

@@ -15,11 +15,10 @@ type Warner interface {
Warn(s string) Warn(s string)
} }
func New(unzipper unzip.Unzipper, presolver resolver.Parallel, func New(unzipper unzip.Unzipper, warner Warner) *Updater {
warner Warner) *Updater {
return &Updater{ return &Updater{
unzipper: unzipper, unzipper: unzipper,
presolver: presolver, presolver: newParallelResolver(),
warner: warner, warner: warner,
} }
} }

View File

@@ -1,16 +1,12 @@
package fastestvpn package fastestvpn
import ( import (
"context"
"net"
"time" "time"
"github.com/qdm12/gluetun/internal/updater/resolver" "github.com/qdm12/gluetun/internal/updater/resolver"
) )
func resolveHosts(ctx context.Context, presolver resolver.Parallel, func newParallelResolver() resolver.Parallel {
hosts []string, minServers int) (hostToIPs map[string][]net.IP,
warnings []string, err error) {
const ( const (
maxFailRatio = 0.1 maxFailRatio = 0.1
maxNoNew = 1 maxNoNew = 1
@@ -18,7 +14,6 @@ func resolveHosts(ctx context.Context, presolver resolver.Parallel,
) )
settings := resolver.ParallelSettings{ settings := resolver.ParallelSettings{
MaxFailRatio: maxFailRatio, MaxFailRatio: maxFailRatio,
MinFound: minServers,
Repeat: resolver.RepeatSettings{ Repeat: resolver.RepeatSettings{
MaxDuration: time.Second, MaxDuration: time.Second,
MaxNoNew: maxNoNew, MaxNoNew: maxNoNew,
@@ -26,5 +21,5 @@ func resolveHosts(ctx context.Context, presolver resolver.Parallel,
SortIPs: true, SortIPs: true,
}, },
} }
return presolver.Resolve(ctx, hosts, settings) return resolver.NewParallelResolver(settings)
} }

View File

@@ -56,7 +56,7 @@ func (u *Updater) FetchServers(ctx context.Context, minServers int) (
} }
hosts := hts.toHostsSlice() hosts := hts.toHostsSlice()
hostToIPs, warnings, err := resolveHosts(ctx, u.presolver, hosts, minServers) hostToIPs, warnings, err := u.presolver.Resolve(ctx, hosts, minServers)
for _, warning := range warnings { for _, warning := range warnings {
u.warner.Warn(warning) u.warner.Warn(warning)
} }

View File

@@ -15,11 +15,10 @@ type Warner interface {
Warn(s string) Warn(s string)
} }
func New(unzipper unzip.Unzipper, presolver resolver.Parallel, func New(unzipper unzip.Unzipper, warner Warner) *Updater {
warner Warner) *Updater {
return &Updater{ return &Updater{
unzipper: unzipper, unzipper: unzipper,
presolver: presolver, presolver: newParallelResolver(),
warner: warner, warner: warner,
} }
} }

View File

@@ -1,16 +1,12 @@
package hidemyass package hidemyass
import ( import (
"context"
"net"
"time" "time"
"github.com/qdm12/gluetun/internal/updater/resolver" "github.com/qdm12/gluetun/internal/updater/resolver"
) )
func resolveHosts(ctx context.Context, presolver resolver.Parallel, func newParallelResolver() resolver.Parallel {
hosts []string, minServers int) (
hostToIPs map[string][]net.IP, warnings []string, err error) {
const ( const (
maxFailRatio = 0.1 maxFailRatio = 0.1
maxDuration = 15 * time.Second maxDuration = 15 * time.Second
@@ -20,7 +16,6 @@ func resolveHosts(ctx context.Context, presolver resolver.Parallel,
) )
settings := resolver.ParallelSettings{ settings := resolver.ParallelSettings{
MaxFailRatio: maxFailRatio, MaxFailRatio: maxFailRatio,
MinFound: minServers,
Repeat: resolver.RepeatSettings{ Repeat: resolver.RepeatSettings{
MaxDuration: maxDuration, MaxDuration: maxDuration,
BetweenDuration: betweenDuration, BetweenDuration: betweenDuration,
@@ -29,5 +24,5 @@ func resolveHosts(ctx context.Context, presolver resolver.Parallel,
SortIPs: true, SortIPs: true,
}, },
} }
return presolver.Resolve(ctx, hosts, settings) return resolver.NewParallelResolver(settings)
} }

View File

@@ -26,7 +26,7 @@ func (u *Updater) FetchServers(ctx context.Context, minServers int) (
common.ErrNotEnoughServers, len(hosts), minServers) common.ErrNotEnoughServers, len(hosts), minServers)
} }
hostToIPs, warnings, err := resolveHosts(ctx, u.presolver, hosts, minServers) hostToIPs, warnings, err := u.presolver.Resolve(ctx, hosts, minServers)
for _, warning := range warnings { for _, warning := range warnings {
u.warner.Warn(warning) u.warner.Warn(warning)
} }

View File

@@ -16,11 +16,10 @@ type Warner interface {
Warn(s string) Warn(s string)
} }
func New(client *http.Client, presolver resolver.Parallel, func New(client *http.Client, warner Warner) *Updater {
warner Warner) *Updater {
return &Updater{ return &Updater{
client: client, client: client,
presolver: presolver, presolver: newParallelResolver(),
warner: warner, warner: warner,
} }
} }

View File

@@ -1,14 +1,12 @@
package ipvanish package ipvanish
import ( import (
"context"
"net"
"time" "time"
"github.com/qdm12/gluetun/internal/updater/resolver" "github.com/qdm12/gluetun/internal/updater/resolver"
) )
func getResolveSettings(minServers int) (settings resolver.ParallelSettings) { func newParallelResolver() (parallelResolver resolver.Parallel) {
const ( const (
maxFailRatio = 0.1 maxFailRatio = 0.1
maxDuration = 20 * time.Second maxDuration = 20 * time.Second
@@ -16,9 +14,8 @@ func getResolveSettings(minServers int) (settings resolver.ParallelSettings) {
maxNoNew = 2 maxNoNew = 2
maxFails = 2 maxFails = 2
) )
return resolver.ParallelSettings{ settings := resolver.ParallelSettings{
MaxFailRatio: maxFailRatio, MaxFailRatio: maxFailRatio,
MinFound: minServers,
Repeat: resolver.RepeatSettings{ Repeat: resolver.RepeatSettings{
MaxDuration: maxDuration, MaxDuration: maxDuration,
BetweenDuration: betweenDuration, BetweenDuration: betweenDuration,
@@ -27,11 +24,5 @@ func getResolveSettings(minServers int) (settings resolver.ParallelSettings) {
SortIPs: true, SortIPs: true,
}, },
} }
} return resolver.NewParallelResolver(settings)
func resolveHosts(ctx context.Context, presolver resolver.Parallel,
hosts []string, minServers int) (hostToIPs map[string][]net.IP,
warnings []string, err error) {
settings := getResolveSettings(minServers)
return presolver.Resolve(ctx, hosts, settings)
} }

View File

@@ -1,57 +0,0 @@
package ipvanish
import (
"context"
"errors"
"net"
"testing"
"time"
"github.com/golang/mock/gomock"
"github.com/qdm12/gluetun/internal/updater/resolver"
"github.com/qdm12/gluetun/internal/updater/resolver/mock_resolver"
"github.com/stretchr/testify/assert"
)
func Test_resolveHosts(t *testing.T) {
t.Parallel()
ctrl := gomock.NewController(t)
ctx := context.Background()
presolver := mock_resolver.NewMockParallel(ctrl)
hosts := []string{"host1", "host2"}
const minServers = 10
expectedHostToIPs := map[string][]net.IP{
"host1": {{1, 2, 3, 4}},
"host2": {{2, 3, 4, 5}},
}
expectedWarnings := []string{"warning1", "warning2"}
expectedErr := errors.New("dummy")
const (
maxFailRatio = 0.1
maxDuration = 20 * time.Second
betweenDuration = time.Second
maxNoNew = 2
maxFails = 2
)
expectedSettings := resolver.ParallelSettings{
MaxFailRatio: maxFailRatio,
MinFound: minServers,
Repeat: resolver.RepeatSettings{
MaxDuration: maxDuration,
BetweenDuration: betweenDuration,
MaxNoNew: maxNoNew,
MaxFails: maxFails,
SortIPs: true,
},
}
presolver.EXPECT().Resolve(ctx, hosts, expectedSettings).
Return(expectedHostToIPs, expectedWarnings, expectedErr)
hostToIPs, warnings, err := resolveHosts(ctx, presolver, hosts, minServers)
assert.Equal(t, expectedHostToIPs, hostToIPs)
assert.Equal(t, expectedWarnings, warnings)
assert.Equal(t, expectedErr, err)
}

View File

@@ -67,7 +67,7 @@ func (u *Updater) FetchServers(ctx context.Context, minServers int) (
} }
hosts := hts.toHostsSlice() hosts := hts.toHostsSlice()
hostToIPs, warnings, err := resolveHosts(ctx, u.presolver, hosts, minServers) hostToIPs, warnings, err := u.presolver.Resolve(ctx, hosts, minServers)
for _, warning := range warnings { for _, warning := range warnings {
u.warner.Warn(warning) u.warner.Warn(warning)
} }

View File

@@ -9,7 +9,6 @@ import (
"github.com/golang/mock/gomock" "github.com/golang/mock/gomock"
"github.com/qdm12/gluetun/internal/constants/vpn" "github.com/qdm12/gluetun/internal/constants/vpn"
"github.com/qdm12/gluetun/internal/models" "github.com/qdm12/gluetun/internal/models"
"github.com/qdm12/gluetun/internal/updater/resolver"
"github.com/qdm12/gluetun/internal/updater/resolver/mock_resolver" "github.com/qdm12/gluetun/internal/updater/resolver/mock_resolver"
"github.com/qdm12/gluetun/internal/updater/unzip/mock_unzip" "github.com/qdm12/gluetun/internal/updater/unzip/mock_unzip"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@@ -32,7 +31,6 @@ func Test_Updater_GetServers(t *testing.T) {
// Resolution // Resolution
expectResolve bool expectResolve bool
hostsToResolve []string hostsToResolve []string
resolveSettings resolver.ParallelSettings
hostToIPs map[string][]net.IP hostToIPs map[string][]net.IP
resolveWarnings []string resolveWarnings []string
resolveErr error resolveErr error
@@ -90,7 +88,6 @@ func Test_Updater_GetServers(t *testing.T) {
}, },
expectResolve: true, expectResolve: true,
hostsToResolve: []string{"hosta"}, hostsToResolve: []string{"hosta"},
resolveSettings: getResolveSettings(1),
err: errors.New("not enough servers found: 0 and expected at least 1"), err: errors.New("not enough servers found: 0 and expected at least 1"),
}, },
"resolve error": { "resolve error": {
@@ -104,7 +101,6 @@ func Test_Updater_GetServers(t *testing.T) {
}, },
expectResolve: true, expectResolve: true,
hostsToResolve: []string{"hosta"}, hostsToResolve: []string{"hosta"},
resolveSettings: getResolveSettings(0),
resolveWarnings: []string{"resolve warning"}, resolveWarnings: []string{"resolve warning"},
resolveErr: errors.New("dummy"), resolveErr: errors.New("dummy"),
err: errors.New("dummy"), err: errors.New("dummy"),
@@ -134,7 +130,6 @@ func Test_Updater_GetServers(t *testing.T) {
}, },
expectResolve: true, expectResolve: true,
hostsToResolve: []string{"hosta", "hostb"}, hostsToResolve: []string{"hosta", "hostb"},
resolveSettings: getResolveSettings(1),
hostToIPs: map[string][]net.IP{ hostToIPs: map[string][]net.IP{
"hosta": {{1, 1, 1, 1}, {2, 2, 2, 2}}, "hosta": {{1, 1, 1, 1}, {2, 2, 2, 2}},
"hostb": {{3, 3, 3, 3}, {4, 4, 4, 4}}, "hostb": {{3, 3, 3, 3}, {4, 4, 4, 4}},
@@ -175,13 +170,15 @@ func Test_Updater_GetServers(t *testing.T) {
presolver := mock_resolver.NewMockParallel(ctrl) presolver := mock_resolver.NewMockParallel(ctrl)
if testCase.expectResolve { if testCase.expectResolve {
presolver.EXPECT().Resolve(ctx, testCase.hostsToResolve, testCase.resolveSettings). presolver.EXPECT().Resolve(ctx, testCase.hostsToResolve, testCase.minServers).
Return(testCase.hostToIPs, testCase.resolveWarnings, testCase.resolveErr) Return(testCase.hostToIPs, testCase.resolveWarnings, testCase.resolveErr)
} }
warner := testCase.warnerBuilder(ctrl) updater := &Updater{
unzipper: unzipper,
updater := New(unzipper, presolver, warner) warner: testCase.warnerBuilder(ctrl),
presolver: presolver,
}
servers, err := updater.FetchServers(ctx, testCase.minServers) servers, err := updater.FetchServers(ctx, testCase.minServers)

View File

@@ -7,19 +7,18 @@ import (
type Updater struct { type Updater struct {
unzipper unzip.Unzipper unzipper unzip.Unzipper
presolver resolver.Parallel
warner Warner warner Warner
presolver resolver.Parallel
} }
type Warner interface { type Warner interface {
Warn(s string) Warn(s string)
} }
func New(unzipper unzip.Unzipper, presolver resolver.Parallel, func New(unzipper unzip.Unzipper, warner Warner) *Updater {
warner Warner) *Updater {
return &Updater{ return &Updater{
unzipper: unzipper, unzipper: unzipper,
presolver: presolver,
warner: warner, warner: warner,
presolver: newParallelResolver(),
} }
} }

View File

@@ -1,14 +1,12 @@
package ivpn package ivpn
import ( import (
"context"
"net"
"time" "time"
"github.com/qdm12/gluetun/internal/updater/resolver" "github.com/qdm12/gluetun/internal/updater/resolver"
) )
func getResolveSettings(minServers int) (settings resolver.ParallelSettings) { func newParallelResolver() (parallelResolver resolver.Parallel) {
const ( const (
maxFailRatio = 0.1 maxFailRatio = 0.1
maxDuration = 20 * time.Second maxDuration = 20 * time.Second
@@ -16,9 +14,8 @@ func getResolveSettings(minServers int) (settings resolver.ParallelSettings) {
maxNoNew = 2 maxNoNew = 2
maxFails = 2 maxFails = 2
) )
return resolver.ParallelSettings{ settings := resolver.ParallelSettings{
MaxFailRatio: maxFailRatio, MaxFailRatio: maxFailRatio,
MinFound: minServers,
Repeat: resolver.RepeatSettings{ Repeat: resolver.RepeatSettings{
MaxDuration: maxDuration, MaxDuration: maxDuration,
BetweenDuration: betweenDuration, BetweenDuration: betweenDuration,
@@ -27,11 +24,5 @@ func getResolveSettings(minServers int) (settings resolver.ParallelSettings) {
SortIPs: true, SortIPs: true,
}, },
} }
} return resolver.NewParallelResolver(settings)
func resolveHosts(ctx context.Context, presolver resolver.Parallel,
hosts []string, minServers int) (hostToIPs map[string][]net.IP,
warnings []string, err error) {
settings := getResolveSettings(minServers)
return presolver.Resolve(ctx, hosts, settings)
} }

View File

@@ -1,57 +0,0 @@
package ivpn
import (
"context"
"errors"
"net"
"testing"
"time"
"github.com/golang/mock/gomock"
"github.com/qdm12/gluetun/internal/updater/resolver"
"github.com/qdm12/gluetun/internal/updater/resolver/mock_resolver"
"github.com/stretchr/testify/assert"
)
func Test_resolveHosts(t *testing.T) {
t.Parallel()
ctrl := gomock.NewController(t)
ctx := context.Background()
presolver := mock_resolver.NewMockParallel(ctrl)
hosts := []string{"host1", "host2"}
const minServers = 10
expectedHostToIPs := map[string][]net.IP{
"host1": {{1, 2, 3, 4}},
"host2": {{2, 3, 4, 5}},
}
expectedWarnings := []string{"warning1", "warning2"}
expectedErr := errors.New("dummy")
const (
maxFailRatio = 0.1
maxDuration = 20 * time.Second
betweenDuration = time.Second
maxNoNew = 2
maxFails = 2
)
expectedSettings := resolver.ParallelSettings{
MaxFailRatio: maxFailRatio,
MinFound: minServers,
Repeat: resolver.RepeatSettings{
MaxDuration: maxDuration,
BetweenDuration: betweenDuration,
MaxNoNew: maxNoNew,
MaxFails: maxFails,
SortIPs: true,
},
}
presolver.EXPECT().Resolve(ctx, hosts, expectedSettings).
Return(expectedHostToIPs, expectedWarnings, expectedErr)
hostToIPs, warnings, err := resolveHosts(ctx, presolver, hosts, minServers)
assert.Equal(t, expectedHostToIPs, hostToIPs)
assert.Equal(t, expectedWarnings, warnings)
assert.Equal(t, expectedErr, err)
}

View File

@@ -38,7 +38,7 @@ func (u *Updater) FetchServers(ctx context.Context, minServers int) (
common.ErrNotEnoughServers, len(hosts), minServers) common.ErrNotEnoughServers, len(hosts), minServers)
} }
hostToIPs, warnings, err := resolveHosts(ctx, u.presolver, hosts, minServers) hostToIPs, warnings, err := u.presolver.Resolve(ctx, hosts, minServers)
for _, warning := range warnings { for _, warning := range warnings {
u.warner.Warn(warning) u.warner.Warn(warning)
} }

View File

@@ -12,7 +12,6 @@ import (
"github.com/golang/mock/gomock" "github.com/golang/mock/gomock"
"github.com/qdm12/gluetun/internal/constants/vpn" "github.com/qdm12/gluetun/internal/constants/vpn"
"github.com/qdm12/gluetun/internal/models" "github.com/qdm12/gluetun/internal/models"
"github.com/qdm12/gluetun/internal/updater/resolver"
"github.com/qdm12/gluetun/internal/updater/resolver/mock_resolver" "github.com/qdm12/gluetun/internal/updater/resolver/mock_resolver"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@@ -35,7 +34,6 @@ func Test_Updater_GetServers(t *testing.T) {
// Resolution // Resolution
expectResolve bool expectResolve bool
hostsToResolve []string hostsToResolve []string
resolveSettings resolver.ParallelSettings
hostToIPs map[string][]net.IP hostToIPs map[string][]net.IP
resolveWarnings []string resolveWarnings []string
resolveErr error resolveErr error
@@ -61,7 +59,6 @@ func Test_Updater_GetServers(t *testing.T) {
responseStatus: http.StatusOK, responseStatus: http.StatusOK,
expectResolve: true, expectResolve: true,
hostsToResolve: []string{"hosta"}, hostsToResolve: []string{"hosta"},
resolveSettings: getResolveSettings(0),
resolveWarnings: []string{"resolve warning"}, resolveWarnings: []string{"resolve warning"},
resolveErr: errors.New("dummy"), resolveErr: errors.New("dummy"),
err: errors.New("dummy"), err: errors.New("dummy"),
@@ -90,7 +87,6 @@ func Test_Updater_GetServers(t *testing.T) {
responseStatus: http.StatusOK, responseStatus: http.StatusOK,
expectResolve: true, expectResolve: true,
hostsToResolve: []string{"hosta", "hostb", "hostc"}, hostsToResolve: []string{"hosta", "hostb", "hostc"},
resolveSettings: getResolveSettings(1),
hostToIPs: map[string][]net.IP{ hostToIPs: map[string][]net.IP{
"hosta": {{1, 1, 1, 1}, {2, 2, 2, 2}}, "hosta": {{1, 1, 1, 1}, {2, 2, 2, 2}},
"hostb": {{3, 3, 3, 3}, {4, 4, 4, 4}}, "hostb": {{3, 3, 3, 3}, {4, 4, 4, 4}},
@@ -134,13 +130,17 @@ func Test_Updater_GetServers(t *testing.T) {
presolver := mock_resolver.NewMockParallel(ctrl) presolver := mock_resolver.NewMockParallel(ctrl)
if testCase.expectResolve { if testCase.expectResolve {
presolver.EXPECT().Resolve(ctx, testCase.hostsToResolve, testCase.resolveSettings). presolver.EXPECT().Resolve(ctx, testCase.hostsToResolve, testCase.minServers).
Return(testCase.hostToIPs, testCase.resolveWarnings, testCase.resolveErr) Return(testCase.hostToIPs, testCase.resolveWarnings, testCase.resolveErr)
} }
warner := testCase.warnerBuilder(ctrl) warner := testCase.warnerBuilder(ctrl)
updater := New(client, presolver, warner) updater := &Updater{
client: client,
presolver: presolver,
warner: warner,
}
servers, err := updater.FetchServers(ctx, testCase.minServers) servers, err := updater.FetchServers(ctx, testCase.minServers)

View File

@@ -16,11 +16,10 @@ type Warner interface {
Warn(s string) Warn(s string)
} }
func New(client *http.Client, presolver resolver.Parallel, func New(client *http.Client, warner Warner) *Updater {
warner Warner) *Updater {
return &Updater{ return &Updater{
client: client, client: client,
presolver: presolver, presolver: newParallelResolver(),
warner: warner, warner: warner,
} }
} }

View File

@@ -1,25 +1,20 @@
package privado package privado
import ( import (
"context"
"net"
"time" "time"
"github.com/qdm12/gluetun/internal/updater/resolver" "github.com/qdm12/gluetun/internal/updater/resolver"
) )
func resolveHosts(ctx context.Context, presolver resolver.Parallel, func newParallelResolver() (parallelResolver resolver.Parallel) {
hosts []string, minServers int) (hostToIPs map[string][]net.IP,
warnings []string, err error) {
const ( const (
maxFailRatio = 0.1 maxFailRatio = 0.1
maxDuration = 30 * time.Second maxDuration = 30 * time.Second
maxNoNew = 1 maxNoNew = 2
maxFails = 5 maxFails = 2
) )
settings := resolver.ParallelSettings{ settings := resolver.ParallelSettings{
MaxFailRatio: maxFailRatio, MaxFailRatio: maxFailRatio,
MinFound: minServers,
Repeat: resolver.RepeatSettings{ Repeat: resolver.RepeatSettings{
MaxDuration: maxDuration, MaxDuration: maxDuration,
MaxNoNew: maxNoNew, MaxNoNew: maxNoNew,
@@ -27,5 +22,5 @@ func resolveHosts(ctx context.Context, presolver resolver.Parallel,
SortIPs: true, SortIPs: true,
}, },
} }
return presolver.Resolve(ctx, hosts, settings) return resolver.NewParallelResolver(settings)
} }

View File

@@ -50,7 +50,7 @@ func (u *Updater) FetchServers(ctx context.Context, minServers int) (
} }
hosts := hts.toHostsSlice() hosts := hts.toHostsSlice()
hostToIPs, warnings, err := resolveHosts(ctx, u.presolver, hosts, minServers) hostToIPs, warnings, err := u.presolver.Resolve(ctx, hosts, minServers)
for _, warning := range warnings { for _, warning := range warnings {
u.warner.Warn(warning) u.warner.Warn(warning)
} }

View File

@@ -19,11 +19,11 @@ type Warner interface {
} }
func New(client *http.Client, unzipper unzip.Unzipper, func New(client *http.Client, unzipper unzip.Unzipper,
presolver resolver.Parallel, warner Warner) *Updater { warner Warner) *Updater {
return &Updater{ return &Updater{
client: client, client: client,
unzipper: unzipper, unzipper: unzipper,
presolver: presolver, presolver: newParallelResolver(),
warner: warner, warner: warner,
} }
} }

View File

@@ -1,16 +1,12 @@
package privatevpn package privatevpn
import ( import (
"context"
"net"
"time" "time"
"github.com/qdm12/gluetun/internal/updater/resolver" "github.com/qdm12/gluetun/internal/updater/resolver"
) )
func resolveHosts(ctx context.Context, presolver resolver.Parallel, func newParallelResolver() (parallelResolver resolver.Parallel) {
hosts []string, minServers int) (hostToIPs map[string][]net.IP,
warnings []string, err error) {
const ( const (
maxFailRatio = 0.1 maxFailRatio = 0.1
maxDuration = 6 * time.Second maxDuration = 6 * time.Second
@@ -20,7 +16,6 @@ func resolveHosts(ctx context.Context, presolver resolver.Parallel,
) )
settings := resolver.ParallelSettings{ settings := resolver.ParallelSettings{
MaxFailRatio: maxFailRatio, MaxFailRatio: maxFailRatio,
MinFound: minServers,
Repeat: resolver.RepeatSettings{ Repeat: resolver.RepeatSettings{
MaxDuration: maxDuration, MaxDuration: maxDuration,
BetweenDuration: betweenDuration, BetweenDuration: betweenDuration,
@@ -29,5 +24,5 @@ func resolveHosts(ctx context.Context, presolver resolver.Parallel,
SortIPs: true, SortIPs: true,
}, },
} }
return presolver.Resolve(ctx, hosts, settings) return resolver.NewParallelResolver(settings)
} }

View File

@@ -82,7 +82,7 @@ func (u *Updater) FetchServers(ctx context.Context, minServers int) (
hosts := hts.toHostsSlice() hosts := hts.toHostsSlice()
hostToIPs, warnings, err := resolveHosts(ctx, u.presolver, hosts, minServers) hostToIPs, warnings, err := u.presolver.Resolve(ctx, hosts, minServers)
for _, warning := range warnings { for _, warning := range warnings {
u.warner.Warn(warning) u.warner.Warn(warning)
} }

View File

@@ -15,11 +15,10 @@ type Warner interface {
Warn(s string) Warn(s string)
} }
func New(unzipper unzip.Unzipper, presolver resolver.Parallel, func New(unzipper unzip.Unzipper, warner Warner) *Updater {
warner Warner) *Updater {
return &Updater{ return &Updater{
unzipper: unzipper, unzipper: unzipper,
presolver: presolver, presolver: newParallelResolver(),
warner: warner, warner: warner,
} }
} }

View File

@@ -1,16 +1,12 @@
package purevpn package purevpn
import ( import (
"context"
"net"
"time" "time"
"github.com/qdm12/gluetun/internal/updater/resolver" "github.com/qdm12/gluetun/internal/updater/resolver"
) )
func resolveHosts(ctx context.Context, presolver resolver.Parallel, func newParallelResolver() (parallelResolver resolver.Parallel) {
hosts []string, minServers int) (hostToIPs map[string][]net.IP,
warnings []string, err error) {
const ( const (
maxFailRatio = 0.1 maxFailRatio = 0.1
maxDuration = 20 * time.Second maxDuration = 20 * time.Second
@@ -20,7 +16,6 @@ func resolveHosts(ctx context.Context, presolver resolver.Parallel,
) )
settings := resolver.ParallelSettings{ settings := resolver.ParallelSettings{
MaxFailRatio: maxFailRatio, MaxFailRatio: maxFailRatio,
MinFound: minServers,
Repeat: resolver.RepeatSettings{ Repeat: resolver.RepeatSettings{
MaxDuration: maxDuration, MaxDuration: maxDuration,
BetweenDuration: betweenDuration, BetweenDuration: betweenDuration,
@@ -29,5 +24,5 @@ func resolveHosts(ctx context.Context, presolver resolver.Parallel,
SortIPs: true, SortIPs: true,
}, },
} }
return presolver.Resolve(ctx, hosts, settings) return resolver.NewParallelResolver(settings)
} }

View File

@@ -60,7 +60,7 @@ func (u *Updater) FetchServers(ctx context.Context, minServers int) (
} }
hosts := hts.toHostsSlice() hosts := hts.toHostsSlice()
hostToIPs, warnings, err := resolveHosts(ctx, u.presolver, hosts, minServers) hostToIPs, warnings, err := u.presolver.Resolve(ctx, hosts, minServers)
for _, warning := range warnings { for _, warning := range warnings {
u.warner.Warn(warning) u.warner.Warn(warning)
} }

View File

@@ -19,11 +19,11 @@ type Warner interface {
} }
func New(client *http.Client, unzipper unzip.Unzipper, func New(client *http.Client, unzipper unzip.Unzipper,
presolver resolver.Parallel, warner Warner) *Updater { warner Warner) *Updater {
return &Updater{ return &Updater{
client: client, client: client,
unzipper: unzipper, unzipper: unzipper,
presolver: presolver, presolver: newParallelResolver(),
warner: warner, warner: warner,
} }
} }

View File

@@ -1,16 +1,12 @@
package surfshark package surfshark
import ( import (
"context"
"net"
"time" "time"
"github.com/qdm12/gluetun/internal/updater/resolver" "github.com/qdm12/gluetun/internal/updater/resolver"
) )
func resolveHosts(ctx context.Context, presolver resolver.Parallel, func newParallelResolver() (parallelResolver resolver.Parallel) {
hosts []string, minServers int) (hostToIPs map[string][]net.IP,
warnings []string, err error) {
const ( const (
maxFailRatio = 0.1 maxFailRatio = 0.1
maxDuration = 20 * time.Second maxDuration = 20 * time.Second
@@ -20,7 +16,6 @@ func resolveHosts(ctx context.Context, presolver resolver.Parallel,
) )
settings := resolver.ParallelSettings{ settings := resolver.ParallelSettings{
MaxFailRatio: maxFailRatio, MaxFailRatio: maxFailRatio,
MinFound: minServers,
Repeat: resolver.RepeatSettings{ Repeat: resolver.RepeatSettings{
MaxDuration: maxDuration, MaxDuration: maxDuration,
BetweenDuration: betweenDuration, BetweenDuration: betweenDuration,
@@ -29,5 +24,5 @@ func resolveHosts(ctx context.Context, presolver resolver.Parallel,
SortIPs: true, SortIPs: true,
}, },
} }
return presolver.Resolve(ctx, hosts, settings) return resolver.NewParallelResolver(settings)
} }

View File

@@ -1,57 +0,0 @@
package surfshark
import (
"context"
"errors"
"net"
"testing"
"time"
"github.com/golang/mock/gomock"
"github.com/qdm12/gluetun/internal/updater/resolver"
"github.com/qdm12/gluetun/internal/updater/resolver/mock_resolver"
"github.com/stretchr/testify/assert"
)
func Test_resolveHosts(t *testing.T) {
t.Parallel()
ctrl := gomock.NewController(t)
ctx := context.Background()
presolver := mock_resolver.NewMockParallel(ctrl)
hosts := []string{"host1", "host2"}
const minServers = 10
expectedHostToIPs := map[string][]net.IP{
"host1": {{1, 2, 3, 4}},
"host2": {{2, 3, 4, 5}},
}
expectedWarnings := []string{"warning1", "warning2"}
expectedErr := errors.New("dummy")
const (
maxFailRatio = 0.1
maxDuration = 20 * time.Second
betweenDuration = time.Second
maxNoNew = 2
maxFails = 2
)
expectedSettings := resolver.ParallelSettings{
MaxFailRatio: maxFailRatio,
MinFound: minServers,
Repeat: resolver.RepeatSettings{
MaxDuration: maxDuration,
BetweenDuration: betweenDuration,
MaxNoNew: maxNoNew,
MaxFails: maxFails,
SortIPs: true,
},
}
presolver.EXPECT().Resolve(ctx, hosts, expectedSettings).
Return(expectedHostToIPs, expectedWarnings, expectedErr)
hostToIPs, warnings, err := resolveHosts(ctx, presolver, hosts, minServers)
assert.Equal(t, expectedHostToIPs, hostToIPs)
assert.Equal(t, expectedWarnings, warnings)
assert.Equal(t, expectedErr, err)
}

View File

@@ -31,7 +31,7 @@ func (u *Updater) FetchServers(ctx context.Context, minServers int) (
getRemainingServers(hts) getRemainingServers(hts)
hosts := hts.toHostsSlice() hosts := hts.toHostsSlice()
hostToIPs, warnings, err := resolveHosts(ctx, u.presolver, hosts, minServers) hostToIPs, warnings, err := u.presolver.Resolve(ctx, hosts, minServers)
for _, warning := range warnings { for _, warning := range warnings {
u.warner.Warn(warning) u.warner.Warn(warning)
} }

View File

@@ -19,11 +19,11 @@ type Warner interface {
} }
func New(client *http.Client, unzipper unzip.Unzipper, func New(client *http.Client, unzipper unzip.Unzipper,
presolver resolver.Parallel, warner Warner) *Updater { warner Warner) *Updater {
return &Updater{ return &Updater{
client: client, client: client,
unzipper: unzipper, unzipper: unzipper,
presolver: presolver, presolver: newParallelResolver(),
warner: warner, warner: warner,
} }
} }

View File

@@ -1,16 +1,12 @@
package torguard package torguard
import ( import (
"context"
"net"
"time" "time"
"github.com/qdm12/gluetun/internal/updater/resolver" "github.com/qdm12/gluetun/internal/updater/resolver"
) )
func resolveHosts(ctx context.Context, presolver resolver.Parallel, func newParallelResolver() (parallelResolver resolver.Parallel) {
hosts []string, minServers int) (hostToIPs map[string][]net.IP,
warnings []string, err error) {
const ( const (
maxFailRatio = 0.1 maxFailRatio = 0.1
maxDuration = 20 * time.Second maxDuration = 20 * time.Second
@@ -20,7 +16,6 @@ func resolveHosts(ctx context.Context, presolver resolver.Parallel,
) )
settings := resolver.ParallelSettings{ settings := resolver.ParallelSettings{
MaxFailRatio: maxFailRatio, MaxFailRatio: maxFailRatio,
MinFound: minServers,
Repeat: resolver.RepeatSettings{ Repeat: resolver.RepeatSettings{
MaxDuration: maxDuration, MaxDuration: maxDuration,
BetweenDuration: betweenDuration, BetweenDuration: betweenDuration,
@@ -29,5 +24,5 @@ func resolveHosts(ctx context.Context, presolver resolver.Parallel,
SortIPs: true, SortIPs: true,
}, },
} }
return presolver.Resolve(ctx, hosts, settings) return resolver.NewParallelResolver(settings)
} }

View File

@@ -50,7 +50,7 @@ func (u *Updater) FetchServers(ctx context.Context, minServers int) (
} }
hosts := hts.toHostsSlice() hosts := hts.toHostsSlice()
hostToIPs, warnings, err := resolveHosts(ctx, u.presolver, hosts, minServers) hostToIPs, warnings, err := u.presolver.Resolve(ctx, hosts, minServers)
u.warnWarnings(warnings) u.warnWarnings(warnings)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -15,11 +15,10 @@ type Warner interface {
Warn(s string) Warn(s string)
} }
func New(unzipper unzip.Unzipper, presolver resolver.Parallel, func New(unzipper unzip.Unzipper, warner Warner) *Updater {
warner Warner) *Updater {
return &Updater{ return &Updater{
unzipper: unzipper, unzipper: unzipper,
presolver: presolver, presolver: newParallelResolver(),
warner: warner, warner: warner,
} }
} }

View File

@@ -1,16 +1,12 @@
package vpnunlimited package vpnunlimited
import ( import (
"context"
"net"
"time" "time"
"github.com/qdm12/gluetun/internal/updater/resolver" "github.com/qdm12/gluetun/internal/updater/resolver"
) )
func resolveHosts(ctx context.Context, presolver resolver.Parallel, func newParallelResolver() (parallelResolver resolver.Parallel) {
hosts []string, minServers int) (hostToIPs map[string][]net.IP,
warnings []string, err error) {
const ( const (
maxFailRatio = 0.1 maxFailRatio = 0.1
maxDuration = 20 * time.Second maxDuration = 20 * time.Second
@@ -20,7 +16,6 @@ func resolveHosts(ctx context.Context, presolver resolver.Parallel,
) )
settings := resolver.ParallelSettings{ settings := resolver.ParallelSettings{
MaxFailRatio: maxFailRatio, MaxFailRatio: maxFailRatio,
MinFound: minServers,
Repeat: resolver.RepeatSettings{ Repeat: resolver.RepeatSettings{
MaxDuration: maxDuration, MaxDuration: maxDuration,
BetweenDuration: betweenDuration, BetweenDuration: betweenDuration,
@@ -29,5 +24,5 @@ func resolveHosts(ctx context.Context, presolver resolver.Parallel,
SortIPs: true, SortIPs: true,
}, },
} }
return presolver.Resolve(ctx, hosts, settings) return resolver.NewParallelResolver(settings)
} }

View File

@@ -20,7 +20,7 @@ func (u *Updater) FetchServers(ctx context.Context, minServers int) (
} }
hosts := hts.toHostsSlice() hosts := hts.toHostsSlice()
hostToIPs, warnings, err := resolveHosts(ctx, u.presolver, hosts, minServers) hostToIPs, warnings, err := u.presolver.Resolve(ctx, hosts, minServers)
for _, warning := range warnings { for _, warning := range warnings {
u.warner.Warn(warning) u.warner.Warn(warning)
} }

View File

@@ -15,11 +15,10 @@ type Warner interface {
Warn(s string) Warn(s string)
} }
func New(unzipper unzip.Unzipper, presolver resolver.Parallel, func New(unzipper unzip.Unzipper, warner Warner) *Updater {
warner Warner) *Updater {
return &Updater{ return &Updater{
unzipper: unzipper, unzipper: unzipper,
presolver: presolver, presolver: newParallelResolver(),
warner: warner, warner: warner,
} }
} }

View File

@@ -1,30 +1,28 @@
package vyprvpn package vyprvpn
import ( import (
"context"
"net"
"time" "time"
"github.com/qdm12/gluetun/internal/updater/resolver" "github.com/qdm12/gluetun/internal/updater/resolver"
) )
func resolveHosts(ctx context.Context, presolver resolver.Parallel, func newParallelResolver() (parallelResolver resolver.Parallel) {
hosts []string, minServers int) (hostToIPs map[string][]net.IP,
warnings []string, err error) {
const ( const (
maxFailRatio = 0.1 maxFailRatio = 0.1
maxDuration = 5 * time.Second
betweenDuration = time.Second
maxNoNew = 2 maxNoNew = 2
maxFails = 2 maxFails = 2
) )
settings := resolver.ParallelSettings{ settings := resolver.ParallelSettings{
MaxFailRatio: maxFailRatio, MaxFailRatio: maxFailRatio,
MinFound: minServers,
Repeat: resolver.RepeatSettings{ Repeat: resolver.RepeatSettings{
MaxDuration: time.Second, MaxDuration: maxDuration,
BetweenDuration: betweenDuration,
MaxNoNew: maxNoNew, MaxNoNew: maxNoNew,
MaxFails: maxFails, MaxFails: maxFails,
SortIPs: true, SortIPs: true,
}, },
} }
return presolver.Resolve(ctx, hosts, settings) return resolver.NewParallelResolver(settings)
} }

View File

@@ -64,7 +64,7 @@ func (u *Updater) FetchServers(ctx context.Context, minServers int) (
} }
hosts := hts.toHostsSlice() hosts := hts.toHostsSlice()
hostToIPs, warnings, err := resolveHosts(ctx, u.presolver, hosts, minServers) hostToIPs, warnings, err := u.presolver.Resolve(ctx, hosts, minServers)
for _, warning := range warnings { for _, warning := range warnings {
u.warner.Warn(warning) u.warner.Warn(warning)
} }

View File

@@ -15,11 +15,10 @@ type Warner interface {
Warn(s string) Warn(s string)
} }
func New(unzipper unzip.Unzipper, presolver resolver.Parallel, func New(unzipper unzip.Unzipper, warner Warner) *Updater {
warner Warner) *Updater {
return &Updater{ return &Updater{
unzipper: unzipper, unzipper: unzipper,
presolver: presolver, presolver: newParallelResolver(),
warner: warner, warner: warner,
} }
} }

View File

@@ -1,16 +1,12 @@
package wevpn package wevpn
import ( import (
"context"
"net"
"time" "time"
"github.com/qdm12/gluetun/internal/updater/resolver" "github.com/qdm12/gluetun/internal/updater/resolver"
) )
func resolveHosts(ctx context.Context, presolver resolver.Parallel, func newParallelResolver() (parallelResolver resolver.Parallel) {
hosts []string, minServers int) (hostToIPs map[string][]net.IP,
warnings []string, err error) {
const ( const (
maxFailRatio = 0.1 maxFailRatio = 0.1
maxDuration = 20 * time.Second maxDuration = 20 * time.Second
@@ -20,7 +16,6 @@ func resolveHosts(ctx context.Context, presolver resolver.Parallel,
) )
settings := resolver.ParallelSettings{ settings := resolver.ParallelSettings{
MaxFailRatio: maxFailRatio, MaxFailRatio: maxFailRatio,
MinFound: minServers,
Repeat: resolver.RepeatSettings{ Repeat: resolver.RepeatSettings{
MaxDuration: maxDuration, MaxDuration: maxDuration,
BetweenDuration: betweenDuration, BetweenDuration: betweenDuration,
@@ -29,5 +24,5 @@ func resolveHosts(ctx context.Context, presolver resolver.Parallel,
SortIPs: true, SortIPs: true,
}, },
} }
return presolver.Resolve(ctx, hosts, settings) return resolver.NewParallelResolver(settings)
} }

View File

@@ -1,57 +0,0 @@
package wevpn
import (
"context"
"errors"
"net"
"testing"
"time"
"github.com/golang/mock/gomock"
"github.com/qdm12/gluetun/internal/updater/resolver"
"github.com/qdm12/gluetun/internal/updater/resolver/mock_resolver"
"github.com/stretchr/testify/assert"
)
func Test_resolveHosts(t *testing.T) {
t.Parallel()
ctrl := gomock.NewController(t)
ctx := context.Background()
presolver := mock_resolver.NewMockParallel(ctrl)
hosts := []string{"host1", "host2"}
const minServers = 10
expectedHostToIPs := map[string][]net.IP{
"host1": {{1, 2, 3, 4}},
"host2": {{2, 3, 4, 5}},
}
expectedWarnings := []string{"warning1", "warning2"}
expectedErr := errors.New("dummy")
const (
maxFailRatio = 0.1
maxDuration = 20 * time.Second
betweenDuration = time.Second
maxNoNew = 2
maxFails = 2
)
expectedSettings := resolver.ParallelSettings{
MaxFailRatio: maxFailRatio,
MinFound: minServers,
Repeat: resolver.RepeatSettings{
MaxDuration: maxDuration,
BetweenDuration: betweenDuration,
MaxNoNew: maxNoNew,
MaxFails: maxFails,
SortIPs: true,
},
}
presolver.EXPECT().Resolve(ctx, hosts, expectedSettings).
Return(expectedHostToIPs, expectedWarnings, expectedErr)
hostToIPs, warnings, err := resolveHosts(ctx, presolver, hosts, minServers)
assert.Equal(t, expectedHostToIPs, hostToIPs)
assert.Equal(t, expectedWarnings, warnings)
assert.Equal(t, expectedErr, err)
}

View File

@@ -31,7 +31,7 @@ func (u *Updater) FetchServers(ctx context.Context, minServers int) (
hostnameToCity[hostname] = city hostnameToCity[hostname] = city
} }
hostnameToIPs, warnings, err := resolveHosts(ctx, u.presolver, hostnames, minServers) hostnameToIPs, warnings, err := u.presolver.Resolve(ctx, hostnames, minServers)
for _, warning := range warnings { for _, warning := range warnings {
u.warner.Warn(warning) u.warner.Warn(warning)
} }

View File

@@ -13,9 +13,9 @@ type Warner interface {
Warn(s string) Warn(s string)
} }
func New(presolver resolver.Parallel, warner Warner) *Updater { func New(warner Warner) *Updater {
return &Updater{ return &Updater{
presolver: presolver, presolver: newParallelResolver(),
warner: warner, warner: warner,
} }
} }

View File

@@ -60,17 +60,17 @@ func (u *Updater) fetchServers(ctx context.Context, provider string,
case providers.Custom: case providers.Custom:
panic("cannot update custom provider") panic("cannot update custom provider")
case providers.Cyberghost: case providers.Cyberghost:
providerUpdater = cyberghost.New(u.presolver) providerUpdater = cyberghost.New()
case providers.Expressvpn: case providers.Expressvpn:
providerUpdater = expressvpn.New(u.unzipper, u.presolver, u.logger) providerUpdater = expressvpn.New(u.unzipper, u.logger)
case providers.Fastestvpn: case providers.Fastestvpn:
providerUpdater = fastestvpn.New(u.unzipper, u.presolver, u.logger) providerUpdater = fastestvpn.New(u.unzipper, u.logger)
case providers.HideMyAss: case providers.HideMyAss:
providerUpdater = hidemyass.New(u.client, u.presolver, u.logger) providerUpdater = hidemyass.New(u.client, u.logger)
case providers.Ipvanish: case providers.Ipvanish:
providerUpdater = ipvanish.New(u.unzipper, u.presolver, u.logger) providerUpdater = ipvanish.New(u.unzipper, u.logger)
case providers.Ivpn: case providers.Ivpn:
providerUpdater = ivpn.New(u.client, u.presolver, u.logger) providerUpdater = ivpn.New(u.client, u.logger)
case providers.Mullvad: case providers.Mullvad:
providerUpdater = mullvad.New(u.client) providerUpdater = mullvad.New(u.client)
case providers.Nordvpn: case providers.Nordvpn:
@@ -78,25 +78,25 @@ func (u *Updater) fetchServers(ctx context.Context, provider string,
case providers.Perfectprivacy: case providers.Perfectprivacy:
providerUpdater = perfectprivacy.New(u.unzipper, u.logger) providerUpdater = perfectprivacy.New(u.unzipper, u.logger)
case providers.Privado: case providers.Privado:
providerUpdater = privado.New(u.client, u.unzipper, u.presolver, u.logger) providerUpdater = privado.New(u.client, u.unzipper, u.logger)
case providers.PrivateInternetAccess: case providers.PrivateInternetAccess:
providerUpdater = privateinternetaccess.New(u.client) providerUpdater = privateinternetaccess.New(u.client)
case providers.Privatevpn: case providers.Privatevpn:
providerUpdater = privatevpn.New(u.unzipper, u.presolver, u.logger) providerUpdater = privatevpn.New(u.unzipper, u.logger)
case providers.Protonvpn: case providers.Protonvpn:
providerUpdater = protonvpn.New(u.client, u.logger) providerUpdater = protonvpn.New(u.client, u.logger)
case providers.Purevpn: case providers.Purevpn:
providerUpdater = purevpn.New(u.client, u.unzipper, u.presolver, u.logger) providerUpdater = purevpn.New(u.client, u.unzipper, u.logger)
case providers.Surfshark: case providers.Surfshark:
providerUpdater = surfshark.New(u.client, u.unzipper, u.presolver, u.logger) providerUpdater = surfshark.New(u.client, u.unzipper, u.logger)
case providers.Torguard: case providers.Torguard:
providerUpdater = torguard.New(u.unzipper, u.presolver, u.logger) providerUpdater = torguard.New(u.unzipper, u.logger)
case providers.VPNUnlimited: case providers.VPNUnlimited:
providerUpdater = vpnunlimited.New(u.unzipper, u.presolver, u.logger) providerUpdater = vpnunlimited.New(u.unzipper, u.logger)
case providers.Vyprvpn: case providers.Vyprvpn:
providerUpdater = vyprvpn.New(u.unzipper, u.presolver, u.logger) providerUpdater = vyprvpn.New(u.unzipper, u.logger)
case providers.Wevpn: case providers.Wevpn:
providerUpdater = wevpn.New(u.presolver, u.logger) providerUpdater = wevpn.New(u.logger)
case providers.Windscribe: case providers.Windscribe:
providerUpdater = windscribe.New(u.client, u.logger) providerUpdater = windscribe.New(u.client, u.logger)
default: default:

View File

@@ -10,7 +10,6 @@ import (
reflect "reflect" reflect "reflect"
gomock "github.com/golang/mock/gomock" gomock "github.com/golang/mock/gomock"
resolver "github.com/qdm12/gluetun/internal/updater/resolver"
) )
// MockParallel is a mock of Parallel interface. // MockParallel is a mock of Parallel interface.
@@ -37,7 +36,7 @@ func (m *MockParallel) EXPECT() *MockParallelMockRecorder {
} }
// Resolve mocks base method. // Resolve mocks base method.
func (m *MockParallel) Resolve(arg0 context.Context, arg1 []string, arg2 resolver.ParallelSettings) (map[string][]net.IP, []string, error) { func (m *MockParallel) Resolve(arg0 context.Context, arg1 []string, arg2 int) (map[string][]net.IP, []string, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Resolve", arg0, arg1, arg2) ret := m.ctrl.Call(m, "Resolve", arg0, arg1, arg2)
ret0, _ := ret[0].(map[string][]net.IP) ret0, _ := ret[0].(map[string][]net.IP)

View File

@@ -10,17 +10,19 @@ import (
//go:generate mockgen -destination=mock_$GOPACKAGE/$GOFILE . Parallel //go:generate mockgen -destination=mock_$GOPACKAGE/$GOFILE . Parallel
type Parallel interface { type Parallel interface {
Resolve(ctx context.Context, hosts []string, settings ParallelSettings) ( Resolve(ctx context.Context, hosts []string, minToFind int) (
hostToIPs map[string][]net.IP, warnings []string, err error) hostToIPs map[string][]net.IP, warnings []string, err error)
} }
type parallel struct { type parallel struct {
repeatResolver Repeat repeatResolver Repeat
settings ParallelSettings
} }
func NewParallelResolver(address string) Parallel { func NewParallelResolver(settings ParallelSettings) Parallel {
return &parallel{ return &parallel{
repeatResolver: NewRepeat(address), repeatResolver: NewRepeat(settings.Repeat),
settings: settings,
} }
} }
@@ -32,10 +34,6 @@ type ParallelSettings struct {
// This value is between 0 and 1. Note this is only // This value is between 0 and 1. Note this is only
// applicable if FailEarly is not set to true. // applicable if FailEarly is not set to true.
MaxFailRatio float64 MaxFailRatio float64
// MinFound is the minimum number of hosts to be found.
// If it is bigger than the number of hosts given, it
// is set to the number of hosts given.
MinFound int
} }
type parallelResult struct { type parallelResult struct {
@@ -48,13 +46,8 @@ var (
ErrMaxFailRatio = errors.New("maximum failure ratio reached") ErrMaxFailRatio = errors.New("maximum failure ratio reached")
) )
func (pr *parallel) Resolve(ctx context.Context, hosts []string, func (pr *parallel) Resolve(ctx context.Context, hosts []string, minToFind int) (
settings ParallelSettings) (hostToIPs map[string][]net.IP, warnings []string, err error) { hostToIPs map[string][]net.IP, warnings []string, err error) {
minFound := settings.MinFound
if minFound > len(hosts) {
minFound = len(hosts)
}
ctx, cancel := context.WithCancel(ctx) ctx, cancel := context.WithCancel(ctx)
defer cancel() defer cancel()
@@ -64,16 +57,16 @@ func (pr *parallel) Resolve(ctx context.Context, hosts []string,
defer close(errors) defer close(errors)
for _, host := range hosts { for _, host := range hosts {
go pr.resolveAsync(ctx, host, settings.Repeat, results, errors) go pr.resolveAsync(ctx, host, results, errors)
} }
hostToIPs = make(map[string][]net.IP, len(hosts)) hostToIPs = make(map[string][]net.IP, len(hosts))
maxFails := int(settings.MaxFailRatio * float64(len(hosts))) maxFails := int(pr.settings.MaxFailRatio * float64(len(hosts)))
for range hosts { for range hosts {
select { select {
case newErr := <-errors: case newErr := <-errors:
if settings.FailEarly { if pr.settings.FailEarly {
if err == nil { if err == nil {
// only set the error to the first error encountered // only set the error to the first error encountered
// and not the context canceled errors coming after. // and not the context canceled errors coming after.
@@ -100,14 +93,14 @@ func (pr *parallel) Resolve(ctx context.Context, hosts []string,
return nil, warnings, err return nil, warnings, err
} }
if len(hostToIPs) < minFound { if len(hostToIPs) < minToFind {
return nil, warnings, return nil, warnings,
fmt.Errorf("%w: found %d hosts but expected at least %d", fmt.Errorf("%w: found %d hosts but expected at least %d",
ErrMinFound, len(hostToIPs), minFound) ErrMinFound, len(hostToIPs), minToFind)
} }
failureRatio := float64(len(warnings)) / float64(len(hosts)) failureRatio := float64(len(warnings)) / float64(len(hosts))
if failureRatio > settings.MaxFailRatio { if failureRatio > pr.settings.MaxFailRatio {
return hostToIPs, warnings, return hostToIPs, warnings,
fmt.Errorf("%w: %.2f failure ratio reached", ErrMaxFailRatio, failureRatio) fmt.Errorf("%w: %.2f failure ratio reached", ErrMaxFailRatio, failureRatio)
} }
@@ -116,8 +109,8 @@ func (pr *parallel) Resolve(ctx context.Context, hosts []string,
} }
func (pr *parallel) resolveAsync(ctx context.Context, host string, func (pr *parallel) resolveAsync(ctx context.Context, host string,
settings RepeatSettings, results chan<- parallelResult, errors chan<- error) { results chan<- parallelResult, errors chan<- error) {
IPs, err := pr.repeatResolver.Resolve(ctx, host, settings) IPs, err := pr.repeatResolver.Resolve(ctx, host)
if err != nil { if err != nil {
errors <- err errors <- err
return return

View File

@@ -11,20 +11,23 @@ import (
) )
type Repeat interface { type Repeat interface {
Resolve(ctx context.Context, host string, settings RepeatSettings) (IPs []net.IP, err error) Resolve(ctx context.Context, host string) (IPs []net.IP, err error)
} }
type repeat struct { type repeat struct {
resolver *net.Resolver resolver *net.Resolver
settings RepeatSettings
} }
func NewRepeat(address string) Repeat { func NewRepeat(settings RepeatSettings) Repeat {
return &repeat{ return &repeat{
resolver: newResolver(address), resolver: newResolver(settings.Address),
settings: settings,
} }
} }
type RepeatSettings struct { type RepeatSettings struct {
Address string
MaxDuration time.Duration MaxDuration time.Duration
BetweenDuration time.Duration BetweenDuration time.Duration
MaxNoNew int MaxNoNew int
@@ -33,8 +36,8 @@ type RepeatSettings struct {
SortIPs bool SortIPs bool
} }
func (r *repeat) Resolve(ctx context.Context, host string, settings RepeatSettings) (ips []net.IP, err error) { func (r *repeat) Resolve(ctx context.Context, host string) (ips []net.IP, err error) {
timedCtx, cancel := context.WithTimeout(ctx, settings.MaxDuration) timedCtx, cancel := context.WithTimeout(ctx, r.settings.MaxDuration)
defer cancel() defer cancel()
noNewCounter := 0 noNewCounter := 0
@@ -45,7 +48,7 @@ func (r *repeat) Resolve(ctx context.Context, host string, settings RepeatSettin
// TODO // TODO
// - one resolving every 100ms for round robin DNS responses // - one resolving every 100ms for round robin DNS responses
// - one every second for time based DNS cycling responses // - one every second for time based DNS cycling responses
noNewCounter, failCounter, err = r.resolveOnce(ctx, timedCtx, host, settings, uniqueIPs, noNewCounter, failCounter) noNewCounter, failCounter, err = r.resolveOnce(ctx, timedCtx, host, r.settings, uniqueIPs, noNewCounter, failCounter)
} }
if len(uniqueIPs) == 0 { if len(uniqueIPs) == 0 {
@@ -54,7 +57,7 @@ func (r *repeat) Resolve(ctx context.Context, host string, settings RepeatSettin
ips = uniqueIPsToSlice(uniqueIPs) ips = uniqueIPsToSlice(uniqueIPs)
if settings.SortIPs { if r.settings.SortIPs {
sort.Slice(ips, func(i, j int) bool { sort.Slice(ips, func(i, j int) bool {
return bytes.Compare(ips[i], ips[j]) < 1 return bytes.Compare(ips[i], ips[j]) < 1
}) })

View File

@@ -8,7 +8,6 @@ import (
"github.com/qdm12/gluetun/internal/configuration/settings" "github.com/qdm12/gluetun/internal/configuration/settings"
"github.com/qdm12/gluetun/internal/models" "github.com/qdm12/gluetun/internal/models"
"github.com/qdm12/gluetun/internal/updater/resolver"
"github.com/qdm12/gluetun/internal/updater/unzip" "github.com/qdm12/gluetun/internal/updater/unzip"
"golang.org/x/text/cases" "golang.org/x/text/cases"
"golang.org/x/text/language" "golang.org/x/text/language"
@@ -24,7 +23,6 @@ type Updater struct {
// Functions for tests // Functions for tests
logger Logger logger Logger
timeNow func() time.Time timeNow func() time.Time
presolver resolver.Parallel
client *http.Client client *http.Client
unzipper unzip.Unzipper unzipper unzip.Unzipper
} }
@@ -49,7 +47,6 @@ func New(settings settings.Updater, httpClient *http.Client,
storage: storage, storage: storage,
logger: logger, logger: logger,
timeNow: time.Now, timeNow: time.Now,
presolver: resolver.NewParallelResolver(settings.DNSAddress.String()),
client: httpClient, client: httpClient,
unzipper: unzipper, unzipper: unzipper,
} }