Ejemplo n.º 1
0
        /// <summary>
        /// Connects synchronously to the host and starts reading
        /// </summary>
        /// <exception cref="SocketException">Throws a SocketException when the connection could not be established with the host</exception>
        public Task <bool> Connect()
        {
            var tcs = TaskHelper.TaskCompletionSourceWithTimeout <bool>(
                Options.ConnectTimeoutMillis,
                () => new SocketException((int)SocketError.TimedOut));
            var socketConnectTask = tcs.Task;
            var eventArgs         = new SocketAsyncEventArgs
            {
                RemoteEndPoint = IPEndPoint
            };

            eventArgs.Completed += (sender, e) =>
            {
                if (e.SocketError != SocketError.Success)
                {
                    tcs.TrySetException(new SocketException((int)e.SocketError));
                    return;
                }
                tcs.TrySetResult(true);
                e.Dispose();
            };

            try
            {
                _socket.ConnectAsync(eventArgs);
            }
            catch (Exception ex)
            {
                return(TaskHelper.FromException <bool>(ex));
            }
            //Prepare read and write
            //There are 2 modes: using SocketAsyncEventArgs (most performant) and Stream mode with APM methods
            if (SSLOptions == null && !Options.UseStreamMode)
            {
                return(socketConnectTask.ContinueSync(_ =>
                {
                    _logger.Verbose("Socket connected, start reading using SocketEventArgs interface");
                    //using SocketAsyncEventArgs
                    _receiveSocketEvent = new SocketAsyncEventArgs();
                    _receiveSocketEvent.SetBuffer(_receiveBuffer, 0, _receiveBuffer.Length);
                    _receiveSocketEvent.Completed += OnReceiveCompleted;
                    _sendSocketEvent = new SocketAsyncEventArgs();
                    _sendSocketEvent.Completed += OnSendCompleted;
                    ReceiveAsync();
                    return true;
                }));
            }
            if (SSLOptions == null)
            {
                return(socketConnectTask.ContinueSync(_ =>
                {
                    _logger.Verbose("Socket connected, start reading using Stream interface");
                    //Stream mode: not the most performant but it is a choice
                    _socketStream = new NetworkStream(_socket);
                    ReceiveAsync();
                    return true;
                }));
            }
            return(socketConnectTask.Then(_ => ConnectSsl()));
        }
Ejemplo n.º 2
0
        private async Task <bool> ConnectSsl()
        {
            _logger.Verbose("Socket connected, starting SSL client authentication");
            //Stream mode: not the most performant but it has ssl support
            var targetHost = IPEndPoint.Address.ToString();
            //HostNameResolver is a sync operation but it can block
            //Use another thread
            Action resolveAction = () =>
            {
                try
                {
                    targetHost = SSLOptions.HostNameResolver(IPEndPoint.Address);
                }
                catch (Exception ex)
                {
                    _logger.Error(
                        string.Format(
                            "SSL connection: Can not resolve host name for address {0}. Using the IP address instead of the host name. This may cause RemoteCertificateNameMismatch error during Cassandra host authentication. Note that the Cassandra node SSL certificate's CN(Common Name) must match the Cassandra node hostname.",
                            targetHost), ex);
                }
            };
            await Task.Factory.StartNew(resolveAction).ConfigureAwait(false);

            _logger.Verbose("Starting SSL authentication");
            var sslStream = new SslStream(new NetworkStream(_socket), false, SSLOptions.RemoteCertValidationCallback, null);

            _socketStream = sslStream;
            // Use a timer to ensure that it does callback
            var tcs = TaskHelper.TaskCompletionSourceWithTimeout <bool>(
                Options.ConnectTimeoutMillis,
                () => new TimeoutException("The timeout period elapsed prior to completion of SSL authentication operation."));

            sslStream.AuthenticateAsClientAsync(targetHost,
                                                SSLOptions.CertificateCollection,
                                                SSLOptions.SslProtocol,
                                                SSLOptions.CheckCertificateRevocation)
            .ContinueWith(t =>
            {
                if (t.Exception != null)
                {
                    t.Exception.Handle(_ => true);
                    // ReSharper disable once AssignNullToNotNullAttribute
                    tcs.TrySetException(t.Exception.InnerException);
                    return;
                }
                tcs.TrySetResult(true);
            }, TaskContinuationOptions.ExecuteSynchronously)
            // Avoid awaiting as it may never yield
            .Forget();

            await tcs.Task.ConfigureAwait(false);

            _logger.Verbose("SSL authentication successful");
            ReceiveAsync();
            return(true);
        }
