コード例 #1
0
        public async Task GetDeviceAndModuleOnBehalfOfAsync([FromRoute] string actorDeviceId, [FromRoute] string actorModuleId, [FromBody] IdentityOnBehalfOfRequest request)
        {
            actorDeviceId = WebUtility.UrlDecode(Preconditions.CheckNonWhiteSpace(actorDeviceId, nameof(actorDeviceId)));
            actorModuleId = WebUtility.UrlDecode(Preconditions.CheckNonWhiteSpace(actorModuleId, nameof(actorModuleId)));
            Preconditions.CheckNonWhiteSpace(request.AuthChain, nameof(request.AuthChain));

            if (actorModuleId != Constants.EdgeHubModuleId)
            {
                // Only child EdgeHubs are allowed to act OnBehalfOf of devices/modules.
                var result = new EdgeHubScopeResultError(HttpStatusCode.Unauthorized, Events.UnauthorizedActor(actorDeviceId, actorModuleId, string.IsNullOrWhiteSpace(request.TargetModuleId) ? request.TargetDeviceId : $"{request.TargetDeviceId}/{request.TargetModuleId}"));
                await this.SendResponse(result.Status, JsonConvert.SerializeObject(result));
            }

            IHttpRequestAuthenticator authenticator = await this.authenticatorGetter;
            HttpAuthResult            authResult    = await authenticator.AuthenticateAsync(actorDeviceId, Option.Some(actorModuleId), Option.Some(request.AuthChain), this.HttpContext);

            if (authResult.Authenticated)
            {
                IEdgeHub edgeHub = await this.edgeHubGetter;
                IDeviceScopeIdentitiesCache identitiesCache = edgeHub.GetDeviceScopeIdentitiesCache();
                EdgeHubScopeResult          reqResult       = await HandleGetDeviceAndModuleOnBehalfOfAsync(actorDeviceId, actorModuleId, request, identitiesCache);

                await this.SendResponse(reqResult.Status, JsonConvert.SerializeObject(reqResult));
            }
            else
            {
                var result = new EdgeHubScopeResultError(HttpStatusCode.Unauthorized, authResult.ErrorMessage);
                await this.SendResponse(result.Status, JsonConvert.SerializeObject(result));
            }
        }
コード例 #2
0
        public static async Task <EdgeHubConnection> Create(
            IIdentity edgeHubIdentity,
            IEdgeHub edgeHub,
            ITwinManager twinManager,
            IConnectionManager connectionManager,
            RouteFactory routeFactory,
            IMessageConverter <TwinCollection> twinCollectionMessageConverter,
            VersionInfo versionInfo,
            IDeviceScopeIdentitiesCache deviceScopeIdentitiesCache)
        {
            Preconditions.CheckNotNull(edgeHubIdentity, nameof(edgeHubIdentity));
            Preconditions.CheckNotNull(edgeHub, nameof(edgeHub));
            Preconditions.CheckNotNull(connectionManager, nameof(connectionManager));
            Preconditions.CheckNotNull(twinCollectionMessageConverter, nameof(twinCollectionMessageConverter));
            Preconditions.CheckNotNull(routeFactory, nameof(routeFactory));
            Preconditions.CheckNotNull(deviceScopeIdentitiesCache, nameof(deviceScopeIdentitiesCache));

            var edgeHubConnection = new EdgeHubConnection(
                edgeHubIdentity,
                twinManager,
                routeFactory,
                twinCollectionMessageConverter,
                versionInfo ?? VersionInfo.Empty,
                deviceScopeIdentitiesCache);

            await InitEdgeHub(edgeHubConnection, connectionManager, edgeHubIdentity, edgeHub);

            connectionManager.DeviceConnected    += edgeHubConnection.DeviceConnected;
            connectionManager.DeviceDisconnected += edgeHubConnection.DeviceDisconnected;
            Events.Initialized(edgeHubIdentity);
            return(edgeHubConnection);
        }
コード例 #3
0
        async Task <EdgeHubScopeResult> HandleDevicesAndModulesInTargetDeviceScopeAsync(string actorDeviceId, string actorModuleId, NestedScopeRequest request)
        {
            Events.ReceivedScopeRequest(actorDeviceId, actorModuleId, request);
            Preconditions.CheckNonWhiteSpace(request.AuthChain, nameof(request.AuthChain));

            if (!this.TryGetTargetDeviceId(request.AuthChain, out string targetDeviceId))
            {
                return(new EdgeHubScopeResultError(HttpStatusCode.BadRequest, Events.InvalidRequestAuthchain(request.AuthChain)));
            }

            // Check that the actor device is authorized to act OnBehalfOf the target
            IEdgeHub edgeHub = await this.edgeHubGetter;
            IDeviceScopeIdentitiesCache identitiesCache = edgeHub.GetDeviceScopeIdentitiesCache();

            if (!await this.AuthorizeActorAsync(identitiesCache, actorDeviceId, actorModuleId, targetDeviceId))
            {
                return(new EdgeHubScopeResultError(HttpStatusCode.Unauthorized, Events.UnauthorizedActor(actorDeviceId, actorModuleId, targetDeviceId)));
            }

            // Get the children of the target device and the target device itself;
            IList <ServiceIdentity> identities = await identitiesCache.GetDevicesAndModulesInTargetScopeAsync(targetDeviceId);

            Option <ServiceIdentity> targetDevice = await identitiesCache.GetServiceIdentity(targetDeviceId);

            targetDevice.ForEach(d => identities.Add(d));

            // Construct the result from the identities
            Events.SendingScopeResult(targetDeviceId, identities);
            return(MakeResultFromIdentities(identities));
        }
コード例 #4
0
 public DeviceMessageHandler(IIdentity identity, IEdgeHub edgeHub, IConnectionManager connectionManager, TimeSpan messageAckTimeout)
 {
     this.Identity          = Preconditions.CheckNotNull(identity, nameof(identity));
     this.edgeHub           = Preconditions.CheckNotNull(edgeHub, nameof(edgeHub));
     this.connectionManager = Preconditions.CheckNotNull(connectionManager, nameof(connectionManager));
     this.messageAckTimeout = messageAckTimeout;
 }
コード例 #5
0
        public async Task DeleteModuleAsync(
            [FromRoute] string deviceId,
            [FromRoute] string moduleId)
        {
            try
            {
                Events.ReceivedRequest(nameof(this.DeleteModuleAsync), deviceId, moduleId);

                try
                {
                    deviceId = WebUtility.UrlDecode(Preconditions.CheckNonWhiteSpace(deviceId, nameof(deviceId)));
                    moduleId = WebUtility.UrlDecode(Preconditions.CheckNonWhiteSpace(moduleId, nameof(moduleId)));
                }
                catch (Exception ex)
                {
                    Events.BadRequest(nameof(this.DeleteModuleAsync), ex.Message);
                    await this.SendResponseAsync(HttpStatusCode.BadRequest, FormatErrorResponseMessage(ex.Message));

                    return;
                }

                IHttpRequestAuthenticator authenticator = await this.authenticatorGetter;
                if (!await AuthenticateAsync(deviceId, Option.None <string>(), Option.None <string>(), this.HttpContext, authenticator))
                {
                    await this.SendResponseAsync(HttpStatusCode.Unauthorized);

                    return;
                }

                IEdgeHub edgeHub = await this.edgeHubGetter;
                IDeviceScopeIdentitiesCache identitiesCache = edgeHub.GetDeviceScopeIdentitiesCache();
                Option <string>             targetAuthChain = await identitiesCache.GetAuthChain(deviceId);

                if (!targetAuthChain.HasValue)
                {
                    Events.AuthorizationFail_NoAuthChain(deviceId);
                    await this.SendResponseAsync(HttpStatusCode.Unauthorized);

                    return;
                }

                string edgeDeviceId          = edgeHub.GetEdgeDeviceId();
                var    requestData           = new DeleteModuleOnBehalfOfData($"{targetAuthChain.OrDefault()}", moduleId);
                RegistryApiHttpResult result = await this.apiClient.DeleteModuleAsync(edgeDeviceId, requestData);

                await this.SendResponseAsync(result.StatusCode, result.JsonContent);

                Events.CompleteRequest(nameof(this.DeleteModuleAsync), edgeDeviceId, requestData.AuthChain, result);
            }
            catch (Exception ex)
            {
                Events.InternalServerError(nameof(this.DeleteModuleAsync), ex);
                await this.SendResponseAsync(HttpStatusCode.InternalServerError, FormatErrorResponseMessage(ex.ToString()));
            }
        }
コード例 #6
0
ファイル: RoutingTest.cs プロジェクト: rdivossen/iotedge
            public static async Task <TestDevice> Create(string deviceId, IEdgeHub edgeHub, IConnectionManager connectionManager)
            {
                IClientCredentials deviceCredentials = SetupDeviceIdentity(deviceId);
                Try <ICloudProxy>  cloudProxy        = await connectionManager.CreateCloudConnectionAsync(deviceCredentials);

                Assert.True(cloudProxy.Success);
                var deviceProxy    = Mock.Of <IDeviceProxy>();
                var deviceListener = new DeviceMessageHandler(deviceCredentials.Identity, edgeHub, connectionManager);

                deviceListener.BindDeviceProxy(deviceProxy);
                return(new TestDevice(deviceCredentials.Identity as IDeviceIdentity, deviceListener));
            }
コード例 #7
0
        async Task <MethodResult> InvokeMethodAsync(DirectMethodRequest directMethodRequest)
        {
            Events.ReceivedMethodCall(directMethodRequest, this.identity);
            IEdgeHub             edgeHub = await this.edgeHubGetter;
            DirectMethodResponse directMethodResponse = await edgeHub.InvokeMethodAsync(this.identity.Id, directMethodRequest);

            Events.ReceivedMethodCallResponse(directMethodRequest, this.identity);

            MethodResult methodResult = GetMethodResult(directMethodResponse);

            return(methodResult);
        }
