/// <summary>
        /// decoding the data with security provider
        /// </summary>
        /// <param name="data">
        /// a bytes data that contains the data to be decoded with security provider.
        /// </param>
        /// <returns>
        /// a bytes data that contains the decoded data.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// thrown when data is null.
        /// </exception>
        public override byte[] Decode(byte[] data)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }

            // if the SASL security provider is not ready, do not decode.
            if (this.securityContext.NeedContinueProcessing ||
                !this.UsingMessageSecurity)
            {
                this.consumedData = false;

                return(data);
            }

            // store the data to buffer.
            this.receivedBuffer.AddReceivedData(data);
            this.consumedData   = true;
            this.consumedLength = data.Length;

            // SaslHeader is used to decode the whole packet from buffer.
            AdtsLdapSaslSecurityHeader saslHeader = new AdtsLdapSaslSecurityHeader();

            // unmarshal the sasl header
            saslHeader.FromBytes(this.receivedBuffer.Peek(AdtsLdapSaslSecurityHeader.SIZE_OF_LENGTH));

            // if the sasl header is not valid, maybe data is not enough, consumed the received data and return.
            if (!saslHeader.IsValid(this.receivedBuffer.Length))
            {
                return(new byte[0]);
            }

            // update the signature length if needed
            if (this.signatureLength < 0)
            {
                this.signatureLength = (int)this.securityContext.ContextSizes.MaxSignatureSize;
            }

            // get a copy of data.
            byte[] bufferData = this.receivedBuffer.Data;

            // get the signature.
            byte[] signature = ArrayUtility.SubArray <byte>(
                bufferData, AdtsLdapSaslSecurityHeader.SIZE_OF_LENGTH, this.signatureLength);

            // get the encrypted message
            byte[] encryptedMessage = ArrayUtility.SubArray <byte>(
                bufferData, AdtsLdapSaslSecurityHeader.SIZE_OF_LENGTH + this.signatureLength,
                saslHeader.Length - this.signatureLength);

            // if the sasl header is valid, decrypt it with security provider.
            byte[] decryptedMessage = this.securityContext.Decrypt(encryptedMessage, signature);

            // remove the sasl header bytes data from the buffer.
            this.receivedBuffer.Remove(AdtsLdapSaslSecurityHeader.SIZE_OF_LENGTH + saslHeader.Length);

            return(decryptedMessage);
        }
        /// <summary>
        /// decoding the data with security provider
        /// </summary>
        /// <param name="data">
        /// a bytes data that contains the data to be decoded with security provider.
        /// </param>
        /// <returns>
        /// a bytes data that contains the decoded data.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// thrown when data is null.
        /// </exception>
        public override byte[] Decode(byte[] data)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }

            // if the SASL security provider is not ready, do not decode.
            if (this.securityContext.NeedContinueProcessing
                || !this.UsingMessageSecurity)
            {
                this.consumedData = false;

                return data;
            }

            // store the data to buffer.
            this.receivedBuffer.AddReceivedData(data);
            this.consumedData = true;
            this.consumedLength = data.Length;

            // SaslHeader is used to decode the whole packet from buffer.
            AdtsLdapSaslSecurityHeader saslHeader = new AdtsLdapSaslSecurityHeader();

            // unmarshal the sasl header
            saslHeader.FromBytes(this.receivedBuffer.Peek(AdtsLdapSaslSecurityHeader.SIZE_OF_LENGTH));

            // if the sasl header is not valid, maybe data is not enough, consumed the received data and return.
            if (!saslHeader.IsValid(this.receivedBuffer.Length))
            {
                return new byte[0];
            }

            // update the signature length if needed
            if (this.signatureLength < 0)
            {
                this.signatureLength = (int)this.securityContext.ContextSizes.MaxSignatureSize;
            }

            // get a copy of data.
            byte[] bufferData = this.receivedBuffer.Data;

            // get the signature.
            byte[] signature = ArrayUtility.SubArray<byte>(
                bufferData, AdtsLdapSaslSecurityHeader.SIZE_OF_LENGTH, this.signatureLength);

            // get the encrypted message
            byte[] encryptedMessage = ArrayUtility.SubArray<byte>(
                bufferData, AdtsLdapSaslSecurityHeader.SIZE_OF_LENGTH + this.signatureLength,
                saslHeader.Length - this.signatureLength);

            // if the sasl header is valid, decrypt it with security provider.
            byte[] decryptedMessage = this.securityContext.Decrypt(encryptedMessage, signature);

            // remove the sasl header bytes data from the buffer.
            this.receivedBuffer.Remove(AdtsLdapSaslSecurityHeader.SIZE_OF_LENGTH + saslHeader.Length);

            return decryptedMessage;
        }