An exception thrown when an error occurs while reading a message.
Inheritance: System.Exception
Ejemplo n.º 1
0
        /// <summary>
        /// Downloads the message payload referred to by the specified <see cref="PayloadReference"/>.
        /// </summary>
        /// <param name="notification">The payload reference.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>The task representing the asynchronous operation.</returns>
        public virtual async Task <Payload> DownloadPayloadAsync(PayloadReference notification, CancellationToken cancellationToken = default(CancellationToken))
        {
            Requires.NotNull(notification, "notification");

            byte[]    messageBuffer = null;
            const int MaxAttempts   = 2;
            int       retry;
            Exception exceptionLeadingToRetry = null;

            for (retry = 0; retry < MaxAttempts; retry++)
            {
                exceptionLeadingToRetry = null;
                try
                {
                    var responseMessage = await this.HttpClient.GetAsync(notification.Location, cancellationToken).ConfigureAwait(false);

                    messageBuffer = await responseMessage.Content.ReadAsByteArrayAsync().ConfigureAwait(false);

                    // Calculate hash of downloaded message and check that it matches the referenced message hash.
                    if (!this.CryptoServices.IsHashMatchWithTolerantHashAlgorithm(messageBuffer, notification.Hash, CryptoProviderExtensions.ParseHashAlgorithmName(notification.HashAlgorithmName)))
                    {
                        // Sometimes when the hash mismatches, it's because the download was truncated
                        // (from switching out the application and then switching back, for example).
                        // Check for that before throwing.
                        if (responseMessage.Content.Headers.ContentLength.HasValue && responseMessage.Content.Headers.ContentLength.Value > messageBuffer.Length)
                        {
                            // It looks like the message was truncated. Retry.
                            exceptionLeadingToRetry = new InvalidMessageException();
                            continue;
                        }

                        throw new InvalidMessageException();
                    }

                    // Stop retrying. We got something that worked!
                    break;
                }
                catch (HttpRequestException ex)
                {
                    exceptionLeadingToRetry = ex;
                    continue;
                }
            }

            if (exceptionLeadingToRetry != null)
            {
                if (exceptionLeadingToRetry.StackTrace != null)
                {
                    ExceptionDispatchInfo.Capture(exceptionLeadingToRetry).Throw();
                }
                else
                {
                    throw exceptionLeadingToRetry;
                }
            }

            var encryptionVariables = new SymmetricEncryptionVariables(notification.Key, notification.IV);

            var cipherStream    = new MemoryStream(messageBuffer);
            var plainTextStream = new MemoryStream();

            await this.CryptoServices.DecryptAsync(cipherStream, plainTextStream, encryptionVariables, cancellationToken).ConfigureAwait(false);

            plainTextStream.Position = 0;
            var plainTextReader = new BinaryReader(plainTextStream);
            var message         = Utilities.DeserializeDataContract <Payload>(plainTextReader);

            message.PayloadReferenceUri = notification.ReferenceLocation;
            return(message);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Downloads the message payload referred to by the specified <see cref="PayloadReference"/>.
        /// </summary>
        /// <param name="notification">The payload reference.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>The task representing the asynchronous operation.</returns>
        public virtual async Task<Payload> DownloadPayloadAsync(PayloadReference notification, CancellationToken cancellationToken = default(CancellationToken))
        {
            Requires.NotNull(notification, "notification");

            byte[] messageBuffer = null;
            const int MaxAttempts = 2;
            int retry;
            Exception exceptionLeadingToRetry = null;
            for (retry = 0; retry < MaxAttempts; retry++)
            {
                exceptionLeadingToRetry = null;
                try
                {
                    var responseMessage = await this.HttpClient.GetAsync(notification.Location, cancellationToken).ConfigureAwait(false);
                    messageBuffer = await responseMessage.Content.ReadAsByteArrayAsync().ConfigureAwait(false);

                    // Calculate hash of downloaded message and check that it matches the referenced message hash.
                    if (!this.CryptoServices.IsHashMatchWithTolerantHashAlgorithm(messageBuffer, notification.Hash, CryptoProviderExtensions.ParseHashAlgorithmName(notification.HashAlgorithmName)))
                    {
                        // Sometimes when the hash mismatches, it's because the download was truncated
                        // (from switching out the application and then switching back, for example).
                        // Check for that before throwing.
                        if (responseMessage.Content.Headers.ContentLength.HasValue && responseMessage.Content.Headers.ContentLength.Value > messageBuffer.Length)
                        {
                            // It looks like the message was truncated. Retry.
                            exceptionLeadingToRetry = new InvalidMessageException();
                            continue;
                        }

                        throw new InvalidMessageException();
                    }

                    // Stop retrying. We got something that worked!
                    break;
                }
                catch (HttpRequestException ex)
                {
                    exceptionLeadingToRetry = ex;
                    continue;
                }
            }

            if (exceptionLeadingToRetry != null)
            {
                if (exceptionLeadingToRetry.StackTrace != null)
                {
                    ExceptionDispatchInfo.Capture(exceptionLeadingToRetry).Throw();
                }
                else
                {
                    throw exceptionLeadingToRetry;
                }
            }

            var encryptionVariables = new SymmetricEncryptionVariables(notification.Key, notification.IV);

            var cipherStream = new MemoryStream(messageBuffer);
            var plainTextStream = new MemoryStream();
            await this.CryptoServices.DecryptAsync(cipherStream, plainTextStream, encryptionVariables, cancellationToken).ConfigureAwait(false);
            plainTextStream.Position = 0;
            var plainTextReader = new BinaryReader(plainTextStream);
            var message = Utilities.DeserializeDataContract<Payload>(plainTextReader);
            message.PayloadReferenceUri = notification.ReferenceLocation;
            return message;
        }