예제 #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="fromSequenceNumber"></param>
        /// <param name="maxMessages"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        internal async IAsyncEnumerable <ServiceBusMessage> PeekRangeBySequenceInternal(
            long?fromSequenceNumber,
            int maxMessages = 1,
            [EnumeratorCancellation]
            CancellationToken cancellationToken = default)
        {
            RetriableContext  context    = CreateRetriableContext(cancellationToken);
            ReceivingAmqpLink openedLink =
                await context.RunOperation(
                    async() => await Consumer.ReceiveLink.GetOrCreateAsync(context.TimeSpan)
                    .ConfigureAwait(false))
                .ConfigureAwait(false);

            var source = (Source)openedLink.Settings.Source;

            if (source.FilterSet.TryGetValue <string>(AmqpClientConstants.SessionFilterName, out var tempSessionId))
            {
                // If one of the constructors not accepting a SessionId was used, the broker will determine which session to send messages from.
                SessionId = tempSessionId;
            }
            IAsyncEnumerable <ServiceBusMessage> ret = PeekRangeBySequenceInternal(
                fromSequenceNumber: fromSequenceNumber,
                maxMessages: maxMessages,
                sessionId: SessionId,
                cancellationToken: cancellationToken);

            await foreach (ServiceBusMessage msg in ret.ConfigureAwait(false))
            {
                yield return(msg);
            }
        }
예제 #2
0
        private static void StartReceiver()
        {
            Task.Run(async() => {
                var tfactory   = new AmqpConnectionFactory();
                var connection = await tfactory.OpenConnectionAsync("amqp://localhost:5672", TimeSpan.FromSeconds(10));

                var session = connection.CreateSession(new AmqpSessionSettings());

                var receicerSettings = new AmqpLinkSettings
                {
                    LinkName        = $"receiver-{DateTime.UtcNow.Ticks}",
                    Role            = true,
                    TotalLinkCredit = 300,
                    Source          = new Source
                    {
                        Address = QueueName,
                    },
                    Target = new Target()
                };

                var receiver = new ReceivingAmqpLink(session, receicerSettings);

                while (true)
                {
                    AmqpMessage message = await receiver.ReceiveMessageAsync(TimeSpan.FromSeconds(20));

                    if (message != null)
                    {
                        receiver.DisposeDelivery(message, true, AmqpConstants.AcceptedOutcome);
                        DisplayMessage(new StreamReader(message.BodyStream).ReadToEnd());
                    }
                }
            });
        }
예제 #3
0
파일: TheClient.cs 프로젝트: Bigsby/PoC
        public static void Start()
        {
            try
            {
                var connection = AmqpConnection.Factory.OpenConnectionAsync("amqp://localhost:5672/").Result;

                var sessionSettings = new AmqpSessionSettings
                {
                };
                //AmqpSessionSettings.Create(new Begin())
                var session = connection.CreateSession(sessionSettings);

                var linkSettings = new AmqpLinkSettings
                {
                    LinkName = "theExchange",
                    Handle   = 1234,
                    Role     = false,
                    Source   = new Source
                    {
                        Address = "theQueue",
                        Durable = 1
                    }
                };
                var receiver = new ReceivingAmqpLink(session, linkSettings);

                receiver.RegisterMessageListener(message =>
                {
                    var stop = "here";
                });
            }
            catch (System.Exception ex)
            {
                var s = ex.Message;
            }
        }
예제 #4
0
        async Task <ReceivingAmqpLink> CreateTwinReceivingLinkAsync(TimeSpan timeout, CancellationToken cancellationToken)
        {
            string path = string.Format(CultureInfo.InvariantCulture, CommonConstants.DeviceTwinPathTemplate, System.Net.WebUtility.UrlEncode(this.deviceId));

            ReceivingAmqpLink twinReceivingLink = await this.IotHubConnection.CreateReceivingLinkAsync(path, this.iotHubConnectionString, this.twinConnectionCorrelationId, IotHubConnection.ReceivingLinkType.Twin, this.prefetchCount, timeout, cancellationToken);

            MyStringCopy(twinReceivingLink.Name, out twinReceivingLinkName);
            this.SafeAddClosedTwinReceivingLinkHandler = this.linkClosedListener;
            twinReceivingLink.SafeAddClosed(async(o, ea) =>
                                            await Task.Run(async() =>
            {
                await this.SafeAddClosedTwinReceivingLinkHandler(
                    o,
                    new ConnectionEventArgs
                {
                    ConnectionType               = ConnectionType.AmqpTwinReceiving,
                    ConnectionStatus             = ConnectionStatus.Disconnected_Retrying,
                    ConnectionStatusChangeReason = ConnectionStatusChangeReason.No_Network
                });
            }
                                                           ));

            twinReceivingLink.RegisterMessageListener(message => this.HandleTwinMessage(message, twinReceivingLink));

            return(twinReceivingLink);
        }