コード例 #8
0
        public async Task CreateOrUpdateModuleOnBehalfOfAsync(
            [FromRoute] string actorDeviceId,
            [FromHeader(Name = "if-match")] string ifMatchHeader,
            [FromBody] CreateOrUpdateModuleOnBehalfOfData requestData)
        {
            try
            {
                Events.ReceivedOnBehalfOfRequest(nameof(this.CreateOrUpdateModuleOnBehalfOfAsync), actorDeviceId, Events.GetAdditionalInfo(requestData));

                try
                {
                    Preconditions.CheckNonWhiteSpace(actorDeviceId, nameof(actorDeviceId));
                    Preconditions.CheckNotNull(requestData, nameof(requestData));
                    Preconditions.CheckNonWhiteSpace(requestData.AuthChain, nameof(requestData.AuthChain));
                    Preconditions.CheckNotNull(requestData.Module, nameof(requestData.Module));
                }
                catch (Exception ex)
                {
                    Events.BadRequest(nameof(this.CreateOrUpdateModuleOnBehalfOfAsync), ex.Message);
                    await this.SendResponseAsync(HttpStatusCode.BadRequest, FormatErrorResponseMessage(ex.ToString()));

                    return;
                }

                actorDeviceId = WebUtility.UrlDecode(actorDeviceId);
                IEdgeHub edgeHub = await this.edgeHubGetter;
                IHttpRequestAuthenticator authenticator = await this.authenticatorGetter;
                Try <string> targetAuthChainTry         = await AuthorizeOnBehalfOf(actorDeviceId, requestData.AuthChain, nameof(this.CreateOrUpdateModuleOnBehalfOfAsync), this.HttpContext, edgeHub, authenticator);

                if (targetAuthChainTry.Success)
                {
                    string targetAuthChain       = targetAuthChainTry.Value;
                    string edgeDeviceId          = edgeHub.GetEdgeDeviceId();
                    RegistryApiHttpResult result = await this.apiClient.PutModuleAsync(
                        edgeDeviceId,
                        new CreateOrUpdateModuleOnBehalfOfData($"{targetAuthChain}", requestData.Module),
                        ifMatchHeader);

                    await this.SendResponseAsync(result.StatusCode, result.JsonContent);

                    Events.CompleteRequest(nameof(this.CreateOrUpdateModuleOnBehalfOfAsync), edgeDeviceId, targetAuthChain, result);
                }
                else
                {
                    await this.SendErrorResponse(targetAuthChainTry.Exception);
                }
            }
            catch (Exception ex)
            {
                Events.InternalServerError(nameof(this.CreateOrUpdateModuleOnBehalfOfAsync), ex);
                await this.SendResponseAsync(HttpStatusCode.InternalServerError, FormatErrorResponseMessage(ex.ToString()));
            }
        }
コード例 #9
0
        async Task StartProtocolHead()
        {
            string certificateValue = await SecretsHelper.GetSecret("IotHubMqttHeadCert");

            byte[] cert        = Convert.FromBase64String(certificateValue);
            var    certificate = new X509Certificate2(cert);

            // TODO for now this is empty as will suffice for SAS X.509 thumbprint auth but we will need other CA certs for X.509 CA validation
            var trustBundle = new List <X509Certificate2>();

            string edgeDeviceConnectionString = await SecretsHelper.GetSecretFromConfigKey("edgeCapableDeviceConnStrKey");

            // TODO - After IoTHub supports MQTT, remove this and move to using MQTT for upstream connections
            await ConnectToIotHub(edgeDeviceConnectionString);

            ConfigHelper.TestConfig[EdgeHubConstants.ConfigKey.IotHubConnectionString] = edgeDeviceConnectionString;

            IDependencyManager dependencyManager = new DependencyManager(ConfigHelper.TestConfig, certificate, trustBundle, this.sslProtocols);
            Hosting            hosting           = Hosting.Initialize(ConfigHelper.TestConfig, certificate, dependencyManager, true, this.sslProtocols);

            this.hosting = hosting;
            IContainer container = hosting.Container;

            // CloudConnectionProvider and RoutingEdgeHub have a circular dependency. So set the
            // EdgeHub on the CloudConnectionProvider before any other operation
            ICloudConnectionProvider cloudConnectionProvider = await container.Resolve <Task <ICloudConnectionProvider> >();

            IEdgeHub edgeHub = await container.Resolve <Task <IEdgeHub> >();

            cloudConnectionProvider.BindEdgeHub(edgeHub);

            IConfigSource configSource = await container.Resolve <Task <IConfigSource> >();

            ConfigUpdater configUpdater = await container.Resolve <Task <ConfigUpdater> >();

            await configUpdater.Init(configSource);

            ILogger          logger           = container.Resolve <ILoggerFactory>().CreateLogger("EdgeHub");
            MqttProtocolHead mqttProtocolHead = await container.Resolve <Task <MqttProtocolHead> >();

            AmqpProtocolHead amqpProtocolHead = await container.Resolve <Task <AmqpProtocolHead> >();

            var httpProtocolHead = new HttpProtocolHead(hosting.WebHost);

            this.protocolHead = new EdgeHubProtocolHead(new List <IProtocolHead> {
                mqttProtocolHead, amqpProtocolHead, httpProtocolHead
            }, logger);
            await this.protocolHead.StartAsync();
        }
コード例 #10
0
        async Task <IActionResult> InvokeMethodAsync(DirectMethodRequest directMethodRequest)
        {
            Events.ReceivedMethodCall(directMethodRequest, this.identity);
            IEdgeHub             edgeHub = await this.edgeHubGetter;
            DirectMethodResponse directMethodResponse = await edgeHub.InvokeMethodAsync(this.identity.Id, directMethodRequest);

            Events.ReceivedMethodCallResponse(directMethodRequest, this.identity);

            var methodResult = new MethodResult
            {
                Status  = directMethodResponse.Status,
                Payload = GetRawJson(directMethodResponse.Data)
            };

            return(this.Json(methodResult));
        }
コード例 #11
0
        public static async Task <EdgeHubConnection> Create(
            IClientCredentials edgeHubCredentials,
            IEdgeHub edgeHub,
            ITwinManager twinManager,
            IConnectionManager connectionManager,
            ICloudProxy cloudProxy,
            RouteFactory routeFactory,
            IMessageConverter <TwinCollection> twinCollectionMessageConverter,
            IMessageConverter <Twin> twinMessageConverter,
            VersionInfo versionInfo,
            IDeviceScopeIdentitiesCache deviceScopeIdentitiesCache
            )
        {
            Preconditions.CheckNotNull(edgeHubCredentials, nameof(edgeHubCredentials));
            Preconditions.CheckNotNull(edgeHub, nameof(edgeHub));
            Preconditions.CheckNotNull(connectionManager, nameof(connectionManager));
            Preconditions.CheckNotNull(cloudProxy, nameof(cloudProxy));
            Preconditions.CheckNotNull(twinCollectionMessageConverter, nameof(twinCollectionMessageConverter));
            Preconditions.CheckNotNull(twinMessageConverter, nameof(twinMessageConverter));
            Preconditions.CheckNotNull(routeFactory, nameof(routeFactory));
            Preconditions.CheckNotNull(deviceScopeIdentitiesCache, nameof(deviceScopeIdentitiesCache));

            var edgeHubConnection = new EdgeHubConnection(
                edgeHubCredentials.Identity as IModuleIdentity, twinManager, routeFactory,
                twinCollectionMessageConverter, twinMessageConverter,
                versionInfo ?? VersionInfo.Empty,
                deviceScopeIdentitiesCache
                );

            IDeviceProxy deviceProxy = new EdgeHubDeviceProxy(edgeHubConnection);
            await connectionManager.AddDeviceConnection(edgeHubCredentials);

            connectionManager.BindDeviceProxy(edgeHubCredentials.Identity, deviceProxy);

            await edgeHub.AddSubscription(edgeHubCredentials.Identity.Id, DeviceSubscription.DesiredPropertyUpdates);

            await edgeHub.AddSubscription(edgeHubCredentials.Identity.Id, DeviceSubscription.Methods);

            // Clear out all the reported devices.
            await edgeHubConnection.ClearDeviceConnectionStatuses();

            connectionManager.DeviceConnected    += edgeHubConnection.DeviceConnected;
            connectionManager.DeviceDisconnected += edgeHubConnection.DeviceDisconnected;
            Events.Initialized(edgeHubCredentials.Identity);
            return(edgeHubConnection);
        }
コード例 #12
0
ファイル: TwinsController.cs プロジェクト: DaveEM/iotedge
        async Task <IActionResult> InvokeMethodAsync(DirectMethodRequest directMethodRequest)
        {
            Events.ReceivedMethodCall(directMethodRequest, this.identity);
            IEdgeHub             edgeHub = await this.edgeHubGetter;
            DirectMethodResponse directMethodResponse = await edgeHub.InvokeMethodAsync(this.identity.Id, directMethodRequest);

            Events.ReceivedMethodCallResponse(directMethodRequest, this.identity);

            MethodResult methodResult = GetMethodResult(directMethodResponse);
            HttpResponse response     = this.Request?.HttpContext?.Response;

            if (response != null)
            {
                response.ContentLength = GetContentLength(methodResult);
            }
            return(this.StatusCode((int)directMethodResponse.HttpStatusCode, methodResult));
        }
コード例 #13
0
ファイル: TwinsController.cs プロジェクト: afzaljan/iotedge
        async Task <MethodResult> InvokeMethodAsync(DirectMethodRequest directMethodRequest)
        {
            Events.ReceivedMethodCall(directMethodRequest);
            IEdgeHub edgeHub = await this.edgeHubGetter;

            MethodResult methodResult;
            string       currentEdgeDeviceId = edgeHub.GetEdgeDeviceId();

            if (this.TryGetActorId(out string actorDeviceId, out string actorModuleId))
            {
                string actorId = $"{actorDeviceId}/{actorModuleId}";

                if (actorDeviceId == currentEdgeDeviceId)
                {
                    IHttpRequestAuthenticator authenticator = await this.authenticatorGetter;
                    HttpAuthResult            authResult    = await authenticator.AuthenticateAsync(actorDeviceId, Option.Some(actorModuleId), this.HttpContext);

                    if (authResult.Authenticated)
                    {
                        using (Metrics.TimeDirectMethod(actorDeviceId, directMethodRequest.Id))
                        {
                            DirectMethodResponse directMethodResponse = await edgeHub.InvokeMethodAsync(actorId, directMethodRequest);

                            Events.ReceivedMethodCallResponse(directMethodRequest, actorId);

                            methodResult = GetMethodResult(directMethodResponse);
                        }
                    }
                    else
                    {
                        methodResult = new MethodErrorResult(HttpStatusCode.Unauthorized, authResult.ErrorMessage);
                    }
                }
                else
                {
                    methodResult = new MethodErrorResult(HttpStatusCode.Unauthorized, "Only modules on the same device can invoke DirectMethods");
                }
            }
            else
            {
                methodResult = new MethodErrorResult(HttpStatusCode.BadRequest, $"Invalid header value for {Constants.ServiceApiIdHeaderKey}");
            }

            return(methodResult);
        }
コード例 #14
0
        public async Task RemoveSubscriptionThrowsTest()
        {
            // Arrange
            string deviceId   = "d1";
            var    cloudProxy = new Mock <ICloudProxy>();

            cloudProxy.Setup(c => c.SetupCallMethodAsync())
            .ThrowsAsync(new InvalidOperationException());

            var connectionManager = new Mock <IConnectionManager>();

            connectionManager.Setup(c => c.AddSubscription(deviceId, DeviceSubscription.Methods));
            connectionManager.Setup(c => c.GetCloudConnection(deviceId)).Returns(Task.FromResult(Option.Some(cloudProxy.Object)));
            IEdgeHub edgeHub = await GetTestEdgeHub(connectionManager.Object);

            // Act
            await Assert.ThrowsAsync <InvalidOperationException>(() => edgeHub.AddSubscription(deviceId, DeviceSubscription.Methods));

            // Assert
            cloudProxy.VerifyAll();
            connectionManager.VerifyAll();
        }
