public static TransportMessage ToTransportMessage(this SqsTransportMessage sqsTransportMessage, IAmazonS3 amazonS3, SqsConnectionConfiguration connectionConfiguration)
        {
            var messageId = sqsTransportMessage.Headers[Headers.MessageId];

            var result = new TransportMessage(messageId, sqsTransportMessage.Headers);

            if (!string.IsNullOrEmpty(sqsTransportMessage.S3BodyKey))
            {
                var s3GetResponse = amazonS3.GetObject(connectionConfiguration.S3BucketForLargeMessages, sqsTransportMessage.S3BodyKey);
                result.Body = new byte[s3GetResponse.ResponseStream.Length];
                s3GetResponse.ResponseStream.Read(result.Body, 0, result.Body.Length);
            }
            else
            {
                result.Body = Convert.FromBase64String(sqsTransportMessage.Body);
            }

            result.TimeToBeReceived = sqsTransportMessage.TimeToBeReceived;

            if (sqsTransportMessage.ReplyToAddress != null)
            {
                result.Headers[Headers.ReplyToAddress] = sqsTransportMessage.ReplyToAddress.ToString();
            }

            return(result);
        }
        public void Send(TransportMessage message, SendOptions sendOptions)
        {
            try
            {
                var sqsTransportMessage = new SqsTransportMessage(message, sendOptions);
                var serializedMessage = JsonConvert.SerializeObject(sqsTransportMessage);
                if (serializedMessage.Length > 256*1024)
                {
                    if (string.IsNullOrEmpty(ConnectionConfiguration.S3BucketForLargeMessages))
                    {
                        throw new InvalidOperationException("Cannot send large message because no S3 bucket was configured. Add an S3 bucket name to your configuration.");
                    }

                    var key = ConnectionConfiguration.S3KeyPrefix + "/" + message.Id;

                    S3Client.PutObject(new Amazon.S3.Model.PutObjectRequest
                    {
                        BucketName = ConnectionConfiguration.S3BucketForLargeMessages,
                        InputStream = new MemoryStream(message.Body),
                        Key = key
                    });

                    sqsTransportMessage.S3BodyKey = key;
                    sqsTransportMessage.Body = String.Empty;
                    serializedMessage = JsonConvert.SerializeObject(sqsTransportMessage);
                }

                try
                {
                    SendMessage(serializedMessage, sendOptions);
                }
                catch (QueueDoesNotExistException)
                {
                    QueueCreator.CreateQueueIfNecessary(sendOptions.Destination, "");

                    SendMessage(serializedMessage, sendOptions);
                }
            }
            catch (Exception e)
            {
                Logger.Error("Exception from Send.", e);
                throw;
            }
        }
        public static async Task <IncomingMessage> ToIncomingMessage(this SqsTransportMessage sqsTransportMessage,
                                                                     IAmazonS3 amazonS3,
                                                                     SqsConnectionConfiguration connectionConfiguration,
                                                                     CancellationToken cancellationToken)
        {
            var messageId = sqsTransportMessage.Headers[Headers.MessageId];

            byte[] body;

            if (!string.IsNullOrEmpty(sqsTransportMessage.S3BodyKey))
            {
                var s3GetResponse = await amazonS3.GetObjectAsync(connectionConfiguration.S3BucketForLargeMessages,
                                                                  sqsTransportMessage.S3BodyKey,
                                                                  cancellationToken).ConfigureAwait(false);

                body = new byte[s3GetResponse.ResponseStream.Length];
                using (BufferedStream bufferedStream = new BufferedStream(s3GetResponse.ResponseStream))
                {
                    int       count;
                    int       transferred  = 0;
                    const int maxChunkSize = 8 * 1024;
                    int       bytesToRead  = Math.Min(maxChunkSize, body.Length - transferred);
                    while ((count = await bufferedStream.ReadAsync(body, transferred, bytesToRead, cancellationToken).ConfigureAwait(false)) > 0)
                    {
                        transferred += count;
                        bytesToRead  = Math.Min(maxChunkSize, body.Length - transferred);
                    }
                }
            }
            else
            {
                body = Convert.FromBase64String(sqsTransportMessage.Body);
            }

            return(new IncomingMessage(messageId, sqsTransportMessage.Headers, body));
        }
		private void DeleteMessage(IAmazonSQS sqs, 
			IAmazonS3 s3,
			Message message, 
			SqsTransportMessage sqsTransportMessage, 
			TransportMessage transportMessage)
		{
			sqs.DeleteMessage(_queueUrl, message.ReceiptHandle);

			if (!String.IsNullOrEmpty(sqsTransportMessage.S3BodyKey))
			{
				// Delete the S3 body asynchronously. 
				// We don't really care too much if this call succeeds or fails - if it fails, 
				// the S3 bucket lifecycle configuration will eventually delete the message anyway.
				// So, we can get better performance by not waiting around for this call to finish.
				var s3DeleteTask = s3.DeleteObjectAsync(
					new DeleteObjectRequest
					{
						BucketName = ConnectionConfiguration.S3BucketForLargeMessages,
						Key = ConnectionConfiguration.S3KeyPrefix + transportMessage.Id
					});

				s3DeleteTask.ContinueWith(t =>
				{
					if (t.Exception != null)
					{
						// If deleting the message body from S3 fails, we don't 
						// want the exception to make its way through to the _endProcessMessage below,
						// as the message has been successfully processed and deleted from the SQS queue
						// and effectively doesn't exist anymore. 
						// It doesn't really matter, as S3 is configured to delete message body data
						// automatically after a certain period of time.
						Logger.Warn("Couldn't delete message body from S3. Message body data will be aged out at a later time.", t.Exception);
					}
				});
			}
		}