Ejemplo n.º 3
0
        private Task <bool> ConnectSsl()
        {
            _logger.Verbose("Socket connected, starting SSL client authentication");
            //Stream mode: not the most performant but it has ssl support
            var targetHost = IPEndPoint.Address.ToString();

            //HostNameResolver is a sync operation but it can block
            //Use another thread
            return(Task.Factory.StartNew(() =>
            {
                try
                {
                    targetHost = SSLOptions.HostNameResolver(IPEndPoint.Address);
                }
                catch (Exception ex)
                {
                    _logger.Error(String.Format("SSL connection: Can not resolve host name for address {0}. Using the IP address instead of the host name. This may cause RemoteCertificateNameMismatch error during Cassandra host authentication. Note that the Cassandra node SSL certificate's CN(Common Name) must match the Cassandra node hostname.", targetHost), ex);
                }
                return true;
            }).Then(_ =>
            {
                _logger.Verbose("Starting SSL authentication");
                var tcs = TaskHelper.TaskCompletionSourceWithTimeout <bool>(Options.ConnectTimeoutMillis,
                                                                            () => new TimeoutException("The timeout period elapsed prior to completion of SSL authentication operation."));
                var sslStream = new SslStream(new NetworkStream(_socket), false, SSLOptions.RemoteCertValidationCallback, null);
                _socketStream = sslStream;
                try
                {
                    sslStream.BeginAuthenticateAsClient(targetHost, SSLOptions.CertificateCollection, SSLOptions.SslProtocol,
                                                        SSLOptions.CheckCertificateRevocation,
                                                        sslAsyncResult =>
                    {
                        try
                        {
                            sslStream.EndAuthenticateAsClient(sslAsyncResult);
                            tcs.TrySetResult(true);
                        }
                        catch (Exception ex)
                        {
                            tcs.TrySetException(ex);
                        }
                    }, null);
                }
                catch (Exception ex)
                {
                    tcs.TrySetException(ex);
                }
                return tcs.Task;
            }).ContinueSync(_ =>
            {
                _logger.Verbose("SSL authentication successful");
                ReceiveAsync();
                return true;
            }));
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Connects asynchronously to the host and starts reading
        /// </summary>
        /// <exception cref="SocketException">Throws a SocketException when the connection could not be established with the host</exception>
        public async Task <bool> Connect()
        {
            var tcs = TaskHelper.TaskCompletionSourceWithTimeout <bool>(
                Options.ConnectTimeoutMillis,
                () => new SocketException((int)SocketError.TimedOut));
            var socketConnectTask = tcs.Task;
            var eventArgs         = new SocketAsyncEventArgs
            {
                RemoteEndPoint = IPEndPoint
            };

            eventArgs.Completed += (sender, e) =>
            {
                if (e.SocketError != SocketError.Success)
                {
                    tcs.TrySetException(new SocketException((int)e.SocketError));
                    return;
                }
                tcs.TrySetResult(true);
                e.Dispose();
            };

            var willCompleteAsync = _socket.ConnectAsync(eventArgs);

            if (!willCompleteAsync)
            {
                // Make the task complete asynchronously
                Task.Run(() => tcs.TrySetResult(true)).Forget();
            }
            try
            {
                await socketConnectTask.ConfigureAwait(false);
            }
            finally
            {
                eventArgs.Dispose();
            }
            if (SSLOptions != null)
            {
                return(await ConnectSsl().ConfigureAwait(false));
            }
            // Prepare read and write
            // There are 2 modes: using SocketAsyncEventArgs (most performant) and Stream mode
            if (Options.UseStreamMode)
            {
                _logger.Verbose("Socket connected, start reading using Stream interface");
                //Stream mode: not the most performant but it is a choice
                _socketStream = new NetworkStream(_socket);
                ReceiveAsync();
                return(true);
            }
            _logger.Verbose("Socket connected, start reading using SocketEventArgs interface");
            //using SocketAsyncEventArgs
            _receiveSocketEvent = new SocketAsyncEventArgs();
            _receiveSocketEvent.SetBuffer(_receiveBuffer, 0, _receiveBuffer.Length);
            _receiveSocketEvent.Completed += OnReceiveCompleted;
            _sendSocketEvent            = new SocketAsyncEventArgs();
            _sendSocketEvent.Completed += OnSendCompleted;
            ReceiveAsync();
            return(true);
        }