コード例 #15
0
        public async Task RemoveSubscriptionTimesOutTest()
        {
            // Arrange
            string deviceId   = "d1";
            var    cloudProxy = new Mock <ICloudProxy>();

            cloudProxy.Setup(c => c.SetupCallMethodAsync())
            .ThrowsAsync(new TimeoutException());

            var connectionManager = new Mock <IConnectionManager>();

            connectionManager.Setup(c => c.AddSubscription(deviceId, DeviceSubscription.Methods));
            connectionManager.Setup(c => c.GetCloudConnection(deviceId)).Returns(Option.Some(cloudProxy.Object));
            IEdgeHub edgeHub = await GetTestEdgeHub(connectionManager.Object);

            // Act
            await edgeHub.AddSubscription(deviceId, DeviceSubscription.Methods);

            // Assert
            cloudProxy.VerifyAll();
            connectionManager.VerifyAll();
        }
コード例 #16
0
        async Task <EdgeHubScopeResult> HandleDevicesAndModulesInTargetDeviceScopeAsync(string actorDeviceId, string actorModuleId, NestedScopeRequest request)
        {
            Events.ReceivedScopeRequest(actorDeviceId, actorModuleId, request);

            if (!AuthChainHelpers.TryGetTargetDeviceId(request.AuthChain, out string targetDeviceId))
            {
                return(new EdgeHubScopeResultError(HttpStatusCode.BadRequest, Events.InvalidRequestAuthchain(request.AuthChain)));
            }

            // Get the children of the target device and the target device itself;
            IEdgeHub edgeHub = await this.edgeHubGetter;
            IDeviceScopeIdentitiesCache identitiesCache = edgeHub.GetDeviceScopeIdentitiesCache();
            IList <ServiceIdentity>     identities      = await identitiesCache.GetDevicesAndModulesInTargetScopeAsync(targetDeviceId);

            Option <ServiceIdentity> targetDevice = await identitiesCache.GetServiceIdentity(targetDeviceId);

            targetDevice.ForEach(d => identities.Add(d));

            // Construct the result from the identities
            Events.SendingScopeResult(targetDeviceId, identities);
            return(MakeResultFromIdentities(identities));
        }
コード例 #17
0
        internal static async Task <Try <string> > AuthorizeOnBehalfOf(
            string actorDeviceId,
            string authChain,
            string source,
            HttpContext httpContext,
            IEdgeHub edgeHub,
            IHttpRequestAuthenticator authenticator)
        {
            if (!AuthChainHelpers.TryGetTargetDeviceId(authChain, out string targetDeviceId))
            {
                Events.InvalidRequestAuthChain(source, authChain);
                return(Try <string> .Failure(new ValidationException(HttpStatusCode.BadRequest, FormatErrorResponseMessage($"Invalid request auth chain {authChain}."))));
            }

            if (!await AuthenticateAsync(actorDeviceId, Option.Some(Constants.EdgeHubModuleId), Option.Some(authChain), httpContext, authenticator))
            {
                return(Try <string> .Failure(new ValidationException(HttpStatusCode.Unauthorized)));
            }

            IDeviceScopeIdentitiesCache identitiesCache = edgeHub.GetDeviceScopeIdentitiesCache();
            Option <string>             targetAuthChain = await identitiesCache.GetAuthChain(targetDeviceId);

            return(targetAuthChain.Match(
                       ac =>
            {
                if (!AuthChainHelpers.ValidateAuthChain(actorDeviceId, targetDeviceId, ac))
                {
                    Events.AuthorizationFail_InvalidAuthChain(actorDeviceId, targetDeviceId, ac);
                    return Try <string> .Failure(new ValidationException(HttpStatusCode.Unauthorized));
                }

                return ac;
            },
                       () =>
            {
                Events.AuthorizationFail_NoAuthChain(targetDeviceId);
                return Try <string> .Failure(new ValidationException(HttpStatusCode.Unauthorized));
            }));
        }
コード例 #18
0
        public async Task AddSubscriptionTest()
        {
            // Arrange
            string deviceId   = "d1";
            var    cloudProxy = new Mock <ICloudProxy>();

            cloudProxy.Setup(c => c.SetupCallMethodAsync())
            .Returns(Task.CompletedTask);

            var connectionManager = new Mock <IConnectionManager>();

            connectionManager.Setup(c => c.AddSubscription(deviceId, DeviceSubscription.Methods));
            connectionManager.Setup(c => c.GetCloudConnection(deviceId)).Returns(Task.FromResult(Option.Some(cloudProxy.Object)));
            IEdgeHub edgeHub = await GetTestEdgeHub(connectionManager.Object);

            // Act
            await edgeHub.AddSubscription(deviceId, DeviceSubscription.Methods);

            // Assert
            cloudProxy.VerifyAll();
            connectionManager.VerifyAll();
        }
コード例 #19
0
        static Task InitEdgeHub(EdgeHubConnection edgeHubConnection, IConnectionManager connectionManager, IIdentity edgeHubIdentity, IEdgeHub edgeHub)
        {
            IDeviceProxy deviceProxy             = new EdgeHubDeviceProxy(edgeHubConnection);
            Task         addDeviceConnectionTask = connectionManager.AddDeviceConnection(edgeHubIdentity, deviceProxy);
            Task         desiredPropertyUpdatesSubscriptionTask = edgeHub.AddSubscription(edgeHubIdentity.Id, DeviceSubscription.DesiredPropertyUpdates);
            Task         methodsSubscriptionTask           = edgeHub.AddSubscription(edgeHubIdentity.Id, DeviceSubscription.Methods);
            Task         clearDeviceConnectionStatusesTask = edgeHubConnection.ClearDeviceConnectionStatuses();

            return(Task.WhenAll(addDeviceConnectionTask, desiredPropertyUpdatesSubscriptionTask, methodsSubscriptionTask, clearDeviceConnectionStatusesTask));
        }
コード例 #20
0
 public void BindEdgeHub(IEdgeHub edgeHub)
 {
     this.edgeHub = edgeHub;
 }
コード例 #21
0
 public void BindEdgeHub(IEdgeHub edgeHub)
 {
     this.cloudProxyDispatcher.BindEdgeHub(edgeHub);
 }
コード例 #22
0
 public void BindEdgeHub(IEdgeHub edgeHubInstance)
 {
     this.edgeHub = Option.Some(Preconditions.CheckNotNull(edgeHubInstance, nameof(edgeHubInstance)));
 }
コード例 #23
0
ファイル: RoutingTest.cs プロジェクト: rdivossen/iotedge
            public static async Task <TestModule> Create(string deviceId, string moduleId, string outputEndpointId, List <string> inputEndpointIds, IEdgeHub edgeHub, IConnectionManager connectionManager)
            {
                IClientCredentials moduleCredentials = SetupModuleCredentials(moduleId, deviceId);
                Try <ICloudProxy>  cloudProxy        = await connectionManager.CreateCloudConnectionAsync(moduleCredentials);

                Assert.True(cloudProxy.Success);
                var deviceListener   = new DeviceMessageHandler(moduleCredentials.Identity, edgeHub, connectionManager);
                var receivedMessages = new List <IMessage>();
                var deviceProxy      = new Mock <IDeviceProxy>();

                deviceProxy.Setup(d => d.SendMessageAsync(It.IsAny <IMessage>(), It.Is <string>(e => inputEndpointIds.Contains(e))))
                .Callback <IMessage, string>((m, e) =>
                {
                    receivedMessages.Add(m);
                    deviceListener.ProcessMessageFeedbackAsync(m.SystemProperties[SystemProperties.LockToken], FeedbackStatus.Complete).Wait();
                })
                .Returns(Task.CompletedTask);
                deviceProxy.SetupGet(d => d.IsActive).Returns(true);
                deviceListener.BindDeviceProxy(deviceProxy.Object);
                await deviceListener.AddSubscription(DeviceSubscription.ModuleMessages);

                return(new TestModule(moduleCredentials.Identity as IModuleIdentity, outputEndpointId, deviceListener, receivedMessages));
            }
コード例 #24
0
ファイル: RoutingTest.cs プロジェクト: rdivossen/iotedge
 public static Task <TestModule> Create(string deviceId, string moduleId, string outputEndpointId, string inputEndpointId, IEdgeHub edgeHub, IConnectionManager connectionManager) =>
 Create(deviceId, moduleId, outputEndpointId, new List <string> {
     inputEndpointId
 }, edgeHub, connectionManager);
