From 83b4a3fe55900d2026a69d05abeef8a30cb8ad6a Mon Sep 17 00:00:00 2001 From: Quentin McGaw Date: Sun, 12 Jun 2022 00:09:01 +0000 Subject: [PATCH] chore(publicip): refactoring - Exported `Fetcher` interface - Inject `Fetcher` to publicip loop and updaters - Get public IP and information at the same time - Only query ipinfo.io - Make `MultiInfo` part of the `Fetch` object --- cmd/gluetun/main.go | 5 +- internal/cli/openvpnconfig.go | 9 ++- internal/cli/update.go | 5 +- internal/provider/common/updater.go | 5 ++ internal/provider/privado/provider.go | 5 +- internal/provider/privado/updater/location.go | 7 +- internal/provider/privado/updater/servers.go | 2 +- internal/provider/privado/updater/updater.go | 8 +- internal/provider/providers.go | 6 +- internal/provider/purevpn/provider.go | 7 +- internal/provider/purevpn/updater/servers.go | 3 +- internal/provider/purevpn/updater/updater.go | 8 +- internal/publicip/fetch.go | 78 ++++++++++--------- internal/publicip/info.go | 56 ------------- internal/publicip/interfaces.go | 5 +- internal/publicip/loop.go | 9 +-- internal/publicip/models/ipinfo.go | 7 +- internal/publicip/multi.go | 7 +- internal/publicip/runner.go | 24 +++--- 19 files changed, 101 insertions(+), 155 deletions(-) delete mode 100644 internal/publicip/info.go diff --git a/cmd/gluetun/main.go b/cmd/gluetun/main.go index e58a5da8..4d2f06c6 100644 --- a/cmd/gluetun/main.go +++ b/cmd/gluetun/main.go @@ -364,7 +364,8 @@ func _main(ctx context.Context, buildInfo models.BuildInformation, go unboundLooper.RunRestartTicker(dnsTickerCtx, dnsTickerDone) controlGroupHandler.Add(dnsTickerHandler) - publicIPLooper := publicip.NewLoop(httpClient, + ipFetcher := publicip.NewFetch(httpClient) + publicIPLooper := publicip.NewLoop(ipFetcher, logger.New(log.SetComponent("ip getter")), allSettings.PublicIP, puid, pgid) pubIPHandler, pubIPCtx, pubIPDone := goshutdown.NewGoRoutineHandler( @@ -382,7 +383,7 @@ func _main(ctx context.Context, buildInfo models.BuildInformation, unzipper := unzip.New(httpClient) parallelResolver := resolver.NewParallelResolver(allSettings.Updater.DNSAddress) providers := provider.NewProviders(storage, time.Now, - updaterLogger, httpClient, unzipper, parallelResolver) + updaterLogger, httpClient, unzipper, parallelResolver, ipFetcher) vpnLogger := logger.New(log.SetComponent("vpn")) vpnLooper := vpn.NewLoop(allSettings.VPN, allSettings.Firewall.VPNInputPorts, diff --git a/internal/cli/openvpnconfig.go b/internal/cli/openvpnconfig.go index 3707efac..8dfe3c0a 100644 --- a/internal/cli/openvpnconfig.go +++ b/internal/cli/openvpnconfig.go @@ -11,6 +11,7 @@ import ( "github.com/qdm12/gluetun/internal/configuration/sources" "github.com/qdm12/gluetun/internal/constants" "github.com/qdm12/gluetun/internal/provider" + publicipmodels "github.com/qdm12/gluetun/internal/publicip/models" "github.com/qdm12/gluetun/internal/storage" "github.com/qdm12/gluetun/internal/updater/resolver" ) @@ -30,6 +31,10 @@ type ParallelResolver interface { hostToIPs map[string][]net.IP, warnings []string, err error) } +type IPFetcher interface { + FetchMultiInfo(ctx context.Context, ips []net.IP) (data []publicipmodels.IPInfoData, err error) +} + func (c *CLI) OpenvpnConfig(logger OpenvpnConfigLogger, source sources.Source) error { storage, err := storage.New(logger, constants.ServersData) if err != nil { @@ -50,8 +55,10 @@ func (c *CLI) OpenvpnConfig(logger OpenvpnConfigLogger, source sources.Source) e client := (*http.Client)(nil) warner := (Warner)(nil) parallelResolver := (ParallelResolver)(nil) + ipFetcher := (IPFetcher)(nil) - providers := provider.NewProviders(storage, time.Now, warner, client, unzipper, parallelResolver) + providers := provider.NewProviders(storage, time.Now, warner, client, + unzipper, parallelResolver, ipFetcher) providerConf := providers.Get(*allSettings.VPN.Provider.Name) connection, err := providerConf.GetConnection(allSettings.VPN.Provider.ServerSelection) if err != nil { diff --git a/internal/cli/update.go b/internal/cli/update.go index 438c15ab..5a33da94 100644 --- a/internal/cli/update.go +++ b/internal/cli/update.go @@ -13,6 +13,7 @@ import ( "github.com/qdm12/gluetun/internal/constants" "github.com/qdm12/gluetun/internal/constants/providers" "github.com/qdm12/gluetun/internal/provider" + "github.com/qdm12/gluetun/internal/publicip" "github.com/qdm12/gluetun/internal/storage" "github.com/qdm12/gluetun/internal/updater" "github.com/qdm12/gluetun/internal/updater/resolver" @@ -74,8 +75,10 @@ func (c *CLI) Update(ctx context.Context, args []string, logger UpdaterLogger) e httpClient := &http.Client{Timeout: clientTimeout} unzipper := unzip.New(httpClient) parallelResolver := resolver.NewParallelResolver(options.DNSAddress) + ipFetcher := publicip.NewFetch(httpClient) - providers := provider.NewProviders(storage, time.Now, logger, httpClient, unzipper, parallelResolver) + providers := provider.NewProviders(storage, time.Now, logger, httpClient, + unzipper, parallelResolver, ipFetcher) updater := updater.New(httpClient, storage, providers, logger) err = updater.UpdateServers(ctx, options.Providers) diff --git a/internal/provider/common/updater.go b/internal/provider/common/updater.go index e4bb0db5..6dd3ef22 100644 --- a/internal/provider/common/updater.go +++ b/internal/provider/common/updater.go @@ -6,6 +6,7 @@ import ( "net" "github.com/qdm12/gluetun/internal/models" + publicipmodels "github.com/qdm12/gluetun/internal/publicip/models" "github.com/qdm12/gluetun/internal/updater/resolver" ) @@ -28,3 +29,7 @@ type Unzipper interface { type Warner interface { Warn(s string) } + +type IPFetcher interface { + FetchMultiInfo(ctx context.Context, ips []net.IP) (data []publicipmodels.IPInfoData, err error) +} diff --git a/internal/provider/privado/provider.go b/internal/provider/privado/provider.go index 3c8c4ef6..6d70f861 100644 --- a/internal/provider/privado/provider.go +++ b/internal/provider/privado/provider.go @@ -2,7 +2,6 @@ package privado import ( "math/rand" - "net/http" "github.com/qdm12/gluetun/internal/constants/providers" "github.com/qdm12/gluetun/internal/provider/common" @@ -18,14 +17,14 @@ type Provider struct { } func New(storage common.Storage, randSource rand.Source, - client *http.Client, unzipper common.Unzipper, + ipFetcher common.IPFetcher, unzipper common.Unzipper, updaterWarner common.Warner, parallelResolver common.ParallelResolver) *Provider { return &Provider{ storage: storage, randSource: randSource, NoPortForwarder: utils.NewNoPortForwarding(providers.Privado), - Fetcher: updater.New(client, unzipper, updaterWarner, parallelResolver), + Fetcher: updater.New(ipFetcher, unzipper, updaterWarner, parallelResolver), } } diff --git a/internal/provider/privado/updater/location.go b/internal/provider/privado/updater/location.go index 50a56428..2e11743b 100644 --- a/internal/provider/privado/updater/location.go +++ b/internal/provider/privado/updater/location.go @@ -3,19 +3,18 @@ package updater import ( "context" "net" - "net/http" "github.com/qdm12/gluetun/internal/models" - "github.com/qdm12/gluetun/internal/publicip" + "github.com/qdm12/gluetun/internal/provider/common" ) -func setLocationInfo(ctx context.Context, client *http.Client, servers []models.Server) (err error) { +func setLocationInfo(ctx context.Context, fetcher common.IPFetcher, servers []models.Server) (err error) { // Get public IP address information ipsToGetInfo := make([]net.IP, 0, len(servers)) for _, server := range servers { ipsToGetInfo = append(ipsToGetInfo, server.IPs...) } - ipsInfo, err := publicip.MultiInfo(ctx, client, ipsToGetInfo) + ipsInfo, err := fetcher.FetchMultiInfo(ctx, ipsToGetInfo) if err != nil { return err } diff --git a/internal/provider/privado/updater/servers.go b/internal/provider/privado/updater/servers.go index 913f24f8..5febd42e 100644 --- a/internal/provider/privado/updater/servers.go +++ b/internal/provider/privado/updater/servers.go @@ -68,7 +68,7 @@ func (u *Updater) FetchServers(ctx context.Context, minServers int) ( servers = hts.toServersSlice() - if err := setLocationInfo(ctx, u.client, servers); err != nil { + if err := setLocationInfo(ctx, u.ipFetcher, servers); err != nil { return nil, err } diff --git a/internal/provider/privado/updater/updater.go b/internal/provider/privado/updater/updater.go index 1d269789..65ee9cfe 100644 --- a/internal/provider/privado/updater/updater.go +++ b/internal/provider/privado/updater/updater.go @@ -1,22 +1,20 @@ package updater import ( - "net/http" - "github.com/qdm12/gluetun/internal/provider/common" ) type Updater struct { - client *http.Client + ipFetcher common.IPFetcher unzipper common.Unzipper parallelResolver common.ParallelResolver warner common.Warner } -func New(client *http.Client, unzipper common.Unzipper, +func New(ipFetcher common.IPFetcher, unzipper common.Unzipper, warner common.Warner, parallelResolver common.ParallelResolver) *Updater { return &Updater{ - client: client, + ipFetcher: ipFetcher, unzipper: unzipper, parallelResolver: parallelResolver, warner: warner, diff --git a/internal/provider/providers.go b/internal/provider/providers.go index a83b2be2..b2f00f58 100644 --- a/internal/provider/providers.go +++ b/internal/provider/providers.go @@ -45,7 +45,7 @@ type Storage interface { func NewProviders(storage Storage, timeNow func() time.Time, updaterWarner common.Warner, client *http.Client, unzipper common.Unzipper, - parallelResolver common.ParallelResolver) *Providers { + parallelResolver common.ParallelResolver, ipFetcher common.IPFetcher) *Providers { randSource := rand.NewSource(timeNow().UnixNano()) //nolint:lll @@ -60,11 +60,11 @@ func NewProviders(storage Storage, timeNow func() time.Time, providers.Mullvad: mullvad.New(storage, randSource, client), providers.Nordvpn: nordvpn.New(storage, randSource, client, updaterWarner), providers.Perfectprivacy: perfectprivacy.New(storage, randSource, unzipper, updaterWarner), - providers.Privado: privado.New(storage, randSource, client, unzipper, updaterWarner, parallelResolver), + providers.Privado: privado.New(storage, randSource, ipFetcher, unzipper, updaterWarner, parallelResolver), providers.PrivateInternetAccess: privateinternetaccess.New(storage, randSource, timeNow, client), providers.Privatevpn: privatevpn.New(storage, randSource, unzipper, updaterWarner, parallelResolver), providers.Protonvpn: protonvpn.New(storage, randSource, client, updaterWarner, parallelResolver), - providers.Purevpn: purevpn.New(storage, randSource, client, unzipper, updaterWarner, parallelResolver), + providers.Purevpn: purevpn.New(storage, randSource, ipFetcher, unzipper, updaterWarner, parallelResolver), providers.Surfshark: surfshark.New(storage, randSource, client, unzipper, updaterWarner, parallelResolver), providers.Torguard: torguard.New(storage, randSource, unzipper, updaterWarner, parallelResolver), providers.VPNUnlimited: vpnunlimited.New(storage, randSource, unzipper, updaterWarner, parallelResolver), diff --git a/internal/provider/purevpn/provider.go b/internal/provider/purevpn/provider.go index dc6e9adc..6442b6e8 100644 --- a/internal/provider/purevpn/provider.go +++ b/internal/provider/purevpn/provider.go @@ -2,7 +2,6 @@ package purevpn import ( "math/rand" - "net/http" "github.com/qdm12/gluetun/internal/constants/providers" "github.com/qdm12/gluetun/internal/provider/common" @@ -18,13 +17,13 @@ type Provider struct { } func New(storage common.Storage, randSource rand.Source, - client *http.Client, unzipper common.Unzipper, updaterWarner common.Warner, - parallelResolver common.ParallelResolver) *Provider { + ipFetcher common.IPFetcher, unzipper common.Unzipper, + updaterWarner common.Warner, parallelResolver common.ParallelResolver) *Provider { return &Provider{ storage: storage, randSource: randSource, NoPortForwarder: utils.NewNoPortForwarding(providers.Purevpn), - Fetcher: updater.New(client, unzipper, updaterWarner, parallelResolver), + Fetcher: updater.New(ipFetcher, unzipper, updaterWarner, parallelResolver), } } diff --git a/internal/provider/purevpn/updater/servers.go b/internal/provider/purevpn/updater/servers.go index 77cb67e0..434e5270 100644 --- a/internal/provider/purevpn/updater/servers.go +++ b/internal/provider/purevpn/updater/servers.go @@ -11,7 +11,6 @@ import ( "github.com/qdm12/gluetun/internal/models" "github.com/qdm12/gluetun/internal/provider/common" - "github.com/qdm12/gluetun/internal/publicip" "github.com/qdm12/gluetun/internal/updater/openvpn" ) @@ -83,7 +82,7 @@ func (u *Updater) FetchServers(ctx context.Context, minServers int) ( for i := range servers { ipsToGetInfo[i] = servers[i].IPs[0] } - ipsInfo, err := publicip.MultiInfo(ctx, u.client, ipsToGetInfo) + ipsInfo, err := u.ipFetcher.FetchMultiInfo(ctx, ipsToGetInfo) if err != nil { return nil, err } diff --git a/internal/provider/purevpn/updater/updater.go b/internal/provider/purevpn/updater/updater.go index 1d269789..65ee9cfe 100644 --- a/internal/provider/purevpn/updater/updater.go +++ b/internal/provider/purevpn/updater/updater.go @@ -1,22 +1,20 @@ package updater import ( - "net/http" - "github.com/qdm12/gluetun/internal/provider/common" ) type Updater struct { - client *http.Client + ipFetcher common.IPFetcher unzipper common.Unzipper parallelResolver common.ParallelResolver warner common.Warner } -func New(client *http.Client, unzipper common.Unzipper, +func New(ipFetcher common.IPFetcher, unzipper common.Unzipper, warner common.Warner, parallelResolver common.ParallelResolver) *Updater { return &Updater{ - client: client, + ipFetcher: ipFetcher, unzipper: unzipper, parallelResolver: parallelResolver, warner: warner, diff --git a/internal/publicip/fetch.go b/internal/publicip/fetch.go index 7b9d69ed..a95828aa 100644 --- a/internal/publicip/fetch.go +++ b/internal/publicip/fetch.go @@ -3,66 +3,74 @@ package publicip import ( "context" + "encoding/json" "errors" "fmt" - "io" - "math/rand" "net" "net/http" "strings" + + "github.com/qdm12/gluetun/internal/constants" + "github.com/qdm12/gluetun/internal/publicip/models" ) type Fetch struct { - client *http.Client - randIntn func(n int) int + client *http.Client } func NewFetch(client *http.Client) *Fetch { return &Fetch{ - client: client, - randIntn: rand.Intn, + client: client, } } -var ErrParseIP = errors.New("cannot parse IP address") +var ( + ErrTooManyRequests = errors.New("too many requests sent for this month") + ErrBadHTTPStatus = errors.New("bad HTTP status received") +) -func (f *Fetch) FetchPublicIP(ctx context.Context) (ip net.IP, err error) { - urls := []string{ - "https://ifconfig.me/ip", - "http://ip1.dynupdate.no-ip.com:8245", - "http://ip1.dynupdate.no-ip.com", - "https://api.ipify.org", - "https://domains.google.com/checkip", - "https://ifconfig.io/ip", - "https://ipinfo.io/ip", - } - url := urls[f.randIntn(len(urls))] - - req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) - if err != nil { - return nil, err +// FetchInfo obtains information on the ip address provided +// using the ipinfo.io API. If the ip is nil, the public IP address +// of the machine is used as the IP. +func (f *Fetch) FetchInfo(ctx context.Context, ip net.IP) ( + result models.IPInfoData, err error) { + const baseURL = "https://ipinfo.io/" + url := baseURL + if ip != nil { + url += ip.String() } - response, err := f.client.Do(req) + request, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) if err != nil { - return nil, err + return result, err + } + + response, err := f.client.Do(request) + if err != nil { + return result, err } defer response.Body.Close() - if response.StatusCode != http.StatusOK { - return nil, fmt.Errorf("%w from %s: %d %s", ErrBadStatusCode, - url, response.StatusCode, response.Status) + switch response.StatusCode { + case http.StatusOK: + case http.StatusTooManyRequests: + return result, fmt.Errorf("%w from %s: %d %s", + ErrTooManyRequests, url, response.StatusCode, response.Status) + default: + return result, fmt.Errorf("%w from %s: %d %s", + ErrBadHTTPStatus, url, response.StatusCode, response.Status) } - content, err := io.ReadAll(response.Body) - if err != nil { - return nil, fmt.Errorf("cannot ready response body: %w", err) + decoder := json.NewDecoder(response.Body) + if err := decoder.Decode(&result); err != nil { + return result, fmt.Errorf("cannot decode response: %w", err) } - s := strings.ReplaceAll(string(content), "\n", "") - ip = net.ParseIP(s) - if ip == nil { - return nil, fmt.Errorf("%w: %s", ErrParseIP, s) + countryCode := strings.ToLower(result.Country) + country, ok := constants.CountryCodes()[countryCode] + if ok { + result.Country = country } - return ip, nil + + return result, nil } diff --git a/internal/publicip/info.go b/internal/publicip/info.go deleted file mode 100644 index d28e3583..00000000 --- a/internal/publicip/info.go +++ /dev/null @@ -1,56 +0,0 @@ -package publicip - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "net" - "net/http" - "strings" - - "github.com/qdm12/gluetun/internal/constants" - "github.com/qdm12/gluetun/internal/publicip/models" -) - -var ( - ErrTooManyRequests = errors.New("too many requests sent for this month") - ErrBadHTTPStatus = errors.New("bad HTTP status received") -) - -func Info(ctx context.Context, client *http.Client, ip net.IP) ( //nolint:interfacer - result models.IPInfoData, err error) { - const baseURL = "https://ipinfo.io/" - url := baseURL + ip.String() - request, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) - if err != nil { - return result, err - } - - response, err := client.Do(request) - if err != nil { - return result, err - } - defer response.Body.Close() - - switch response.StatusCode { - case http.StatusOK: - case http.StatusTooManyRequests: - return result, fmt.Errorf("%w: %s", ErrTooManyRequests, baseURL) - default: - return result, fmt.Errorf("%w: %d %s", ErrBadHTTPStatus, - response.StatusCode, response.Status) - } - - decoder := json.NewDecoder(response.Body) - if err := decoder.Decode(&result); err != nil { - return result, err - } - - countryCode := strings.ToLower(result.Country) - country, ok := constants.CountryCodes()[countryCode] - if ok { - result.Country = country - } - return result, nil -} diff --git a/internal/publicip/interfaces.go b/internal/publicip/interfaces.go index 3cfdbe0f..031395b7 100644 --- a/internal/publicip/interfaces.go +++ b/internal/publicip/interfaces.go @@ -23,6 +23,7 @@ type stateManager interface { SetSettings(ctx context.Context, settings settings.PublicIP) (outcome string) } -type fetcher interface { - FetchPublicIP(ctx context.Context) (ip net.IP, err error) +type Fetcher interface { + FetchInfo(ctx context.Context, ip net.IP) ( + result publicipmodels.IPInfoData, err error) } diff --git a/internal/publicip/loop.go b/internal/publicip/loop.go index f96a3b62..0ab5ae62 100644 --- a/internal/publicip/loop.go +++ b/internal/publicip/loop.go @@ -1,7 +1,6 @@ package publicip import ( - "net/http" "time" "github.com/qdm12/gluetun/internal/configuration/settings" @@ -15,8 +14,7 @@ type Loop struct { statusManager statusManager state stateManager // Objects - fetcher fetcher - client *http.Client + fetcher Fetcher logger Logger // Fixed settings puid int @@ -35,7 +33,7 @@ type Loop struct { const defaultBackoffTime = 5 * time.Second -func NewLoop(client *http.Client, logger Logger, +func NewLoop(fetcher Fetcher, logger Logger, settings settings.PublicIP, puid, pgid int) *Loop { start := make(chan struct{}) running := make(chan models.LoopStatus) @@ -50,8 +48,7 @@ func NewLoop(client *http.Client, logger Logger, statusManager: statusManager, state: state, // Objects - client: client, - fetcher: NewFetch(client), + fetcher: fetcher, logger: logger, puid: puid, pgid: pgid, diff --git a/internal/publicip/models/ipinfo.go b/internal/publicip/models/ipinfo.go index b074248d..792d126c 100644 --- a/internal/publicip/models/ipinfo.go +++ b/internal/publicip/models/ipinfo.go @@ -3,7 +3,7 @@ package models import "net" type IPInfoData struct { - IP net.IP `json:"public_ip"` + IP net.IP `json:"ip,omitempty"` Region string `json:"region,omitempty"` Country string `json:"country,omitempty"` City string `json:"city,omitempty"` @@ -20,8 +20,3 @@ func (i IPInfoData) Copy() (copied IPInfoData) { copy(copied.IP, i.IP) return copied } - -func (i *IPInfoData) SetIP(ip net.IP) { - i.IP = make(net.IP, len(ip)) - copy(i.IP, ip) -} diff --git a/internal/publicip/multi.go b/internal/publicip/multi.go index c06243b6..79108c87 100644 --- a/internal/publicip/multi.go +++ b/internal/publicip/multi.go @@ -3,18 +3,17 @@ package publicip import ( "context" "net" - "net/http" "github.com/qdm12/gluetun/internal/publicip/models" ) -// MultiInfo obtains the public IP address information for every IP +// FetchMultiInfo obtains the public IP address information for every IP // addresses provided and returns a slice of results with the corresponding // order as to the IP addresses slice order. // If an error is encountered, all the operations are canceled and // an error is returned, so the results returned should be considered // incomplete in this case. -func MultiInfo(ctx context.Context, client *http.Client, ips []net.IP) ( +func (f *Fetch) FetchMultiInfo(ctx context.Context, ips []net.IP) ( results []models.IPInfoData, err error) { ctx, cancel := context.WithCancel(ctx) @@ -30,7 +29,7 @@ func MultiInfo(ctx context.Context, client *http.Client, ips []net.IP) ( aResult := asyncResult{ index: index, } - aResult.result, aResult.err = Info(ctx, client, ip) + aResult.result, aResult.err = f.FetchInfo(ctx, ip) resultsCh <- aResult }(i, ip) } diff --git a/internal/publicip/runner.go b/internal/publicip/runner.go index 2a5325af..1ce73b0c 100644 --- a/internal/publicip/runner.go +++ b/internal/publicip/runner.go @@ -2,10 +2,10 @@ package publicip import ( "context" - "net" "os" "github.com/qdm12/gluetun/internal/constants" + "github.com/qdm12/gluetun/internal/publicip/models" ) func (l *Loop) Run(ctx context.Context, done chan<- struct{}) { @@ -21,17 +21,17 @@ func (l *Loop) Run(ctx context.Context, done chan<- struct{}) { getCtx, getCancel := context.WithCancel(ctx) defer getCancel() - ipCh := make(chan net.IP) + resultCh := make(chan models.IPInfoData) errorCh := make(chan error) go func() { - ip, err := l.fetcher.FetchPublicIP(getCtx) + result, err := l.fetcher.FetchInfo(getCtx, nil) if err != nil { if getCtx.Err() == nil { errorCh <- err } return } - ipCh <- ip + resultCh <- result }() if l.userTrigger { @@ -64,30 +64,24 @@ func (l *Loop) Run(ctx context.Context, done chan<- struct{}) { getCancel() <-errorCh l.stopped <- struct{}{} - case ip := <-ipCh: + case result := <-resultCh: getCancel() - message := "Public IP address is " + ip.String() - result, err := Info(ctx, l.client, ip) - if err != nil { - l.logger.Warn(err.Error()) - } else { - message += " (" + result.Country + ", " + result.Region + ", " + result.City + ")" - } + message := "Public IP address is " + result.IP.String() + message += " (" + result.Country + ", " + result.Region + ", " + result.City + ")" l.logger.Info(message) - result.SetIP(ip) l.state.SetData(result) filepath := *l.state.GetSettings().IPFilepath - err = persistPublicIP(filepath, ip.String(), l.puid, l.pgid) + err := persistPublicIP(filepath, result.IP.String(), l.puid, l.pgid) if err != nil { l.logger.Error(err.Error()) } l.statusManager.SetStatus(constants.Completed) case err := <-errorCh: getCancel() - close(ipCh) + close(resultCh) l.statusManager.SetStatus(constants.Crashed) l.logAndWait(ctx, err) stayHere = false