public async Task <IAmqpAuthenticationRefresher> CreateRefresherAsync(DeviceIdentity deviceIdentity, TimeSpan timeout)
        {
            if (Logging.IsEnabled)
            {
                Logging.Enter(this, deviceIdentity, timeout, $"{nameof(CreateRefresherAsync)}");
            }
            AmqpIoTConnection amqpIoTConnection = await EnsureConnectionAsync(timeout).ConfigureAwait(false);

            IAmqpAuthenticationRefresher amqpAuthenticator = await amqpIoTConnection.CreateRefresherAsync(deviceIdentity, timeout).ConfigureAwait(false);

            if (Logging.IsEnabled)
            {
                Logging.Exit(this, deviceIdentity, timeout, $"{nameof(CreateRefresherAsync)}");
            }
            return(amqpAuthenticator);
        }
        public AmqpUnit CreateAmqpUnit(
            DeviceIdentity deviceIdentity,
            Func <MethodRequestInternal, Task> methodHandler,
            Action <Twin, string, TwinCollection> twinMessageListener,
            Func <string, Message, Task> eventListener,
            Action onUnitDisconnected)
        {
            IAmqpUnitManager amqpConnectionPool = ResolveConnectionPool(deviceIdentity.IotHubConnectionString.HostName);

            return(amqpConnectionPool.CreateAmqpUnit(
                       deviceIdentity,
                       methodHandler,
                       twinMessageListener,
                       eventListener,
                       onUnitDisconnected));
        }
 public AmqpUnit CreateAmqpUnit(
     DeviceIdentity deviceIdentity,
     Func <MethodRequestInternal, Task> methodHandler,
     Action <Twin, string, TwinCollection> twinMessageListener,
     Func <string, Message, Task> eventListener)
 {
     if (Logging.IsEnabled)
     {
         Logging.Enter(this, deviceIdentity, $"{nameof(CreateAmqpUnit)}");
     }
     if (deviceIdentity.AuthenticationModel != AuthenticationModel.X509 && (deviceIdentity.AmqpTransportSettings?.AmqpConnectionPoolSettings?.Pooling ?? false))
     {
         IAmqpConnectionHolder amqpConnectionHolder;
         lock (Lock)
         {
             ISet <IAmqpConnectionHolder> amqpConnectionHolders = ResolveConnectionGroup(deviceIdentity, true);
             if (amqpConnectionHolders.Count < deviceIdentity.AmqpTransportSettings.AmqpConnectionPoolSettings.MaxPoolSize)
             {
                 amqpConnectionHolder = new AmqpConnectionHolder(deviceIdentity);
                 amqpConnectionHolder.OnConnectionDisconnected += (o, args) => RemoveConnection(amqpConnectionHolders, o as IAmqpConnectionHolder);
                 amqpConnectionHolders.Add(amqpConnectionHolder);
                 if (Logging.IsEnabled)
                 {
                     Logging.Associate(this, amqpConnectionHolder, "amqpConnectionHolders");
                 }
             }
             else
             {
                 amqpConnectionHolder = GetLeastUsedConnection(amqpConnectionHolders);
             }
         }
         if (Logging.IsEnabled)
         {
             Logging.Exit(this, deviceIdentity, $"{nameof(CreateAmqpUnit)}");
         }
         return(amqpConnectionHolder.CreateAmqpUnit(deviceIdentity, methodHandler, twinMessageListener, eventListener));
     }
     else
     {
         if (Logging.IsEnabled)
         {
             Logging.Exit(this, deviceIdentity, $"{nameof(CreateAmqpUnit)}");
         }
         return(new AmqpConnectionHolder(deviceIdentity)
                .CreateAmqpUnit(deviceIdentity, methodHandler, twinMessageListener, eventListener));
     }
 }
        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 AmqpUnit CreateAmqpUnit(
            DeviceIdentity deviceIdentity,
            Func <MethodRequestInternal, Task> onMethodCallback,
            Action <Twin, string, TwinCollection, IotHubException> twinMessageListener,
            Func <string, Message, Task> onModuleMessageReceivedCallback,
            Func <Message, Task> onDeviceMessageReceivedCallback,
            Action onUnitDisconnected)
        {
            IAmqpUnitManager amqpConnectionPool = ResolveConnectionPool(deviceIdentity.IotHubConnectionString.HostName);

            return(amqpConnectionPool.CreateAmqpUnit(
                       deviceIdentity,
                       onMethodCallback,
                       twinMessageListener,
                       onModuleMessageReceivedCallback,
                       onDeviceMessageReceivedCallback,
                       onUnitDisconnected));
        }
