public async Task ConstructorCreatesTheConnection()
        {
            var endpoint       = new Uri("amqp://test.service.gov");
            var eventHub       = "myHub";
            var credential     = Mock.Of <TokenCredential>();
            var transport      = TransportType.AmqpTcp;
            var identifier     = "customIdentIFIER";
            var mockConnection = new AmqpConnection(new MockTransport(), CreateMockAmqpSettings(), new AmqpConnectionSettings());

            var mockScope = new Mock <AmqpConnectionScope>(endpoint, eventHub, credential, transport, null, identifier)
            {
                CallBase = true
            };

            mockScope
            .Protected()
            .Setup <Task <AmqpConnection> >("CreateConnectionAsync",
                                            ItExpr.IsAny <Version>(),
                                            ItExpr.Is <Uri>(value => value == endpoint),
                                            ItExpr.Is <TransportType>(value => value == transport),
                                            ItExpr.Is <IWebProxy>(value => value == null),
                                            ItExpr.Is <string>(value => value == identifier),
                                            ItExpr.IsAny <TimeSpan>())
            .Returns(Task.FromResult(mockConnection))
            .Verifiable();

            var connection = await GetActiveConnection(mockScope.Object).GetOrCreateAsync(TimeSpan.FromDays(1));

            Assert.That(connection, Is.SameAs(mockConnection), "The connection instance should have been returned");

            mockScope.VerifyAll();
        }
Example #2
0
        public async Task <AmqpConnection> OpenConnectionAsync(TimeSpan timeout)
        {
            if (Logging.IsEnabled)
            {
                Logging.Enter(this, timeout, $"{nameof(OpenConnectionAsync)}");
            }
            TransportBase transportBase = null;

            try
            {
                transportBase = await InitializeTransport(timeout).ConfigureAwait(false);

                AmqpConnection amqpConnection = new AmqpConnection(transportBase, AmqpSettings, AmqpConnectionSettings);
                await amqpConnection.OpenAsync(timeout).ConfigureAwait(false);

                if (Logging.IsEnabled)
                {
                    Logging.Exit(this, timeout, $"{nameof(OpenConnectionAsync)}");
                }
                return(amqpConnection);
            }
            catch (Exception)
            {
                transportBase?.Close();
                throw;
            }
        }
Example #3
0
        /// <summary>
        ///   Creates the timer event handler to support refreshing AMQP link authorization
        ///   on a recurring basis.
        /// </summary>
        ///
        /// <param name="connection">The AMQP connection to which the link being refreshed is bound to.</param>
        /// <param name="amqpLink">The AMQO link to refresh authorization for.</param>
        /// <param name="tokenProvider">The <see cref="CbsTokenProvider" /> to use for obtaining access tokens.</param>
        /// <param name="endpoint">The Event Hubs service endpoint that the AMQP link is communicating with.</param>
        /// <param name="audience">The audience associated with the authorization.  This is likely the <paramref name="endpoint"/> absolute URI.</param>
        /// <param name="resource">The resource associated with the authorization.  This is likely the <paramref name="endpoint"/> absolute URI.</param>
        /// <param name="requiredClaims">The set of claims required to support the operations of the AMQP link.</param>
        /// <param name="refreshTimeout">The timeout to apply when requesting authorization refresh.</param>
        /// <param name="refreshTimerFactory">A function to allow retrieving the <see cref="Timer" /> associated with the link authorization.</param>
        ///
        /// <returns>A <see cref="TimerCallback"/> delegate to perform the refresh when a timer is due.</returns>
        ///
        protected virtual TimerCallback CreateAuthorizationRefreshHandler(AmqpConnection connection,
                                                                          AmqpObject amqpLink,
                                                                          CbsTokenProvider tokenProvider,
                                                                          Uri endpoint,
                                                                          string audience,
                                                                          string resource,
                                                                          string[] requiredClaims,
                                                                          TimeSpan refreshTimeout,
                                                                          Func <Timer> refreshTimerFactory)
        {
            return(async _ =>
            {
                EventHubsEventSource.Log.AmqpLinkAuthorizationRefreshStart(EventHubName, endpoint.AbsoluteUri);
                var refreshTimer = refreshTimerFactory();

                try
                {
                    var authExpirationUtc = await RequestAuthorizationUsingCbsAsync(connection, tokenProvider, endpoint, audience, resource, requiredClaims, refreshTimeout).ConfigureAwait(false);

                    // Reset the timer for the next refresh.

                    if (authExpirationUtc >= DateTimeOffset.UtcNow)
                    {
                        refreshTimer.Change(CalculateLinkAuthorizationRefreshInterval(authExpirationUtc), Timeout.InfiniteTimeSpan);
                    }

                    EventHubsEventSource.Log.AmqpLinkAuthorizationRefreshComplete(EventHubName, endpoint.AbsoluteUri);
                }
                catch (Exception ex)
                {
                    EventHubsEventSource.Log.AmqpLinkAuthorizationRefreshError(EventHubName, endpoint.AbsoluteUri, ex.Message);
                    refreshTimer.Change(Timeout.Infinite, Timeout.Infinite);
                }
            });
        }
        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);
        }
