Ejemplo n.º 1
0
 public SendAsyncResult(SendingAmqpLink link, AmqpMessage message, TimeSpan timeout, AsyncCallback callback, object state)
     : base(callback, state)
 {
     this.message = message;
     this.message.CompleteCallback = onSendComplete;
     link.SendDelivery(message);
 }
Ejemplo n.º 2
0
 public IAsyncResult BeginSendMessage(AmqpMessage message, ArraySegment<byte> deliveryTag, ArraySegment<byte> txnId, TimeSpan timeout, AsyncCallback callback, object state)
 {
     Fx.Assert(message.CompleteCallback == null, "Call SendDelivery() when using a complete callback");
     message.DeliveryTag = deliveryTag;
     message.TxnId = txnId;
     return new SendAsyncResult(this, message, timeout, callback, state);
 }
Ejemplo n.º 3
0
        static ArraySegment<byte>[] ReadMessagePayLoad(AmqpMessage message, int payloadSize)
        {
            List<ArraySegment<byte>> buffers = new List<ArraySegment<byte>>();
            bool more = true;
            while (more)
            {
                ArraySegment<byte>[] messageBuffers = message.GetPayload(payloadSize, out more);
                if (messageBuffers != null)
                {
                    foreach (var segment in messageBuffers) { message.CompletePayload(segment.Count); }
                    buffers.AddRange(messageBuffers);
                }
            }

            return buffers.ToArray();
        }
Ejemplo n.º 4
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="message"></param>
        /// <param name="retryPolicy"></param>
        /// <param name="receiveLinkName"></param>
        /// <param name="timeout"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        internal async Task <long> ScheduleMessageInternal(
            ServiceBusMessage message,
            ServiceBusRetryPolicy retryPolicy,
            string receiveLinkName,
            TimeSpan timeout,
            CancellationToken cancellationToken = default)
        {
            var stopWatch = Stopwatch.StartNew();

            using (AmqpMessage amqpMessage = AmqpMessageConverter.SBMessageToAmqpMessage(message))
            {
                var request = AmqpRequestMessage.CreateRequest(
                    ManagementConstants.Operations.ScheduleMessageOperation,
                    timeout,
                    null);

                if (receiveLinkName != null)
                {
                    request.AmqpMessage.ApplicationProperties.Map[ManagementConstants.Request.AssociatedLinkName] = receiveLinkName;
                }

                ArraySegment <byte>[] payload = amqpMessage.GetPayload();
                var buffer = new BufferListStream(payload);
                ArraySegment <byte> value = buffer.ReadBytes((int)buffer.Length);

                var entry = new AmqpMap();
                {
                    entry[ManagementConstants.Properties.Message]   = value;
                    entry[ManagementConstants.Properties.MessageId] = message.MessageId;

                    if (!string.IsNullOrWhiteSpace(message.SessionId))
                    {
                        entry[ManagementConstants.Properties.SessionId] = message.SessionId;
                    }

                    if (!string.IsNullOrWhiteSpace(message.PartitionKey))
                    {
                        entry[ManagementConstants.Properties.PartitionKey] = message.PartitionKey;
                    }

                    if (!string.IsNullOrWhiteSpace(message.ViaPartitionKey))
                    {
                        entry[ManagementConstants.Properties.ViaPartitionKey] = message.ViaPartitionKey;
                    }
                }

                request.Map[ManagementConstants.Properties.Messages] = new List <AmqpMap> {
                    entry
                };

                RequestResponseAmqpLink link = await ManagementLink.GetOrCreateAsync(
                    UseMinimum(ConnectionScope.SessionTimeout,
                               timeout.CalculateRemaining(stopWatch.Elapsed)))
                                               .ConfigureAwait(false);

                using AmqpMessage response = await link.RequestAsync(
                          request.AmqpMessage,
                          timeout.CalculateRemaining(stopWatch.Elapsed))
                                             .ConfigureAwait(false);

                cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>();
                stopWatch.Stop();

                AmqpResponseMessage amqpResponseMessage = AmqpResponseMessage.CreateResponse(response);

                if (amqpResponseMessage.StatusCode == AmqpResponseStatusCode.OK)
                {
                    var sequenceNumbers = amqpResponseMessage.GetValue <long[]>(ManagementConstants.Properties.SequenceNumbers);
                    if (sequenceNumbers == null || sequenceNumbers.Length < 1)
                    {
                        throw new ServiceBusException(true, "Could not schedule message successfully.");
                    }

                    return(sequenceNumbers[0]);
                }
                else
                {
                    throw new Exception();
                    //throw response.ToMessagingContractException();
                }
            }
        }
Ejemplo n.º 5
0
 public void DisposeMessage(AmqpMessage message, DeliveryState deliveryState, bool settled, bool batchable)
 {
     this.receiver.DisposeMessage(message, deliveryState, settled, batchable);
 }
Ejemplo n.º 6
0
        void OnReceiveMessage(AmqpMessage message)
        {
            if (this.messageListener != null)
            {
                this.messageListener(message);
            }
            else
            {
                ReceiveAsyncResult waiter = null;
                lock (this.syncRoot)
                {
                    if (this.waiterList != null && this.waiterList.Count > 0)
                    {
                        waiter = this.waiterList.First.Value;
                        this.waiterList.RemoveFirst();
                        waiter.OnRemoved();
                    }
                    else if (this.messageQueue != null)
                    {
                        this.messageQueue.Enqueue(message);
                    }
                }

                if (waiter != null)
                {
                    waiter.Signal(message, false);
                }
            }

            this.minTimeout = TimeSpan.Zero;
        }
Ejemplo n.º 7
0
        public void RejectMessage(AmqpMessage message, Exception exception)
        {
            Rejected rejected = new Rejected();
            rejected.Error = AmqpError.FromException(exception);

            this.DisposeMessage(message, rejected, true, false);
        }
Ejemplo n.º 8
0
 void OnMessage(AmqpMessage message)
 {
     string errorCondition = null;
     if (message.ApplicationProperties != null &&
         message.ApplicationProperties.Map.TryGetValue<string>("errorcondition", out errorCondition))
     {
         this.link.DisposeMessage(message, new Rejected() { Error = new Error() { Condition = errorCondition, Description = "message was rejected" } }, true, false);
     }
     else
     {
         if (message.TxnId.Array != null)
         {
             Transaction txn = this.queue.broker.txnManager.GetTransaction(message.TxnId);
             txn.AddOperation(message, this.OnTxnDischarge);
             this.link.DisposeMessage(message, new TransactionalState() { Outcome = AmqpConstants.AcceptedOutcome }, true, message.Batchable);
         }
         else
         {
             this.queue.Enqueue(new BrokerMessage(message));
             this.link.AcceptMessage(message, message.Batchable);
             message.Dispose();
         }
     }
 }
Ejemplo n.º 9
0
 protected override Task OnMessageReceived(AmqpMessage amqpMessage)
 {
     this.ReceivedMessages.Add(amqpMessage);
     return(Task.CompletedTask);
 }
Ejemplo n.º 10
0
 public static AmqpResponseMessage CreateResponse(AmqpMessage response)
 {
     return(new AmqpResponseMessage(response));
 }
Ejemplo n.º 11
0
 void OnMessageReceived(AmqpMessage message)
 {
     Events.NewTokenReceived();
     this.authenticationUpdateTask = this.UpdateAmqpAuthentication(message);
 }
Ejemplo n.º 12
0
        static void AddSection(AmqpMessage message, SectionFlag sections)
        {
            if ((sections & SectionFlag.Header) != 0)
            {
                message.Header.Priority = 10;
                message.Header.Ttl = (uint)(DateTime.Parse("2011-02-01 12:00:00") - AmqpConstants.StartOfEpoch).TotalMilliseconds;
            }

            if ((sections & SectionFlag.DeliveryAnnotations) != 0)
            {
                message.DeliveryAnnotations.Map["delivery-annotation"] = "delivery annotation";
            }

            if ((sections & SectionFlag.MessageAnnotations) != 0)
            {
                message.MessageAnnotations.Map["message-annotation"] = "message annotation";
            }

            if ((sections & SectionFlag.Properties) != 0)
            {
                message.Properties.MessageId = "message 1";
            }

            if ((sections & SectionFlag.ApplicationProperties) != 0)
            {
                message.ApplicationProperties.Map["message-prop"] = "message property";
            }

            if ((sections & SectionFlag.Footer) != 0)
            {
                message.Footer.Map["footer-prop"] = "footer";
            }
        }
Ejemplo n.º 13
0
        static void ValidateMessage(AmqpMessage original, AmqpMessage deserialized)
        {
            Assert.Equal(original.Sections, deserialized.Sections);

            if ((original.Sections & SectionFlag.Header) != 0)
            {
                Assert.Equal(original.Header.Priority.Value, deserialized.Header.Priority.Value);
                Assert.Equal(original.Header.Ttl.Value, deserialized.Header.Ttl.Value);
            }

            if ((original.Sections & SectionFlag.DeliveryAnnotations) != 0)
            {
                Assert.Equal(original.DeliveryAnnotations.Map.Count(), deserialized.DeliveryAnnotations.Map.Count());
                foreach (var pair in original.DeliveryAnnotations.Map)
                {
                    Assert.Equal(original.DeliveryAnnotations.Map[pair.Key], deserialized.DeliveryAnnotations.Map[pair.Key]);
                }
            }

            if ((original.Sections & SectionFlag.MessageAnnotations) != 0)
            {
                Assert.Equal(original.MessageAnnotations.Map.Count(), deserialized.MessageAnnotations.Map.Count());
                foreach (var pair in original.MessageAnnotations.Map)
                {
                    Assert.Equal(original.MessageAnnotations.Map[pair.Key], deserialized.MessageAnnotations.Map[pair.Key]);
                }
            }

            if ((original.Sections & SectionFlag.Properties) != 0)
            {
                Assert.Equal(original.Properties.MessageId.ToString(), deserialized.Properties.MessageId.ToString());
            }

            if ((original.Sections & SectionFlag.ApplicationProperties) != 0)
            {
                Assert.Equal(original.ApplicationProperties.Map.Count(), deserialized.ApplicationProperties.Map.Count());
                foreach (var pair in original.ApplicationProperties.Map)
                {
                    Assert.Equal(original.ApplicationProperties.Map[pair.Key], deserialized.ApplicationProperties.Map[pair.Key]);
                }
            }

            if ((original.Sections & SectionFlag.Footer) != 0)
            {
                Assert.Equal(original.Footer.Map.Count(), deserialized.Footer.Map.Count());
                foreach (var pair in original.Footer.Map)
                {
                    Assert.Equal(original.Footer.Map[pair.Key], deserialized.Footer.Map[pair.Key]);
                }
            }

            if ((original.Sections & SectionFlag.Data) != 0)
            {
                try
                {
                    Assert.Equal(original.DataBody.Count(), deserialized.DataBody.Count());
                    using (IEnumerator<Data> enumerator1 = original.DataBody.GetEnumerator())
                    using (IEnumerator<Data> enumerator2 = deserialized.DataBody.GetEnumerator())
                    {
                        while (enumerator1.MoveNext() && enumerator2.MoveNext())
                        {
                            ArraySegment<byte> data1 = (ArraySegment<byte>)enumerator1.Current.Value;
                            ArraySegment<byte> data2 = (ArraySegment<byte>)enumerator1.Current.Value;
                            Assert.Equal(data1.Count, data2.Count);
                        }
                    }
                }
                catch (InvalidOperationException)
                {
                    // some messages do not support DataBody property
                    Stream bodyStream1 = original.BodyStream;
                    Stream bodyStream2 = deserialized.BodyStream;
                    Assert.Equal(bodyStream1.Length, bodyStream2.Length);
                }
            }

            if ((original.Sections & SectionFlag.AmqpValue) != 0)
            {
                Assert.Equal(original.ValueBody.Value, deserialized.ValueBody.Value);
            }

            if ((original.Sections & SectionFlag.AmqpSequence) != 0)
            {
                Assert.Equal(original.SequenceBody.Count(), deserialized.SequenceBody.Count());
                using(IEnumerator<AmqpSequence> enumerator1 = original.SequenceBody.GetEnumerator())
                using(IEnumerator<AmqpSequence> enumerator2 = deserialized.SequenceBody.GetEnumerator())
                {
                    while (enumerator1.MoveNext() && enumerator2.MoveNext())
                    {
                        Assert.Equal(enumerator1.Current.List.Count, enumerator2.Current.List.Count);
                        for(int i = 0; i < enumerator1.Current.List.Count; i++)
                        {
                            Assert.Equal(enumerator1.Current.List[i], enumerator2.Current.List[i]); 
                        }
                    }
                }
            }
        }
