예제 #1
0
        /// <summary>
        /// Connects the <see cref="TcpClient"/> to the server asynchronously.
        /// </summary>
        /// <exception cref="InvalidOperationException">Attempt is made to connect the <see cref="TcpClient"/> when it is not disconnected.</exception>
        /// <returns><see cref="WaitHandle"/> for the asynchronous operation.</returns>
        public override WaitHandle ConnectAsync()
        {
            ConnectState connectState = null;

            Match endpoint;
            string integratedSecuritySetting;

            if (CurrentState == ClientState.Disconnected && !m_disposed)
            {
                try
                {
                    // If we do not already have a wait handle to use
                    // for connections, get one from the base class
                    if ((object)m_connectWaitHandle == null)
                        m_connectWaitHandle = (ManualResetEvent)base.ConnectAsync();

                    // Create state object for the asynchronous connection loop
                    connectState = new ConnectState();

                    // Store connectState in m_connectState so that calls to Disconnect
                    // and Dispose can dispose resources and cancel asynchronous loops
                    m_connectState = connectState;

                    OnConnectionAttempt();
                    m_connectWaitHandle.Reset();

                    // Overwrite config file if integrated security exists in connection string
                    if (m_connectData.TryGetValue("integratedSecurity", out integratedSecuritySetting))
                        m_integratedSecurity = integratedSecuritySetting.ParseBoolean();
#if MONO
                    // Force integrated security to be False under Mono since it's not supported
                    m_integratedSecurity = false;
#endif

                    // Initialize state object for the asynchronous connection loop
                    endpoint = Regex.Match(m_connectData["server"], Transport.EndpointFormatRegex);

                    connectState.ConnectArgs.RemoteEndPoint = Transport.CreateEndPoint(endpoint.Groups["host"].Value, int.Parse(endpoint.Groups["port"].Value), m_ipStack);
                    connectState.ConnectArgs.SocketFlags = SocketFlags.None;
                    connectState.ConnectArgs.UserToken = connectState;
                    connectState.ConnectArgs.Completed += (sender, args) => ProcessConnect((ConnectState)args.UserToken);

                    // Create client socket
                    connectState.Socket = Transport.CreateSocket(m_connectData["interface"], 0, ProtocolType.Tcp, m_ipStack, m_allowDualStackSocket);

                    // Initiate the asynchronous connection loop
                    ConnectAsync(connectState);
                }
                catch (Exception ex)
                {
                    // Log exception during connection attempt
                    OnConnectionException(ex);

                    // Terminate the connection
                    if ((object)connectState != null)
                        TerminateConnection(connectState.Token);

                    // Ensure that the wait handle is set so that operations waiting
                    // for completion of the asynchronous connection loop can continue
                    if ((object)m_connectWaitHandle != null)
                        m_connectWaitHandle.Set();
                }
                finally
                {
                    // If the operation was cancelled during execution,
                    // make sure to dispose of erroneously allocated resources
                    if ((object)connectState != null && connectState.Token.Cancelled)
                        connectState.Dispose();
                }
            }

            // Return the wait handle that signals completion
            // of the asynchronous connection loop
            return m_connectWaitHandle;
        }