コード例 #25
0
        static async Task <int> MainAsync(IConfigurationRoot configuration)
        {
            string logLevel = configuration.GetValue($"{Logger.RuntimeLogLevelEnvKey}", "info");

            Logger.SetLogLevel(logLevel);

            // Set the LoggerFactory used by the Routing code.
            if (configuration.GetValue("EnableRoutingLogging", false))
            {
                Routing.LoggerFactory = Logger.Factory;
            }

            ILogger logger = Logger.Factory.CreateLogger("EdgeHub");

            EdgeHubCertificates certificates = await EdgeHubCertificates.LoadAsync(configuration, logger);

            bool clientCertAuthEnabled = configuration.GetValue(Constants.ConfigKey.EdgeHubClientCertAuthEnabled, false);

            string       sslProtocolsConfig = configuration.GetValue(Constants.ConfigKey.SslProtocols, string.Empty);
            SslProtocols sslProtocols       = SslProtocolsHelper.Parse(sslProtocolsConfig, DefaultSslProtocols, logger);

            logger.LogInformation($"Enabling SSL protocols: {sslProtocols.Print()}");

            IDependencyManager dependencyManager = new DependencyManager(configuration, certificates.ServerCertificate, certificates.TrustBundle, sslProtocols);
            Hosting            hosting           = Hosting.Initialize(configuration, certificates.ServerCertificate, dependencyManager, clientCertAuthEnabled, sslProtocols);
            IContainer         container         = hosting.Container;

            logger.LogInformation("Initializing Edge Hub");
            LogLogo(logger);
            LogVersionInfo(logger);
            logger.LogInformation($"OptimizeForPerformance={configuration.GetValue("OptimizeForPerformance", true)}");
            logger.LogInformation($"MessageAckTimeoutSecs={configuration.GetValue("MessageAckTimeoutSecs", 30)}");
            logger.LogInformation("Loaded server certificate with expiration date of {0}", certificates.ServerCertificate.NotAfter.ToString("o"));

            var metricsProvider = container.Resolve <IMetricsProvider>();

            Metrics.InitWithAspNet(metricsProvider, logger); // Note this requires App.UseMetricServer() to be called in Startup.cs

            // Init V0 Metrics
            MetricsV0.BuildMetricsCollector(configuration);

            // EdgeHub and CloudConnectionProvider have a circular dependency. So need to Bind the EdgeHub to the CloudConnectionProvider.
            IEdgeHub edgeHub = await container.Resolve <Task <IEdgeHub> >();

            ICloudConnectionProvider cloudConnectionProvider = await container.Resolve <Task <ICloudConnectionProvider> >();

            cloudConnectionProvider.BindEdgeHub(edgeHub);

            // EdgeHub cloud proxy and DeviceConnectivityManager have a circular dependency,
            // so the cloud proxy has to be set on the DeviceConnectivityManager after both have been initialized.
            var deviceConnectivityManager        = container.Resolve <IDeviceConnectivityManager>();
            IConnectionManager connectionManager = await container.Resolve <Task <IConnectionManager> >();

            (deviceConnectivityManager as DeviceConnectivityManager)?.SetConnectionManager(connectionManager);

            // Register EdgeHub credentials
            var edgeHubCredentials             = container.ResolveNamed <IClientCredentials>("EdgeHubCredentials");
            ICredentialsCache credentialsCache = await container.Resolve <Task <ICredentialsCache> >();

            await credentialsCache.Add(edgeHubCredentials);

            // Initializing configuration
            logger.LogInformation("Initializing configuration");
            IConfigSource configSource = await container.Resolve <Task <IConfigSource> >();

            ConfigUpdater configUpdater = await container.Resolve <Task <ConfigUpdater> >();

            await configUpdater.Init(configSource);

            if (!Enum.TryParse(configuration.GetValue("AuthenticationMode", string.Empty), true, out AuthenticationMode authenticationMode) ||
                authenticationMode != AuthenticationMode.Cloud)
            {
                ConnectionReauthenticator connectionReauthenticator = await container.Resolve <Task <ConnectionReauthenticator> >();

                connectionReauthenticator.Init();
            }

            TimeSpan shutdownWaitPeriod = TimeSpan.FromSeconds(configuration.GetValue("ShutdownWaitPeriod", DefaultShutdownWaitPeriod));

            (CancellationTokenSource cts, ManualResetEventSlim completed, Option <object> handler) = ShutdownHandler.Init(shutdownWaitPeriod, logger);

            using (IProtocolHead protocolHead = await GetEdgeHubProtocolHeadAsync(logger, configuration, container, hosting))
                using (var renewal = new CertificateRenewal(certificates, logger))
                {
                    await protocolHead.StartAsync();

                    await Task.WhenAny(cts.Token.WhenCanceled(), renewal.Token.WhenCanceled());

                    logger.LogInformation("Stopping the protocol heads...");
                    await protocolHead.CloseAsync(CancellationToken.None);

                    logger.LogInformation("Protocol heads stopped.");

                    await CloseDbStoreProviderAsync(container);
                }

            completed.Set();
            handler.ForEach(h => GC.KeepAlive(h));
            logger.LogInformation("Shutdown complete.");
            return(0);
        }