Ejemplo n.º 14
0
 static void RunSerializationTest(AmqpMessage message)
 {
     AmqpMessage deserialized = AmqpMessage.CreateAmqpStreamMessage(new BufferListStream(ReadMessagePayLoad(message, 89)));
     ValidateMessage(message, deserialized);
 }
 AmqpMessage PopulateAmqpMessageForSend(AmqpMessage message)
 {
     MethodConverter.PopulateAmqpMessageFromMethodResponse(message, this);
     return(message);
 }
 private void DisposeDelivery(AmqpMessage amqpMessage, bool settled, Accepted acceptedOutcome)
 {
     _receivingAmqpLink.DisposeDelivery(amqpMessage, settled, acceptedOutcome);
 }
        public static ServiceBusReceivedMessage AmqpMessageToSBMessage(AmqpMessage amqpMessage, bool isPeeked = false)
        {
            Argument.AssertNotNull(amqpMessage, nameof(amqpMessage));
            AmqpAnnotatedMessage annotatedMessage;

            // body

            if ((amqpMessage.BodyType & SectionFlag.Data) != 0 && amqpMessage.DataBody != null)
            {
                annotatedMessage = new AmqpAnnotatedMessage(AmqpMessageBody.FromData(MessageBody.FromDataSegments(amqpMessage.DataBody)));
            }
            else if ((amqpMessage.BodyType & SectionFlag.AmqpValue) != 0 && amqpMessage.ValueBody?.Value != null)
            {
                if (TryGetNetObjectFromAmqpObject(amqpMessage.ValueBody.Value, MappingType.MessageBody, out object netObject))
                {
                    annotatedMessage = new AmqpAnnotatedMessage(AmqpMessageBody.FromValue(netObject));
                }
                else
                {
                    throw new NotSupportedException(Resources.InvalidAmqpMessageValueBody.FormatForUser(amqpMessage.ValueBody.Value.GetType()));
                }
            }
            else if ((amqpMessage.BodyType & SectionFlag.AmqpSequence) != 0)
            {
                annotatedMessage = new AmqpAnnotatedMessage(
                    AmqpMessageBody.FromSequence(amqpMessage.SequenceBody.Select(s => (IList <object>)s.List).ToList()));
            }
            // default to using an empty Data section if no data
            else
            {
                annotatedMessage = new AmqpAnnotatedMessage(new AmqpMessageBody(Enumerable.Empty <ReadOnlyMemory <byte> >()));
            }
            ServiceBusReceivedMessage sbMessage = new ServiceBusReceivedMessage(annotatedMessage);

            SectionFlag sections = amqpMessage.Sections;

            // properties

            if ((sections & SectionFlag.Properties) != 0)
            {
                if (amqpMessage.Properties.MessageId != null)
                {
                    annotatedMessage.Properties.MessageId = new AmqpMessageId(amqpMessage.Properties.MessageId.ToString());
                }

                if (amqpMessage.Properties.CorrelationId != null)
                {
                    annotatedMessage.Properties.CorrelationId = new AmqpMessageId(amqpMessage.Properties.CorrelationId.ToString());
                }

                if (amqpMessage.Properties.ContentType.Value != null)
                {
                    annotatedMessage.Properties.ContentType = amqpMessage.Properties.ContentType.Value;
                }

                if (amqpMessage.Properties.ContentEncoding.Value != null)
                {
                    annotatedMessage.Properties.ContentEncoding = amqpMessage.Properties.ContentEncoding.Value;
                }

                if (amqpMessage.Properties.Subject != null)
                {
                    annotatedMessage.Properties.Subject = amqpMessage.Properties.Subject;
                }

                if (amqpMessage.Properties.To != null)
                {
                    annotatedMessage.Properties.To = new AmqpAddress(amqpMessage.Properties.To.ToString());
                }

                if (amqpMessage.Properties.ReplyTo != null)
                {
                    annotatedMessage.Properties.ReplyTo = new AmqpAddress(amqpMessage.Properties.ReplyTo.ToString());
                }

                if (amqpMessage.Properties.GroupId != null)
                {
                    annotatedMessage.Properties.GroupId = amqpMessage.Properties.GroupId;
                }

                if (amqpMessage.Properties.ReplyToGroupId != null)
                {
                    annotatedMessage.Properties.ReplyToGroupId = amqpMessage.Properties.ReplyToGroupId;
                }

                if (amqpMessage.Properties.GroupSequence != null)
                {
                    annotatedMessage.Properties.GroupSequence = amqpMessage.Properties.GroupSequence;
                }

                if (amqpMessage.Properties.UserId != null)
                {
                    annotatedMessage.Properties.UserId = amqpMessage.Properties.UserId;
                }

                if (amqpMessage.Properties.CreationTime != null)
                {
                    annotatedMessage.Properties.CreationTime = amqpMessage.Properties.CreationTime;
                }

                if (amqpMessage.Properties.AbsoluteExpiryTime != null)
                {
                    annotatedMessage.Properties.AbsoluteExpiryTime =
                        amqpMessage.Properties.AbsoluteExpiryTime >= DateTimeOffset.MaxValue.UtcDateTime
                        ? DateTimeOffset.MaxValue
                        : amqpMessage.Properties.AbsoluteExpiryTime;
                }
            }

            // Do application properties before message annotations, because the application properties
            // can be updated by entries from message annotation.
            if ((sections & SectionFlag.ApplicationProperties) != 0)
            {
                foreach (var pair in amqpMessage.ApplicationProperties.Map)
                {
                    if (TryGetNetObjectFromAmqpObject(pair.Value, MappingType.ApplicationProperty, out var netObject))
                    {
                        annotatedMessage.ApplicationProperties[pair.Key.ToString()] = netObject;
                    }
                }
            }

            // message annotations

            if ((sections & SectionFlag.MessageAnnotations) != 0)
            {
                foreach (var pair in amqpMessage.MessageAnnotations.Map)
                {
                    var key = pair.Key.ToString();
                    switch (key)
                    {
                    case AmqpMessageConstants.EnqueuedTimeUtcName:
                        annotatedMessage.MessageAnnotations[AmqpMessageConstants.EnqueuedTimeUtcName] = pair.Value;
                        break;

                    case AmqpMessageConstants.ScheduledEnqueueTimeUtcName:
                        annotatedMessage.MessageAnnotations[AmqpMessageConstants.ScheduledEnqueueTimeUtcName] = pair.Value;
                        break;

                    case AmqpMessageConstants.SequenceNumberName:
                        annotatedMessage.MessageAnnotations[AmqpMessageConstants.SequenceNumberName] = pair.Value;
                        break;

                    case AmqpMessageConstants.EnqueueSequenceNumberName:
                        annotatedMessage.MessageAnnotations[AmqpMessageConstants.EnqueueSequenceNumberName] = pair.Value;
                        break;

                    case AmqpMessageConstants.LockedUntilName:
                        DateTimeOffset lockedUntil = (DateTime)pair.Value >= DateTimeOffset.MaxValue.UtcDateTime ?
                                                     DateTimeOffset.MaxValue : (DateTime)pair.Value;
                        annotatedMessage.MessageAnnotations[AmqpMessageConstants.LockedUntilName] = lockedUntil.UtcDateTime;
                        break;

                    case AmqpMessageConstants.PartitionKeyName:
                        annotatedMessage.MessageAnnotations[AmqpMessageConstants.PartitionKeyName] = pair.Value;
                        break;

                    case AmqpMessageConstants.PartitionIdName:
                        annotatedMessage.MessageAnnotations[AmqpMessageConstants.PartitionIdName] = pair.Value;
                        break;

                    case AmqpMessageConstants.ViaPartitionKeyName:
                        annotatedMessage.MessageAnnotations[AmqpMessageConstants.ViaPartitionKeyName] = pair.Value;
                        break;

                    case AmqpMessageConstants.DeadLetterSourceName:
                        annotatedMessage.MessageAnnotations[AmqpMessageConstants.DeadLetterSourceName] = pair.Value;
                        break;

                    default:
                        if (TryGetNetObjectFromAmqpObject(pair.Value, MappingType.ApplicationProperty, out var netObject))
                        {
                            annotatedMessage.MessageAnnotations[key] = netObject;
                        }
                        break;
                    }
                }
            }

            // delivery annotations

            if (amqpMessage.DeliveryAnnotations != null)
            {
                foreach (KeyValuePair <MapKey, object> kvp in amqpMessage.DeliveryAnnotations.Map)
                {
                    if (TryGetNetObjectFromAmqpObject(kvp.Value, MappingType.ApplicationProperty, out var netObject))
                    {
                        annotatedMessage.DeliveryAnnotations[kvp.Key.ToString()] = netObject;
                    }
                }
            }

            // header

            if ((sections & SectionFlag.Header) != 0)
            {
                if (amqpMessage.Header.Ttl != null)
                {
                    annotatedMessage.Header.TimeToLive = TimeSpan.FromMilliseconds(amqpMessage.Header.Ttl.Value);
                }

                if (amqpMessage.Header.DeliveryCount != null)
                {
                    annotatedMessage.Header.DeliveryCount = isPeeked ? (amqpMessage.Header.DeliveryCount.Value) : (amqpMessage.Header.DeliveryCount.Value + 1);
                }
                annotatedMessage.Header.Durable       = amqpMessage.Header.Durable;
                annotatedMessage.Header.FirstAcquirer = amqpMessage.Header.FirstAcquirer;
                annotatedMessage.Header.Priority      = amqpMessage.Header.Priority;
            }

            // footer

            if (amqpMessage.DeliveryTag.Count == GuidSizeInBytes)
            {
                Span <byte> guidBytes = stackalloc byte[GuidSizeInBytes];
                amqpMessage.DeliveryTag.AsSpan().CopyTo(guidBytes);
                if (!MemoryMarshal.TryRead <Guid>(guidBytes, out var lockTokenGuid))
                {
                    lockTokenGuid = new Guid(guidBytes.ToArray());
                }
                sbMessage.LockTokenGuid = lockTokenGuid;
            }

            amqpMessage.Dispose();

            return(sbMessage);
        }
Ejemplo n.º 18
0
 void OnMessage(AmqpMessage message)
 {
     this.messages.EnqueueAndDispatch(message, null, false);
     this.Link.DisposeDelivery(message, true, message.State);
 }
Ejemplo n.º 19
0
        public void CreateBatchFromMessagesAllowNoPartitionKey(string partitionKey)
        {
            var converter = new AmqpMessageConverter();

            Assert.That(() => converter.CreateBatchFromMessages(new[] { AmqpMessage.Create() }, partitionKey), Throws.Nothing);
        }
Ejemplo n.º 20
0
 public void AcceptMessage(AmqpMessage message, bool batchable)
 {
     bool settled = this.Settings.SettleType != SettleMode.SettleOnDispose;
     this.AcceptMessage(message, settled, batchable);
 }
Ejemplo n.º 21
0
        public void FromMessageTest_AllProperties()
        {
            // Arrange
            byte[] bytes           = { 1, 2, 3, 4 };
            string messageId       = Guid.NewGuid().ToString();
            string correlationId   = Guid.NewGuid().ToString();
            string contentType     = "UTF-8";
            string contentEncoding = "application/json";
            string to                 = "d1";
            string userId             = "userId1";
            var    expiryTime         = new DateTime(2018, 2, 3, 02, 03, 04, DateTimeKind.Utc);
            string creationTime       = new DateTime(2018, 1, 1, 02, 03, 04, DateTimeKind.Utc).ToString("o");
            var    enqueuedTime       = new DateTime(2018, 4, 5, 04, 05, 06, DateTimeKind.Utc);
            byte   deliveryCount      = 10;
            string lockToken          = Guid.NewGuid().ToString();
            ulong  sequenceNumber     = 100;
            string messageSchema      = "testSchema";
            string operation          = "foo";
            string inputName          = "inputName";
            string outputName         = "outputName";
            string connectionDeviceId = "edgeDevice1";
            string connectionModuleId = "module1";

            var systemProperties = new Dictionary <string, string>
            {
                [SystemProperties.MessageId]        = messageId,
                [SystemProperties.MsgCorrelationId] = correlationId,
                [SystemProperties.ContentType]      = contentType,
                [SystemProperties.ContentEncoding]  = contentEncoding,
                [SystemProperties.To]                 = to,
                [SystemProperties.UserId]             = userId,
                [SystemProperties.ExpiryTimeUtc]      = expiryTime.ToString("o"),
                [SystemProperties.EnqueuedTime]       = enqueuedTime.ToString("o"),
                [SystemProperties.DeliveryCount]      = deliveryCount.ToString(),
                [SystemProperties.LockToken]          = lockToken,
                [SystemProperties.SequenceNumber]     = sequenceNumber.ToString(),
                [SystemProperties.MessageSchema]      = messageSchema,
                [SystemProperties.CreationTime]       = creationTime,
                [SystemProperties.Operation]          = operation,
                [SystemProperties.InputName]          = inputName,
                [SystemProperties.OutputName]         = outputName,
                [SystemProperties.ConnectionDeviceId] = connectionDeviceId,
                [SystemProperties.ConnectionModuleId] = connectionModuleId
            };

            var properties = new Dictionary <string, string>
            {
                ["Prop1"] = "Value1",
                ["Prop2"] = "Value2"
            };

            byte[] GetMessageBody(AmqpMessage sourceMessage)
            {
                using (var ms = new MemoryStream())
                {
                    sourceMessage.BodyStream.CopyTo(ms);
                    return(ms.ToArray());
                }
            }

            var message          = new EdgeMessage(bytes, properties, systemProperties);
            var messageConverter = new AmqpMessageConverter();

            // Act
            using (AmqpMessage amqpMessage = messageConverter.FromMessage(message))
            {
                // Assert
                Assert.NotNull(amqpMessage);
                Assert.Equal(bytes, GetMessageBody(amqpMessage));

                Assert.Equal(messageId, amqpMessage.Properties.MessageId.ToString());
                Assert.Equal(correlationId, amqpMessage.Properties.CorrelationId.ToString());
                Assert.Equal(contentEncoding, amqpMessage.Properties.ContentEncoding.ToString());
                Assert.Equal(contentType, amqpMessage.Properties.ContentType.ToString());
                Assert.Equal(to, amqpMessage.Properties.To.ToString());
                Assert.Equal(userId, Encoding.UTF8.GetString(amqpMessage.Properties.UserId.Array));
                Assert.Equal(expiryTime, amqpMessage.Properties.AbsoluteExpiryTime.HasValue ? amqpMessage.Properties.AbsoluteExpiryTime.Value : DateTime.MinValue);

                Assert.Equal(enqueuedTime, amqpMessage.MessageAnnotations.Map[Constants.MessageAnnotationsEnqueuedTimeKey]);
                Assert.Equal(deliveryCount, amqpMessage.MessageAnnotations.Map[Constants.MessageAnnotationsDeliveryCountKey]);
                Assert.Equal(lockToken, amqpMessage.MessageAnnotations.Map[Constants.MessageAnnotationsLockTokenName]);
                Assert.Equal(sequenceNumber, amqpMessage.MessageAnnotations.Map[Constants.MessageAnnotationsSequenceNumberName]);
                Assert.Equal(inputName, amqpMessage.MessageAnnotations.Map[Constants.MessageAnnotationsInputNameKey]);
                Assert.Equal(connectionDeviceId, amqpMessage.MessageAnnotations.Map[Constants.MessageAnnotationsConnectionDeviceId]);
                Assert.Equal(connectionModuleId, amqpMessage.MessageAnnotations.Map[Constants.MessageAnnotationsConnectionModuleId]);

                Assert.Equal(messageSchema, amqpMessage.ApplicationProperties.Map[Constants.MessagePropertiesMessageSchemaKey]);
                Assert.Equal(creationTime, amqpMessage.ApplicationProperties.Map[Constants.MessagePropertiesCreationTimeKey]);
                Assert.Equal(operation, amqpMessage.ApplicationProperties.Map[Constants.MessagePropertiesOperationKey]);
                Assert.False(amqpMessage.ApplicationProperties.Map.TryGetValue(Constants.MessagePropertiesOutputNameKey, out string _));

                Assert.Equal("Value1", amqpMessage.ApplicationProperties.Map["Prop1"].ToString());
                Assert.Equal("Value2", amqpMessage.ApplicationProperties.Map["Prop2"].ToString());
            }
        }
