Example #1
0
        public static SIPDNSLookupResult DNSAAAARecordLookup(string host, int port, bool async, SIPURI uri, SIPDNSLookupResult lookupResult = null)
        {
            SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS A record lookup requested for " + host + ".", null));

            SIPDNSLookupResult result = lookupResult ?? new SIPDNSLookupResult(uri);

            result.LookupError = null;

            DNSResponse aaaaRecordResponse = DNSManager.Lookup(host, QType.AAAA, DNS_A_RECORD_LOOKUP_TIMEOUT, null, true, async);

            if (aaaaRecordResponse == null)
            {
                if (async)
                {
                    result.Pending = true;
                }
            }
            else if (aaaaRecordResponse.Timedout)
            {
                result.ATimedoutAt = DateTime.Now;
            }
            else if (!string.IsNullOrWhiteSpace(aaaaRecordResponse.Error))
            {
                result.LookupError = aaaaRecordResponse.Error;
            }
            else if (aaaaRecordResponse.RecordsAAAA == null || aaaaRecordResponse.RecordsAAAA.Length == 0)
            {
                SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS no AAAA records found for " + host + ".", null));
                result.LookupError = "No AAAA records found for " + host + ".";
            }
            else
            {
                SIPURI sipURI = result.URI;
                foreach (RecordAAAA aRecord in aaaaRecordResponse.RecordsAAAA)
                {
                    SIPDNSLookupEndPoint sipLookupEndPoint = new SIPDNSLookupEndPoint(new SIPEndPoint(sipURI.Protocol, new IPEndPoint(aRecord.Address, port)), aRecord.RR.TTL);
                    result.AddLookupResult(sipLookupEndPoint);
                    SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS AAAA record found for " + host + ", result " + sipLookupEndPoint.LookupEndPoint.ToString() + ".", null));
                }
            }

            return(result);
        }