コード例 #26
0
        protected override void Load(ContainerBuilder builder)
        {
            // IMessageConverter<IRoutingMessage>
            builder.Register(c => new RoutingMessageConverter())
            .As <Core.IMessageConverter <IRoutingMessage> >()
            .SingleInstance();

            // IRoutingPerfCounter
            builder.Register(
                c =>
            {
                Routing.PerfCounter = NullRoutingPerfCounter.Instance;
                return(Routing.PerfCounter);
            })
            .As <IRoutingPerfCounter>()
            .AutoActivate()
            .SingleInstance();

            // IRoutingUserAnalyticsLogger
            builder.Register(
                c =>
            {
                Routing.UserAnalyticsLogger = NullUserAnalyticsLogger.Instance;
                return(Routing.UserAnalyticsLogger);
            })
            .As <IRoutingUserAnalyticsLogger>()
            .AutoActivate()
            .SingleInstance();

            // IRoutingUserMetricLogger
            builder.Register(
                c =>
            {
                Routing.UserMetricLogger = NullRoutingUserMetricLogger.Instance;
                return(Routing.UserMetricLogger);
            })
            .As <IRoutingUserMetricLogger>()
            .AutoActivate()
            .SingleInstance();

            // IMessageConverter<Message>
            builder.Register(c => new DeviceClientMessageConverter())
            .As <Core.IMessageConverter <Message> >()
            .SingleInstance();

            // IMessageConverter<Twin>
            builder.Register(c => new TwinMessageConverter())
            .As <Core.IMessageConverter <Twin> >()
            .SingleInstance();

            // IMessageConverter<TwinCollection>
            builder.Register(c => new TwinCollectionMessageConverter())
            .As <Core.IMessageConverter <TwinCollection> >()
            .SingleInstance();

            // IMessageConverterProvider
            builder.Register(
                c => new MessageConverterProvider(new Dictionary <Type, IMessageConverter>()
            {
                { typeof(Message), c.Resolve <Core.IMessageConverter <Message> >() },
                { typeof(Twin), c.Resolve <Core.IMessageConverter <Twin> >() },
                { typeof(TwinCollection), c.Resolve <Core.IMessageConverter <TwinCollection> >() }
            }))
            .As <Core.IMessageConverterProvider>()
            .SingleInstance();

            // IDeviceConnectivityManager
            builder.Register(
                c =>
            {
                IDeviceConnectivityManager deviceConnectivityManager = new DeviceConnectivityManager(this.connectivityCheckFrequency, TimeSpan.FromMinutes(2));
                return(deviceConnectivityManager);
            })
            .As <IDeviceConnectivityManager>()
            .SingleInstance();

            // IDeviceClientProvider
            builder.Register(c =>
            {
                IClientProvider underlyingClientProvider        = new ClientProvider();
                IClientProvider connectivityAwareClientProvider = new ConnectivityAwareClientProvider(underlyingClientProvider, c.Resolve <IDeviceConnectivityManager>());
                return(connectivityAwareClientProvider);
            })
            .As <IClientProvider>()
            .SingleInstance();

            // ICloudConnectionProvider
            builder.Register(c => new CloudConnectionProvider(c.Resolve <Core.IMessageConverterProvider>(), this.connectionPoolSize, c.Resolve <IClientProvider>(), this.upstreamProtocol))
            .As <ICloudConnectionProvider>()
            .SingleInstance();

            if (this.isStoreAndForwardEnabled || this.cacheTokens)
            {
                // Detect system environment
                builder.Register(c => new SystemEnvironment())
                .As <ISystemEnvironment>()
                .SingleInstance();

                // DataBase options
                builder.Register(c => new Storage.RocksDb.RocksDbOptionsProvider(c.Resolve <ISystemEnvironment>(), this.optimizeForPerformance))
                .As <Storage.RocksDb.IRocksDbOptionsProvider>()
                .SingleInstance();

                // IDbStore
                builder.Register(
                    c =>
                {
                    var loggerFactory = c.Resolve <ILoggerFactory>();
                    ILogger logger    = loggerFactory.CreateLogger(typeof(RoutingModule));

                    if (this.usePersistentStorage)
                    {
                        // Create partitions for messages and twins
                        var partitionsList = new List <string> {
                            Core.Constants.MessageStorePartitionKey, Core.Constants.TwinStorePartitionKey, Core.Constants.CheckpointStorePartitionKey
                        };
                        try
                        {
                            IDbStoreProvider dbStoreprovider = Storage.RocksDb.DbStoreProvider.Create(c.Resolve <Storage.RocksDb.IRocksDbOptionsProvider>(),
                                                                                                      this.storagePath, partitionsList);
                            logger.LogInformation($"Created persistent store at {this.storagePath}");
                            return(dbStoreprovider);
                        }
                        catch (Exception ex) when(!ExceptionEx.IsFatal(ex))
                        {
                            logger.LogError(ex, "Error creating RocksDB store. Falling back to in-memory store.");
                            return(new InMemoryDbStoreProvider());
                        }
                    }
                    else
                    {
                        logger.LogInformation($"Using in-memory store");
                        return(new InMemoryDbStoreProvider());
                    }
                })
                .As <IDbStoreProvider>()
                .SingleInstance();
            }

            // Task<ICredentialsStore>
            builder.Register(async c =>
            {
                if (this.cacheTokens)
                {
                    var dbStoreProvider = c.Resolve <IDbStoreProvider>();
                    IEncryptionProvider encryptionProvider = await this.workloadUri.Map(
                        async uri => await EncryptionProvider.CreateAsync(
                            this.storagePath,
                            new Uri(uri),
                            Service.Constants.WorkloadApiVersion,
                            this.edgeModuleId,
                            this.edgeModuleGenerationId.Expect(() => new InvalidOperationException("Missing generation ID")),
                            Service.Constants.InitializationVectorFileName) as IEncryptionProvider)
                                                             .GetOrElse(() => Task.FromResult <IEncryptionProvider>(NullEncryptionProvider.Instance));
                    IStoreProvider storeProvider = new StoreProvider(dbStoreProvider);
                    IEntityStore <string, string> tokenCredentialsEntityStore = storeProvider.GetEntityStore <string, string>("tokenCredentials");
                    return(new TokenCredentialsStore(tokenCredentialsEntityStore, encryptionProvider));
                }
                else
                {
                    return(new NullCredentialsStore() as ICredentialsStore);
                }
            })
            .As <Task <ICredentialsStore> >()
            .SingleInstance();

            // IConnectionManager
            builder.Register(c => new ConnectionManager(c.Resolve <ICloudConnectionProvider>(), this.maxConnectedClients))
            .As <IConnectionManager>()
            .SingleInstance();

            // IEndpointFactory
            builder.Register(c => new EndpointFactory(c.Resolve <IConnectionManager>(), c.Resolve <Core.IMessageConverter <IRoutingMessage> >(), this.edgeDeviceId))
            .As <IEndpointFactory>()
            .SingleInstance();

            // RouteFactory
            builder.Register(c => new EdgeRouteFactory(c.Resolve <IEndpointFactory>()))
            .As <RouteFactory>()
            .SingleInstance();

            // RouterConfig
            builder.Register(c => new RouterConfig(Enumerable.Empty <Route>()))
            .As <RouterConfig>()
            .SingleInstance();

            if (!this.isStoreAndForwardEnabled)
            {
                // EndpointExecutorConfig
                builder.Register(
                    c =>
                {
                    RetryStrategy defaultRetryStrategy = new FixedInterval(0, TimeSpan.FromSeconds(1));
                    TimeSpan defaultRevivePeriod       = TimeSpan.FromHours(1);
                    TimeSpan defaultTimeout            = TimeSpan.FromSeconds(60);
                    return(new EndpointExecutorConfig(defaultTimeout, defaultRetryStrategy, defaultRevivePeriod, true));
                })
                .As <EndpointExecutorConfig>()
                .SingleInstance();

                // IEndpointExecutorFactory
                builder.Register(c => new SyncEndpointExecutorFactory(c.Resolve <EndpointExecutorConfig>()))
                .As <IEndpointExecutorFactory>()
                .SingleInstance();

                // Task<Router>
                builder.Register(
                    async c =>
                {
                    var endpointExecutorFactory = c.Resolve <IEndpointExecutorFactory>();
                    var routerConfig            = c.Resolve <RouterConfig>();
                    Router router = await Router.CreateAsync(Guid.NewGuid().ToString(), this.iotHubName, routerConfig, endpointExecutorFactory);
                    return(router);
                })
                .As <Task <Router> >()
                .SingleInstance();

                // ITwinManager
                builder.Register(c => TwinManager.CreateTwinManager(c.Resolve <IConnectionManager>(), c.Resolve <IMessageConverterProvider>(), Option.None <IStoreProvider>()))
                .As <ITwinManager>()
                .SingleInstance();
            }
            else
            {
                // EndpointExecutorConfig
                builder.Register(
                    c =>
                {
                    // Endpoint executor config values -
                    // ExponentialBackoff - minBackoff = 1s, maxBackoff = 60s, delta (used to add randomness to backoff) - 1s (default)
                    // Num of retries = int.MaxValue(we want to keep retrying till the message is sent)
                    // Revive period - period for which the endpoint should be considered dead if it doesn't respond - 1 min (we want to try continuously till the message expires)
                    // Timeout - time for which we want for the ack from the endpoint = 30s
                    // TODO - Should the number of retries be tied to the Store and Forward ttl? Not
                    // doing that right now as that value can be changed at runtime, but these settings
                    // cannot. Need to make the number of retries dynamically configurable for that.

                    TimeSpan minWait            = TimeSpan.FromSeconds(1);
                    TimeSpan maxWait            = TimeSpan.FromSeconds(60);
                    TimeSpan delta              = TimeSpan.FromSeconds(1);
                    int retries                 = int.MaxValue;
                    RetryStrategy retryStrategy = new ExponentialBackoff(retries, minWait, maxWait, delta);
                    TimeSpan timeout            = TimeSpan.FromSeconds(30);
                    TimeSpan revivePeriod       = TimeSpan.FromSeconds(30);
                    return(new EndpointExecutorConfig(timeout, retryStrategy, revivePeriod));
                })
                .As <EndpointExecutorConfig>()
                .SingleInstance();

                // ICheckpointStore
                builder.Register(c => CheckpointStore.Create(c.Resolve <IDbStoreProvider>()))
                .As <ICheckpointStore>()
                .SingleInstance();

                // IMessageStore
                builder.Register(
                    c =>
                {
                    var checkpointStore          = c.Resolve <ICheckpointStore>();
                    var dbStoreProvider          = c.Resolve <IDbStoreProvider>();
                    IStoreProvider storeProvider = new StoreProvider(dbStoreProvider);
                    IMessageStore messageStore   = new MessageStore(storeProvider, checkpointStore, TimeSpan.MaxValue);
                    return(messageStore);
                })
                .As <IMessageStore>()
                .SingleInstance();

                // IEndpointExecutorFactory
                builder.Register(
                    c =>
                {
                    var endpointExecutorConfig = c.Resolve <EndpointExecutorConfig>();
                    var messageStore           = c.Resolve <IMessageStore>();
                    IEndpointExecutorFactory endpointExecutorFactory = new StoringAsyncEndpointExecutorFactory(endpointExecutorConfig, new AsyncEndpointExecutorOptions(10, TimeSpan.FromSeconds(10)), messageStore);
                    return(endpointExecutorFactory);
                })
                .As <IEndpointExecutorFactory>()
                .SingleInstance();

                // Task<Router>
                builder.Register(
                    async c =>
                {
                    var checkpointStore         = c.Resolve <ICheckpointStore>();
                    var routerConfig            = c.Resolve <RouterConfig>();
                    var endpointExecutorFactory = c.Resolve <IEndpointExecutorFactory>();
                    return(await Router.CreateAsync(Guid.NewGuid().ToString(), this.iotHubName, routerConfig, endpointExecutorFactory, checkpointStore));
                })
                .As <Task <Router> >()
                .SingleInstance();

                // ITwinManager
                builder.Register(c => TwinManager.CreateTwinManager(c.Resolve <IConnectionManager>(), c.Resolve <IMessageConverterProvider>(), Option.Some <IStoreProvider>(new StoreProvider(c.Resolve <IDbStoreProvider>()))))
                .As <ITwinManager>()
                .SingleInstance();
            }

            // IClientCredentials "EdgeHubCredentials"
            builder.Register(
                c =>
            {
                var identityFactory = c.Resolve <IClientCredentialsFactory>();
                IClientCredentials edgeHubCredentials = this.connectionString.Map(cs => identityFactory.GetWithConnectionString(cs)).GetOrElse(
                    () => identityFactory.GetWithIotEdged(this.edgeDeviceId, this.edgeModuleId));
                return(edgeHubCredentials);
            })
            .Named <IClientCredentials>("EdgeHubCredentials")
            .SingleInstance();

            // Task<ICloudProxy> "EdgeHubCloudProxy"
            builder.Register(
                async c =>
            {
                var edgeHubCredentials          = c.ResolveNamed <IClientCredentials>("EdgeHubCredentials");
                var connectionManager           = c.Resolve <IConnectionManager>();
                Try <ICloudProxy> cloudProxyTry = await connectionManager.CreateCloudConnectionAsync(edgeHubCredentials);
                if (!cloudProxyTry.Success)
                {
                    throw new EdgeHubConnectionException("Edge hub is unable to connect to IoT Hub", cloudProxyTry.Exception);
                }

                ICloudProxy cloudProxy = cloudProxyTry.Value;
                return(cloudProxy);
            })
            .Named <Task <ICloudProxy> >("EdgeHubCloudProxy")
            .SingleInstance();

            // Task<IEdgeHub>
            builder.Register(
                async c =>
            {
                Router router = await c.Resolve <Task <Router> >();
                IEdgeHub hub  = new RoutingEdgeHub(router, c.Resolve <Core.IMessageConverter <IRoutingMessage> >(), c.Resolve <IConnectionManager>(), c.Resolve <ITwinManager>(), this.edgeDeviceId);
                return(hub);
            })
            .As <Task <IEdgeHub> >()
            .SingleInstance();

            // Task<ConfigUpdater>
            builder.Register(
                async c =>
            {
                IMessageStore messageStore = this.isStoreAndForwardEnabled ? c.Resolve <IMessageStore>() : null;
                Router router     = await c.Resolve <Task <Router> >();
                var configUpdater = new ConfigUpdater(router, messageStore);
                return(configUpdater);
            })
            .As <Task <ConfigUpdater> >()
            .SingleInstance();

            // Task<IConfigSource>
            builder.Register(
                async c =>
            {
                var routeFactory = c.Resolve <RouteFactory>();

                if (this.useTwinConfig)
                {
                    var connectionManager              = c.Resolve <IConnectionManager>();
                    var edgeHubCredentials             = c.ResolveNamed <IClientCredentials>("EdgeHubCredentials");
                    var twinCollectionMessageConverter = c.Resolve <Core.IMessageConverter <TwinCollection> >();
                    var twinMessageConverter           = c.Resolve <Core.IMessageConverter <Twin> >();
                    var twinManager                 = c.Resolve <ITwinManager>();
                    ICloudProxy cloudProxy          = await c.ResolveNamed <Task <ICloudProxy> >("EdgeHubCloudProxy");
                    IEdgeHub edgeHub                = await c.Resolve <Task <IEdgeHub> >();
                    IConfigSource edgeHubConnection = await EdgeHubConnection.Create(
                        edgeHubCredentials.Identity as IModuleIdentity,
                        edgeHub,
                        twinManager,
                        connectionManager,
                        cloudProxy,
                        routeFactory,
                        twinCollectionMessageConverter,
                        twinMessageConverter,
                        this.versionInfo
                        );
                    return(edgeHubConnection);
                }
                else
                {
                    return(new LocalConfigSource(routeFactory, this.routes, this.storeAndForwardConfiguration));
                }
            })
            .As <Task <IConfigSource> >()
            .SingleInstance();

            // Task<IConnectionProvider>
            builder.Register(
                async c =>
            {
                IEdgeHub edgeHub = await c.Resolve <Task <IEdgeHub> >();
                IConnectionProvider connectionProvider = new ConnectionProvider(c.Resolve <IConnectionManager>(), edgeHub);
                return(connectionProvider);
            })
            .As <Task <IConnectionProvider> >()
            .SingleInstance();

            base.Load(builder);
        }