예제 #2
0
        /// <summary>
        /// Callback method for asynchronous connect operation.
        /// </summary>
        private void ProcessConnect(ConnectState connectState)
        {
            ReceiveState receiveState = null;
            SendState sendState = null;

            try
            {
                // Quit if this connection loop has been cancelled
                if (connectState.Token.Cancelled)
                    return;

                // Increment the number of connection attempts that
                // have occurred in this asynchronous connection loop
                connectState.ConnectionAttempts++;

                // Check the SocketAsyncEventArgs for errors during the asynchronous connection attempt
                if (connectState.ConnectArgs.SocketError != SocketError.Success)
                    throw new SocketException((int)connectState.ConnectArgs.SocketError);

                // Set the size of the buffer used by the socket to store incoming data from the server
                connectState.Socket.ReceiveBufferSize = ReceiveBufferSize;

                if (m_integratedSecurity)
                {
#if !MONO
                    // Check the state of cancellation one more time before
                    // proceeding to the next step of the connection loop
                    if (connectState.Token.Cancelled)
                        return;

                    // Create the SslStream object used to perform
                    // send and receive operations on the socket
                    connectState.NetworkStream = new NetworkStream(connectState.Socket, false);
                    connectState.NegotiateStream = new NegotiateStream(connectState.NetworkStream, true);
                    connectState.NegotiateStream.BeginAuthenticateAsClient(m_networkCredential ?? (NetworkCredential)CredentialCache.DefaultCredentials, string.Empty, ProcessIntegratedSecurityAuthentication, connectState);
#endif
                }
                else
                {
                    // Initialize the SocketAsyncEventArgs for receive operations
                    connectState.ReceiveArgs = FastObjectFactory<SocketAsyncEventArgs>.CreateObjectFunction();
                    connectState.ReceiveArgs.SetBuffer(new byte[ReceiveBufferSize], 0, ReceiveBufferSize);

                    if (m_payloadAware)
                        connectState.ReceiveArgs.Completed += (sender, args) => ProcessReceivePayloadAware((ReceiveState)args.UserToken);
                    else
                        connectState.ReceiveArgs.Completed += (sender, args) => ProcessReceivePayloadUnaware((ReceiveState)args.UserToken);

                    // Initialize the SocketAsyncEventArgs for send operations
                    connectState.SendArgs = FastObjectFactory<SocketAsyncEventArgs>.CreateObjectFunction();
                    connectState.SendArgs.SetBuffer(new byte[SendBufferSize], 0, SendBufferSize);
                    connectState.SendArgs.Completed += (sender, args) => ProcessSend((SendState)args.UserToken);

                    // Initialize state object for the asynchronous send loop
                    sendState = new SendState();
                    sendState.Token = connectState.Token;
                    sendState.Socket = connectState.Socket;
                    sendState.ReceiveArgs = connectState.ReceiveArgs;
                    sendState.SendArgs = connectState.SendArgs;
                    sendState.SendArgs.UserToken = sendState;

                    // Store sendState in m_sendState so that calls to Disconnect
                    // and Dispose can dispose resources and cancel asynchronous loops
                    m_sendState = sendState;

                    // Check the state of cancellation one more time before
                    // proceeding to the next step of the connection loop
                    if (connectState.Token.Cancelled)
                        return;

                    // Notify of established connection
                    m_connectWaitHandle.Set();
                    OnConnectionEstablished();

                    // Initialize state object for the asynchronous receive loop
                    receiveState = new ReceiveState();
                    receiveState.Token = connectState.Token;
                    receiveState.Socket = connectState.Socket;
                    receiveState.Buffer = connectState.ReceiveArgs.Buffer;
                    receiveState.ReceiveArgs = connectState.ReceiveArgs;
                    receiveState.ReceiveArgs.UserToken = receiveState;
                    receiveState.SendArgs = connectState.SendArgs;

                    // Store receiveState in m_receiveState so that calls to Disconnect
                    // and Dispose can dispose resources and cancel asynchronous loops
                    m_receiveState = receiveState;

                    // Start receiving data
                    if (m_payloadAware)
                        ReceivePayloadAwareAsync(receiveState);
                    else
                        ReceivePayloadUnawareAsync(receiveState);

                    // Further socket interactions are handled through the ReceiveArgs
                    // and SendArgs objects, so the ConnectArgs is no longer needed
                    connectState.ConnectArgs.Dispose();
                }
            }
            catch (SocketException ex)
            {
                // Log exception during connection attempt
                OnConnectionException(ex);

                // If the connection is refused by the server,
                // keep trying until we reach our maximum connection attempts
                if (ex.SocketErrorCode == SocketError.ConnectionRefused &&
                    (MaxConnectionAttempts == -1 || connectState.ConnectionAttempts < MaxConnectionAttempts))
                {
                    // Server is unavailable, so keep retrying connection to the server.
                    try
                    {
                        ConnectAsync(connectState);
                    }
                    catch
                    {
                        TerminateConnection(connectState.Token);
                    }
                }
                else
                {
                    // For any other reason, clean-up as if the client was disconnected.
                    TerminateConnection(connectState.Token);
                }
            }
            catch (Exception ex)
            {
                // Log exception during connection attempt
                OnConnectionException(ex);

                // Terminate the connection
                TerminateConnection(connectState.Token);
            }
            finally
            {
                // If the operation was cancelled during execution,
                // make sure to dispose of erroneously allocated resources
                if ((object)connectState != null && connectState.Token.Cancelled)
                    connectState.Dispose();

                if ((object)receiveState != null && receiveState.Token.Cancelled)
                    receiveState.Dispose();

                if ((object)sendState != null && sendState.Token.Cancelled)
                    sendState.Dispose();
            }
        }
