1 /*
2 * Copyright (c) 2022 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 #include "log_ioctl.h"
17
18 namespace OHOS {
19 namespace HiviewDFX {
20 using namespace std;
21
GetSocketName(IoctlCmd cmd)22 static string GetSocketName(IoctlCmd cmd)
23 {
24 if (cmd == IoctlCmd::OUTPUT_RQST) {
25 return OUTPUT_SOCKET_NAME;
26 } else {
27 return CONTROL_SOCKET_NAME;
28 }
29 }
30
LogIoctl(IoctlCmd rqst,IoctlCmd rsp)31 LogIoctl::LogIoctl(IoctlCmd rqst, IoctlCmd rsp) : socket(GetSocketName(rqst), 0)
32 {
33 socketInit = socket.Init();
34 if (socketInit != SeqPacketSocketResult::CREATE_AND_CONNECTED) {
35 PrintErrorno(errno);
36 }
37 rqstCmd = rqst;
38 rspCmd = rsp;
39 }
40
SendMsgHeader(IoctlCmd cmd,size_t len)41 int LogIoctl::SendMsgHeader(IoctlCmd cmd, size_t len)
42 {
43 MsgHeader header = {MSG_VER, static_cast<uint8_t>(cmd), 0, static_cast<uint16_t>(len)};
44 if (socketInit != SeqPacketSocketResult::CREATE_AND_CONNECTED) {
45 return ERR_SOCKET_CLIENT_INIT_FAIL;
46 }
47 int ret = socket.WriteAll(reinterpret_cast<char*>(&header), sizeof(MsgHeader));
48 if (ret < 0) {
49 PrintErrorno(errno);
50 return ERR_SOCKET_WRITE_MSG_HEADER_FAIL;
51 }
52 return RET_SUCCESS;
53 }
54
ReceiveMsgHeaer(MsgHeader & hdr)55 int LogIoctl::ReceiveMsgHeaer(MsgHeader& hdr)
56 {
57 int ret = socket.RecvMsg(reinterpret_cast<char *>(&hdr), sizeof(hdr));
58 if (ret <= 0) {
59 return ERR_SOCKET_RECEIVE_RSP;
60 }
61 return RET_SUCCESS;
62 }
63
GetRsp(char * rsp,int len)64 int LogIoctl::GetRsp(char* rsp, int len)
65 {
66 int ret = socket.RecvMsg(rsp, len);
67 if (ret <= 0) {
68 return ERR_SOCKET_RECEIVE_RSP;
69 }
70 return RET_SUCCESS;
71 }
72
ReceiveProcTagStats(StatsQueryRsp & rsp)73 int LogIoctl::ReceiveProcTagStats(StatsQueryRsp &rsp)
74 {
75 int i = 0;
76 for (i = 0; i < rsp.procNum; i++) {
77 ProcStatsRsp &pStats = rsp.pStats[i];
78 int msgSize = pStats.tagNum * sizeof(TagStatsRsp);
79 if (msgSize == 0) {
80 pStats.tStats = nullptr;
81 continue;
82 }
83 char* tmp = new (std::nothrow) char[msgSize];
84 if (tmp == nullptr) {
85 pStats.tStats = nullptr;
86 return RET_FAIL;
87 }
88 if (memset_s(tmp, msgSize, 0, msgSize) != 0) {
89 delete []tmp;
90 tmp = nullptr;
91 return RET_FAIL;
92 }
93 if (GetRsp(tmp, msgSize) != RET_SUCCESS) {
94 pStats.tStats = nullptr;
95 delete []tmp;
96 tmp = nullptr;
97 return RET_FAIL;
98 }
99 pStats.tStats = reinterpret_cast<TagStatsRsp*>(tmp);
100 }
101 return RET_SUCCESS;
102 }
103
ReceiveProcLogTypeStats(StatsQueryRsp & rsp)104 int LogIoctl::ReceiveProcLogTypeStats(StatsQueryRsp &rsp)
105 {
106 int i = 0;
107 for (i = 0; i < rsp.procNum; i++) {
108 ProcStatsRsp &pStats = rsp.pStats[i];
109 int msgSize = pStats.typeNum * sizeof(LogTypeStatsRsp);
110 if (msgSize == 0) {
111 continue;
112 }
113 char* tmp = new (std::nothrow) char[msgSize];
114 if (tmp == nullptr) {
115 pStats.lStats = nullptr;
116 return RET_FAIL;
117 }
118 if (memset_s(tmp, msgSize, 0, msgSize) != 0) {
119 delete []tmp;
120 tmp = nullptr;
121 return RET_FAIL;
122 }
123 if (GetRsp(tmp, msgSize) != RET_SUCCESS) {
124 pStats.lStats = nullptr;
125 delete []tmp;
126 tmp = nullptr;
127 return RET_FAIL;
128 }
129 pStats.lStats = reinterpret_cast<LogTypeStatsRsp*>(tmp);
130 }
131 return RET_SUCCESS;
132 }
133
ReceiveProcStats(StatsQueryRsp & rsp)134 int LogIoctl::ReceiveProcStats(StatsQueryRsp &rsp)
135 {
136 if (rsp.procNum == 0) {
137 return RET_FAIL;
138 }
139 int msgSize = rsp.procNum * sizeof(ProcStatsRsp);
140 if (msgSize == 0) {
141 return RET_SUCCESS;
142 }
143 char* tmp = new (std::nothrow) char[msgSize];
144 if (tmp == nullptr) {
145 rsp.pStats = nullptr;
146 return RET_FAIL;
147 }
148 if (memset_s(tmp, msgSize, 0, msgSize) != 0) {
149 delete []tmp;
150 tmp = nullptr;
151 return RET_FAIL;
152 }
153 if (GetRsp(tmp, msgSize) != RET_SUCCESS) {
154 rsp.pStats = nullptr;
155 delete []tmp;
156 tmp = nullptr;
157 return RET_FAIL;
158 }
159 rsp.pStats = reinterpret_cast<ProcStatsRsp*>(tmp);
160 return RET_SUCCESS;
161 }
162
ReceiveDomainTagStats(StatsQueryRsp & rsp)163 int LogIoctl::ReceiveDomainTagStats(StatsQueryRsp &rsp)
164 {
165 int i = 0;
166 for (i = 0; i < rsp.typeNum; i++) {
167 LogTypeDomainStatsRsp &ldStats = rsp.ldStats[i];
168 int j = 0;
169 for (j = 0; j < ldStats.domainNum; j++) {
170 DomainStatsRsp &dStats = ldStats.dStats[j];
171 int msgSize = dStats.tagNum * sizeof(TagStatsRsp);
172 if (msgSize == 0) {
173 dStats.tStats = nullptr;
174 continue;
175 }
176 char* tmp = new (std::nothrow) char[msgSize];
177 if (tmp == nullptr) {
178 dStats.tStats = nullptr;
179 return RET_FAIL;
180 }
181 if (memset_s(tmp, msgSize, 0, msgSize) != 0) {
182 delete []tmp;
183 tmp = nullptr;
184 return RET_FAIL;
185 }
186 if (GetRsp(tmp, msgSize) != RET_SUCCESS) {
187 dStats.tStats = nullptr;
188 delete []tmp;
189 tmp = nullptr;
190 return RET_FAIL;
191 }
192 dStats.tStats = reinterpret_cast<TagStatsRsp*>(tmp);
193 }
194 }
195 return RET_SUCCESS;
196 }
197
ReceiveDomainStats(StatsQueryRsp & rsp)198 int LogIoctl::ReceiveDomainStats(StatsQueryRsp &rsp)
199 {
200 int i = 0;
201 for (i = 0; i < rsp.typeNum; i++) {
202 LogTypeDomainStatsRsp &ldStats = rsp.ldStats[i];
203 int msgSize = ldStats.domainNum * sizeof(DomainStatsRsp);
204 if (msgSize == 0) {
205 continue;
206 }
207 char* tmp = new (std::nothrow) char[msgSize];
208 if (tmp == nullptr) {
209 ldStats.dStats = nullptr;
210 return RET_FAIL;
211 }
212 if (memset_s(tmp, msgSize, 0, msgSize) != 0) {
213 delete []tmp;
214 tmp = nullptr;
215 return RET_FAIL;
216 }
217 if (GetRsp(tmp, msgSize) != RET_SUCCESS) {
218 ldStats.dStats = nullptr;
219 delete []tmp;
220 tmp = nullptr;
221 return RET_FAIL;
222 }
223 ldStats.dStats = reinterpret_cast<DomainStatsRsp*>(tmp);
224 }
225 return RET_SUCCESS;
226 }
227
ReceiveLogTypeDomainStats(StatsQueryRsp & rsp)228 int LogIoctl::ReceiveLogTypeDomainStats(StatsQueryRsp &rsp)
229 {
230 if (rsp.typeNum == 0) {
231 return RET_FAIL;
232 }
233 int msgSize = rsp.typeNum * sizeof(LogTypeDomainStatsRsp);
234 if (msgSize == 0) {
235 return RET_SUCCESS;
236 }
237 char* tmp = new (std::nothrow) char[msgSize];
238 if (tmp == nullptr) {
239 rsp.ldStats = nullptr;
240 return RET_FAIL;
241 }
242 if (memset_s(tmp, msgSize, 0, msgSize) != 0) {
243 delete []tmp;
244 tmp = nullptr;
245 return RET_FAIL;
246 }
247 if (GetRsp(tmp, msgSize) != RET_SUCCESS) {
248 rsp.ldStats = nullptr;
249 delete []tmp;
250 tmp = nullptr;
251 return RET_FAIL;
252 }
253 rsp.ldStats = reinterpret_cast<LogTypeDomainStatsRsp*>(tmp);
254 return RET_SUCCESS;
255 }
256
DeleteLogStatsInfo(StatsQueryRsp & rsp)257 void LogIoctl::DeleteLogStatsInfo(StatsQueryRsp &rsp)
258 {
259 if (rsp.ldStats == nullptr) {
260 return;
261 }
262 int i = 0;
263 for (i = 0; i < rsp.typeNum; i++) {
264 LogTypeDomainStatsRsp &ldStats = rsp.ldStats[i];
265 if (ldStats.dStats == nullptr) {
266 break;
267 }
268 int j = 0;
269 for (j = 0; j < ldStats.domainNum; j++) {
270 DomainStatsRsp &dStats = ldStats.dStats[j];
271 if (dStats.tStats == nullptr) {
272 break;
273 }
274 delete []dStats.tStats;
275 dStats.tStats = nullptr;
276 }
277 delete []ldStats.dStats;
278 ldStats.dStats = nullptr;
279 }
280 delete []rsp.ldStats;
281 rsp.ldStats = nullptr;
282
283 if (rsp.pStats == nullptr) {
284 return;
285 }
286 for (i = 0; i < rsp.procNum; i++) {
287 ProcStatsRsp &pStats = rsp.pStats[i];
288 if (pStats.lStats == nullptr) {
289 return;
290 }
291 delete []pStats.lStats;
292 pStats.lStats = nullptr;
293 if (pStats.tStats == nullptr) {
294 return;
295 }
296 delete []pStats.tStats;
297 pStats.tStats = nullptr;
298 }
299 }
300
RequestOutput(const OutputRqst & rqst,std::function<int (const OutputRsp & rsp)> handle)301 int LogIoctl::RequestOutput(const OutputRqst& rqst, std::function<int(const OutputRsp& rsp)> handle)
302 {
303 // 0. Send reqeust message and process the response header
304 int ret = RequestMsgHead<OutputRqst, OutputRsp>(rqst);
305 if (ret != RET_SUCCESS) {
306 return ret;
307 }
308 // 1. process the response message
309 return ReceiveAndProcessOutputRsp(handle);
310 }
311
ReceiveAndProcessOutputRsp(std::function<int (const OutputRsp & rsp)> handle)312 int LogIoctl::ReceiveAndProcessOutputRsp(std::function<int(const OutputRsp& rsp)> handle)
313 {
314 vector<char> buffer(DEFAULT_RECV_BUF_LEN, 0);
315 OutputRsp *rsp = reinterpret_cast<OutputRsp *>(buffer.data());
316 while (true) {
317 int ret = GetRsp(reinterpret_cast<char*>(rsp), DEFAULT_RECV_BUF_LEN);
318 if (ret != RET_SUCCESS) {
319 return ret;
320 }
321 ret = handle(*rsp);
322 if (likely(ret == static_cast<int>(SUCCESS_CONTINUE))) {
323 continue;
324 }
325 return ret;
326 }
327 }
328
RequestStatsQuery(const StatsQueryRqst & rqst,std::function<int (const StatsQueryRsp & rsp)> handle)329 int LogIoctl::RequestStatsQuery(const StatsQueryRqst& rqst, std::function<int(const StatsQueryRsp& rsp)> handle)
330 {
331 // 0. Send reqeust message and process the response header
332 int ret = RequestMsgHead<StatsQueryRqst, StatsQueryRsp>(rqst);
333 if (ret != RET_SUCCESS) {
334 return ret;
335 }
336 // 1. process the response message
337 return ReceiveAndProcessStatsQueryRsp(handle);
338 }
339
ReceiveAndProcessStatsQueryRsp(std::function<int (const StatsQueryRsp & rsp)> handle)340 int LogIoctl::ReceiveAndProcessStatsQueryRsp(std::function<int(const StatsQueryRsp& rsp)> handle)
341 {
342 int ret;
343 StatsQueryRsp rsp = { 0 };
344 do {
345 ret = GetRsp(reinterpret_cast<char*>(&rsp), sizeof(rsp));
346 if (RET_SUCCESS != ret) {
347 break;
348 }
349 rsp.ldStats = nullptr;
350 rsp.pStats = nullptr;
351 ret = ReceiveLogTypeDomainStats(rsp);
352 if (RET_SUCCESS != ret) {
353 break;
354 }
355 ret = ReceiveDomainStats(rsp);
356 if (RET_SUCCESS != ret) {
357 break;
358 }
359 ret = ReceiveDomainTagStats(rsp);
360 if (RET_SUCCESS != ret) {
361 break;
362 }
363 ret = ReceiveProcStats(rsp);
364 if (RET_SUCCESS != ret) {
365 break;
366 }
367 ret = ReceiveProcLogTypeStats(rsp);
368 if (RET_SUCCESS != ret) {
369 break;
370 }
371 ret = ReceiveProcTagStats(rsp);
372 if (RET_SUCCESS != ret) {
373 break;
374 }
375 } while (0);
376 if (ret == RET_SUCCESS) {
377 ret = handle(rsp);
378 }
379 DeleteLogStatsInfo(rsp);
380 return ret;
381 }
382 } // namespace HiviewDFX
383 } // namespace OHOS