Example #2
0
        public static SIPDNSLookupResult ResolveSIPService(SIPURI sipURI, bool async)
        {
            try
            {
                if (sipURI == null)
                {
                    throw new ArgumentNullException("sipURI", "Cannot resolve SIP service on a null URI.");
                }

                string host = sipURI.Host;
                int port = (sipURI.Scheme == SIPSchemesEnum.sip) ? m_defaultSIPPort : m_defaultSIPSPort;
                bool explicitPort = false;

                if (sipURI.Host.IndexOf(':') != -1)
                {
                    host = sipURI.Host.Split(':')[0];
                    Int32.TryParse(sipURI.Host.Split(':')[1], out port);
                    explicitPort = true;
                }

                if (Regex.Match(host, @"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$").Success)
                {
                    // Target is an IP address, no DNS lookup required.
                    IPAddress hostIP = IPAddress.Parse(host);
                    SIPDNSLookupEndPoint sipLookupEndPoint = new SIPDNSLookupEndPoint(new SIPEndPoint(sipURI.Protocol, new IPEndPoint(hostIP, port)), 0);
                    SIPDNSLookupResult result = new SIPDNSLookupResult(sipURI);
                    result.AddLookupResult(sipLookupEndPoint);
                    return result;
                }
                else if (explicitPort)
                {
                    // Target is a hostname with an explicit port, DNS lookup for A or AAAA record.
                    return DNSARecordLookup(host, port, async, sipURI);
                }
                else
                {
                    // Target is a hostname with no explicit port, use the whole NAPTR->SRV->A lookup procedure.
                    SIPDNSLookupResult sipLookupResult = new SIPDNSLookupResult(sipURI);

                    // Do without the NAPTR lookup for the time being. Very few organisations appear to use them and it can cost up to 2.5s to get a failed resolution.
                    /*SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS full lookup requested for " + sipURI.ToString() + ".", null));
                    DNSNAPTRRecordLookup(host, async, ref sipLookupResult);
                    if (sipLookupResult.Pending)
                    {
                        if (!m_inProgressSIPServiceLookups.Contains(sipURI.ToString()))
                        {
                            m_inProgressSIPServiceLookups.Add(sipURI.ToString());
                            ThreadPool.QueueUserWorkItem(delegate { ResolveSIPService(sipURI, false); });
                        }
                        return sipLookupResult;
                    }*/

                    DNSSRVRecordLookup(sipURI.Scheme, sipURI.Protocol, host, async, ref sipLookupResult);
                    if (sipLookupResult.Pending)
                    {
                        //logger.Debug("SIPDNSManager SRV lookup for " + host + " is pending.");
                        return sipLookupResult;
                    }
                    else
                    {
                        //logger.Debug("SIPDNSManager SRV lookup for " + host + " is final.");
                        SIPDNSServiceResult nextSRVRecord = sipLookupResult.GetNextUnusedSRV();
                        int lookupPort = (nextSRVRecord != null) ? nextSRVRecord.Port : port;
                        return DNSARecordLookup(nextSRVRecord, host, lookupPort, async, sipLookupResult.URI);
                    }
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception SIPDNSManager ResolveSIPService (" + sipURI.ToString() + "). " + excp.Message);
                m_inProgressSIPServiceLookups.Remove(sipURI.ToString());
                return new SIPDNSLookupResult(sipURI, excp.Message);
            }
        }
Example #3
0
        public static SIPDNSLookupResult DNSARecordLookup(string host, int port, bool async, SIPURI uri)
        {
            SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS A record lookup requested for " + host + ".", null));
            SIPDNSLookupResult result = new SIPDNSLookupResult(uri);

            DNSResponse aRecordResponse = DNSManager.Lookup(host, DNSQType.A, DNS_A_RECORD_LOOKUP_TIMEOUT, null, true, async);
            if (aRecordResponse == null && async)
            {
                result.Pending = true;
            }
            else if (aRecordResponse.Timedout)
            {
                result.ATimedoutAt = DateTime.Now;
            }
            else if (aRecordResponse.Error != null)
            {
                result.LookupError = aRecordResponse.Error;
            }
            else if (aRecordResponse.RecordsA == null || aRecordResponse.RecordsA.Length == 0)
            {
                SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS no A records found for " + host + ".", null));
                result.LookupError = "No A records found for " + host + ".";
            }
            else
            {
                SIPURI sipURI = result.URI;
                foreach (RecordA aRecord in aRecordResponse.RecordsA)
                {
                    SIPDNSLookupEndPoint sipLookupEndPoint = new SIPDNSLookupEndPoint(new SIPEndPoint(sipURI.Protocol, new IPEndPoint(aRecord.Address, port)), aRecord.RR.TTL);
                    result.AddLookupResult(sipLookupEndPoint);
                    SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS A record found for " + host + ", result " + sipLookupEndPoint.LookupEndPoint.ToString() + ".", null));
                }
            }

            return result;
        }
Example #4
0
        public static SIPDNSLookupResult ResolveSIPService(SIPURI sipURI, bool async)
        {
            try
            {
                if (sipURI == null)
                {
                    throw new ArgumentNullException("sipURI", "Cannot resolve SIP service on a null URI.");
                }

                string host         = sipURI.Host;
                int    port         = (sipURI.Scheme == SIPSchemesEnum.sip) ? m_defaultSIPPort : m_defaultSIPSPort;
                bool   explicitPort = false;

                if (sipURI.Host.IndexOf(':') != -1)
                {
                    host = sipURI.Host.Split(':')[0];
                    Int32.TryParse(sipURI.Host.Split(':')[1], out port);
                    explicitPort = true;
                }

                if (Regex.Match(host, @"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$").Success)
                {
                    // Target is an IP address, no DNS lookup required.
                    IPAddress            hostIP            = IPAddress.Parse(host);
                    SIPDNSLookupEndPoint sipLookupEndPoint = new SIPDNSLookupEndPoint(new SIPEndPoint(sipURI.Protocol, new IPEndPoint(hostIP, port)), 0);
                    SIPDNSLookupResult   result            = new SIPDNSLookupResult(sipURI);
                    result.AddLookupResult(sipLookupEndPoint);
                    return(result);
                }
                else if (explicitPort)
                {
                    // Target is a hostname with an explicit port, DNS lookup for A or AAAA record.
                    return(DNSARecordLookup(host, port, async, sipURI));
                }
                else
                {
                    // Target is a hostname with no explicit port, use the whole NAPTR->SRV->A lookup procedure.
                    SIPDNSLookupResult sipLookupResult = new SIPDNSLookupResult(sipURI);

                    // Do without the NAPTR lookup for the time being. Very few organisations appear to use them and it can cost up to 2.5s to get a failed resolution.

                    /*SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS full lookup requested for " + sipURI.ToString() + ".", null));
                     * DNSNAPTRRecordLookup(host, async, ref sipLookupResult);
                     * if (sipLookupResult.Pending)
                     * {
                     *  if (!m_inProgressSIPServiceLookups.Contains(sipURI.ToString()))
                     *  {
                     *      m_inProgressSIPServiceLookups.Add(sipURI.ToString());
                     *      ThreadPool.QueueUserWorkItem(delegate { ResolveSIPService(sipURI, false); });
                     *  }
                     *  return sipLookupResult;
                     * }*/

                    DNSSRVRecordLookup(sipURI.Scheme, sipURI.Protocol, host, async, ref sipLookupResult);
                    if (sipLookupResult.Pending)
                    {
                        //logger.Debug("SIPDNSManager SRV lookup for " + host + " is pending.");
                        return(sipLookupResult);
                    }
                    else
                    {
                        //logger.Debug("SIPDNSManager SRV lookup for " + host + " is final.");

                        // Add some custom logic to cope with sips SRV records using _sips._tcp (e.g. free.call.ciscospark.com).
                        // By default only _sips._tls SRV records are checked for. THis block adds an additional check for _sips._tcp SRV records.
                        //if ((sipLookupResult.SIPSRVResults == null || sipLookupResult.SIPSRVResults.Count == 0) && sipURI.Scheme == SIPSchemesEnum.sips)
                        //{
                        //    DNSSRVRecordLookup(sipURI.Scheme, SIPProtocolsEnum.tcp, host, async, ref sipLookupResult);
                        //    SIPDNSServiceResult nextSRVRecord = sipLookupResult.GetNextUnusedSRV();
                        //    int lookupPort = (nextSRVRecord != null) ? nextSRVRecord.Port : port;
                        //    return DNSARecordLookup(nextSRVRecord, host, lookupPort, async, sipLookupResult.URI);
                        //}
                        //else
                        //{
                        SIPDNSServiceResult nextSRVRecord = sipLookupResult.GetNextUnusedSRV();
                        int lookupPort = (nextSRVRecord != null) ? nextSRVRecord.Port : port;
                        return(DNSARecordLookup(nextSRVRecord, host, lookupPort, async, sipLookupResult.URI));
                        //}
                    }
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception SIPDNSManager ResolveSIPService (" + sipURI.ToString() + "). " + excp.Message);
                m_inProgressSIPServiceLookups.Remove(sipURI.ToString());
                return(new SIPDNSLookupResult(sipURI, excp.Message));
            }
        }
Example #5
0
        public static SIPDNSLookupResult DNSNameRecordLookup(string host, int port, bool async, SIPURI uri, SIPDNSLookupResult lookupResult = null, bool?preferIPv6 = null, int recursionLevel = 0)
        {
            SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS Name record lookup requested for " + host + ".", null));

            SIPDNSLookupResult result = lookupResult ?? new SIPDNSLookupResult(uri);

            result.LookupError = null;

            if (UseANYLookups)
            {
                DNSResponse aRecordResponse = DNSManager.Lookup(host, QType.ANY, DNS_A_RECORD_LOOKUP_TIMEOUT, null, true, async);
                if (aRecordResponse == null && async)
                {
                    result.Pending = true;
                }
                else if (aRecordResponse == null)
                {
                }
                else if (aRecordResponse.Timedout)
                {
                    result.ATimedoutAt = DateTime.Now;
                }
                else if (!string.IsNullOrWhiteSpace(aRecordResponse.Error))
                {
                    result.LookupError = aRecordResponse.Error;
                }
                else if ((aRecordResponse.RecordsAAAA == null || aRecordResponse.RecordsAAAA.Length == 0) && (aRecordResponse.RecordsA == null || aRecordResponse.RecordsA.Length == 0) && (aRecordResponse.RecordsCNAME == null || aRecordResponse.RecordsCNAME.Length == 0))
                {
                    SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS no CNAME, A or AAAA records found for " + host + ".", null));
                    result.LookupError = "No CNAME, A or AAAA records found for " + host + ".";
                }
                else
                {
                    if (preferIPv6 == null)
                    {
                        preferIPv6 = SIPDNSManager.PreferIPv6NameResolution;
                    }

                    foreach (RecordCNAME aRecord in aRecordResponse.RecordsCNAME)
                    {
                        //CNAME could be another CNAME or A/AAAA Record -> max 3 levels recursive name resolution
                        if (recursionLevel < 3)
                        {
                            SIPDNSLookupResult resultCName = DNSNameRecordLookup(aRecord.CNAME, port, async, uri, lookupResult, preferIPv6, recursionLevel + 1);
                            if (resultCName != null)
                            {
                                foreach (SIPDNSLookupEndPoint ep in resultCName.EndPointResults)
                                {
                                    result.AddLookupResult(ep);
                                }
                            }
                        }
                    }
                    if (preferIPv6 == true)
                    {
                        SIPURI sipURI = result.URI;
                        foreach (RecordAAAA aRecord in aRecordResponse.RecordsAAAA)
                        {
                            SIPDNSLookupEndPoint sipLookupEndPoint = new SIPDNSLookupEndPoint(new SIPEndPoint(sipURI.Protocol, new IPEndPoint(aRecord.Address, port)), aRecord.RR.TTL);
                            result.AddLookupResult(sipLookupEndPoint);
                            SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS AAAA record found for " + host + ", result " + sipLookupEndPoint.LookupEndPoint.ToString() + ".", null));
                        }
                        foreach (RecordA aRecord in aRecordResponse.RecordsA)
                        {
                            SIPDNSLookupEndPoint sipLookupEndPoint = new SIPDNSLookupEndPoint(new SIPEndPoint(sipURI.Protocol, new IPEndPoint(aRecord.Address, port)), aRecord.RR.TTL);
                            result.AddLookupResult(sipLookupEndPoint);
                            SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS A record found for " + host + ", result " + sipLookupEndPoint.LookupEndPoint.ToString() + ".", null));
                        }
                    }
                    else
                    {
                        SIPURI sipURI = result.URI;
                        foreach (RecordA aRecord in aRecordResponse.RecordsA)
                        {
                            SIPDNSLookupEndPoint sipLookupEndPoint = new SIPDNSLookupEndPoint(new SIPEndPoint(sipURI.Protocol, new IPEndPoint(aRecord.Address, port)), aRecord.RR.TTL);
                            result.AddLookupResult(sipLookupEndPoint);
                            SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS A record found for " + host + ", result " + sipLookupEndPoint.LookupEndPoint.ToString() + ".", null));
                        }
                        foreach (RecordAAAA aRecord in aRecordResponse.RecordsAAAA)
                        {
                            SIPDNSLookupEndPoint sipLookupEndPoint = new SIPDNSLookupEndPoint(new SIPEndPoint(sipURI.Protocol, new IPEndPoint(aRecord.Address, port)), aRecord.RR.TTL);
                            result.AddLookupResult(sipLookupEndPoint);
                            SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS AAAA record found for " + host + ", result " + sipLookupEndPoint.LookupEndPoint.ToString() + ".", null));
                        }
                    }
                }
            }

            if (result.LookupError != null || result.EndPointResults == null || result.EndPointResults.Count == 0)
            {
                if (preferIPv6 == true)
                {
                    result = DNSAAAARecordLookup(host, port, async, uri, lookupResult);
                }
                else
                {
                    result = DNSARecordLookup(host, port, async, uri, lookupResult);
                }
            }

            return(result);
        }
Example #6
0
        // TODO: Remove this nasty code duplication with ResolveSIPService!
        public static async Task <SIPDNSLookupResult> ResolveAsync(SIPURI sipURI, bool?preferIPv6 = null)
        {
            try
            {
                if (sipURI == null)
                {
                    throw new ArgumentNullException("sipURI", "Cannot resolve SIP service on a null URI.");
                }

                if (IPSocket.TryParseIPEndPoint(sipURI.MAddrOrHost, out var ipEndPoint))
                {
                    // Target is an IP address, no DNS lookup required.
                    SIPDNSLookupEndPoint sipLookupEndPoint = new SIPDNSLookupEndPoint(new SIPEndPoint(sipURI.Protocol, ipEndPoint), 0);
                    SIPDNSLookupResult   result            = new SIPDNSLookupResult(sipURI);
                    result.AddLookupResult(sipLookupEndPoint);
                    return(result);
                }
                else
                {
                    string host = sipURI.MAddrOrHostAddress;
                    //int port = IPSocket.ParsePortFromSocket(host);
                    int port = sipURI.Protocol != SIPProtocolsEnum.tls ? m_defaultSIPPort : m_defaultSIPSPort;
                    if (preferIPv6 == null)
                    {
                        preferIPv6 = SIPDNSManager.PreferIPv6NameResolution;
                    }
                    bool explicitPort = false;

                    try
                    {
                        //Parse returns true if sipURI.Host can be parsed as an ipaddress
                        bool parseresult = SIPSorcery.Sys.IPSocket.Parse(sipURI.MAddrOrHost, out host, out port);
                        explicitPort = port >= 0;
                        if (!explicitPort)
                        {
                            //port = (sipURI.Scheme == SIPSchemesEnum.sip) ? m_defaultSIPPort : m_defaultSIPSPort;
                            port = sipURI.Protocol != SIPProtocolsEnum.tls ? m_defaultSIPPort : m_defaultSIPSPort;
                        }
                        if (parseresult == true)
                        {
                            IPAddress            hostIP            = IPAddress.Parse(host);
                            SIPDNSLookupEndPoint sipLookupEndPoint = new SIPDNSLookupEndPoint(new SIPEndPoint(sipURI.Protocol, new IPEndPoint(hostIP, port)), 0);
                            SIPDNSLookupResult   result            = new SIPDNSLookupResult(sipURI);
                            result.AddLookupResult(sipLookupEndPoint);
                            return(result);
                        }
                    }
                    catch (Exception ex)
                    {
                        SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "Exception SIPDNSManager ResolveSIPService (" + sipURI.ToString() + "). " + ex, null));

                        //rj2: if there is a parsing exception, then fallback to original sipsorcery parsing mechanism
                        port         = IPSocket.ParsePortFromSocket(sipURI.Host);
                        explicitPort = port > 0;

                        //if(Regex.Match(host, @"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$").Success)
                        if (SIPSorcery.Sys.IPSocket.IsIPAddress(host))
                        {
                            // Target is an IP address, no DNS lookup required.
                            IPAddress            hostIP            = IPAddress.Parse(host);
                            SIPDNSLookupEndPoint sipLookupEndPoint = new SIPDNSLookupEndPoint(new SIPEndPoint(sipURI.Protocol, new IPEndPoint(hostIP, port)), 0);
                            SIPDNSLookupResult   result            = new SIPDNSLookupResult(sipURI);
                            result.AddLookupResult(sipLookupEndPoint);
                            return(result);
                        }
                    }

                    if (!explicitPort)
                    {
                        //port = (sipURI.Scheme == SIPSchemesEnum.sip) ? m_defaultSIPPort : m_defaultSIPSPort;
                        port = sipURI.Protocol != SIPProtocolsEnum.tls ? m_defaultSIPPort : m_defaultSIPSPort;
                    }

                    if (host.Contains(".") == false || IPSocket.ParseHostFromSocket(host).EndsWith(MDNS_TLD))
                    {
                        string hostOnly = IPSocket.ParseHostFromSocket(host);

                        // If host is not fully qualified then assume there's no point using NAPTR or SRV record look ups and go straight to A's.
                        if (hostOnly.ToLower() == System.Net.Dns.GetHostName()?.ToLower())
                        {
                            // The lookup is for the current machine.
                            var addressList = System.Net.Dns.GetHostEntry(System.Net.Dns.GetHostName()).AddressList;

                            if (addressList?.Length == 0)
                            {
                                return(new SIPDNSLookupResult(sipURI, $"Failed to resolve local machine hostname."));
                            }
                            else
                            {
                                // Preference for IPv4 IP address for local host name lookup.
                                IPAddress   firstAddress = addressList.Where(x => x.AddressFamily == (preferIPv6 == true ? AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork)).FirstOrDefault() ?? addressList.FirstOrDefault();
                                SIPEndPoint resultEp     = new SIPEndPoint(sipURI.Protocol, new IPEndPoint(firstAddress, port));
                                return(new SIPDNSLookupResult(sipURI, resultEp));
                            }
                        }
                        else
                        {
                            return(await Task.Run(() => DNSNameRecordLookup(hostOnly, port, false, sipURI, null, preferIPv6)).ConfigureAwait(false));
                        }
                    }
                    else if (explicitPort)
                    {
                        // If target is a hostname with an explicit port then SIP lookup rules state to use DNS lookup for A or AAAA record.
                        host = host.Substring(0, host.LastIndexOf(':'));
                        return(await Task.Run(() => DNSNameRecordLookup(host, port, false, sipURI, null, preferIPv6)).ConfigureAwait(false));
                    }
                    else
                    {
                        // Target is a hostname with no explicit port, use the whole NAPTR->SRV->A lookup procedure.
                        SIPDNSLookupResult sipLookupResult = new SIPDNSLookupResult(sipURI);

                        // Do without the NAPTR lookup for the time being. Very few organisations appear to use them and it can cost up to 2.5s to get a failed resolution.
                        //rj2: uncomment this section for telekom 1TR118 lookup
                        SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS full lookup requested for " + sipURI.ToString() + ".", null));
                        DNSNAPTRRecordLookup(host, false, ref sipLookupResult);
                        if (sipLookupResult.Pending)
                        {
                            if (!m_inProgressSIPServiceLookups.Contains(sipURI.ToString()))
                            {
                                m_inProgressSIPServiceLookups.Add(sipURI.ToString());
                                //ThreadPool.QueueUserWorkItem(delegate { ResolveSIPService(sipURI, false); });
                                System.Threading.ThreadPool.QueueUserWorkItem((obj) => ResolveSIPService(sipURI, false, preferIPv6));
                            }
                            return(sipLookupResult);
                        }

                        return(await Task.Run(() =>
                        {
                            DNSSRVRecordLookup(sipURI.Scheme, sipURI.Protocol, host, false, ref sipLookupResult);
                            if (sipLookupResult.Pending)
                            {
                                //logger.LogDebug("SIPDNSManager SRV lookup for " + host + " is pending.");
                                return sipLookupResult;
                            }
                            else
                            {
                                //logger.LogDebug("SIPDNSManager SRV lookup for " + host + " is final.");

                                // Add some custom logic to cope with sips SRV records using _sips._tcp (e.g. free.call.ciscospark.com).
                                // By default only _sips._tls SRV records are checked for. THis block adds an additional check for _sips._tcp SRV records.
                                //if ((sipLookupResult.SIPSRVResults == null || sipLookupResult.SIPSRVResults.Count == 0) && sipURI.Scheme == SIPSchemesEnum.sips)
                                //{
                                //    DNSSRVRecordLookup(sipURI.Scheme, SIPProtocolsEnum.tcp, host, async, ref sipLookupResult);
                                //    SIPDNSServiceResult nextSRVRecord = sipLookupResult.GetNextUnusedSRV();
                                //    int lookupPort = (nextSRVRecord != null) ? nextSRVRecord.Port : port;
                                //    return DNSARecordLookup(nextSRVRecord, host, lookupPort, async, sipLookupResult.URI);
                                //}
                                //else
                                //{
                                //   SIPDNSServiceResult nextSRVRecord = sipLookupResult.GetNextUnusedSRV();
                                //   int lookupPort = (nextSRVRecord != null) ? nextSRVRecord.Port : port;
                                //   return DNSARecordLookup(nextSRVRecord, host, lookupPort, false, sipLookupResult.URI);
                                //}

                                // The SRV record can indicate the SIP server is using a non-standard port.
                                SIPDNSServiceResult nextSRVRecord = sipLookupResult.GetNextUnusedSRV();
                                int lookupPort = (nextSRVRecord != null) ? nextSRVRecord.Port : port;

                                return DNSNameRecordLookup(host, lookupPort, false, sipLookupResult.URI, ref sipLookupResult, preferIPv6);
                            }
                        }).ConfigureAwait(false));
                    }
                }
            }
            catch (Exception excp)
            {
                logger.LogError("Exception SIPDNSManager ResolveSIPService (" + sipURI.ToString() + "). " + excp.Message);
                m_inProgressSIPServiceLookups.Remove(sipURI.ToString());
                return(new SIPDNSLookupResult(sipURI, excp.Message));
            }
        }