Ejemplo n.º 22
0
        public void ModifyMessage(AmqpMessage message, bool deliveryFailed, bool deliverElseWhere, Fields messageAttributes)
        {
            Modified modified = new Modified();
            modified.DeliveryFailed = deliveryFailed;
            modified.UndeliverableHere = deliverElseWhere;
            modified.MessageAnnotations = messageAttributes;

            this.DisposeMessage(message, modified, true, false);
        }
Ejemplo n.º 23
0
        public void ToMessageTest_AllProperties()
        {
            // Arrange
            IMessage receivedMessage;

            byte[] bytes           = { 1, 2, 3, 4 };
            string messageId       = Guid.NewGuid().ToString();
            string correlationId   = Guid.NewGuid().ToString();
            string contentType     = "application/json";
            string contentEncoding = "UTF-8";
            string to             = "d1";
            string userId         = "userId1";
            var    expiryTime     = new DateTime(2018, 2, 3, 02, 03, 04, DateTimeKind.Utc);
            string creationTime   = new DateTime(2018, 1, 1, 02, 03, 04, DateTimeKind.Utc).ToString("o");
            var    enqueuedTime   = new DateTime(2018, 4, 5, 04, 05, 06, DateTimeKind.Utc);
            byte   deliveryCount  = 10;
            string lockToken      = Guid.NewGuid().ToString();
            ulong  sequenceNumber = 100;
            string messageSchema  = "testSchema";
            string operation      = "foo";
            string outputName     = "output1";

            using (AmqpMessage amqpMessage = AmqpMessage.Create(new Data {
                Value = new ArraySegment <byte>(bytes)
            }))
            {
                amqpMessage.Properties.MessageId       = messageId;
                amqpMessage.Properties.CorrelationId   = correlationId;
                amqpMessage.Properties.ContentType     = contentType;
                amqpMessage.Properties.ContentEncoding = contentEncoding;
                amqpMessage.Properties.To                 = to;
                amqpMessage.Properties.UserId             = new ArraySegment <byte>(Encoding.UTF8.GetBytes(userId));
                amqpMessage.Properties.AbsoluteExpiryTime = expiryTime;

                amqpMessage.MessageAnnotations.Map[Constants.MessageAnnotationsEnqueuedTimeKey]    = enqueuedTime;
                amqpMessage.MessageAnnotations.Map[Constants.MessageAnnotationsDeliveryCountKey]   = deliveryCount;
                amqpMessage.MessageAnnotations.Map[Constants.MessageAnnotationsLockTokenName]      = lockToken;
                amqpMessage.MessageAnnotations.Map[Constants.MessageAnnotationsSequenceNumberName] = sequenceNumber;

                amqpMessage.ApplicationProperties.Map[Constants.MessagePropertiesMessageSchemaKey] = messageSchema;
                amqpMessage.ApplicationProperties.Map[Constants.MessagePropertiesCreationTimeKey]  = creationTime;
                amqpMessage.ApplicationProperties.Map[Constants.MessagePropertiesOperationKey]     = operation;
                amqpMessage.ApplicationProperties.Map[Constants.MessagePropertiesOutputNameKey]    = outputName;

                amqpMessage.ApplicationProperties.Map["Prop1"] = "Value1";
                amqpMessage.ApplicationProperties.Map["Prop2"] = "Value2";

                var messageConverter = new AmqpMessageConverter();

                // Act
                receivedMessage = messageConverter.ToMessage(amqpMessage);
            }

            // Assert
            Assert.NotNull(receivedMessage);
            Assert.Equal(receivedMessage.Body, bytes);
            Assert.Equal(15, receivedMessage.SystemProperties.Count);
            Assert.Equal(2, receivedMessage.Properties.Count);

            Assert.Equal(receivedMessage.SystemProperties[SystemProperties.MessageId], messageId);
            Assert.Equal(receivedMessage.SystemProperties[SystemProperties.MsgCorrelationId], correlationId);
            Assert.Equal(receivedMessage.SystemProperties[SystemProperties.ContentType], contentType);
            Assert.Equal(receivedMessage.SystemProperties[SystemProperties.ContentEncoding], contentEncoding);
            Assert.Equal(receivedMessage.SystemProperties[SystemProperties.To], to);
            Assert.Equal(receivedMessage.SystemProperties[SystemProperties.UserId], userId);
            Assert.Equal(receivedMessage.SystemProperties[SystemProperties.ExpiryTimeUtc], expiryTime.ToString("o"));
            Assert.Equal(receivedMessage.SystemProperties[SystemProperties.EnqueuedTime], enqueuedTime.ToString("o"));
            Assert.Equal(receivedMessage.SystemProperties[SystemProperties.DeliveryCount], deliveryCount.ToString());
            Assert.Equal(receivedMessage.SystemProperties[SystemProperties.LockToken], lockToken);
            Assert.Equal(receivedMessage.SystemProperties[SystemProperties.SequenceNumber], sequenceNumber.ToString());
            Assert.Equal(receivedMessage.SystemProperties[SystemProperties.MessageSchema], messageSchema);
            Assert.Equal(receivedMessage.SystemProperties[SystemProperties.CreationTime], creationTime);
            Assert.Equal(receivedMessage.SystemProperties[SystemProperties.Operation], operation);
            Assert.Equal(receivedMessage.SystemProperties[SystemProperties.OutputName], outputName);

            Assert.Equal("Value1", receivedMessage.Properties["Prop1"]);
            Assert.Equal("Value2", receivedMessage.Properties["Prop2"]);
        }
Ejemplo n.º 24
0
 void CompleteInternal(AmqpMessage message, bool syncComplete)
 {
     if (Interlocked.Exchange(ref this.completed, 1) == 0)
     {
         this.message = message;
         this.Complete(syncComplete);
     }
 }
 /// <summary>
 ///   Converts a given <see cref="AmqpMessage" /> source into its corresponding
 ///   <see cref="EventData" /> representation.
 /// </summary>
 ///
 /// <param name="source">The source message to convert.</param>
 ///
 /// <returns>The event that represents the converted AMQP message.</returns>
 ///
 /// <remarks>
 ///   The caller is assumed to hold ownership over the specified message, including
 ///   ensuring proper disposal.
 /// </remarks>
 ///
 public virtual EventData CreateEventFromMessage(AmqpMessage source)
 {
     Argument.AssertNotNull(source, nameof(source));
     return(BuildEventFromAmqpMessage(source));
 }
Ejemplo n.º 26
0
        /// <summary>
        /// Copies the Message instance's properties to the AmqpMessage instance.
        /// </summary>
        public static void UpdateAmqpMessageHeadersAndProperties(AmqpMessage amqpMessage, Message data, bool copyUserProperties = true)
        {
            amqpMessage.Properties.MessageId = data.MessageId;

            if (data.To != null)
            {
                amqpMessage.Properties.To = data.To;
            }

            if (!data.ExpiryTimeUtc.Equals(default(DateTime)))
            {
                amqpMessage.Properties.AbsoluteExpiryTime = data.ExpiryTimeUtc;
            }

            if (data.CorrelationId != null)
            {
                amqpMessage.Properties.CorrelationId = data.CorrelationId;
            }

            if (data.UserId != null)
            {
                amqpMessage.Properties.UserId = new ArraySegment<byte>(Encoding.UTF8.GetBytes(data.UserId));
            }

            if (amqpMessage.ApplicationProperties == null)
            {
                amqpMessage.ApplicationProperties = new ApplicationProperties();
            }

            object deliveryAckSetting;
            if (data.SystemProperties.TryGetValue(MessageSystemPropertyNames.Ack, out deliveryAckSetting))
            {
                amqpMessage.ApplicationProperties.Map["iothub-ack"] = (string)deliveryAckSetting;
            }

            if (copyUserProperties && data.Properties.Count > 0)
            {
                foreach (var pair in data.Properties)
                {
                    object amqpObject;
                    if (TryGetAmqpObjectFromNetObject(pair.Value, MappingType.ApplicationProperty, out amqpObject))
                    {
                        amqpMessage.ApplicationProperties.Map[pair.Key] = amqpObject;
                    }
                }
            }
        }
        /// <summary>
        ///   Parses the annotations set by the Event Hubs service on the <see cref="AmqpMessage"/>
        ///   associated with an event, extracting them into a consumable form.
        /// </summary>
        ///
        /// <param name="source">The message to use as the source of the event.</param>
        ///
        /// <returns>The <see cref="ParsedAnnotations" /> parsed from the source message.</returns>
        ///
        private static ParsedAnnotations ParseSystemAnnotations(AmqpMessage source)
        {
            var systemProperties = new ParsedAnnotations
            {
                ServiceAnnotations = new Dictionary <string, object>()
            };

            object amqpValue;
            object propertyValue;

            // Process the message annotations.

            if (source.Sections.HasFlag(SectionFlag.MessageAnnotations))
            {
                Annotations annotations = source.MessageAnnotations.Map;
                var         processed   = new HashSet <string>();

                if ((annotations.TryGetValue(AmqpProperty.EnqueuedTime, out amqpValue)) &&
                    (TryCreateEventPropertyForAmqpProperty(amqpValue, out propertyValue)))
                {
                    systemProperties.EnqueuedTime = propertyValue switch
                    {
                        DateTime dateValue => new DateTimeOffset(dateValue, TimeSpan.Zero),
                        long longValue => new DateTimeOffset(longValue, TimeSpan.Zero),
                        _ => (DateTimeOffset)propertyValue
                    };

                    processed.Add(AmqpProperty.EnqueuedTime.ToString());
                }

                if ((annotations.TryGetValue(AmqpProperty.SequenceNumber, out amqpValue)) &&
                    (TryCreateEventPropertyForAmqpProperty(amqpValue, out propertyValue)))
                {
                    systemProperties.SequenceNumber = (long)propertyValue;
                    processed.Add(AmqpProperty.SequenceNumber.ToString());
                }

                if ((annotations.TryGetValue(AmqpProperty.Offset, out amqpValue)) &&
                    (TryCreateEventPropertyForAmqpProperty(amqpValue, out propertyValue)) &&
                    (long.TryParse((string)propertyValue, NumberStyles.Integer, CultureInfo.InvariantCulture, out var offset)))
                {
                    systemProperties.Offset = offset;
                    processed.Add(AmqpProperty.Offset.ToString());
                }

                if ((annotations.TryGetValue(AmqpProperty.PartitionKey, out amqpValue)) &&
                    (TryCreateEventPropertyForAmqpProperty(amqpValue, out propertyValue)))
                {
                    systemProperties.PartitionKey = (string)propertyValue;
                    processed.Add(AmqpProperty.PartitionKey.ToString());
                }

                string key;

                foreach (KeyValuePair <MapKey, object> pair in annotations)
                {
                    key = pair.Key.ToString();

                    if ((!processed.Contains(key)) &&
                        (TryCreateEventPropertyForAmqpProperty(pair.Value, out propertyValue)))
                    {
                        systemProperties.ServiceAnnotations.Add(key, propertyValue);
                        processed.Add(key);
                    }
                }
            }

            // Process the delivery annotations.

            if (source.Sections.HasFlag(SectionFlag.DeliveryAnnotations))
            {
                if ((source.DeliveryAnnotations.Map.TryGetValue(AmqpProperty.PartitionLastEnqueuedTimeUtc, out amqpValue)) &&
                    (TryCreateEventPropertyForAmqpProperty(amqpValue, out propertyValue)))
                {
                    systemProperties.LastEnqueuedTime = propertyValue switch
                    {
                        DateTime dateValue => new DateTimeOffset(dateValue, TimeSpan.Zero),
                        long longValue => new DateTimeOffset(longValue, TimeSpan.Zero),
                        _ => (DateTimeOffset)propertyValue
                    };
                }

                if ((source.DeliveryAnnotations.Map.TryGetValue(AmqpProperty.PartitionLastEnqueuedSequenceNumber, out amqpValue)) &&
                    (TryCreateEventPropertyForAmqpProperty(amqpValue, out propertyValue)))
                {
                    systemProperties.LastSequenceNumber = (long)propertyValue;
                }

                if ((source.DeliveryAnnotations.Map.TryGetValue(AmqpProperty.PartitionLastEnqueuedOffset, out amqpValue)) &&
                    (TryCreateEventPropertyForAmqpProperty(amqpValue, out propertyValue)) &&
                    (long.TryParse((string)propertyValue, NumberStyles.Integer, CultureInfo.InvariantCulture, out var offset)))
                {
                    systemProperties.LastOffset = offset;
                }

                if ((source.DeliveryAnnotations.Map.TryGetValue(AmqpProperty.LastPartitionPropertiesRetrievalTimeUtc, out amqpValue)) &&
                    (TryCreateEventPropertyForAmqpProperty(amqpValue, out propertyValue)))
                {
                    systemProperties.LastReceivedTime = propertyValue switch
                    {
                        DateTime dateValue => new DateTimeOffset(dateValue, TimeSpan.Zero),
                        long longValue => new DateTimeOffset(longValue, TimeSpan.Zero),
                        _ => (DateTimeOffset)propertyValue
                    };
                }
            }

            // Process the properties annotations

            if (source.Sections.HasFlag(SectionFlag.Properties))
            {
                Properties properties = source.Properties;

                void conditionalAdd(string name, object value, bool condition)
                {
                    if (condition)
                    {
                        systemProperties.ServiceAnnotations.Add(name, value);
                    }
                }

                conditionalAdd(Properties.MessageIdName, properties.MessageId, properties.MessageId != null);
                conditionalAdd(Properties.UserIdName, properties.UserId, properties.UserId.Array != null);
                conditionalAdd(Properties.ToName, properties.To, properties.To != null);
                conditionalAdd(Properties.SubjectName, properties.Subject, properties.Subject != null);
                conditionalAdd(Properties.ReplyToName, properties.ReplyTo, properties.ReplyTo != null);
                conditionalAdd(Properties.CorrelationIdName, properties.CorrelationId, properties.CorrelationId != null);
                conditionalAdd(Properties.ContentTypeName, properties.ContentType, properties.ContentType.Value != null);
                conditionalAdd(Properties.ContentEncodingName, properties.ContentEncoding, properties.ContentEncoding.Value != null);
                conditionalAdd(Properties.AbsoluteExpiryTimeName, properties.AbsoluteExpiryTime, properties.AbsoluteExpiryTime != null);
                conditionalAdd(Properties.CreationTimeName, properties.CreationTime, properties.CreationTime != null);
                conditionalAdd(Properties.GroupIdName, properties.GroupId, properties.GroupId != null);
                conditionalAdd(Properties.GroupSequenceName, properties.GroupSequence, properties.GroupSequence != null);
                conditionalAdd(Properties.ReplyToGroupIdName, properties.ReplyToGroupId, properties.ReplyToGroupId != null);
            }

            return(systemProperties);
        }