コード例 #27
0
ファイル: Program.cs プロジェクト: danbruder/iotedge
        public static async Task <int> MainAsync(IConfigurationRoot configuration)
        {
            string logLevel = configuration.GetValue($"{Logger.RuntimeLogLevelEnvKey}", "info");

            Logger.SetLogLevel(logLevel);

            // Set the LoggerFactory used by the Routing code.
            if (configuration.GetValue("EnableRoutingLogging", false))
            {
                Routing.Core.Routing.LoggerFactory = Logger.Factory;
            }

            X509Certificate2 cert;
            IEnumerable <X509Certificate2> chain;
            string edgeHubConnectionString = configuration.GetValue <string>(Constants.IotHubConnectionStringVariableName);

            // When connection string is not set it is edged mode
            if (string.IsNullOrEmpty(edgeHubConnectionString))
            {
                var      workloadUri     = new Uri(configuration.GetValue <string>(Constants.WorkloadUriVariableName));
                string   edgeHubHostname = configuration.GetValue <string>(Constants.EdgeDeviceHostnameVariableName);
                string   moduleId        = configuration.GetValue <string>(Constants.ModuleIdVariableName);
                string   generationId    = configuration.GetValue <string>(Constants.ModuleGenerationIdVariableName);
                DateTime expiration      = DateTime.UtcNow.AddDays(Constants.CertificateValidityDays);
                (cert, chain) = await CertificateHelper.GetServerCertificatesFromEdgelet(workloadUri, Constants.WorkloadApiVersion, moduleId, generationId, edgeHubHostname, expiration);
            }
            else
            {
                string edgeHubCertPath = configuration.GetValue <string>(Constants.EdgeHubServerCertificateFileKey);
                cert = new X509Certificate2(edgeHubCertPath);
                string edgeHubCaChainCertPath = configuration.GetValue <string>(Constants.EdgeHubServerCAChainCertificateFileKey);
                chain = CertificateHelper.GetServerCACertificatesFromFile(edgeHubCaChainCertPath);
            }

            // TODO: set certificate for Startup without the cache
            ServerCertificateCache.X509Certificate = cert;

            int     port    = configuration.GetValue("httpSettings:port", 443);
            Hosting hosting = Hosting.Initialize(port);

            IContainer container = hosting.Container;

            ILogger logger = container.Resolve <ILoggerFactory>().CreateLogger("EdgeHub");

            logger.LogInformation("Starting Edge Hub");
            VersionInfo versionInfo = VersionInfo.Get(Constants.VersionInfoFileName);

            if (versionInfo != VersionInfo.Empty)
            {
                logger.LogInformation($"Version - {versionInfo.ToString(true)}");
            }
            LogLogo(logger);

            if (chain != null)
            {
                logger.LogInformation("Installing intermediate certificates.");

                CertificateHelper.InstallCerts(
                    RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? StoreName.CertificateAuthority : StoreName.Root,
                    StoreLocation.CurrentUser,
                    chain);
            }
            else
            {
                logger.LogWarning("Unable to find intermediate certificates.");
            }

            // EdgeHub and CloudConnectionProvider have a circular dependency. So need to Bind the EdgeHub to the CloudConnectionProvider.
            IEdgeHub edgeHub = await container.Resolve <Task <IEdgeHub> >();

            var cloudConnectionProvider = container.Resolve <ICloudConnectionProvider>();

            cloudConnectionProvider.BindEdgeHub(edgeHub);

            // EdgeHub cloud proxy and DeviceConnectivityManager have a circular dependency,
            // so the cloud proxy has to be set on the DeviceConnectivityManager after both have been initialized.
            var         deviceConnectivityManager = container.Resolve <IDeviceConnectivityManager>();
            ICloudProxy cloudProxy = await container.ResolveNamed <Task <ICloudProxy> >("EdgeHubCloudProxy");

            (deviceConnectivityManager as DeviceConnectivityManager)?.SetTestCloudProxy(cloudProxy);

            logger.LogInformation("Initializing configuration");
            IConfigSource configSource = await container.Resolve <Task <IConfigSource> >();

            ConfigUpdater configUpdater = await container.Resolve <Task <ConfigUpdater> >();

            await configUpdater.Init(configSource);

            (CancellationTokenSource cts, ManualResetEventSlim completed, Option <object> handler)
                = ShutdownHandler.Init(ShutdownWaitPeriod, logger);

            var protocolHeads = new List <IProtocolHead>();

            if (configuration.GetValue("mqttSettings:enabled", true))
            {
                protocolHeads.Add(await container.Resolve <Task <MqttProtocolHead> >());
            }

            if (configuration.GetValue("amqpSettings:enabled", true))
            {
                protocolHeads.Add(await container.Resolve <Task <AmqpProtocolHead> >());
            }

            if (configuration.GetValue("httpSettings:enabled", true))
            {
                protocolHeads.Add(new HttpProtocolHead(hosting.WebHost));
            }

            using (IProtocolHead protocolHead = new EdgeHubProtocolHead(protocolHeads, logger))
            {
                await protocolHead.StartAsync();

                await cts.Token.WhenCanceled();

                await Task.WhenAny(protocolHead.CloseAsync(CancellationToken.None), Task.Delay(TimeSpan.FromSeconds(10), CancellationToken.None));
            }

            completed.Set();
            handler.ForEach(h => GC.KeepAlive(h));
            return(0);
        }
コード例 #28
0
ファイル: Program.cs プロジェクト: vjrantal/iotedge
        static async Task <int> MainAsync(IConfigurationRoot configuration)
        {
            string logLevel = configuration.GetValue($"{Logger.RuntimeLogLevelEnvKey}", "info");

            Logger.SetLogLevel(logLevel);

            // Set the LoggerFactory used by the Routing code.
            if (configuration.GetValue("EnableRoutingLogging", false))
            {
                Routing.LoggerFactory = Logger.Factory;
            }

            EdgeHubCertificates certificates = await EdgeHubCertificates.LoadAsync(configuration);

            bool       clientCertAuthEnabled = configuration.GetValue(Constants.ConfigKey.EdgeHubClientCertAuthEnabled, false);
            Hosting    hosting   = Hosting.Initialize(configuration, certificates.ServerCertificate, new DependencyManager(configuration, certificates.ServerCertificate, certificates.TrustBundle), clientCertAuthEnabled);
            IContainer container = hosting.Container;

            ILogger logger = container.Resolve <ILoggerFactory>().CreateLogger("EdgeHub");

            logger.LogInformation("Initializing Edge Hub");
            LogLogo(logger);
            LogVersionInfo(logger);

            logger.LogInformation("Loaded server certificate with expiration date of {0}", certificates.ServerCertificate.NotAfter.ToString("o"));

            // EdgeHub and CloudConnectionProvider have a circular dependency. So need to Bind the EdgeHub to the CloudConnectionProvider.
            IEdgeHub edgeHub = await container.Resolve <Task <IEdgeHub> >();

            ICloudConnectionProvider cloudConnectionProvider = await container.Resolve <Task <ICloudConnectionProvider> >();

            cloudConnectionProvider.BindEdgeHub(edgeHub);

            // EdgeHub cloud proxy and DeviceConnectivityManager have a circular dependency,
            // so the cloud proxy has to be set on the DeviceConnectivityManager after both have been initialized.
            var deviceConnectivityManager        = container.Resolve <IDeviceConnectivityManager>();
            IConnectionManager connectionManager = await container.Resolve <Task <IConnectionManager> >();

            (deviceConnectivityManager as DeviceConnectivityManager)?.SetConnectionManager(connectionManager);

            // Register EdgeHub credentials
            var edgeHubCredentials             = container.ResolveNamed <IClientCredentials>("EdgeHubCredentials");
            ICredentialsCache credentialsCache = await container.Resolve <Task <ICredentialsCache> >();

            await credentialsCache.Add(edgeHubCredentials);

            // Initializing configuration
            logger.LogInformation("Initializing configuration");
            IConfigSource configSource = await container.Resolve <Task <IConfigSource> >();

            ConfigUpdater configUpdater = await container.Resolve <Task <ConfigUpdater> >();

            await configUpdater.Init(configSource);

            if (!Enum.TryParse(configuration.GetValue("AuthenticationMode", string.Empty), true, out AuthenticationMode authenticationMode) ||
                authenticationMode != AuthenticationMode.Cloud)
            {
                ConnectionReauthenticator connectionReauthenticator = await container.Resolve <Task <ConnectionReauthenticator> >();

                connectionReauthenticator.Init();
            }

            (CancellationTokenSource cts, ManualResetEventSlim completed, Option <object> handler) = ShutdownHandler.Init(ShutdownWaitPeriod, logger);

            Metrics.BuildMetricsCollector(configuration);

            using (IProtocolHead protocolHead = await GetEdgeHubProtocolHeadAsync(logger, configuration, container, hosting))
                using (var renewal = new CertificateRenewal(certificates, logger))
                {
                    await protocolHead.StartAsync();

                    await Task.WhenAny(cts.Token.WhenCanceled(), renewal.Token.WhenCanceled());

                    logger.LogInformation("Stopping the protocol heads...");
                    await Task.WhenAny(protocolHead.CloseAsync(CancellationToken.None), Task.Delay(TimeSpan.FromSeconds(10), CancellationToken.None));

                    logger.LogInformation("Protocol heads stopped.");
                }

            completed.Set();
            handler.ForEach(h => GC.KeepAlive(h));
            logger.LogInformation("Shutdown complete.");
            return(0);
        }
コード例 #29
0
ファイル: MqttModule.cs プロジェクト: zacseas/iotedge
        protected override void Load(ContainerBuilder builder)
        {
            // IByteBufferAllocator
            builder.Register(
                c =>
            {
                // TODO - We should probably also use some heuristics to make this determination, like how much memory does the system have.
                return(this.optimizeForPerformance ? PooledByteBufferAllocator.Default : UnpooledByteBufferAllocator.Default as IByteBufferAllocator);
            })
            .As <IByteBufferAllocator>()
            .SingleInstance();

            builder.Register(c => new ByteBufferConverter(c.Resolve <IByteBufferAllocator>()))
            .As <IByteBufferConverter>()
            .SingleInstance();

            // MessageAddressConverter
            builder.Register(c => new MessageAddressConverter(this.conversionConfiguration))
            .As <MessageAddressConverter>()
            .SingleInstance();

            // IMessageConverter<IProtocolGatewayMessage>
            builder.Register(c => new ProtocolGatewayMessageConverter(c.Resolve <MessageAddressConverter>(), c.Resolve <IByteBufferConverter>()))
            .As <IMessageConverter <IProtocolGatewayMessage> >()
            .SingleInstance();

            // ISettingsProvider
            builder.Register(c => new MqttSettingsProvider(this.mqttSettingsConfiguration))
            .As <ISettingsProvider>()
            .SingleInstance();

            // Task<IMqttConnectionProvider>
            builder.Register(
                async c =>
            {
                var pgMessageConverter  = c.Resolve <IMessageConverter <IProtocolGatewayMessage> >();
                var byteBufferConverter = c.Resolve <IByteBufferConverter>();
                IConnectionProvider connectionProvider = await c.Resolve <Task <IConnectionProvider> >();
                IMqttConnectionProvider mqtt           = new MqttConnectionProvider(connectionProvider, pgMessageConverter, byteBufferConverter);
                return(mqtt);
            })
            .As <Task <IMqttConnectionProvider> >()
            .SingleInstance();

            // Task<ISessionStatePersistenceProvider>
            builder.Register(
                async c =>
            {
                if (this.isStoreAndForwardEnabled)
                {
                    IDbStoreProvider dbStoreProvider = await c.Resolve <Task <IDbStoreProvider> >();
                    IEntityStore <string, SessionState> entityStore = new StoreProvider(dbStoreProvider).GetEntityStore <string, SessionState>(Constants.SessionStorePartitionKey);
                    IEdgeHub edgeHub = await c.Resolve <Task <IEdgeHub> >();
                    return(new SessionStateStoragePersistenceProvider(edgeHub, entityStore) as ISessionStatePersistenceProvider);
                }
                else
                {
                    IEdgeHub edgeHub = await c.Resolve <Task <IEdgeHub> >();
                    return(new SessionStatePersistenceProvider(edgeHub) as ISessionStatePersistenceProvider);
                }
            })
            .As <Task <ISessionStatePersistenceProvider> >()
            .SingleInstance();

            // MqttProtocolHead
            builder.Register(
                async c =>
            {
                var productInfoStore                                = await c.Resolve <Task <IProductInfoStore> >();
                var settingsProvider                                = c.Resolve <ISettingsProvider>();
                var websocketListenerRegistry                       = c.Resolve <IWebSocketListenerRegistry>();
                var byteBufferAllocator                             = c.Resolve <IByteBufferAllocator>();
                var mqttConnectionProviderTask                      = c.Resolve <Task <IMqttConnectionProvider> >();
                var sessionStatePersistenceProviderTask             = c.Resolve <Task <ISessionStatePersistenceProvider> >();
                var authenticatorProviderTask                       = c.Resolve <Task <IAuthenticator> >();
                IClientCredentialsFactory clientCredentialsProvider = c.Resolve <IClientCredentialsFactory>();
                IMqttConnectionProvider mqttConnectionProvider      = await mqttConnectionProviderTask;
                ISessionStatePersistenceProvider sessionStatePersistenceProvider = await sessionStatePersistenceProviderTask;
                IAuthenticator authenticator = await authenticatorProviderTask;
                return(new MqttProtocolHead(
                           settingsProvider,
                           this.tlsCertificate,
                           mqttConnectionProvider,
                           authenticator,
                           clientCredentialsProvider,
                           sessionStatePersistenceProvider,
                           websocketListenerRegistry,
                           byteBufferAllocator,
                           productInfoStore,
                           this.clientCertAuthAllowed,
                           this.sslProtocols));
            })
            .As <Task <MqttProtocolHead> >()
            .SingleInstance();

            base.Load(builder);
        }
