Example #1
0
        public AmqpSession CreateSession(AmqpSessionSettings sessionSettings)
        {
            if (this.IsClosing())
            {
                throw new InvalidOperationException(CommonResources.CreateSessionOnClosingConnection);
            }

            AmqpSession session = this.SessionFactory.CreateSession(this, sessionSettings);
            this.AddSession(session, null);
            return session;
        }
Example #2
0
 protected AmqpSession(string type, AmqpConnection connection, AmqpSessionSettings settings, ILinkFactory linkFactory)
     : base(type)
 {
     Fx.Assert(connection != null, "connection must not be null");
     Fx.Assert(settings != null, "settings must not be null");
     this.connection = connection;
     this.settings = settings;
     this.linkFactory = linkFactory;
     this.State = AmqpObjectState.Start;
     this.links = new Dictionary<string, AmqpLink>();
     this.linksByLocalHandle = new HandleTable<AmqpLink>(settings.HandleMax ?? AmqpConstants.DefaultMaxLinkHandles - 1);
     this.linksByRemoteHandle = new HandleTable<AmqpLink>(settings.HandleMax ?? AmqpConstants.DefaultMaxLinkHandles - 1);
     this.outgoingChannel = new OutgoingSessionChannel(this);
     this.incomingChannel = new IncomingSessionChannel(this);
 }
        /// <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
            }
        }
Example #4
0
        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;
            }
        }
Example #5
0
        async Task <AmqpSession> CreateSessionAsync(TimeSpan timeout)
        {
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);

            this.refreshTokenTimer.Cancel();

            var           amqpSettings = 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);
        }
        async Task <SendingAmqpLink> CreateLinkAsync(TimeSpan timeout)
        {
            var            amqpEventHubClient = ((AmqpEventHubClient)this.EventHubClient);
            var            csb           = amqpEventHubClient.ConnectionStringBuilder;
            var            timeoutHelper = new TimeoutHelper(csb.OperationTimeout);
            AmqpConnection connection    = await amqpEventHubClient.ConnectionManager.GetOrCreateAsync(timeoutHelper.RemainingTime());

            // Authenticate over CBS
            var cbsLink = connection.Extensions.Find <AmqpCbsLink>();

            ICbsTokenProvider cbsTokenProvider = amqpEventHubClient.CbsTokenProvider;
            Uri    address   = new Uri(csb.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());

            AmqpSession session = null;

            try
            {
                // Create our Session
                var sessionSettings = new AmqpSessionSettings {
                    Properties = new Fields()
                };
                session = connection.CreateSession(sessionSettings);
                await session.OpenAsync(timeoutHelper.RemainingTime());

                // 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());

                var activeClientLink = new ActiveClientLink(
                    link,
                    this.EventHubClient.ConnectionStringBuilder.Endpoint.AbsoluteUri, // audience
                    this.EventHubClient.ConnectionStringBuilder.Endpoint.AbsoluteUri, // endpointUri
                    new[] { ClaimConstants.Send },
                    true,
                    expiresAt);

                this.clientLinkManager.SetActiveLink(activeClientLink);

                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;
        }
Example #8
0
        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));
            }
        }
Example #9
0
 public AmqpSession CreateSession(AmqpConnection connection, AmqpSessionSettings settings)
 {
     throw new InvalidOperationException();
 }
 public AmqpSession CreateSession(AmqpConnection connection, AmqpSessionSettings settings)
 {
     return(new AmqpSession(connection, settings, this));
 }
        /// <summary>
        ///   Creates an AMQP link for use with receiving operations.
        /// </summary>
        /// <param name="entityName"></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 entityName,
            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.

                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>();

                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 = (uint)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);

                var refreshHandler = CreateAuthorizationRefreshHandler
                                     (
                    entityName,
                    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(entityName, link, refreshTimer);
                return(link);
            }
            catch
            {
                // Aborting the session will perform any necessary cleanup of
                // the associated link as well.

                session?.Abort();
                throw;
            }
        }