Example #5
0
        public async Task OpenAsync(TimeSpan timeout, bool useWebSocket, X509Certificate2 clientCert)
        {
            var hostName = _uri.Host;

            var tcpSettings = new TcpTransportSettings {
                Host = hostName, Port = _uri.Port != -1 ? _uri.Port : AmqpConstants.DefaultSecurePort
            };

            TransportSettings = new TlsTransportSettings(tcpSettings)
            {
                TargetHost = hostName,
                CertificateValidationCallback = (sender, cert, chain, errors) => true,
                Certificate = clientCert
            };

            TransportBase transport;

            if (useWebSocket)
            {
                transport = await CreateClientWebSocketTransportAsync(timeout).ConfigureAwait(false);
            }
            else
            {
                var tcpInitiator = new AmqpTransportInitiator(_amqpSettings, TransportSettings);
                transport = await tcpInitiator.ConnectTaskAsync(timeout).ConfigureAwait(false);
            }

            AmqpConnection = new AmqpConnection(transport, _amqpSettings, AmqpConnectionSettings);
            await AmqpConnection.OpenAsync(timeout).ConfigureAwait(false);

            _isConnectionClosed    = false;
            AmqpConnection.Closed += OnConnectionClosed;
        }
Example #6
0
        void OnAcceptTransport(TransportListener listener, TransportAsyncCallbackArgs args)
        {
            AmqpConnectionSettings connectionSettings = new AmqpConnectionSettings()
            {
                ContainerId  = this.containerId,
                MaxFrameSize = this.maxFrameSize
            };

            AmqpConnection connection = null;

            try
            {
                connection = this.CreateConnection(
                    args.Transport,
                    (ProtocolHeader)args.UserToken,
                    false,
                    this.settings,
                    connectionSettings);

                connection.BeginOpen(connection.DefaultOpenTimeout, this.OnConnectionOpenComplete, connection);
            }
            catch (Exception ex)
            {
                if (connection != null)
                {
                    connection.SafeClose(ex);
                }
            }
        }
Example #7
0
 public void AmqpSessionCreationException(string entityPath, AmqpConnection connection, Exception exception)
 {
     if (this.IsEnabled())
     {
         this.AmqpSessionCreationException(entityPath, connection.ToString(), connection.State.ToString(), exception.ToString());
     }
 }
        /// <summary>
        ///   Opens an AMQP link for use with producer operations.
        /// </summary>
        /// <param name="entityPath"></param>
        /// <param name="viaEntityPath">The entity path to route the message through. Useful when using transactions.</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 producer operations.</returns>
        ///
        public virtual async Task <SendingAmqpLink> OpenSenderLinkAsync(
            string entityPath,
            string viaEntityPath,
            TimeSpan timeout,
            CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>();

            var stopWatch = Stopwatch.StartNew();

            AmqpConnection connection = await ActiveConnection.GetOrCreateAsync(timeout).ConfigureAwait(false);

            cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>();

            SendingAmqpLink link = await CreateSendingLinkAsync(
                entityPath,
                viaEntityPath,
                connection,
                timeout.CalculateRemaining(stopWatch.Elapsed), cancellationToken).ConfigureAwait(false);

            cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>();

            await OpenAmqpObjectAsync(link, timeout.CalculateRemaining(stopWatch.Elapsed)).ConfigureAwait(false);

            cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>();

            stopWatch.Stop();
            return(link);
        }