コード例 #30
0
        protected override void Load(ContainerBuilder builder)
        {
            // IMessageConverter<IRoutingMessage>
            builder.Register(c => new RoutingMessageConverter())
            .As <Core.IMessageConverter <IRoutingMessage> >()
            .SingleInstance();

            // IRoutingPerfCounter
            builder.Register(
                c =>
            {
                Routing.PerfCounter = NullRoutingPerfCounter.Instance;
                return(Routing.PerfCounter);
            })
            .As <IRoutingPerfCounter>()
            .AutoActivate()
            .SingleInstance();

            // IRoutingUserAnalyticsLogger
            builder.Register(
                c =>
            {
                Routing.UserAnalyticsLogger = NullUserAnalyticsLogger.Instance;
                return(Routing.UserAnalyticsLogger);
            })
            .As <IRoutingUserAnalyticsLogger>()
            .AutoActivate()
            .SingleInstance();

            // IRoutingUserMetricLogger
            builder.Register(
                c =>
            {
                Routing.UserMetricLogger = NullRoutingUserMetricLogger.Instance;
                return(Routing.UserMetricLogger);
            })
            .As <IRoutingUserMetricLogger>()
            .AutoActivate()
            .SingleInstance();

            // IMessageConverter<Message>
            builder.Register(c => new DeviceClientMessageConverter())
            .As <Core.IMessageConverter <Message> >()
            .SingleInstance();

            // IMessageConverter<Twin>
            builder.Register(c => new TwinMessageConverter())
            .As <Core.IMessageConverter <Twin> >()
            .SingleInstance();

            // IMessageConverter<TwinCollection>
            builder.Register(c => new TwinCollectionMessageConverter())
            .As <Core.IMessageConverter <TwinCollection> >()
            .SingleInstance();

            // IMessageConverterProvider
            builder.Register(
                c => new MessageConverterProvider(
                    new Dictionary <Type, IMessageConverter>()
            {
                { typeof(Message), c.Resolve <Core.IMessageConverter <Message> >() },
                { typeof(Twin), c.Resolve <Core.IMessageConverter <Twin> >() },
                { typeof(TwinCollection), c.Resolve <Core.IMessageConverter <TwinCollection> >() }
            }))
            .As <IMessageConverterProvider>()
            .SingleInstance();

            // IDeviceConnectivityManager
            builder.Register(
                c =>
            {
                var edgeHubCredentials = c.ResolveNamed <IClientCredentials>("EdgeHubCredentials");
                IDeviceConnectivityManager deviceConnectivityManager = this.experimentalFeatures.DisableConnectivityCheck
                            ? new NullDeviceConnectivityManager()
                            : new DeviceConnectivityManager(this.connectivityCheckFrequency, TimeSpan.FromMinutes(2), edgeHubCredentials.Identity) as IDeviceConnectivityManager;
                return(deviceConnectivityManager);
            })
            .As <IDeviceConnectivityManager>()
            .SingleInstance();

            // IDeviceClientProvider
            builder.Register(
                c =>
            {
                IClientProvider underlyingClientProvider        = new ClientProvider();
                IClientProvider connectivityAwareClientProvider = new ConnectivityAwareClientProvider(underlyingClientProvider, c.Resolve <IDeviceConnectivityManager>());
                return(connectivityAwareClientProvider);
            })
            .As <IClientProvider>()
            .SingleInstance();

            // Task<ICloudConnectionProvider>
            builder.Register(
                async c =>
            {
                var productInfoStore               = await c.Resolve <Task <IProductInfoStore> >();
                var messageConverterProvider       = c.Resolve <IMessageConverterProvider>();
                var clientProvider                 = c.Resolve <IClientProvider>();
                var tokenProvider                  = c.ResolveNamed <ITokenProvider>("EdgeHubClientAuthTokenProvider");
                var credentialsCacheTask           = c.Resolve <Task <ICredentialsCache> >();
                var edgeHubCredentials             = c.ResolveNamed <IClientCredentials>("EdgeHubCredentials");
                var deviceScopeIdentitiesCacheTask = c.Resolve <Task <IDeviceScopeIdentitiesCache> >();
                var proxy = c.Resolve <Option <IWebProxy> >();
                IDeviceScopeIdentitiesCache deviceScopeIdentitiesCache = await deviceScopeIdentitiesCacheTask;
                ICredentialsCache credentialsCache = await credentialsCacheTask;
                ICloudConnectionProvider cloudConnectionProvider = new CloudConnectionProvider(
                    messageConverterProvider,
                    this.connectionPoolSize,
                    clientProvider,
                    this.upstreamProtocol,
                    tokenProvider,
                    deviceScopeIdentitiesCache,
                    credentialsCache,
                    edgeHubCredentials.Identity,
                    this.cloudConnectionIdleTimeout,
                    this.closeCloudConnectionOnIdleTimeout,
                    this.operationTimeout,
                    this.useServerHeartbeat,
                    proxy,
                    productInfoStore);
                return(cloudConnectionProvider);
            })
            .As <Task <ICloudConnectionProvider> >()
            .SingleInstance();

            // IIdentityProvider
            builder.Register(_ => new IdentityProvider(this.iotHubName))
            .As <IIdentityProvider>()
            .SingleInstance();

            // Task<IConnectionManager>
            builder.Register(
                async c =>
            {
                var cloudConnectionProviderTask = c.Resolve <Task <ICloudConnectionProvider> >();
                var credentialsCacheTask        = c.Resolve <Task <ICredentialsCache> >();
                var identityProvider            = c.Resolve <IIdentityProvider>();
                var deviceConnectivityManager   = c.Resolve <IDeviceConnectivityManager>();
                ICloudConnectionProvider cloudConnectionProvider = await cloudConnectionProviderTask;
                ICredentialsCache credentialsCache   = await credentialsCacheTask;
                IConnectionManager connectionManager = new ConnectionManager(
                    cloudConnectionProvider,
                    credentialsCache,
                    identityProvider,
                    deviceConnectivityManager,
                    this.maxConnectedClients,
                    this.closeCloudConnectionOnDeviceDisconnect);
                return(connectionManager);
            })
            .As <Task <IConnectionManager> >()
            .SingleInstance();

            // Task<IEndpointFactory>
            builder.Register(
                async c =>
            {
                var messageConverter = c.Resolve <Core.IMessageConverter <IRoutingMessage> >();
                IConnectionManager connectionManager = await c.Resolve <Task <IConnectionManager> >();
                return(new EndpointFactory(connectionManager, messageConverter, this.edgeDeviceId, this.maxUpstreamBatchSize, this.upstreamFanOutFactor) as IEndpointFactory);
            })
            .As <Task <IEndpointFactory> >()
            .SingleInstance();

            // Task<RouteFactory>
            builder.Register(async c => new EdgeRouteFactory(await c.Resolve <Task <IEndpointFactory> >()) as RouteFactory)
            .As <Task <RouteFactory> >()
            .SingleInstance();

            // RouterConfig
            builder.Register(c => new RouterConfig(Enumerable.Empty <Route>()))
            .As <RouterConfig>()
            .SingleInstance();

            if (!this.isStoreAndForwardEnabled)
            {
                // EndpointExecutorConfig
                builder.Register(
                    c =>
                {
                    RetryStrategy defaultRetryStrategy = new FixedInterval(0, TimeSpan.FromSeconds(1));
                    TimeSpan defaultRevivePeriod       = TimeSpan.FromHours(1);
                    TimeSpan defaultTimeout            = TimeSpan.FromSeconds(60);
                    return(new EndpointExecutorConfig(defaultTimeout, defaultRetryStrategy, defaultRevivePeriod, true));
                })
                .As <EndpointExecutorConfig>()
                .SingleInstance();

                // IEndpointExecutorFactory
                builder.Register(c => new SyncEndpointExecutorFactory(c.Resolve <EndpointExecutorConfig>()))
                .As <IEndpointExecutorFactory>()
                .SingleInstance();

                // Task<Router>
                builder.Register(
                    async c =>
                {
                    var endpointExecutorFactory = c.Resolve <IEndpointExecutorFactory>();
                    var routerConfig            = c.Resolve <RouterConfig>();
                    Router router = await Router.CreateAsync(Guid.NewGuid().ToString(), this.iotHubName, routerConfig, endpointExecutorFactory);
                    return(router);
                })
                .As <Task <Router> >()
                .SingleInstance();

                // Task<ITwinManager>
                builder.Register(
                    async c =>
                {
                    if (!this.useV1TwinManager)
                    {
                        var messageConverterProvider         = c.Resolve <IMessageConverterProvider>();
                        IConnectionManager connectionManager = await c.Resolve <Task <IConnectionManager> >();
                        ITwinManager twinManager             = new PassThroughTwinManager(connectionManager, messageConverterProvider);
                        return(twinManager);
                    }
                    else
                    {
                        var messageConverterProvider         = c.Resolve <IMessageConverterProvider>();
                        IConnectionManager connectionManager = await c.Resolve <Task <IConnectionManager> >();
                        return(TwinManager.CreateTwinManager(connectionManager, messageConverterProvider, Option.None <IStoreProvider>()));
                    }
                })
                .As <Task <ITwinManager> >()
                .SingleInstance();
            }
            else
            {
                // EndpointExecutorConfig
                builder.Register(
                    c =>
                {
                    // Endpoint executor config values -
                    // ExponentialBackoff - minBackoff = 1s, maxBackoff = 60s, delta (used to add randomness to backoff) - 1s (default)
                    // Num of retries = int.MaxValue(we want to keep retrying till the message is sent)
                    // Revive period - period for which the endpoint should be considered dead if it doesn't respond - 1 min (we want to try continuously till the message expires)
                    // Timeout - time for which we want for the ack from the endpoint = 30s
                    // TODO - Should the number of retries be tied to the Store and Forward ttl? Not
                    // doing that right now as that value can be changed at runtime, but these settings
                    // cannot. Need to make the number of retries dynamically configurable for that.
                    TimeSpan minWait            = TimeSpan.FromSeconds(1);
                    TimeSpan maxWait            = TimeSpan.FromSeconds(60);
                    TimeSpan delta              = TimeSpan.FromSeconds(1);
                    int retries                 = int.MaxValue;
                    RetryStrategy retryStrategy = new ExponentialBackoff(retries, minWait, maxWait, delta);
                    TimeSpan timeout            = TimeSpan.FromSeconds(30);
                    TimeSpan revivePeriod       = TimeSpan.FromSeconds(30);
                    return(new EndpointExecutorConfig(timeout, retryStrategy, revivePeriod));
                })
                .As <EndpointExecutorConfig>()
                .SingleInstance();

                // Task<ICheckpointStore>
                builder.Register(
                    async c =>
                {
                    var dbStoreProvider              = await c.Resolve <Task <IDbStoreProvider> >();
                    IStoreProvider storeProvider     = new StoreProvider(dbStoreProvider);
                    ICheckpointStore checkpointStore = CheckpointStore.Create(storeProvider);
                    return(checkpointStore);
                })
                .As <Task <ICheckpointStore> >()
                .SingleInstance();

                // Task<IMessageStore>
                builder.Register(
                    async c =>
                {
                    var checkpointStore          = await c.Resolve <Task <ICheckpointStore> >();
                    var dbStoreProvider          = await c.Resolve <Task <IDbStoreProvider> >();
                    IStoreProvider storeProvider = new StoreProvider(dbStoreProvider);
                    IMessageStore messageStore   = new MessageStore(storeProvider, checkpointStore, this.storeAndForwardConfiguration.TimeToLive, this.checkEntireQueueOnCleanup);
                    return(messageStore);
                })
                .As <Task <IMessageStore> >()
                .SingleInstance();

                // Task<IEndpointExecutorFactory>
                builder.Register(
                    async c =>
                {
                    var endpointExecutorConfig = c.Resolve <EndpointExecutorConfig>();
                    var messageStore           = await c.Resolve <Task <IMessageStore> >();
                    IEndpointExecutorFactory endpointExecutorFactory = new StoringAsyncEndpointExecutorFactory(endpointExecutorConfig, new AsyncEndpointExecutorOptions(10, TimeSpan.FromSeconds(10)), messageStore);
                    return(endpointExecutorFactory);
                })
                .As <Task <IEndpointExecutorFactory> >()
                .SingleInstance();

                // Task<Router>
                builder.Register(
                    async c =>
                {
                    var checkpointStore         = await c.Resolve <Task <ICheckpointStore> >();
                    var routerConfig            = c.Resolve <RouterConfig>();
                    var endpointExecutorFactory = await c.Resolve <Task <IEndpointExecutorFactory> >();
                    return(await Router.CreateAsync(Guid.NewGuid().ToString(), this.iotHubName, routerConfig, endpointExecutorFactory, checkpointStore));
                })
                .As <Task <Router> >()
                .SingleInstance();

                // Task<ITwinManager>
                builder.Register(
                    async c =>
                {
                    if (this.useV1TwinManager)
                    {
                        var dbStoreProvider                  = await c.Resolve <Task <IDbStoreProvider> >();
                        var messageConverterProvider         = c.Resolve <IMessageConverterProvider>();
                        IConnectionManager connectionManager = await c.Resolve <Task <IConnectionManager> >();
                        return(TwinManager.CreateTwinManager(connectionManager, messageConverterProvider, Option.Some <IStoreProvider>(new StoreProvider(dbStoreProvider))));
                    }
                    else
                    {
                        var messageConverterProvider  = c.Resolve <IMessageConverterProvider>();
                        var deviceConnectivityManager = c.Resolve <IDeviceConnectivityManager>();
                        var connectionManagerTask     = c.Resolve <Task <IConnectionManager> >();
                        IEntityStore <string, TwinStoreEntity> entityStore = await this.GetTwinStore(c);
                        IConnectionManager connectionManager = await connectionManagerTask;
                        ITwinManager twinManager             = StoringTwinManager.Create(
                            connectionManager,
                            messageConverterProvider,
                            entityStore,
                            deviceConnectivityManager,
                            new ReportedPropertiesValidator(),
                            this.minTwinSyncPeriod,
                            this.reportedPropertiesSyncFrequency);
                        return(twinManager);
                    }
                })
                .As <Task <ITwinManager> >()
                .SingleInstance();
            }

            // IClientCredentials "EdgeHubCredentials"
            builder.Register(
                c =>
            {
                var identityFactory = c.Resolve <IClientCredentialsFactory>();
                IClientCredentials edgeHubCredentials = this.connectionString.Map(cs => identityFactory.GetWithConnectionString(cs)).GetOrElse(
                    () => identityFactory.GetWithIotEdged(this.edgeDeviceId, this.edgeModuleId));
                return(edgeHubCredentials);
            })
            .Named <IClientCredentials>("EdgeHubCredentials")
            .SingleInstance();

            // Task<IInvokeMethodHandler>
            builder.Register(
                async c =>
            {
                IConnectionManager connectionManager = await c.Resolve <Task <IConnectionManager> >();
                return(new InvokeMethodHandler(connectionManager) as IInvokeMethodHandler);
            })
            .As <Task <IInvokeMethodHandler> >()
            .SingleInstance();

            // Task<ISubscriptionProcessor>
            builder.Register(
                async c =>
            {
                var connectionManagerTask = c.Resolve <Task <IConnectionManager> >();
                if (this.experimentalFeatures.DisableCloudSubscriptions)
                {
                    return(new LocalSubscriptionProcessor(await connectionManagerTask) as ISubscriptionProcessor);
                }
                else
                {
                    var invokeMethodHandlerTask              = c.Resolve <Task <IInvokeMethodHandler> >();
                    var deviceConnectivityManager            = c.Resolve <IDeviceConnectivityManager>();
                    IConnectionManager connectionManager     = await connectionManagerTask;
                    IInvokeMethodHandler invokeMethodHandler = await invokeMethodHandlerTask;
                    return(new SubscriptionProcessor(connectionManager, invokeMethodHandler, deviceConnectivityManager) as ISubscriptionProcessor);
                }
            })
            .As <Task <ISubscriptionProcessor> >()
            .SingleInstance();

            // Task<IEdgeHub>
            builder.Register(
                async c =>
            {
                var routingMessageConverter = c.Resolve <Core.IMessageConverter <IRoutingMessage> >();
                var routerTask                = c.Resolve <Task <Router> >();
                var twinManagerTask           = c.Resolve <Task <ITwinManager> >();
                var invokeMethodHandlerTask   = c.Resolve <Task <IInvokeMethodHandler> >();
                var connectionManagerTask     = c.Resolve <Task <IConnectionManager> >();
                var subscriptionProcessorTask = c.Resolve <Task <ISubscriptionProcessor> >();
                Router router                                = await routerTask;
                ITwinManager twinManager                     = await twinManagerTask;
                IConnectionManager connectionManager         = await connectionManagerTask;
                IInvokeMethodHandler invokeMethodHandler     = await invokeMethodHandlerTask;
                ISubscriptionProcessor subscriptionProcessor = await subscriptionProcessorTask;
                IEdgeHub hub = new RoutingEdgeHub(
                    router,
                    routingMessageConverter,
                    connectionManager,
                    twinManager,
                    this.edgeDeviceId,
                    invokeMethodHandler,
                    subscriptionProcessor);
                return(hub);
            })
            .As <Task <IEdgeHub> >()
            .SingleInstance();

            // Task<ConfigUpdater>
            builder.Register(
                async c =>
            {
                IMessageStore messageStore = this.isStoreAndForwardEnabled ? await c.Resolve <Task <IMessageStore> >() : null;
                var storageSpaceChecker    = c.Resolve <IStorageSpaceChecker>();
                var edgeHubCredentials     = c.ResolveNamed <IClientCredentials>("EdgeHubCredentials");
                RouteFactory routeFactory  = await c.Resolve <Task <RouteFactory> >();
                Router router            = await c.Resolve <Task <Router> >();
                var twinManagerTask      = c.Resolve <Task <ITwinManager> >();
                var twinMessageConverter = c.Resolve <Core.IMessageConverter <Twin> >();
                var twinManager          = await twinManagerTask;
                var configUpdater        = new ConfigUpdater(router, messageStore, this.configUpdateFrequency, storageSpaceChecker);
                return(configUpdater);
            })
            .As <Task <ConfigUpdater> >()
            .SingleInstance();

            // Task<IConfigSource>
            builder.Register <Task <IConfigSource> >(
                async c =>
            {
                RouteFactory routeFactory = await c.Resolve <Task <RouteFactory> >();
                if (this.useTwinConfig)
                {
                    var edgeHubCredentials             = c.ResolveNamed <IClientCredentials>("EdgeHubCredentials");
                    var twinCollectionMessageConverter = c.Resolve <Core.IMessageConverter <TwinCollection> >();
                    var twinMessageConverter           = c.Resolve <Core.IMessageConverter <Twin> >();
                    var twinManagerTask                  = c.Resolve <Task <ITwinManager> >();
                    var edgeHubTask                      = c.Resolve <Task <IEdgeHub> >();
                    ITwinManager twinManager             = await twinManagerTask;
                    IEdgeHub edgeHub                     = await edgeHubTask;
                    IConnectionManager connectionManager = await c.Resolve <Task <IConnectionManager> >();
                    IDeviceScopeIdentitiesCache deviceScopeIdentitiesCache = await c.Resolve <Task <IDeviceScopeIdentitiesCache> >();

                    var edgeHubConnection = await EdgeHubConnection.Create(
                        edgeHubCredentials.Identity,
                        edgeHub,
                        twinManager,
                        connectionManager,
                        routeFactory,
                        twinCollectionMessageConverter,
                        this.versionInfo,
                        deviceScopeIdentitiesCache);

                    return(new TwinConfigSource(edgeHubConnection, edgeHubCredentials.Identity.Id, this.versionInfo, twinManager, twinMessageConverter, twinCollectionMessageConverter, routeFactory));
                }
                else
                {
                    return(new LocalConfigSource(routeFactory, this.routes, this.storeAndForwardConfiguration));
                }
            })
            .As <Task <IConfigSource> >()
            .SingleInstance();

            // Task<IConnectionProvider>
            builder.Register(
                async c =>
            {
                var connectionManagerTask              = c.Resolve <Task <IConnectionManager> >();
                var edgeHubTask                        = c.Resolve <Task <IEdgeHub> >();
                IConnectionManager connectionManager   = await connectionManagerTask;
                IEdgeHub edgeHub                       = await edgeHubTask;
                IConnectionProvider connectionProvider = new ConnectionProvider(connectionManager, edgeHub, this.messageAckTimeout);
                return(connectionProvider);
            })
            .As <Task <IConnectionProvider> >()
            .SingleInstance();

            base.Load(builder);
        }