示例#6
0
 internal static async Task <ReceivingAmqpLink> OpenEventsReceiverLinkAsync(
     DeviceIdentity deviceIdentity,
     AmqpSession amqpSession,
     TimeSpan timeout
     )
 {
     return(await OpenReceivingAmqpLinkAsync(
                deviceIdentity,
                amqpSession,
                null,
                (byte)ReceiverSettleMode.First,
                CommonConstants.DeviceEventPathTemplate,
                CommonConstants.ModuleEventPathTemplate,
                EventsReceiverLinkSuffix,
                null,
                timeout
                ).ConfigureAwait(false));
 }
示例#7
0
 internal static async Task <SendingAmqpLink> OpenTelemetrySenderLinkAsync(
     DeviceIdentity deviceIdentity,
     AmqpSession amqpSession,
     TimeSpan timeout
     )
 {
     return(await OpenSendingAmqpLinkAsync(
                deviceIdentity,
                amqpSession,
                null,
                null,
                CommonConstants.DeviceEventPathTemplate,
                CommonConstants.ModuleEventPathTemplate,
                TelemetrySenderLinkSuffix,
                null,
                timeout
                ).ConfigureAwait(false));
 }
 private ISet <IAmqpConnectionHolder> ResolveConnectionGroup(DeviceIdentity deviceIdentity, bool create)
 {
     if (deviceIdentity.AuthenticationModel == AuthenticationModel.SasIndividual)
     {
         return(AmqpSasIndividualPool);
     }
     else
     {
         string scope = deviceIdentity.IotHubConnectionString.SharedAccessKeyName;
         AmqpSasGroupedPool.TryGetValue(scope, out ISet <IAmqpConnectionHolder> amqpConnectionHolders);
         if (create && amqpConnectionHolders == null)
         {
             amqpConnectionHolders = new HashSet <IAmqpConnectionHolder>();
             AmqpSasGroupedPool.Add(scope, amqpConnectionHolders);
         }
         return(amqpConnectionHolders);
     }
 }
示例#9
0
        private void RemoveDevice(DeviceIdentity deviceIdentity, bool gracefulDisconnect)
        {
            if (Logging.IsEnabled)
            {
                Logging.Enter(this, deviceIdentity, $"{nameof(RemoveDevice)}");
            }
            bool removed = AmqpUnits.Remove(deviceIdentity);

            if (removed && GetNumberOfUnits() == 0)
            {
                // TODO #887: handle gracefulDisconnect
                Shutdown();
            }
            if (Logging.IsEnabled)
            {
                Logging.Exit(this, deviceIdentity, $"{nameof(RemoveDevice)}");
            }
        }
示例#10
0
 internal static async Task <SendingAmqpLink> OpenTwinSenderLinkAsync(
     DeviceIdentity deviceIdentity,
     AmqpSession amqpSession,
     string correlationIdSuffix,
     TimeSpan timeout
     )
 {
     return(await OpenSendingAmqpLinkAsync(
                deviceIdentity,
                amqpSession,
                (byte)SenderSettleMode.Settled,
                (byte)ReceiverSettleMode.First,
                CommonConstants.DeviceTwinPathTemplate,
                CommonConstants.ModuleTwinPathTemplate,
                TwinSenderLinkSuffix,
                TwinCorrelationIdPrefix + correlationIdSuffix,
                timeout
                ).ConfigureAwait(false));
 }
        public async Task <AmqpIoTSession> OpenSessionAsync(DeviceIdentity deviceIdentity, TimeSpan timeout)
        {
            if (Logging.IsEnabled)
            {
                Logging.Enter(this, deviceIdentity, timeout, $"{nameof(OpenSessionAsync)}");
            }
            AmqpIoTConnection amqpIoTConnection = await EnsureConnectionAsync(timeout).ConfigureAwait(false);

            AmqpIoTSession amqpIoTSession = await amqpIoTConnection.OpenSessionAsync(timeout).ConfigureAwait(false);

            if (Logging.IsEnabled)
            {
                Logging.Associate(amqpIoTConnection, amqpIoTSession, $"{nameof(OpenSessionAsync)}");
            }
            if (Logging.IsEnabled)
            {
                Logging.Exit(this, deviceIdentity, timeout, $"{nameof(OpenSessionAsync)}");
            }
            return(amqpIoTSession);
        }
