/// <summary> /// Called by the service fabric when the listener is to be started /// </summary> /// <param name="cancellationToken">A token to monitor for abort requests</param> /// <returns>A task that completes when the service is openned</returns> public async Task <string> OpenAsync(CancellationToken cancellationToken) { string publishAddress = null; Guid traceId = Guid.NewGuid(); int threadCount = Environment.ProcessorCount; this.serverControl = new CancellationTokenSource(); GatewayConfiguration configuration = this.configurationProvider.Config; this.logger.Informational(traceId, this.componentName, "OpenAsync() invoked."); var iotHubConfigurationProvider = new ConfigurationProvider <IoTHubConfiguration>(traceId, this.serviceContext.ServiceName, this.serviceContext.CodePackageActivationContext, this.logger, "IoTHubClient"); iotHubConfigurationProvider.ConfigurationChangedEvent += (sender, args) => this.unsupportedConfigurationChangeCallback?.Invoke(); iotHubConfigurationProvider.ConfigurationPropertyChangedEvent += (sender, args) => this.unsupportedConfigurationChangeCallback?.Invoke(); IoTHubConfiguration iotHubConfiguration = iotHubConfigurationProvider.Config; X509Certificate2 certificate = this.GetServerCertificate(configuration); this.logger.Informational(traceId, this.componentName, "Certificate retrieved."); var mqttConfigurationProvider = new ConfigurationProvider <MqttServiceConfiguration>(traceId, this.serviceContext.ServiceName, this.serviceContext.CodePackageActivationContext, this.logger, "Mqtt"); mqttConfigurationProvider.ConfigurationChangedEvent += (sender, args) => this.unsupportedConfigurationChangeCallback?.Invoke(); mqttConfigurationProvider.ConfigurationPropertyChangedEvent += (sender, args) => this.unsupportedConfigurationChangeCallback?.Invoke(); MqttServiceConfiguration mqttConfiguration = mqttConfigurationProvider.Config; if (mqttConfiguration != null) { var mqttInboundTemplates = new List <string>(mqttConfiguration.MqttInboundTemplates); var mqttOutboundTemplates = new List <string>(mqttConfiguration.MqttOutboundTemplates); ISessionStatePersistenceProvider qosSessionProvider = await this.GetSessionStateProviderAsync(traceId, mqttConfiguration).ConfigureAwait(false); IQos2StatePersistenceProvider qos2SessionProvider = await this.GetQos2StateProvider(traceId, mqttConfiguration).ConfigureAwait(false); this.logger.Informational(traceId, this.componentName, "QOS Providers instantiated."); var settingsProvider = new ServiceFabricConfigurationProvider(traceId, this.componentName, this.logger, configuration, iotHubConfiguration, mqttConfiguration); this.bootStrapper = new Bootstrapper(settingsProvider, qosSessionProvider, qos2SessionProvider, mqttInboundTemplates, mqttOutboundTemplates); this.runTask = this.bootStrapper.RunAsync(certificate, threadCount, this.serverControl.Token); publishAddress = this.BuildPublishAddress(configuration); this.logger.Informational(traceId, this.componentName, "Bootstrapper instantiated."); } else { this.logger.Critical(traceId, this.componentName, "Failed to start endpoint because Mqtt service configuration is missing."); } return(publishAddress); }
/// <summary> /// Initializes a new instance of the <see cref="MqttService"/> class. /// </summary> /// <param name="mqttServiceConfiguration">The MQTT service configuration.</param> /// <param name="serviceName">The service name.</param> public MqttService(MqttServiceConfiguration mqttServiceConfiguration, string serviceName) { this.MqttServiceConfiguration = mqttServiceConfiguration; this.logger = Log.ForContext("Type", nameof(MqttService)); this.serviceName = serviceName; }
/// <summary> /// Retrieves the state provider for QoS 2 sessions /// </summary> /// <param name="traceId">A unique identifier used to correlate debugging and diagnostics messages</param> /// <param name="configuration">The gateway configuration</param> /// <returns>A Qos2 persistence provider if available</returns> async Task <IQos2StatePersistenceProvider> GetQos2StateProvider(Guid traceId, MqttServiceConfiguration configuration) { IQos2StatePersistenceProvider stateProvider = null; this.logger.Informational(traceId, this.componentName, "QOS2 state provider requested."); switch (configuration.MqttQoS2StateProvider) { case MqttServiceConfiguration.QosStateType.AzureStorage: this.logger.Informational(traceId, this.componentName, "QOS2 state provider requested was Azure Storage."); AzureSessionStateConfiguration provider = new ConfigurationProvider <AzureSessionStateConfiguration>(traceId, this.serviceContext.ServiceName, this.serviceContext.CodePackageActivationContext, this.logger, "AzureState")?.Config; if (provider == null) { this.logger.Critical(traceId, this.componentName, "QOS2 state provider or configuration could not be retrieved."); throw new ApplicationException("Azure state QoS2 provider configuration could not be retrieved"); } stateProvider = await TableQos2StatePersistenceProvider.CreateAsync(provider.TableConnectionString, provider.TableName).ConfigureAwait(false); this.logger.Informational(traceId, this.componentName, "QOS2 state provider request complete."); break; case MqttServiceConfiguration.QosStateType.ServiceFabricStateful: this.logger.Critical(traceId, this.componentName, "QOS2 state provider requested was Service Fabric Stateful Service but it is not currently implemented."); throw new NotImplementedException("Only azure storage provider is supported"); default: this.logger.Critical(traceId, this.componentName, "QOS2 state provider requested was unknown."); throw new ApplicationException("MQTT state provider must be specified in configuration."); } return(stateProvider); }
/// <summary> /// Retrieves the session state provider to be used for MQTT Sessions /// </summary> /// <param name="traceId">A unique identifier used to correlate debugging and diagnostics messages</param> /// <param name="configuration">The gateway configuration</param> /// <returns>A session state persistence provider if available</returns> async Task <ISessionStatePersistenceProvider> GetSessionStateProviderAsync(Guid traceId, MqttServiceConfiguration configuration) { ISessionStatePersistenceProvider stateProvider = null; this.logger.Informational(traceId, this.componentName, "QOS state provider requested."); switch (configuration.MqttQoSStateProvider) { case MqttServiceConfiguration.QosStateType.AzureStorage: this.logger.Informational(traceId, this.componentName, "QOS state provider requested was Azure Storage."); var azureConfigurationProvider = new ConfigurationProvider <AzureSessionStateConfiguration>(traceId, this.serviceContext.ServiceName, this.serviceContext.CodePackageActivationContext, this.logger, "AzureState"); azureConfigurationProvider.ConfigurationChangedEvent += (sender, args) => this.unsupportedConfigurationChangeCallback?.Invoke(); azureConfigurationProvider.ConfigurationPropertyChangedEvent += (sender, args) => this.unsupportedConfigurationChangeCallback?.Invoke(); AzureSessionStateConfiguration azureConfiguration = azureConfigurationProvider.Config; if (azureConfiguration == null) { this.logger.Critical(traceId, this.componentName, "QOS state provider or configuration could not be retrieved."); throw new ApplicationException("Azure state QoS provider configuration could not be retrieved"); } stateProvider = await BlobSessionStatePersistenceProvider.CreateAsync(azureConfiguration.BlobConnectionString, azureConfiguration.ContainerName).ConfigureAwait(false); this.logger.Informational(traceId, this.componentName, "QOS state provider request complete."); break; case MqttServiceConfiguration.QosStateType.ServiceFabricStateful: this.logger.Critical(traceId, this.componentName, "QOS state provider requested was Service Fabric Stateful Service but it is not currently implemented."); throw new NotImplementedException("Only azure storage provider is supported"); default: this.logger.Critical(traceId, this.componentName, "QOS state provider requested was unknown."); throw new ApplicationException("MQTT state provider must be specified in configuration."); } return(stateProvider); }