Files
opera-proxy/resolver/fast.go
T

76 lines
1.6 KiB
Go
Raw Normal View History

2025-08-12 19:38:17 +03:00
package resolver
import (
"context"
2026-01-08 22:38:17 +02:00
"crypto/x509"
2025-08-12 19:38:17 +03:00
"fmt"
"net/netip"
2026-04-13 21:23:26 +03:00
"github.com/Alexey71/go-multierror"
2025-08-12 19:38:17 +03:00
)
type LookupNetIPer interface {
LookupNetIP(context.Context, string, string) ([]netip.Addr, error)
}
type FastResolver struct {
upstreams []LookupNetIPer
}
2026-01-08 22:38:17 +02:00
func FastFromURLs(caPool *x509.CertPool, urls ...string) (LookupNetIPer, error) {
2025-08-12 19:38:17 +03:00
resolvers := make([]LookupNetIPer, 0, len(urls))
for i, u := range urls {
2026-01-08 22:38:17 +02:00
res, err := FromURL(u, caPool)
2025-08-12 19:38:17 +03:00
if err != nil {
return nil, fmt.Errorf("unable to construct resolver #%d (%q): %w", i, u, err)
}
resolvers = append(resolvers, res)
}
if len(resolvers) == 1 {
return resolvers[0], nil
}
2025-08-12 19:38:17 +03:00
return NewFastResolver(resolvers...), nil
}
func NewFastResolver(resolvers ...LookupNetIPer) *FastResolver {
return &FastResolver{
upstreams: resolvers,
}
}
func (r FastResolver) LookupNetIP(ctx context.Context, network, host string) ([]netip.Addr, error) {
2025-09-23 23:19:28 +03:00
ctx, cl := context.WithCancel(ctx)
defer cl()
2025-09-23 23:02:17 +03:00
errors := make(chan error)
success := make(chan []netip.Addr)
2025-08-12 19:38:17 +03:00
for _, res := range r.upstreams {
go func(res LookupNetIPer) {
addrs, err := res.LookupNetIP(ctx, network, host)
2025-09-23 23:02:17 +03:00
if err == nil {
select {
case success <- addrs:
2025-09-23 23:19:28 +03:00
case <-ctx.Done():
2025-09-23 23:02:17 +03:00
}
} else {
select {
2025-09-23 23:19:28 +03:00
case errors <- err:
case <-ctx.Done():
2025-09-23 23:02:17 +03:00
}
}
2025-08-12 19:38:17 +03:00
}(res)
}
var resErr error
2025-09-23 23:02:17 +03:00
for _ = range r.upstreams {
select {
case <-ctx.Done():
return nil, ctx.Err()
case resAddrs := <-success:
return resAddrs, nil
case err := <-errors:
resErr = multierror.Append(resErr, err)
2025-08-12 19:38:17 +03:00
}
}
2025-09-23 23:02:17 +03:00
return nil, resErr
2025-08-12 19:38:17 +03:00
}