github.com/cilium/cilium@v1.16.2/pkg/dial/dialer.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package dial 5 6 import ( 7 "context" 8 "net" 9 10 "github.com/sirupsen/logrus" 11 12 "github.com/cilium/cilium/pkg/logging/logfields" 13 ) 14 15 type Resolver interface { 16 // Resolve translates the provided hostname into the corresponding IP address, or 17 // possibly another alias DNS name. An error is returned if no mapping is found. 18 Resolve(ctx context.Context, host string) (string, error) 19 } 20 21 type dialContextFn func(context.Context, string) (net.Conn, error) 22 23 // NewContextDialer returns a custom dialer associated with a set of resolvers, 24 // that map the target hostname into the corresponding IP address (or a possible 25 // alias DNS name). The dialer eventually calls (&net.Dialer{}).DialContext with 26 // the first successfully translated address, or the original one otherwise. 27 func NewContextDialer(log logrus.FieldLogger, resolvers ...Resolver) dialContextFn { 28 return newContextDialer(log, func(ctx context.Context, address string) (net.Conn, error) { 29 return (&net.Dialer{}).DialContext(ctx, "tcp", address) 30 }, resolvers...) 31 } 32 33 func newContextDialer(log logrus.FieldLogger, dialContext dialContextFn, resolvers ...Resolver) dialContextFn { 34 return func(ctx context.Context, hostport string) (conn net.Conn, e error) { 35 host, port, err := net.SplitHostPort(hostport) 36 if err != nil { 37 // Return the same error that DialContext would return in this case. 38 return nil, &net.OpError{Op: "dial", Net: "tcp", Source: nil, Addr: nil, Err: err} 39 } 40 41 for _, resolver := range resolvers { 42 if resolved, err := resolver.Resolve(ctx, host); err == nil { 43 log.WithFields(logrus.Fields{ 44 logfields.Address: host, 45 logfields.Port: port, 46 logfields.Target: resolved, 47 }).Debug("Resolved hostname via custom dialer") 48 49 hostport = net.JoinHostPort(resolved, port) 50 break 51 } 52 } 53 54 return dialContext(ctx, hostport) 55 } 56 }