public IAsyncResult BeginOpen(AmqpSession session, TimeSpan timeout, AsyncCallback callback, object state) { string uniqueueName = Guid.NewGuid().ToString("N"); Source source = new Source(); source.Address = uniqueueName; source.DistributionMode = DistributionMode.Move; Coordinator coordinator = new Coordinator(); AmqpLinkSettings settings = new AmqpLinkSettings(); settings.Source = source; settings.Target = coordinator; settings.LinkName = uniqueueName; settings.Role = false; this.sendLink = new SendingAmqpLink(session, settings); return this.sendLink.BeginOpen(timeout, callback, state); }
public static AmqpLinkSettings GetLinkSettings(bool forSender, string address, SettleMode settleType, int credit = 0, bool dynamic = false) { AmqpLinkSettings settings = null; // create a setting for sender settings = new AmqpLinkSettings(); settings.LinkName = string.Format("link-{0}", Guid.NewGuid().ToString("N")); settings.Role = !forSender; Target target = new Target(); target.Address = address; Source source = new Source(); source.Address = address; source.DistributionMode = "move"; settings.Source = source; settings.Target = target; settings.SettleType = settleType; if (!forSender) { settings.TotalLinkCredit = (uint)credit; settings.AutoSendFlow = credit > 0; if (dynamic) { source.Address = null; source.Dynamic = true; } } else { settings.InitialDeliveryCount = 0; if (dynamic) { target.Address = null; target.Dynamic = true; } } settings.AddProperty("x-opt-just-testing", "ignore me"); return settings; }
/// <summary> /// Creates an AMQP link for use with publishing operations. /// </summary> /// <param name="entityPath">The entity path to send to.</param> /// <param name="connection">The active and opened AMQP connection to use for this link.</param> /// <param name="timeout">The timeout to apply when creating the link.</param> /// <param name="cancellationToken">An optional <see cref="CancellationToken"/> instance to signal the request to cancel the operation.</param> /// /// <returns>A link for use for operations related to receiving events.</returns> protected virtual async Task <SendingAmqpLink> CreateSendingLinkAsync( string entityPath, AmqpConnection connection, TimeSpan timeout, CancellationToken cancellationToken) { Argument.AssertNotDisposed(IsDisposed, nameof(AmqpConnectionScope)); cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>(); var session = default(AmqpSession); var stopWatch = ValueStopwatch.StartNew(); try { string[] audience; Uri destinationEndpoint = null; destinationEndpoint = new Uri(ServiceEndpoint, entityPath); audience = new string[] { destinationEndpoint.AbsoluteUri }; // Perform the initial authorization for the link. var authClaims = new[] { ServiceBusClaim.Send }; DateTime authExpirationUtc = await RequestAuthorizationUsingCbsAsync( connection, TokenProvider, destinationEndpoint, audience, authClaims, timeout.CalculateRemaining(stopWatch.GetElapsedTime())) .ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>(); // Create and open the AMQP session associated with the link. var sessionSettings = new AmqpSessionSettings { Properties = new Fields() }; session = connection.CreateSession(sessionSettings); await OpenAmqpObjectAsync(session, timeout).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>(); // Create and open the link. var linkSettings = new AmqpLinkSettings { Role = false, InitialDeliveryCount = 0, Source = new Source { Address = Guid.NewGuid().ToString() }, Target = new Target { Address = destinationEndpoint.AbsolutePath } }; linkSettings.AddProperty(AmqpClientConstants.TimeoutName, (uint)timeout.CalculateRemaining(stopWatch.GetElapsedTime()).TotalMilliseconds); var link = new SendingAmqpLink(linkSettings); linkSettings.LinkName = $"{ Id };{ connection.Identifier }:{ session.Identifier }:{ link.Identifier }"; link.AttachTo(session); // Configure refresh for authorization of the link. var refreshTimer = default(Timer); TimerCallback refreshHandler = CreateAuthorizationRefreshHandler ( entityPath, connection, link, TokenProvider, destinationEndpoint, audience, authClaims, AuthorizationRefreshTimeout, () => refreshTimer ); refreshTimer = new Timer(refreshHandler, null, CalculateLinkAuthorizationRefreshInterval(authExpirationUtc), Timeout.InfiniteTimeSpan); // Track the link before returning it, so that it can be managed with the scope. BeginTrackingLinkAsActive(entityPath, link, refreshTimer); return(link); } catch (Exception exception) { // Aborting the session will perform any necessary cleanup of // the associated link as well. session?.Abort(); ExceptionDispatchInfo.Capture(AmqpExceptionHelper.TranslateException( exception, null, session.GetInnerException(), connection.IsClosing())) .Throw(); throw; // will never be reached } }
public AmqpSendReceiveLinkCreator(string entityPath, ServiceBusConnection serviceBusConnection, Uri endpointAddress, string[] requiredClaims, ICbsTokenProvider cbsTokenProvider, AmqpLinkSettings linkSettings, string clientId) : base(entityPath, serviceBusConnection, endpointAddress, requiredClaims, cbsTokenProvider, linkSettings, clientId) { }
/// <summary> /// Creates an AMQP link for use with management operations. /// </summary> /// <param name="entityPath"></param> /// /// <param name="connection">The active and opened AMQP connection to use for this link.</param> /// <param name="timeout">The timeout to apply when creating the link.</param> /// <param name="cancellationToken">An optional <see cref="CancellationToken"/> instance to signal the request to cancel the operation.</param> /// /// <returns>A link for use with management operations.</returns> protected virtual async Task <RequestResponseAmqpLink> CreateManagementLinkAsync( string entityPath, AmqpConnection connection, TimeSpan timeout, CancellationToken cancellationToken) { Argument.AssertNotDisposed(IsDisposed, nameof(AmqpConnectionScope)); cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>(); var session = default(AmqpSession); var stopWatch = ValueStopwatch.StartNew(); try { // Create and open the AMQP session associated with the link. var sessionSettings = new AmqpSessionSettings { Properties = new Fields() }; session = connection.CreateSession(sessionSettings); await OpenAmqpObjectAsync(session, timeout).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>(); // Create and open the link. var linkSettings = new AmqpLinkSettings(); linkSettings.AddProperty(AmqpClientConstants.TimeoutName, (uint)timeout.CalculateRemaining(stopWatch.GetElapsedTime()).TotalMilliseconds); linkSettings.AddProperty(AmqpClientConstants.EntityTypeName, AmqpClientConstants.EntityTypeManagement); entityPath += '/' + AmqpClientConstants.ManagementAddress; // Perform the initial authorization for the link. string[] claims = { ServiceBusClaim.Manage, ServiceBusClaim.Listen, ServiceBusClaim.Send }; var endpoint = new Uri(ServiceEndpoint, entityPath); var audience = new[] { endpoint.AbsoluteUri }; DateTime authExpirationUtc = await RequestAuthorizationUsingCbsAsync( connection, TokenProvider, ServiceEndpoint, audience, claims, timeout.CalculateRemaining(stopWatch.GetElapsedTime())) .ConfigureAwait(false); var link = new RequestResponseAmqpLink( AmqpClientConstants.EntityTypeManagement, session, entityPath, linkSettings.Properties); linkSettings.LinkName = $"{connection.Settings.ContainerId};{connection.Identifier}:{session.Identifier}:{link.Identifier}"; // Track the link before returning it, so that it can be managed with the scope. var refreshTimer = default(Timer); TimerCallback refreshHandler = CreateAuthorizationRefreshHandler ( entityPath, connection, link, TokenProvider, ServiceEndpoint, audience, claims, AuthorizationRefreshTimeout, () => (ActiveLinks.ContainsKey(link) ? refreshTimer : null) ); refreshTimer = new Timer(refreshHandler, null, CalculateLinkAuthorizationRefreshInterval(authExpirationUtc), Timeout.InfiniteTimeSpan); // Track the link before returning it, so that it can be managed with the scope. BeginTrackingLinkAsActive(entityPath, link, refreshTimer); return(link); } catch (Exception exception) { // Aborting the session will perform any necessary cleanup of // the associated link as well. session?.Abort(); ExceptionDispatchInfo.Capture(AmqpExceptionHelper.TranslateException( exception, null, session.GetInnerException(), connection.IsClosing())) .Throw(); throw; // will never be reached } }
/// <summary> /// Creates an AMQP link for use with receiving operations. /// </summary> /// <param name="entityPath">The entity path to receive from.</param> /// <param name="connection">The active and opened AMQP connection to use for this link.</param> /// <param name="endpoint">The fully qualified endpoint to open the link for.</param> /// <param name="prefetchCount">Controls the number of events received and queued locally without regard to whether an operation was requested.</param> /// <param name="receiveMode">The <see cref="ReceiveMode"/> used to specify how messages are received. Defaults to PeekLock mode.</param> /// <param name="sessionId">The session to receive from.</param> /// <param name="isSessionReceiver">Whether or not this is a sessionful receiver.</param> /// <param name="timeout">The timeout to apply when creating the link.</param> /// <param name="cancellationToken">An optional <see cref="CancellationToken"/> instance to signal the request to cancel the operation.</param> /// /// <returns>A link for use for operations related to receiving events.</returns> protected virtual async Task <ReceivingAmqpLink> CreateReceivingLinkAsync( string entityPath, AmqpConnection connection, Uri endpoint, TimeSpan timeout, uint prefetchCount, ReceiveMode receiveMode, string sessionId, bool isSessionReceiver, CancellationToken cancellationToken) { Argument.AssertNotDisposed(IsDisposed, nameof(AmqpConnectionScope)); cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>(); var session = default(AmqpSession); var stopWatch = ValueStopwatch.StartNew(); try { // Perform the initial authorization for the link. string[] authClaims = new string[] { ServiceBusClaim.Send }; var audience = new[] { endpoint.AbsoluteUri }; DateTime authExpirationUtc = await RequestAuthorizationUsingCbsAsync( connection, TokenProvider, endpoint, audience, authClaims, timeout.CalculateRemaining(stopWatch.GetElapsedTime())).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>(); // Create and open the AMQP session associated with the link. var sessionSettings = new AmqpSessionSettings { Properties = new Fields() }; // This is the maximum number of unsettled transfers across all receive links on this session. // This will allow the session to accept unlimited number of transfers, even if the recevier(s) // are not settling any of the deliveries. sessionSettings.IncomingWindow = uint.MaxValue; session = connection.CreateSession(sessionSettings); await OpenAmqpObjectAsync(session, timeout).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>(); var filters = new FilterSet(); // even if supplied sessionId is null, we need to add the Session filter if it is a session receiver if (isSessionReceiver) { filters.Add(AmqpClientConstants.SessionFilterName, sessionId); } var linkSettings = new AmqpLinkSettings { Role = true, TotalLinkCredit = prefetchCount, AutoSendFlow = prefetchCount > 0, SettleType = (receiveMode == ReceiveMode.PeekLock) ? SettleMode.SettleOnDispose : SettleMode.SettleOnSend, Source = new Source { Address = endpoint.AbsolutePath, FilterSet = filters }, Target = new Target { Address = Guid.NewGuid().ToString() } }; var link = new ReceivingAmqpLink(linkSettings); linkSettings.LinkName = $"{connection.Settings.ContainerId};{connection.Identifier}:{session.Identifier}:{link.Identifier}:{linkSettings.Source.ToString()}"; link.AttachTo(session); // Configure refresh for authorization of the link. var refreshTimer = default(Timer); TimerCallback refreshHandler = CreateAuthorizationRefreshHandler ( entityPath, connection, link, TokenProvider, endpoint, audience, authClaims, AuthorizationRefreshTimeout, () => (ActiveLinks.ContainsKey(link) ? refreshTimer : null) ); refreshTimer = new Timer(refreshHandler, null, CalculateLinkAuthorizationRefreshInterval(authExpirationUtc), Timeout.InfiniteTimeSpan); // Track the link before returning it, so that it can be managed with the scope. BeginTrackingLinkAsActive(entityPath, link, refreshTimer); return(link); } catch (Exception exception) { // Aborting the session will perform any necessary cleanup of // the associated link as well. session?.Abort(); ExceptionDispatchInfo.Capture(AmqpExceptionHelper.TranslateException( exception, null, session.GetInnerException(), connection.IsClosing())) .Throw(); throw; // will never be reached } }
async Task <ReceivingAmqpLink> CreateLinkAsync(TimeSpan timeout) { var amqpEventHubClient = ((AmqpEventHubClient)this.EventHubClient); var timeoutHelper = new TimeoutHelper(timeout); AmqpConnection connection = await amqpEventHubClient.ConnectionManager.GetOrCreateAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); // Authenticate over CBS var cbsLink = connection.Extensions.Find <AmqpCbsLink>(); ICbsTokenProvider cbsTokenProvider = amqpEventHubClient.CbsTokenProvider; Uri address = new Uri(amqpEventHubClient.ConnectionStringBuilder.Endpoint, this.Path); string audience = address.AbsoluteUri; string resource = address.AbsoluteUri; var expiresAt = await cbsLink.SendTokenAsync(cbsTokenProvider, address, audience, resource, new[] { ClaimConstants.Listen }, timeoutHelper.RemainingTime()).ConfigureAwait(false); AmqpSession session = null; try { // Create our Session var sessionSettings = new AmqpSessionSettings { Properties = new Fields() }; session = connection.CreateSession(sessionSettings); await session.OpenAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); FilterSet filterMap = null; var filters = this.CreateFilters(); if (filters != null && filters.Count > 0) { filterMap = new FilterSet(); foreach (var filter in filters) { filterMap.Add(filter.DescriptorName, filter); } } // Create our Link var linkSettings = new AmqpLinkSettings { Role = true, TotalLinkCredit = (uint)this.PrefetchCount, AutoSendFlow = this.PrefetchCount > 0 }; linkSettings.AddProperty(AmqpClientConstants.EntityTypeName, (int)MessagingEntityType.ConsumerGroup); linkSettings.Source = new Source { Address = address.AbsolutePath, FilterSet = filterMap }; linkSettings.Target = new Target { Address = this.ClientId }; linkSettings.SettleType = SettleMode.SettleOnSend; // Receiver metrics enabled? if (this.ReceiverRuntimeMetricEnabled) { linkSettings.DesiredCapabilities = new Multiple <AmqpSymbol>(new List <AmqpSymbol> { AmqpClientConstants.EnableReceiverRuntimeMetricName }); } if (this.Epoch.HasValue) { linkSettings.AddProperty(AmqpClientConstants.AttachEpoch, this.Epoch.Value); } if (!string.IsNullOrWhiteSpace(this.Identifier)) { linkSettings.AddProperty(AmqpClientConstants.ReceiverIdentifierName, this.Identifier); } var link = new ReceivingAmqpLink(linkSettings); linkSettings.LinkName = $"{amqpEventHubClient.ContainerId};{connection.Identifier}:{session.Identifier}:{link.Identifier}"; link.AttachTo(session); await link.OpenAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); var activeClientLink = new ActiveClientLink( link, audience, // audience this.EventHubClient.ConnectionStringBuilder.Endpoint.AbsoluteUri, // endpointUri new[] { ClaimConstants.Listen }, true, expiresAt); this.clientLinkManager.SetActiveLink(activeClientLink); return(link); } catch { // Cleanup any session (and thus link) in case of exception. session?.Abort(); throw; } }
async Task <SendingAmqpLink> CreateLinkAsync(TimeSpan timeout) { var amqpEventHubClient = ((AmqpEventHubClient)this.EventHubClient); var timeoutHelper = new TimeoutHelper(timeout); AmqpConnection connection = await amqpEventHubClient.ConnectionManager.GetOrCreateAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); // Authenticate over CBS var cbsLink = connection.Extensions.Find <AmqpCbsLink>(); ICbsTokenProvider cbsTokenProvider = amqpEventHubClient.CbsTokenProvider; Uri address = new Uri(amqpEventHubClient.ConnectionStringBuilder.Endpoint, this.Path); string audience = address.AbsoluteUri; string resource = address.AbsoluteUri; var expiresAt = await cbsLink.SendTokenAsync( cbsTokenProvider, address, audience, resource, new[] { ClaimConstants.Send }, timeoutHelper.RemainingTime()).ConfigureAwait(false); AmqpSession session = null; try { // Create our Session var sessionSettings = new AmqpSessionSettings { Properties = new Fields() }; session = connection.CreateSession(sessionSettings); await session.OpenAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); // Create our Link var linkSettings = new AmqpLinkSettings(); linkSettings.AddProperty(AmqpClientConstants.TimeoutName, (uint)timeoutHelper.RemainingTime().TotalMilliseconds); linkSettings.AddProperty(AmqpClientConstants.EntityTypeName, (int)MessagingEntityType.EventHub); linkSettings.Role = false; linkSettings.InitialDeliveryCount = 0; linkSettings.Target = new Target { Address = address.AbsolutePath }; linkSettings.Source = new Source { Address = this.ClientId }; var link = new SendingAmqpLink(linkSettings); linkSettings.LinkName = $"{amqpEventHubClient.ContainerId};{connection.Identifier}:{session.Identifier}:{link.Identifier}"; link.AttachTo(session); await link.OpenAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); var activeClientLink = new ActiveClientLink( link, audience, // audience this.EventHubClient.ConnectionStringBuilder.Endpoint.AbsoluteUri, // endpointUri new[] { ClaimConstants.Send }, true, expiresAt); this.MaxMessageSize = (long)activeClientLink.Link.Settings.MaxMessageSize(); this.clientLinkManager.SetActiveLink(activeClientLink); return(link); } catch { // Cleanup any session (and thus link) in case of exception. session?.Abort(); throw; } }
/// <summary> /// Creates an AMQP link for use with publishing operations. /// </summary> /// /// <param name="connection">The active and opened AMQP connection to use for this link.</param> /// <param name="endpoint">The fully qualified endpoint to open the link for.</param> /// <param name="timeout">The timeout to apply when creating the link.</param> /// <param name="cancellationToken">An optional <see cref="CancellationToken"/> instance to signal the request to cancel the operation.</param> /// /// <returns>A link for use for operations related to receiving events.</returns> /// protected virtual async Task <SendingAmqpLink> CreateSendingLinkAsync(AmqpConnection connection, Uri endpoint, TimeSpan timeout, CancellationToken cancellationToken) { Argument.AssertNotDisposed(IsDisposed, nameof(AmqpConnectionScope)); cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>(); var session = default(AmqpSession); var stopWatch = Stopwatch.StartNew(); try { // Perform the initial authorization for the link. var authClaims = new[] { EventHubsClaim.Send }; var authExpirationUtc = await RequestAuthorizationUsingCbsAsync(connection, TokenProvider, endpoint, endpoint.AbsoluteUri, endpoint.AbsoluteUri, authClaims, timeout.CalculateRemaining(stopWatch.Elapsed)).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>(); // Create and open the AMQP session associated with the link. var sessionSettings = new AmqpSessionSettings { Properties = new Fields() }; session = connection.CreateSession(sessionSettings); await OpenAmqpObjectAsync(session, timeout).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>(); // Create and open the link. var linkSettings = new AmqpLinkSettings { Role = false, InitialDeliveryCount = 0, Source = new Source { Address = Guid.NewGuid().ToString() }, Target = new Target { Address = endpoint.AbsolutePath } }; linkSettings.AddProperty(AmqpProperty.Timeout, (uint)timeout.CalculateRemaining(stopWatch.Elapsed).TotalMilliseconds); linkSettings.AddProperty(AmqpProperty.EntityType, (int)AmqpProperty.Entity.EventHub); var link = new SendingAmqpLink(linkSettings); linkSettings.LinkName = $"{ Id };{ connection.Identifier }:{ session.Identifier }:{ link.Identifier }"; link.AttachTo(session); stopWatch.Stop(); // Configure refresh for authorization of the link. var refreshTimer = default(Timer); var refreshHandler = CreateAuthorizationRefreshHandler ( connection, link, TokenProvider, endpoint, endpoint.AbsoluteUri, endpoint.AbsoluteUri, authClaims, AuthorizationRefreshTimeout, () => refreshTimer ); refreshTimer = new Timer(refreshHandler, null, CalculateLinkAuthorizationRefreshInterval(authExpirationUtc), Timeout.InfiniteTimeSpan); // Track the link before returning it, so that it can be managed with the scope. BeginTrackingLinkAsActive(link, refreshTimer); return(link); } catch { // Aborting the session will perform any necessary cleanup of // the associated link as well. session?.Abort(); throw; } }
private static async Task <AmqpIoTReceivingLink> 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(AmqpIoTSession), deviceIdentity, $"{nameof(OpenReceivingAmqpLinkAsync)}"); } uint prefetchCount = deviceIdentity.AmqpTransportSettings.PrefetchCount; AmqpLinkSettings amqpLinkSettings = new AmqpLinkSettings { LinkName = 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(AmqpIoTErrorAdapter.TimeoutName, timeout.TotalMilliseconds); amqpLinkSettings.AddProperty(AmqpIoTErrorAdapter.ClientVersion, deviceIdentity.ProductInfo.ToString()); amqpLinkSettings.AddProperty(AmqpIoTErrorAdapter.ApiVersion, ClientApiVersionHelper.ApiVersionString); if (correlationId != null) { amqpLinkSettings.AddProperty(AmqpIoTErrorAdapter.ChannelCorrelationId, correlationId); } try { ReceivingAmqpLink receivingLink = new ReceivingAmqpLink(amqpLinkSettings); receivingLink.AttachTo(amqpSession); await receivingLink.OpenAsync(timeout).ConfigureAwait(false); return(new AmqpIoTReceivingLink(receivingLink)); } catch (Exception e) when(!e.IsFatal()) { Exception ex = AmqpIoTExceptionAdapter.ConvertToIoTHubException(e, amqpSession); if (ReferenceEquals(e, ex)) { throw; } else { if (ex is AmqpIoTResourceException) { amqpSession.SafeClose(); throw new IotHubCommunicationException(ex.Message, ex); } throw ex; } } finally { if (Logging.IsEnabled) { Logging.Exit(typeof(AmqpIoTSession), deviceIdentity, $"{nameof(OpenReceivingAmqpLinkAsync)}"); } } }
/// <summary> /// Creates an AMQP link for use with receiving operations. /// </summary> /// /// <param name="connection">The active and opened AMQP connection to use for this link.</param> /// <param name="endpoint">The fully qualified endpoint to open the link for.</param> /// <param name="eventPosition">The position of the event in the partition where the link should be filtered to.</param> /// <param name="consumerOptions">The set of active options for the consumer that will make use of the link.</param> /// <param name="timeout">The timeout to apply when creating the link.</param> /// <param name="cancellationToken">An optional <see cref="CancellationToken"/> instance to signal the request to cancel the operation.</param> /// /// <returns>A link for use for operations related to receiving events.</returns> /// protected virtual async Task <ReceivingAmqpLink> CreateReceivingLinkAsync(AmqpConnection connection, Uri endpoint, EventPosition eventPosition, EventHubConsumerClientOptions consumerOptions, TimeSpan timeout, CancellationToken cancellationToken) { Argument.AssertNotDisposed(IsDisposed, nameof(AmqpConnectionScope)); cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>(); var session = default(AmqpSession); var stopWatch = Stopwatch.StartNew(); try { // Perform the initial authorization for the link. var authClaims = new[] { EventHubsClaim.Listen }; var authExpirationUtc = await RequestAuthorizationUsingCbsAsync(connection, TokenProvider, endpoint, endpoint.AbsoluteUri, endpoint.AbsoluteUri, authClaims, timeout.CalculateRemaining(stopWatch.Elapsed)).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>(); // Create and open the AMQP session associated with the link. var sessionSettings = new AmqpSessionSettings { Properties = new Fields() }; session = connection.CreateSession(sessionSettings); await OpenAmqpObjectAsync(session, timeout).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>(); // Create and open the link. var filters = new FilterSet(); filters.Add(AmqpFilter.ConsumerFilterName, AmqpFilter.CreateConsumerFilter(AmqpFilter.BuildFilterExpression(eventPosition))); var linkSettings = new AmqpLinkSettings { Role = true, TotalLinkCredit = (uint)consumerOptions.PrefetchCount, AutoSendFlow = consumerOptions.PrefetchCount > 0, SettleType = SettleMode.SettleOnSend, Source = new Source { Address = endpoint.AbsolutePath, FilterSet = filters }, Target = new Target { Address = Guid.NewGuid().ToString() } }; linkSettings.AddProperty(AmqpProperty.EntityType, (int)AmqpProperty.Entity.ConsumerGroup); if (consumerOptions.OwnerLevel.HasValue) { linkSettings.AddProperty(AmqpProperty.OwnerLevel, consumerOptions.OwnerLevel.Value); } if (consumerOptions.TrackLastEnqueuedEventInformation) { linkSettings.DesiredCapabilities = new Multiple <AmqpSymbol>(new List <AmqpSymbol> { AmqpProperty.TrackLastEnqueuedEventInformation }); } var link = new ReceivingAmqpLink(linkSettings); linkSettings.LinkName = $"{ Id };{ connection.Identifier }:{ session.Identifier }:{ link.Identifier }"; link.AttachTo(session); stopWatch.Stop(); // Configure refresh for authorization of the link. var refreshTimer = default(Timer); var refreshHandler = CreateAuthorizationRefreshHandler ( connection, link, TokenProvider, endpoint, endpoint.AbsoluteUri, endpoint.AbsoluteUri, authClaims, AuthorizationRefreshTimeout, () => refreshTimer ); refreshTimer = new Timer(refreshHandler, null, CalculateLinkAuthorizationRefreshInterval(authExpirationUtc), Timeout.InfiniteTimeSpan); // Track the link before returning it, so that it can be managed with the scope. BeginTrackingLinkAsActive(link, refreshTimer); return(link); } catch { // Aborting the session will perform any necessary cleanup of // the associated link as well. session?.Abort(); throw; } }
public async Task <SendingAmqpLink> CreateSendingLinkAsync( string path, IotHubConnectionString connectionString, string corrId, SendingLinkType linkType, TimeSpan timeout, ProductInfo productInfo, CancellationToken cancellationToken) { try { if (Logging.IsEnabled) { Logging.Enter(this, corrId, linkType, $"{nameof(IotHubConnection)}.{nameof(CreateSendingLinkAsync)}"); } this.OnCreateSendingLink(connectionString); var timeoutHelper = new TimeoutHelper(timeout); AmqpSession session = await this.GetSessionAsync(timeoutHelper, cancellationToken).ConfigureAwait(false); var linkAddress = this.BuildLinkAddress(connectionString, path); var linkSettings = new AmqpLinkSettings() { Role = false, InitialDeliveryCount = 0, Target = new Target() { Address = linkAddress.AbsoluteUri }, LinkName = Guid.NewGuid().ToString("N") // Use a human readable link name to help with debugging }; switch (linkType) { case SendingLinkType.TelemetryEvents: linkSettings.SndSettleMode = null; // SenderSettleMode.Unsettled (null as it is the default and to avoid bytes on the wire) linkSettings.RcvSettleMode = null; // (byte)ReceiverSettleMode.First (null as it is the default and to avoid bytes on the wire) break; case SendingLinkType.Methods: case SendingLinkType.Twin: linkSettings.SndSettleMode = (byte)SenderSettleMode.Settled; linkSettings.RcvSettleMode = (byte)ReceiverSettleMode.First; break; } SetLinkSettingsCommonProperties(linkSettings, timeoutHelper.RemainingTime(), productInfo); if (linkType == SendingLinkType.Methods) { SetLinkSettingsCommonPropertiesForMethod(linkSettings, corrId); } else if (linkType == SendingLinkType.Twin) { SetLinkSettingsCommonPropertiesForTwin(linkSettings, corrId); } var link = new SendingAmqpLink(linkSettings); link.AttachTo(session); var audience = this.BuildAudience(connectionString, path); await this.OpenLinkAsync(link, connectionString, audience, timeoutHelper.RemainingTime(), cancellationToken).ConfigureAwait(false); return(link); } finally { if (Logging.IsEnabled) { Logging.Exit(this, corrId, linkType, $"{nameof(IotHubConnection)}.{nameof(CreateSendingLinkAsync)}"); } } }
AmqpLinkSettings SetLinkSettingsCommonPropertiesForTwin(AmqpLinkSettings linkSettings, string corrId) { linkSettings.AddProperty(IotHubAmqpProperty.ApiVersion, ClientApiVersionHelper.ApiVersionString); linkSettings.AddProperty(IotHubAmqpProperty.ChannelCorrelationId, "twin:" + corrId); return(linkSettings); }
protected static AmqpLinkSettings SetLinkSettingsCommonPropertiesForMethod(AmqpLinkSettings linkSettings, string corrId) { linkSettings.AddProperty(IotHubAmqpProperty.ApiVersion, ClientApiVersionHelper.ApiVersionString); linkSettings.AddProperty(IotHubAmqpProperty.ChannelCorrelationId, "methods:" + corrId); return(linkSettings); }
public async Task <ReceivingAmqpLink> CreateReceivingLinkAsync( string path, IotHubConnectionString connectionString, string corrId, ReceivingLinkType linkType, uint prefetchCount, TimeSpan timeout, ProductInfo productInfo, CancellationToken cancellationToken) { try { if (Logging.IsEnabled) { Logging.Enter(this, corrId, linkType, $"{nameof(IotHubConnection)}.{nameof(CreateReceivingLinkAsync)}"); } this.OnCreateReceivingLink(connectionString); var timeoutHelper = new TimeoutHelper(timeout); AmqpSession session = await this.GetSessionAsync(timeoutHelper, cancellationToken).ConfigureAwait(false); var linkAddress = this.BuildLinkAddress(connectionString, path); var linkSettings = new AmqpLinkSettings() { Role = true, TotalLinkCredit = prefetchCount, AutoSendFlow = prefetchCount > 0, Source = new Source() { Address = linkAddress.AbsoluteUri }, LinkName = Guid.NewGuid().ToString("N") // Use a human readable link name to help with debuggin }; switch (linkType) { // Exactly once case ReceivingLinkType.C2DMessages: linkSettings.SndSettleMode = null; // SenderSettleMode.Unsettled (null as it is the default and to avoid bytes on the wire) linkSettings.RcvSettleMode = (byte)ReceiverSettleMode.Second; break; // At least once case ReceivingLinkType.Events: linkSettings.SndSettleMode = null; // SenderSettleMode.Unsettled (null as it is the default and to avoid bytes on the wire) linkSettings.RcvSettleMode = (byte)ReceiverSettleMode.First; break; // At most once case ReceivingLinkType.Methods: case ReceivingLinkType.Twin: linkSettings.SndSettleMode = (byte)SenderSettleMode.Settled; linkSettings.RcvSettleMode = (byte)ReceiverSettleMode.First; break; } SetLinkSettingsCommonProperties(linkSettings, timeoutHelper.RemainingTime(), productInfo); if (linkType == ReceivingLinkType.Methods) { SetLinkSettingsCommonPropertiesForMethod(linkSettings, corrId); } else if (linkType == ReceivingLinkType.Twin) { SetLinkSettingsCommonPropertiesForTwin(linkSettings, corrId); } var link = new ReceivingAmqpLink(linkSettings); link.AttachTo(session); var audience = this.BuildAudience(connectionString, path); await this.OpenLinkAsync(link, connectionString, audience, timeoutHelper.RemainingTime(), cancellationToken).ConfigureAwait(false); return(link); } finally { if (Logging.IsEnabled) { Logging.Exit(this, corrId, linkType, $"{nameof(IotHubConnection)}.{nameof(CreateReceivingLinkAsync)}"); } } }