Example #9
0
 public void AmqpConnectionCreated(string hostName, AmqpConnection connection)
 {
     if (this.IsEnabled())
     {
         this.AmqpConnectionCreated(hostName, connection.ToString(), connection.State.ToString());
     }
 }
Example #10
0
 public void AmqpConnectionClosed(AmqpConnection connection)
 {
     if (this.IsEnabled())
     {
         this.AmqpConnectionClosed(connection.RemoteEndpoint.ToString(), connection.ToString(), connection.State.ToString());
     }
 }
        protected override AmqpObject OnCreateAmqpLink(AmqpConnection connection, AmqpLinkSettings linkSettings, AmqpSession amqpSession)
        {
            AmqpObject link = new RequestResponseAmqpLink(AmqpClientConstants.EntityTypeManagement, amqpSession, this.entityPath, linkSettings.Properties);

            linkSettings.LinkName = $"{connection.Settings.ContainerId};{connection.Identifier}:{amqpSession.Identifier}:{link.Identifier}:{this.ClientId}";
            return(link);
        }
        private async Task <AmqpConnection> CreateConnectionAsync(TimeSpan timeout)
        {
            string hostName      = ConnectionStringBuilder.Endpoint.Host;
            int    port          = ConnectionStringBuilder.Endpoint.Port;
            bool   useWebSockets = ConnectionStringBuilder.TransportType == TrackOne.TransportType.AmqpWebSockets;

            var          timeoutHelper = new TimeoutHelper(timeout);
            AmqpSettings amqpSettings  = CreateAmqpSettings(
                amqpVersion: AmqpVersion,
                useSslStreamSecurity: true,
                hasTokenProvider: true,
                useWebSockets: useWebSockets);

            TransportSettings tpSettings = useWebSockets
                ? CreateWebSocketsTransportSettings(hostName, WebProxy)
                : CreateTcpTlsTransportSettings(hostName, port);

            var           initiator = new AmqpTransportInitiator(amqpSettings, tpSettings);
            TransportBase transport = await initiator.ConnectTaskAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false);

            AmqpConnectionSettings connectionSettings = CreateAmqpConnectionSettings(MaxFrameSize, ContainerId, hostName);
            var connection = new AmqpConnection(transport, amqpSettings, connectionSettings);
            await connection.OpenAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false);

            // Always create the CBS Link + Session
            var cbsLink = new AmqpCbsLink(connection);

            if (connection.Extensions.Find <AmqpCbsLink>() == null)
            {
                connection.Extensions.Add(cbsLink);
            }

            return(connection);
        }
Example #13
0
        async Task <AmqpConnection> CreateConnectionAsync(TimeSpan timeout)
        {
            var hostName = this.Endpoint.Host;

            var timeoutHelper = new TimeoutHelper(timeout);
            var amqpSettings  = AmqpConnectionHelper.CreateAmqpSettings(
                amqpVersion: AmqpVersion,
                useSslStreamSecurity: true,
                hasTokenProvider: true,
                useWebSockets: TransportType == TransportType.AmqpWebSockets);

            var transportSettings      = CreateTransportSettings();
            var amqpTransportInitiator = new AmqpTransportInitiator(amqpSettings, transportSettings);
            var transport = await amqpTransportInitiator.ConnectTaskAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false);

            var containerId            = Guid.NewGuid().ToString();
            var amqpConnectionSettings = AmqpConnectionHelper.CreateAmqpConnectionSettings(AmqpConstants.DefaultMaxFrameSize, containerId, hostName);
            var connection             = new AmqpConnection(transport, amqpSettings, amqpConnectionSettings);
            await connection.OpenAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false);

            // Always create the CBS Link + Session
            var cbsLink = new AmqpCbsLink(connection);

            if (connection.Extensions.Find <AmqpCbsLink>() == null)
            {
                connection.Extensions.Add(cbsLink);
            }

            MessagingEventSource.Log.AmqpConnectionCreated(hostName, connection);

            return(connection);
        }
        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;
            }
        }
        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);
        }
