// 正引き v4/v6 Dual Stack 対応 public async Task <List <IPAddress> > GetIpAddressListDualStackAsync(string hostname, bool preferV6 = false, CancellationToken cancel = default, bool noCache = false) { try { ConcurrentBag <Tuple <IPAddress, int> > list = new(); var queryTypeList = new DnsResolverQueryType[] { DnsResolverQueryType.A, DnsResolverQueryType.AAAA }; await TaskUtil.ForEachAsync(int.MaxValue, queryTypeList, async (item, index, cancel) => { var resultsList = await GetIpAddressListSingleStackAsync(hostname, item, null, cancel, noCache); if (resultsList != null) { int i = 0; foreach (var ip in resultsList.Distinct(IpComparer.Comparer)) { list.Add(new Tuple <IPAddress, int>(ip, i)); i++; } } }, cancel, 0); return(list.OrderBy(x => (int)x.Item1.AddressFamily * (preferV6 ? -1 : 1)).Select(x => x.Item1).Distinct().ToList()); } catch { return(new List <IPAddress>(0)); } }
protected abstract Task <IEnumerable <IPAddress>?> GetIpAddressListImplAsync(string hostname, DnsResolverQueryType queryType, Ref <DnsAdditionalResults>?additional = null, CancellationToken cancel = default);
protected override async Task <IEnumerable <IPAddress>?> GetIpAddressListImplAsync(string hostname, DnsResolverQueryType queryType, Ref <DnsAdditionalResults>?additional = null, CancellationToken cancel = default) { DnsAdditionalResults additionalData = new DnsAdditionalResults(true, false); QueryType qt; switch (queryType) { case DnsResolverQueryType.A: qt = QueryType.A; break; case DnsResolverQueryType.AAAA: qt = QueryType.AAAA; break; default: throw new ArgumentOutOfRangeException(nameof(queryType)); } try { var res = await Client.QueryAsync(hostname, qt, queryClass : QueryClass.IN, cancel); if (res.Header.ResponseCode == DnsHeaderResponseCode.NotExistentDomain) { additionalData = new DnsAdditionalResults(false, true); } if (res.HasError) { additionalData = new DnsAdditionalResults(true, false); return(null); } if (qt == QueryType.A) { return(res.Answers?.ARecords().Where(x => x.Address.AddressFamily == AddressFamily.InterNetwork).Select(x => x.Address).ToArray() ?? null); } else { return(res.Answers?.AaaaRecords().Where(x => x.Address.AddressFamily == AddressFamily.InterNetworkV6).Select(x => x.Address).ToArray() ?? null); } } finally { additional?.Set(additionalData); } }