17c804472Sopenharmony_ci/*
27c804472Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
37c804472Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
47c804472Sopenharmony_ci * you may not use this file except in compliance with the License.
57c804472Sopenharmony_ci * You may obtain a copy of the License at
67c804472Sopenharmony_ci *
77c804472Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
87c804472Sopenharmony_ci *
97c804472Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
107c804472Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
117c804472Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
127c804472Sopenharmony_ci * See the License for the specific language governing permissions and
137c804472Sopenharmony_ci * limitations under the License.
147c804472Sopenharmony_ci */
157c804472Sopenharmony_ci
167c804472Sopenharmony_ci
177c804472Sopenharmony_ci#include "CommandLineInterface.h"
187c804472Sopenharmony_ci
197c804472Sopenharmony_ci#include <chrono>
207c804472Sopenharmony_ci#include <regex>
217c804472Sopenharmony_ci
227c804472Sopenharmony_ci#include "CommandLine.h"
237c804472Sopenharmony_ci#include "CommandLineFactory.h"
247c804472Sopenharmony_ci#include "ModelManager.h"
257c804472Sopenharmony_ci#include "PreviewerEngineLog.h"
267c804472Sopenharmony_ci#include "VirtualScreen.h"
277c804472Sopenharmony_ci#include "CommandParser.h"
287c804472Sopenharmony_ci
297c804472Sopenharmony_ciconst std::string CommandLineInterface::COMMAND_VERSION = "1.0.1";
307c804472Sopenharmony_cibool CommandLineInterface::isFirstWsSend = true;
317c804472Sopenharmony_cibool CommandLineInterface::isPipeConnected = false;
327c804472Sopenharmony_ciCommandLineInterface::CommandLineInterface() : socket(nullptr) {}
337c804472Sopenharmony_ci
347c804472Sopenharmony_ciCommandLineInterface::~CommandLineInterface() {}
357c804472Sopenharmony_ci
367c804472Sopenharmony_civoid CommandLineInterface::InitPipe(const std::string name)
377c804472Sopenharmony_ci{
387c804472Sopenharmony_ci    if (socket != nullptr) {
397c804472Sopenharmony_ci        socket.reset();
407c804472Sopenharmony_ci        ELOG("CommandLineInterface::InitPipe socket is not null");
417c804472Sopenharmony_ci    }
427c804472Sopenharmony_ci
437c804472Sopenharmony_ci    socket = std::make_unique<LocalSocket>();
447c804472Sopenharmony_ci    if (socket == nullptr) {
457c804472Sopenharmony_ci        FLOG("CommandLineInterface::Connect socket memory allocation failed!");
467c804472Sopenharmony_ci    }
477c804472Sopenharmony_ci
487c804472Sopenharmony_ci    if (!socket->ConnectToServer(socket->GetCommandPipeName(name), LocalSocket::READ_WRITE)) {
497c804472Sopenharmony_ci        FLOG("CommandLineInterface command pipe connect failed");
507c804472Sopenharmony_ci    }
517c804472Sopenharmony_ci    isPipeConnected  = true;
527c804472Sopenharmony_ci}
537c804472Sopenharmony_ci
547c804472Sopenharmony_ciCommandLineInterface& CommandLineInterface::GetInstance()
557c804472Sopenharmony_ci{
567c804472Sopenharmony_ci    static CommandLineInterface instance; /* NOLINT */
577c804472Sopenharmony_ci    return instance;
587c804472Sopenharmony_ci}
597c804472Sopenharmony_ci
607c804472Sopenharmony_civoid CommandLineInterface::SendJsonData(const Json2::Value& value)
617c804472Sopenharmony_ci{
627c804472Sopenharmony_ci    *(GetInstance().socket) << value.ToStyledString();
637c804472Sopenharmony_ci}
647c804472Sopenharmony_ci
657c804472Sopenharmony_civoid CommandLineInterface::SendJSHeapMemory(size_t total, size_t alloc, size_t peak) const
667c804472Sopenharmony_ci{
677c804472Sopenharmony_ci    Json2::Value result = JsonReader::CreateObject();
687c804472Sopenharmony_ci    result.Add("version", COMMAND_VERSION.c_str());
697c804472Sopenharmony_ci    result.Add("property", "memoryUsage");
707c804472Sopenharmony_ci    Json2::Value memory = JsonReader::CreateObject();
717c804472Sopenharmony_ci    memory.Add("totalBytes", static_cast<double>(total));
727c804472Sopenharmony_ci    memory.Add("allocBytes", static_cast<double>(alloc));
737c804472Sopenharmony_ci    memory.Add("peakAllocBytes", static_cast<double>(peak));
747c804472Sopenharmony_ci    result.Add("result", memory);
757c804472Sopenharmony_ci    if (socket == nullptr) {
767c804472Sopenharmony_ci        ELOG("CommandLineInterface::SendJSHeapMemory socket is null");
777c804472Sopenharmony_ci        return;
787c804472Sopenharmony_ci    }
797c804472Sopenharmony_ci    *socket << result.ToStyledString();
807c804472Sopenharmony_ci}
817c804472Sopenharmony_ci
827c804472Sopenharmony_civoid CommandLineInterface::SendWebsocketStartupSignal() const
837c804472Sopenharmony_ci{
847c804472Sopenharmony_ci    Json2::Value result = JsonReader::CreateObject();
857c804472Sopenharmony_ci    Json2::Value args = JsonReader::CreateObject();
867c804472Sopenharmony_ci    result.Add("MessageType", "imageWebsocket");
877c804472Sopenharmony_ci    args.Add("port", VirtualScreen::webSocketPort.c_str());
887c804472Sopenharmony_ci    result.Add("args", args);
897c804472Sopenharmony_ci    *socket << result.ToStyledString();
907c804472Sopenharmony_ci}
917c804472Sopenharmony_ci
927c804472Sopenharmony_civoid CommandLineInterface::ProcessCommand() const
937c804472Sopenharmony_ci{
947c804472Sopenharmony_ci    std::string message; /* NOLINT */
957c804472Sopenharmony_ci    if (socket == nullptr) {
967c804472Sopenharmony_ci        ELOG("CommandLineInterface::ProcessCommand socket is null");
977c804472Sopenharmony_ci        return;
987c804472Sopenharmony_ci    }
997c804472Sopenharmony_ci    if (isPipeConnected && VirtualScreen::isWebSocketListening && isFirstWsSend) {
1007c804472Sopenharmony_ci        isFirstWsSend = false;
1017c804472Sopenharmony_ci        SendWebsocketStartupSignal();
1027c804472Sopenharmony_ci    }
1037c804472Sopenharmony_ci    *socket >> message;
1047c804472Sopenharmony_ci    if (message.empty()) {
1057c804472Sopenharmony_ci        return;
1067c804472Sopenharmony_ci    }
1077c804472Sopenharmony_ci
1087c804472Sopenharmony_ci    ProcessCommandMessage(message);
1097c804472Sopenharmony_ci}
1107c804472Sopenharmony_ci
1117c804472Sopenharmony_civoid CommandLineInterface::ProcessCommandMessage(std::string message) const
1127c804472Sopenharmony_ci{
1137c804472Sopenharmony_ci    ILOG("***cmd*** message:%s", message.c_str());
1147c804472Sopenharmony_ci    Json2::Value jsonData = JsonReader::ParseJsonData2(message);
1157c804472Sopenharmony_ci    std::string errors; /* NOLINT */
1167c804472Sopenharmony_ci    bool parsingSuccessful = jsonData.IsNull() ? false : true;
1177c804472Sopenharmony_ci    if (!parsingSuccessful) {
1187c804472Sopenharmony_ci        errors = JsonReader::GetErrorPtr();
1197c804472Sopenharmony_ci    }
1207c804472Sopenharmony_ci
1217c804472Sopenharmony_ci    if (!ProcessCommandValidate(parsingSuccessful, jsonData, errors)) {
1227c804472Sopenharmony_ci        return;
1237c804472Sopenharmony_ci    }
1247c804472Sopenharmony_ci
1257c804472Sopenharmony_ci    CommandLine::CommandType type = GetCommandType(jsonData["type"].AsString());
1267c804472Sopenharmony_ci    if (type == CommandLine::CommandType::INVALID) {
1277c804472Sopenharmony_ci        return;
1287c804472Sopenharmony_ci    }
1297c804472Sopenharmony_ci
1307c804472Sopenharmony_ci    std::string command = jsonData["command"].AsString();
1317c804472Sopenharmony_ci    if (CommandParser::GetInstance().IsStaticCard() && IsStaticIgnoreCmd(command)) {
1327c804472Sopenharmony_ci        return;
1337c804472Sopenharmony_ci    }
1347c804472Sopenharmony_ci    Json2::Value val = jsonData["args"];
1357c804472Sopenharmony_ci    std::unique_ptr<CommandLine> commandLine =
1367c804472Sopenharmony_ci        CommandLineFactory::CreateCommandLine(command, type, val, *socket);
1377c804472Sopenharmony_ci    if (commandLine == nullptr) {
1387c804472Sopenharmony_ci        ELOG("Unsupported command");
1397c804472Sopenharmony_ci        return;
1407c804472Sopenharmony_ci    }
1417c804472Sopenharmony_ci    commandLine->CheckAndRun();
1427c804472Sopenharmony_ci}
1437c804472Sopenharmony_ci
1447c804472Sopenharmony_cibool CommandLineInterface::ProcessCommandValidate(bool parsingSuccessful,
1457c804472Sopenharmony_ci                                                  const Json2::Value& jsonData,
1467c804472Sopenharmony_ci                                                  const std::string& errors) const
1477c804472Sopenharmony_ci{
1487c804472Sopenharmony_ci    if (!parsingSuccessful) {
1497c804472Sopenharmony_ci        ELOG("Failed to parse the JSON, errors: %s", errors.c_str());
1507c804472Sopenharmony_ci        return false;
1517c804472Sopenharmony_ci    }
1527c804472Sopenharmony_ci
1537c804472Sopenharmony_ci    if (!jsonData.IsObject()) {
1547c804472Sopenharmony_ci        ELOG("Command is not a object!");
1557c804472Sopenharmony_ci        return false;
1567c804472Sopenharmony_ci    }
1577c804472Sopenharmony_ci
1587c804472Sopenharmony_ci    if (!jsonData.IsMember("type") || !jsonData.IsMember("command") || !jsonData.IsMember("version")) {
1597c804472Sopenharmony_ci        ELOG("Command error!");
1607c804472Sopenharmony_ci        return false;
1617c804472Sopenharmony_ci    }
1627c804472Sopenharmony_ci
1637c804472Sopenharmony_ci    if (!regex_match(jsonData["version"].AsString(),
1647c804472Sopenharmony_ci        std::regex("(([0-9]|([1-9]([0-9]*))).){2}([0-9]|([1-9]([0-9]*)))"))) {
1657c804472Sopenharmony_ci        ELOG("Invalid command version!");
1667c804472Sopenharmony_ci        return false;
1677c804472Sopenharmony_ci    }
1687c804472Sopenharmony_ci    return true;
1697c804472Sopenharmony_ci}
1707c804472Sopenharmony_ci
1717c804472Sopenharmony_ciCommandLine::CommandType CommandLineInterface::GetCommandType(std::string name) const
1727c804472Sopenharmony_ci{
1737c804472Sopenharmony_ci    CommandLine::CommandType type = CommandLine::CommandType::INVALID;
1747c804472Sopenharmony_ci    if (name == "set") {
1757c804472Sopenharmony_ci        type = CommandLine::CommandType::SET;
1767c804472Sopenharmony_ci    } else if (name == "get") {
1777c804472Sopenharmony_ci        type = CommandLine::CommandType::GET;
1787c804472Sopenharmony_ci    } else if (name == "action") {
1797c804472Sopenharmony_ci        type = CommandLine::CommandType::ACTION;
1807c804472Sopenharmony_ci    } else {
1817c804472Sopenharmony_ci        ELOG("Command type invalid!");
1827c804472Sopenharmony_ci    }
1837c804472Sopenharmony_ci    return type;
1847c804472Sopenharmony_ci}
1857c804472Sopenharmony_ci
1867c804472Sopenharmony_civoid CommandLineInterface::ApplyConfig(const Json2::Value& val) const
1877c804472Sopenharmony_ci{
1887c804472Sopenharmony_ci    const std::string set("setting");
1897c804472Sopenharmony_ci    if (val.IsMember(set.c_str())) {
1907c804472Sopenharmony_ci        Json2::Value versionMembers = val[set];
1917c804472Sopenharmony_ci        if (!versionMembers.IsObject()) {
1927c804472Sopenharmony_ci            return;
1937c804472Sopenharmony_ci        }
1947c804472Sopenharmony_ci
1957c804472Sopenharmony_ci        Json2::Value::Members versions = versionMembers.GetMemberNames();
1967c804472Sopenharmony_ci
1977c804472Sopenharmony_ci        for (Json2::Value::Members::iterator viter = versions.begin(); viter != versions.end(); viter++) {
1987c804472Sopenharmony_ci            std::string version = *viter;
1997c804472Sopenharmony_ci            Json2::Value commands = versionMembers[version];
2007c804472Sopenharmony_ci            if (!commands.IsObject()) {
2017c804472Sopenharmony_ci                continue;
2027c804472Sopenharmony_ci            }
2037c804472Sopenharmony_ci            Json2::Value::Members members = commands.GetMemberNames();
2047c804472Sopenharmony_ci
2057c804472Sopenharmony_ci            ApplyConfigMembers(commands, members);
2067c804472Sopenharmony_ci        }
2077c804472Sopenharmony_ci    }
2087c804472Sopenharmony_ci}
2097c804472Sopenharmony_ci
2107c804472Sopenharmony_civoid CommandLineInterface::ApplyConfigMembers(const Json2::Value& commands,
2117c804472Sopenharmony_ci                                              const Json2::Value::Members& members) const
2127c804472Sopenharmony_ci{
2137c804472Sopenharmony_ci    for (Json2::Value::Members::const_iterator iter = members.begin(); iter != members.end(); iter++)  {
2147c804472Sopenharmony_ci        std::string key = *iter;
2157c804472Sopenharmony_ci        if (!commands[key].IsObject() || !commands[key].IsMember("args") || !commands[key]["args"].IsObject()) {
2167c804472Sopenharmony_ci            ELOG("Invalid JSON: %s", commands[key].AsString().c_str());
2177c804472Sopenharmony_ci            continue;
2187c804472Sopenharmony_ci        }
2197c804472Sopenharmony_ci        Json2::Value val = commands[key]["args"];
2207c804472Sopenharmony_ci        std::unique_ptr<CommandLine> command =
2217c804472Sopenharmony_ci            CommandLineFactory::CreateCommandLine(key, CommandLine::CommandType::SET, val, *socket);
2227c804472Sopenharmony_ci        ApplyConfigCommands(key, command);
2237c804472Sopenharmony_ci    }
2247c804472Sopenharmony_ci}
2257c804472Sopenharmony_ci
2267c804472Sopenharmony_civoid CommandLineInterface::ApplyConfigCommands(const std::string& key,
2277c804472Sopenharmony_ci                                               const std::unique_ptr<CommandLine>& command) const
2287c804472Sopenharmony_ci{
2297c804472Sopenharmony_ci    if (command == nullptr) {
2307c804472Sopenharmony_ci        ELOG("Unsupported configuration: %s", key.c_str());
2317c804472Sopenharmony_ci        return;
2327c804472Sopenharmony_ci    }
2337c804472Sopenharmony_ci
2347c804472Sopenharmony_ci    if (command->IsArgValid()) {
2357c804472Sopenharmony_ci        command->RunSet();
2367c804472Sopenharmony_ci    }
2377c804472Sopenharmony_ci}
2387c804472Sopenharmony_ci
2397c804472Sopenharmony_civoid CommandLineInterface::Init(std::string pipeBaseName)
2407c804472Sopenharmony_ci{
2417c804472Sopenharmony_ci    CommandLineFactory::InitCommandMap();
2427c804472Sopenharmony_ci    InitPipe(pipeBaseName);
2437c804472Sopenharmony_ci}
2447c804472Sopenharmony_ci
2457c804472Sopenharmony_civoid CommandLineInterface::ReadAndApplyConfig(std::string path) const
2467c804472Sopenharmony_ci{
2477c804472Sopenharmony_ci    if (path.empty()) {
2487c804472Sopenharmony_ci        return;
2497c804472Sopenharmony_ci    }
2507c804472Sopenharmony_ci    std::string jsonStr = JsonReader::ReadFile(path);
2517c804472Sopenharmony_ci    Json2::Value val = JsonReader::ParseJsonData2(jsonStr);
2527c804472Sopenharmony_ci    ApplyConfig(val);
2537c804472Sopenharmony_ci}
2547c804472Sopenharmony_ci
2557c804472Sopenharmony_civoid CommandLineInterface::CreatCommandToSendData(const std::string commandName,
2567c804472Sopenharmony_ci                                                  const Json2::Value& jsonData,
2577c804472Sopenharmony_ci                                                  const std::string type) const
2587c804472Sopenharmony_ci{
2597c804472Sopenharmony_ci    CommandLine::CommandType commandType = GetCommandType(type);
2607c804472Sopenharmony_ci    std::unique_ptr<CommandLine> commandLine =
2617c804472Sopenharmony_ci        CommandLineFactory::CreateCommandLine(commandName, commandType, jsonData, *socket);
2627c804472Sopenharmony_ci    if (commandLine == nullptr) {
2637c804472Sopenharmony_ci        ELOG("Unsupported CreatCommandToSendData: %s", commandName.c_str());
2647c804472Sopenharmony_ci        return;
2657c804472Sopenharmony_ci    }
2667c804472Sopenharmony_ci    commandLine->RunAndSendResultToManager();
2677c804472Sopenharmony_ci}
2687c804472Sopenharmony_ci
2697c804472Sopenharmony_cibool CommandLineInterface::IsStaticIgnoreCmd(const std::string cmd) const
2707c804472Sopenharmony_ci{
2717c804472Sopenharmony_ci    auto it = std::find(staticIgnoreCmd.begin(), staticIgnoreCmd.end(), cmd);
2727c804472Sopenharmony_ci    if (it != staticIgnoreCmd.end()) {
2737c804472Sopenharmony_ci        return false;
2747c804472Sopenharmony_ci    } else {
2757c804472Sopenharmony_ci        return true;
2767c804472Sopenharmony_ci    }
2777c804472Sopenharmony_ci}
278