예제 #5
0
        public async Task EnableEventReceiveAsync(TimeSpan timeout)
        {
            if (Logging.IsEnabled)
            {
                Logging.Enter(this, timeout, $"{nameof(EnableEventReceiveAsync)}");
            }

            try
            {
                Debug.Assert(_eventReceivingLink == null);
                _eventReceivingLink = await AmqpLinkHelper.OpenEventsReceiverLinkAsync(
                    _deviceIdentity,
                    _amqpSession,
                    timeout
                    ).ConfigureAwait(false);

                _eventReceivingLink.RegisterMessageListener(OnEventsReceived);
                _eventReceivingLink.Closed += OnLinkDisconnected;

                if (Logging.IsEnabled)
                {
                    Logging.Associate(this, this, _eventReceivingLink, $"{nameof(EnableEventReceiveAsync)}");
                }
            }
            finally
            {
                if (Logging.IsEnabled)
                {
                    Logging.Exit(this, timeout, $"{nameof(EnableEventReceiveAsync)}");
                }
            }
        }
예제 #6
0
        private async Task EnsureReceivingLinkIsOpenedAsync(TimeSpan timeout)
        {
            if (Volatile.Read(ref _messageReceivingLink) != null) return;

            if (Logging.IsEnabled) Logging.Enter(this, timeout, $"{nameof(EnsureReceivingLinkIsOpenedAsync)}");

            try
            {
                await _messageReceivingLinkLock.WaitAsync().ConfigureAwait(false);
                if (_messageReceivingLink != null) return;

                _messageReceivingLink = await AmqpLinkHelper.OpenTelemetryReceiverLinkAsync(
                    _deviceIdentity,
                    _amqpSession,
                    timeout
                ).ConfigureAwait(false);

                _messageReceivingLink.Closed += OnLinkDisconnected;
                if (Logging.IsEnabled) Logging.Associate(this, this, _messageReceivingLink, $"{nameof(EnsureReceivingLinkIsOpenedAsync)}");
            }
            finally
            {
                _messageReceivingLinkLock.Release();
                if (Logging.IsEnabled) Logging.Exit(this, timeout, $"{nameof(EnsureReceivingLinkIsOpenedAsync)}");
            }
        }
예제 #7
0
        /// <summary>
        ///   Closes the AMQP link used by the consumer, capturing the passive terminal exception that triggered
        ///   closing if it should be surfaced during the next requested operation.
        /// </summary>
        ///
        protected void CloseConsumerLink(ReceivingAmqpLink link)
        {
            // If there is no link, then no action needs to be
            // taken.

            if (link == null)
            {
                return;
            }

            // If the consumer is being closed, the sentinel variable will already be set, and
            // the terminal exception need not be considered.

            if (!_closed)
            {
                var linkException = GetTerminalException(link);

                // If the terminal exception indicates that the partition was stolen from the consumer,
                // capture it so that it can be surfaced when the next operation is requested.

                if (linkException.IsConsumerPartitionStolenException())
                {
                    EventHubsEventSource.Log.AmqpConsumerLinkFaultCapture(EventHubName, ConsumerGroup, PartitionId, linkException.Message);
                    _activePartitionStolenException = linkException;
                }
            }

            // Close the link and it's associated session.

            link.Session?.SafeClose();
            link.SafeClose();

            EventHubsEventSource.Log.FaultTolerantAmqpObjectClose(nameof(ReceivingAmqpLink), "", EventHubName, ConsumerGroup, PartitionId, link.TerminalException?.Message);
        }
예제 #8
0
        async Task <ReceivingAmqpLink> CreateLinkAsync(TimeSpan timeout)
        {
            FilterSet filterMap = null;

            MessagingEventSource.Log.AmqpReceiveLinkCreateStart(this.ClientId, false, this.EntityType, this.Path);

            if (this.isSessionReceiver)
            {
                filterMap = new FilterSet {
                    { AmqpClientConstants.SessionFilterName, this.sessionId }
                };
            }

            AmqpLinkSettings linkSettings = new AmqpLinkSettings
            {
                Role            = true,
                TotalLinkCredit = (uint)this.PrefetchCount,
                AutoSendFlow    = this.PrefetchCount > 0,
                Source          = new Source {
                    Address = this.Path, FilterSet = filterMap
                },
                SettleType = (this.ReceiveMode == ReceiveMode.PeekLock) ? SettleMode.SettleOnDispose : SettleMode.SettleOnSend
            };

            linkSettings.AddProperty(AmqpClientConstants.EntityTypeName, (int)this.EntityType);
            linkSettings.AddProperty(AmqpClientConstants.TimeoutName, (uint)timeout.TotalMilliseconds);

            AmqpSendReceiveLinkCreator sendReceiveLinkCreator = new AmqpSendReceiveLinkCreator(this.Path, this.ServiceBusConnection, new[] { ClaimConstants.Listen }, this.CbsTokenProvider, linkSettings);
            ReceivingAmqpLink          receivingAmqpLink      = (ReceivingAmqpLink)await sendReceiveLinkCreator.CreateAndOpenAmqpLinkAsync().ConfigureAwait(false);

            MessagingEventSource.Log.AmqpReceiveLinkCreateStop(this.ClientId);

            return(receivingAmqpLink);
        }
