예제 #1
0
        /// <summary>
        /// Attempts a lookup from cache.
        /// </summary>
        /// <param name="uri"></param>
        /// <param name="startQuery"></param>
        /// <param name="preferIPv6"></param>
        /// <returns></returns>
        private static SIPEndPoint SIPLookupFromCache(
            SIPURI uri,
            QueryType startQuery,
            bool preferIPv6)
        {
            SIPEndPoint result    = null;
            QueryType   queryType = startQuery;

            string host = uri.MAddrOrHostAddress;
            int    port = SIPConstants.GetDefaultPort(uri.Protocol);

            if (ushort.TryParse(uri.HostPort, out var uriPort))
            {
                port = uriPort;
            }

            bool isDone = false;

            while (!isDone)
            {
                switch (queryType)
                {
                case QueryType.SRV:

                    var    srvProtocol = SIPServices.GetSRVProtocolForSIPURI(uri);
                    string serviceHost = DnsQueryExtensions.ConcatServiceName(uri.MAddrOrHostAddress, uri.Scheme.ToString(), srvProtocol.ToString());
                    var    srvResult   = _lookupClient.QueryCache(serviceHost, QueryType.SRV);
                    (var srvHost, var srvPort) = GetHostAndPortFromSrvResult(srvResult);
                    if (srvHost != null)
                    {
                        host = srvHost;
                        port = srvPort != 0 ? srvPort : port;
                    }
                    queryType = preferIPv6 ? QueryType.AAAA : QueryType.A;

                    break;

                case QueryType.AAAA:

                    var aaaaResult = _lookupClient.QueryCache(host, UseANYLookups ? QueryType.ANY : QueryType.AAAA, QueryClass.IN);
                    if (aaaaResult?.Answers?.Count > 0)
                    {
                        result = GetFromLookupResult(uri.Protocol, aaaaResult.Answers.OrderByDescending(x => x.RecordType).First(), port);
                        isDone = true;
                    }
                    else
                    {
                        queryType = QueryType.A;
                    }

                    break;

                default:
                    // A record lookup.

                    var aResult = _lookupClient.QueryCache(host, QueryType.A, QueryClass.IN);
                    if (aResult != null)
                    {
                        if (aResult.Answers?.Count > 0)
                        {
                            result = GetFromLookupResult(uri.Protocol, aResult.Answers.First(), port);
                        }
                        else
                        {
                            // We got a result back but it was empty indicating an unresolvable host or
                            // some other DNS error condition.
                            result = SIPEndPoint.Empty;
                        }
                    }

                    isDone = true;
                    break;
                }
            }

            return(result);
        }
예제 #2
0
파일: SIPDns.cs 프로젝트: xyanlong/AKStream
        /// <summary>
        /// Attempts a lookup from DNS.
        /// </summary>
        /// <param name="uri"></param>
        /// <param name="startQuery"></param>
        /// <param name="preferIPv6"></param>
        /// <param name="ct"></param>
        /// <returns></returns>
        private static async Task <SIPEndPoint> SIPLookupAsync(
            SIPURI uri,
            QueryType startQuery,
            bool preferIPv6,
            CancellationToken ct)
        {
            SIPEndPoint result    = null;
            QueryType   queryType = startQuery;

            string host = uri.MAddrOrHostAddress;
            int    port = SIPConstants.GetDefaultPort(uri.Protocol);

            if (ushort.TryParse(uri.HostPort, out var uriPort))
            {
                port = uriPort;
            }

            bool isDone = false;

            while (!isDone && !ct.IsCancellationRequested)
            {
                switch (queryType)
                {
                case QueryType.SRV:

                    try
                    {
                        var srvProtocol = SIPServices.GetSRVProtocolForSIPURI(uri);
                        //string serviceHost = DnsQueryExtensions.ConcatResolveServiceName(uri.MAddrOrHostAddress, uri.Scheme.ToString(), srvProtocol.ToString());
                        //var srvResult = await _lookupClient.QueryAsync(serviceHost, QueryType.SRV, QueryClass.IN, ct).ConfigureAwait(false);
                        var srvResult = await _lookupClient.ResolveServiceAsync(uri.MAddrOrHostAddress,
                                                                                uri.Scheme.ToString(), srvProtocol.ToString());

                        (var srvHost, var srvPort) = GetHostAndPortFromSrvResult(srvResult);
                        if (srvHost != null)
                        {
                            host = srvHost;
                            port = srvPort != 0 ? srvPort : port;
                        }
                    }
                    catch (Exception srvExcp)
                    {
                        logger.LogWarning($"SIPDNS exception on SRV lookup. {srvExcp.Message}.");
                    }

                    queryType = preferIPv6 ? QueryType.AAAA : QueryType.A;

                    break;

                case QueryType.AAAA:

                    try
                    {
                        var aaaaResult = await _lookupClient
                                         .QueryAsync(host, UseANYLookups?QueryType.ANY : QueryType.AAAA, QueryClass.IN, ct)
                                         .ConfigureAwait(false);

                        if (aaaaResult?.Answers?.Count > 0)
                        {
                            result = GetFromLookupResult(uri.Protocol,
                                                         aaaaResult.Answers.AddressRecords().OrderByDescending(x => x.RecordType).First(),
                                                         port);
                            isDone = true;
                        }
                        else
                        {
                            queryType = QueryType.A;
                        }
                    }
                    catch (Exception srvExcp)
                    {
                        logger.LogWarning($"SIPDNS exception on AAAA lookup. {srvExcp.Message}.");
                        queryType = QueryType.A;
                    }

                    break;

                default:
                    // A record lookup.
                    try
                    {
                        var aResult = await _lookupClient.QueryAsync(host, QueryType.A, QueryClass.IN, ct)
                                      .ConfigureAwait(false);

                        if (aResult != null)
                        {
                            if (aResult.Answers?.Count > 0)
                            {
                                result = GetFromLookupResult(uri.Protocol, aResult.Answers.AddressRecords().First(),
                                                             port);
                            }
                            else
                            {
                                // We got a result back but it was empty indicating an unresolvable host or
                                // some other DNS error condition.
                                result = SIPEndPoint.Empty;
                            }
                        }
                    }
                    catch (Exception srvExcp)
                    {
                        logger.LogWarning($"SIPDNS exception on A lookup. {srvExcp.Message}.");
                        result = SIPEndPoint.Empty;
                    }

                    isDone = true;
                    break;
                }
            }

            return(result);
        }