示例#12
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);
        }
示例#13
0
        public AmqpUnit(
            DeviceIdentity deviceIdentity,
            Func<DeviceIdentity, ILinkFactory, AmqpSessionSettings, TimeSpan, Task<AmqpSession>> amqpSessionCreator,
            Func<DeviceIdentity, TimeSpan, Task<IAmqpAuthenticationRefresher>> amqpAuthenticationRefresherCreator,
            Func<MethodRequestInternal, Task> methodHandler,
            Action<AmqpMessage> twinMessageListener,
            Func<string, Message, Task> eventListener)
        {
            _deviceIdentity = deviceIdentity;
            _methodHandler = methodHandler;
            _twinMessageListener = twinMessageListener;
            _eventListener = eventListener;
            _amqpSessionCreator = amqpSessionCreator;
            _amqpAuthenticationRefresherCreator = amqpAuthenticationRefresherCreator;
            _amqpSessionSettings = new AmqpSessionSettings()
            {
                Properties = new Fields()
            };

            if (Logging.IsEnabled) Logging.Associate(this, _deviceIdentity, $"{nameof(_deviceIdentity)}");
        }
示例#14
0
        private static string BuildLinkAddress(DeviceIdentity deviceIdentity, string deviceTemplate, string moduleTemplate)
        {
            string path;

            if (string.IsNullOrEmpty(deviceIdentity.IotHubConnectionString.ModuleId))
            {
                path = string.Format(
                    CultureInfo.InvariantCulture,
                    deviceTemplate,
                    WebUtility.UrlEncode(deviceIdentity.IotHubConnectionString.DeviceId)
                    );
            }
            else
            {
                path = string.Format(
                    CultureInfo.InvariantCulture,
                    moduleTemplate,
                    WebUtility.UrlEncode(deviceIdentity.IotHubConnectionString.DeviceId), WebUtility.UrlEncode(deviceIdentity.IotHubConnectionString.ModuleId)
                    );
            }
            return(deviceIdentity.IotHubConnectionString.BuildLinkAddress(path).AbsoluteUri);
        }
示例#15
0
        public AmqpUnit CreateAmqpUnit(
            DeviceIdentity deviceIdentity,
            Func <MethodRequestInternal, Task> methodHandler,
            Action <Twin, string, TwinCollection> twinMessageListener,
            Func <string, Message, Task> eventListener,
            Action onUnitDisconnected)
        {
            if (Logging.IsEnabled)
            {
                Logging.Enter(this, deviceIdentity, $"{nameof(CreateAmqpUnit)}");
            }

            if (deviceIdentity.IsPooling())
            {
                AmqpConnectionHolder amqpConnectionHolder;
                lock (_lock)
                {
                    AmqpConnectionHolder[] amqpConnectionHolders = ResolveConnectionGroup(deviceIdentity);
                    amqpConnectionHolder = ResolveConnectionByHashing(amqpConnectionHolders, deviceIdentity);
                }

                if (Logging.IsEnabled)
                {
                    Logging.Exit(this, deviceIdentity, $"{nameof(CreateAmqpUnit)}");
                }

                return(amqpConnectionHolder.CreateAmqpUnit(deviceIdentity, methodHandler, twinMessageListener, eventListener, onUnitDisconnected));
            }
            else
            {
                if (Logging.IsEnabled)
                {
                    Logging.Exit(this, deviceIdentity, $"{nameof(CreateAmqpUnit)}");
                }

                return(new AmqpConnectionHolder(deviceIdentity).CreateAmqpUnit(deviceIdentity, methodHandler, twinMessageListener, eventListener, onUnitDisconnected));
            }
        }
