| File: FallbackDnsResolver.cs | Web Access |
| Project: src\src\Libraries\Microsoft.Extensions.ServiceDiscovery.Dns\Microsoft.Extensions.ServiceDiscovery.Dns.csproj (Microsoft.Extensions.ServiceDiscovery.Dns) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using DnsClient; using DnsClient.Protocol; using Microsoft.Extensions.Options; using Microsoft.Extensions.ServiceDiscovery.Dns.Resolver; namespace Microsoft.Extensions.ServiceDiscovery.Dns; internal sealed class FallbackDnsResolver : IDnsResolver { private readonly LookupClient _lookupClient; private readonly IOptionsMonitor<DnsServiceEndpointProviderOptions> _options; private readonly TimeProvider _timeProvider; public FallbackDnsResolver(LookupClient lookupClient, IOptionsMonitor<DnsServiceEndpointProviderOptions> options, TimeProvider timeProvider) { _lookupClient = lookupClient; _options = options; _timeProvider = timeProvider; } private TimeSpan DefaultRefreshPeriod => _options.CurrentValue.DefaultRefreshPeriod; public async ValueTask<AddressResult[]> ResolveIPAddressesAsync(string name, CancellationToken cancellationToken = default) { DateTime expiresAt = _timeProvider.GetUtcNow().DateTime.Add(DefaultRefreshPeriod); var addresses = await System.Net.Dns.GetHostAddressesAsync(name, cancellationToken).ConfigureAwait(false); var results = new AddressResult[addresses.Length]; for (int i = 0; i < addresses.Length; i++) { results[i] = new AddressResult { Address = addresses[i], ExpiresAt = expiresAt }; } return results; } public async ValueTask<ServiceResult[]> ResolveServiceAsync(string name, CancellationToken cancellationToken = default) { DateTime now = _timeProvider.GetUtcNow().DateTime; var queryResult = await _lookupClient.QueryAsync(name, DnsClient.QueryType.SRV, cancellationToken: cancellationToken).ConfigureAwait(false); if (queryResult.HasError) { throw CreateException(name, queryResult.ErrorMessage); } var lookupMapping = new Dictionary<string, List<AddressResult>>(); foreach (var record in queryResult.Additionals.OfType<AddressRecord>()) { if (!lookupMapping.TryGetValue(record.DomainName, out var addresses)) { addresses = new List<AddressResult>(); lookupMapping[record.DomainName] = addresses; } addresses.Add(new AddressResult { Address = record.Address, ExpiresAt = now.Add(TimeSpan.FromSeconds(record.TimeToLive)) }); } var srvRecords = queryResult.Answers.OfType<SrvRecord>().ToList(); var results = new ServiceResult[srvRecords.Count]; for (int i = 0; i < srvRecords.Count; i++) { var record = srvRecords[i]; results[i] = new ServiceResult { ExpiresAt = now.Add(TimeSpan.FromSeconds(record.TimeToLive)), Priority = record.Priority, Weight = record.Weight, Port = record.Port, Target = record.Target, Addresses = lookupMapping.TryGetValue(record.Target, out var addresses) ? addresses.ToArray() : Array.Empty<AddressResult>() }; } return results; } private static InvalidOperationException CreateException(string dnsName, string errorMessage) { var msg = errorMessage switch { { Length: > 0 } => $"No DNS SRV records were found for DNS name '{dnsName}': {errorMessage}.", _ => $"No DNS SRV records were found for DNS name '{dnsName}'", }; return new InvalidOperationException(msg); } }