예제 #3
0
        /// <summary>
        /// Resolve method that performs either an A or AAAA record lookup. If required
        /// a SRV record lookup will be performed prior to the A or AAAA lookup.
        /// </summary>
        /// <param name="uri">The SIP URI to lookup.</param>
        /// <param name="queryType">Whether the address lookup should be A or AAAA.</param>
        /// <returns>A SIPEndPoint or null.</returns>
        private static async Task <SIPEndPoint> Resolve(SIPURI uri, QueryType queryType)
        {
            if (uri == null || String.IsNullOrWhiteSpace(uri.MAddrOrHostAddress))
            {
                throw new ArgumentNullException("uri", "SIP DNS resolve was supplied an empty input.");
            }

            if (!ushort.TryParse(uri.HostPort, out var uriPort))
            {
                uriPort = SIPConstants.DEFAULT_SIP_PORT;
            }

            if (IPAddress.TryParse(uri.MAddrOrHostAddress, out var ipAddress))
            {
                // Target is already an IP address, no DNS lookup required.
                return(new SIPEndPoint(uri.Protocol, ipAddress, uriPort));
            }
            else
            {
                if (!uri.MAddrOrHostAddress.Contains(".") || uri.MAddrOrHostAddress.EndsWith(MDNS_TLD))
                {
                    AddressFamily family = (queryType == QueryType.AAAA) ? AddressFamily.InterNetworkV6 :
                                           AddressFamily.InterNetwork;

                    // The lookup is for a local network host. Use the OS DNS logic as the
                    // main DNS client can be configured to use external DNS servers that won't
                    // be able to lookup this hostname.

                    IPHostEntry hostEntry = null;

                    try
                    {
                        hostEntry = Dns.GetHostEntry(uri.MAddrOrHostAddress);
                    }
                    catch (SocketException)
                    {
                        // Socket exception gets thrown for failed lookups,
                    }

                    if (hostEntry != null)
                    {
                        var addressList = hostEntry.AddressList;

                        if (addressList?.Length == 0)
                        {
                            logger.LogWarning($"Operating System DNS lookup failed for {uri.MAddrOrHostAddress}.");
                            return(null);
                        }
                        else
                        {
                            if (addressList.Any(x => x.AddressFamily == family))
                            {
                                var addressResult = addressList.First(x => x.AddressFamily == family);
                                return(new SIPEndPoint(uri.Protocol, addressResult, uriPort));
                            }
                            else
                            {
                                // Didn't get a result for the preferred address family so just use the
                                // first available result.
                                var addressResult = addressList.First();
                                return(new SIPEndPoint(uri.Protocol, addressResult, uriPort));
                            }
                        }
                    }
                    else
                    {
                        return(null);
                    }
                }
                else
                {
                    if (uri.HostPort != null)
                    {
                        // Explicit port means no SRV lookup.
                        return(HostQuery(uri.Protocol, uri.MAddrOrHostAddress, uriPort, queryType));
                    }
                    else
                    {
                        // No explicit port so use a SRV -> (A | AAAA -> A | ANY) record lookup.
                        var srvProtocol = SIPServices.GetSRVProtocolForSIPURI(uri);
                        try
                        {
                            ServiceHostEntry srvResult = null;
                            var srvResults             = await _lookupClient.ResolveServiceAsync(uri.MAddrOrHostAddress, uri.Scheme.ToString(), srvProtocol.ToString()).ConfigureAwait(false);

                            if (srvResults == null || srvResults.Count() == 0)
                            {
                                logger.LogWarning($"SIP DNS SRV lookup returned no results for {uri}.");
                            }
                            else
                            {
                                srvResult = srvResults.OrderBy(y => y.Priority).ThenByDescending(w => w.Weight).FirstOrDefault();
                            }

                            string host = uri.MAddrOrHostAddress;        // If no SRV results then fallback is to lookup the hostname directly.
                            int    port = SIPConstants.DEFAULT_SIP_PORT; // If no SRV results then fallback is to use the default port.

                            if (srvResult != null)
                            {
                                host = srvResult.HostName;
                                port = srvResult.Port;
                            }

                            return(HostQuery(uri.Protocol, host, port, queryType));
                        }
                        catch (Exception e)
                        {
                            logger.LogWarning($"SIP DNS SRV lookup failure for {uri}. {e?.InnerException?.Message}");
                        }
                    }
                }
                return(null);
            }
        }