예제 #9
0
        public override async Task <Message> ReceiveAsync(TimeSpan timeout, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            Message message = null;

            AmqpMessage amqpMessage;

            try
            {
                ReceivingAmqpLink deviceBoundReceivingLink = await this.GetDeviceBoundReceivingLinkAsync(cancellationToken).ConfigureAwait(false);

                amqpMessage = await deviceBoundReceivingLink.ReceiveMessageAsync(timeout).ConfigureAwait(false);
            }
            catch (Exception exception) when(!exception.IsFatal() && !(exception is OperationCanceledException))
            {
                throw AmqpClientHelper.ToIotHubClientContract(exception);
            }

            if (amqpMessage != null)
            {
                message = new Message(amqpMessage)
                {
                    LockToken = new Guid(amqpMessage.DeliveryTag.Array).ToString()
                };
            }
            else
            {
                message = null;
            }

            return(message);
        }
예제 #10
0
        public async Task DisableMethodsAsync(TimeSpan timeout)
        {
            if (Logging.IsEnabled) Logging.Enter(this, timeout, $"{nameof(DisableMethodsAsync)}");

            Debug.Assert(_methodSendingLink != null);
            Debug.Assert(_methodReceivingLink != null);

            try
            {
                ICollection<Task> tasks = new List<Task>();
                if (_methodReceivingLink != null)
                {
                    tasks.Add(_methodReceivingLink.CloseAsync(timeout));
                }

                if (_methodSendingLink != null)
                {
                    tasks.Add(_methodSendingLink.CloseAsync(timeout));
                }

                if (tasks.Count > 0)
                {
                    await Task.WhenAll(tasks).ConfigureAwait(false);
                    _methodReceivingLink = null;
                    _methodSendingLink = null;
                }
            }
            finally
            {
                if (Logging.IsEnabled) Logging.Exit(this, timeout, $"{nameof(DisableMethodsAsync)}");
            }
        }
        private async Task EnableReceivingLinkAsync(CancellationToken cancellationToken)
        {
            ReceivingAmqpLink methodReceivingLink = await this.GetMethodReceivingLinkAsync(cancellationToken);

            this.SafeAddClosedReceivingLinkHandler = this.linkClosedListener;
            methodReceivingLink.SafeAddClosed((o, ea) => this.SafeAddClosedReceivingLinkHandler(o, ea));
        }
예제 #12
0
        public DuplexAmqpLink(AmqpSession session, AmqpLinkSettings settings)
            : base("duplex")
        {
            AmqpTrace.Provider.AmqpLogOperationInformational(this, TraceOperation.Create, "Create");

            var senderSettings = new AmqpLinkSettings
            {
                Role = false,
                LinkName = settings.LinkName + ":out",
                SettleType = settings.SettleType,
                Source = new Source(),
                TotalLinkCredit = settings.TotalLinkCredit,
                AutoSendFlow = settings.AutoSendFlow,
                Target = settings.Target,
                Properties = settings.Properties
            };
            this.sender = new SendingAmqpLink(session, senderSettings);

            var receiverSettings = new AmqpLinkSettings
            {
                Role = true,
                LinkName = settings.LinkName + ":in",
                SettleType = settings.SettleType,
                Source = settings.Source,
                TotalLinkCredit = settings.TotalLinkCredit,
                AutoSendFlow = settings.AutoSendFlow,
                Target = new Target(),
                Properties = settings.Properties
            };
            this.receiver = new ReceivingAmqpLink(session, receiverSettings);
            this.receiver.SetTotalLinkCredit(receiverSettings.TotalLinkCredit, true); // WHY set both here AND on settings? Follow up with Xin.

            this.sender.SafeAddClosed(this.OnLinkClosed);
            this.receiver.SafeAddClosed(this.OnLinkClosed);
        }
        internal static async Task DisposeMessageAsync(FaultTolerantAmqpObject <ReceivingAmqpLink> faultTolerantReceivingLink, string lockToken, Outcome outcome, bool batchable)
        {
            var deliveryTag = IotHubConnection.ConvertToDeliveryTag(lockToken);

            Outcome disposeOutcome;

            try
            {
                ReceivingAmqpLink deviceBoundReceivingLink = await faultTolerantReceivingLink.GetReceivingLinkAsync().ConfigureAwait(false);

                disposeOutcome = await deviceBoundReceivingLink.DisposeMessageAsync(deliveryTag, outcome, batchable, IotHubConnection.DefaultOperationTimeout).ConfigureAwait(false);
            }
            catch (Exception exception)
            {
                if (exception.IsFatal())
                {
                    throw;
                }

                throw AmqpClientHelper.ToIotHubClientContract(exception);
            }

            if (disposeOutcome.DescriptorCode != Accepted.Code)
            {
                throw AmqpErrorMapper.GetExceptionFromOutcome(disposeOutcome);
            }
        }
