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  }