Example #12
0
 AmqpSession ISessionFactory.CreateSession(AmqpConnection connection, AmqpSessionSettings sessionSettings)
 {
     return new AmqpSession(this, sessionSettings, this.amqpSettings.RuntimeProvider);
 }
        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;
            }
        }
Example #14
0
            protected override IEnumerator <IteratorTask <object> .TaskStep> GetTasks()
            {
                ConnectivityMode connectivityMode;
                object           obj  = null;
                bool             flag = false;

                try
                {
                    object thisLock = this.relay.ThisLock;
                    object obj1     = thisLock;
                    obj = thisLock;
                    Monitor.Enter(obj1, ref flag);
                    if (this.relay.State != AmqpObjectState.OpenReceived && this.relay.State != AmqpObjectState.Opened)
                    {
                        goto Label0;
                    }
                }
                finally
                {
                    if (flag)
                    {
                        Monitor.Exit(obj);
                    }
                }
                Microsoft.ServiceBus.Common.TimeoutHelper timeoutHelper = new Microsoft.ServiceBus.Common.TimeoutHelper(this.timeout);
                string       host        = this.relay.serviceBusUri.Host;
                AmqpSettings amqpSetting = AmqpRelay.ConnectTask.CreateAmqpSettings();

                connectivityMode = (this.relay.connectivitySettings != null ? this.relay.connectivitySettings.Mode : ServiceBusEnvironment.SystemConnectivity.Mode);
                ConnectivityMode connectivityMode1 = connectivityMode;

                if (connectivityMode1 == ConnectivityMode.Tcp)
                {
                    TcpTransportSettings tcpTransportSetting = new TcpTransportSettings()
                    {
                        Host = host,
                        Port = 5671
                    };
                    TlsTransportSettings tlsTransportSetting = new TlsTransportSettings(tcpTransportSetting)
                    {
                        TargetHost = host
                    };
                    AmqpTransportInitiator amqpTransportInitiator = new AmqpTransportInitiator(amqpSetting, tlsTransportSetting);
                    yield return(base.CallTask(amqpTransportInitiator.ConnectTaskAsync(timeoutHelper.RemainingTime()), IteratorTask <TResult> .ExceptionPolicy.Transfer));
                }
                else if (connectivityMode1 == ConnectivityMode.Http || this.relay.httpConnectivitySettings != null)
                {
                    WebSocketTransportSettings webSocketTransportSetting = new WebSocketTransportSettings(this.relay.serviceBusUri);
                    AmqpTransportInitiator     amqpTransportInitiator1   = new AmqpTransportInitiator(amqpSetting, webSocketTransportSetting);
                    yield return(base.CallTask(amqpTransportInitiator1.ConnectTaskAsync(timeoutHelper.RemainingTime()), IteratorTask <TResult> .ExceptionPolicy.Transfer));
                }
                else
                {
                    TcpTransportSettings tcpTransportSetting1 = new TcpTransportSettings()
                    {
                        Host = host,
                        Port = 5671
                    };
                    TlsTransportSettings tlsTransportSetting1 = new TlsTransportSettings(tcpTransportSetting1)
                    {
                        TargetHost = host
                    };
                    AmqpTransportInitiator amqpTransportInitiator2 = new AmqpTransportInitiator(amqpSetting, tlsTransportSetting1);
                    yield return(base.CallTask(amqpTransportInitiator2.ConnectTaskAsync(Microsoft.ServiceBus.Common.TimeoutHelper.Divide(timeoutHelper.RemainingTime(), 2)), IteratorTask <TResult> .ExceptionPolicy.Continue));

                    if (base.LastTask.Exception != null)
                    {
                        if (timeoutHelper.RemainingTime() == TimeSpan.Zero)
                        {
                            throw base.LastTask.Exception;
                        }
                        WebSocketTransportSettings webSocketTransportSetting1 = new WebSocketTransportSettings(this.relay.serviceBusUri);
                        AmqpTransportInitiator     amqpTransportInitiator3    = new AmqpTransportInitiator(amqpSetting, webSocketTransportSetting1);
                        yield return(base.CallTask(amqpTransportInitiator3.ConnectTaskAsync(timeoutHelper.RemainingTime()), IteratorTask <TResult> .ExceptionPolicy.Transfer));
                    }
                }
                TransportBase transportBase = base.LastTaskResult <TransportBase>();

                string[] strArrays = host.Split(new char[] { '.' });
                strArrays[0] = string.Concat(strArrays[0], "-relay");
                AmqpConnectionSettings amqpConnectionSetting = new AmqpConnectionSettings()
                {
                    ContainerId = Guid.NewGuid().ToString(),
                    HostName    = string.Join(".", strArrays)
                };

                this.relay.connection = new AmqpConnection(transportBase, amqpSetting, amqpConnectionSetting);
                yield return(base.CallTask(this.relay.connection.OpenAsync(timeoutHelper.RemainingTime()), IteratorTask <TResult> .ExceptionPolicy.Transfer));

                AmqpSessionSettings amqpSessionSetting = new AmqpSessionSettings();
                AmqpSession         amqpSession        = this.relay.connection.CreateSession(amqpSessionSetting);

                yield return(base.CallTask(amqpSession.OpenAsync(timeoutHelper.RemainingTime()), IteratorTask <TResult> .ExceptionPolicy.Transfer));

                AmqpLinkSettings amqpLinkSetting = new AmqpLinkSettings()
                {
                    Role = new bool?(false),
                    InitialDeliveryCount = new uint?(0),
                    LinkName             = string.Concat("HttpRelayServer_Link_", Guid.NewGuid()),
                    Target          = new Target(this.relay.serviceBusUri),
                    Source          = new Source(this.relay.serviceBusUri),
                    TotalLinkCredit = 1000,
                    AutoSendFlow    = true
                };
                AmqpLinkSettings amqpLinkSetting1 = amqpLinkSetting;

                if (this.relay.tokenRenewer != null)
                {
                    amqpLinkSetting1.AddProperty(AmqpConstants.SimpleWebTokenPropertyName, this.relay.tokenRenewer.CurrentToken.Token);
                }
                if (!this.relay.TransportSecurityRequired)
                {
                    amqpLinkSetting1.AddProperty(ClientConstants.TransportSecurityRequiredName, false);
                }
                if (!this.relay.RelayClientAuthorizationRequired)
                {
                    amqpLinkSetting1.AddProperty(ClientConstants.ClientAuthenticationRequiredName, false);
                }
                if (this.relay.PublishToRegistry)
                {
                    amqpLinkSetting1.AddProperty(ClientConstants.RequiresPublicRegistry, true);
                }
                if (!string.IsNullOrEmpty(this.relay.ClientAgent))
                {
                    amqpLinkSetting1.AddProperty(ClientConstants.ClientAgent, this.relay.ClientAgent);
                }
                if (!string.IsNullOrEmpty(this.relay.DisplayName))
                {
                    amqpLinkSetting1.AddProperty(ClientConstants.DisplayName, this.relay.DisplayName);
                }
                amqpLinkSetting1.AddProperty(ClientConstants.DynamicRelay, this.relay.IsDynamic);
                amqpLinkSetting1.AddProperty(ClientConstants.ListenerTypeName, this.relay.ListenerType.ToString());
                this.relay.link = new DuplexAmqpLink(amqpSession, amqpLinkSetting1);
                yield return(base.CallTask(this.relay.link.OpenAsync(timeoutHelper.RemainingTime()), IteratorTask <TResult> .ExceptionPolicy.Transfer));

                this.relay.link.SafeAddClosed(this.relay.onAmqpObjectClosed);
                this.relay.link.RegisterMessageListener((AmqpMessage msg) => this.relay.messageListener(this.relay.link, msg));
                this.relay.OnOnline();
Label0:
                yield break;
            }