Example #16
0
        async Task <AmqpConnection> CreateConnectionAsync(TimeSpan timeout)
        {
            string hostName    = this.ConnectionStringBuilder.Endpoint.Host;
            string networkHost = this.ConnectionStringBuilder.Endpoint.Host;
            int    port        = this.ConnectionStringBuilder.Endpoint.Port;

            var timeoutHelper = new TimeoutHelper(timeout);
            var amqpSettings  = CreateAmqpSettings(
                amqpVersion: this.AmqpVersion,
                useSslStreamSecurity: true,
                hasTokenProvider: true);

            TransportSettings tpSettings = CreateTcpTransportSettings(
                networkHost: networkHost,
                hostName: hostName,
                port: port,
                useSslStreamSecurity: true);

            var initiator = new AmqpTransportInitiator(amqpSettings, tpSettings);
            var transport = await initiator.ConnectTaskAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false);

            var connectionSettings = CreateAmqpConnectionSettings(this.MaxFrameSize, this.ContainerId, hostName);
            var connection         = new AmqpConnection(transport, amqpSettings, connectionSettings);
            await connection.OpenAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false);

            // Always create the CBS Link + Session
            var cbsLink = new AmqpCbsLink(connection);

            if (connection.Extensions.Find <AmqpCbsLink>() == null)
            {
                connection.Extensions.Add(cbsLink);
            }

            return(connection);
        }
Example #17
0
        internal async Task <AmqpIoTConnection> OpenConnectionAsync(TimeSpan timeout)
        {
            if (Logging.IsEnabled)
            {
                Logging.Enter(this, $"{nameof(OpenConnectionAsync)}");
            }

            TransportBase transportBase = await _amqpIoTTransport.Initialize(timeout).ConfigureAwait(false);

            try
            {
                _amqpConnection         = new AmqpConnection(transportBase, _amqpSettings, _amqpConnectionSettings);
                _amqpConnection.Closed += _amqpConnectionClosed;
                await _amqpConnection.OpenAsync(timeout).ConfigureAwait(false);

                if (Logging.IsEnabled)
                {
                    Logging.Exit(this, timeout, $"{nameof(OpenConnectionAsync)}");
                }
                return(this);
            }
            catch (Exception)
            {
                transportBase?.Close();
                throw;
            }
            finally
            {
                if (Logging.IsEnabled)
                {
                    Logging.Exit(this, $"{nameof(OpenConnectionAsync)}");
                }
            }
        }
Example #18
0
        protected override AmqpObject OnCreateAmqpLink(AmqpConnection connection, AmqpLinkSettings linkSettings, AmqpSession amqpSession)
        {
            AmqpObject link = (linkSettings.IsReceiver()) ? (AmqpObject) new ReceivingAmqpLink(linkSettings) : (AmqpObject) new SendingAmqpLink(linkSettings);

            linkSettings.LinkName = $"{connection.Settings.ContainerId};{connection.Identifier}:{amqpSession.Identifier}:{link.Identifier}";
            ((AmqpLink)link).AttachTo(amqpSession);
            return(link);
        }
Example #19
0
 static void UnsharedIdleConnectionHandler(Object sender, EventArgs empty)
 {
     if (sender is AmqpConnection)
     {
         AmqpConnection connection = (AmqpConnection)sender;
         connection.Close();
     }
 }
