diff --git a/src/Enyim.Caching/Configuration/IMemcachedClientConfiguration.cs b/src/Enyim.Caching/Configuration/IMemcachedClientConfiguration.cs index 6463908b..9349167c 100755 --- a/src/Enyim.Caching/Configuration/IMemcachedClientConfiguration.cs +++ b/src/Enyim.Caching/Configuration/IMemcachedClientConfiguration.cs @@ -44,6 +44,8 @@ public interface IMemcachedClientConfiguration bool UseSslStream { get; } + bool UseIPv6 { get; } + bool SuppressException { get; } } } diff --git a/src/Enyim.Caching/Configuration/MemcachedClientConfiguration.cs b/src/Enyim.Caching/Configuration/MemcachedClientConfiguration.cs index d7c721e3..fd5f6195 100755 --- a/src/Enyim.Caching/Configuration/MemcachedClientConfiguration.cs +++ b/src/Enyim.Caching/Configuration/MemcachedClientConfiguration.cs @@ -121,6 +121,7 @@ public MemcachedClientConfiguration( } UseSslStream = options.UseSslStream; + UseIPv6 = options.UseIPv6; SuppressException = options.SuppressException; if (!string.IsNullOrEmpty(options.KeyTransformer)) @@ -201,7 +202,7 @@ private void ConfigureServers(MemcachedClientOptions options) if (!IPAddress.TryParse(server.Address, out var address)) { address = Dns.GetHostAddresses(server.Address) - .FirstOrDefault(i => i.AddressFamily == AddressFamily.InterNetwork); + .FirstOrDefault(i => i.AddressFamily == (options.UseIPv6 ? AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork)); if (address == null) { @@ -348,7 +349,7 @@ IServerPool IMemcachedClientConfiguration.CreatePool() } public bool UseSslStream { get; private set; } - + public bool UseIPv6 { get; private set; } public bool SuppressException { get; private set; } #endregion diff --git a/src/Enyim.Caching/Configuration/MemcachedClientOptions.cs b/src/Enyim.Caching/Configuration/MemcachedClientOptions.cs index aa36c492..1b8f2433 100644 --- a/src/Enyim.Caching/Configuration/MemcachedClientOptions.cs +++ b/src/Enyim.Caching/Configuration/MemcachedClientOptions.cs @@ -23,6 +23,8 @@ public class MemcachedClientOptions : IOptions public bool UseSslStream { get; set; } + public bool UseIPv6 { get; set; } + public bool SuppressException { get; set; } = true; public IProviderFactory NodeLocatorFactory { get; set; } diff --git a/src/Enyim.Caching/Memcached/DefaultServerPool.cs b/src/Enyim.Caching/Memcached/DefaultServerPool.cs index 3bb1854c..46885496 100644 --- a/src/Enyim.Caching/Memcached/DefaultServerPool.cs +++ b/src/Enyim.Caching/Memcached/DefaultServerPool.cs @@ -50,7 +50,7 @@ public DefaultServerPool( protected virtual IMemcachedNode CreateNode(EndPoint endpoint) { - return new MemcachedNode(endpoint, _configuration.SocketPool, _logger, _configuration.UseSslStream); + return new MemcachedNode(endpoint, _configuration.SocketPool, _logger, _configuration.UseSslStream, _configuration.UseIPv6); } private void rezCallback(object state) diff --git a/src/Enyim.Caching/Memcached/MemcachedNode.cs b/src/Enyim.Caching/Memcached/MemcachedNode.cs index da2e9d2b..abce961a 100755 --- a/src/Enyim.Caching/Memcached/MemcachedNode.cs +++ b/src/Enyim.Caching/Memcached/MemcachedNode.cs @@ -36,12 +36,14 @@ public class MemcachedNode : IMemcachedNode private SemaphoreSlim poolInitSemaphore = new SemaphoreSlim(1, 1); private readonly TimeSpan _initPoolTimeout; private bool _useSslStream; + private bool _useIPv6; public MemcachedNode( EndPoint endpoint, ISocketPoolConfiguration socketPoolConfig, ILogger logger, - bool useSslStream) + bool useSslStream, + bool useIPv6) { _endPoint = endpoint; _useSslStream = useSslStream; @@ -62,6 +64,7 @@ public MemcachedNode( _logger = logger; _internalPoolImpl = new InternalPoolImpl(this, socketPoolConfig, _logger); + _useIPv6 = useIPv6; } public event Action Failed; @@ -856,7 +859,7 @@ protected internal virtual PooledSocket CreateSocket() { try { - var ps = new PooledSocket(_endPoint, _config.ConnectionTimeout, _config.ReceiveTimeout, _logger, _useSslStream); + var ps = new PooledSocket(_endPoint, _config.ConnectionTimeout, _config.ReceiveTimeout, _logger, _useSslStream, _useIPv6); ps.Connect(); return ps; } @@ -872,7 +875,7 @@ protected internal virtual async Task CreateSocketAsync() { try { - var ps = new PooledSocket(_endPoint, _config.ConnectionTimeout, _config.ReceiveTimeout, _logger, _useSslStream); + var ps = new PooledSocket(_endPoint, _config.ConnectionTimeout, _config.ReceiveTimeout, _logger, _useSslStream, _useIPv6); await ps.ConnectAsync(); return ps; } diff --git a/src/Enyim.Caching/Memcached/PooledSocket.cs b/src/Enyim.Caching/Memcached/PooledSocket.cs index 7dee258b..0d8cd019 100755 --- a/src/Enyim.Caching/Memcached/PooledSocket.cs +++ b/src/Enyim.Caching/Memcached/PooledSocket.cs @@ -20,6 +20,7 @@ public partial class PooledSocket : IDisposable private bool _isAlive; private bool _useSslStream; + private bool _useIPv6; private Socket _socket; private readonly EndPoint _endpoint; private readonly int _connectionTimeout; @@ -27,13 +28,14 @@ public partial class PooledSocket : IDisposable private NetworkStream _inputStream; private SslStream _sslStream; - public PooledSocket(EndPoint endpoint, TimeSpan connectionTimeout, TimeSpan receiveTimeout, ILogger logger, bool useSslStream) + public PooledSocket(EndPoint endpoint, TimeSpan connectionTimeout, TimeSpan receiveTimeout, ILogger logger, bool useSslStream, bool useIPv6) { _logger = logger; _isAlive = true; _useSslStream = useSslStream; + _useIPv6 = useIPv6; - var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + var socket = new Socket(useIPv6 ? AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true); socket.NoDelay = true; @@ -540,10 +542,10 @@ private IPEndPoint GetIPEndPoint(EndPoint endpoint) { var dnsEndPoint = (DnsEndPoint)endpoint; var address = Dns.GetHostAddresses(dnsEndPoint.Host).FirstOrDefault(ip => - ip.AddressFamily == AddressFamily.InterNetwork); - if (address == null) - throw new ArgumentException(String.Format("Could not resolve host '{0}'.", endpoint)); - return new IPEndPoint(address, dnsEndPoint.Port); + ip.AddressFamily == (_useIPv6 ? AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork)); + return address == null + ? throw new ArgumentException(string.Format("Could not resolve host '{0}'.", endpoint)) + : new IPEndPoint(address, dnsEndPoint.Port); } else if (endpoint is IPEndPoint) { diff --git a/src/Enyim.Caching/Memcached/Protocol/Binary/BinaryNode.cs b/src/Enyim.Caching/Memcached/Protocol/Binary/BinaryNode.cs index 8a6a9410..a4c26b39 100644 --- a/src/Enyim.Caching/Memcached/Protocol/Binary/BinaryNode.cs +++ b/src/Enyim.Caching/Memcached/Protocol/Binary/BinaryNode.cs @@ -24,8 +24,9 @@ public BinaryNode( ISocketPoolConfiguration config, ISaslAuthenticationProvider authenticationProvider, ILogger logger, - bool useSslStream) - : base(endpoint, config, logger, useSslStream) + bool useSslStream, + bool useIPv6) + : base(endpoint, config, logger, useSslStream, useIPv6) { _authenticationProvider = authenticationProvider; _logger = logger; diff --git a/src/Enyim.Caching/Memcached/Protocol/Binary/BinaryPool.cs b/src/Enyim.Caching/Memcached/Protocol/Binary/BinaryPool.cs index 63c6c912..01a8e558 100644 --- a/src/Enyim.Caching/Memcached/Protocol/Binary/BinaryPool.cs +++ b/src/Enyim.Caching/Memcached/Protocol/Binary/BinaryPool.cs @@ -29,7 +29,7 @@ public BinaryPool(IMemcachedClientConfiguration configuration, ILogger logger) protected override IMemcachedNode CreateNode(EndPoint endpoint) { - return new BinaryNode(endpoint, _configuration.SocketPool, _authenticationProvider, _logger, _configuration.UseSslStream); + return new BinaryNode(endpoint, _configuration.SocketPool, _authenticationProvider, _logger, _configuration.UseSslStream, _configuration.UseIPv6); } private static ISaslAuthenticationProvider GetProvider(IMemcachedClientConfiguration configuration)