Compare commits

..

9 Commits

Author SHA1 Message Date
Snawoot
6aa4fc334a Merge pull request #127 from Snawoot/upd_doc
upd doc
2024-11-05 22:02:53 +02:00
Vladislav Yarmak
124212a5e2 upd doc 2024-11-05 22:02:09 +02:00
Vladislav Yarmak
b120cb5462 bump snap version 2024-11-05 22:00:33 +02:00
Snawoot
972771b6af Merge pull request #126 from Snawoot/deps_upd
Dependencies update
2024-11-05 21:59:53 +02:00
Vladislav Yarmak
49b6ba9147 go mod tidy 2024-11-05 21:59:13 +02:00
Vladislav Yarmak
1e4c6684cc dependencies update 2024-11-05 21:58:26 +02:00
Snawoot
569bf1d39f Merge pull request #125 from Snawoot/try_hard
Retry init
2024-11-05 21:44:43 +02:00
Vladislav Yarmak
92fdd4fb72 retry init 2024-11-05 21:38:04 +02:00
Vladislav Yarmak
d4d37bb354 upd doc 2024-10-07 21:09:53 +03:00
6 changed files with 121 additions and 71 deletions

View File

@@ -165,6 +165,8 @@ zagent248.hola.org,165.22.65.3,22222,22223,22224,22225,22226,digitalocean
| ext-ver | String | extension version to mimic in requests. Can be obtained from https://chrome.google.com/webstore/detail/hola-vpn-the-website-unbl/gkojfkhlekighikafcpjkiklfbnlmeio (default "999.999.999") |
| force-port-field | Number | force specific port field/num (example 24232 or lum) |
| hide-SNI | Boolean | hide SNI in TLS sessions with proxy server (default true) |
| init-retries | Number | number of attempts for initialization steps, zero for unlimited retry |
| init-retry-interval | Duration | delay between initialization retries (default 5s) |
| limit | Unsigned Integer (Number) | amount of proxies in retrieved list (default 3) |
| list-countries | String | list available countries and exit |
| list-proxies | - | output proxy list and exit |
@@ -173,7 +175,7 @@ zagent248.hola.org,165.22.65.3,22222,22223,22224,22225,22226,digitalocean
| resolver | String | DNS/DoH/DoT resolver to workaround Hola blocked hosts. See https://github.com/ameshkov/dnslookup/ for upstream DNS URL format. (default "https://cloudflare-dns.com/dns-query") |
| rotate | Duration | rotate user ID once per given period (default 1h0m0s) |
| timeout | Duration | timeout for network operations (default 35s) |
| user-agent | String | value of User-Agent header in requests (default "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36") |
| user-agent | String | value of User-Agent header in requests (default "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36") |
| verbosity | Number | logging verbosity (10 - debug, 20 - info, 30 - warning, 40 - error, 50 - critical) (default 20) |
## See also

18
go.mod
View File

