private async Task <string> ResolvePath(string path)
 {
     using (CommandConnection connection = await BuildConnection())
     {
         return(await connection.ResolvePath(path));
     }
 }
        /// <summary>
        /// Handler for property changes of the Directories namespace in the machine model
        /// </summary>
        /// <param name="sender">Sender object</param>
        /// <param name="e">Information about the changed property</param>
        private async void Directories_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (e.PropertyName == nameof(Directories.WWW))
            {
                Directories directories = (Directories)sender;
                string      path        = await _commandConnection.ResolvePath(directories.WWW);

                OnWebDirectoryChanged?.Invoke(path);
            }
        }
        private async Task ValidateProvider()
        {
            using (CommandConnection connection = new CommandConnection())
            {
                await connection.Connect(_configuration.GetValue("SocketPath", DuetAPI.Connection.Defaults.SocketPath));

                string wwwRoot = await connection.ResolvePath("0:/www");

                if (wwwRoot != _wwwRoot)
                {
                    _provider = new PhysicalFileProvider(wwwRoot);
                    _wwwRoot  = wwwRoot;
                }
            }
        }
        /// <summary>
        /// Synchronize all registered endpoints and user sessions
        /// </summary>
        public async Task Execute()
        {
            string unixSocket = _configuration.GetValue("SocketPath", DuetAPI.Connection.Defaults.FullSocketPath);
            int    retryDelay = _configuration.GetValue("ModelRetryDelay", 5000);

            MachineModel model;

            try
            {
                do
                {
                    try
                    {
                        // Establish connections to DCS
                        using SubscribeConnection subscribeConnection = new SubscribeConnection();
                        using CommandConnection commandConnection     = new CommandConnection();
                        await subscribeConnection.Connect(DuetAPI.Connection.SubscriptionMode.Patch, "directories/www|httpEndpoints/**|userSessions/**", unixSocket);

                        await commandConnection.Connect(unixSocket);

                        _logger.LogInformation("Connections to DuetControlServer established");

                        // Get the machine model and keep it up-to-date
                        model = await subscribeConnection.GetMachineModel(_stopRequest.Token);

                        lock (Endpoints)
                        {
                            foreach (HttpEndpoint ep in model.HttpEndpoints)
                            {
                                string fullPath = $"{ep.EndpointType}/machine/{ep.Namespace}/{ep.Path}";
                                Endpoints[fullPath] = ep;
                                _logger.LogInformation("Registered HTTP {0} endpoint via /machine/{1}/{2}", ep.EndpointType, ep.Namespace, ep.Path);
                            }
                        }

                        // Keep track of the web directory
                        _commandConnection = commandConnection;
                        model.Directories.PropertyChanged += Directories_PropertyChanged;
                        string wwwDirectory = await commandConnection.ResolvePath(model.Directories.WWW);

                        OnWebDirectoryChanged?.Invoke(wwwDirectory);

                        do
                        {
                            // Wait for more updates
                            using JsonDocument jsonPatch = await subscribeConnection.GetMachineModelPatch(_stopRequest.Token);

                            DuetAPI.Utility.JsonPatch.Patch(model, jsonPatch);

                            // Check if the HTTP sessions have changed and rebuild them on demand
                            if (jsonPatch.RootElement.TryGetProperty("httpEndpoints", out _))
                            {
                                _logger.LogInformation("New number of custom HTTP endpoints: {0}", model.HttpEndpoints.Count);


                                lock (Endpoints)
                                {
                                    Endpoints.Clear();
                                    foreach (HttpEndpoint ep in model.HttpEndpoints)
                                    {
                                        string fullPath = $"{ep.EndpointType}/machine/{ep.Namespace}/{ep.Path}";
                                        Endpoints[fullPath] = ep;
                                        _logger.LogInformation("Registered HTTP {0} endpoint via /machine/{1}/{2}", ep.EndpointType, ep.Namespace, ep.Path);
                                    }
                                }
                            }

                            // Rebuild the list of user sessions on demand
                            if (jsonPatch.RootElement.TryGetProperty("userSessions", out _))
                            {
                                lock (UserSessions)
                                {
                                    UserSessions.Clear();
                                    foreach (UserSession session in model.UserSessions)
                                    {
                                        UserSessions[session.Origin] = session.Id;
                                    }
                                }
                            }
                        }while (!!_stopRequest.IsCancellationRequested);
                    }
                    catch (Exception e) when(!(e is OperationCanceledException))
                    {
                        _logger.LogWarning(e, "Failed to synchronize machine model");
                        await Task.Delay(retryDelay, _stopRequest.Token);
                    }
                }while (!_stopRequest.IsCancellationRequested);
            }
            catch (Exception e)
            {
                if (!(e is OperationCanceledException))
                {
                    _logger.LogError(e, "Failed to synchronize object model");
                }
            }
        }
