* Asynchronous repeatResolve * Parallel cyberghost and PIA (v3) processing, with a 10 goroutines limit * Add missing vyprvpn cli flag to updater * Increase DNS repetitions to 5 in order to obtain more IP addresses * Update old PIA IP addresses * Add Surfshark servers by API (unused for now)
81 lines
1.6 KiB
Go
81 lines
1.6 KiB
Go
package updater
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"net"
|
|
"sort"
|
|
)
|
|
|
|
func newResolver(resolverAddress string) *net.Resolver {
|
|
return &net.Resolver{
|
|
PreferGo: true,
|
|
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
|
|
d := net.Dialer{}
|
|
return d.DialContext(ctx, "udp", net.JoinHostPort(resolverAddress, "53"))
|
|
},
|
|
}
|
|
}
|
|
|
|
func newLookupIP(r *net.Resolver) lookupIPFunc {
|
|
return func(ctx context.Context, host string) (ips []net.IP, err error) {
|
|
addresses, err := r.LookupIPAddr(ctx, host)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
ips = make([]net.IP, len(addresses))
|
|
for i := range addresses {
|
|
ips[i] = addresses[i].IP
|
|
}
|
|
return ips, nil
|
|
}
|
|
}
|
|
|
|
func resolveRepeat(ctx context.Context, lookupIP lookupIPFunc, host string, n int) (ips []net.IP, err error) {
|
|
foundIPs := make(chan []net.IP)
|
|
errors := make(chan error)
|
|
ctx, cancel := context.WithCancel(ctx)
|
|
defer cancel()
|
|
for i := 0; i < n; i++ {
|
|
go func() {
|
|
newIPs, err := lookupIP(ctx, host)
|
|
if err != nil {
|
|
errors <- err
|
|
} else {
|
|
foundIPs <- newIPs
|
|
}
|
|
}()
|
|
}
|
|
|
|
uniqueIPs := make(map[string]struct{})
|
|
for i := 0; i < n; i++ {
|
|
select {
|
|
case newIPs := <-foundIPs:
|
|
for _, ip := range newIPs {
|
|
key := ip.String()
|
|
uniqueIPs[key] = struct{}{}
|
|
}
|
|
case newErr := <-errors:
|
|
if err == nil {
|
|
err = newErr
|
|
cancel()
|
|
}
|
|
}
|
|
}
|
|
|
|
ips = make([]net.IP, 0, len(uniqueIPs))
|
|
for key := range uniqueIPs {
|
|
ip := net.ParseIP(key)
|
|
if ipv4 := ip.To4(); ipv4 != nil {
|
|
ip = ipv4
|
|
}
|
|
ips = append(ips, ip)
|
|
}
|
|
|
|
sort.Slice(ips, func(i, j int) bool {
|
|
return bytes.Compare(ips[i], ips[j]) < 1
|
|
})
|
|
|
|
return ips, err
|
|
}
|