• 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 "ModelManager.h"
25 #include "PreviewerEngineLog.h"
26 #include "VirtualScreen.h"
27 #include "CommandParser.h"
28 
29 using namespace std;
30 
31 const string CommandLineInterface::COMMAND_VERSION = "1.0.1";
32 bool CommandLineInterface::isFirstWsSend = true;
33 bool CommandLineInterface::isPipeConnected = false;
CommandLineInterface()34 CommandLineInterface::CommandLineInterface() : socket(nullptr) {}
35 
~CommandLineInterface()36 CommandLineInterface::~CommandLineInterface() {}
37 
InitPipe(const string name)38 void CommandLineInterface::InitPipe(const string name)
39 {
40     if (socket != nullptr) {
41         socket.reset();
42         ELOG("CommandLineInterface::InitPipe socket is not null");
43     }
44 
45     socket = std::make_unique<LocalSocket>();
46     if (socket == nullptr) {
47         FLOG("CommandLineInterface::Connect socket memory allocation failed!");
48     }
49 
50     if (!socket->ConnectToServer(socket->GetCommandPipeName(name), LocalSocket::READ_WRITE)) {
51         FLOG("CommandLineInterface command pipe connect failed");
52     }
53     isPipeConnected  = true;
54 }
55 
GetInstance()56 CommandLineInterface& CommandLineInterface::GetInstance()
57 {
58     static CommandLineInterface instance; /* NOLINT */
59     return instance;
60 }
61 
SendJsonData(const Json2::Value & value)62 void CommandLineInterface::SendJsonData(const Json2::Value& value)
63 {
64     *(GetInstance().socket) << value.ToStyledString();
65 }
66 
SendJSHeapMemory(size_t total,size_t alloc,size_t peak) const67 void CommandLineInterface::SendJSHeapMemory(size_t total, size_t alloc, size_t peak) const
68 {
69     Json2::Value result = JsonReader::CreateObject();
70     result.Add("version", COMMAND_VERSION.c_str());
71     result.Add("property", "memoryUsage");
72     Json2::Value memory = JsonReader::CreateObject();
73     memory.Add("totalBytes", static_cast<double>(total));
74     memory.Add("allocBytes", static_cast<double>(alloc));
75     memory.Add("peakAllocBytes", static_cast<double>(peak));
76     result.Add("result", memory);
77     if (socket == nullptr) {
78         ELOG("CommandLineInterface::SendJSHeapMemory socket is null");
79         return;
80     }
81     *socket << result.ToStyledString();
82 }
83 
SendWebsocketStartupSignal() const84 void CommandLineInterface::SendWebsocketStartupSignal() const
85 {
86     Json2::Value result = JsonReader::CreateObject();
87     Json2::Value args = JsonReader::CreateObject();
88     result.Add("MessageType", "imageWebsocket");
89     args.Add("port", VirtualScreen::webSocketPort.c_str());
90     result.Add("args", args);
91     *socket << result.ToStyledString();
92 }
93 
ProcessCommand() const94 void CommandLineInterface::ProcessCommand() const
95 {
96     string message; /* NOLINT */
97     if (socket == nullptr) {
98         ELOG("CommandLineInterface::ProcessCommand socket is null");
99         return;
100     }
101     if (isPipeConnected && VirtualScreen::isWebSocketListening && isFirstWsSend) {
102         isFirstWsSend = false;
103         SendWebsocketStartupSignal();
104     }
105     *socket >> message;
106     if (message.empty()) {
107         return;
108     }
109 
110     ProcessCommandMessage(message);
111 }
112 
ProcessCommandMessage(std::string message) const113 void CommandLineInterface::ProcessCommandMessage(std::string message) const
114 {
115     ILOG("***cmd*** message:%s", message.c_str());
116     Json2::Value jsonData = JsonReader::ParseJsonData2(message);
117     std::string errors; /* NOLINT */
118     bool parsingSuccessful = jsonData.IsNull() ? false : true;
119     if (!parsingSuccessful) {
120         errors = JsonReader::GetErrorPtr();
121     }
122 
123     if (!ProcessCommandValidate(parsingSuccessful, jsonData, errors)) {
124         return;
125     }
126 
127     CommandLine::CommandType type = GetCommandType(jsonData["type"].AsString());
128     if (type == CommandLine::CommandType::INVALID) {
129         return;
130     }
131 
132     string command = jsonData["command"].AsString();
133     if (CommandParser::GetInstance().IsStaticCard() && IsStaticIgnoreCmd(command)) {
134         return;
135     }
136     Json2::Value val = jsonData["args"];
137     std::unique_ptr<CommandLine> commandLine =
138         CommandLineFactory::CreateCommandLine(command, type, val, *socket);
139     if (commandLine == nullptr) {
140         ELOG("Unsupported command");
141         return;
142     }
143     commandLine->CheckAndRun();
144 }
145 
ProcessCommandValidate(bool parsingSuccessful,const Json2::Value & jsonData,const std::string & errors) const146 bool CommandLineInterface::ProcessCommandValidate(bool parsingSuccessful,
147                                                   const Json2::Value& jsonData,
148                                                   const std::string& errors) const
149 {
150     if (!parsingSuccessful) {
151         ELOG("Failed to parse the JSON, errors: %s", errors.c_str());
152         return false;
153     }
154 
155     if (!jsonData.IsObject()) {
156         ELOG("Command is not a object!");
157         return false;
158     }
159 
160     if (!jsonData.IsMember("type") || !jsonData.IsMember("command") || !jsonData.IsMember("version")) {
161         ELOG("Command error!");
162         return false;
163     }
164 
165     if (!regex_match(jsonData["version"].AsString(), regex("(([0-9]|([1-9]([0-9]*))).){2}([0-9]|([1-9]([0-9]*)))"))) {
166         ELOG("Invalid command version!");
167         return false;
168     }
169     return true;
170 }
171 
GetCommandType(string name) const172 CommandLine::CommandType CommandLineInterface::GetCommandType(string name) const
173 {
174     CommandLine::CommandType type = CommandLine::CommandType::INVALID;
175     if (name == "set") {
176         type = CommandLine::CommandType::SET;
177     } else if (name == "get") {
178         type = CommandLine::CommandType::GET;
179     } else if (name == "action") {
180         type = CommandLine::CommandType::ACTION;
181     } else {
182         ELOG("Command type invalid!");
183     }
184     return type;
185 }
186 
ApplyConfig(const Json2::Value & val) const187 void CommandLineInterface::ApplyConfig(const Json2::Value& val) const
188 {
189     const string set("setting");
190     if (val.IsMember(set.c_str())) {
191         Json2::Value versionMembers = val[set];
192         if (!versionMembers.IsObject()) {
193             return;
194         }
195 
196         Json2::Value::Members versions = versionMembers.GetMemberNames();
197 
198         for (Json2::Value::Members::iterator viter = versions.begin(); viter != versions.end(); viter++) {
199             string version = *viter;
200             Json2::Value commands = versionMembers[version];
201             if (!commands.IsObject()) {
202                 continue;
203             }
204             Json2::Value::Members members = commands.GetMemberNames();
205 
206             ApplyConfigMembers(commands, members);
207         }
208     }
209 }
210 
ApplyConfigMembers(const Json2::Value & commands,const Json2::Value::Members & members) const211 void CommandLineInterface::ApplyConfigMembers(const Json2::Value& commands,
212                                               const Json2::Value::Members& members) const
213 {
214     for (Json2::Value::Members::const_iterator iter = members.begin(); iter != members.end(); iter++)  {
215         string key = *iter;
216         if (!commands[key].IsObject() || !commands[key].IsMember("args") || !commands[key]["args"].IsObject()) {
217             ELOG("Invalid JSON: %s", commands[key].AsString().c_str());
218             continue;
219         }
220         Json2::Value val = commands[key]["args"];
221         std::unique_ptr<CommandLine> command =
222             CommandLineFactory::CreateCommandLine(key, CommandLine::CommandType::SET, val, *socket);
223         ApplyConfigCommands(key, command);
224     }
225 }
226 
ApplyConfigCommands(const string & key,const unique_ptr<CommandLine> & command) const227 void CommandLineInterface::ApplyConfigCommands(const string& key,
228                                                const unique_ptr<CommandLine>& command) const
229 {
230     if (command == nullptr) {
231         ELOG("Unsupported configuration: %s", key.c_str());
232         return;
233     }
234 
235     if (command->IsArgValid()) {
236         command->RunSet();
237     }
238 }
239 
Init(string pipeBaseName)240 void CommandLineInterface::Init(string pipeBaseName)
241 {
242     CommandLineFactory::InitCommandMap();
243     InitPipe(pipeBaseName);
244 }
245 
ReadAndApplyConfig(string path) const246 void CommandLineInterface::ReadAndApplyConfig(string path) const
247 {
248     if (path.empty()) {
249         return;
250     }
251     string jsonStr = JsonReader::ReadFile(path);
252     Json2::Value val = JsonReader::ParseJsonData2(jsonStr);
253     ApplyConfig(val);
254 }
255 
CreatCommandToSendData(const string commandName,const Json2::Value & jsonData,const string type) const256 void CommandLineInterface::CreatCommandToSendData(const string commandName,
257                                                   const Json2::Value& jsonData,
258                                                   const string type) const
259 {
260     CommandLine::CommandType commandType = GetCommandType(type);
261     std::unique_ptr<CommandLine> commandLine =
262         CommandLineFactory::CreateCommandLine(commandName, commandType, jsonData, *socket);
263     if (commandLine == nullptr) {
264         ELOG("Unsupported CreatCommandToSendData: %s", commandName.c_str());
265         return;
266     }
267     commandLine->RunAndSendResultToManager();
268 }
269 
IsStaticIgnoreCmd(const string cmd) const270 bool CommandLineInterface::IsStaticIgnoreCmd(const string cmd) const
271 {
272     auto it = std::find(staticIgnoreCmd.begin(), staticIgnoreCmd.end(), cmd);
273     if (it != staticIgnoreCmd.end()) {
274         return false;
275     } else {
276         return true;
277     }
278 }
279