Ejemplo n.º 28
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="retryPolicy"></param>
        /// <param name="fromSequenceNumber"></param>
        /// <param name="messageCount"></param>
        /// <param name="sessionId"></param>
        /// <param name="receiveLinkName"></param>
        /// <param name="timeout"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        internal async Task <IEnumerable <ServiceBusMessage> > PeekInternal(
            ServiceBusRetryPolicy retryPolicy,
            long?fromSequenceNumber,
            int messageCount,
            string sessionId,
            string receiveLinkName,
            TimeSpan timeout,
            CancellationToken cancellationToken = default)
        {
            var stopWatch = new Stopwatch();

            stopWatch.Start();

            AmqpRequestMessage amqpRequestMessage = AmqpRequestMessage.CreateRequest(
                ManagementConstants.Operations.PeekMessageOperation,
                timeout,
                null);

            await AquireAccessTokenAsync(cancellationToken).ConfigureAwait(false);

            if (receiveLinkName != null)
            {
                // include associated link for service optimization
                amqpRequestMessage.AmqpMessage.ApplicationProperties.Map[ManagementConstants.Request.AssociatedLinkName] = receiveLinkName;
            }

            amqpRequestMessage.Map[ManagementConstants.Properties.FromSequenceNumber] = fromSequenceNumber ?? LastPeekedSequenceNumber + 1;
            amqpRequestMessage.Map[ManagementConstants.Properties.MessageCount]       = messageCount;

            if (!string.IsNullOrWhiteSpace(sessionId))
            {
                amqpRequestMessage.Map[ManagementConstants.Properties.SessionId] = sessionId;
            }

            RequestResponseAmqpLink link = await ManagementLink.GetOrCreateAsync(
                UseMinimum(ConnectionScope.SessionTimeout,
                           timeout.CalculateRemaining(stopWatch.Elapsed)))
                                           .ConfigureAwait(false);

            cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>();

            using AmqpMessage responseAmqpMessage = await link.RequestAsync(
                      amqpRequestMessage.AmqpMessage,
                      timeout.CalculateRemaining(stopWatch.Elapsed))
                                                    .ConfigureAwait(false);

            cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>();

            AmqpResponseMessage amqpResponseMessage = AmqpResponseMessage.CreateResponse(responseAmqpMessage);

            var messages = new List <ServiceBusMessage>();

            //AmqpError.ThrowIfErrorResponse(responseAmqpMessage, EntityName);
            if (amqpResponseMessage.StatusCode == AmqpResponseStatusCode.OK)
            {
                ServiceBusMessage     message     = null;
                IEnumerable <AmqpMap> messageList = amqpResponseMessage.GetListValue <AmqpMap>(ManagementConstants.Properties.Messages);
                foreach (AmqpMap entry in messageList)
                {
                    var payload     = (ArraySegment <byte>)entry[ManagementConstants.Properties.Message];
                    var amqpMessage = AmqpMessage.CreateAmqpStreamMessage(new BufferListStream(new[] { payload }), true);
                    message = AmqpMessageConverter.AmqpMessageToSBMessage(amqpMessage, true);
                    messages.Add(message);
                }

                if (message != null)
                {
                    LastPeekedSequenceNumber = message.SystemProperties.SequenceNumber;
                }
                return(messages);
            }

            if (amqpResponseMessage.StatusCode == AmqpResponseStatusCode.NoContent ||
                (amqpResponseMessage.StatusCode == AmqpResponseStatusCode.NotFound && Equals(AmqpClientConstants.MessageNotFoundError, amqpResponseMessage.GetResponseErrorCondition())))
            {
                return(messages);
            }
            // TODO throw correct exception
            throw new Exception();
        }
Ejemplo n.º 29
0
        /// <summary>
        /// Copies the Message instance's properties to the AmqpMessage instance.
        /// </summary>
        public static void UpdateAmqpMessageHeadersAndProperties(AmqpMessage amqpMessage, Message data, bool copyUserProperties = true)
        {
            amqpMessage.Properties.MessageId = data.MessageId;

            if (data.To != null)
            {
                amqpMessage.Properties.To = data.To;
            }

            if (!data.ExpiryTimeUtc.Equals(default(DateTime)))
            {
                amqpMessage.Properties.AbsoluteExpiryTime = data.ExpiryTimeUtc;
            }

            if (data.CorrelationId != null)
            {
                amqpMessage.Properties.CorrelationId = data.CorrelationId;
            }

            if (data.UserId != null)
            {
                amqpMessage.Properties.UserId = new ArraySegment <byte>(Encoding.UTF8.GetBytes(data.UserId));
            }

            if (amqpMessage.ApplicationProperties == null)
            {
                amqpMessage.ApplicationProperties = new ApplicationProperties();
            }

            object propertyValue;

            if (data.SystemProperties.TryGetValue(MessageSystemPropertyNames.Ack, out propertyValue))
            {
                amqpMessage.ApplicationProperties.Map["iothub-ack"] = (string)propertyValue;
            }

            if (data.SystemProperties.TryGetValue(MessageSystemPropertyNames.MessageSchema, out propertyValue))
            {
                amqpMessage.ApplicationProperties.Map[MessageSystemPropertyNames.MessageSchema] = (string)propertyValue;
            }

            if (data.SystemProperties.TryGetValue(MessageSystemPropertyNames.CreationTimeUtc, out propertyValue))
            {
                amqpMessage.ApplicationProperties.Map[MessageSystemPropertyNames.CreationTimeUtc] = ((DateTime)propertyValue).ToString("o");    // Convert to string that complies with ISO 8601
            }

            if (data.SystemProperties.TryGetValue(MessageSystemPropertyNames.ContentType, out propertyValue))
            {
                amqpMessage.Properties.ContentType = (string)propertyValue;
            }

            if (data.SystemProperties.TryGetValue(MessageSystemPropertyNames.ContentEncoding, out propertyValue))
            {
                amqpMessage.Properties.ContentEncoding = (string)propertyValue;
            }

            if (data.SystemProperties.TryGetValue(MessageSystemPropertyNames.OutputName, out propertyValue))
            {
                amqpMessage.ApplicationProperties.Map[MessageSystemPropertyNames.OutputName] = (string)propertyValue;
            }

            if (data.SystemProperties.TryGetValue(MessageSystemPropertyNames.InterfaceId, out propertyValue))
            {
                amqpMessage.MessageAnnotations.Map[MessageSystemPropertyNames.InterfaceId] = (string)propertyValue;
            }

            if (copyUserProperties && data.Properties.Count > 0)
            {
                foreach (var pair in data.Properties)
                {
                    object amqpObject;
                    if (TryGetAmqpObjectFromNetObject(pair.Value, MappingType.ApplicationProperty, out amqpObject))
                    {
                        amqpMessage.ApplicationProperties.Map[pair.Key] = amqpObject;
                    }
                }
            }

            if (IoTHubClientDiagnostic.HasDiagnosticProperties(data))
            {
                amqpMessage.MessageAnnotations.Map[AmqpDiagIdKey] = data.SystemProperties[MessageSystemPropertyNames.DiagId];
                amqpMessage.MessageAnnotations.Map[AmqpDiagCorrelationContextKey] = data.SystemProperties[MessageSystemPropertyNames.DiagCorrelationContext];
            }
        }
        public async Task SendMessageWithFeedbackExactlyOnceModeTest()
        {
            // Arrange
            var metadataStore  = Mock.Of <IMetadataStore>();
            var feedbackStatus = FeedbackStatus.Abandon;
            var deviceListener = new Mock <IDeviceListener>();

            deviceListener.Setup(d => d.ProcessMessageFeedbackAsync(It.IsAny <string>(), It.IsAny <FeedbackStatus>()))
            .Callback <string, FeedbackStatus>((m, s) => feedbackStatus = s)
            .Returns(Task.CompletedTask);
            AmqpMessage receivedAmqpMessage = null;
            var         identity            = Mock.Of <IIdentity>(i => i.Id == "d1");
            var         connectionHandler   = Mock.Of <IConnectionHandler>(c => c.GetDeviceListener() == Task.FromResult(deviceListener.Object));
            var         amqpAuthenticator   = new Mock <IAmqpAuthenticator>();

            amqpAuthenticator.Setup(c => c.AuthenticateAsync("d1", Option.None <string>())).ReturnsAsync(true);
            Mock <ICbsNode> cbsNodeMock    = amqpAuthenticator.As <ICbsNode>();
            ICbsNode        cbsNode        = cbsNodeMock.Object;
            var             amqpConnection = Mock.Of <IAmqpConnection>(
                c =>
                c.FindExtension <IConnectionHandler>() == connectionHandler &&
                c.FindExtension <ICbsNode>() == cbsNode);
            var amqpSession      = Mock.Of <IAmqpSession>(s => s.Connection == amqpConnection);
            var amqpLinkSettings = new AmqpLinkSettings();
            var sendingLink      = Mock.Of <ISendingAmqpLink>(l => l.Session == amqpSession && !l.IsReceiver && l.Settings == amqpLinkSettings && l.State == AmqpObjectState.Opened);

            Mock.Get(sendingLink).Setup(s => s.SendMessageNoWait(It.IsAny <AmqpMessage>(), It.IsAny <ArraySegment <byte> >(), It.IsAny <ArraySegment <byte> >()))
            .Callback <AmqpMessage, ArraySegment <byte>, ArraySegment <byte> >((m, d, t) => { receivedAmqpMessage = m; });

            var requestUri     = new Uri("amqps://foo.bar/devices/d1");
            var boundVariables = new Dictionary <string, string> {
                { "deviceid", "d1" }
            };
            var messageConverter = new AmqpMessageConverter();

            var      sendingLinkHandler = new TestSendingLinkHandler(identity, sendingLink, requestUri, boundVariables, connectionHandler, messageConverter, QualityOfService.ExactlyOnce, metadataStore);
            var      body          = new byte[] { 0, 1, 2, 3 };
            IMessage message       = new EdgeMessage.Builder(body).Build();
            var      deliveryState = new Mock <DeliveryState>(new AmqpSymbol(string.Empty), AmqpConstants.AcceptedOutcome.DescriptorCode);
            var      delivery      = Mock.Of <Delivery>(
                d => d.State == deliveryState.Object &&
                d.DeliveryTag == new ArraySegment <byte>(Guid.NewGuid().ToByteArray()));

            // Act
            await sendingLinkHandler.OpenAsync(TimeSpan.FromSeconds(5));

            await sendingLinkHandler.SendMessage(message);

            // Assert
            Assert.NotNull(receivedAmqpMessage);
            Assert.Equal(body, receivedAmqpMessage.GetPayloadBytes());

            // Act
            sendingLinkHandler.DispositionListener(delivery);
            await Task.Delay(TimeSpan.FromSeconds(5));

            // Assert
            Assert.Equal(FeedbackStatus.Complete, feedbackStatus);
            Assert.Null(amqpLinkSettings.SndSettleMode);
            Assert.Equal((byte)ReceiverSettleMode.Second, amqpLinkSettings.RcvSettleMode);
        }
Ejemplo n.º 31
0
        /// <summary>
        /// Copies the properties from the amqp message to the Message instance.
        /// </summary>
        public static void UpdateMessageHeaderAndProperties(AmqpMessage amqpMessage, Message message)
        {
            Fx.AssertAndThrow(amqpMessage.DeliveryTag != null, "AmqpMessage should always contain delivery tag.");
            message.DeliveryTag = amqpMessage.DeliveryTag;

            SectionFlag sections = amqpMessage.Sections;

            if ((sections & SectionFlag.Properties) != 0)
            {
                // Extract only the Properties that we support
                message.MessageId = amqpMessage.Properties.MessageId != null?amqpMessage.Properties.MessageId.ToString() : null;

                message.To = amqpMessage.Properties.To != null?amqpMessage.Properties.To.ToString() : null;

                if (amqpMessage.Properties.AbsoluteExpiryTime.HasValue)
                {
                    message.ExpiryTimeUtc = amqpMessage.Properties.AbsoluteExpiryTime.Value;
                }

                message.CorrelationId = amqpMessage.Properties.CorrelationId != null?amqpMessage.Properties.CorrelationId.ToString() : null;

                if (!string.IsNullOrWhiteSpace(amqpMessage.Properties.ContentType.Value))
                {
                    message.ContentType = amqpMessage.Properties.ContentType.Value;
                }

                if (!string.IsNullOrWhiteSpace(amqpMessage.Properties.ContentEncoding.Value))
                {
                    message.ContentEncoding = amqpMessage.Properties.ContentEncoding.Value;
                }

                message.UserId = amqpMessage.Properties.UserId.Array != null?Encoding.UTF8.GetString(amqpMessage.Properties.UserId.Array, 0 /*index*/, amqpMessage.Properties.UserId.Array.Length) : null;
            }

            if ((sections & SectionFlag.MessageAnnotations) != 0)
            {
                if (amqpMessage.MessageAnnotations.Map.TryGetValue(LockTokenName, out string lockToken))
                {
                    message.LockToken = lockToken;
                }

                if (amqpMessage.MessageAnnotations.Map.TryGetValue(SequenceNumberName, out ulong sequenceNumber))
                {
                    message.SequenceNumber = sequenceNumber;
                }

                if (amqpMessage.MessageAnnotations.Map.TryGetValue(MessageSystemPropertyNames.EnqueuedTime, out DateTime enqueuedTime))
                {
                    message.EnqueuedTimeUtc = enqueuedTime;
                }

                if (amqpMessage.MessageAnnotations.Map.TryGetValue(MessageSystemPropertyNames.DeliveryCount, out byte deliveryCount))
                {
                    message.DeliveryCount = deliveryCount;
                }

                if (amqpMessage.MessageAnnotations.Map.TryGetValue(InputName, out string inputName))
                {
                    message.InputName = inputName;
                }

                if (amqpMessage.MessageAnnotations.Map.TryGetValue(MessageSystemPropertyNames.ConnectionDeviceId, out string connectionDeviceId))
                {
                    message.ConnectionDeviceId = connectionDeviceId;
                }

                if (amqpMessage.MessageAnnotations.Map.TryGetValue(MessageSystemPropertyNames.ConnectionModuleId, out string connectionModuleId))
                {
                    message.ConnectionModuleId = connectionModuleId;
                }
            }

            if ((sections & SectionFlag.ApplicationProperties) != 0)
            {
                foreach (KeyValuePair <MapKey, object> pair in amqpMessage.ApplicationProperties.Map)
                {
                    object netObject = null;
                    if (TryGetNetObjectFromAmqpObject(pair.Value, MappingType.ApplicationProperty, out netObject))
                    {
                        var stringObject = netObject as string;

                        if (stringObject != null)
                        {
                            switch (pair.Key.ToString())
                            {
                            case MessageSystemPropertyNames.Operation:
                                message.SystemProperties[pair.Key.ToString()] = stringObject;
                                break;

                            case MessageSystemPropertyNames.MessageSchema:
                                message.MessageSchema = stringObject;
                                break;

                            case MessageSystemPropertyNames.CreationTimeUtc:
                                message.CreationTimeUtc = DateTime.Parse(stringObject);
                                break;

                            default:
                                message.Properties[pair.Key.ToString()] = stringObject;
                                break;
                            }
                        }
                        else
                        {
                            // TODO: RDBug 4093369 Handling of non-string property values in Amqp messages
                            // Drop non-string properties and log an error
                            Fx.Exception.TraceHandled(new InvalidDataException("IotHub does not accept non-string Amqp properties"), "MessageConverter.UpdateMessageHeaderAndProperties");
                        }
                    }
                }
            }
        }
