private async Task <Controller> CreateControllerAsync(TimeSpan timeout) { var stopWatch = ValueStopwatch.StartNew(); AmqpConnection connection = await ActiveConnection.GetOrCreateAsync(timeout.CalculateRemaining(stopWatch.GetElapsedTime())).ConfigureAwait(false); var sessionSettings = new AmqpSessionSettings { Properties = new Fields() }; AmqpSession amqpSession = null; Controller controller; try { amqpSession = connection.CreateSession(sessionSettings); await amqpSession.OpenAsync(timeout.CalculateRemaining(stopWatch.GetElapsedTime())).ConfigureAwait(false); controller = new Controller(amqpSession, timeout.CalculateRemaining(stopWatch.GetElapsedTime())); await controller.OpenAsync(timeout.CalculateRemaining(stopWatch.GetElapsedTime())).ConfigureAwait(false); } catch (Exception exception) { if (amqpSession != null) { await amqpSession.CloseAsync(timeout).ConfigureAwait(false); } ServiceBusEventSource.Log.CreateControllerException(ActiveConnection.ToString(), exception.ToString()); throw; } return(controller); }
private async Task <Controller> CreateControllerAsync(TimeSpan timeout) { var timeoutHelper = new TimeoutHelper(timeout, true); AmqpConnection connection = await ActiveConnection.GetOrCreateAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); var sessionSettings = new AmqpSessionSettings { Properties = new Fields() }; AmqpSession amqpSession = null; Controller controller; try { amqpSession = connection.CreateSession(sessionSettings); await amqpSession.OpenAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); controller = new Controller(amqpSession, timeoutHelper.RemainingTime()); await controller.OpenAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); } catch (Exception exception) { if (amqpSession != null) { await amqpSession.CloseAsync(timeout).ConfigureAwait(false); } MessagingEventSource.Log.AmqpCreateControllerException(ActiveConnection.ToString(), exception); throw; } return(controller); }
public async Task <AmqpObject> CreateAndOpenAmqpLinkAsync() { TimeoutHelper timeoutHelper = new TimeoutHelper(this.serviceBusConnection.OperationTimeout); AmqpConnection connection = await this.serviceBusConnection.ConnectionManager.GetOrCreateAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); // Authenticate over CBS AmqpCbsLink cbsLink = connection.Extensions.Find <AmqpCbsLink>(); Uri address = new Uri(this.serviceBusConnection.Endpoint, this.entityPath); string audience = address.AbsoluteUri; string resource = address.AbsoluteUri; await cbsLink.SendTokenAsync(this.cbsTokenProvider, address, audience, resource, this.requiredClaims, timeoutHelper.RemainingTime()).ConfigureAwait(false); AmqpSession session = null; try { // Create our Session AmqpSessionSettings sessionSettings = new AmqpSessionSettings { Properties = new Fields() }; session = connection.CreateSession(sessionSettings); await session.OpenAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); // Create our Link AmqpObject link = this.OnCreateAmqpLink(connection, this.amqpLinkSettings, session); await link.OpenAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); return(link); } catch (Exception) { session?.Abort(); throw; } }
public async Task <Tuple <AmqpObject, DateTime> > CreateAndOpenAmqpLinkAsync() { TimeoutHelper timeoutHelper = new TimeoutHelper(this.serviceBusConnection.OperationTimeout); MessagingEventSource.Log.AmqpGetOrCreateConnectionStart(); AmqpConnection connection = await this.serviceBusConnection.ConnectionManager.GetOrCreateAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); MessagingEventSource.Log.AmqpGetOrCreateConnectionStop(this.entityPath, connection.ToString(), connection.State.ToString()); // Authenticate over CBS AmqpCbsLink cbsLink = connection.Extensions.Find <AmqpCbsLink>(); string resource = this.endpointAddress.AbsoluteUri; MessagingEventSource.Log.AmqpSendAuthenticanTokenStart(this.endpointAddress, resource, resource, this.requiredClaims); DateTime cbsTokenExpiresAtUtc = await cbsLink.SendTokenAsync(this.cbsTokenProvider, this.endpointAddress, resource, resource, this.requiredClaims, timeoutHelper.RemainingTime()).ConfigureAwait(false); MessagingEventSource.Log.AmqpSendAuthenticanTokenStop(); AmqpSession session = null; try { // Create Session AmqpSessionSettings sessionSettings = new AmqpSessionSettings { Properties = new Fields() }; session = connection.CreateSession(sessionSettings); await session.OpenAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); } catch (Exception exception) { MessagingEventSource.Log.AmqpSessionCreationException(this.entityPath, connection, exception); session?.Abort(); throw AmqpExceptionHelper.GetClientException(exception, null, session.GetInnerException()); } AmqpObject link = null; try { // Create Link link = this.OnCreateAmqpLink(connection, this.amqpLinkSettings, session); await link.OpenAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); return(new Tuple <AmqpObject, DateTime>(link, cbsTokenExpiresAtUtc)); } catch (Exception exception) { MessagingEventSource.Log.AmqpLinkCreationException( this.entityPath, session, connection, exception); throw AmqpExceptionHelper.GetClientException(exception, null, link?.GetInnerException(), session.IsClosing()); } }
private async Task <ActiveClientRequestResponseLink> OpenRequestResponseLinkAsync( string type, string address, MessagingEntityType?entityType, string[] requiredClaims, TimeSpan timeout) { var timeoutHelper = new TimeoutHelper(timeout, true); AmqpSession session = null; try { // Don't need to get token for namespace scope operations, included in request bool isNamespaceScope = address.Equals(AmqpClientConstants.ManagementAddress, StringComparison.OrdinalIgnoreCase); AmqpConnection connection = await eventHubClient.ConnectionManager.GetOrCreateAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); var sessionSettings = new AmqpSessionSettings { Properties = new Fields() }; session = connection.CreateSession(sessionSettings); await session.OpenAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); var linkSettings = new AmqpLinkSettings(); linkSettings.AddProperty(AmqpClientConstants.TimeoutName, (uint)timeoutHelper.RemainingTime().TotalMilliseconds); if (entityType != null) { linkSettings.AddProperty(AmqpClientConstants.EntityTypeName, (int)entityType.Value); } // Create the link var link = new RequestResponseAmqpLink(type, session, address, linkSettings.Properties); DateTime authorizationValidToUtc = DateTime.MaxValue; if (!isNamespaceScope) { // TODO: Get Entity level token here } await link.OpenAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); // Redirected scenario requires entityPath as the audience, otherwise we // should always use the full EndpointUri as audience. return(new ActiveClientRequestResponseLink( link, eventHubClient.ConnectionStringBuilder.Endpoint.AbsoluteUri, // audience eventHubClient.ConnectionStringBuilder.Endpoint.AbsoluteUri, // endpointUri requiredClaims, false, authorizationValidToUtc)); } catch (Exception) { // Aborting the session will cleanup the link as well. session?.Abort(); throw; } }
async Task <AmqpSession> CreateSessionAsync(TimeSpan timeout) { var timeoutHelper = new TimeoutHelper(timeout); this.refreshTokenTimer.Cancel(); AmqpSettings amqpSettings = this.CreateAmqpSettings(); TlsTransportSettings tlsTransportSettings = this.CreateTlsTransportSettings(); var amqpTransportInitiator = new AmqpTransportInitiator(amqpSettings, tlsTransportSettings); TransportBase transport; switch (this.amqpTransportSettings.GetTransportType()) { case TransportType.Amqp_WebSocket_Only: transport = await this.CreateClientWebSocketTransport(timeoutHelper.RemainingTime()); break; case TransportType.Amqp_Tcp_Only: transport = await amqpTransportInitiator.ConnectTaskAsync(timeoutHelper.RemainingTime()); break; default: throw new InvalidOperationException("AmqpTransportSettings must specify WebSocketOnly or TcpOnly"); } var amqpConnectionSettings = new AmqpConnectionSettings() { MaxFrameSize = AmqpConstants.DefaultMaxFrameSize, ContainerId = Guid.NewGuid().ToString("N"), HostName = this.connectionString.AmqpEndpoint.Host }; var amqpConnection = new AmqpConnection(transport, amqpSettings, amqpConnectionSettings); await amqpConnection.OpenAsync(timeoutHelper.RemainingTime()); var sessionSettings = new AmqpSessionSettings() { Properties = new Fields() }; var amqpSession = amqpConnection.CreateSession(sessionSettings); await amqpSession.OpenAsync(timeoutHelper.RemainingTime()); // This adds itself to amqpConnection.Extensions var cbsLink = new AmqpCbsLink(amqpConnection); await this.SendCbsTokenAsync(cbsLink, timeoutHelper.RemainingTime()); return(amqpSession); }
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(); } }
protected virtual async Task <AmqpSession> CreateSessionAsync(TimeSpan timeout) { this.OnCreateSession(); var timeoutHelper = new TimeoutHelper(timeout); AmqpSettings amqpSettings = CreateAmqpSettings(); TransportBase transport; switch (this.AmqpTransportSettings.GetTransportType()) { #if !WINDOWS_UWP case TransportType.Amqp_WebSocket_Only: transport = await this.CreateClientWebSocketTransportAsync(timeoutHelper.RemainingTime()); break; #endif case TransportType.Amqp_Tcp_Only: TlsTransportSettings tlsTransportSettings = this.CreateTlsTransportSettings(); var amqpTransportInitiator = new AmqpTransportInitiator(amqpSettings, tlsTransportSettings); transport = await amqpTransportInitiator.ConnectTaskAsync(timeoutHelper.RemainingTime()); break; default: throw new InvalidOperationException("AmqpTransportSettings must specify WebSocketOnly or TcpOnly"); } var amqpConnectionSettings = new AmqpConnectionSettings() { MaxFrameSize = AmqpConstants.DefaultMaxFrameSize, ContainerId = Guid.NewGuid().ToString("N"), HostName = this.hostName }; var amqpConnection = new AmqpConnection(transport, amqpSettings, amqpConnectionSettings); await amqpConnection.OpenAsync(timeoutHelper.RemainingTime()); var sessionSettings = new AmqpSessionSettings() { Properties = new Fields() }; var amqpSession = amqpConnection.CreateSession(sessionSettings); await amqpSession.OpenAsync(timeoutHelper.RemainingTime()); // This adds itself to amqpConnection.Extensions var cbsLink = new AmqpCbsLink(amqpConnection); return(amqpSession); }
public void AmqpWebSocketTransportTest() { string queue = "AmqpWebSocketTransportTest"; broker.AddQueue(queue); AmqpConnection connection = AmqpConnection.Factory.OpenConnectionAsync( TestAmqpBrokerFixture.WsAddress.OriginalString).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 = 1800; for (int i = 0; i < messageCount; i++) { AmqpMessage message = AmqpMessage.Create(new AmqpValue() { Value = "message" + i }); sLink.SendMessageAsync(message, EmptyBinary, 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); message2.Dispose(); } rLink.Close(); connection.Close(); }
/// <summary> /// Creates an AMQP link for use with management operations. /// </summary> /// /// <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(AmqpConnection connection, TimeSpan timeout, CancellationToken cancellationToken) { Argument.AssertNotDisposed(IsDisposed, nameof(AmqpConnectionScope)); cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>(); var session = default(AmqpSession); var stopWatch = Stopwatch.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(AmqpProperty.Timeout, (uint)timeout.CalculateRemaining(stopWatch.Elapsed).TotalMilliseconds); var link = new RequestResponseAmqpLink(AmqpManagement.LinkType, session, AmqpManagement.Address, linkSettings.Properties); stopWatch.Stop(); // Track the link before returning it, so that it can be managed with the scope. BeginTrackingLinkAsActive(link); return(link); } catch { // Aborting the session will perform any necessary cleanup of // the associated link as well. session?.Abort(); throw; } }
/// <summary> /// Creates the AMQP link used to trigger a redirection response from the /// IoT Hub service. /// </summary> /// <param name="connection">The connection to the IoT Hub service to associate the link with.</param> /// <param name="serviceEndpoint">The endpoint of the IoT Hub service that the connection was made to.</param> /// <param name="timeout">The maximum amount of time that creating the link should be allowed to take.</param> /// <returns>An <see cref="AmqpLink" /> to an IoT Hub resource that will trigger redirection when opened.</returns> /// <remarks> /// The link is not opened by this method; callers are required to open the link in order to trigger /// the redirection error. /// </remarks> /// <seealso href="https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-amqp-support"/> private static async Task <AmqpLink> CreateRedirectLinkAsync( AmqpConnection connection, Uri serviceEndpoint, TimeSpan timeout) { var linkPath = $"{ serviceEndpoint.AbsolutePath }/$management"; var session = default(AmqpSession); try { var sessionSettings = new AmqpSessionSettings { Properties = new Fields() }; session = connection.CreateSession(sessionSettings); await session.OpenAsync(timeout).ConfigureAwait(false); var linkSettings = new AmqpLinkSettings { Role = true, TotalLinkCredit = 1, AutoSendFlow = true, SettleType = SettleMode.SettleOnSend, Source = new Source { Address = linkPath }, Target = new Target { Address = serviceEndpoint.AbsoluteUri } }; var link = new ReceivingAmqpLink(linkSettings); linkSettings.LinkName = $"{ nameof(IotHubConnection) };{ connection.Identifier }:{ session.Identifier }:{ link.Identifier }"; link.AttachTo(session); return(link); } catch { session?.Abort(); throw; } }
async Task RunClientAsync(string address) { AmqpConnectionFactory factory = new AmqpConnectionFactory(); factory.Settings.TransportProviders.Add( new TlsTransportProvider( new TlsTransportSettings() { CertificateValidationCallback = (a, b, c, d) => true }, AmqpVersion.V100)); AmqpConnection connection = await factory.OpenConnectionAsync(address); AmqpSession session = connection.CreateSession(new AmqpSessionSettings()); await session.OpenAsync(TimeSpan.FromSeconds(20)); SendingAmqpLink sLink = new SendingAmqpLink(session, AmqpUtils.GetLinkSettings(true, queue, SettleMode.SettleOnSend)); await sLink.OpenAsync(TimeSpan.FromSeconds(20)); AmqpMessage message = AmqpMessage.Create(new AmqpValue() { Value = "AmqpConnectionFactoryTest" }); Outcome outcome = await sLink.SendMessageAsync(message, EmptyBinary, NullBinary, TimeSpan.FromSeconds(10)); Assert.Equal(Accepted.Code, outcome.DescriptorCode); ReceivingAmqpLink rLink = new ReceivingAmqpLink(session, AmqpUtils.GetLinkSettings(false, queue, SettleMode.SettleOnDispose, 10)); await rLink.OpenAsync(TimeSpan.FromSeconds(20)); var receivedMessage = await rLink.ReceiveMessageAsync(TimeSpan.FromSeconds(20)); Assert.NotNull(receivedMessage); outcome = await rLink.DisposeMessageAsync(receivedMessage.DeliveryTag, new Accepted(), false, TimeSpan.FromSeconds(20)); Assert.Equal(Accepted.Code, outcome.DescriptorCode); await connection.CloseAsync(TimeSpan.FromSeconds(20)); }
async Task <AmqpSession> CreateSessionAsync(TimeSpan timeout) { TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); this.refreshTokenTimer.Cancel(); var amqpSettings = this.CreateAmqpSettings(); var tlsTransportSettings = this.CreateTlsTransportSettings(); var amqpTransportInitiator = new AmqpTransportInitiator(amqpSettings, tlsTransportSettings); var transport = await amqpTransportInitiator.ConnectTaskAsync(timeoutHelper.RemainingTime()); AmqpConnectionSettings amqpConnectionSettings = new AmqpConnectionSettings() { MaxFrameSize = AmqpConstants.DefaultMaxFrameSize, ContainerId = Guid.NewGuid().ToString("N"), HostName = this.connectionString.AmqpEndpoint.Host }; var amqpConnection = new AmqpConnection(transport, amqpSettings, amqpConnectionSettings); await amqpConnection.OpenAsync(timeoutHelper.RemainingTime()); var sessionSettings = new AmqpSessionSettings() { Properties = new Fields() }; var amqpSession = amqpConnection.CreateSession(sessionSettings); await amqpSession.OpenAsync(timeoutHelper.RemainingTime()); // This adds itself to amqpConnection.Extensions var cbsLink = new AmqpCbsLink(amqpConnection); await this.SendCbsTokenAsync(cbsLink, timeoutHelper.RemainingTime()); return(amqpSession); }
private async Task <AmqpSession> CreateSessionAsync(TimeSpan timeout) { Logging.Enter(this, timeout, nameof(CreateSessionAsync)); TransportBase transport = null; try { var timeoutHelper = new TimeoutHelper(timeout); _refreshTokenTimer.Cancel(); AmqpSettings amqpSettings = CreateAmqpSettings(); if (_useWebSocketOnly) { // Try only AMQP transport over WebSocket transport = _clientWebSocketTransport = (ClientWebSocketTransport) await CreateClientWebSocketTransportAsync(timeoutHelper.RemainingTime()) .ConfigureAwait(false); } else { TlsTransportSettings tlsTransportSettings = CreateTlsTransportSettings(); var amqpTransportInitiator = new AmqpTransportInitiator(amqpSettings, tlsTransportSettings); try { transport = await amqpTransportInitiator.ConnectTaskAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); } catch (Exception e) when(!(e is AuthenticationException)) { Logging.Error(this, e, nameof(CreateSessionAsync)); if (Fx.IsFatal(e)) { throw; } // AMQP transport over TCP failed. Retry AMQP transport over WebSocket if (timeoutHelper.RemainingTime() != TimeSpan.Zero) { transport = _clientWebSocketTransport = (ClientWebSocketTransport) await CreateClientWebSocketTransportAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); } else { throw; } } } Logging.Info(this, $"Initialized {nameof(TransportBase)}, ws={_useWebSocketOnly}"); var amqpConnectionSettings = new AmqpConnectionSettings { MaxFrameSize = AmqpConstants.DefaultMaxFrameSize, ContainerId = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture), // Use a human readable link name to help with debugging HostName = ConnectionString.AmqpEndpoint.Host, }; var amqpConnection = new AmqpConnection(transport, amqpSettings, amqpConnectionSettings); await amqpConnection.OpenAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); Logging.Info(this, $"{nameof(AmqpConnection)} opened."); var sessionSettings = new AmqpSessionSettings { Properties = new Fields(), }; try { AmqpSession amqpSession = amqpConnection.CreateSession(sessionSettings); await amqpSession.OpenAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); Logging.Info(this, $"{nameof(AmqpSession)} opened."); // This adds itself to amqpConnection.Extensions var cbsLink = new AmqpCbsLink(amqpConnection); await SendCbsTokenAsync(cbsLink, timeoutHelper.RemainingTime()).ConfigureAwait(false); return(amqpSession); } catch (Exception ex) when(!ex.IsFatal()) { Logging.Error(this, ex, nameof(CreateSessionAsync)); _clientWebSocketTransport?.Dispose(); _clientWebSocketTransport = null; if (amqpConnection.TerminalException != null) { throw AmqpClientHelper.ToIotHubClientContract(amqpConnection.TerminalException); } amqpConnection.SafeClose(ex); throw; } } finally { Logging.Exit(this, timeout, nameof(CreateSessionAsync)); } }
private async Task <SendingAmqpLink> CreateLinkAsync(TimeSpan timeout) { var amqpEventHubClient = ((AmqpEventHubClient)EventHubClient); var timeoutHelper = new TimeoutHelper(timeout); AmqpConnection connection = await amqpEventHubClient.ConnectionManager.GetOrCreateAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); // Authenticate over CBS AmqpCbsLink cbsLink = connection.Extensions.Find <AmqpCbsLink>(); ICbsTokenProvider cbsTokenProvider = amqpEventHubClient.CbsTokenProvider; Uri address = new Uri(amqpEventHubClient.ConnectionStringBuilder.Endpoint, Path); string audience = address.AbsoluteUri; string resource = address.AbsoluteUri; DateTime 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 = 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 EventHubClient.ConnectionStringBuilder.Endpoint.AbsoluteUri, // endpointUri new[] { ClaimConstants.Send }, true, expiresAt); MaxMessageSize = (long)activeClientLink.Link.Settings.MaxMessageSize(); _clientLinkManager.SetActiveLink(activeClientLink); _linkCreated = true; return(link); } catch { // Cleanup any session (and thus link) in case of exception. session?.Abort(); throw; } }
async Task <AmqpSession> CreateSessionAsync(TimeSpan timeout) { TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); this.refreshTokenTimer.Cancel(); var amqpSettings = this.CreateAmqpSettings(); TransportBase transport; if (this.useWebSocketOnly) { // Try only Amqp transport over WebSocket transport = await this.CreateClientWebSocketTransport(timeoutHelper.RemainingTime()); } else { var tlsTransportSettings = this.CreateTlsTransportSettings(); var amqpTransportInitiator = new AmqpTransportInitiator(amqpSettings, tlsTransportSettings); try { transport = await amqpTransportInitiator.ConnectTaskAsync(timeoutHelper.RemainingTime()); } catch (Exception e) { if (Fx.IsFatal(e)) { throw; } // Amqp transport over TCP failed. Retry Amqp transport over WebSocket if (timeoutHelper.RemainingTime() != TimeSpan.Zero) { transport = await this.CreateClientWebSocketTransport(timeoutHelper.RemainingTime()); } else { throw; } } } AmqpConnectionSettings amqpConnectionSettings = new AmqpConnectionSettings() { MaxFrameSize = AmqpConstants.DefaultMaxFrameSize, ContainerId = Guid.NewGuid().ToString("N"), HostName = this.connectionString.AmqpEndpoint.Host }; var amqpConnection = new AmqpConnection(transport, amqpSettings, amqpConnectionSettings); await amqpConnection.OpenAsync(timeoutHelper.RemainingTime()); var sessionSettings = new AmqpSessionSettings() { Properties = new Fields() }; var amqpSession = amqpConnection.CreateSession(sessionSettings); await amqpSession.OpenAsync(timeoutHelper.RemainingTime()); // This adds itself to amqpConnection.Extensions var cbsLink = new AmqpCbsLink(amqpConnection); await this.SendCbsTokenAsync(cbsLink, timeoutHelper.RemainingTime()); return(amqpSession); }
/// <summary> /// Creates an AMQP link for use with receiving operations. /// </summary> /// <param name="entityPath"></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"></param> /// <param name="isSessionReceiver"></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 = Stopwatch.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.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>(); 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); stopWatch.Stop(); // 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(); throw AmqpExceptionHelper.TranslateException( exception, null, session.GetInnerException(), connection.IsClosing()); } }
/// <summary> /// Creates an AMQP link for use with publishing operations. /// </summary> /// <param name="entityPath"></param> /// <param name="viaEntityPath">The entity path to route the message through. Useful when using transactions.</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, string viaEntityPath, AmqpConnection connection, TimeSpan timeout, CancellationToken cancellationToken) { Argument.AssertNotDisposed(IsDisposed, nameof(AmqpConnectionScope)); cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>(); var session = default(AmqpSession); var stopWatch = Stopwatch.StartNew(); try { string[] audience; Uri destinationEndpoint = null; // if there is a via entityPath, include that in the audience if (!string.IsNullOrEmpty(viaEntityPath)) { destinationEndpoint = new Uri(ServiceEndpoint, viaEntityPath); var finalDestinationEndpoint = new Uri(ServiceEndpoint, entityPath); audience = new string[] { finalDestinationEndpoint.AbsoluteUri, destinationEndpoint.AbsoluteUri }; } else { 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.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 = destinationEndpoint.AbsolutePath } }; if (!string.IsNullOrEmpty(viaEntityPath)) { linkSettings.AddProperty(AmqpClientConstants.TransferDestinationAddress, entityPath); } linkSettings.AddProperty(AmqpProperty.Timeout, (uint)timeout.CalculateRemaining(stopWatch.Elapsed).TotalMilliseconds); 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); 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(); throw AmqpExceptionHelper.TranslateException( exception, null, session.GetInnerException(), connection.IsClosing()); } }
private async Task <AmqpSession> CreateSessionAsync(TimeSpan timeout) { var timeoutHelper = new TimeoutHelper(timeout); _refreshTokenTimer.Cancel(); AmqpSettings amqpSettings = CreateAmqpSettings(); TransportBase transport; if (_useWebSocketOnly) { // Try only Amqp transport over WebSocket transport = await CreateClientWebSocketTransport(timeoutHelper.RemainingTime()).ConfigureAwait(false); } else { TlsTransportSettings tlsTransportSettings = CreateTlsTransportSettings(); var amqpTransportInitiator = new AmqpTransportInitiator(amqpSettings, tlsTransportSettings); try { transport = await amqpTransportInitiator.ConnectTaskAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); } #if !NETSTANDARD1_3 catch (AuthenticationException) { throw; } #endif catch (Exception e) { if (Fx.IsFatal(e)) { throw; } // Amqp transport over TCP failed. Retry Amqp transport over WebSocket if (timeoutHelper.RemainingTime() != TimeSpan.Zero) { transport = await CreateClientWebSocketTransport(timeoutHelper.RemainingTime()).ConfigureAwait(false); } else { throw; } } } var amqpConnectionSettings = new AmqpConnectionSettings { MaxFrameSize = AmqpConstants.DefaultMaxFrameSize, ContainerId = Guid.NewGuid() #if NETSTANDARD1_3 .ToString("N"), #else .ToString("N", CultureInfo.InvariantCulture), // Use a human readable link name to help with debugging #endif HostName = ConnectionString.AmqpEndpoint.Host, }; var amqpConnection = new AmqpConnection(transport, amqpSettings, amqpConnectionSettings); await amqpConnection.OpenAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); var sessionSettings = new AmqpSessionSettings { Properties = new Fields(), }; try { AmqpSession amqpSession = amqpConnection.CreateSession(sessionSettings); await amqpSession.OpenAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false); // This adds itself to amqpConnection.Extensions var cbsLink = new AmqpCbsLink(amqpConnection); await SendCbsTokenAsync(cbsLink, timeoutHelper.RemainingTime()).ConfigureAwait(false); return(amqpSession); } catch (Exception ex) when(!ex.IsFatal()) { if (amqpConnection.TerminalException != null) { throw AmqpClientHelper.ToIotHubClientContract(amqpConnection.TerminalException); } amqpConnection.SafeClose(ex); throw; } }
/// <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 = Stopwatch.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(AmqpProperty.Timeout, (uint)timeout.CalculateRemaining(stopWatch.Elapsed).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.Elapsed)) .ConfigureAwait(false); var link = new RequestResponseAmqpLink( AmqpClientConstants.EntityTypeManagement, session, entityPath, linkSettings.Properties); linkSettings.LinkName = $"{connection.Settings.ContainerId};{connection.Identifier}:{session.Identifier}:{link.Identifier}"; stopWatch.Stop(); // 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(); throw AmqpExceptionHelper.TranslateException( exception, null, session.GetInnerException(), connection.IsClosing()); } }
/// <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, EventHubConsumerOptions 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 (!string.IsNullOrEmpty(consumerOptions.Identifier)) { linkSettings.AddProperty(AmqpProperty.ConsumerIdentifier, consumerOptions.Identifier); } 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; } }
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?.SafeClose(); 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; } }
/// <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="prefetchCount">Controls the number of events received and queued locally without regard to whether an operation was requested.</param> /// <param name="ownerLevel">The relative priority to associate with the link; for a non-exclusive link, this value should be <c>null</c>.</param> /// <param name="sessionId"></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, TimeSpan timeout, uint prefetchCount, long?ownerLevel, string sessionId, 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[] { ServiceBusClaim.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(); if (sessionId != null) { filters.Add(AmqpClientConstants.SessionFilterName, sessionId); } //if (this.isSessionReceiver) //{ // filterMap = new FilterSet { { AmqpClientConstants.SessionFilterName, this.SessionIdInternal } }; //} var linkSettings = new AmqpLinkSettings { Role = true, TotalLinkCredit = prefetchCount, AutoSendFlow = prefetchCount > 0, SettleType = SettleMode.SettleOnSend, Source = new Source { Address = endpoint.AbsolutePath, FilterSet = filters }, Target = new Target { Address = Guid.NewGuid().ToString() } }; //linkSettings.AddProperty(AmqpProperty.EntityType, "0,1,2,3");//(int)AmqpProperty.Entity.ConsumerGroup); if (ownerLevel.HasValue) { linkSettings.AddProperty(AmqpProperty.OwnerLevel, ownerLevel.Value); } var link = new ReceivingAmqpLink(linkSettings); linkSettings.LinkName = $"{connection.Settings.ContainerId};{connection.Identifier}:{session.Identifier}:{link.Identifier}:{linkSettings.Source.ToString()}:test"; //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, () => (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(link, refreshTimer); return(link); } catch { // Aborting the session will perform any necessary cleanup of // the associated link as well. session?.Abort(); throw; } }
protected virtual async Task <AmqpSession> CreateSessionAsync(TimeSpan timeout, CancellationToken token) { this.OnCreateSession(); var timeoutHelper = new TimeoutHelper(timeout); AmqpSettings amqpSettings = CreateAmqpSettings(); TransportBase transport; token.ThrowIfCancellationRequested(); switch (this.AmqpTransportSettings.GetTransportType()) { #if !WINDOWS_UWP && !PCL case TransportType.Amqp_WebSocket_Only: transport = await this.CreateClientWebSocketTransportAsync(timeoutHelper.RemainingTime()); break; #endif case TransportType.Amqp_Tcp_Only: TlsTransportSettings tlsTransportSettings = this.CreateTlsTransportSettings(); var amqpTransportInitiator = new AmqpTransportInitiator(amqpSettings, tlsTransportSettings); transport = await amqpTransportInitiator.ConnectTaskAsync(timeoutHelper.RemainingTime()); break; default: throw new InvalidOperationException("AmqpTransportSettings must specify WebSocketOnly or TcpOnly"); } var amqpConnectionSettings = new AmqpConnectionSettings() { MaxFrameSize = AmqpConstants.DefaultMaxFrameSize, ContainerId = Guid.NewGuid().ToString("N"), HostName = this.hostName }; var amqpConnection = new AmqpConnection(transport, amqpSettings, amqpConnectionSettings); try { token.ThrowIfCancellationRequested(); await amqpConnection.OpenAsync(timeoutHelper.RemainingTime()); var sessionSettings = new AmqpSessionSettings() { Properties = new Fields() }; AmqpSession amqpSession = amqpConnection.CreateSession(sessionSettings); token.ThrowIfCancellationRequested(); await amqpSession.OpenAsync(timeoutHelper.RemainingTime()); // This adds itself to amqpConnection.Extensions var cbsLink = new AmqpCbsLink(amqpConnection); return(amqpSession); } catch (Exception ex) when(!ex.IsFatal()) { if (amqpConnection.TerminalException != null) { throw AmqpClientHelper.ToIotHubClientContract(amqpConnection.TerminalException); } amqpConnection.SafeClose(ex); throw; } }