public async Task <IAmqpIoTAuthenticationRefresher> CreateRefresher(DeviceIdentity deviceIdentity, TimeSpan timeout)
        {
            if (Logging.IsEnabled)
            {
                Logging.Enter(this, deviceIdentity, timeout, $"{nameof(CreateRefresher)}");
            }
            if (_amqpIoTConnection == null)
            {
                throw new IotHubCommunicationException();
            }

            if (_amqpIoTCbsLink == null)
            {
                _amqpIoTCbsLink = _amqpIoTConnection.CreateCbsLink(deviceIdentity, timeout);
            }

            IAmqpIoTAuthenticationRefresher amqpAuthenticator = new AmqpAuthenticationRefresher(deviceIdentity, _amqpIoTCbsLink);
            await amqpAuthenticator.InitLoopAsync(timeout).ConfigureAwait(false);

            if (Logging.IsEnabled)
            {
                Logging.Exit(this, deviceIdentity, timeout, $"{nameof(CreateRefresher)}");
            }
            return(amqpAuthenticator);
        }
        internal AmqpAuthenticationRefresher(DeviceIdentity deviceIdentity, AmqpIoTCbsLink amqpCbsLink)
        {
            _amqpIoTCbsLink          = amqpCbsLink;
            _connectionString        = deviceIdentity.IotHubConnectionString;
            _operationTimeout        = deviceIdentity.AmqpTransportSettings.OperationTimeout;
            _audience                = deviceIdentity.Audience;
            _amqpIoTCbsTokenProvider = new AmqpIoTCbsTokenProvider(_connectionString);

            if (Logging.IsEnabled)
            {
                Logging.Associate(this, deviceIdentity, $"{nameof(DeviceIdentity)}");
            }
            if (Logging.IsEnabled)
            {
                Logging.Associate(this, amqpCbsLink, $"{nameof(_amqpIoTCbsLink)}");
            }
        }
        public async Task <AmqpIoTConnection> EnsureConnection(TimeSpan timeout)
        {
            if (Logging.IsEnabled)
            {
                Logging.Enter(this, timeout, $"{nameof(EnsureConnection)}");
            }
            AmqpIoTConnection amqpIoTConnection = null;
            IAmqpIoTAuthenticationRefresher amqpAuthenticationRefresher = null;
            AmqpIoTCbsLink amqpIoTCbsLink = null;
            bool           gain           = await _lock.WaitAsync(timeout).ConfigureAwait(false);

            if (!gain)
            {
                throw new TimeoutException();
            }
            try
            {
                if (_amqpIoTConnection == null)
                {
                    if (Logging.IsEnabled)
                    {
                        Logging.Info(this, "Creating new AmqpConnection", $"{nameof(EnsureConnection)}");
                    }
                    // Create AmqpConnection
                    amqpIoTConnection = await _amqpIoTConnector.OpenConnectionAsync(timeout).ConfigureAwait(false);

                    if (_deviceIdentity.AuthenticationModel != AuthenticationModel.X509)
                    {
                        if (_amqpIoTCbsLink == null)
                        {
                            if (Logging.IsEnabled)
                            {
                                Logging.Info(this, "Creating new AmqpCbsLink", $"{nameof(EnsureConnection)}");
                            }
                            amqpIoTCbsLink = amqpIoTConnection.CreateCbsLink(_deviceIdentity, timeout);
                        }
                        else
                        {
                            amqpIoTCbsLink = _amqpIoTCbsLink;
                        }

                        if (_deviceIdentity.AuthenticationModel == AuthenticationModel.SasGrouped)
                        {
                            if (Logging.IsEnabled)
                            {
                                Logging.Info(this, "Creating connection width AmqpAuthenticationRefresher", $"{nameof(EnsureConnection)}");
                            }
                            amqpAuthenticationRefresher = new AmqpAuthenticationRefresher(_deviceIdentity, amqpIoTCbsLink);
                            await amqpAuthenticationRefresher.InitLoopAsync(timeout).ConfigureAwait(false);
                        }
                    }
                    _amqpIoTConnection           = amqpIoTConnection;
                    _amqpIoTCbsLink              = amqpIoTCbsLink;
                    _amqpAuthenticationRefresher = amqpAuthenticationRefresher;
                    _amqpIoTConnection.Closed   += OnConnectionClosed;
                    if (Logging.IsEnabled)
                    {
                        Logging.Associate(this, _amqpIoTConnection, $"{nameof(_amqpIoTConnection)}");
                    }
                    if (Logging.IsEnabled)
                    {
                        Logging.Associate(this, _amqpIoTCbsLink, $"{nameof(_amqpIoTCbsLink)}");
                    }
                }
                else if (_amqpIoTConnection.IsClosing())
                {
                    throw new IotHubCommunicationException("AMQP connection is closing.");
                }
                else
                {
                    amqpIoTConnection = _amqpIoTConnection;
                }
            }
            catch (Exception ex) when(!ex.IsFatal())
            {
                amqpIoTCbsLink?.Close();
                amqpAuthenticationRefresher?.StopLoop();
                amqpIoTConnection?.SafeClose();
                throw;
            }
            finally
            {
                _lock.Release();
            }
            if (Logging.IsEnabled)
            {
                Logging.Exit(this, timeout, $"{nameof(EnsureConnection)}");
            }
            return(amqpIoTConnection);
        }