예제 #14
0
        public AmqpLink CreateLink(AmqpSession session, AmqpLinkSettings settings)
        {
            bool     isReceiver = settings.Role.Value;
            AmqpLink link;

            if (isReceiver)
            {
                if (settings.Target is Target && ((Target)settings.Target).Dynamic())
                {
                    string name = string.Format("$dynamic.{0}", Interlocked.Increment(ref this.dynamicId));
                    this.queues.Add(name, new TestQueue(this));
                    ((Target)settings.Target).Address = name;
                }

                link = new ReceivingAmqpLink(session, settings);
            }
            else
            {
                if (((Source)settings.Source).Dynamic())
                {
                    string name = string.Format("$dynamic.{0}", Interlocked.Increment(ref this.dynamicId));
                    this.queues.Add(name, new TestQueue(this));
                    ((Source)settings.Source).Address = name;
                }

                link = new SendingAmqpLink(session, settings);
            }

            return(link);
        }
        async Task DisposeMessageAsync(string lockToken, Outcome outcome)
        {
            var deliveryTag = IotHubConnection.ConvertToDeliveryTag(lockToken);

            Outcome disposeOutcome;

            try
            {
                ReceivingAmqpLink deviceBoundReceivingLink = await this.GetReceivingLinkAsync();

                disposeOutcome = await deviceBoundReceivingLink.DisposeMessageAsync(deliveryTag, outcome, batchable : true, timeout : this.OperationTimeout);
            }
            catch (Exception exception)
            {
                if (exception.IsFatal())
                {
                    throw;
                }

                throw AmqpClientHelper.ToIotHubClientContract(exception);
            }

            if (disposeOutcome.DescriptorCode != Accepted.Code)
            {
                throw AmqpErrorMapper.GetExceptionFromOutcome(disposeOutcome);
            }
        }
예제 #16
0
        public override async Task <FileNotification> ReceiveAsync(TimeSpan timeout)
        {
            try
            {
                ReceivingAmqpLink receivingLink = await this.faultTolerantReceivingLink.GetReceivingLinkAsync();

                AmqpMessage amqpMessage = await receivingLink.ReceiveMessageAsync(timeout);

                if (amqpMessage != null)
                {
                    using (amqpMessage)
                    {
                        AmqpClientHelper.ValidateContentType(amqpMessage, CommonConstants.FileNotificationContentType);

                        var fileNotification = await AmqpClientHelper.GetObjectFromAmqpMessageAsync <FileNotification>(amqpMessage);

                        fileNotification.LockToken = new Guid(amqpMessage.DeliveryTag.Array).ToString();

                        return(fileNotification);
                    }
                }

                return(null);
            }
            catch (Exception exception)
            {
                if (exception.IsFatal())
                {
                    throw;
                }

                throw AmqpClientHelper.ToIotHubClientContract(exception);
            }
        }
예제 #17
0
        async Task <ReceivingAmqpLink> CreateMethodReceivingLinkAsync(TimeSpan timeout, CancellationToken cancellationToken)
        {
            string path = string.Format(CultureInfo.InvariantCulture, CommonConstants.DeviceMethodPathTemplate, System.Net.WebUtility.UrlEncode(this.deviceId));

            ReceivingAmqpLink methodReceivingLink = await this.IotHubConnection.CreateReceivingLinkAsync(path, this.iotHubConnectionString, this.methodConnectionCorrelationId, IotHubConnection.ReceivingLinkType.Methods, this.prefetchCount, timeout, cancellationToken);

            methodReceivingLink.RegisterMessageListener(amqpMessage =>
            {
                MethodRequestInternal methodRequestInternal = MethodConverter.ConstructMethodRequestFromAmqpMessage(amqpMessage);
                methodReceivingLink.DisposeDelivery(amqpMessage, true, AmqpConstants.AcceptedOutcome);
                this.messageListener(methodRequestInternal);
            });

            MyStringCopy(methodReceivingLink.Name, out methodReceivingLinkName);
            this.SafeAddClosedMethodReceivingLinkHandler = this.linkClosedListener;
            methodReceivingLink.SafeAddClosed(async(o, ea) =>
                                              await Task.Run(async() =>
            {
                await this.SafeAddClosedMethodReceivingLinkHandler(
                    o,
                    new ConnectionEventArgs
                {
                    ConnectionType               = ConnectionType.AmqpMethodReceiving,
                    ConnectionStatus             = ConnectionStatus.Disconnected_Retrying,
                    ConnectionStatusChangeReason = ConnectionStatusChangeReason.No_Network
                });
            }
                                                             ));

            return(methodReceivingLink);
        }
