Пример #1
0
        private void ProcessIntegratedSecurityAuthentication(IAsyncResult asyncResult)
        {
            ConnectState connectState = null;
            ReceiveState receiveState = null;
            SendState sendState = null;

            try
            {
                // Get the connect state from the async result
                connectState = (ConnectState)asyncResult.AsyncState;

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

                try
                {
                    // Complete the operation to authenticate with the server
                    connectState.NegotiateStream.EndAuthenticateAsClient(asyncResult);
                }
                catch (InvalidCredentialException)
                {
                    if (!m_ignoreInvalidCredentials)
                        throw;
                }

                // 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
                // and begin receiving data.
                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 SslStream
                // object, so the SocketAsyncEventArgs is no longer needed
                connectState.ConnectArgs.Dispose();
            }
            catch (SocketException ex)
            {
                // Log exception during connection attempt
                OnConnectionException(ex);

                // If connectState is null, we cannot proceed
                if ((object)connectState == null)
                    return;

                // 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
                string errorMessage = $"Unable to authenticate connection to server: {ex.Message}";
                OnConnectionException(new Exception(errorMessage, ex));

                // Terminate the connection
                if ((object)connectState != null)
                    TerminateConnection(connectState.Token);
            }
            finally
            {
                if ((object)connectState != null)
                {
                    // If the operation was cancelled during execution,
                    // make sure to dispose of erroneously allocated resources;
                    // otherwise, dispose of the NegotiateStream which is only used for authentication
                    if (connectState.Token.Cancelled)
                    {
                        connectState.Dispose();
                    }
                    else
                    {
                        connectState.NetworkStream.Dispose();
                        connectState.NegotiateStream.Dispose();
                    }
                }

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

                if ((object)sendState != null && sendState.Token.Cancelled)
                    sendState.Dispose();
            }
        }
Пример #2
0
        /// <summary>
        /// Callback method for asynchronous receive operation of payload data in "payload-aware" mode.
        /// </summary>
        private void ProcessReceivePayloadAware(ReceiveState receiveState)
        {
            try
            {
                // Quit if this receive loop has been cancelled
                if (receiveState.Token.Cancelled)
                    return;

                // Determine if the server disconnected gracefully
                if (receiveState.ReceiveArgs.SocketError != SocketError.Success)
                    throw new SocketException((int)receiveState.ReceiveArgs.SocketError);

                if (receiveState.ReceiveArgs.BytesTransferred == 0)
                    throw new SocketException((int)SocketError.Disconnecting);

                // Update statistics and bytes received.
                UpdateBytesReceived(receiveState.ReceiveArgs.BytesTransferred);
                receiveState.Offset += receiveState.ReceiveArgs.BytesTransferred;

                if (receiveState.PayloadLength < 0)
                {
                    // If we haven't parsed the length of the payload yet, attempt to parse it
                    receiveState.PayloadLength = Payload.ExtractLength(receiveState.Buffer, receiveState.Offset, m_payloadMarker);

                    if (receiveState.PayloadLength > 0)
                    {
                        receiveState.Offset = 0;

                        if (receiveState.Buffer.Length < receiveState.PayloadLength)
                            receiveState.Buffer = new byte[receiveState.PayloadLength];
                    }
                }
                else if (receiveState.Offset == receiveState.PayloadLength)
                {
                    // We've received the entire payload so notify the user
                    OnReceiveDataComplete(receiveState.Buffer, receiveState.PayloadLength);

                    // Reset payload length
                    receiveState.Offset = 0;
                    receiveState.PayloadLength = -1;
                }

                // Continue asynchronous loop
                ReceivePayloadAwareAsync(receiveState);
            }
            catch (ObjectDisposedException)
            {
                // Make sure connection is terminated when client is disposed.
                TerminateConnection(receiveState.Token);
            }
            catch (SocketException ex)
            {
                // Log exception during receive operation
                OnReceiveDataException(ex);

                // Terminate connection when socket exception is encountered
                TerminateConnection(receiveState.Token);
            }
            catch (Exception ex)
            {
                try
                {
                    // For any other exception, notify and resume
                    OnReceiveDataException(ex);
                    ReceivePayloadAwareAsync(receiveState);
                }
                catch
                {
                    // Terminate connection if resume fails
                    TerminateConnection(receiveState.Token);
                }
            }
            finally
            {
                // If the operation was cancelled during execution,
                // make sure to dispose of allocated resources
                if ((object)receiveState != null && receiveState.Token.Cancelled)
                    receiveState.Dispose();
            }
        }