Ejemplo n.º 32
0
        private static void UpdateEventDataHeaderAndProperties(AmqpMessage amqpMessage, EventData data)
        {
            //Fx.AssertAndThrow(amqpMessage.DeliveryTag != null, "AmqpMessage should always contain delivery tag.");
            //data.DeliveryTag = amqpMessage.DeliveryTag;

            SectionFlag sections = amqpMessage.Sections;

            if ((sections & SectionFlag.MessageAnnotations) != 0)
            {
                // services (e.g. IoTHub) assumes that all Amqp message annotation will get bubbled up so we will cycle
                // through the list and add them to system properties as well.
                foreach (var keyValuePair in amqpMessage.MessageAnnotations.Map)
                {
                    if (data.Properties == null)
                    {
                        data.Properties = new Dictionary <string, object>();
                    }

                    object netObject;
                    if (TryGetNetObjectFromAmqpObject(keyValuePair.Value, MappingType.ApplicationProperty, out netObject))
                    {
                        data.Properties[keyValuePair.Key.ToString()] = netObject;
                    }
                }

                // Custom override for EventHub scenario. Note that these
                // "can" override existing properties, which is intentional as
                // in the EH these system properties take precedence over Amqp data.
                //string publisher;
                //if (amqpMessage.MessageAnnotations.Map.TryGetValue<string>(PublisherName, out publisher))
                //{
                //    data.Publisher = publisher;
                //}

//#if DEBUG
//                short partitionId;
//                if (amqpMessage.MessageAnnotations.Map.TryGetValue<short>(PartitionIdName, out partitionId))
//                {
//                    data.PartitionId = partitionId;
//                }
//#endif

                if (data.SystemProperties == null)
                {
                    data.SystemProperties = new EventData.SystemPropertiesCollection();
                }

                string partitionKey;
                if (amqpMessage.MessageAnnotations.Map.TryGetValue(AmqpMessageConverter.PartitionKeyName, out partitionKey))
                {
                    data.SystemProperties.PartitionKey = partitionKey;
                }

                DateTime enqueuedTimeUtc;
                if (amqpMessage.MessageAnnotations.Map.TryGetValue(AmqpMessageConverter.EnqueuedTimeUtcName, out enqueuedTimeUtc))
                {
                    data.SystemProperties.EnqueuedTimeUtc = enqueuedTimeUtc;
                }

                long sequenceNumber;
                if (amqpMessage.MessageAnnotations.Map.TryGetValue(AmqpMessageConverter.SequenceNumberName, out sequenceNumber))
                {
                    data.SystemProperties.SequenceNumber = sequenceNumber;
                }

                string offset;
                if (amqpMessage.MessageAnnotations.Map.TryGetValue(AmqpMessageConverter.OffsetName, out offset))
                {
                    data.SystemProperties.Offset = offset;
                }
            }

            if ((sections & SectionFlag.ApplicationProperties) != 0)
            {
                foreach (KeyValuePair <MapKey, object> pair in amqpMessage.ApplicationProperties.Map)
                {
                    if (data.Properties == null)
                    {
                        data.Properties = new Dictionary <string, object>();
                    }

                    object netObject;
                    if (TryGetNetObjectFromAmqpObject(pair.Value, MappingType.ApplicationProperty, out netObject))
                    {
                        data.Properties[pair.Key.ToString()] = netObject;
                    }
                }
            }

            //if ((sections & SectionFlag.Properties) != 0)
            //{
            //    var properties = amqpMessage.Properties;
            //    AddIfTrue(data.SystemProperties, properties, p => p.MessageId != null, Properties.MessageIdName, p => p.MessageId.ToString());
            //    AddIfTrue(data.SystemProperties, properties, p => p.UserId.Array != null, Properties.UserIdName, p => p.UserId);
            //    AddIfTrue(data.SystemProperties, properties, p => p.To != null, Properties.ToName, p => p.To.ToString());
            //    AddIfTrue(data.SystemProperties, properties, p => p.Subject != null, Properties.SubjectName, p => p.Subject);
            //    AddIfTrue(data.SystemProperties, properties, p => p.ReplyTo != null, Properties.ReplyToName, p => p.ReplyTo.ToString());
            //    AddIfTrue(data.SystemProperties, properties, p => p.CorrelationId != null, Properties.CorrelationIdName, p => p.CorrelationId.ToString());
            //    AddIfTrue(data.SystemProperties, properties, p => p.ContentType.Value != null, Properties.ContentTypeName, p => p.ContentType.ToString());
            //    AddIfTrue(data.SystemProperties, properties, p => p.ContentEncoding.Value != null, Properties.ContentEncodingName, p => p.ContentEncoding.ToString());
            //    AddIfTrue(data.SystemProperties, properties, p => p.AbsoluteExpiryTime != null, Properties.AbsoluteExpiryTimeName, p => p.AbsoluteExpiryTime);
            //    AddIfTrue(data.SystemProperties, properties, p => p.CreationTime != null, Properties.CreationTimeName, p => p.CreationTime);
            //    AddIfTrue(data.SystemProperties, properties, p => p.GroupId != null, Properties.GroupIdName, p => p.GroupId);
            //    AddIfTrue(data.SystemProperties, properties, p => p.GroupSequence != null, Properties.GroupSequenceName, p => p.GroupSequence);
            //    AddIfTrue(data.SystemProperties, properties, p => p.ReplyToGroupId != null, Properties.ReplyToGroupIdName, p => p.ReplyToGroupId);
            //}
        }
Ejemplo n.º 33
0
 public AmqpDelivery(AmqpMessage amqpMessage, ulong deliveryTag)
 {
     this.Message     = amqpMessage;
     this.DeliveryTag = deliveryTag;
 }
        private void OnTwinChangesReceived(AmqpMessage amqpMessage)
        {
            if (Logging.IsEnabled)
            {
                Logging.Enter(this, amqpMessage, $"{nameof(OnTwinChangesReceived)}");
            }

            try
            {
                _receivingAmqpLink.DisposeDelivery(amqpMessage, true, AmqpIoTConstants.AcceptedOutcome);
                string correlationId = amqpMessage.Properties?.CorrelationId?.ToString();
                int    status        = GetStatus(amqpMessage);

                Twin           twin           = null;
                TwinCollection twinProperties = null;

                if (status >= 400)
                {
                    // Handle failures
                    if (correlationId.StartsWith(AmqpTwinMessageType.Get.ToString(), StringComparison.OrdinalIgnoreCase) ||
                        correlationId.StartsWith(AmqpTwinMessageType.Patch.ToString(), StringComparison.OrdinalIgnoreCase))
                    {
                        string error = null;
                        using (var reader = new StreamReader(amqpMessage.BodyStream, System.Text.Encoding.UTF8))
                        {
                            error = reader.ReadToEnd();
                        };

                        // Retry for Http status code request timeout, Too many requests and server errors
                        var exception = new IotHubException(error, status >= 500 || status == 429 || status == 408);
                        _onTwinMessageReceived.Invoke(null, correlationId, null, exception);
                    }
                }
                else
                {
                    if (correlationId == null)
                    {
                        // Here we are getting desired property update notifications and want to handle it first
                        using var reader = new StreamReader(amqpMessage.BodyStream, System.Text.Encoding.UTF8);
                        string patch = reader.ReadToEnd();
                        twinProperties = JsonConvert.DeserializeObject <TwinCollection>(patch);
                    }
                    else if (correlationId.StartsWith(AmqpTwinMessageType.Get.ToString(), StringComparison.OrdinalIgnoreCase))
                    {
                        // This a response of a GET TWIN so return (set) the full twin
                        using var reader = new StreamReader(amqpMessage.BodyStream, System.Text.Encoding.UTF8);
                        string body       = reader.ReadToEnd();
                        var    properties = JsonConvert.DeserializeObject <TwinProperties>(body);
                        twin = new Twin(properties);
                    }
                    else if (correlationId.StartsWith(AmqpTwinMessageType.Patch.ToString(), StringComparison.OrdinalIgnoreCase))
                    {
                        // This can be used to coorelate success response with updating reported properties
                        // However currently we do not have it as request response style implementation
                        Logging.Info("Updated twin reported properties successfully", nameof(OnTwinChangesReceived));
                    }
                    else if (correlationId.StartsWith(AmqpTwinMessageType.Put.ToString(), StringComparison.OrdinalIgnoreCase))
                    {
                        // This is an acknowledgement received from service for subscribing to desired property updates
                        Logging.Info("Subscribed for twin successfully", nameof(OnTwinChangesReceived));
                    }
                    else
                    {
                        // This shouldn't happen
                        Logging.Info("Received a correlation Id for Twin operation that does not match Get, Patch or Put request", nameof(OnTwinChangesReceived));
                    }
                    _onTwinMessageReceived.Invoke(twin, correlationId, twinProperties, null);
                }
            }
            finally
            {
                if (Logging.IsEnabled)
                {
                    Logging.Exit(this, amqpMessage, $"{nameof(OnTwinChangesReceived)}");
                }
            }
        }
Ejemplo n.º 35
0
        /// <summary>
        ///   Sends an AMQP message that contains a batch of events to the associated Service Bus entity. If the size of events exceed the
        ///   maximum size of a single batch, an exception will be triggered and the send will fail.
        /// </summary>
        ///
        /// <param name="messageFactory">A factory which can be used to produce an AMQP message containing the batch of events to be sent.</param>
        /// <param name="cancellationToken">An optional <see cref="CancellationToken"/> instance to signal the request to cancel the operation.</param>
        ///
        protected virtual async Task SendAsync(Func <AmqpMessage> messageFactory,
                                               CancellationToken cancellationToken)
        {
            var failedAttemptCount = 0;
            var stopWatch          = Stopwatch.StartNew();

            SendingAmqpLink link;

            try
            {
                var tryTimeout = RetryPolicy.CalculateTryTimeout(0);
                while (!cancellationToken.IsCancellationRequested)
                {
                    try
                    {
                        using AmqpMessage batchMessage = messageFactory();
                        string messageHash = batchMessage.GetHashCode().ToString();

                        //ServiceBusEventSource.Log.EventPublishStart(EventHubName, logPartition, messageHash);

                        link = await SendLink.GetOrCreateAsync(UseMinimum(ConnectionScope.SessionTimeout, tryTimeout)).ConfigureAwait(false);

                        cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>();

                        // Validate that the batch of messages is not too large to send.  This is done after the link is created to ensure
                        // that the maximum message size is known, as it is dictated by the service using the link.

                        if (batchMessage.SerializedMessageSize > MaximumMessageSize)
                        {
                            throw new ServiceBusException(EntityName, string.Format(Resources1.MessageSizeExceeded, messageHash, batchMessage.SerializedMessageSize, MaximumMessageSize), ServiceBusException.FailureReason.MessageSizeExceeded);
                        }

                        // Attempt to send the message batch.

                        var deliveryTag = new ArraySegment <byte>(BitConverter.GetBytes(Interlocked.Increment(ref _deliveryCount)));
                        var outcome     = await link.SendMessageAsync(batchMessage, deliveryTag, AmqpConstants.NullBinary, tryTimeout.CalculateRemaining(stopWatch.Elapsed)).ConfigureAwait(false);

                        cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>();

                        if (outcome.DescriptorCode != Accepted.Code)
                        {
                            throw AmqpError.CreateExceptionForError((outcome as Rejected)?.Error, EntityName);
                        }

                        // The send operation should be considered successful; return to
                        // exit the retry loop.

                        return;
                    }
                    catch (Exception ex)
                    {
                        Exception activeEx = ex.TranslateServiceException(EntityName);

                        // Determine if there should be a retry for the next attempt; if so enforce the delay but do not quit the loop.
                        // Otherwise, bubble the exception.

                        ++failedAttemptCount;
                        TimeSpan?retryDelay = RetryPolicy.CalculateRetryDelay(activeEx, failedAttemptCount);

                        if (retryDelay.HasValue && !ConnectionScope.IsDisposed && !cancellationToken.IsCancellationRequested)
                        {
                            //ServiceBusEventSource.Log.EventPublishError(EventHubName, messageHash, activeEx.Message);
                            await Task.Delay(retryDelay.Value, cancellationToken).ConfigureAwait(false);

                            tryTimeout = RetryPolicy.CalculateTryTimeout(failedAttemptCount);
                            stopWatch.Reset();
                        }
                        else if (ex is AmqpException)
                        {
                            throw activeEx;
                        }
                        else
                        {
                            throw;
                        }
                    }
                }

                // If no value has been returned nor exception thrown by this point,
                // then cancellation has been requested.

                throw new TaskCanceledException();
            }
            catch (Exception)
            {
                //ServiceBusEventSource.Log.EventPublishError(EventHubName, logPartition, messageHash, ex.Message);
                throw;
            }
            finally
            {
                stopWatch.Stop();
                //ServiceBusEventSource.Log.EventPublishComplete(EventHubName, logPartition, messageHash);
            }
        }