예제 #18
0
        private void HandleTwinMessage(AmqpMessage message, ReceivingAmqpLink link)
        {
            link.DisposeDelivery(message, true, AmqpConstants.AcceptedOutcome);

            string correlationId = message.Properties?.CorrelationId?.ToString();

            if (correlationId != null)
            {
                // If we have a correlation id, it must be a response, complete the task.
                TaskCompletionSource <AmqpMessage> task;
                if (this.twinResponseCompletions.TryRemove(correlationId, out task))
                {
                    task.SetResult(message);
                }
            }
            else
            {
                // No correlation id? Must be a patch.
                if (this.onDesiredStatePatchListener != null)
                {
                    using (StreamReader reader = new StreamReader(message.BodyStream, System.Text.Encoding.UTF8))
                    {
                        string patch = reader.ReadToEnd();
                        var    props = JsonConvert.DeserializeObject <TwinCollection>(patch);
                        this.onDesiredStatePatchListener(props);
                    }
                }
            }
        }
            public AmqpLink CreateLink(AmqpSession session, AmqpLinkSettings settings)
            {
                AmqpLink link;

                if (settings.Role.Value)
                {
                    var receiver = new ReceivingAmqpLink(session, settings);
                    receiver.RegisterMessageListener(m =>
                    {
                        this.messages.Enqueue(m.Clone());
                        receiver.AcceptMessage(m, true, true);
                        m.Dispose();
                    });
                    link = receiver;
                }
                else
                {
                    var sender = new SendingAmqpLink(session, settings);
                    sender.RegisterCreditListener((credit, drain, tx) =>
                    {
                        AmqpMessage message = this.messages.Dequeue();
                        message.DeliveryAnnotations.Map["x-opt-sequence-number"] = 1;
                        sender.SendMessageNoWait(message, EmptyBinary, NullBinary);
                    });
                    sender.RegisterDispositionListener(d =>
                    {
                        sender.DisposeDelivery(d, true, d.State);
                    });
                    link = sender;
                }

                return(link);
            }
예제 #20
0
 public Publisher(TestQueue queue, ReceivingAmqpLink link, int id)
 {
     this.queue = queue;
     this.link  = link;
     this.id    = id;
     this.link.RegisterMessageListener(this.OnMessage);
     this.link.Closed += new EventHandler(link_Closed);
 }
예제 #21
0
        public async Task EnsureTwinLinksAreOpenedAsync(TimeSpan timeout)
        {
            if (Volatile.Read(ref _twinLinksOpened) == true) return;
            if (Logging.IsEnabled) Logging.Enter(this, timeout, $"{nameof(EnsureTwinLinksAreOpenedAsync)}");

            try
            {
                await _twinLinksLock.WaitAsync().ConfigureAwait(false);
                if (_twinLinksOpened) return;

                Debug.Assert(_twinSendingLink == null);
                Debug.Assert(_twinReceivingLink == null);

                string correlationIdSuffix = Guid.NewGuid().ToString();

                Task<ReceivingAmqpLink> receiveLinkCreator =
                    AmqpLinkHelper.OpenTwinReceiverLinkAsync(
                        _deviceIdentity,
                        _amqpSession,
                        correlationIdSuffix,
                        timeout);

                Task<SendingAmqpLink> sendingLinkCreator =
                    AmqpLinkHelper.OpenTwinSenderLinkAsync(
                        _deviceIdentity,
                        _amqpSession,
                        correlationIdSuffix,
                        timeout);

                await Task.WhenAll(receiveLinkCreator, sendingLinkCreator).ConfigureAwait(false);

                _twinSendingLink = sendingLinkCreator.Result;
                _twinSendingLink.Closed += OnLinkDisconnected;

                _twinReceivingLink = receiveLinkCreator.Result;
                _twinReceivingLink.RegisterMessageListener(OnDesiredPropertyReceived);
                _twinReceivingLink.Closed += OnLinkDisconnected;

                _twinLinksOpened = true;

                if (Logging.IsEnabled) Logging.Associate(this, this, _twinReceivingLink, $"{nameof(EnsureTwinLinksAreOpenedAsync)}");
                if (Logging.IsEnabled) Logging.Associate(this, this, _twinSendingLink, $"{nameof(EnsureTwinLinksAreOpenedAsync)}");
            }
            catch (Exception ex) when (!ex.IsFatal())
            {
                _twinReceivingLink?.Abort();
                _twinSendingLink?.Abort();
                _twinReceivingLink = null;
                _twinSendingLink = null;

                throw;
            }
            finally
            {
                _twinLinksLock.Release();
                if (Logging.IsEnabled) Logging.Exit(this, timeout, $"{nameof(EnsureTwinLinksAreOpenedAsync)}");
            }
        }
        private async Task EnableTwinReceivingLinkAsync(CancellationToken cancellationToken)
        {
            ReceivingAmqpLink twinReceivingLink = await this.GetTwinReceivingLinkAsync(cancellationToken);

            this.SafeAddClosedTwinReceivingLinkHandler = this.linkClosedListener;
            twinReceivingLink.SafeAddClosed((o, ea) => this.SafeAddClosedTwinReceivingLinkHandler(o, new ConnectionEventArgs {
                ConnectionKey = ConnectionKeys.AmqpTwinReceiving, ConnectionStatus = ConnectionStatus.Disconnected_Retrying, ConnectionStatusChangeReason = ConnectionStatusChangeReason.No_Network
            }));
        }