Example #7
0
        public static SIPDNSLookupResult ResolveSIPService(SIPURI sipURI, bool async)
        {
            try
            {
                if (sipURI == null)
                {
                    throw new ArgumentNullException("sipURI", "Cannot resolve SIP service on a null URI.");
                }

                if (IPSocket.TryParseIPEndPoint(sipURI.Host, out var ipEndPoint))
                {
                    // Target is an IP address, no DNS lookup required.
                    SIPDNSLookupEndPoint sipLookupEndPoint = new SIPDNSLookupEndPoint(new SIPEndPoint(sipURI.Protocol, ipEndPoint), 0);
                    SIPDNSLookupResult   result            = new SIPDNSLookupResult(sipURI);
                    result.AddLookupResult(sipLookupEndPoint);
                    return(result);
                }
                else
                {
                    string host         = sipURI.Host;
                    int    port         = IPSocket.ParsePortFromSocket(sipURI.Host);
                    bool   explicitPort = (port != 0);

                    if (!explicitPort)
                    {
                        port = (sipURI.Scheme == SIPSchemesEnum.sip) ? m_defaultSIPPort : m_defaultSIPSPort;
                    }

                    if (host.Contains(".") == false)
                    {
                        string hostOnly = IPSocket.ParseHostFromSocket(host);

                        // If host is not fully qualified then assume there's no point using NAPTR or SRV record look ups and go straight to A's.
                        if (hostOnly.ToLower() == System.Net.Dns.GetHostName()?.ToLower())
                        {
                            // The lookup is for the current machine.
                            var addressList = System.Net.Dns.GetHostEntry(System.Net.Dns.GetHostName()).AddressList;

                            if (addressList?.Length == 0)
                            {
                                return(new SIPDNSLookupResult(sipURI, $"Failed to resolve local machine hostname."));
                            }
                            else
                            {
                                // Preference for IPv4 IP address for local host anem lookup.
                                IPAddress   firstAddress = addressList.Where(x => x.AddressFamily == AddressFamily.InterNetwork).FirstOrDefault() ?? addressList.FirstOrDefault();
                                SIPEndPoint resultEp     = new SIPEndPoint(sipURI.Protocol, new IPEndPoint(firstAddress, port));
                                return(new SIPDNSLookupResult(sipURI, resultEp));
                            }
                        }
                        else
                        {
                            return(DNSARecordLookup(hostOnly, port, async, sipURI));
                        }
                    }
                    else if (explicitPort)
                    {
                        // If target is a hostname with an explicit port then SIP lookup rules state to use DNS lookup for A or AAAA record.
                        host = host.Substring(0, host.LastIndexOf(':'));
                        return(DNSARecordLookup(host, port, async, sipURI));
                    }
                    else
                    {
                        // Target is a hostname with no explicit port, use the whole NAPTR->SRV->A lookup procedure.
                        SIPDNSLookupResult sipLookupResult = new SIPDNSLookupResult(sipURI);

                        // Do without the NAPTR lookup for the time being. Very few organisations appear to use them and it can cost up to 2.5s to get a failed resolution.

                        /*SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS full lookup requested for " + sipURI.ToString() + ".", null));
                         * DNSNAPTRRecordLookup(host, async, ref sipLookupResult);
                         * if (sipLookupResult.Pending)
                         * {
                         *  if (!m_inProgressSIPServiceLookups.Contains(sipURI.ToString()))
                         *  {
                         *      m_inProgressSIPServiceLookups.Add(sipURI.ToString());
                         *      ThreadPool.QueueUserWorkItem(delegate { ResolveSIPService(sipURI, false); });
                         *  }
                         *  return sipLookupResult;
                         * }*/

                        DNSSRVRecordLookup(sipURI.Scheme, sipURI.Protocol, host, async, ref sipLookupResult);
                        if (sipLookupResult.Pending)
                        {
                            //logger.LogDebug("SIPDNSManager SRV lookup for " + host + " is pending.");
                            return(sipLookupResult);
                        }
                        else
                        {
                            //logger.LogDebug("SIPDNSManager SRV lookup for " + host + " is final.");

                            // Add some custom logic to cope with sips SRV records using _sips._tcp (e.g. free.call.ciscospark.com).
                            // By default only _sips._tls SRV records are checked for. THis block adds an additional check for _sips._tcp SRV records.
                            //if ((sipLookupResult.SIPSRVResults == null || sipLookupResult.SIPSRVResults.Count == 0) && sipURI.Scheme == SIPSchemesEnum.sips)
                            //{
                            //    DNSSRVRecordLookup(sipURI.Scheme, SIPProtocolsEnum.tcp, host, async, ref sipLookupResult);
                            //    SIPDNSServiceResult nextSRVRecord = sipLookupResult.GetNextUnusedSRV();
                            //    int lookupPort = (nextSRVRecord != null) ? nextSRVRecord.Port : port;
                            //    return DNSARecordLookup(nextSRVRecord, host, lookupPort, async, sipLookupResult.URI);
                            //}
                            //else
                            //{
                            SIPDNSServiceResult nextSRVRecord = sipLookupResult.GetNextUnusedSRV();
                            int lookupPort = (nextSRVRecord != null) ? nextSRVRecord.Port : port;
                            return(DNSARecordLookup(nextSRVRecord, host, lookupPort, async, sipLookupResult.URI));
                            //}
                        }
                    }
                }
            }
            catch (Exception excp)
            {
                logger.LogError("Exception SIPDNSManager ResolveSIPService (" + sipURI.ToString() + "). " + excp.Message);
                m_inProgressSIPServiceLookups.Remove(sipURI.ToString());
                return(new SIPDNSLookupResult(sipURI, excp.Message));
            }
        }