Ejemplo n.º 36
0
            bool OnSend(AmqpMessage message)
            {
                if (this.Link == null)
                {
                    return false;
                }

                this.Link.SendDelivery(message);
                return true;
            }
Ejemplo n.º 37
0
        public async Task SendMessageBatchTest()
        {
            // Arrange
            var identity = Mock.Of <IIdentity>(i => i.Id == "d1");
            var amqpAuth = new AmqpAuthentication(true, Option.Some(Mock.Of <IClientCredentials>(c => c.Identity == identity)));

            IEnumerable <IMessage> receivedMessages = null;
            var deviceListener = Mock.Of <IDeviceListener>();

            Mock.Get(deviceListener).Setup(d => d.ProcessDeviceMessageBatchAsync(It.IsAny <IEnumerable <IMessage> >()))
            .Callback <IEnumerable <IMessage> >(m => receivedMessages = m)
            .Returns(Task.CompletedTask);

            var connectionHandler = Mock.Of <IConnectionHandler>(c => c.GetAmqpAuthentication() == Task.FromResult(amqpAuth) && c.GetDeviceListener() == Task.FromResult(deviceListener));
            var amqpConnection    = Mock.Of <IAmqpConnection>(c => c.FindExtension <IConnectionHandler>() == connectionHandler);
            var amqpSession       = Mock.Of <IAmqpSession>(s => s.Connection == amqpConnection);
            var amqpLink          = Mock.Of <IReceivingAmqpLink>(l => l.Session == amqpSession && l.IsReceiver && l.Settings == new AmqpLinkSettings() && l.State == AmqpObjectState.Opened);

            Action <AmqpMessage> onMessageCallback = null;

            Mock.Get(amqpLink).Setup(l => l.RegisterMessageListener(It.IsAny <Action <AmqpMessage> >())).Callback <Action <AmqpMessage> >(a => onMessageCallback = a);
            Mock.Get(amqpLink).SetupGet(l => l.Settings).Returns(new AmqpLinkSettings());
            Mock.Get(amqpLink).Setup(l => l.SafeAddClosed(It.IsAny <EventHandler>()));

            var requestUri     = new Uri("amqps://foo.bar/devices/d1/messages/events");
            var boundVariables = new Dictionary <string, string>
            {
                { "deviceid", "d1" }
            };
            var messageConverter = new AmqpMessageConverter();

            string content1 = "Message1 Contents ABC";
            string content2 = "Message2 Contents PQR";
            string content3 = "Message3 Contents XYZ";
            var    contents = new List <string>
            {
                content1,
                content2,
                content3
            };

            using (AmqpMessage amqpMessage = GetBatchedMessage(contents))
            {
                amqpMessage.MessageFormat = AmqpConstants.AmqpBatchedMessageFormat;
                ILinkHandler linkHandler = new EventsLinkHandler(amqpLink, requestUri, boundVariables, messageConverter);

                // Act
                await linkHandler.OpenAsync(TimeSpan.FromSeconds(30));

                // Assert
                Assert.NotNull(onMessageCallback);

                // Act
                onMessageCallback.Invoke(amqpMessage);

                // Assert
                await WaitAndAssert(
                    () =>
                {
                    if (receivedMessages == null)
                    {
                        return(false);
                    }
                    IList <IMessage> receivedMessagesList = receivedMessages.ToList();
                    Assert.Equal(contents.Count, receivedMessagesList.Count);

                    for (int i = 0; i < receivedMessagesList.Count; i++)
                    {
                        IMessage receivedMessage = receivedMessagesList[i];
                        string actualContents    = Encoding.UTF8.GetString(receivedMessage.Body);

                        Assert.Equal(contents[i], actualContents);
                        Assert.Equal($"{i}", receivedMessage.SystemProperties[SystemProperties.MessageId]);
                        Assert.Equal($"{i}", receivedMessage.Properties["MsgCnt"]);
                        Assert.Equal(contents[i], receivedMessage.Properties["MsgData"]);
                    }
                    return(true);
                },
                    TimeSpan.FromSeconds(5));
            }
        }
Ejemplo n.º 38
0
 public BrokerMessage(AmqpMessage message)
 {
     this.stream = (BufferListStream)message.ToStream();
     foreach (var buffer in message.RawByteBuffers) buffer.Clone();
     this.RawByteBuffers = message.RawByteBuffers;
 }
Ejemplo n.º 39
0
        public async Task SendMessageTest()
        {
            // Arrange
            var identity = Mock.Of <IIdentity>(i => i.Id == "d1");
            var amqpAuth = new AmqpAuthentication(true, Option.Some(Mock.Of <IClientCredentials>(c => c.Identity == identity)));

            IEnumerable <IMessage> receivedMessages = null;
            var deviceListener = Mock.Of <IDeviceListener>();

            Mock.Get(deviceListener).Setup(d => d.ProcessDeviceMessageBatchAsync(It.IsAny <IEnumerable <IMessage> >())).Callback <IEnumerable <IMessage> >(m => receivedMessages = m);

            var connectionHandler = Mock.Of <IConnectionHandler>(c => c.GetAmqpAuthentication() == Task.FromResult(amqpAuth) && c.GetDeviceListener() == Task.FromResult(deviceListener));
            var amqpConnection    = Mock.Of <IAmqpConnection>(c => c.FindExtension <IConnectionHandler>() == connectionHandler);
            var amqpSession       = Mock.Of <IAmqpSession>(s => s.Connection == amqpConnection);
            var amqpLink          = Mock.Of <IReceivingAmqpLink>(l => l.Session == amqpSession && l.IsReceiver && l.Settings == new AmqpLinkSettings() && l.State == AmqpObjectState.Opened);

            Action <AmqpMessage> onMessageCallback = null;

            Mock.Get(amqpLink).Setup(l => l.RegisterMessageListener(It.IsAny <Action <AmqpMessage> >())).Callback <Action <AmqpMessage> >(a => onMessageCallback = a);
            Mock.Get(amqpLink).SetupGet(l => l.Settings).Returns(new AmqpLinkSettings());
            Mock.Get(amqpLink).Setup(l => l.SafeAddClosed(It.IsAny <EventHandler>()));

            var requestUri     = new Uri("amqps://foo.bar/devices/d1/messages/events");
            var boundVariables = new Dictionary <string, string> {
                { "deviceid", "d1" }
            };
            var messageConverter = new AmqpMessageConverter();

            using (AmqpMessage amqpMessage = AmqpMessage.Create(new MemoryStream(new byte[] { 1, 2, 3, 4 }), false))
            {
                amqpMessage.ApplicationProperties.Map["Prop1"] = "Value1";
                amqpMessage.ApplicationProperties.Map["Prop2"] = "Value2";
                amqpMessage.Properties.ContentType             = "application/json";
                amqpMessage.Properties.ContentEncoding         = "utf-8";

                ILinkHandler linkHandler = new EventsLinkHandler(amqpLink, requestUri, boundVariables, messageConverter);

                // Act
                await linkHandler.OpenAsync(TimeSpan.FromSeconds(30));

                // Assert
                Assert.NotNull(onMessageCallback);

                // Act
                onMessageCallback.Invoke(amqpMessage);

                // Assert
                await WaitAndAssert(
                    () =>
                {
                    if (receivedMessages == null)
                    {
                        return(false);
                    }
                    IList <IMessage> receivedMessagesList = receivedMessages.ToList();
                    Assert.Equal(1, receivedMessagesList.Count);
                    Assert.Equal(receivedMessagesList[0].Properties["Prop1"], "Value1");
                    Assert.Equal(receivedMessagesList[0].Properties["Prop2"], "Value2");
                    Assert.Equal(receivedMessagesList[0].SystemProperties[SystemProperties.ContentEncoding], "utf-8");
                    Assert.Equal(receivedMessagesList[0].SystemProperties[SystemProperties.ContentType], "application/json");
                    Assert.Equal(receivedMessagesList[0].SystemProperties[SystemProperties.ConnectionDeviceId], "d1");
                    Assert.Equal(receivedMessagesList[0].Body, new byte[] { 1, 2, 3, 4 });
                    return(true);
                },
                    TimeSpan.FromSeconds(5));
            }
        }
Ejemplo n.º 40
0
            void OnMessage(AmqpMessage message)
            {
                Outcome outcome;
                if (message.ValueBody.Value is Declare)
                {
                    int txnId = this.CreateTransaction();
                    outcome = new Declared() { TxnId = new ArraySegment<byte>(BitConverter.GetBytes(txnId)) };
                }
                else if (message.ValueBody.Value is Discharge)
                {
                    Discharge discharge = (Discharge)message.ValueBody.Value;
                    int txnId = BitConverter.ToInt32(discharge.TxnId.Array, discharge.TxnId.Offset);
                    Transaction txn;
                    if (this.transactions.TryGetValue(txnId, out txn))
                    {
                        lock (this.transactions)
                        {
                            this.transactions.Remove(txnId);
                        }

                        txn.Discharge(discharge.Fail ?? false);
                        outcome = AmqpConstants.AcceptedOutcome;
                    }
                    else
                    {
                        outcome = new Rejected() { Error = new Error() { Condition = AmqpErrorCode.NotFound } };
                    }
                }
                else
                {
                    outcome = new Rejected() { Error = new Error() { Condition = AmqpErrorCode.NotAllowed } };
                }

                message.Link.DisposeDelivery(message, true, outcome);
            }
Ejemplo n.º 41
0
        /// <summary>
        ///   Sends an AMQP message that contains a batch of events to the associated Event Hub. If the size of events exceed the
        ///   maximum size of a single batch, an exception will be triggered and the send will fail.
        /// </summary>
        ///
        /// <param name="messageFactory">A factory which can be used to produce an AMQP message containing the batch of events to be sent.</param>
        /// <param name="partitionKey">The hashing key to use for influencing the partition to which events should be routed.</param>
        /// <param name="cancellationToken">An optional <see cref="CancellationToken"/> instance to signal the request to cancel the operation.</param>
        ///
        protected virtual async Task SendAsync(Func <AmqpMessage> messageFactory,
                                               string partitionKey,
                                               CancellationToken cancellationToken)
        {
            var failedAttemptCount = 0;
            var logPartition       = PartitionId ?? partitionKey;
            var operationId        = Guid.NewGuid().ToString("D", CultureInfo.InvariantCulture);
            var stopWatch          = ValueStopwatch.StartNew();

            TimeSpan?       retryDelay;
            SendingAmqpLink link;

            try
            {
                var tryTimeout = RetryPolicy.CalculateTryTimeout(0);

                while (!cancellationToken.IsCancellationRequested)
                {
                    try
                    {
                        using AmqpMessage batchMessage = messageFactory();

                        // Creation of the link happens without explicit knowledge of the cancellation token
                        // used for this operation; validate the token state before attempting link creation and
                        // again after the operation completes to provide best efforts in respecting it.

                        EventHubsEventSource.Log.EventPublishStart(EventHubName, logPartition, operationId);
                        cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>();

                        link = await SendLink.GetOrCreateAsync(UseMinimum(ConnectionScope.SessionTimeout, tryTimeout)).ConfigureAwait(false);

                        cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>();

                        // Validate that the batch of messages is not too large to send.  This is done after the link is created to ensure
                        // that the maximum message size is known, as it is dictated by the service using the link.

                        if (batchMessage.SerializedMessageSize > MaximumMessageSize)
                        {
                            throw new EventHubsException(EventHubName, string.Format(CultureInfo.CurrentCulture, Resources.MessageSizeExceeded, operationId, batchMessage.SerializedMessageSize, MaximumMessageSize), EventHubsException.FailureReason.MessageSizeExceeded);
                        }

                        // Attempt to send the message batch.

                        var deliveryTag = new ArraySegment <byte>(BitConverter.GetBytes(Interlocked.Increment(ref _deliveryCount)));
                        var outcome     = await link.SendMessageAsync(batchMessage, deliveryTag, AmqpConstants.NullBinary, tryTimeout.CalculateRemaining(stopWatch.GetElapsedTime())).ConfigureAwait(false);

                        cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>();

                        if (outcome.DescriptorCode != Accepted.Code)
                        {
                            throw AmqpError.CreateExceptionForError((outcome as Rejected)?.Error, EventHubName);
                        }

                        // The send operation should be considered successful; return to
                        // exit the retry loop.

                        return;
                    }
                    catch (Exception ex)
                    {
                        Exception activeEx = ex.TranslateServiceException(EventHubName);

                        // Determine if there should be a retry for the next attempt; if so enforce the delay but do not quit the loop.
                        // Otherwise, bubble the exception.

                        ++failedAttemptCount;
                        retryDelay = RetryPolicy.CalculateRetryDelay(activeEx, failedAttemptCount);

                        if ((retryDelay.HasValue) && (!ConnectionScope.IsDisposed) && (!cancellationToken.IsCancellationRequested))
                        {
                            EventHubsEventSource.Log.EventPublishError(EventHubName, logPartition, operationId, activeEx.Message);
                            await Task.Delay(retryDelay.Value, cancellationToken).ConfigureAwait(false);

                            tryTimeout = RetryPolicy.CalculateTryTimeout(failedAttemptCount);
                            stopWatch  = ValueStopwatch.StartNew();
                        }
                        else if (ex is AmqpException)
                        {
                            ExceptionDispatchInfo.Capture(activeEx).Throw();
                        }
                        else
                        {
                            throw;
                        }
                    }
                }

                // If no value has been returned nor exception thrown by this point,
                // then cancellation has been requested.

                throw new TaskCanceledException();
            }
            catch (TaskCanceledException)
            {
                throw;
            }
            catch (Exception ex)
            {
                EventHubsEventSource.Log.EventPublishError(EventHubName, logPartition, operationId, ex.Message);
                throw;
            }
            finally
            {
                EventHubsEventSource.Log.EventPublishComplete(EventHubName, logPartition, operationId, failedAttemptCount);
            }
        }