예제 #23
0
        AmqpLink ILinkFactory.CreateLink(AmqpSession session, AmqpLinkSettings settings)
        {
            try
            {
                this.ValidateLinkSettings(settings);

                // Override AmqpLinkSetting MaxMessageSize to restrict it to Constants.AmqpMaxMessageSize
                if (settings.MaxMessageSize == null || settings.MaxMessageSize == 0 || settings.MaxMessageSize > Constants.AmqpMaxMessageSize)
                {
                    settings.MaxMessageSize = Constants.AmqpMaxMessageSize;
                }

                AmqpLink  amqpLink;
                IAmqpLink wrappingAmqpLink;
                string    linkAddress;
                if (settings.IsReceiver())
                {
                    amqpLink         = new ReceivingAmqpLink(session, settings);
                    wrappingAmqpLink = new EdgeReceivingAmqpLink((ReceivingAmqpLink)amqpLink);
                    linkAddress      = ((Target)settings.Target).Address.ToString();
                }
                else
                {
                    amqpLink         = new SendingAmqpLink(session, settings);
                    wrappingAmqpLink = new EdgeSendingAmqpLink((SendingAmqpLink)amqpLink);
                    linkAddress      = ((Source)settings.Source).Address.ToString();
                }

                // TODO: implement the rules below
                // Link address may be of the forms:
                //
                //  amqp[s]://my.servicebus.windows.net/a/b     <-- FQ address where host name should match connection remote host name
                //  amqp[s]:a/b                                 <-- path relative to hostname specified in OPEN
                //  a/b                                         <-- pre-global addressing style path relative to hostname specified in OPEN
                //  /a/b                                        <-- same as above

                Uri linkUri;
                if (!linkAddress.StartsWith(Constants.AmqpsScheme, StringComparison.OrdinalIgnoreCase))
                {
                    string host = session.Connection.Settings.RemoteHostName;
                    linkUri = new Uri("amqps://" + host + linkAddress.EnsureStartsWith('/'));
                }
                else
                {
                    linkUri = new Uri(linkAddress, UriKind.RelativeOrAbsolute);
                }

                ILinkHandler linkHandler = this.linkHandlerProvider.Create(wrappingAmqpLink, linkUri);
                amqpLink.Settings.AddProperty(LinkHandlerPropertyKey, linkHandler);
                return(amqpLink);
            }
            catch (Exception e) when(!ExceptionEx.IsFatal(e))
            {
                // Don't throw here because we cannot provide error info. Instead delay and throw from Link.Open.
                return(new FaultedLink(e, session, settings));
            }
        }
예제 #24
0
 public void AddCoordinator(ReceivingAmqpLink link)
 {
     link.RegisterMessageListener(this.OnMessage);
     link.Closed += this.link_Closed;
     lock (this.coordinators)
     {
         this.coordinators.Add(link.Identifier, link);
     }
 }
예제 #25
0
        private async Task EnableMethodReceivingLinkAsync(CancellationToken cancellationToken)
        {
            ReceivingAmqpLink methodReceivingLink = await this.GetMethodReceivingLinkAsync(cancellationToken);

            this.SafeAddClosedMethodReceivingLinkHandler = this.linkClosedListener;
            methodReceivingLink.SafeAddClosed((o, ea) => this.SafeAddClosedMethodReceivingLinkHandler(o, new ConnectionEventArgs {
                ConnectionKey = ConnectionKeys.AmqpMethodReceiving, ConnectionStatus = ConnectionStatus.Disconnected_Retrying
            }));
        }
예제 #26
0
        internal static async Task <ReceivingAmqpLink> OpenReceivingAmqpLinkAsync(
            DeviceIdentity deviceIdentity,
            AmqpSession amqpSession,
            byte?senderSettleMode,
            byte?receiverSettleMode,
            string deviceTemplate,
            string moduleTemplate,
            string linkSuffix,
            string CorrelationId,
            TimeSpan timeout
            )
        {
            if (Logging.IsEnabled)
            {
                Logging.Enter(typeof(AmqpLinkHelper), deviceIdentity, $"{nameof(OpenReceivingAmqpLinkAsync)}");
            }

            uint prefetchCount = deviceIdentity.AmqpTransportSettings.PrefetchCount;

            AmqpLinkSettings amqpLinkSettings = new AmqpLinkSettings
            {
                LinkName        = CommonResources.GetNewStringGuid(linkSuffix),
                Role            = true,
                TotalLinkCredit = prefetchCount,
                AutoSendFlow    = prefetchCount > 0,
                Source          = new Source()
                {
                    Address = BuildLinkAddress(deviceIdentity, deviceTemplate, moduleTemplate)
                },
                Target = new Target()
                {
                    Address = deviceIdentity.IotHubConnectionString.DeviceId
                }
            };

            amqpLinkSettings.SndSettleMode = senderSettleMode;
            amqpLinkSettings.RcvSettleMode = receiverSettleMode;
            amqpLinkSettings.AddProperty(IotHubAmqpProperty.TimeoutName, timeout.TotalMilliseconds);
            amqpLinkSettings.AddProperty(IotHubAmqpProperty.ClientVersion, deviceIdentity.ProductInfo.ToString());
            amqpLinkSettings.AddProperty(IotHubAmqpProperty.ApiVersion, ClientApiVersionHelper.ApiVersionString);
            if (CorrelationId != null)
            {
                amqpLinkSettings.AddProperty(IotHubAmqpProperty.ChannelCorrelationId, CorrelationId);
            }

            ReceivingAmqpLink receivingLink = new ReceivingAmqpLink(amqpLinkSettings);

            receivingLink.AttachTo(amqpSession);
            await receivingLink.OpenAsync(timeout).ConfigureAwait(false);

            if (Logging.IsEnabled)
            {
                Logging.Exit(typeof(AmqpLinkHelper), deviceIdentity, $"{nameof(OpenReceivingAmqpLinkAsync)}");
            }
            return(receivingLink);
        }