Example #20
0
        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());
            }
        }
        public async Task <AmqpIoTConnection> OpenConnectionAsync(TimeSpan timeout)
        {
            if (Logging.IsEnabled)
            {
                Logging.Enter(this, timeout, $"{nameof(OpenConnectionAsync)}");
            }

            var amqpSettings          = new AmqpSettings();
            var amqpTransportProvider = new AmqpTransportProvider();

            amqpTransportProvider.Versions.Add(s_amqpVersion_1_0_0);
            amqpSettings.TransportProviders.Add(amqpTransportProvider);

            var amqpConnectionSettings = new AmqpConnectionSettings()
            {
                MaxFrameSize = AmqpConstants.DefaultMaxFrameSize,
                ContainerId  = CommonResources.GetNewStringGuid(),
                HostName     = _hostName
            };

            TimeSpan idleTimeout = _amqpTransportSettings.IdleTimeout;

            if (idleTimeout != null)
            {
                amqpConnectionSettings.IdleTimeOut = Convert.ToUInt32(idleTimeout.TotalMilliseconds);
            }

            var amqpIoTTransport = new AmqpIoTTransport(amqpSettings, _amqpTransportSettings, _hostName, s_disableServerCertificateValidation);

            TransportBase transportBase = await amqpIoTTransport.InitializeAsync(timeout).ConfigureAwait(false);

            try
            {
                var amqpConnection = new AmqpConnection(transportBase, amqpSettings, amqpConnectionSettings);
                AmqpIoTConnection amqpIoTConnection = new AmqpIoTConnection(amqpConnection);
                amqpConnection.Closed += amqpIoTConnection.AmqpConnectionClosed;
                await amqpConnection.OpenAsync(timeout).ConfigureAwait(false);

                if (Logging.IsEnabled)
                {
                    Logging.Exit(this, timeout, $"{nameof(OpenConnectionAsync)}");
                }

                return(amqpIoTConnection);
            }
            catch (Exception e) when(!e.IsFatal())
            {
                transportBase?.Close();
                throw;
            }
            finally
            {
                if (Logging.IsEnabled)
                {
                    Logging.Exit(this, $"{nameof(OpenConnectionAsync)}");
                }
            }
        }
Example #22
0
        public void Close()
        {
            AmqpConnection connection = AmqpConnection;

            if (connection != null)
            {
                connection.Close();
            }
        }
Example #23
0
        public async Task CloseAsync(CancellationToken cancellationToken)
        {
            AmqpConnection connection = AmqpConnection;

            if (connection != null)
            {
                await connection.CloseAsync(cancellationToken).ConfigureAwait(false);
            }
        }
Example #24
0
        public async Task CloseAsync(TimeSpan timeout)
        {
            AmqpConnection connection = AmqpConnection;

            if (connection != null)
            {
                await connection.CloseAsync(timeout).ConfigureAwait(false);
            }
        }
Example #25
0
        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;
            }
        }
        /// <summary>
        ///   Creates the timer event handler to support refreshing AMQP link authorization
        ///   on a recurring basis.
        /// </summary>
        /// <param name="entityPath"></param>
        ///
        /// <param name="connection">The AMQP connection to which the link being refreshed is bound to.</param>
        /// <param name="amqpLink">The AMQO link to refresh authorization for.</param>
        /// <param name="tokenProvider">The <see cref="CbsTokenProvider" /> to use for obtaining access tokens.</param>
        /// <param name="endpoint">The Service Bus service endpoint that the AMQP link is communicating with.</param>
        /// <param name="audience">The audience associated with the authorization.  This is likely the <paramref name="endpoint"/> absolute URI.</param>
        /// <param name="resource">The resource associated with the authorization.  This is likely the <paramref name="endpoint"/> absolute URI.</param>
        /// <param name="requiredClaims">The set of claims required to support the operations of the AMQP link.</param>
        /// <param name="refreshTimeout">The timeout to apply when requesting authorization refresh.</param>
        /// <param name="refreshTimerFactory">A function to allow retrieving the <see cref="Timer" /> associated with the link authorization.</param>
        ///
        /// <returns>A <see cref="TimerCallback"/> delegate to perform the refresh when a timer is due.</returns>
        ///
        protected virtual TimerCallback CreateAuthorizationRefreshHandler(
            string entityPath,
            AmqpConnection connection,
            AmqpObject amqpLink,
            CbsTokenProvider tokenProvider,
            Uri endpoint,
            string audience,
            string resource,
            string[] requiredClaims,
            TimeSpan refreshTimeout,
            Func <Timer> refreshTimerFactory)
        {
            return(async _ =>
            {
                ServiceBusEventSource.Log.AmqpLinkAuthorizationRefreshStart(entityPath, endpoint.AbsoluteUri);
                Timer refreshTimer = refreshTimerFactory();

                try
                {
                    if (refreshTimer == null)
                    {
                        return;
                    }

                    DateTime authExpirationUtc = await RequestAuthorizationUsingCbsAsync(connection, tokenProvider, endpoint, audience, resource, requiredClaims, refreshTimeout).ConfigureAwait(false);

                    // Reset the timer for the next refresh.

                    if (authExpirationUtc >= DateTimeOffset.UtcNow)
                    {
                        refreshTimer.Change(CalculateLinkAuthorizationRefreshInterval(authExpirationUtc), Timeout.InfiniteTimeSpan);
                    }
                }
                catch (ObjectDisposedException)
                {
                    // This can occur if the connection is closed or the scope disposed after the factory
                    // is called but before the timer is updated.  The callback may also fire while the timer is
                    // in the act of disposing.  Do not consider it an error.
                }
                catch (Exception ex)
                {
                    ServiceBusEventSource.Log.AmqpLinkAuthorizationRefreshError(entityPath, endpoint.AbsoluteUri, ex.Message);

                    // Attempt to unset the timer; there's a decent chance that it has been disposed at this point or
                    // that the connection has been closed.  Ignore potential exceptions, as they won't impact operation.
                    // At worse, another timer tick will occur and the operation will be retried.

                    try { refreshTimer.Change(Timeout.Infinite, Timeout.Infinite); } catch {}
                }
                finally
                {
                    ServiceBusEventSource.Log.AmqpLinkAuthorizationRefreshComplete(entityPath, endpoint.AbsoluteUri);
                }
            });
        }
