private static async Task <IPHostEntry> GetHostEntryFromNameAsync(IDnsQuery query, string hostName) { if (string.IsNullOrWhiteSpace(hostName)) { throw new ArgumentNullException(nameof(hostName)); } var hostString = DnsString.FromResponseQueryString(hostName); var ipv4Result = query.QueryAsync(hostString, QueryType.A); var ipv6Result = query.QueryAsync(hostString, QueryType.AAAA); await Task.WhenAll(ipv4Result, ipv6Result).ConfigureAwait(false); var allRecords = ipv4Result.Result .Answers.Concat(ipv6Result.Result.Answers) .ToArray(); return(GetHostEntryProcessResult(hostString, allRecords)); }
public static async Task <ServiceHostEntry[]> ResolveServiceAsync(this IDnsQuery query, string baseDomain, string serviceName, string tag = null) { if (baseDomain == null) { throw new ArgumentNullException(nameof(baseDomain)); } if (string.IsNullOrWhiteSpace(serviceName)) { throw new ArgumentNullException(nameof(serviceName)); } string queryString; if (string.IsNullOrWhiteSpace(tag)) { queryString = $"{serviceName}.{baseDomain}."; } else { queryString = $"_{serviceName}._{tag}.{baseDomain}."; } var hosts = new List <ServiceHostEntry>(); var result = await query.QueryAsync(queryString, QueryType.SRV); if (result.HasError) { return(hosts.ToArray()); } foreach (var entry in result.Answers.SrvRecords()) { var addresses = result.Additionals .OfType <AddressRecord>() .Where(p => p.DomainName.Equals(entry.Target)) .Select(p => p.Address); hosts.Add(new ServiceHostEntry() { AddressList = addresses.ToArray(), HostName = entry.Target.Value, Port = entry.Port }); } return(hosts.ToArray()); }
/// <summary> /// The <c>ResolveServiceAsync</c> method does a <see cref="QueryType.SRV"/> lookup for <c>_{<paramref name="serviceName"/>}[._{<paramref name="tag"/>}].{<paramref name="baseDomain"/>}</c> /// and aggregates the result (hostname, port and list of <see cref="IPAddress"/>s) to a <see cref="ServiceHostEntry"/>. /// <para> /// This method expects matching A or AAAA records to populate the <see cref="IPHostEntry.AddressList"/>, /// and/or a <see cref="ResourceRecordType.CNAME"/> record to populate the <see cref="IPHostEntry.HostName"/> property of the result. /// </para> /// </summary> /// <remarks> /// The returned list of <see cref="IPAddress"/>s and/or the hostname can be empty if no matching additional records are found. /// </remarks> /// <param name="query">The <see cref="IDnsQuery"/> instance.</param> /// <param name="baseDomain">The base domain, which will be appended to the end of the query string.</param> /// <param name="serviceName">The name of the service to look for. Must not have any <c>_</c> prefix.</param> /// <param name="tag">An optional tag. Must not have any <c>_</c> prefix.</param> /// <returns>A collection of <see cref="ServiceHostEntry"/>s.</returns> /// <exception cref="ArgumentNullException">If <paramref name="baseDomain"/> or <paramref name="serviceName"/> are null.</exception> /// <seealso href="https://tools.ietf.org/html/rfc2782">RFC 2782</seealso> public static async Task <ServiceHostEntry[]> ResolveServiceAsync(this IDnsQuery query, string baseDomain, string serviceName, string tag = null) { if (query == null) { throw new ArgumentNullException(nameof(query)); } if (baseDomain == null) { throw new ArgumentNullException(nameof(baseDomain)); } if (string.IsNullOrWhiteSpace(serviceName)) { throw new ArgumentNullException(nameof(serviceName)); } var queryString = ConcatResolveServiceName(baseDomain, serviceName, tag); var result = await query.QueryAsync(queryString, QueryType.SRV).ConfigureAwait(false); return(ResolveServiceProcessResult(result)); }