/// <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); var srvResult = await _lookupClient.ResolveServiceAsync(uri.MAddrOrHostAddress, uri.Scheme.ToString(), srvProtocol.ToString()).ConfigureAwait(false); (var srvHost, var srvPort) = GetHostAndPortFromSrvResult(srvResult); if (srvHost != null) { host = srvHost; port = srvPort != 0 ? srvPort : port; logger.LogDebug($"SIP DNS SRV for {uri} resolved to {host} and port {port}."); } } catch (Exception srvExcp) { logger.LogWarning(srvExcp, $"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(srvExcp, $"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(srvExcp, $"SIPDNS exception on A lookup. {srvExcp.Message}."); result = SIPEndPoint.Empty; } isDone = true; break; } } return(result); }