예제 #1
0
        public async Task <IPEndPoint> ResolveAsync(string endpoint, int port, IpVersion ipVersion = IpVersion.IpV4, CancellationToken token = default(CancellationToken))
        {
            string cacheKey = $"{endpoint}:{port}:{ipVersion}";

            if (port < IPEndPoint.MinPort || port > IPEndPoint.MaxPort)
            {
                throw new ArgumentOutOfRangeException(nameof(port));
            }

            if (cache.HasKey(cacheKey))
            {
                return(cache.Get <IPEndPoint>(cacheKey));
            }

            var addressFamily = ipVersion.HasFlag(IpVersion.IpV4)
                ? AddressFamily.InterNetwork
                : AddressFamily.InterNetworkV6;


            token.ThrowIfCancellationRequested();

            IPEndPoint ipEndpoint;

            var ipAddress = TryGetIpAddress(endpoint);

            if (ipAddress != null)
            {
                ipEndpoint = new IPEndPoint(ipAddress, port);
                cache.Add(cacheKey, ipEndpoint, TimeSpan.FromMinutes(60));
                return(ipEndpoint);
            }

            try
            {
#if NET40
                var allAddresses = Dns.GetHostAddresses(endpoint);
#else
                var allAddresses = await Dns.GetHostAddressesAsync(endpoint);
#endif

                var firstAddressInFamily = allAddresses.FirstOrDefault(x => x.AddressFamily == addressFamily);
                if (firstAddressInFamily != null)
                {
                    ipEndpoint = new IPEndPoint(firstAddressInFamily, port);
                    cache.Add(cacheKey, ipEndpoint, TimeSpan.FromMinutes(60));
                    return(ipEndpoint);
                }


                if (addressFamily == AddressFamily.InterNetwork && ipVersion.HasFlag(IpVersion.IpV6))
                {
                    ipEndpoint = await ResolveAsync(endpoint, port, IpVersion.IpV6, token);

                    if (ipEndpoint != null)
                    {
                        cache.Add(cacheKey, ipEndpoint, TimeSpan.FromMinutes(60));
                        return(ipEndpoint);
                    }
                }

                var firstAddress = allAddresses.FirstOrDefault();
                if (firstAddress == null)
                {
                    return(null);
                }

                switch (firstAddress.AddressFamily)
                {
                case AddressFamily.InterNetwork:
#if NET40
                    ipEndpoint = new IPEndPoint(firstAddress, port);
#else
                    ipEndpoint = new IPEndPoint(firstAddress.MapToIPv6(), port);
#endif
                    break;

                case AddressFamily.InterNetworkV6:
#if NET40
                    ipEndpoint = new IPEndPoint(firstAddress, port);
#else
                    ipEndpoint = new IPEndPoint(firstAddress.MapToIPv4(), port);
#endif
                    break;

                default:
                    return(null);
                }

                cache.Add(cacheKey, ipEndpoint, TimeSpan.FromMinutes(60));

                return(ipEndpoint);
            }
            catch
            {
                return(null);
            }
        }