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); }
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); } }
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; }
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)); } }
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); }
// 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)); } }
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)); } }