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