github.com/imannamdari/v2ray-core/v5@v5.0.5/features/dns/client.go (about)

     1  package dns
     2  
     3  import (
     4  	"github.com/imannamdari/v2ray-core/v5/common/errors"
     5  	"github.com/imannamdari/v2ray-core/v5/common/net"
     6  	"github.com/imannamdari/v2ray-core/v5/common/serial"
     7  	"github.com/imannamdari/v2ray-core/v5/features"
     8  )
     9  
    10  // IPOption is an object for IP query options.
    11  type IPOption struct {
    12  	IPv4Enable bool
    13  	IPv6Enable bool
    14  	FakeEnable bool
    15  }
    16  
    17  func (opt IPOption) With(other IPOption) IPOption {
    18  	return IPOption{
    19  		IPv4Enable: opt.IPv4Enable && other.IPv4Enable,
    20  		IPv6Enable: opt.IPv6Enable && other.IPv6Enable,
    21  		FakeEnable: opt.FakeEnable && other.FakeEnable,
    22  	}
    23  }
    24  
    25  func (opt IPOption) IsValid() bool {
    26  	return opt.IPv4Enable || opt.IPv6Enable
    27  }
    28  
    29  // Client is a V2Ray feature for querying DNS information.
    30  //
    31  // v2ray:api:stable
    32  type Client interface {
    33  	features.Feature
    34  
    35  	// LookupIP returns IP address for the given domain. IPs may contain IPv4 and/or IPv6 addresses.
    36  	LookupIP(domain string) ([]net.IP, error)
    37  }
    38  
    39  // IPv4Lookup is an optional feature for querying IPv4 addresses only.
    40  //
    41  // v2ray:api:beta
    42  type IPv4Lookup interface {
    43  	LookupIPv4(domain string) ([]net.IP, error)
    44  }
    45  
    46  // IPv6Lookup is an optional feature for querying IPv6 addresses only.
    47  //
    48  // v2ray:api:beta
    49  type IPv6Lookup interface {
    50  	LookupIPv6(domain string) ([]net.IP, error)
    51  }
    52  
    53  // LookupIPWithOption is a helper function for querying DNS information from a dns.Client with dns.IPOption.
    54  //
    55  // v2ray:api:beta
    56  func LookupIPWithOption(client Client, domain string, option IPOption) ([]net.IP, error) {
    57  	if option.FakeEnable {
    58  		if clientWithFakeDNS, ok := client.(ClientWithFakeDNS); ok {
    59  			client = clientWithFakeDNS.AsFakeDNSClient()
    60  		}
    61  	}
    62  	if option.IPv4Enable && !option.IPv6Enable {
    63  		if ipv4Lookup, ok := client.(IPv4Lookup); ok {
    64  			return ipv4Lookup.LookupIPv4(domain)
    65  		} else {
    66  			return nil, errors.New("dns.Client doesn't implement IPv4Lookup")
    67  		}
    68  	}
    69  	if option.IPv6Enable && !option.IPv4Enable {
    70  		if ipv6Lookup, ok := client.(IPv6Lookup); ok {
    71  			return ipv6Lookup.LookupIPv6(domain)
    72  		} else {
    73  			return nil, errors.New("dns.Client doesn't implement IPv6Lookup")
    74  		}
    75  	}
    76  	return client.LookupIP(domain)
    77  }
    78  
    79  // ClientType returns the type of Client interface. Can be used for implementing common.HasType.
    80  //
    81  // v2ray:api:beta
    82  func ClientType() interface{} {
    83  	return (*Client)(nil)
    84  }
    85  
    86  // ErrEmptyResponse indicates that DNS query succeeded but no answer was returned.
    87  var ErrEmptyResponse = errors.New("empty response")
    88  
    89  type RCodeError uint16
    90  
    91  func (e RCodeError) Error() string {
    92  	return serial.Concat("rcode: ", uint16(e))
    93  }
    94  
    95  func RCodeFromError(err error) uint16 {
    96  	if err == nil {
    97  		return 0
    98  	}
    99  	cause := errors.Cause(err)
   100  	if r, ok := cause.(RCodeError); ok {
   101  		return uint16(r)
   102  	}
   103  	return 0
   104  }