Example #27
0
        /// <summary>
        ///   Requests authorization for a connection or link using a connection via the CBS mechanism.
        /// </summary>
        ///
        /// <param name="connection">The AMQP connection for which the authorization is associated.</param>
        /// <param name="tokenProvider">The <see cref="CbsTokenProvider" /> to use for obtaining access tokens.</param>
        /// <param name="endpoint">The Event Hubs service endpoint that the authorization is requested for.</param>
        /// <param name="audience">The audience associated with the authorization.  This is likely the <paramref name="endpoint"/> absolute URI.</param>
        /// <param name="resource">The resource associated with the authorization.  This is likely the <paramref name="endpoint"/> absolute URI.</param>
        /// <param name="requiredClaims">The set of claims required to support the operations of the AMQP link.</param>
        /// <param name="timeout">The timeout to apply when requesting authorization.</param>
        ///
        /// <returns>The date/time, in UTC, when the authorization expires.</returns>
        ///
        /// <remarks>
        ///   It is assumed that there is a valid <see cref="AmqpCbsLink" /> already associated
        ///   with the connection; this will be used as the transport for the authorization
        ///   credentials.
        /// </remarks>
        ///
        protected virtual Task <DateTime> RequestAuthorizationUsingCbsAsync(AmqpConnection connection,
                                                                            CbsTokenProvider tokenProvider,
                                                                            Uri endpoint,
                                                                            string audience,
                                                                            string resource,
                                                                            string[] requiredClaims,
                                                                            TimeSpan timeout)
        {
            var authLink = connection.Extensions.Find <AmqpCbsLink>();

            return(authLink.SendTokenAsync(TokenProvider, endpoint, audience, resource, requiredClaims, timeout));
        }
        /// <summary>
        ///   Opens an AMQP link for use with management operations.
        /// </summary>
        ///
        /// <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>
        ///
        /// <remarks>
        ///   The authorization for this link does not require periodic
        ///   refreshing.
        /// </remarks>
        ///
        public async Task <RequestResponseAmqpLink> OpenManagementLinkAsync(TimeSpan timeout,
                                                                            CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>();

            var            stopWatch  = Stopwatch.StartNew();
            AmqpConnection connection = await ActiveConnection.GetOrCreateAsync(timeout).ConfigureAwait(false);

            stopWatch.Stop();

            return(await OpenManagementLinkAsync(connection, timeout.CalculateRemaining(stopWatch.Elapsed), cancellationToken).ConfigureAwait(false));
        }
Example #29
0
        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);
        }