Example #15
0
        private async Task <AmqpSession> AmqpSessionCreator(DeviceIdentity deviceIdentity, ILinkFactory linkFactory, AmqpSessionSettings amqpSessionSettings, TimeSpan timeout)
        {
            if (Logging.IsEnabled)
            {
                Logging.Enter(this, deviceIdentity, timeout, $"{nameof(AmqpSessionCreator)}");
            }
            AmqpConnection amqpConnection = await EnsureConnection(timeout).ConfigureAwait(false);

            AmqpSession amqpSession = new AmqpSession(amqpConnection, amqpSessionSettings, linkFactory);

            amqpConnection.AddSession(amqpSession, new ushort?());
            if (Logging.IsEnabled)
            {
                Logging.Associate(amqpConnection, amqpSession, $"{nameof(AmqpSessionCreator)}");
            }
            if (Logging.IsEnabled)
            {
                Logging.Exit(this, deviceIdentity, timeout, $"{nameof(AmqpSessionCreator)}");
            }
            return(amqpSession);
        }
Example #16
0
 public AmqpClientSession(AmqpClientConnection amqpTestConnection)
 {
     _amqpConnection     = amqpTestConnection;
     AmqpSessionSettings = new AmqpSessionSettings();
 }
        /// <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 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);
                linkSettings.AddProperty(AmqpClientConstants.EntityTypeName, AmqpClientConstants.EntityTypeManagement);
                var      entityPath  = EntityName + '/' + AmqpClientConstants.ManagementAddress;
                string[] claims      = { ClaimConstants.Manage, ClaimConstants.Listen };
                var      endpointUri = new Uri(ServiceEndpoint, entityPath);

                var authExpirationUtc = await RequestAuthorizationUsingCbsAsync(connection, TokenProvider, ServiceEndpoint, endpointUri.AbsoluteUri, endpointUri.AbsoluteUri, claims, timeout.CalculateRemaining(stopWatch.Elapsed)).ConfigureAwait(false);

                var link = new RequestResponseAmqpLink(/*AmqpManagement.LinkType*/ "entity-mgmt", 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);

                var refreshHandler = CreateAuthorizationRefreshHandler
                                     (
                    connection,
                    link,
                    TokenProvider,
                    ServiceEndpoint,
                    ServiceEndpoint.AbsoluteUri,
                    ServiceEndpoint.AbsoluteUri,
                    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(link, refreshTimer);
                return(link);
            }
            catch
            {
                // Aborting the session will perform any necessary cleanup of
                // the associated link as well.

                session?.Abort();
                throw;
            }
        }