예제 #3
0
파일: TlsClient.cs 프로젝트: rmc00/gsf
        private void ProcessConnect(ConnectState connectState)
        {
            Match endpoint;

            try
            {
                // Quit if this connection loop has been cancelled
                if (connectState.Token.Cancelled)
                    return;

                // Increment the number of connection attempts that
                // have occurred in this asynchronous connection loop
                connectState.ConnectionAttempts++;

                // Check the SocketAsyncEventArgs for errors during the asynchronous connection attempt
                if (connectState.ConnectArgs.SocketError != SocketError.Success)
                    throw new SocketException((int)connectState.ConnectArgs.SocketError);

                // Set the size of the buffer used by the socket to store incoming data from the server
                connectState.Socket.ReceiveBufferSize = ReceiveBufferSize;

                // Create the SslStream object used to perform
                // send and receive operations on the socket
                connectState.NetworkStream = new NetworkStream(connectState.Socket, true);
                connectState.SslStream = new SslStream(connectState.NetworkStream, false, m_remoteCertificateValidationCallback ?? CertificateChecker.ValidateRemoteCertificate, m_localCertificateSelectionCallback);

                // Load trusted certificates from
                // the trusted certificates directory
                LoadTrustedCertificates();

                // Begin authentication with the TlsServer
                endpoint = Regex.Match(m_connectData["server"], Transport.EndpointFormatRegex);

                if (!connectState.Token.Cancelled)
                    connectState.SslStream.BeginAuthenticateAsClient(endpoint.Groups["host"].Value, m_clientCertificates, m_enabledSslProtocols, m_checkCertificateRevocation, ProcessTlsAuthentication, connectState);
            }
            catch (SocketException ex)
            {
                // Log exception during connection attempt
                OnConnectionException(ex);

                // If the connection is refused by the server,
                // keep trying until we reach our maximum connection attempts
                if (ex.SocketErrorCode == SocketError.ConnectionRefused &&
                    (MaxConnectionAttempts == -1 || connectState.ConnectionAttempts < MaxConnectionAttempts))
                {
                    try
                    {
                        ConnectAsync(connectState);
                    }
                    catch
                    {
                        TerminateConnection(connectState.Token);
                    }
                }
                else
                {
                    // For any other socket exception,
                    // terminate the connection
                    TerminateConnection(connectState.Token);
                }
            }
            catch (Exception ex)
            {
                // Log exception during connection attempt
                OnConnectionException(ex);

                // Terminate the connection
                TerminateConnection(connectState.Token);
            }
            finally
            {
                // If the operation was cancelled during execution,
                // make sure to dispose of erroneously allocated resources
                if (connectState.Token.Cancelled)
                    connectState.Dispose();
            }
        }