Example #30
0
        public void AmqpWebSocketTransportTest()
        {
            string address = "ws://localhost:28088";
            var    broker  = new TestAmqpBroker(new string[] { address }, null, null, null);

            try
            {
                broker.Start();

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

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

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

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

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

                sLink.Close();

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

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

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

                rLink.Close();

                connection.Close();
            }
            finally
            {
                broker.Stop();
            }
        }
Example #31
0
 void IdleConnectionHandler(Object sender, EventArgs empty)
 {
     lock (this)
     {
         if (sharedConnection != sender || sharedConnection == null)
         {
             return;
         }
         if (!sharedConnection.IsIdle)
         {
             // Another thread made the connection busy again.
             // That's OK.  Another idle event will come along later.
             return;
         }
         sharedConnection.Close();  // also closes all child sessions
         sharedConnection = null;
         //sharedSessions = null;
     }
 }
Example #32
0
            public object GetLink(AmqpChannelProperties channelProperties, bool sessionSharing, string inputQueue, string outputQueue)
            {
                AmqpConnection connection = null;
                AmqpSession session = null;
                Object link = null;
                bool newConnection = false;
                //bool newSession = false;
                bool success = false;

                // when called in the non-shared case, only stack variables should be used for holding connections/sessions/links

                if (this.shared)
                {
                    Monitor.Enter(this); // lock
                }

                try
                {
                    if (this.shared)
                    {
                        // TODO: check shared connection not closed (i.e. network drop) and refresh this instance if needed
                        if (sessionSharing)
                        {
                            throw new NotImplementedException("shared session");
                            /* * ... once we have a defined shared session config parameter:

                            // lazilly create
                            if (this.sharedSessions == null)
                            {
                                this.sharedSessions = new Dictionary<string, AmqpSession>();
                            }

                            alreadydeclaredstring sessionKey = channelProperties.name_of_key_goes_here;
                            this.sharedSessions.TryGetValue(sessionKey, out session);

                            * */
                        }

                        if (this.sharedConnection != null)
                        {
                            connection = this.sharedConnection;
                        }
                    }

                    if (connection == null)
                    {
                        if (channelProperties.AmqpSecurityMode != AmqpSecurityMode.None)
                        {
                            string user = null;
                            string passwd = null;
                            bool ssl = false;
                            bool saslPlain = false;

                            AmqpTransportSecurity tsec = channelProperties.AmqpTransportSecurity;
                            if (tsec.UseSSL)
                            {
                                ssl = true;
                            }

                            if (tsec.CredentialType == AmqpCredentialType.Plain)
                            {
                                saslPlain = true;
                                AmqpCredential plainCred = channelProperties.AmqpCredential;
                                if (plainCred != null)
                                {
                                    user = plainCred.UserName;
                                    passwd = plainCred.Password;
                                }
                            }

                            connection = new AmqpConnection(channelProperties.BrokerHost, channelProperties.BrokerPort,
                                ssl, saslPlain, user, passwd);
                        }
                        else
                        {
                            connection = new AmqpConnection(channelProperties.BrokerHost, channelProperties.BrokerPort);
                        }

                        newConnection = true;
                        if (this.shared)
                        {
                            connection.OnConnectionIdle += new ConnectionIdleEventHandler(this.IdleConnectionHandler);
                        }
                        else
                        {
                            connection.OnConnectionIdle += new ConnectionIdleEventHandler(UnsharedIdleConnectionHandler);
                        }
                    }

                    if (session == null)
                    {
                        session = connection.CreateSession();
                        //newSession = true;
                    }

                    if (inputQueue != null)
                    {
                        link = session.CreateInputLink(inputQueue);
                    }
                    else
                    {
                        link = session.CreateOutputLink(outputQueue);
                    }

                    if (this.shared)
                    {
                        if (newConnection)
                        {
                            this.sharedConnection = connection;
                        }
                        /*
                        if (newSession)
                        {
                            sharedSessions.Add(foo, session);
                        }
                         * */
                    }

                    success = true;
                }
                finally
                {
                    if (this.shared)
                    {
                        Monitor.Exit(this);
                    }
                    if (!success)
                    {
                        /*
                        if (newSession)
                        {
                            session.Close();
                        }
                         */
                        if (newConnection)
                        {
                            connection.Close();
                        }
                    }
                }

                return link;
            }