示例#16
0
        internal AmqpTransportHandler(
            IPipelineContext context,
            IotHubConnectionString connectionString,
            AmqpTransportSettings transportSettings,
            Func <MethodRequestInternal, Task> methodHandler = null,
            Action <TwinCollection> desiredPropertyListener  = null,
            Func <string, Message, Task> eventListener       = null)
            : base(context, transportSettings)
        {
            _operationTimeout        = transportSettings.OperationTimeout;
            _desiredPropertyListener = desiredPropertyListener;
            DeviceIdentity deviceIdentity = new DeviceIdentity(connectionString, transportSettings, context.Get <ProductInfo>());

            _amqpUnit = AmqpUnitManager.GetInstance().CreateAmqpUnit(
                deviceIdentity,
                methodHandler,
                TwinMessageListener,
                eventListener
                );

            _amqpUnit.OnUnitDisconnected += (o, args) =>
            {
                bool gracefulDisconnect = (bool)o;
                if (gracefulDisconnect)
                {
                    OnTransportClosedGracefully();
                }
                else
                {
                    OnTransportDisconnected();
                }
            };

            if (Logging.IsEnabled)
            {
                Logging.Associate(this, _amqpUnit, $"{nameof(_amqpUnit)}");
            }
        }
示例#17
0
        private AmqpConnectionHolder[] ResolveConnectionGroup(DeviceIdentity deviceIdentity)
        {
            if (deviceIdentity.AuthenticationModel == AuthenticationModel.SasIndividual)
            {
                if (_amqpSasIndividualPool == null)
                {
                    _amqpSasIndividualPool = new AmqpConnectionHolder[deviceIdentity.AmqpTransportSettings.AmqpConnectionPoolSettings.MaxPoolSize];
                }

                return(_amqpSasIndividualPool);
            }
            else
            {
                string scope = deviceIdentity.IotHubConnectionString.SharedAccessKeyName;
                _amqpSasGroupedPool.TryGetValue(scope, out AmqpConnectionHolder[] amqpConnectionHolders);
                if (amqpConnectionHolders == null)
                {
                    amqpConnectionHolders = new AmqpConnectionHolder[deviceIdentity.AmqpTransportSettings.AmqpConnectionPoolSettings.MaxPoolSize];
                    _amqpSasGroupedPool.Add(scope, amqpConnectionHolders);
                }

                return(amqpConnectionHolders);
            }
        }
        public void RemoveAmqpUnit(AmqpUnit amqpUnit)
        {
            if (Logging.IsEnabled)
            {
                Logging.Enter(this, amqpUnit, $"{nameof(RemoveAmqpUnit)}");
            }
            DeviceIdentity deviceIdentity = amqpUnit.GetDeviceIdentity();

            if (deviceIdentity.IsPooling())
            {
                AmqpConnectionHolder amqpConnectionHolder;
                lock (_lock)
                {
                    AmqpConnectionHolder[] amqpConnectionHolders = ResolveConnectionGroup(deviceIdentity);
                    amqpConnectionHolder = ResolveConnectionByHashing(amqpConnectionHolders, deviceIdentity);
                }
                amqpConnectionHolder.RemoveAmqpUnit(amqpUnit);
            }

            if (Logging.IsEnabled)
            {
                Logging.Exit(this, amqpUnit, $"{nameof(RemoveAmqpUnit)}");
            }
        }
示例#19
0
        internal AmqpTransportHandler(
            IPipelineContext context,
            IotHubConnectionString connectionString,
            AmqpTransportSettings transportSettings,
            Func <MethodRequestInternal, Task> onMethodCallback          = null,
            Action <TwinCollection> onDesiredStatePatchReceivedCallback  = null,
            Func <string, Message, Task> onModuleMessageReceivedCallback = null,
            Func <Message, Task> onDeviceMessageReceivedCallback         = null)
            : base(context, transportSettings)
        {
            _operationTimeout            = transportSettings.OperationTimeout;
            _onDesiredStatePatchListener = onDesiredStatePatchReceivedCallback;
            var deviceIdentity = new DeviceIdentity(connectionString, transportSettings, context.Get <ProductInfo>(), context.Get <ClientOptions>());

            _amqpUnit = AmqpUnitManager.GetInstance().CreateAmqpUnit(
                deviceIdentity,
                onMethodCallback,
                TwinMessageListener,
                onModuleMessageReceivedCallback,
                onDeviceMessageReceivedCallback,
                OnDisconnected);

            Logging.Associate(this, _amqpUnit, nameof(_amqpUnit));
        }