예제 #27
0
        public static async Task <AmqpMessage> ReceiveMessageAsync(this ReceivingAmqpLink link, TimeSpan timeout)
        {
            AmqpMessage message = null;
            await Task.Factory.FromAsync(
                (c, s) => link.BeginReceiveMessage(timeout, c, s),
                (r) => link.EndReceiveMessage(r, out message),
                link);

            return(message);
        }
예제 #28
0
        public void AmqpWebSocketTransportTest()
        {
            string address = "ws://localhost:28088";
            var    broker  = new TestAmqpBroker(new string[] { address }, null, null, null);

            try
            {
                broker.Start();

                string queue = "AmqpWebSocketTransportTest";
                broker.AddQueue(queue);

                AmqpConnection connection = AmqpConnection.Factory.OpenConnectionAsync(address).GetAwaiter().GetResult();

                AmqpSession session = connection.CreateSession(new AmqpSessionSettings());
                session.Open();

                SendingAmqpLink sLink = new SendingAmqpLink(session, AmqpUtils.GetLinkSettings(true, queue, SettleMode.SettleOnSend));
                sLink.Open();

                int messageCount = 100;
                for (int i = 0; i < messageCount; i++)
                {
                    AmqpMessage message = AmqpMessage.Create(new AmqpValue()
                    {
                        Value = "message" + i
                    });
                    sLink.SendMessageAsync(message, AmqpConstants.EmptyBinary, AmqpConstants.NullBinary, TimeSpan.FromSeconds(10)).Wait();
                }

                sLink.Close();

                ReceivingAmqpLink rLink = new ReceivingAmqpLink(session, AmqpUtils.GetLinkSettings(false, queue, SettleMode.SettleOnReceive, 100));
                rLink.Open();

                for (int i = 0; i < messageCount; i++)
                {
                    AmqpMessage message2 = rLink.ReceiveMessageAsync(TimeSpan.FromSeconds(60)).GetAwaiter().GetResult();
                    Assert.NotNull(message2);

                    rLink.AcceptMessage(message2, false);
                    message2.Dispose();
                }

                rLink.Close();

                connection.Close();
            }
            finally
            {
                broker.Stop();
            }
        }
예제 #29
0
        async Task <ReceivingAmqpLink> CreateTwinReceivingLinkAsync(TimeSpan timeout, CancellationToken cancellationToken)
        {
            string path = this.BuildPath(CommonConstants.DeviceTwinPathTemplate, CommonConstants.ModuleTwinPathTemplate);

            ReceivingAmqpLink twinReceivingLink = await this.IotHubConnection.CreateReceivingLinkAsync(path, this.iotHubConnectionString, this.twinConnectionCorrelationId, IotHubConnection.ReceivingLinkType.Twin, this.prefetchCount, timeout, this.productInfo, cancellationToken).ConfigureAwait(false);

            MyStringCopy(twinReceivingLink.Name, out twinReceivingLinkName);
            twinReceivingLink.SafeAddClosed(OnAmqpConnectionClose);
            twinReceivingLink.RegisterMessageListener(message => this.HandleTwinMessage(message, twinReceivingLink));

            return(twinReceivingLink);
        }
예제 #30
0
        internal static async Task DisposeMessageAsync(
            FaultTolerantAmqpObject <ReceivingAmqpLink> faultTolerantReceivingLink,
            string lockToken,
            Outcome outcome,
            bool batchable,
            CancellationToken cancellationToken)
        {
            Logging.Enter(faultTolerantReceivingLink, lockToken, outcome.DescriptorCode, batchable, nameof(DisposeMessageAsync));

            try
            {
                cancellationToken.ThrowIfCancellationRequested();

                ArraySegment <byte> deliveryTag = IotHubConnection.ConvertToDeliveryTag(lockToken);

                Outcome disposeOutcome;
                try
                {
                    ReceivingAmqpLink deviceBoundReceivingLink = await faultTolerantReceivingLink.GetReceivingLinkAsync().ConfigureAwait(false);

                    disposeOutcome = await deviceBoundReceivingLink
                                     .DisposeMessageAsync(
                        deliveryTag,
                        outcome,
                        batchable,
                        cancellationToken)
                                     .ConfigureAwait(false);
                }
                catch (Exception exception)
                {
                    Logging.Error(faultTolerantReceivingLink, exception, nameof(DisposeMessageAsync));

                    if (exception.IsFatal())
                    {
                        throw;
                    }

                    throw ToIotHubClientContract(exception);
                }

                Logging.Info(faultTolerantReceivingLink, disposeOutcome.DescriptorCode, nameof(DisposeMessageAsync));

                if (disposeOutcome.DescriptorCode != Accepted.Code)
                {
                    throw AmqpErrorMapper.GetExceptionFromOutcome(disposeOutcome);
                }
            }
            finally
            {
                Logging.Exit(faultTolerantReceivingLink, lockToken, outcome.DescriptorCode, batchable, nameof(DisposeMessageAsync));
            }
        }