예제 #5
0
        /// <summary>
        /// Synchronize all registered endpoints and user sessions
        /// </summary>
        public async Task Execute()
        {
            string unixSocket = _configuration.GetValue("SocketPath", DuetAPI.Connection.Defaults.FullSocketPath);
            int    retryDelay = _configuration.GetValue("ModelRetryDelay", 5000);

            ObjectModel model;

            try
            {
                do
                {
                    try
                    {
                        // Establish connections to DCS
                        using SubscribeConnection subscribeConnection = new SubscribeConnection();
                        using CommandConnection commandConnection     = new CommandConnection();
                        await subscribeConnection.Connect(DuetAPI.Connection.SubscriptionMode.Patch, new string[] {
                            "directories/www",
                            "httpEndpoints/**",
                            "network/corsSite",
                            "userSessions/**"
                        }, unixSocket);

                        await commandConnection.Connect(unixSocket);

                        _logger.LogInformation("Connections to DuetControlServer established");

                        // Get the machine model and keep it up-to-date
                        model = await subscribeConnection.GetObjectModel(_stopRequest.Token);

                        if (!string.IsNullOrEmpty(model.Network.CorsSite))
                        {
                            _logger.LogInformation("Changing CORS policy to accept site '{0}'", model.Network.CorsSite);
                            CorsPolicy.Origins.Add(model.Network.CorsSite);
                        }
                        lock (Endpoints)
                        {
                            Endpoints.Clear();
                            foreach (HttpEndpoint ep in model.HttpEndpoints)
                            {
                                string fullPath = (ep.Namespace == HttpEndpoint.RepRapFirmwareNamespace) ? $"{ep.EndpointType}/rr_{ep.Path}" : $"{ep.EndpointType}/machine/{ep.Namespace}/{ep.Path}";
                                Endpoints[fullPath] = ep;
                                _logger.LogInformation("Registered HTTP endpoint {0}", fullPath);
                            }
                        }

                        // Keep track of the web directory
                        _commandConnection = commandConnection;
                        model.Directories.PropertyChanged += Directories_PropertyChanged;
                        string wwwDirectory = await commandConnection.ResolvePath(model.Directories.Web);

                        OnWebDirectoryChanged?.Invoke(wwwDirectory);

                        do
                        {
                            // Wait for more updates
                            using JsonDocument jsonPatch = await subscribeConnection.GetObjectModelPatch(_stopRequest.Token);

                            model.UpdateFromJson(jsonPatch.RootElement);

                            // Check for updated CORS site
                            if (jsonPatch.RootElement.TryGetProperty("network", out _))
                            {
                                CorsPolicy.Origins.Clear();
                                if (!string.IsNullOrEmpty(model.Network.CorsSite))
                                {
                                    _logger.LogInformation("Changing CORS policy to accept site '{0}'", model.Network.CorsSite);
                                    CorsPolicy.Origins.Add(model.Network.CorsSite);
                                }
                                else
                                {
                                    _logger.LogInformation("Reset CORS policy");
                                }
                            }

                            // Check if the HTTP sessions have changed and rebuild them on demand
                            if (jsonPatch.RootElement.TryGetProperty("httpEndpoints", out _))
                            {
                                _logger.LogInformation("New number of custom HTTP endpoints: {0}", model.HttpEndpoints.Count);

                                lock (Endpoints)
                                {
                                    Endpoints.Clear();
                                    foreach (HttpEndpoint ep in model.HttpEndpoints)
                                    {
                                        string fullPath = $"{ep.EndpointType}/machine/{ep.Namespace}/{ep.Path}";
                                        Endpoints[fullPath] = ep;
                                        _logger.LogInformation("Registered HTTP {0} endpoint via /machine/{1}/{2}", ep.EndpointType, ep.Namespace, ep.Path);
                                    }
                                }
                            }

                            // Rebuild the list of user sessions on demand
                            if (jsonPatch.RootElement.TryGetProperty("userSessions", out _))
                            {
                                lock (UserSessions)
                                {
                                    UserSessions.Clear();
                                    foreach (UserSession session in model.UserSessions)
                                    {
                                        UserSessions[session.Origin] = session.Id;
                                    }
                                }
                            }
                        }while (!_stopRequest.IsCancellationRequested);
                    }
                    catch (Exception e) when(!(e is OperationCanceledException))
                    {
                        _logger.LogWarning(e, "Failed to synchronize machine model");
                        await Task.Delay(retryDelay, _stopRequest.Token);
                    }
                }while (!_stopRequest.IsCancellationRequested);
            }
            catch (OperationCanceledException)
            {
                // unhandled
            }
        }