public static QualityOfService DeriveQos(Message message, Settings config)
 {
     QualityOfService qos;
     string qosValue;
     if (message.Properties.TryGetValue(config.QoSPropertyName, out qosValue))
     {
         int qosAsInt;
         if (int.TryParse(qosValue, out qosAsInt))
         {
             qos = (QualityOfService)qosAsInt;
             if (qos > QualityOfService.ExactlyOnce)
             {
                 MqttIotHubAdapterEventSource.Log.Warning(string.Format("Message defined QoS '{0}' is not supported. Downgrading to default value of '{1}'", qos, config.DefaultPublishToClientQoS));
                 qos = config.DefaultPublishToClientQoS;
             }
         }
         else
         {
             MqttIotHubAdapterEventSource.Log.Warning(string.Format("Message defined QoS '{0}' could not be parsed. Resorting to default value of '{1}'", qosValue, config.DefaultPublishToClientQoS));
             qos = config.DefaultPublishToClientQoS;
         }
     }
     else
     {
         qos = config.DefaultPublishToClientQoS;
     }
     return qos;
 }
        public MqttIotHubAdapter(Settings settings, DeviceClientFactoryFunc deviceClientFactory, ISessionStatePersistenceProvider sessionStateManager, IAuthenticationProvider authProvider,
            ITopicNameRouter topicNameRouter, IQos2StatePersistenceProvider qos2StateProvider)
        {
            Contract.Requires(settings != null);
            Contract.Requires(sessionStateManager != null);
            Contract.Requires(authProvider != null);
            Contract.Requires(topicNameRouter != null);

            if (qos2StateProvider != null)
            {
                this.maxSupportedQosToClient = QualityOfService.ExactlyOnce;
                this.qos2StateProvider = qos2StateProvider;
            }
            else
            {
                this.maxSupportedQosToClient = QualityOfService.AtLeastOnce;
            }

            this.settings = settings;
            this.deviceClientFactory = deviceClientFactory;
            this.sessionStateManager = sessionStateManager;
            this.authProvider = authProvider;
            this.topicNameRouter = topicNameRouter;

            this.publishProcessor = new PacketAsyncProcessor<PublishPacket>(this.PublishToServerAsync);
            this.publishProcessor.Completion.OnFault(ShutdownOnPublishToServerFaultAction);

            TimeSpan? ackTimeout = this.settings.DeviceReceiveAckCanTimeout ? this.settings.DeviceReceiveAckTimeout : (TimeSpan?)null;
            this.publishPubAckProcessor = new RequestAckPairProcessor<AckPendingMessageState, PublishPacket>(this.AcknowledgePublishAsync, this.RetransmitNextPublish, ackTimeout);
            this.publishPubAckProcessor.Completion.OnFault(ShutdownOnPubAckFaultAction);
            this.publishPubRecProcessor = new RequestAckPairProcessor<AckPendingMessageState, PublishPacket>(this.AcknowledgePublishReceiveAsync, this.RetransmitNextPublish, ackTimeout);
            this.publishPubRecProcessor.Completion.OnFault(ShutdownOnPubRecFaultAction);
            this.pubRelPubCompProcessor = new RequestAckPairProcessor<CompletionPendingMessageState, PubRelPacket>(this.AcknowledgePublishCompleteAsync, this.RetransmitNextPublishRelease, ackTimeout);
            this.pubRelPubCompProcessor.Completion.OnFault(ShutdownOnPubCompFaultAction);
        }
        public static QualityOfService DeriveQos(IMessage message, Settings config, string scope)
        {
            string qosValue;
            if (!message.Properties.TryGetValue(config.QoSPropertyName, out qosValue))
            {
                return config.DefaultPublishToClientQoS;
            }

            if (qosValue.Length > 1)
            {
                CommonEventSource.Log.Warning($"Message defined QoS '{qosValue}' is not supported. Downgrading to default value of '{config.DefaultPublishToClientQoS}'", scope);
                return config.DefaultPublishToClientQoS;
            }

            switch (qosValue[0])
            {
                case '0':
                    return QualityOfService.AtMostOnce;
                case '1':
                    return QualityOfService.AtLeastOnce;
                case '2':
                    return QualityOfService.ExactlyOnce;
                default:
                    CommonEventSource.Log.Warning($"Message defined QoS '{qosValue}' is not supported. Downgrading to default value of '{config.DefaultPublishToClientQoS}'", scope);
                    return config.DefaultPublishToClientQoS;
            }
        }
        public Bootstrapper(ISettingsProvider settingsProvider, ISessionStatePersistenceProvider sessionStateManager, IQos2StatePersistenceProvider qos2StateProvider)
        {
            Contract.Requires(settingsProvider != null);
            Contract.Requires(sessionStateManager != null);

            this.closeCompletionSource = new TaskCompletionSource();

            this.settingsProvider = settingsProvider;
            this.settings = new Settings(this.settingsProvider);
            this.sessionStateManager = sessionStateManager;
            this.qos2StateProvider = qos2StateProvider;
            this.authProvider = new SasTokenAuthenticationProvider();
            this.topicNameRouter = new TopicNameRouter();
        }
        Bootstrapper(ISettingsProvider settingsProvider, ISessionStatePersistenceProvider sessionStateManager, IQos2StatePersistenceProvider qos2StateProvider, IMessageAddressConverter addressConverter)
        {
            Contract.Requires(settingsProvider != null);
            Contract.Requires(sessionStateManager != null);

            this.closeCompletionSource = new TaskCompletionSource();

            this.settingsProvider = settingsProvider;
            this.settings = new Settings(this.settingsProvider);
            this.iotHubClientSettings = new IotHubClientSettings(this.settingsProvider);
            this.sessionStateManager = sessionStateManager;
            this.qos2StateProvider = qos2StateProvider;
            this.authProvider = new SasTokenDeviceIdentityProvider();
            this.topicNameConverter = addressConverter;
        }
        public static Message CompleteMessageFromPacket(Message message, PublishPacket packet, Settings settings)
        {
            message.MessageId = Guid.NewGuid().ToString("N");
            if (packet.RetainRequested)
            {
                message.Properties[settings.RetainPropertyName] = IotHubTrueString;
            }
            if (packet.Duplicate)
            {
                message.Properties[settings.DupPropertyName] = IotHubTrueString;
            }

            return message;
        }
        async Task EnsureServerInitializedAsync()
        {
            if (this.ServerAddress != null)
            {
                return;
            }

            int threadCount = Environment.ProcessorCount;
            var executorGroup = new MultithreadEventLoopGroup(threadCount);
            var bufAllocator = new PooledByteBufferAllocator(16 * 1024, 10 * 1024 * 1024 / threadCount); // reserve 10 MB for 64 KB buffers
            BlobSessionStatePersistenceProvider sessionStateProvider = await BlobSessionStatePersistenceProvider.CreateAsync(
                this.settingsProvider.GetSetting("BlobSessionStatePersistenceProvider.StorageConnectionString"),
                this.settingsProvider.GetSetting("BlobSessionStatePersistenceProvider.StorageContainerName"));
            TableQos2StatePersistenceProvider qos2StateProvider = await TableQos2StatePersistenceProvider.CreateAsync(
                this.settingsProvider.GetSetting("TableQos2StatePersistenceProvider.StorageConnectionString"),
                this.settingsProvider.GetSetting("TableQos2StatePersistenceProvider.StorageTableName"));
            var settings = new Settings(this.settingsProvider);
            var authProvider = new SasTokenAuthenticationProvider();
            var topicNameRouter = new TopicNameRouter();

            DeviceClientFactoryFunc deviceClientFactoryFactory = IotHubDeviceClient.PreparePoolFactory(settings.IotHubConnectionString + ";DeviceId=stub", "a", 1);

            ServerBootstrap server = new ServerBootstrap()
                .Group(executorGroup)
                .Channel<TcpServerSocketChannel>()
                .ChildOption(ChannelOption.Allocator, bufAllocator)
                .ChildOption(ChannelOption.AutoRead, false)
                .ChildHandler(new ActionChannelInitializer<IChannel>(ch =>
                {
                    ch.Pipeline.AddLast(TlsHandler.Server(this.tlsCertificate));
                    ch.Pipeline.AddLast(
                        MqttEncoder.Instance,
                        new MqttDecoder(true, 256 * 1024),
                        new MqttIotHubAdapter(
                            settings,
                            deviceClientFactoryFactory,
                            sessionStateProvider,
                            authProvider,
                            topicNameRouter,
                            qos2StateProvider),
                        new XUnitLoggingHandler(this.output));
                }));

            IChannel serverChannel = await server.BindAsync(IPAddress.Any, this.ProtocolGatewayPort);

            this.ScheduleCleanup(async () =>
            {
                await serverChannel.CloseAsync();
                await executorGroup.ShutdownGracefullyAsync();
            });
            this.ServerAddress = IPAddress.Loopback;
        }
        public static IMessage CompleteMessageFromPacket(IMessage message, PublishPacket packet, Settings settings)
        {
            if (packet.RetainRequested)
            {
                message.Properties[settings.RetainPropertyName] = IotHubTrueString;
            }
            if (packet.Duplicate)
            {
                message.Properties[settings.DupPropertyName] = IotHubTrueString;
            }

            return message;
        }