Example #19
0
 public AmqpSession CreateSession(AmqpConnection connection, AmqpSessionSettings settings)
 {
     throw new InvalidOperationException();
 }
        public async Task <Tuple <AmqpObject, DateTime> > CreateAndOpenAmqpLinkAsync()
        {
            var timeoutHelper = new TimeoutHelper(this.serviceBusConnection.OperationTimeout, true);

            MessagingEventSource.Log.AmqpGetOrCreateConnectionStart();
            var amqpConnection = await this.serviceBusConnection.ConnectionManager.GetOrCreateAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false);

            MessagingEventSource.Log.AmqpGetOrCreateConnectionStop(this.entityPath, amqpConnection.ToString(), amqpConnection.State.ToString());

            // Authenticate over CBS
            var      cbsLink = amqpConnection.Extensions.Find <AmqpCbsLink>();
            DateTime cbsTokenExpiresAtUtc = DateTime.MaxValue;

            foreach (var resource in this.audience)
            {
                MessagingEventSource.Log.AmqpSendAuthenticationTokenStart(this.endpointAddress, resource, resource, this.requiredClaims);
                cbsTokenExpiresAtUtc = TimeoutHelper.Min(
                    cbsTokenExpiresAtUtc,
                    await cbsLink.SendTokenAsync(this.cbsTokenProvider, this.endpointAddress, resource, resource, this.requiredClaims, timeoutHelper.RemainingTime()).ConfigureAwait(false));
                MessagingEventSource.Log.AmqpSendAuthenticationTokenStop();
            }

            AmqpSession session = null;

            try
            {
                // Create Session
                var amqpSessionSettings = new AmqpSessionSettings {
                    Properties = new Fields()
                };
                if (this.amqpLinkSettings.IsReceiver())
                {
                    // 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.
                    amqpSessionSettings.IncomingWindow = uint.MaxValue;
                }

                session = amqpConnection.CreateSession(amqpSessionSettings);
                await session.OpenAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false);
            }
            catch (Exception exception)
            {
                MessagingEventSource.Log.AmqpSessionCreationException(this.entityPath, amqpConnection, exception);
                session?.Abort();
                throw AmqpExceptionHelper.GetClientException(exception, null, session.GetInnerException(), amqpConnection.IsClosing());
            }

            AmqpObject link = null;

            try
            {
                // Create Link
                link = this.OnCreateAmqpLink(amqpConnection, 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,
                    amqpConnection,
                    exception);

                session.SafeClose(exception);
                throw AmqpExceptionHelper.GetClientException(exception, null, link?.GetInnerException(), amqpConnection.IsClosing());
            }
        }
        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;
        }
        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;
        }
