• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 
17 #include "CommandLineInterface.h"
18 
19 #include <chrono>
20 #include <regex>
21 
22 #include "CommandLine.h"
23 #include "CommandLineFactory.h"
24 #include "JsonReader.h"
25 #include "ModelManager.h"
26 #include "PreviewerEngineLog.h"
27 #include "VirtualScreen.h"
28 #include "CommandParser.h"
29 
30 using namespace std;
31 
32 const string CommandLineInterface::COMMAND_VERSION = "1.0.1";
33 bool CommandLineInterface::isFirstWsSend = true;
34 bool CommandLineInterface::isPipeConnected = false;
CommandLineInterface()35 CommandLineInterface::CommandLineInterface() : socket(nullptr) {}
36 
~CommandLineInterface()37 CommandLineInterface::~CommandLineInterface() {}
38 
InitPipe(const string name)39 void CommandLineInterface::InitPipe(const string name)
40 {
41     if (socket != nullptr) {
42         socket.reset();
43         ELOG("CommandLineInterface::InitPipe socket is not null");
44     }
45 
46     socket = std::make_unique<LocalSocket>();
47     if (socket == nullptr) {
48         FLOG("CommandLineInterface::Connect socket memory allocation failed!");
49     }
50 
51     if (!socket->ConnectToServer(socket->GetCommandPipeName(name), LocalSocket::READ_WRITE)) {
52         FLOG("CommandLineInterface command pipe connect failed");
53     }
54     isPipeConnected  = true;
55 }
56 
GetInstance()57 CommandLineInterface& CommandLineInterface::GetInstance()
58 {
59     static CommandLineInterface instance; /* NOLINT */
60     return instance;
61 }
62 
SendJsonData(const Json::Value & value)63 void CommandLineInterface::SendJsonData(const Json::Value& value)
64 {
65     *(GetInstance().socket) << value.toStyledString();
66 }
67 
SendJSHeapMemory(size_t total,size_t alloc,size_t peak) const68 void CommandLineInterface::SendJSHeapMemory(size_t total, size_t alloc, size_t peak) const
69 {
70     Json::Value result;
71     result["version"] = COMMAND_VERSION;
72     result["property"] = "memoryUsage";
73     Json::Value memory;
74     memory["totalBytes"] = static_cast<Json::UInt64>(total);
75     memory["allocBytes"] = static_cast<Json::UInt64>(alloc);
76     memory["peakAllocBytes"] = static_cast<Json::UInt64>(peak);
77     result["result"] = memory;
78     if (socket == nullptr) {
79         ELOG("CommandLineInterface::SendJSHeapMemory socket is null");
80         return;
81     }
82     *socket << result.toStyledString();
83 }
84 
SendWebsocketStartupSignal() const85 void CommandLineInterface::SendWebsocketStartupSignal() const
86 {
87     Json::Value result;
88     Json::Value args;
89     result["MessageType"] = "imageWebsocket";
90     args["port"] = VirtualScreen::webSocketPort;
91     result["args"] = args;
92     *socket << result.toStyledString();
93 }
94 
ProcessCommand() const95 void CommandLineInterface::ProcessCommand() const
96 {
97     string message; /* NOLINT */
98     if (socket == nullptr) {
99         ELOG("CommandLineInterface::ProcessCommand socket is null");
100         return;
101     }
102     if (isPipeConnected && VirtualScreen::isWebSocketListening && isFirstWsSend) {
103         isFirstWsSend = false;
104         SendWebsocketStartupSignal();
105     }
106     *socket >> message;
107     if (message.empty()) {
108         return;
109     }
110 
111     ProcessCommandMessage(message);
112 }
113 
ProcessCommandMessage(std::string message) const114 void CommandLineInterface::ProcessCommandMessage(std::string message) const
115 {
116     ILOG("***cmd*** message:%s", message.c_str());
117     Json::CharReaderBuilder builder;
118     Json::CharReader* reader = builder.newCharReader();
119     if (reader == nullptr) {
120         FLOG("CommandLineInterface: CharReader memory allocation failed.");
121     }
122 
123     Json::Value jsonData;
124     std::string errors; /* NOLINT */
125 
126     bool parsingSuccessful = reader->parse(message.c_str(), message.c_str() + message.size(), &jsonData, &errors);
127     delete reader;
128     reader = nullptr;
129 
130     if (!ProcessCommandValidate(parsingSuccessful, jsonData, errors)) {
131         return;
132     }
133 
134     CommandLine::CommandType type = GetCommandType(jsonData["type"].asString());
135     if (type == CommandLine::CommandType::INVALID) {
136         return;
137     }
138 
139     string command = jsonData["command"].asString();
140     if (CommandParser::GetInstance().IsStaticCard() && IsStaticIgnoreCmd(command)) {
141         return;
142     }
143     std::unique_ptr<CommandLine> commandLine =
144         CommandLineFactory::CreateCommandLine(command, type, jsonData["args"], *socket);
145     if (commandLine == nullptr) {
146         ELOG("Unsupported command");
147         return;
148     }
149     commandLine->CheckAndRun();
150 }
151 
ProcessCommandValidate(bool parsingSuccessful,const Json::Value & jsonData,const std::string & errors) const152 bool CommandLineInterface::ProcessCommandValidate(bool parsingSuccessful,
153                                                   const Json::Value& jsonData,
154                                                   const std::string& errors) const
155 {
156     if (!parsingSuccessful) {
157         ELOG("Failed to parse the JSON, errors: %s", errors.c_str());
158         return false;
159     }
160 
161     if (!jsonData.isObject()) {
162         ELOG("Command is not a object!");
163         return false;
164     }
165 
166     if (!jsonData.isMember("type") || !jsonData.isMember("command") || !jsonData.isMember("version")) {
167         ELOG("Command error!");
168         return false;
169     }
170 
171     if (!regex_match(jsonData["version"].asString(), regex("(([0-9]|([1-9]([0-9]*))).){2}([0-9]|([1-9]([0-9]*)))"))) {
172         ELOG("Invalid command version!");
173         return false;
174     }
175     return true;
176 }
177 
GetCommandType(string name) const178 CommandLine::CommandType CommandLineInterface::GetCommandType(string name) const
179 {
180     CommandLine::CommandType type = CommandLine::CommandType::INVALID;
181     if (name == "set") {
182         type = CommandLine::CommandType::SET;
183     } else if (name == "get") {
184         type = CommandLine::CommandType::GET;
185     } else if (name == "action") {
186         type = CommandLine::CommandType::ACTION;
187     } else {
188         ELOG("Command type invalid!");
189     }
190     return type;
191 }
192 
ApplyConfig(const Json::Value & val) const193 void CommandLineInterface::ApplyConfig(const Json::Value& val) const
194 {
195     const string set("setting");
196     if (val.isMember(set)) {
197         Json::Value versionMembers = val[set];
198         if (!versionMembers.isObject()) {
199             return;
200         }
201 
202         Json::Value::Members versions = versionMembers.getMemberNames();
203 
204         for (Json::Value::Members::iterator viter = versions.begin(); viter != versions.end(); viter++) {
205             string version = *viter;
206             Json::Value commands = versionMembers[version];
207             if (!commands.isObject()) {
208                 continue;
209             }
210             Json::Value::Members members = commands.getMemberNames();
211 
212             ApplyConfigMembers(commands, members);
213         }
214     }
215 }
216 
ApplyConfigMembers(const Json::Value & commands,const Json::Value::Members & members) const217 void CommandLineInterface::ApplyConfigMembers(const Json::Value& commands,
218                                               const Json::Value::Members& members) const
219 {
220     for (Json::Value::Members::const_iterator iter = members.begin(); iter != members.end(); iter++)  {
221         string key = *iter;
222         if (!commands[key].isObject() || !commands[key].isMember("args") || !commands[key]["args"].isObject()) {
223             ELOG("Invalid JSON: %s", commands[key].asString().c_str());
224             continue;
225         }
226         std::unique_ptr<CommandLine> command =
227             CommandLineFactory::CreateCommandLine(key, CommandLine::CommandType::SET, commands[key]["args"], *socket);
228         ApplyConfigCommands(key, command);
229     }
230 }
231 
ApplyConfigCommands(const string & key,const unique_ptr<CommandLine> & command) const232 void CommandLineInterface::ApplyConfigCommands(const string& key,
233                                                const unique_ptr<CommandLine>& command) const
234 {
235     if (command == nullptr) {
236         ELOG("Unsupported configuration: %s", key.c_str());
237         return;
238     }
239 
240     if (command->IsArgValid()) {
241         command->RunSet();
242     }
243 }
244 
Init(string pipeBaseName)245 void CommandLineInterface::Init(string pipeBaseName)
246 {
247     CommandLineFactory::InitCommandMap();
248     InitPipe(pipeBaseName);
249 }
250 
ReadAndApplyConfig(string path) const251 void CommandLineInterface::ReadAndApplyConfig(string path) const
252 {
253     if (path.empty()) {
254         return;
255     }
256     string jsonStr = JsonReader::ReadFile(path);
257     Json::Value val = JsonReader::ParseJsonData(jsonStr);
258     ApplyConfig(val);
259 }
260 
CreatCommandToSendData(const string commandName,const Json::Value jsonData,const string type) const261 void CommandLineInterface::CreatCommandToSendData(const string commandName,
262                                                   const Json::Value jsonData,
263                                                   const string type) const
264 {
265     CommandLine::CommandType commandType = GetCommandType(type);
266     std::unique_ptr<CommandLine> commandLine =
267         CommandLineFactory::CreateCommandLine(commandName, commandType, jsonData, *socket);
268     if (commandLine == nullptr) {
269         ELOG("Unsupported CreatCommandToSendData: %s", commandName.c_str());
270         return;
271     }
272     commandLine->RunAndSendResultToManager();
273 }
274 
IsStaticIgnoreCmd(const string cmd) const275 bool CommandLineInterface::IsStaticIgnoreCmd(const string cmd) const
276 {
277     auto it = std::find(staticIgnoreCmd.begin(), staticIgnoreCmd.end(), cmd);
278     if (it != staticIgnoreCmd.end()) {
279         return false;
280     } else {
281         return true;
282     }
283 }
284