예제 #31
0
        private async Task <ReceivingAmqpLink> CreateEventReceivingLinkAsync(TimeSpan timeout, CancellationToken cancellationToken)
        {
            string path = this.BuildPath(CommonConstants.DeviceEventPathTemplate, CommonConstants.ModuleEventPathTemplate);

            ReceivingAmqpLink messageReceivingLink = await this.IotHubConnection.CreateReceivingLinkAsync(path, this.iotHubConnectionString, this.deviceId, IotHubConnection.ReceivingLinkType.Events, this.prefetchCount, timeout, this.productInfo, cancellationToken).ConfigureAwait(false);

            messageReceivingLink.RegisterMessageListener(amqpMessage => this.ProcessReceivedEventMessage(amqpMessage));

            MyStringCopy(messageReceivingLink.Name, out eventReceivingLinkName);
            messageReceivingLink.SafeAddClosed(OnAmqpConnectionClose);

            return(messageReceivingLink);
        }
예제 #32
0
        public DuplexAmqpLink(SendingAmqpLink sender, ReceivingAmqpLink receiver)
            : base("duplex")
        {
            AmqpTrace.Provider.AmqpLogOperationInformational(this, TraceOperation.Create, "Create");
            this.sender = sender;
            this.receiver = receiver;

            this.sender.SafeAddClosed(this.OnLinkClosed);
            this.receiver.SafeAddClosed(this.OnLinkClosed);

            // TODO:
            ////if (this.sender.State != AmqpObjectState.Opened)
            ////{
            ////    this.SafeClose();
            ////    throw Fx.Exception.AsWarning(new ArgumentException("Sender wasn't open", "sender"));
            ////}

            ////if (this.receiver.State != AmqpObjectState.Opened)
            ////{
            ////    this.SafeClose();
            ////    throw Fx.Exception.AsWarning(new ArgumentException("Reciever wasn't open", "receiver"));
            ////}
        }
예제 #33
0
 public void AddCoordinator(ReceivingAmqpLink link)
 {
     link.RegisterMessageListener(this.OnMessage);
     link.Closed += this.link_Closed;
     lock (this.coordinators)
     {
         this.coordinators.Add(link.Identifier, link);
     }
 }
예제 #34
0
 public Publisher(TestQueue queue, ReceivingAmqpLink link, int id)
 {
     this.queue = queue;
     this.link = link;
     this.id = id;
     this.link.RegisterMessageListener(this.OnMessage);
     this.link.Closed += new EventHandler(link_Closed);
 }
예제 #35
0
        public AmqpLink CreateLink(AmqpSession session, AmqpLinkSettings settings)
        {
            bool isReceiver = settings.Role.Value;
            AmqpLink link;
            if (isReceiver)
            {
                if (settings.Target is Target && ((Target)settings.Target).Dynamic())
                {
                    string name = string.Format("$dynamic.{0}", Interlocked.Increment(ref this.dynamicId));
                    this.queues.Add(name, new TestQueue(this));
                    ((Target)settings.Target).Address = name;
                }

                link = new ReceivingAmqpLink(session, settings);
            }
            else
            {
                if (((Source)settings.Source).Dynamic())
                {
                    string name = string.Format("$dynamic.{0}", Interlocked.Increment(ref this.dynamicId));
                    this.queues.Add(name, new TestQueue(this));
                    ((Source)settings.Source).Address = name;
                }

                link = new SendingAmqpLink(session, settings);
            }

            return link;
        }
        public async Task<ReceivingAmqpLink> CreateReceivingLink(string path, TimeSpan timeout, uint prefetchCount)
        {
            var timeoutHelper = new TimeoutHelper(timeout);

            AmqpSession session;
            if (!this.faultTolerantSession.TryGetOpenedObject(out session))
            {
                session = await this.faultTolerantSession.GetOrCreateAsync(timeoutHelper.RemainingTime());
            }

            var linkAddress = this.connectionString.BuildLinkAddress(path);

            var linkSettings = new AmqpLinkSettings()
            {
                Role = true,
                TotalLinkCredit = prefetchCount,
                AutoSendFlow = prefetchCount > 0, 
                Source = new Source() { Address = linkAddress.AbsoluteUri },
                SndSettleMode = null, // SenderSettleMode.Unsettled (null as it is the default and to avoid bytes on the wire)
                RcvSettleMode = (byte)ReceiverSettleMode.Second, 
                LinkName = Guid.NewGuid().ToString("N") // Use a human readable link name to help with debuggin
            };

            SetLinkSettingsCommonProperties(linkSettings, timeoutHelper.RemainingTime());

            var link = new ReceivingAmqpLink(linkSettings);
            link.AttachTo(session);

            await OpenLinkAsync(link, timeoutHelper.RemainingTime());

            return link;
        }