e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
148 lines
4.7 KiB
C#
148 lines
4.7 KiB
C#
//----------------------------------------------------------------------------
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//----------------------------------------------------------------------------
|
|
namespace System.ServiceModel.Channels
|
|
{
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Net;
|
|
using System.Net.NetworkInformation;
|
|
using System.Net.Sockets;
|
|
using System.Runtime;
|
|
using System.Security.Permissions;
|
|
using System.ServiceModel;
|
|
using System.ServiceModel.Dispatcher;
|
|
using System.Text;
|
|
|
|
static class DnsCache
|
|
{
|
|
const int mruWatermark = 64;
|
|
static MruCache<string, DnsCacheEntry> resolveCache = new MruCache<string, DnsCacheEntry>(mruWatermark);
|
|
static readonly TimeSpan cacheTimeout = TimeSpan.FromSeconds(2);
|
|
|
|
// Double-checked locking pattern requires volatile for read/write synchronization
|
|
static volatile string machineName;
|
|
|
|
static object ThisLock
|
|
{
|
|
get
|
|
{
|
|
return resolveCache;
|
|
}
|
|
}
|
|
|
|
public static string MachineName
|
|
{
|
|
get
|
|
{
|
|
if (machineName == null)
|
|
{
|
|
lock (ThisLock)
|
|
{
|
|
if (machineName == null)
|
|
{
|
|
try
|
|
{
|
|
machineName = Dns.GetHostEntry(String.Empty).HostName;
|
|
}
|
|
catch (SocketException exception)
|
|
{
|
|
DiagnosticUtility.TraceHandledException(exception,
|
|
TraceEventType.Information);
|
|
// we fall back to the NetBios machine if Dns fails
|
|
machineName = UnsafeNativeMethods.GetComputerName(ComputerNameFormat.PhysicalNetBIOS);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return machineName;
|
|
}
|
|
}
|
|
|
|
public static IPHostEntry Resolve(Uri uri)
|
|
{
|
|
string hostName = uri.DnsSafeHost;
|
|
IPHostEntry hostEntry = null;
|
|
DateTime now = DateTime.UtcNow;
|
|
|
|
lock (ThisLock)
|
|
{
|
|
DnsCacheEntry cacheEntry;
|
|
if (resolveCache.TryGetValue(hostName, out cacheEntry))
|
|
{
|
|
if (now.Subtract(cacheEntry.TimeStamp) > cacheTimeout)
|
|
{
|
|
resolveCache.Remove(hostName);
|
|
}
|
|
else
|
|
{
|
|
if (cacheEntry.HostEntry == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new EndpointNotFoundException(SR.GetString(SR.DnsResolveFailed, hostName)));
|
|
}
|
|
hostEntry = cacheEntry.HostEntry;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (hostEntry == null)
|
|
{
|
|
SocketException dnsException = null;
|
|
try
|
|
{
|
|
hostEntry = Dns.GetHostEntry(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)
|
|
resolveCache.Remove(hostName);
|
|
resolveCache.Add(hostName, new DnsCacheEntry(hostEntry, now));
|
|
}
|
|
|
|
if (dnsException != null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new EndpointNotFoundException(SR.GetString(SR.DnsResolveFailed, hostName), dnsException));
|
|
}
|
|
}
|
|
|
|
return hostEntry;
|
|
}
|
|
|
|
class DnsCacheEntry
|
|
{
|
|
IPHostEntry hostEntry;
|
|
DateTime timeStamp;
|
|
|
|
public DnsCacheEntry(IPHostEntry hostEntry, DateTime timeStamp)
|
|
{
|
|
this.hostEntry = hostEntry;
|
|
this.timeStamp = timeStamp;
|
|
}
|
|
|
|
public IPHostEntry HostEntry
|
|
{
|
|
get
|
|
{
|
|
return hostEntry;
|
|
}
|
|
}
|
|
|
|
public DateTime TimeStamp
|
|
{
|
|
get
|
|
{
|
|
return timeStamp;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|