diff --git a/Enyim.Caching/Configuration/IMemcachedClientConfiguration.cs b/Enyim.Caching/Configuration/IMemcachedClientConfiguration.cs
index b9cc125e..2951d33e 100755
--- a/Enyim.Caching/Configuration/IMemcachedClientConfiguration.cs
+++ b/Enyim.Caching/Configuration/IMemcachedClientConfiguration.cs
@@ -42,6 +42,8 @@ public interface IMemcachedClientConfiguration
IServerPool CreatePool();
+ bool UseSslStream { get; }
+
}
}
diff --git a/Enyim.Caching/Configuration/MemcachedClientConfiguration.cs b/Enyim.Caching/Configuration/MemcachedClientConfiguration.cs
index 9e93bcc5..d28b9504 100755
--- a/Enyim.Caching/Configuration/MemcachedClientConfiguration.cs
+++ b/Enyim.Caching/Configuration/MemcachedClientConfiguration.cs
@@ -1,352 +1,363 @@
-using System;
-using System.Collections.Generic;
-using System.Net;
-using Enyim.Caching.Memcached;
-using Enyim.Reflection;
-using Enyim.Caching.Memcached.Protocol.Binary;
-using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Options;
-using Microsoft.Extensions.Configuration;
-using System.Linq;
-using System.Net.Sockets;
-
-namespace Enyim.Caching.Configuration
-{
- ///
- /// Configuration class
- ///
- public class MemcachedClientConfiguration : IMemcachedClientConfiguration
- {
- // these are lazy initialized in the getters
- private Type nodeLocator;
- private ITranscoder _transcoder;
- private IMemcachedKeyTransformer _keyTransformer;
- private ILogger _logger;
-
- ///
- /// Initializes a new instance of the class.
- ///
- public MemcachedClientConfiguration(
- ILoggerFactory loggerFactory,
- IOptions optionsAccessor,
- IConfiguration configuration = null,
- ITranscoder transcoder = null,
- IMemcachedKeyTransformer keyTransformer = null)
- {
- if (optionsAccessor == null)
- {
- throw new ArgumentNullException(nameof(optionsAccessor));
- }
-
- _logger = loggerFactory.CreateLogger();
-
- var options = optionsAccessor.Value;
- if ((options == null || options.Servers.Count == 0) && configuration != null)
- {
- var section = configuration.GetSection("enyimMemcached");
- if (section.Exists())
- {
- section.Bind(options);
- }
- else
- {
- _logger.LogWarning($"No enyimMemcached setting in appsetting.json. Use default configuration");
- options.AddDefaultServer();
- }
- }
-
- ConfigureServers(options);
-
- SocketPool = new SocketPoolConfiguration();
- if (options.SocketPool != null)
- {
- options.SocketPool.CheckPoolSize();
- options.SocketPool.CheckTimeout();
-
- SocketPool.MinPoolSize = options.SocketPool.MinPoolSize;
- _logger.LogInformation($"{nameof(SocketPool.MinPoolSize)}: {SocketPool.MinPoolSize}");
-
- SocketPool.MaxPoolSize = options.SocketPool.MaxPoolSize;
- _logger.LogInformation($"{nameof(SocketPool.MaxPoolSize)}: {SocketPool.MaxPoolSize}");
-
- SocketPool.ConnectionTimeout = options.SocketPool.ConnectionTimeout;
- _logger.LogInformation($"{nameof(SocketPool.ConnectionTimeout)}: {SocketPool.ConnectionTimeout}");
-
- SocketPool.ReceiveTimeout = options.SocketPool.ReceiveTimeout;
- _logger.LogInformation($"{nameof(SocketPool.ReceiveTimeout)}: {SocketPool.ReceiveTimeout}");
-
- SocketPool.DeadTimeout = options.SocketPool.DeadTimeout;
- _logger.LogInformation($"{nameof(SocketPool.DeadTimeout)}: {SocketPool.DeadTimeout}");
-
- SocketPool.QueueTimeout = options.SocketPool.QueueTimeout;
- _logger.LogInformation($"{nameof(SocketPool.QueueTimeout)}: {SocketPool.QueueTimeout}");
-
- SocketPool.InitPoolTimeout = options.SocketPool.InitPoolTimeout;
-
- SocketPool.FailurePolicyFactory = options.SocketPool.FailurePolicyFactory;
- }
-
- Protocol = options.Protocol;
-
- if (options.Authentication != null && !string.IsNullOrEmpty(options.Authentication.Type))
- {
- try
- {
- var authenticationType = Type.GetType(options.Authentication.Type);
- if (authenticationType != null)
- {
- _logger.LogDebug($"Authentication type is {authenticationType}.");
-
- Authentication = new AuthenticationConfiguration();
- Authentication.Type = authenticationType;
- foreach (var parameter in options.Authentication.Parameters)
- {
- Authentication.Parameters[parameter.Key] = parameter.Value;
- _logger.LogDebug($"Authentication {parameter.Key} is '{parameter.Value}'.");
- }
- }
- else
- {
- _logger.LogError($"Unable to load authentication type {options.Authentication.Type}.");
- }
- }
- catch (Exception ex)
- {
- _logger.LogError(new EventId(), ex, $"Unable to load authentication type {options.Authentication.Type}.");
- }
- }
-
- if (!string.IsNullOrEmpty(options.KeyTransformer))
- {
- try
- {
- var keyTransformerType = Type.GetType(options.KeyTransformer);
- if (keyTransformerType != null)
- {
- KeyTransformer = Activator.CreateInstance(keyTransformerType) as IMemcachedKeyTransformer;
- _logger.LogDebug($"Use '{options.KeyTransformer}' KeyTransformer");
- }
- }
- catch (Exception ex)
- {
- _logger.LogError(new EventId(), ex, $"Unable to load '{options.KeyTransformer}' KeyTransformer");
- }
- }
- else if (keyTransformer != null)
- {
- this._keyTransformer = keyTransformer;
- _logger.LogDebug($"Use KeyTransformer Type : '{keyTransformer.ToString()}'");
- }
-
- if (NodeLocator == null)
- {
- NodeLocator = options.Servers.Count > 1 ? typeof(DefaultNodeLocator) : typeof(SingleNodeLocator);
- }
-
- if (!string.IsNullOrEmpty(options.Transcoder))
- {
- try
- {
- if (options.Transcoder == "BinaryFormatterTranscoder")
- options.Transcoder = "Enyim.Caching.Memcached.Transcoders.BinaryFormatterTranscoder";
-
- var transcoderType = Type.GetType(options.Transcoder);
- if (transcoderType != null)
- {
- Transcoder = Activator.CreateInstance(transcoderType) as ITranscoder;
- _logger.LogDebug($"Use '{options.Transcoder}'");
- }
- }
- catch (Exception ex)
- {
- _logger.LogError(new EventId(), ex, $"Unable to load '{options.Transcoder}'");
- }
- }
- else if (transcoder != null)
- {
- this._transcoder = transcoder;
- _logger.LogDebug($"Use Transcoder Type : '{transcoder.ToString()}'");
- }
-
- if (options.NodeLocatorFactory != null)
- {
- NodeLocatorFactory = options.NodeLocatorFactory;
- }
- }
-
- private void ConfigureServers(MemcachedClientOptions options)
- {
- Servers = new List();
- foreach (var server in options.Servers)
- {
- if (!IPAddress.TryParse(server.Address, out var address))
- {
- address = Dns.GetHostAddresses(server.Address)
- .FirstOrDefault(i => i.AddressFamily == AddressFamily.InterNetwork);
-
- if (address == null)
- {
- _logger.LogError($"Could not resolve host '{server.Address}'.");
- }
- else
- {
- _logger.LogInformation($"Memcached server address - {address}");
- }
- }
- else
- {
- _logger.LogInformation($"Memcached server address - {server.Address }:{server.Port}");
- }
-
- Servers.Add(new IPEndPoint(address, server.Port));
- }
- }
-
- ///
- /// Adds a new server to the pool.
- ///
- /// The address and the port of the server in the format 'host:port'.
- public void AddServer(string address)
- {
- this.Servers.Add(ConfigurationHelper.ResolveToEndPoint(address));
- }
-
- ///
- /// Adds a new server to the pool.
- ///
- /// The host name or IP address of the server.
- /// The port number of the memcached instance.
- public void AddServer(string host, int port)
- {
- this.Servers.Add(new DnsEndPoint(host, port));
- }
-
- ///
- /// Gets a list of each representing a Memcached server in the pool.
- ///
- public IList Servers { get; private set; }
-
- ///
- /// Gets the configuration of the socket pool.
- ///
- public ISocketPoolConfiguration SocketPool { get; private set; }
-
- ///
- /// Gets the authentication settings.
- ///
- public IAuthenticationConfiguration Authentication { get; private set; }
-
- ///
- /// Gets or sets the which will be used to convert item keys for Memcached.
- ///
- public IMemcachedKeyTransformer KeyTransformer
- {
- get { return this._keyTransformer ?? (this._keyTransformer = new DefaultKeyTransformer()); }
- set { this._keyTransformer = value; }
- }
-
- ///
- /// Gets or sets the Type of the which will be used to assign items to Memcached nodes.
- ///
- /// If both and are assigned then the latter takes precedence.
- public Type NodeLocator
- {
- get { return this.nodeLocator; }
- set
- {
- ConfigurationHelper.CheckForInterface(value, typeof(IMemcachedNodeLocator));
- this.nodeLocator = value;
- }
- }
-
- ///
- /// Gets or sets the NodeLocatorFactory instance which will be used to create a new IMemcachedNodeLocator instances.
- ///
- /// If both and are assigned then the latter takes precedence.
- public IProviderFactory NodeLocatorFactory { get; set; }
-
- ///
- /// Gets or sets the which will be used serialize or deserialize items.
- ///
- public ITranscoder Transcoder
- {
- get { return _transcoder ?? (_transcoder = new DefaultTranscoder()); }
- set { _transcoder = value; }
- }
-
- ///
- /// Gets or sets the type of the communication between client and server.
- ///
- public MemcachedProtocol Protocol { get; set; }
-
- #region [ interface ]
-
- IList IMemcachedClientConfiguration.Servers
- {
- get { return this.Servers; }
- }
-
- ISocketPoolConfiguration IMemcachedClientConfiguration.SocketPool
- {
- get { return this.SocketPool; }
- }
-
- IAuthenticationConfiguration IMemcachedClientConfiguration.Authentication
- {
- get { return this.Authentication; }
- }
-
- IMemcachedKeyTransformer IMemcachedClientConfiguration.CreateKeyTransformer()
- {
- return this.KeyTransformer;
- }
-
- IMemcachedNodeLocator IMemcachedClientConfiguration.CreateNodeLocator()
- {
- var f = this.NodeLocatorFactory;
- if (f != null) return f.Create();
-
- return this.NodeLocator == null
- ? new SingleNodeLocator()
- : (IMemcachedNodeLocator)FastActivator.Create(this.NodeLocator);
- }
-
- ITranscoder IMemcachedClientConfiguration.CreateTranscoder()
- {
- return this.Transcoder;
- }
-
- IServerPool IMemcachedClientConfiguration.CreatePool()
- {
- switch (this.Protocol)
- {
- case MemcachedProtocol.Text: return new DefaultServerPool(this, new Memcached.Protocol.Text.TextOperationFactory(), _logger);
- case MemcachedProtocol.Binary: return new BinaryPool(this, _logger);
- }
-
- throw new ArgumentOutOfRangeException("Unknown protocol: " + (int)this.Protocol);
- }
-
- #endregion
- }
-}
-
-#region [ License information ]
-/* ************************************************************
- *
- * Copyright (c) 2010 Attila Kisk? enyim.com
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * ************************************************************/
-#endregion
+using System;
+using System.Collections.Generic;
+using System.Net;
+using Enyim.Caching.Memcached;
+using Enyim.Reflection;
+using Enyim.Caching.Memcached.Protocol.Binary;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using Microsoft.Extensions.Configuration;
+using System.Linq;
+using System.Net.Sockets;
+
+namespace Enyim.Caching.Configuration
+{
+ ///
+ /// Configuration class
+ ///
+ public class MemcachedClientConfiguration : IMemcachedClientConfiguration
+ {
+ // these are lazy initialized in the getters
+ private Type nodeLocator;
+ private ITranscoder _transcoder;
+ private IMemcachedKeyTransformer _keyTransformer;
+ private ILogger _logger;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public MemcachedClientConfiguration(
+ ILoggerFactory loggerFactory,
+ IOptions optionsAccessor,
+ IConfiguration configuration = null,
+ ITranscoder transcoder = null,
+ IMemcachedKeyTransformer keyTransformer = null)
+ {
+ if (optionsAccessor == null)
+ {
+ throw new ArgumentNullException(nameof(optionsAccessor));
+ }
+
+ _logger = loggerFactory.CreateLogger();
+
+ var options = optionsAccessor.Value;
+ if ((options == null || options.Servers.Count == 0) && configuration != null)
+ {
+ var section = configuration.GetSection("enyimMemcached");
+ if (section.Exists())
+ {
+ section.Bind(options);
+ }
+ else
+ {
+ _logger.LogWarning($"No enyimMemcached setting in appsetting.json. Use default configuration");
+ options.AddDefaultServer();
+ }
+ }
+
+ ConfigureServers(options);
+
+ SocketPool = new SocketPoolConfiguration();
+ if (options.SocketPool != null)
+ {
+ options.SocketPool.CheckPoolSize();
+ options.SocketPool.CheckTimeout();
+
+ SocketPool.MinPoolSize = options.SocketPool.MinPoolSize;
+ _logger.LogInformation($"{nameof(SocketPool.MinPoolSize)}: {SocketPool.MinPoolSize}");
+
+ SocketPool.MaxPoolSize = options.SocketPool.MaxPoolSize;
+ _logger.LogInformation($"{nameof(SocketPool.MaxPoolSize)}: {SocketPool.MaxPoolSize}");
+
+ SocketPool.ConnectionTimeout = options.SocketPool.ConnectionTimeout;
+ _logger.LogInformation($"{nameof(SocketPool.ConnectionTimeout)}: {SocketPool.ConnectionTimeout}");
+
+ SocketPool.ReceiveTimeout = options.SocketPool.ReceiveTimeout;
+ _logger.LogInformation($"{nameof(SocketPool.ReceiveTimeout)}: {SocketPool.ReceiveTimeout}");
+
+ SocketPool.DeadTimeout = options.SocketPool.DeadTimeout;
+ _logger.LogInformation($"{nameof(SocketPool.DeadTimeout)}: {SocketPool.DeadTimeout}");
+
+ SocketPool.QueueTimeout = options.SocketPool.QueueTimeout;
+ _logger.LogInformation($"{nameof(SocketPool.QueueTimeout)}: {SocketPool.QueueTimeout}");
+
+ SocketPool.InitPoolTimeout = options.SocketPool.InitPoolTimeout;
+
+ SocketPool.FailurePolicyFactory = options.SocketPool.FailurePolicyFactory;
+ }
+
+ Protocol = options.Protocol;
+
+ if (options.Authentication != null && !string.IsNullOrEmpty(options.Authentication.Type))
+ {
+ try
+ {
+ var authenticationType = Type.GetType(options.Authentication.Type);
+ if (authenticationType != null)
+ {
+ _logger.LogDebug($"Authentication type is {authenticationType}.");
+
+ Authentication = new AuthenticationConfiguration();
+ Authentication.Type = authenticationType;
+ foreach (var parameter in options.Authentication.Parameters)
+ {
+ Authentication.Parameters[parameter.Key] = parameter.Value;
+ _logger.LogDebug($"Authentication {parameter.Key} is '{parameter.Value}'.");
+ }
+ }
+ else
+ {
+ _logger.LogError($"Unable to load authentication type {options.Authentication.Type}.");
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(new EventId(), ex, $"Unable to load authentication type {options.Authentication.Type}.");
+ }
+ }
+
+ UseSslStream = options.UseSslStream;
+
+ if (!string.IsNullOrEmpty(options.KeyTransformer))
+ {
+ try
+ {
+ var keyTransformerType = Type.GetType(options.KeyTransformer);
+ if (keyTransformerType != null)
+ {
+ KeyTransformer = Activator.CreateInstance(keyTransformerType) as IMemcachedKeyTransformer;
+ _logger.LogDebug($"Use '{options.KeyTransformer}' KeyTransformer");
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(new EventId(), ex, $"Unable to load '{options.KeyTransformer}' KeyTransformer");
+ }
+ }
+ else if (keyTransformer != null)
+ {
+ this._keyTransformer = keyTransformer;
+ _logger.LogDebug($"Use KeyTransformer Type : '{keyTransformer.ToString()}'");
+ }
+
+ if (NodeLocator == null)
+ {
+ NodeLocator = options.Servers.Count > 1 ? typeof(DefaultNodeLocator) : typeof(SingleNodeLocator);
+ }
+
+ if (!string.IsNullOrEmpty(options.Transcoder))
+ {
+ try
+ {
+ if (options.Transcoder == "BinaryFormatterTranscoder")
+ options.Transcoder = "Enyim.Caching.Memcached.Transcoders.BinaryFormatterTranscoder";
+
+ var transcoderType = Type.GetType(options.Transcoder);
+ if (transcoderType != null)
+ {
+ Transcoder = Activator.CreateInstance(transcoderType) as ITranscoder;
+ _logger.LogDebug($"Use '{options.Transcoder}'");
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(new EventId(), ex, $"Unable to load '{options.Transcoder}'");
+ }
+ }
+ else if (transcoder != null)
+ {
+ this._transcoder = transcoder;
+ _logger.LogDebug($"Use Transcoder Type : '{transcoder.ToString()}'");
+ }
+
+ if (options.NodeLocatorFactory != null)
+ {
+ NodeLocatorFactory = options.NodeLocatorFactory;
+ }
+ }
+
+ private void ConfigureServers(MemcachedClientOptions options)
+ {
+ Servers = new List();
+ foreach (var server in options.Servers)
+ {
+ if (options.UseSslStream)
+ {
+ AddServer(server.Address, server.Port);
+ }
+ else
+ {
+ if (!IPAddress.TryParse(server.Address, out var address))
+ {
+ address = Dns.GetHostAddresses(server.Address)
+ .FirstOrDefault(i => i.AddressFamily == AddressFamily.InterNetwork);
+
+ if (address == null)
+ {
+ _logger.LogError($"Could not resolve host '{server.Address}'.");
+ }
+ else
+ {
+ _logger.LogInformation($"Memcached server address - {address}");
+ }
+ }
+ else
+ {
+ _logger.LogInformation($"Memcached server address - {server.Address }:{server.Port}");
+ }
+
+ Servers.Add(new IPEndPoint(address, server.Port));
+ }
+ }
+ }
+
+ ///
+ /// Adds a new server to the pool.
+ ///
+ /// The address and the port of the server in the format 'host:port'.
+ public void AddServer(string address)
+ {
+ this.Servers.Add(ConfigurationHelper.ResolveToEndPoint(address));
+ }
+
+ ///
+ /// Adds a new server to the pool.
+ ///
+ /// The host name or IP address of the server.
+ /// The port number of the memcached instance.
+ public void AddServer(string host, int port)
+ {
+ this.Servers.Add(new DnsEndPoint(host, port));
+ }
+
+ ///
+ /// Gets a list of each representing a Memcached server in the pool.
+ ///
+ public IList Servers { get; private set; }
+
+ ///
+ /// Gets the configuration of the socket pool.
+ ///
+ public ISocketPoolConfiguration SocketPool { get; private set; }
+
+ ///
+ /// Gets the authentication settings.
+ ///
+ public IAuthenticationConfiguration Authentication { get; private set; }
+
+ ///
+ /// Gets or sets the which will be used to convert item keys for Memcached.
+ ///
+ public IMemcachedKeyTransformer KeyTransformer
+ {
+ get { return this._keyTransformer ?? (this._keyTransformer = new DefaultKeyTransformer()); }
+ set { this._keyTransformer = value; }
+ }
+
+ ///
+ /// Gets or sets the Type of the which will be used to assign items to Memcached nodes.
+ ///
+ /// If both and are assigned then the latter takes precedence.
+ public Type NodeLocator
+ {
+ get { return this.nodeLocator; }
+ set
+ {
+ ConfigurationHelper.CheckForInterface(value, typeof(IMemcachedNodeLocator));
+ this.nodeLocator = value;
+ }
+ }
+
+ ///
+ /// Gets or sets the NodeLocatorFactory instance which will be used to create a new IMemcachedNodeLocator instances.
+ ///
+ /// If both and are assigned then the latter takes precedence.
+ public IProviderFactory NodeLocatorFactory { get; set; }
+
+ ///
+ /// Gets or sets the which will be used serialize or deserialize items.
+ ///
+ public ITranscoder Transcoder
+ {
+ get { return _transcoder ?? (_transcoder = new DefaultTranscoder()); }
+ set { _transcoder = value; }
+ }
+
+ ///
+ /// Gets or sets the type of the communication between client and server.
+ ///
+ public MemcachedProtocol Protocol { get; set; }
+
+ #region [ interface ]
+
+ IList IMemcachedClientConfiguration.Servers
+ {
+ get { return this.Servers; }
+ }
+
+ ISocketPoolConfiguration IMemcachedClientConfiguration.SocketPool
+ {
+ get { return this.SocketPool; }
+ }
+
+ IAuthenticationConfiguration IMemcachedClientConfiguration.Authentication
+ {
+ get { return this.Authentication; }
+ }
+
+ IMemcachedKeyTransformer IMemcachedClientConfiguration.CreateKeyTransformer()
+ {
+ return this.KeyTransformer;
+ }
+
+ IMemcachedNodeLocator IMemcachedClientConfiguration.CreateNodeLocator()
+ {
+ var f = this.NodeLocatorFactory;
+ if (f != null) return f.Create();
+
+ return this.NodeLocator == null
+ ? new SingleNodeLocator()
+ : (IMemcachedNodeLocator)FastActivator.Create(this.NodeLocator);
+ }
+
+ ITranscoder IMemcachedClientConfiguration.CreateTranscoder()
+ {
+ return this.Transcoder;
+ }
+
+ IServerPool IMemcachedClientConfiguration.CreatePool()
+ {
+ switch (this.Protocol)
+ {
+ case MemcachedProtocol.Text: return new DefaultServerPool(this, new Memcached.Protocol.Text.TextOperationFactory(), _logger);
+ case MemcachedProtocol.Binary: return new BinaryPool(this, _logger);
+ }
+
+ throw new ArgumentOutOfRangeException("Unknown protocol: " + (int)this.Protocol);
+ }
+
+ public bool UseSslStream { get; private set; }
+
+ #endregion
+ }
+}
+
+#region [ License information ]
+/* ************************************************************
+ *
+ * Copyright (c) 2010 Attila Kisk? enyim.com
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ************************************************************/
+#endregion
diff --git a/Enyim.Caching/Configuration/MemcachedClientOptions.cs b/Enyim.Caching/Configuration/MemcachedClientOptions.cs
index 0a9306d9..4f58ab85 100644
--- a/Enyim.Caching/Configuration/MemcachedClientOptions.cs
+++ b/Enyim.Caching/Configuration/MemcachedClientOptions.cs
@@ -21,6 +21,8 @@ public class MemcachedClientOptions : IOptions
public string Transcoder { get; set; }
+ public bool UseSslStream { get; set; }
+
public IProviderFactory NodeLocatorFactory { get; set; }
public MemcachedClientOptions Value => this;
diff --git a/Enyim.Caching/Configuration/SocketPoolConfiguration.cs b/Enyim.Caching/Configuration/SocketPoolConfiguration.cs
index 0e72845c..05f5c6cc 100644
--- a/Enyim.Caching/Configuration/SocketPoolConfiguration.cs
+++ b/Enyim.Caching/Configuration/SocketPoolConfiguration.cs
@@ -10,6 +10,7 @@ public class SocketPoolConfiguration : ISocketPoolConfiguration
{
private int minPoolSize = 5;
private int maxPoolSize = 100;
+ private bool useSslStream = false;
private TimeSpan connectionTimeout = new TimeSpan(0, 0, 10);
private TimeSpan receiveTimeout = new TimeSpan(0, 0, 10);
private TimeSpan deadTimeout = new TimeSpan(0, 0, 10);
diff --git a/Enyim.Caching/Enyim.Caching.csproj b/Enyim.Caching/Enyim.Caching.csproj
index cb2c1e1f..47ef98e7 100755
--- a/Enyim.Caching/Enyim.Caching.csproj
+++ b/Enyim.Caching/Enyim.Caching.csproj
@@ -3,7 +3,7 @@
EnyimMemcachedCore is a Memcached client library for .NET Core. Usage: Add services.AddEnyimMemcached(...) and app.UseEnyimMemcached() in Startup. Add IMemcachedClient into constructor.
cnblogs.com
- netstandard2.0;netstandard2.1;net5.0
+ netstandard2.0;netstandard2.1;net6.0
true
EnyimMemcachedCore
EnyimMemcachedCore
@@ -16,11 +16,11 @@
-
-
-
-
-
+
+
+
+
+
diff --git a/Enyim.Caching/Memcached/DefaultServerPool.cs b/Enyim.Caching/Memcached/DefaultServerPool.cs
index 0dac96ff..2eb90c18 100644
--- a/Enyim.Caching/Memcached/DefaultServerPool.cs
+++ b/Enyim.Caching/Memcached/DefaultServerPool.cs
@@ -50,7 +50,7 @@ public DefaultServerPool(
protected virtual IMemcachedNode CreateNode(EndPoint endpoint)
{
- return new MemcachedNode(endpoint, this.configuration.SocketPool, _logger);
+ return new MemcachedNode(endpoint, this.configuration.SocketPool, _logger, this.configuration.UseSslStream);
}
private void rezCallback(object state)
diff --git a/Enyim.Caching/Memcached/MemcachedNode.cs b/Enyim.Caching/Memcached/MemcachedNode.cs
index 84c5201d..c54d9166 100755
--- a/Enyim.Caching/Memcached/MemcachedNode.cs
+++ b/Enyim.Caching/Memcached/MemcachedNode.cs
@@ -35,13 +35,16 @@ public class MemcachedNode : IMemcachedNode
private bool isInitialized = false;
private SemaphoreSlim poolInitSemaphore = new SemaphoreSlim(1, 1);
private readonly TimeSpan _initPoolTimeout;
+ private bool _useSslStream;
public MemcachedNode(
EndPoint endpoint,
ISocketPoolConfiguration socketPoolConfig,
- ILogger logger)
+ ILogger logger,
+ bool useSslStream)
{
_endPoint = endpoint;
+ _useSslStream = useSslStream;
EndPointString = endpoint?.ToString().Replace("Unspecified/", string.Empty);
_config = socketPoolConfig;
@@ -800,7 +803,7 @@ protected internal virtual PooledSocket CreateSocket()
{
try
{
- var ps = new PooledSocket(_endPoint, _config.ConnectionTimeout, _config.ReceiveTimeout, _logger);
+ var ps = new PooledSocket(_endPoint, _config.ConnectionTimeout, _config.ReceiveTimeout, _logger, _useSslStream);
ps.Connect();
return ps;
}
@@ -816,7 +819,7 @@ protected internal virtual async Task CreateSocketAsync()
{
try
{
- var ps = new PooledSocket(_endPoint, _config.ConnectionTimeout, _config.ReceiveTimeout, _logger);
+ var ps = new PooledSocket(_endPoint, _config.ConnectionTimeout, _config.ReceiveTimeout, _logger, _useSslStream);
await ps.ConnectAsync();
return ps;
}
diff --git a/Enyim.Caching/Memcached/PooledSocket.cs b/Enyim.Caching/Memcached/PooledSocket.cs
index f8df8747..ec98791a 100755
--- a/Enyim.Caching/Memcached/PooledSocket.cs
+++ b/Enyim.Caching/Memcached/PooledSocket.cs
@@ -4,6 +4,7 @@
using System.IO;
using System.Linq;
using System.Net;
+using System.Net.Security;
using System.Net.Sockets;
using System.Text;
using System.Threading;
@@ -18,16 +19,19 @@ public partial class PooledSocket : IDisposable
private readonly ILogger _logger;
private bool _isAlive;
+ private bool _useSslStream;
private Socket _socket;
private readonly EndPoint _endpoint;
private readonly int _connectionTimeout;
private NetworkStream _inputStream;
+ private SslStream _sslStream;
- public PooledSocket(EndPoint endpoint, TimeSpan connectionTimeout, TimeSpan receiveTimeout, ILogger logger)
+ public PooledSocket(EndPoint endpoint, TimeSpan connectionTimeout, TimeSpan receiveTimeout, ILogger logger, bool useSslStream)
{
_logger = logger;
_isAlive = true;
+ _useSslStream = useSslStream;
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
@@ -90,7 +94,15 @@ void Cancel()
if (success)
{
- _inputStream = new NetworkStream(_socket);
+ if (_useSslStream)
+ {
+ _sslStream = new SslStream(new NetworkStream(_socket));
+ _sslStream.AuthenticateAsClient(((DnsEndPoint)_endpoint).Host);
+ }
+ else
+ {
+ _inputStream = new NetworkStream(_socket);
+ }
}
else
{
@@ -141,7 +153,15 @@ public async Task ConnectAsync()
if (success)
{
- _inputStream = new NetworkStream(_socket);
+ if (_useSslStream)
+ {
+ _sslStream = new SslStream(new NetworkStream(_socket));
+ await _sslStream.AuthenticateAsClientAsync(((DnsEndPoint)_endpoint).Host);
+ }
+ else
+ {
+ _inputStream = new NetworkStream(_socket);
+ }
}
else
{
@@ -251,7 +271,13 @@ protected void Dispose(bool disposing)
_inputStream.Dispose();
}
+ if (_sslStream != null)
+ {
+ _sslStream.Dispose();
+ }
+
_inputStream = null;
+ _sslStream = null;
_socket = null;
this.CleanupCallback = null;
}
@@ -290,7 +316,7 @@ public int ReadByte()
try
{
- return _inputStream.ReadByte();
+ return (_useSslStream ? _sslStream.ReadByte() : _inputStream.ReadByte());
}
catch (Exception ex)
{
@@ -309,7 +335,7 @@ public int ReadByteAsync()
try
{
- return _inputStream.ReadByte();
+ return (_useSslStream ? _sslStream.ReadByte() : _inputStream.ReadByte());
}
catch (Exception ex)
{
@@ -332,7 +358,7 @@ public async Task ReadAsync(byte[] buffer, int offset, int count)
{
try
{
- int currentRead = await _inputStream.ReadAsync(buffer, offset, shouldRead);
+ int currentRead = (_useSslStream ? await _sslStream.ReadAsync(buffer, offset, shouldRead) : await _inputStream.ReadAsync(buffer, offset, shouldRead));
if (currentRead == count)
break;
if (currentRead < 1)
@@ -372,7 +398,7 @@ public void Read(byte[] buffer, int offset, int count)
{
try
{
- int currentRead = _inputStream.Read(buffer, offset, shouldRead);
+ int currentRead = (_useSslStream ? _sslStream.Read(buffer, offset, shouldRead) : _inputStream.Read(buffer, offset, shouldRead));
if (currentRead == count)
break;
if (currentRead < 1)
@@ -397,15 +423,34 @@ public void Write(byte[] data, int offset, int length)
{
this.CheckDisposed();
- SocketError status;
+ if (_useSslStream)
+ {
+ try
+ {
+ _sslStream.Write(data, offset, length);
+ _sslStream.Flush();
+ }
+ catch (Exception ex)
+ {
+ if (ex is IOException || ex is SocketException)
+ {
+ _isAlive = false;
+ }
+ throw;
+ }
+ }
+ else
+ {
+ SocketError status;
- _socket.Send(data, offset, length, SocketFlags.None, out status);
+ _socket.Send(data, offset, length, SocketFlags.None, out status);
- if (status != SocketError.Success)
- {
- _isAlive = false;
+ if (status != SocketError.Success)
+ {
+ _isAlive = false;
- ThrowHelper.ThrowSocketWriteError(_endpoint, status);
+ ThrowHelper.ThrowSocketWriteError(_endpoint, status);
+ }
}
}
@@ -417,11 +462,22 @@ public void Write(IList> buffers)
try
{
- _socket.Send(buffers, SocketFlags.None, out status);
- if (status != SocketError.Success)
+ if (_useSslStream)
{
- _isAlive = false;
- ThrowHelper.ThrowSocketWriteError(_endpoint, status);
+ foreach (var buf in buffers)
+ {
+ _sslStream.Write(buf.Array);
+ }
+ _sslStream.Flush();
+ }
+ else
+ {
+ _socket.Send(buffers, SocketFlags.None, out status);
+ if (status != SocketError.Success)
+ {
+ _isAlive = false;
+ ThrowHelper.ThrowSocketWriteError(_endpoint, status);
+ }
}
}
catch (Exception ex)
@@ -441,12 +497,23 @@ public async Task WriteAsync(IList> buffers)
try
{
- var bytesTransferred = await _socket.SendAsync(buffers, SocketFlags.None);
- if (bytesTransferred <= 0)
+ if (_useSslStream)
{
- _isAlive = false;
- _logger.LogError($"Failed to {nameof(PooledSocket.WriteAsync)}. bytesTransferred: {bytesTransferred}");
- ThrowHelper.ThrowSocketWriteError(_endpoint);
+ foreach (var buf in buffers)
+ {
+ await _sslStream.WriteAsync(buf.Array,0,buf.Count);
+ }
+ await _sslStream.FlushAsync();
+ }
+ else
+ {
+ var bytesTransferred = await _socket.SendAsync(buffers, SocketFlags.None);
+ if (bytesTransferred <= 0)
+ {
+ _isAlive = false;
+ _logger.LogError($"Failed to {nameof(PooledSocket.WriteAsync)}. bytesTransferred: {bytesTransferred}");
+ ThrowHelper.ThrowSocketWriteError(_endpoint);
+ }
}
}
catch (Exception ex)
diff --git a/Enyim.Caching/Memcached/Protocol/Binary/BinaryNode.cs b/Enyim.Caching/Memcached/Protocol/Binary/BinaryNode.cs
index 10356fb4..d7191b16 100644
--- a/Enyim.Caching/Memcached/Protocol/Binary/BinaryNode.cs
+++ b/Enyim.Caching/Memcached/Protocol/Binary/BinaryNode.cs
@@ -23,8 +23,9 @@ public BinaryNode(
EndPoint endpoint,
ISocketPoolConfiguration config,
ISaslAuthenticationProvider authenticationProvider,
- ILogger logger)
- : base(endpoint, config, logger)
+ ILogger logger,
+ bool useSslStream)
+ : base(endpoint, config, logger, useSslStream)
{
this.authenticationProvider = authenticationProvider;
_logger = logger;
diff --git a/Enyim.Caching/Memcached/Protocol/Binary/BinaryPool.cs b/Enyim.Caching/Memcached/Protocol/Binary/BinaryPool.cs
index 8f4e1763..d134eff3 100644
--- a/Enyim.Caching/Memcached/Protocol/Binary/BinaryPool.cs
+++ b/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, this.configuration.SocketPool, this.authenticationProvider, _logger);
+ return new BinaryNode(endpoint, this.configuration.SocketPool, this.authenticationProvider, _logger, this.configuration.UseSslStream);
}
private static ISaslAuthenticationProvider GetProvider(IMemcachedClientConfiguration configuration)