/// <exception cref="System.IO.IOException"></exception> public ClientConnection(ClientConnectionManager clientConnectionManager, ClientInvocationService invocationService, int id, Address address, ClientNetworkConfig clientNetworkConfig) { _clientConnectionManager = clientConnectionManager; _id = id; var isa = address.GetInetSocketAddress(); var socketOptions = clientNetworkConfig.GetSocketOptions(); var socketFactory = socketOptions.GetSocketFactory() ?? new DefaultSocketFactory(); _clientSocket = socketFactory.CreateSocket(); try { _clientSocket = new Socket(isa.AddressFamily, SocketType.Stream, ProtocolType.Tcp); _clientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true); var lingerOption = new LingerOption(true, 5); if (socketOptions.GetLingerSeconds() > 0) { lingerOption.LingerTime = socketOptions.GetLingerSeconds(); } _clientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, lingerOption); _clientSocket.NoDelay = socketOptions.IsTcpNoDelay(); _clientSocket.ReceiveTimeout = socketOptions.GetTimeout() > 0 ? socketOptions.GetTimeout() : -1; var bufferSize = socketOptions.GetBufferSize() * 1024; if (bufferSize < 0) { bufferSize = BufferSize; } _clientSocket.SendBufferSize = bufferSize; _clientSocket.ReceiveBufferSize = bufferSize; var connectionTimeout = clientNetworkConfig.GetConnectionTimeout() > -1 ? clientNetworkConfig.GetConnectionTimeout() : ConnectionTimeout; var socketResult = _clientSocket.BeginConnect(address.GetHost(), address.GetPort(), null, null); if (!socketResult.AsyncWaitHandle.WaitOne(connectionTimeout, true) || !_clientSocket.Connected) { // NOTE, MUST CLOSE THE SOCKET _clientSocket.Close(); throw new IOException("Failed to connect to " + address); } _sendBuffer = ByteBuffer.Allocate(BufferSize); _receiveBuffer = ByteBuffer.Allocate(BufferSize); _builder = new ClientMessageBuilder(invocationService.HandleClientMessage); var networkStream = new NetworkStream(_clientSocket, false); if (clientNetworkConfig.GetSSLConfig().IsEnabled()) { var sslStream = new SslStream(networkStream, false, (sender, certificate, chain, sslPolicyErrors) => RemoteCertificateValidationCallback(sender, certificate, chain, sslPolicyErrors, clientNetworkConfig), null); var certificateName = clientNetworkConfig.GetSSLConfig().GetCertificateName() ?? ""; sslStream.AuthenticateAsClient(certificateName); _stream = sslStream; } else { _stream = networkStream; } _live = new AtomicBoolean(true); } catch (Exception e) { _clientSocket.Close(); if (_stream != null) { _stream.Close(); } throw new IOException("Cannot connect! Socket error:" + e.Message); } }
private bool RemoteCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors, ClientNetworkConfig clientNetworkConfig) { if (sslPolicyErrors == SslPolicyErrors.None) { return true; } var validation = true; if (sslPolicyErrors.HasFlag(SslPolicyErrors.RemoteCertificateChainErrors)) { var isValidateChain = clientNetworkConfig.GetSSLConfig().IsValidateCertificateChain(); if (isValidateChain) { Logger.Warning("Certificate error:" + sslPolicyErrors); validation = false; } else { Logger.Info("SSL Configured to ignore Certificate chain validation. Ignoring:"); } foreach (var status in chain.ChainStatus) { Logger.Info("Certificate chain status:" + status.StatusInformation); } } if (sslPolicyErrors.HasFlag(SslPolicyErrors.RemoteCertificateNameMismatch)) { var isValidateName = clientNetworkConfig.GetSSLConfig().IsValidateCertificateName(); if (isValidateName) { Logger.Warning("Certificate error:" + sslPolicyErrors); validation = false; } else { Logger.Info("Certificate name mismatched but client is configured to ignore Certificate name validation."); } } if (sslPolicyErrors.HasFlag(SslPolicyErrors.RemoteCertificateNotAvailable)) { Logger.Warning("Certificate error:" + sslPolicyErrors); validation = false; } return validation; }