Example #23
0
 AmqpSession ISessionFactory.CreateSession(AmqpConnection connection, AmqpSessionSettings settings) => new AmqpSession(connection, settings, this);
Example #24
0
 public AmqpSession(AmqpConnection connection, AmqpSessionSettings settings, ILinkFactory linkFactory)
     : this("session", connection, settings, linkFactory)
 {
 }
Example #25
0
        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;
            }
        }
Example #26
0
File: Sender.cs Project: Bigsby/PoC
        static void Main(string[] args)
        {
            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,
                    Target = new Target
                    {
                        Address = "theQueue",
                        Durable = 1
                    }
                };

                var sender = new SendingAmqpLink(session, linkSettings);
                session.Open();
                sender.Open();
                var key = ConsoleKey.A;
                var i   = 0;
                do
                {
                    Console.WriteLine("Press any key to send message");

                    var body    = "Hello, AMQP1.0!";
                    var message = AmqpMessage.Create(new AmqpValue()
                    {
                        Value = body
                    });
                    var tag     = new ArraySegment <byte>(BitConverter.GetBytes(i++));
                    var outcome = sender.SendMessageAsync(message, tag, AmqpConstants.NullBinary, TimeSpan.FromSeconds(3)).Result;

                    if (outcome.DescriptorCode == Accepted.Code)
                    {
                        Console.WriteLine(" [x] Sent {0}", body);
                    }
                    else
                    {
                        Console.WriteLine("Error sending message!");
                    }
                } while (key != ConsoleKey.Q);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error: " + ex.Message);
                throw;
            }

            Console.WriteLine(" Press [enter] to exit.");
            Console.ReadLine();
        }