Ejemplo n.º 42
0
 public void AcceptMessage(AmqpMessage message, bool settled, bool batchable)
 {
     this.DisposeMessage(message, AmqpConstants.AcceptedOutcome, settled, batchable);
 }
        public static ServiceBusReceivedMessage AmqpMessageToSBMessage(AmqpMessage amqpMessage, bool isPeeked = false)
        {
            Argument.AssertNotNull(amqpMessage, nameof(amqpMessage));
            AmqpAnnotatedMessage annotatedMessage;

            if ((amqpMessage.BodyType & SectionFlag.Data) != 0 && amqpMessage.DataBody != null)
            {
                annotatedMessage = new AmqpAnnotatedMessage(amqpMessage.GetDataViaDataBody());
            }
            else
            {
                annotatedMessage = new AmqpAnnotatedMessage(new BinaryData[] { new BinaryData(Array.Empty <byte>()) });
            }
            ServiceBusReceivedMessage sbMessage = new ServiceBusReceivedMessage(annotatedMessage);

            SectionFlag sections = amqpMessage.Sections;

            if ((sections & SectionFlag.Header) != 0)
            {
                if (amqpMessage.Header.Ttl != null)
                {
                    annotatedMessage.Header.TimeToLive = TimeSpan.FromMilliseconds(amqpMessage.Header.Ttl.Value);
                }

                if (amqpMessage.Header.DeliveryCount != null)
                {
                    annotatedMessage.Header.DeliveryCount = isPeeked ? (amqpMessage.Header.DeliveryCount.Value) : (amqpMessage.Header.DeliveryCount.Value + 1);
                }
            }

            if ((sections & SectionFlag.Properties) != 0)
            {
                if (amqpMessage.Properties.MessageId != null)
                {
                    annotatedMessage.Properties.MessageId = amqpMessage.Properties.MessageId.ToString();
                }

                if (amqpMessage.Properties.CorrelationId != null)
                {
                    annotatedMessage.Properties.CorrelationId = amqpMessage.Properties.CorrelationId.ToString();
                }

                if (amqpMessage.Properties.ContentType.Value != null)
                {
                    annotatedMessage.Properties.ContentType = amqpMessage.Properties.ContentType.Value;
                }

                if (amqpMessage.Properties.Subject != null)
                {
                    annotatedMessage.Properties.Subject = amqpMessage.Properties.Subject;
                }

                if (amqpMessage.Properties.To != null)
                {
                    annotatedMessage.Properties.To = amqpMessage.Properties.To.ToString();
                }

                if (amqpMessage.Properties.ReplyTo != null)
                {
                    annotatedMessage.Properties.ReplyTo = amqpMessage.Properties.ReplyTo.ToString();
                }

                if (amqpMessage.Properties.GroupId != null)
                {
                    annotatedMessage.Properties.GroupId = amqpMessage.Properties.GroupId;
                }

                if (amqpMessage.Properties.ReplyToGroupId != null)
                {
                    annotatedMessage.Properties.ReplyToGroupId = amqpMessage.Properties.ReplyToGroupId;
                }
            }

            // Do application properties before message annotations, because the application properties
            // can be updated by entries from message annotation.
            if ((sections & SectionFlag.ApplicationProperties) != 0)
            {
                foreach (var pair in amqpMessage.ApplicationProperties.Map)
                {
                    if (TryGetNetObjectFromAmqpObject(pair.Value, MappingType.ApplicationProperty, out var netObject))
                    {
                        annotatedMessage.ApplicationProperties[pair.Key.ToString()] = netObject;
                    }
                }
            }

            if ((sections & SectionFlag.MessageAnnotations) != 0)
            {
                foreach (var pair in amqpMessage.MessageAnnotations.Map)
                {
                    var key = pair.Key.ToString();
                    switch (key)
                    {
                    case AmqpMessageConstants.EnqueuedTimeUtcName:
                        annotatedMessage.MessageAnnotations[AmqpMessageConstants.EnqueuedTimeUtcName] = (DateTime)pair.Value;
                        break;

                    case AmqpMessageConstants.ScheduledEnqueueTimeUtcName:
                        annotatedMessage.MessageAnnotations[AmqpMessageConstants.ScheduledEnqueueTimeUtcName] = (DateTime)pair.Value;
                        break;

                    case AmqpMessageConstants.SequenceNumberName:
                        annotatedMessage.MessageAnnotations[AmqpMessageConstants.SequenceNumberName] = (long)pair.Value;
                        break;

                    case AmqpMessageConstants.EnqueueSequenceNumberName:
                        annotatedMessage.MessageAnnotations[AmqpMessageConstants.EnqueueSequenceNumberName] = (long)pair.Value;
                        break;

                    case AmqpMessageConstants.LockedUntilName:
                        DateTimeOffset lockedUntil = (DateTime)pair.Value >= DateTimeOffset.MaxValue.UtcDateTime ?
                                                     DateTimeOffset.MaxValue : (DateTime)pair.Value;
                        annotatedMessage.MessageAnnotations[AmqpMessageConstants.LockedUntilName] = lockedUntil.UtcDateTime;
                        break;

                    case AmqpMessageConstants.PartitionKeyName:
                        annotatedMessage.MessageAnnotations[AmqpMessageConstants.PartitionKeyName] = (string)pair.Value;
                        break;

                    case AmqpMessageConstants.PartitionIdName:
                        annotatedMessage.MessageAnnotations[AmqpMessageConstants.PartitionIdName] = (short)pair.Value;
                        break;

                    case AmqpMessageConstants.ViaPartitionKeyName:
                        annotatedMessage.MessageAnnotations[AmqpMessageConstants.ViaPartitionKeyName] = (string)pair.Value;
                        break;

                    case AmqpMessageConstants.DeadLetterSourceName:
                        annotatedMessage.MessageAnnotations[AmqpMessageConstants.DeadLetterSourceName] = (string)pair.Value;
                        break;

                    default:
                        if (TryGetNetObjectFromAmqpObject(pair.Value, MappingType.ApplicationProperty, out var netObject))
                        {
                            annotatedMessage.MessageAnnotations[key] = netObject;
                        }
                        break;
                    }
                }
            }

            if (amqpMessage.DeliveryTag.Count == GuidSizeInBytes)
            {
                var guidBuffer = new byte[GuidSizeInBytes];
                Buffer.BlockCopy(amqpMessage.DeliveryTag.Array, amqpMessage.DeliveryTag.Offset, guidBuffer, 0, GuidSizeInBytes);
                sbMessage.LockTokenGuid = new Guid(guidBuffer);
            }

            amqpMessage.Dispose();

            return(sbMessage);
        }
Ejemplo n.º 44
0
 public void ReleaseMessage(AmqpMessage message)
 {
     this.DisposeMessage(message, AmqpConstants.ReleasedOutcome, true, false);
 }
Ejemplo n.º 45
0
 AmqpMessage PopulateAmqpMessageForSend(AmqpMessage message)
 {
     MessageConverter.UpdateAmqpMessageHeadersAndProperties(message, this);
     return(message);
 }
Ejemplo n.º 46
0
 public void DisposeMessage(AmqpMessage message, DeliveryState state, bool settled, bool batchable)
 {
     message.Batchable = batchable;
     this.DisposeDelivery(message, settled, state);
 }
        public static AmqpMessage SBMessageToAmqpMessage(SBMessage sbMessage)
        {
            var amqpMessage = sbMessage.Body == null?AmqpMessage.Create() : AmqpMessage.Create(new Data {
                Value = new ArraySegment <byte>(sbMessage.Body)
            });

            amqpMessage.Properties.MessageId      = sbMessage.MessageId;
            amqpMessage.Properties.CorrelationId  = sbMessage.CorrelationId;
            amqpMessage.Properties.ContentType    = sbMessage.ContentType;
            amqpMessage.Properties.Subject        = sbMessage.Label;
            amqpMessage.Properties.To             = sbMessage.To;
            amqpMessage.Properties.ReplyTo        = sbMessage.ReplyTo;
            amqpMessage.Properties.GroupId        = sbMessage.SessionId;
            amqpMessage.Properties.ReplyToGroupId = sbMessage.ReplyToSessionId;

            if (sbMessage.TimeToLive != TimeSpan.MaxValue)
            {
                amqpMessage.Header.Ttl = (uint)sbMessage.TimeToLive.TotalMilliseconds;
                amqpMessage.Properties.CreationTime = DateTime.UtcNow;

                if (AmqpConstants.MaxAbsoluteExpiryTime - amqpMessage.Properties.CreationTime.Value > sbMessage.TimeToLive)
                {
                    amqpMessage.Properties.AbsoluteExpiryTime = amqpMessage.Properties.CreationTime.Value + sbMessage.TimeToLive;
                }
                else
                {
                    amqpMessage.Properties.AbsoluteExpiryTime = AmqpConstants.MaxAbsoluteExpiryTime;
                }
            }

            if ((sbMessage.ScheduledEnqueueTimeUtc != null) && sbMessage.ScheduledEnqueueTimeUtc > DateTime.MinValue)
            {
                amqpMessage.MessageAnnotations.Map.Add(ScheduledEnqueueTimeUtcName, sbMessage.ScheduledEnqueueTimeUtc);
            }

            if (sbMessage.PartitionKey != null)
            {
                amqpMessage.MessageAnnotations.Map.Add(PartitionKeyName, sbMessage.PartitionKey);
            }

            if (sbMessage.ViaPartitionKey != null)
            {
                amqpMessage.MessageAnnotations.Map.Add(ViaPartitionKeyName, sbMessage.ViaPartitionKey);
            }

            if (sbMessage.UserProperties != null && sbMessage.UserProperties.Count > 0)
            {
                if (amqpMessage.ApplicationProperties == null)
                {
                    amqpMessage.ApplicationProperties = new ApplicationProperties();
                }

                foreach (var pair in sbMessage.UserProperties)
                {
                    if (TryGetAmqpObjectFromNetObject(pair.Value, MappingType.ApplicationProperty, out var amqpObject))
                    {
                        amqpMessage.ApplicationProperties.Map.Add(pair.Key, amqpObject);
                    }
                    else
                    {
                        throw new NotSupportedException(Resources.InvalidAmqpMessageProperty.FormatForUser(pair.Key.GetType()));
                    }
                }
            }

            return(amqpMessage);
        }
Ejemplo n.º 48
0
            public void Signal(AmqpMessage message, bool syncComplete)
            {
                IOThreadTimer t = this.timer;
                if (t != null)
                {
                    t.Cancel();
                }

                this.CompleteInternal(message, syncComplete);
            }
        public static SBMessage AmqpMessageToSBMessage(AmqpMessage amqpMessage)
        {
            if (amqpMessage == null)
            {
                throw Fx.Exception.ArgumentNull(nameof(amqpMessage));
            }

            SBMessage sbMessage;

            if ((amqpMessage.BodyType & SectionFlag.AmqpValue) != 0 &&
                amqpMessage.ValueBody.Value != null)
            {
                sbMessage = new SBMessage();

                if (TryGetNetObjectFromAmqpObject(amqpMessage.ValueBody.Value, MappingType.MessageBody, out var dotNetObject))
                {
                    sbMessage.SystemProperties.BodyObject = dotNetObject;
                }
                else
                {
                    sbMessage.SystemProperties.BodyObject = amqpMessage.ValueBody.Value;
                }
            }
            else if ((amqpMessage.BodyType & SectionFlag.Data) != 0 &&
                     amqpMessage.DataBody != null)
            {
                var dataSegments = new List <byte>();
                foreach (var data in amqpMessage.DataBody)
                {
                    if (data.Value is byte[] byteArrayValue)
                    {
                        dataSegments.AddRange(byteArrayValue);
                    }
                    else if (data.Value is ArraySegment <byte> arraySegmentValue)
                    {
                        byte[] byteArray;
                        if (arraySegmentValue.Count == arraySegmentValue.Array.Length)
                        {
                            byteArray = arraySegmentValue.Array;
                        }
                        else
                        {
                            byteArray = new byte[arraySegmentValue.Count];
                            Array.ConstrainedCopy(arraySegmentValue.Array, arraySegmentValue.Offset, byteArray, 0, arraySegmentValue.Count);
                        }
                        dataSegments.AddRange(byteArray);
                    }
                }
                sbMessage = new SBMessage(dataSegments.ToArray());
            }
            else
            {
                sbMessage = new SBMessage();
            }

            var sections = amqpMessage.Sections;

            if ((sections & SectionFlag.Header) != 0)
            {
                if (amqpMessage.Header.Ttl != null)
                {
                    sbMessage.TimeToLive = TimeSpan.FromMilliseconds(amqpMessage.Header.Ttl.Value);
                }

                if (amqpMessage.Header.DeliveryCount != null)
                {
                    sbMessage.SystemProperties.DeliveryCount = (int)(amqpMessage.Header.DeliveryCount.Value + 1);
                }
            }

            if ((sections & SectionFlag.Properties) != 0)
            {
                if (amqpMessage.Properties.MessageId != null)
                {
                    sbMessage.MessageId = amqpMessage.Properties.MessageId.ToString();
                }

                if (amqpMessage.Properties.CorrelationId != null)
                {
                    sbMessage.CorrelationId = amqpMessage.Properties.CorrelationId.ToString();
                }

                if (amqpMessage.Properties.ContentType.Value != null)
                {
                    sbMessage.ContentType = amqpMessage.Properties.ContentType.Value;
                }

                if (amqpMessage.Properties.Subject != null)
                {
                    sbMessage.Label = amqpMessage.Properties.Subject;
                }

                if (amqpMessage.Properties.To != null)
                {
                    sbMessage.To = amqpMessage.Properties.To.ToString();
                }

                if (amqpMessage.Properties.ReplyTo != null)
                {
                    sbMessage.ReplyTo = amqpMessage.Properties.ReplyTo.ToString();
                }

                if (amqpMessage.Properties.GroupId != null)
                {
                    sbMessage.SessionId = amqpMessage.Properties.GroupId;
                }

                if (amqpMessage.Properties.ReplyToGroupId != null)
                {
                    sbMessage.ReplyToSessionId = amqpMessage.Properties.ReplyToGroupId;
                }
            }

            // Do application properties before message annotations, because the application properties
            // can be updated by entries from message annotation.
            if ((sections & SectionFlag.ApplicationProperties) != 0)
            {
                foreach (var pair in amqpMessage.ApplicationProperties.Map)
                {
                    if (TryGetNetObjectFromAmqpObject(pair.Value, MappingType.ApplicationProperty, out var netObject))
                    {
                        sbMessage.UserProperties[pair.Key.ToString()] = netObject;
                    }
                }
            }

            if ((sections & SectionFlag.MessageAnnotations) != 0)
            {
                foreach (var pair in amqpMessage.MessageAnnotations.Map)
                {
                    var key = pair.Key.ToString();
                    switch (key)
                    {
                    case EnqueuedTimeUtcName:
                        sbMessage.SystemProperties.EnqueuedTimeUtc = (DateTime)pair.Value;
                        break;

                    case ScheduledEnqueueTimeUtcName:
                        sbMessage.ScheduledEnqueueTimeUtc = (DateTime)pair.Value;
                        break;

                    case SequenceNumberName:
                        sbMessage.SystemProperties.SequenceNumber = (long)pair.Value;
                        break;

                    case EnqueueSequenceNumberName:
                        sbMessage.SystemProperties.EnqueuedSequenceNumber = (long)pair.Value;
                        break;

                    case LockedUntilName:
                        sbMessage.SystemProperties.LockedUntilUtc = (DateTime)pair.Value;
                        break;

                    case PartitionKeyName:
                        sbMessage.PartitionKey = (string)pair.Value;
                        break;

                    case PartitionIdName:
                        sbMessage.SystemProperties.PartitionId = (short)pair.Value;
                        break;

                    case ViaPartitionKeyName:
                        sbMessage.ViaPartitionKey = (string)pair.Value;
                        break;

                    case DeadLetterSourceName:
                        sbMessage.SystemProperties.DeadLetterSource = (string)pair.Value;
                        break;

                    default:
                        if (TryGetNetObjectFromAmqpObject(pair.Value, MappingType.ApplicationProperty, out var netObject))
                        {
                            sbMessage.UserProperties[key] = netObject;
                        }
                        break;
                    }
                }
            }

            if (amqpMessage.DeliveryTag.Count == GuidSize)
            {
                var guidBuffer = new byte[GuidSize];
                Buffer.BlockCopy(amqpMessage.DeliveryTag.Array, amqpMessage.DeliveryTag.Offset, guidBuffer, 0, GuidSize);
                sbMessage.SystemProperties.LockTokenGuid = new Guid(guidBuffer);
            }

            amqpMessage.Dispose();

            return(sbMessage);
        }