示例#20
0
        private AmqpConnectionHolder ResolveConnectionByHashing(AmqpConnectionHolder[] pool, DeviceIdentity deviceIdentity)
        {
            if (Logging.IsEnabled)
            {
                Logging.Enter(this, deviceIdentity, $"{nameof(ResolveConnectionByHashing)}");
            }

            int index = Math.Abs(deviceIdentity.GetHashCode()) % pool.Length;

            if (pool[index] == null)
            {
                pool[index] = new AmqpConnectionHolder(deviceIdentity);
            }

            if (Logging.IsEnabled)
            {
                Logging.Exit(this, deviceIdentity, $"{nameof(ResolveConnectionByHashing)}");
            }

            return(pool[index]);
        }
示例#21
0
        private async Task <IAmqpAuthenticationRefresher> AuthenticationRefresherCreator(DeviceIdentity deviceIdentity, TimeSpan timeout)
        {
            if (Logging.IsEnabled)
            {
                Logging.Enter(this, deviceIdentity, timeout, $"{nameof(AuthenticationRefresherCreator)}");
            }
            if (AmqpConnection == null)
            {
                throw new IotHubCommunicationException();
            }
            AmqpCbsLink = AmqpCbsLink ?? new AmqpCbsLink(AmqpConnection);

            IAmqpAuthenticationRefresher amqpAuthenticator = new AmqpAuthenticationRefresher(deviceIdentity, AmqpCbsLink);
            await amqpAuthenticator.InitLoopAsync(timeout).ConfigureAwait(false);

            if (Logging.IsEnabled)
            {
                Logging.Exit(this, deviceIdentity, timeout, $"{nameof(AuthenticationRefresherCreator)}");
            }
            return(amqpAuthenticator);
        }
        public AmqpUnit CreateAmqpUnit(
            DeviceIdentity deviceIdentity,
            Func <MethodRequestInternal, Task> onMethodCallback,
            Action <Twin, string, TwinCollection, IotHubException> twinMessageListener,
            Func <string, Message, Task> onModuleMessageReceivedCallback,
            Func <Message, Task> onDeviceMessageReceivedCallback,
            Action onUnitDisconnected)
        {
            if (Logging.IsEnabled)
            {
                Logging.Enter(this, deviceIdentity, nameof(CreateAmqpUnit));
            }

            if (deviceIdentity.IsPooling())
            {
                AmqpConnectionHolder amqpConnectionHolder;
                lock (_lock)
                {
                    AmqpConnectionHolder[] amqpConnectionHolders = ResolveConnectionGroup(deviceIdentity);
                    amqpConnectionHolder = ResolveConnectionByHashing(amqpConnectionHolders, deviceIdentity);

                    // For group sas token authenticated devices over a multiplexed connection, the TokenRefresher
                    // of the first client connecting will be used for generating the group sas tokens
                    // and will be associated with the connection itself.
                    // For this reason, if the device identity of the client is not the one associated with the
                    // connection, the associated TokenRefresher can be safely disposed.
                    // Note - This does not cause any identity related issues since the group sas tokens are generated
                    // against the hub host as the intended audience (without the "device Id").
                    if (deviceIdentity.AuthenticationModel == AuthenticationModel.SasGrouped &&
                        !ReferenceEquals(amqpConnectionHolder.GetDeviceIdentityOfAuthenticationProvider(), deviceIdentity) &&
                        deviceIdentity.IotHubConnectionString?.TokenRefresher != null &&
                        deviceIdentity.IotHubConnectionString.TokenRefresher.DisposalWithClient)
                    {
                        deviceIdentity.IotHubConnectionString.TokenRefresher.Dispose();
                    }
                }

                if (Logging.IsEnabled)
                {
                    Logging.Exit(this, deviceIdentity, nameof(CreateAmqpUnit));
                }

                return(amqpConnectionHolder.CreateAmqpUnit(
                           deviceIdentity,
                           onMethodCallback,
                           twinMessageListener,
                           onModuleMessageReceivedCallback,
                           onDeviceMessageReceivedCallback,
                           onUnitDisconnected));
            }
            else
            {
                if (Logging.IsEnabled)
                {
                    Logging.Exit(this, deviceIdentity, nameof(CreateAmqpUnit));
                }

                return(new AmqpConnectionHolder(deviceIdentity)
                       .CreateAmqpUnit(
                           deviceIdentity,
                           onMethodCallback,
                           twinMessageListener,
                           onModuleMessageReceivedCallback,
                           onDeviceMessageReceivedCallback,
                           onUnitDisconnected));
            }
        }