Example #27
0
        /// <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 = ValueStopwatch.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.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
                    }
                };

                if (!string.IsNullOrEmpty(viaEntityPath))
                {
                    linkSettings.AddProperty(AmqpClientConstants.TransferDestinationAddress, entityPath);
                }

                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
            }
        }
            protected override IEnumerator <IteratorAsyncResult <AmqpManagementLink.OpenManagementRequestResponseLinkAsyncResult> .AsyncStep> GetAsyncSteps()
            {
                string str = "$management";

                if (base.RemainingTime() > TimeSpan.Zero)
                {
                    try
                    {
                        AmqpSessionSettings amqpSessionSetting = new AmqpSessionSettings()
                        {
                            Properties = new Fields()
                        };
                        this.session = new AmqpSession(this.connection, amqpSessionSetting, this);
                        this.connection.AddSession(this.session, null);
                    }
                    catch (InvalidOperationException invalidOperationException1)
                    {
                        InvalidOperationException invalidOperationException = invalidOperationException1;
                        base.Complete(new MessagingException(invalidOperationException.Message, true, invalidOperationException));
                        goto Label0;
                    }
                    AmqpManagementLink.OpenManagementRequestResponseLinkAsyncResult openManagementRequestResponseLinkAsyncResult = this;
                    IteratorAsyncResult <AmqpManagementLink.OpenManagementRequestResponseLinkAsyncResult> .BeginCall beginCall   = (AmqpManagementLink.OpenManagementRequestResponseLinkAsyncResult thisPtr, TimeSpan t, AsyncCallback c, object s) => thisPtr.session.BeginOpen(t, c, s);
                    yield return(openManagementRequestResponseLinkAsyncResult.CallAsync(beginCall, (AmqpManagementLink.OpenManagementRequestResponseLinkAsyncResult thisPtr, IAsyncResult r) => thisPtr.session.EndOpen(r), IteratorAsyncResult <TIteratorAsyncResult> .ExceptionPolicy.Continue));

                    Exception lastAsyncStepException = base.LastAsyncStepException;
                    if (lastAsyncStepException == null)
                    {
                        AmqpLinkSettings amqpLinkSetting  = new AmqpLinkSettings();
                        AmqpLinkSettings amqpLinkSetting1 = amqpLinkSetting;
                        AmqpSymbol       timeoutName      = ClientConstants.TimeoutName;
                        TimeSpan         timeSpan         = base.RemainingTime();
                        amqpLinkSetting1.AddProperty(timeoutName, (uint)timeSpan.TotalMilliseconds);
                        amqpLinkSetting.Target = new Target()
                        {
                            Address = str
                        };
                        amqpLinkSetting.Source = new Source()
                        {
                            Address = str
                        };
                        amqpLinkSetting.InitialDeliveryCount = new uint?(0);
                        amqpLinkSetting.TotalLinkCredit      = 50;
                        amqpLinkSetting.AutoSendFlow         = true;
                        amqpLinkSetting.SettleType           = SettleMode.SettleOnSend;
                        this.Link = new RequestResponseAmqpLink(this.session, amqpLinkSetting);
                        AmqpManagementLink.OpenManagementRequestResponseLinkAsyncResult openManagementRequestResponseLinkAsyncResult1 = this;
                        IteratorAsyncResult <AmqpManagementLink.OpenManagementRequestResponseLinkAsyncResult> .BeginCall beginCall1   = (AmqpManagementLink.OpenManagementRequestResponseLinkAsyncResult thisPtr, TimeSpan t, AsyncCallback c, object s) => thisPtr.Link.BeginOpen(t, c, s);
                        yield return(openManagementRequestResponseLinkAsyncResult1.CallAsync(beginCall1, (AmqpManagementLink.OpenManagementRequestResponseLinkAsyncResult thisPtr, IAsyncResult r) => thisPtr.Link.EndOpen(r), IteratorAsyncResult <TIteratorAsyncResult> .ExceptionPolicy.Continue));

                        lastAsyncStepException = base.LastAsyncStepException;
                        if (lastAsyncStepException == null)
                        {
                            MessagingClientEtwProvider.Provider.EventWriteAmqpOpenEntitySucceeded(this.connection, this.Link, this.Link.Name, str);
                        }
                        else
                        {
                            this.Link = null;
                            MessagingClientEtwProvider.Provider.EventWriteAmqpOpenEntityFailed(this.connection, this.Link, this.Link.Name, str, lastAsyncStepException.Message);
                            this.session.SafeClose();
                            base.Complete(Microsoft.ServiceBus.Messaging.Amqp.ExceptionHelper.ToMessagingContract(lastAsyncStepException, this.connection.RemoteEndpoint.ToString()));
                        }
                    }
                    else
                    {
                        MessagingClientEtwProvider.Provider.EventWriteAmqpOpenEntityFailed(this.connection, this.session, string.Empty, str, lastAsyncStepException.Message);
                        this.session.Abort();
                        base.Complete(Microsoft.ServiceBus.Messaging.Amqp.ExceptionHelper.ToMessagingContract(lastAsyncStepException, this.connection.RemoteEndpoint.ToString()));
                    }
                }
                else
                {
                    if (this.session != null)
                    {
                        this.session.SafeClose();
                    }
                    base.Complete(new TimeoutException(SRAmqp.AmqpTimeout(base.OriginalTimeout, str)));
                }
Label0:
                yield break;
            }
        public async Task <Tuple <AmqpObject, DateTime> > CreateAndOpenAmqpLinkAsync()
        {
            var timeoutHelper = new TimeoutHelper(this.serviceBusConnection.OperationTimeout);

            MessagingEventSource.Log.AmqpGetOrCreateConnectionStart();
            var amqpConnection = await this.serviceBusConnection.ConnectionManager.GetOrCreateAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false);

            MessagingEventSource.Log.AmqpGetOrCreateConnectionStop(this.entityPath, amqpConnection.ToString(), amqpConnection.State.ToString());

            // Authenticate over CBS
            var      cbsLink = amqpConnection.Extensions.Find <AmqpCbsLink>();
            DateTime cbsTokenExpiresAtUtc = DateTime.MaxValue;

            foreach (var resource in this.audience)
            {
                MessagingEventSource.Log.AmqpSendAuthenticationTokenStart(this.endpointAddress, resource, resource, this.requiredClaims);
                cbsTokenExpiresAtUtc = TimeoutHelper.Min(
                    cbsTokenExpiresAtUtc,
                    await cbsLink.SendTokenAsync(this.cbsTokenProvider, this.endpointAddress, resource, resource, this.requiredClaims, timeoutHelper.RemainingTime()).ConfigureAwait(false));
                MessagingEventSource.Log.AmqpSendAuthenticationTokenStop();
            }

            AmqpSession session = null;

            try
            {
                // Create Session
                var amqpSessionSettings = new AmqpSessionSettings {
                    Properties = new Fields()
                };
                session = amqpConnection.CreateSession(amqpSessionSettings);
                await session.OpenAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false);
            }
            catch (Exception exception)
            {
                MessagingEventSource.Log.AmqpSessionCreationException(this.entityPath, amqpConnection, exception);
                session?.Abort();
                throw AmqpExceptionHelper.GetClientException(exception, null, session.GetInnerException());
            }

            AmqpObject link = null;

            try
            {
                // Create Link
                link = this.OnCreateAmqpLink(amqpConnection, 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,
                    amqpConnection,
                    exception);

                session.SafeClose(exception);
                throw AmqpExceptionHelper.GetClientException(exception, null, link?.GetInnerException(), session.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="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="trackLastEnqueuedEventProperties">Indicates whether information on the last enqueued event on the partition is sent as events are received.</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,
                                                                                  TimeSpan timeout,
                                                                                  uint prefetchCount,
                                                                                  long?ownerLevel,
                                                                                  bool trackLastEnqueuedEventProperties,
                                                                                  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 = 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, (int)AmqpProperty.Entity.ConsumerGroup);

                if (ownerLevel.HasValue)
                {
                    linkSettings.AddProperty(AmqpProperty.OwnerLevel, ownerLevel.Value);
                }

                if (trackLastEnqueuedEventProperties)
                {
                    linkSettings.DesiredCapabilities = new Multiple <AmqpSymbol>(new List <AmqpSymbol>
                    {
                        AmqpProperty.TrackLastEnqueuedEventProperties
                    });
                }

                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,
                    () => (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;
            }
        }
        /// <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 receiver(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<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;
        }