Ejemplo n.º 50
0
 public Task<Outcome> SendMessageAsync(AmqpMessage message, ArraySegment<byte> deliveryTag, ArraySegment<byte> txnId, TimeSpan timeout)
 {
     return this.sender.SendMessageAsync(message, deliveryTag, txnId, timeout);
 }
        public static AmqpMessage BatchSBMessagesAsAmqpMessage(IEnumerable <SBMessage> sbMessages)
        {
            if (sbMessages == null)
            {
                throw Fx.Exception.ArgumentNull(nameof(sbMessages));
            }

            AmqpMessage amqpMessage;
            AmqpMessage firstAmqpMessage = null;
            SBMessage   firstMessage     = null;
            List <Data> dataList         = null;
            var         messageCount     = 0;

            foreach (var sbMessage in sbMessages)
            {
                messageCount++;

                amqpMessage = AmqpMessageConverter.SBMessageToAmqpMessage(sbMessage);
                if (firstAmqpMessage == null)
                {
                    firstAmqpMessage = amqpMessage;
                    firstMessage     = sbMessage;
                    continue;
                }

                if (dataList == null)
                {
                    dataList = new List <Data> {
                        ToData(firstAmqpMessage)
                    };
                }

                dataList.Add(ToData(amqpMessage));
            }

            if (messageCount == 1 && firstAmqpMessage != null)
            {
                firstAmqpMessage.Batchable = true;
                return(firstAmqpMessage);
            }

            amqpMessage = AmqpMessage.Create(dataList);
            amqpMessage.MessageFormat = AmqpConstants.AmqpBatchedMessageFormat;

            if (firstMessage.MessageId != null)
            {
                amqpMessage.Properties.MessageId = firstMessage.MessageId;
            }
            if (firstMessage.SessionId != null)
            {
                amqpMessage.Properties.GroupId = firstMessage.SessionId;
            }

            if (firstMessage.PartitionKey != null)
            {
                amqpMessage.MessageAnnotations.Map[AmqpMessageConverter.PartitionKeyName] =
                    firstMessage.PartitionKey;
            }

            if (firstMessage.ViaPartitionKey != null)
            {
                amqpMessage.MessageAnnotations.Map[AmqpMessageConverter.ViaPartitionKeyName] =
                    firstMessage.ViaPartitionKey;
            }

            amqpMessage.Batchable = true;
            return(amqpMessage);
        }
Ejemplo n.º 52
0
       async Task<Outcome> SendAmqpMessageAsync(AmqpMessage amqpMessage)
       {
            Outcome outcome;
            try
            {
                SendingAmqpLink eventSendingLink = await this.GetEventSendingLinkAsync();
                outcome = await eventSendingLink.SendMessageAsync(amqpMessage, IotHubConnection.GetNextDeliveryTag(ref this.eventsDeliveryTag), AmqpConstants.NullBinary, this.OperationTimeout);
            }
            catch (Exception exception)
            {
                if (exception.IsFatal())
                {
                    throw;
                }

                throw AmqpClientHelper.ToIotHubClientContract(exception);
            }

            return outcome;
       } 
        /// <summary>
        ///   Retrieves information about a specific partition for an Event Hub, including elements that describe the available
        ///   events in the partition event stream.
        /// </summary>
        ///
        /// <param name="partitionId">The unique identifier of a partition associated with the Event Hub.</param>
        /// <param name="retryPolicy">The retry policy to use as the basis for retrieving the information.</param>
        /// <param name="cancellationToken">An optional <see cref="CancellationToken"/> instance to signal the request to cancel the operation.</param>
        ///
        /// <returns>The set of information for the requested partition under the Event Hub this client is associated with.</returns>
        ///
        public override async Task <PartitionProperties> GetPartitionPropertiesAsync(string partitionId,
                                                                                     EventHubsRetryPolicy retryPolicy,
                                                                                     CancellationToken cancellationToken)
        {
            Argument.AssertNotClosed(_closed, nameof(AmqpClient));
            Argument.AssertNotNullOrEmpty(partitionId, nameof(partitionId));
            Argument.AssertNotNull(retryPolicy, nameof(retryPolicy));

            var failedAttemptCount = 0;
            var retryDelay         = default(TimeSpan?);
            var token = default(string);
            var link  = default(RequestResponseAmqpLink);

            var stopWatch = Stopwatch.StartNew();

            try
            {
                var tryTimeout = retryPolicy.CalculateTryTimeout(0);

                while (!cancellationToken.IsCancellationRequested)
                {
                    try
                    {
                        EventHubsEventSource.Log.GetPartitionPropertiesStart(EventHubName, partitionId);

                        // Create the request message and the management link.

                        token = await AquireAccessTokenAsync(cancellationToken).ConfigureAwait(false);

                        using AmqpMessage request = MessageConverter.CreatePartitionPropertiesRequest(EventHubName, partitionId, token);
                        cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>();

                        link = await ManagementLink.GetOrCreateAsync(UseMinimum(ConnectionScope.SessionTimeout, tryTimeout.CalculateRemaining(stopWatch.Elapsed))).ConfigureAwait(false);

                        cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>();

                        // Send the request and wait for the response.

                        using AmqpMessage response = await link.RequestAsync(request, tryTimeout.CalculateRemaining(stopWatch.Elapsed)).ConfigureAwait(false);

                        cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>();
                        stopWatch.Stop();

                        // Process the response.

                        AmqpError.ThrowIfErrorResponse(response, EventHubName);
                        return(MessageConverter.CreatePartitionPropertiesFromResponse(response));
                    }
                    catch (Exception ex)
                    {
                        // Determine if there should be a retry for the next attempt; if so enforce the delay but do not quit the loop.
                        // Otherwise, mark the exception as active and break out of the loop.

                        ++failedAttemptCount;
                        retryDelay = retryPolicy.CalculateRetryDelay(ex, failedAttemptCount);

                        if ((retryDelay.HasValue) && (!ConnectionScope.IsDisposed) && (!cancellationToken.IsCancellationRequested))
                        {
                            EventHubsEventSource.Log.GetPartitionPropertiesError(EventHubName, partitionId, ex.Message);
                            await Task.Delay(retryDelay.Value, cancellationToken).ConfigureAwait(false);

                            tryTimeout = retryPolicy.CalculateTryTimeout(failedAttemptCount);
                            stopWatch.Reset();
                        }
                        else
                        {
                            throw;
                        }
                    }
                }

                // If no value has been returned nor exception thrown by this point,
                // then cancellation has been requested.

                throw new TaskCanceledException();
            }
            catch (Exception ex)
            {
                EventHubsEventSource.Log.GetPartitionPropertiesError(EventHubName, partitionId, ex.Message);
                throw;
            }
            finally
            {
                stopWatch.Stop();
                EventHubsEventSource.Log.GetPartitionPropertiesComplete(EventHubName, partitionId);
            }
        }
Ejemplo n.º 54
0
        /// <summary>
        /// Copies the properties from the amqp message to the Message instance.
        /// </summary>
        public static void UpdateMessageHeaderAndProperties(AmqpMessage amqpMessage, Message data)
        {
            Fx.AssertAndThrow(amqpMessage.DeliveryTag != null, "AmqpMessage should always contain delivery tag.");
            data.DeliveryTag = amqpMessage.DeliveryTag;

            SectionFlag sections = amqpMessage.Sections;
            if ((sections & SectionFlag.Properties) != 0)
            {
                // Extract only the Properties that we support
                data.MessageId = amqpMessage.Properties.MessageId != null ? amqpMessage.Properties.MessageId.ToString() : null;
                data.To = amqpMessage.Properties.To != null ? amqpMessage.Properties.To.ToString() : null;

                if (amqpMessage.Properties.AbsoluteExpiryTime.HasValue)
                {
                    data.ExpiryTimeUtc = amqpMessage.Properties.AbsoluteExpiryTime.Value;
                }

                data.CorrelationId = amqpMessage.Properties.CorrelationId != null ? amqpMessage.Properties.CorrelationId.ToString() : null;
                data.UserId = amqpMessage.Properties.UserId.Array != null ? Encoding.UTF8.GetString(amqpMessage.Properties.UserId.Array) : null;
            }

            if ((sections & SectionFlag.MessageAnnotations) != 0)
            {
                string lockToken;
                if (amqpMessage.MessageAnnotations.Map.TryGetValue(LockTokenName, out lockToken))
                {
                    data.LockToken = lockToken;
                }

                ulong sequenceNumber;
                if (amqpMessage.MessageAnnotations.Map.TryGetValue(SequenceNumberName, out sequenceNumber))
                {
                    data.SequenceNumber = sequenceNumber;
                }

                DateTime enqueuedTime;
                if (amqpMessage.MessageAnnotations.Map.TryGetValue(MessageSystemPropertyNames.EnqueuedTime, out enqueuedTime))
                {
                    data.EnqueuedTimeUtc = enqueuedTime;
                }

                byte deliveryCount;
                if (amqpMessage.MessageAnnotations.Map.TryGetValue(MessageSystemPropertyNames.DeliveryCount, out deliveryCount))
                {
                    data.DeliveryCount = deliveryCount;
                }
            }

            if ((sections & SectionFlag.ApplicationProperties) != 0)
            {
                foreach (KeyValuePair<MapKey, object> pair in amqpMessage.ApplicationProperties.Map)
                {
                    object netObject = null;
                    if (TryGetNetObjectFromAmqpObject(pair.Value, MappingType.ApplicationProperty, out netObject))
                    {
                        var stringObject = netObject as string;
                        
                        if (stringObject != null)
                        {
                            switch (pair.Key.ToString())
                            {
                                case MessageSystemPropertyNames.Operation:
                                    data.SystemProperties[pair.Key.ToString()] = stringObject;
                                    break;
                                default:
                                    data.Properties[pair.Key.ToString()] = stringObject;
                                    break;
                            }
                        }
                        else
                        {
                            // TODO: RDBug 4093369 Handling of non-string property values in Amqp messages
                            // Drop non-string properties and log an error
                            Fx.Exception.TraceHandled(new InvalidDataException("IotHub does not accept non-string Amqp properties"), "MessageConverter.UpdateMessageHeaderAndProperties");
                        }                        
                    }
                }
            }
        }
Ejemplo n.º 55
0
        protected override async Task OnSendAsync(IEnumerable <EventData> eventDatas, string partitionKey)
        {
            bool shouldRetry;
            int  retryCount = 0;

            var timeoutHelper = new TimeoutHelper(this.EventHubClient.ConnectionStringBuilder.OperationTimeout, startTimeout: true);

            do
            {
                using (AmqpMessage amqpMessage = AmqpMessageConverter.EventDatasToAmqpMessage(eventDatas, partitionKey))
                {
                    shouldRetry = false;

                    try
                    {
                        try
                        {
                            // Always use default timeout for AMQP sesssion.
                            var amqpLink = await this.SendLinkManager.GetOrCreateAsync(
                                TimeSpan.FromSeconds(AmqpClientConstants.AmqpSessionTimeoutInSeconds)).ConfigureAwait(false);

                            if (amqpLink.Settings.MaxMessageSize.HasValue)
                            {
                                ulong size = (ulong)amqpMessage.SerializedMessageSize;
                                if (size > amqpLink.Settings.MaxMessageSize.Value)
                                {
                                    throw new MessageSizeExceededException(amqpMessage.DeliveryId.Value, size, amqpLink.Settings.MaxMessageSize.Value);
                                }
                            }

                            Outcome outcome = await amqpLink.SendMessageAsync(
                                amqpMessage,
                                this.GetNextDeliveryTag(),
                                AmqpConstants.NullBinary,
                                timeoutHelper.RemainingTime()).ConfigureAwait(false);

                            if (outcome.DescriptorCode != Accepted.Code)
                            {
                                Rejected rejected = (Rejected)outcome;
                                throw new AmqpException(rejected.Error);
                            }
                        }
                        catch (AmqpException amqpException)
                        {
                            throw AmqpExceptionHelper.ToMessagingContract(amqpException.Error);
                        }
                    }
                    catch (Exception ex)
                    {
                        // Evaluate retry condition?
                        TimeSpan?retryInterval = this.RetryPolicy.GetNextRetryInterval(ex, timeoutHelper.RemainingTime(), ++retryCount);
                        if (retryInterval != null && !this.EventHubClient.CloseCalled)
                        {
                            await Task.Delay(retryInterval.Value).ConfigureAwait(false);

                            shouldRetry = true;
                        }
                        else
                        {
                            throw;
                        }
                    }
                }
            } while (shouldRetry);
        }