@@ -13,22 +13,22 @@ require (
)
require (
github.com/AdguardTeam/golibs v0.29.0 // indirect
github.com/AdguardTeam/golibs v0.30.2 // indirect
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 // indirect
github.com/ameshkov/dnscrypt/v2 v2.3.0 // indirect
github.com/ameshkov/dnsstamps v1.0.3 // indirect
github.com/andybalholm/brotli v1.1.0 // indirect
github.com/cloudflare/circl v1.4.0 // indirect
github.com/andybalholm/brotli v1.1.1 // indirect
github.com/cloudflare/circl v1.5.0 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/google/pprof v0.0.0-20241001023024-f4c0cfd0cf1d // indirect
github.com/klauspost/compress v1.17.10 // indirect
github.com/onsi/ginkgo/v2 v2.20.2 // indirect
github.com/google/pprof v0.0.0-20241101162523-b92577c0c142 // indirect
github.com/klauspost/compress v1.17.11 // indirect
github.com/onsi/ginkgo/v2 v2.21.0 // indirect
github.com/quic-go/qpack v0.5.1 // indirect
github.com/quic-go/quic-go v0.47.0 // indirect
go.uber.org/mock v0.4.0 // indirect
github.com/quic-go/quic-go v0.48.1 // indirect
go.uber.org/mock v0.5.0 // indirect
golang.org/x/crypto v0.28.0 // indirect
golang.org/x/exp v0.0.0-20241004190924-225e2abe05e6 // indirect
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect
golang.org/x/mod v0.21.0 // indirect
golang.org/x/sync v0.8.0 // indirect
golang.org/x/sys v0.26.0 // indirect

42
go.sum
View File

@@ -1,7 +1,7 @@
github.com/AdguardTeam/dnsproxy v0.73.2 h1:O6wRXzHsnWL5TkhYcuLWCShVFF0X5RFI6qUmq1ZFVsQ=
github.com/AdguardTeam/dnsproxy v0.73.2/go.mod h1:zD5WfTctbRvYYk8PS39h6/OT84NTu6QxKbAiBN5PUcI=
github.com/AdguardTeam/golibs v0.29.0 h1:NG3eUXaUwRTgKssblolh4XHME8MQCCdogyIZxxv4bOU=
github.com/AdguardTeam/golibs v0.29.0/go.mod h1:vjw1OVZG6BYyoqGRY88U4LCJLOMfhBFhU0UJBdaSAuQ=
github.com/AdguardTeam/golibs v0.30.2 h1:urU/NAyIvQOeArBqDmKCDpaRkfTCJ26uSiSuDMKQfuY=
github.com/AdguardTeam/golibs v0.30.2/go.mod h1:FkwcNQEJoGsgDGXcalrVa/4gWbE68KsmE2guXWtBQUE=
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY=
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA=
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 h1:52m0LGchQBBVqJRyYYufQuIbVqRawmubW3OFGqK1ekw=
@@ -10,14 +10,14 @@ github.com/ameshkov/dnscrypt/v2 v2.3.0 h1:pDXDF7eFa6Lw+04C0hoMh8kCAQM8NwUdFEllSP
github.com/ameshkov/dnscrypt/v2 v2.3.0/go.mod h1:N5hDwgx2cNb4Ay7AhvOSKst+eUiOZ/vbKRO9qMpQttE=
github.com/ameshkov/dnsstamps v1.0.3 h1:Srzik+J9mivH1alRACTbys2xOxs0lRH9qnTA7Y1OYVo=
github.com/ameshkov/dnsstamps v1.0.3/go.mod h1:Ii3eUu73dx4Vw5O4wjzmT5+lkCwovjzaEZZ4gKyIH5A=
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA=
github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA=
github.com/campoy/unique v0.0.0-20180121183637-88950e537e7e h1:V9a67dfYqPLAvzk5hMQOXYJlZ4SLIXgyKIE+ZiHzgGQ=
github.com/campoy/unique v0.0.0-20180121183637-88950e537e7e/go.mod h1:9IOqJGCPMSc6E5ydlp5NIonxObaeu/Iub/X03EKPVYo=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/cloudflare/circl v1.4.0 h1:BV7h5MgrktNzytKmWjpOtdYrf0lkkbF8YMlBGPhJQrY=
github.com/cloudflare/circl v1.4.0/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU=
github.com/cloudflare/circl v1.5.0 h1:hxIWksrX6XN5a1L2TI/h53AGPhNHoUBo+TD1ms9+pys=
github.com/cloudflare/circl v1.5.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
@@ -26,34 +26,36 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/pprof v0.0.0-20241001023024-f4c0cfd0cf1d h1:Jaz2JzpQaQXyET0AjLBXShrthbpqMkhGiEfkcQAiAUs=
github.com/google/pprof v0.0.0-20241001023024-f4c0cfd0cf1d/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/pprof v0.0.0-20241101162523-b92577c0c142 h1:sAGdeJj0bnMgUNVeUpp6AYlVdCt3/GdI3pGRqsNSQLs=
github.com/google/pprof v0.0.0-20241101162523-b92577c0c142/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/klauspost/compress v1.17.10 h1:oXAz+Vh0PMUvJczoi+flxpnBEPxoER1IaAnU/NMPtT0=
github.com/klauspost/compress v1.17.10/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ=
github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ=
github.com/onsi/ginkgo/v2 v2.20.2 h1:7NVCeyIWROIAheY21RLS+3j2bb52W0W82tkberYytp4=
github.com/onsi/ginkgo/v2 v2.20.2/go.mod h1:K9gyxPIlb+aIvnZ8bd9Ak+YP18w3APlR+5coaZoE2ag=
github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM=
github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8=
github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
github.com/quic-go/quic-go v0.47.0 h1:yXs3v7r2bm1wmPTYNLKAAJTHMYkPEsfYJmTazXrCZ7Y=
github.com/quic-go/quic-go v0.47.0/go.mod h1:3bCapYsJvXGZcipOHuu7plYtaV6tnF+z7wIFsU0WK9E=
github.com/quic-go/quic-go v0.48.1 h1:y/8xmfWI9qmGTc+lBr4jKRUWLGSlSigv847ULJ4hYXA=
github.com/quic-go/quic-go v0.48.1/go.mod h1:yBgs3rWBOADpga7F+jJsb6Ybg1LSYiQvwWlLX+/6HMs=
github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B2MR1K67ULZM=
github.com/refraction-networking/utls v1.6.7/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
golang.org/x/exp v0.0.0-20241004190924-225e2abe05e6 h1:1wqE9dj9NpSm04INVsJhhEUzhuDVjbcyKH91sVyPATw=
golang.org/x/exp v0.0.0-20241004190924-225e2abe05e6/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8=
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY=
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8=
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=

58
main.go
View File

@@ -64,6 +64,8 @@ type CLIArgs struct {
maxPause time.Duration
backoffInitial time.Duration
backoffDeadline time.Duration
initRetries int
initRetryInterval time.Duration
hideSNI bool
userAgent string
}
@@ -84,6 +86,8 @@ func parse_args() CLIArgs {
flag.DurationVar(&args.rotate, "rotate", 1*time.Hour, "rotate user ID once per given period")
flag.DurationVar(&args.backoffInitial, "backoff-initial", 3*time.Second, "initial average backoff delay for zgettunnels (randomized by +/-50%)")
flag.DurationVar(&args.backoffDeadline, "backoff-deadline", 5*time.Minute, "total duration of zgettunnels method attempts")
flag.IntVar(&args.initRetries, "init-retries", 0, "number of attempts for initialization steps, zero for unlimited retry")
flag.DurationVar(&args.initRetryInterval, "init-retry-interval", 5*time.Second, "delay between initialization retries")
flag.StringVar(&args.proxy_type, "proxy-type", "direct", "proxy type: direct or lum") // or skip but not mentioned
// skip would be used something like this: `./bin/hola-proxy -proxy-type skip -force-port-field 24232 -country ua.peer` for debugging
flag.StringVar(&args.resolver, "resolver", "https://cloudflare-dns.com/dns-query",
@@ -180,28 +184,32 @@ func run() int {
SetUserAgent(args.userAgent)
try := retryPolicy(args.initRetries, args.initRetryInterval, mainLogger)
if args.list_countries {
return print_countries(args.timeout)
return print_countries(try, args.timeout)
}
mainLogger.Info("hola-proxy client version %s is starting...", version)
if args.extVer == "" {
ctx, cl := context.WithTimeout(context.Background(), args.timeout)
defer cl()
extVer, err := GetExtVer(ctx, nil, HolaExtStoreID, dialer)
err := try("get latest version of browser extension", func() error {
ctx, cl := context.WithTimeout(context.Background(), args.timeout)
defer cl()
extVer, err := GetExtVer(ctx, nil, HolaExtStoreID, dialer)
args.extVer = extVer
return err
})
if err != nil {
mainLogger.Critical("Can't detect latest API version. Try to specify -ext-ver parameter. Error: %v", err)
return 8
}
args.extVer = extVer
mainLogger.Warning("Detected latest extension version: %q. Pass -ext-ver parameter to skip resolve and speedup startup", args.extVer)
cl()
}
if args.list_proxies {
return print_proxies(mainLogger, args.extVer, args.country, args.proxy_type, args.limit, args.timeout,
return print_proxies(try, mainLogger, args.extVer, args.country, args.proxy_type, args.limit, args.timeout,
args.backoffInitial, args.backoffDeadline)
}
mainLogger.Info("hola-proxy client version %s is starting...", version)
mainLogger.Info("Constructing fallback DNS upstream...")
resolver, err := NewResolver(args.resolver, args.timeout)
if err != nil {
@@ -209,11 +217,16 @@ func run() int {
return 6
}
mainLogger.Info("Initializing configuration provider...")
auth, tunnels, err := CredService(args.rotate, args.timeout, args.extVer, args.country,
args.proxy_type, credLogger, args.backoffInitial, args.backoffDeadline)
var (
auth AuthProvider
tunnels *ZGetTunnelsResponse
)
err = try("run credentials service", func() error {
auth, tunnels, err = CredService(args.rotate, args.timeout, args.extVer, args.country,
args.proxy_type, credLogger, args.backoffInitial, args.backoffDeadline)
return err
})
if err != nil {
mainLogger.Critical("Unable to instantiate credential service: %v", err)
return 4
}
endpoint, err := get_endpoint(tunnels, args.proxy_type, args.use_trial, args.force_port_field)
@@ -236,3 +249,24 @@ func run() int {
func main() {
os.Exit(run())
}
func retryPolicy(retries int, retryInterval time.Duration, logger *CondLogger) func(string, func() error) error {
return func(name string, f func() error) error {
var err error
for i := 1; retries <= 0 || i <= retries; i++ {
if i > 1 {
logger.Warning("Retrying action %q in %v...", name, retryInterval)
time.Sleep(retryInterval)
}
logger.Info("Attempting action %q, attempt #%d...", name, i)
err = f()
if err == nil {
logger.Info("Action %q succeeded on attempt #%d", name, i)
return nil
}
logger.Warning("Action %q failed: %v", name, err)
}
logger.Critical("All attempts for action %q have failed. Last error: %v", name, err)
return err
}
}

View File

@@ -1,5 +1,5 @@
name: hola-proxy
version: '1.13.4'
version: '1.14.0'
summary: Standalone Hola proxy client.
description: |
Standalone Hola proxy client. Just run it and it'll start plain HTTP proxy server forwarding traffic via Hola proxies of your choice.

View File

@@ -106,27 +106,33 @@ func proxyh2(ctx context.Context, leftreader io.ReadCloser, leftwriter io.Writer
return
}
func print_countries(timeout time.Duration) int {
func print_countries(try func(string, func() error) error, timeout time.Duration) int {
var (
countries CountryList
err error
tx_res bool
tx_err error
)
tx_res, tx_err := EnsureTransaction(context.Background(), timeout, func(ctx context.Context, client *http.Client) bool {
ctx1, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
countries, err = VPNCountries(ctx1, client)
if err != nil {
fmt.Fprintf(os.Stderr, "Transaction error: %v. Retrying with the fallback mechanism...\n", err)
return false
err = try("list VPN countries", func() error {
tx_res, tx_err = EnsureTransaction(context.Background(), timeout, func(ctx context.Context, client *http.Client) bool {
ctx1, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
countries, err = VPNCountries(ctx1, client)
if err != nil {
fmt.Fprintf(os.Stderr, "Transaction error: %v. Retrying with the fallback mechanism...\n", err)
return false
}
return true
})
if tx_err != nil {
return fmt.Errorf("transaction recovery mechanism failure: %v", err)
}
return true
if !tx_res {
return errors.New("all fallback proxies failed.")
}
return nil
})
if tx_err != nil {
fmt.Fprintf(os.Stderr, "Transaction recovery mechanism failure: %v.\n", tx_err)
return 4
}
if !tx_res {
fmt.Fprintf(os.Stderr, "All attempts failed.")
if err != nil {
return 3
}
for _, code := range countries {
@@ -135,28 +141,34 @@ func print_countries(timeout time.Duration) int {
return 0
}
func print_proxies(logger *CondLogger, extVer, country string, proxy_type string,
func print_proxies(try func(string, func() error) error, logger *CondLogger, extVer, country string, proxy_type string,
limit uint, timeout time.Duration, backoffInitial time.Duration, backoffDeadline time.Duration,
) int {
var (
tunnels *ZGetTunnelsResponse
user_uuid string
err error
tx_res bool
tx_err error
)
tx_res, tx_err := EnsureTransaction(context.Background(), timeout, func(ctx context.Context, client *http.Client) bool {
tunnels, user_uuid, err = Tunnels(ctx, logger, client, extVer, country, proxy_type, limit, timeout, backoffInitial, backoffDeadline)
if err != nil {
fmt.Fprintf(os.Stderr, "Transaction error: %v. Retrying with the fallback mechanism...\n", err)
return false
err = try("list proxies", func() error {
tx_res, tx_err = EnsureTransaction(context.Background(), timeout, func(ctx context.Context, client *http.Client) bool {
tunnels, user_uuid, err = Tunnels(ctx, logger, client, extVer, country, proxy_type, limit, timeout, backoffInitial, backoffDeadline)
if err != nil {
fmt.Fprintf(os.Stderr, "Transaction error: %v. Retrying with the fallback mechanism...\n", err)
return false
}
return true
})
if tx_err != nil {
return fmt.Errorf("transaction recovery mechanism failure: %v", err)
}
return true
if !tx_res {
return errors.New("all fallback proxies failed.")
}
return nil
})
if tx_err != nil {
fmt.Fprintf(os.Stderr, "Transaction recovery mechanism failure: %v.\n", tx_err)
return 4
}
if !tx_res {
fmt.Fprintf(os.Stderr, "All attempts failed.")
if err != nil {
return 3
}
wr := csv.NewWriter(os.Stdout)