| File: System\ServiceModel\Channels\DnsCache.cs | Web Access |
| Project: src\src\System.ServiceModel.NetTcp\src\System.ServiceModel.NetTcp.csproj (System.ServiceModel.NetTcp) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Net; using System.Net.Sockets; using System.Runtime; using System.Threading.Tasks; namespace System.ServiceModel.Channels { internal static class DnsCache { private const int MruWatermark = 64; private static MruCache<string, DnsCacheEntry> s_resolveCache = new MruCache<string, DnsCacheEntry>(MruWatermark); private static readonly TimeSpan s_cacheTimeout = TimeSpan.FromSeconds(2); // Double-checked locking pattern requires volatile for read/write synchronization private static volatile string s_machineName; private static object ThisLock { get { return s_resolveCache; } } public static string MachineName { get { if (s_machineName == null) { lock (ThisLock) { if (s_machineName == null) { try { s_machineName = Dns.GetHostEntry(string.Empty).HostName; } catch (SocketException) { throw; } } } } return s_machineName; } } public static async Task<IPAddress[]> ResolveAsync(Uri uri) { string hostName = uri.DnsSafeHost; IPAddress[] hostAddresses = null; DateTime now = DateTime.UtcNow; lock (ThisLock) { DnsCacheEntry cacheEntry; if (s_resolveCache.TryGetValue(hostName, out cacheEntry)) { if (now.Subtract(cacheEntry.TimeStamp) > s_cacheTimeout) { s_resolveCache.Remove(hostName); cacheEntry = null; } else { if (cacheEntry.AddressList == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new EndpointNotFoundException(SR.Format(SR.DnsResolveFailed, hostName))); } hostAddresses = cacheEntry.AddressList; } } } if (hostAddresses == null) { SocketException dnsException = null; try { hostAddresses = await LookupHostName(hostName); } catch (SocketException e) { dnsException = e; } lock (ThisLock) { // MruCache doesn't have a this[] operator, so we first remove (just in case it exists already) s_resolveCache.Remove(hostName); s_resolveCache.Add(hostName, new DnsCacheEntry(hostAddresses, now)); } if (dnsException != null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new EndpointNotFoundException(SR.Format(SR.DnsResolveFailed, hostName), dnsException)); } } return hostAddresses; } internal static async Task<IPAddress[]> LookupHostName(string hostName) { return (await Dns.GetHostEntryAsync(hostName)).AddressList; } internal class DnsCacheEntry { private IPAddress[] _addressList; public DnsCacheEntry(IPAddress[] addressList, DateTime timeStamp) { TimeStamp = timeStamp; _addressList = addressList; } public IPAddress[] AddressList { get { return _addressList; } } public DateTime TimeStamp { get; } } } }