1 /*
2  * Copyright (c) 2021 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 #include <algorithm>
16 #include <array>
17 #include <chrono>
18 #include <cstdio>
19 #include <cstring>
20 #include <ctime>
21 #include <fcntl.h>
22 #include <iostream>
23 #include <memory>
24 #include <optional>
25 #include <regex>
26 #include <sstream>
27 #include <sys/mman.h>
28 #include <sys/prctl.h>
29 #include <sys/stat.h>
30 #include <thread>
31 #include <unistd.h>
32 #include <dirent.h>
33 
34 #include <securec.h>
35 #include <hilog/log.h>
36 #include <hilog_common.h>
37 #include <log_utils.h>
38 #include <properties.h>
39 
40 #include "log_data.h"
41 #include "log_buffer.h"
42 #include "log_kmsg.h"
43 
44 #include "service_controller.h"
45 
46 namespace OHOS {
47 namespace HiviewDFX {
48 using namespace std;
49 static const string LOG_PERSISTER_DIR = HILOG_FILE_DIR;
50 static constexpr uint16_t DEFAULT_LOG_TYPES = ((0b01 << LOG_APP) | (0b01 << LOG_CORE)
51                                               | (0b01 << LOG_INIT) | (0b01 << LOG_ONLY_PRERELEASE));
52 static constexpr uint16_t DEFAULT_REMOVE_LOG_TYPES = ((0b01 << LOG_APP) | (0b01 << LOG_CORE)
53                                                      | (0b01 << LOG_ONLY_PRERELEASE));
54 static constexpr uint32_t DEFAULT_PERSIST_FILE_NUM = 10;
55 static constexpr uint32_t DEFAULT_PERSIST_FILE_SIZE = (4 * 1024 * 1024);
56 static constexpr uint32_t DEFAULT_PERSIST_NORMAL_JOB_ID = 1;
57 static constexpr uint32_t DEFAULT_PERSIST_KMSG_JOB_ID = 2;
58 static constexpr int INFO_SUFFIX = 5;
59 static const uid_t SHELL_UID = 2000;
60 static const uid_t ROOT_UID = 0;
61 static const uid_t LOGD_UID = 1036;
62 static const uid_t HIVIEW_UID = 1201;
63 static const uid_t PROFILER_UID = 3063;
64 
IsKmsg(uint16_t types)65 inline bool IsKmsg(uint16_t types)
66 {
67     return types == (0b01 << LOG_KMSG);
68 }
69 
ServiceController(std::unique_ptr<Socket> communicationSocket,LogCollector & collector,HilogBuffer & hilogBuffer,HilogBuffer & kmsgBuffer)70 ServiceController::ServiceController(std::unique_ptr<Socket> communicationSocket,
71     LogCollector& collector, HilogBuffer& hilogBuffer, HilogBuffer& kmsgBuffer)
72     : m_communicationSocket(std::move(communicationSocket)),
73     m_logCollector(collector),
74     m_hilogBuffer(hilogBuffer),
75     m_kmsgBuffer(kmsgBuffer)
76 {
77     m_hilogBufferReader = m_hilogBuffer.CreateBufReader([this]() { NotifyForNewData(); });
78     m_kmsgBufferReader = m_kmsgBuffer.CreateBufReader([this]() { NotifyForNewData(); });
79 }
80 
~ServiceController()81 ServiceController::~ServiceController()
82 {
83     m_hilogBuffer.RemoveBufReader(m_hilogBufferReader);
84     m_kmsgBuffer.RemoveBufReader(m_kmsgBufferReader);
85     m_notifyNewDataCv.notify_all();
86 }
87 
IsValidFileName(const std::string & strFileName)88 inline bool IsValidFileName(const std::string& strFileName)
89 {
90     // File name shouldn't contain "[\\/:*?\"<>|]"
91     std::regex regExpress("[\\/:*?\"<>|]");
92     bool bValid = !std::regex_search(strFileName, regExpress);
93     return bValid;
94 }
95 
GetMsgHeader(MsgHeader & hdr)96 int ServiceController::GetMsgHeader(MsgHeader& hdr)
97 {
98     if (!m_communicationSocket) {
99         std::cerr << " Invalid socket handler!" << std::endl;
100         return RET_FAIL;
101     }
102     int ret = m_communicationSocket->Read(reinterpret_cast<char *>(&hdr), sizeof(MsgHeader));
103     if (ret < static_cast<int>(sizeof(MsgHeader))) {
104         std::cerr << "Read MsgHeader error!" << std::endl;
105         return RET_FAIL;
106     }
107     return RET_SUCCESS;
108 }
109 
GetRqst(const MsgHeader & hdr,char * rqst,int expectedLen)110 int ServiceController::GetRqst(const MsgHeader& hdr, char* rqst, int expectedLen)
111 {
112     if (hdr.len !=  expectedLen) {
113         std::cout << "Invalid MsgHeader! hdr.len:" << hdr.len << ", expectedLen:" << expectedLen << endl;
114         return RET_FAIL;
115     }
116     int ret = m_communicationSocket->Read(rqst, hdr.len);
117     if (ret <= 0) {
118         std::cout << "Read socket error! " << ret << endl;
119         return RET_FAIL;
120     }
121     return RET_SUCCESS;
122 }
123 
WriteRspHeader(IoctlCmd cmd,size_t len)124 void ServiceController::WriteRspHeader(IoctlCmd cmd, size_t len)
125 {
126     MsgHeader header = {MSG_VER, static_cast<uint8_t>(cmd), 0, static_cast<uint16_t>(len)};
127     (void)m_communicationSocket->Write(reinterpret_cast<char*>(&header), sizeof(MsgHeader));
128     return;
129 }
130 
WriteErrorRsp(int code)131 void ServiceController::WriteErrorRsp(int code)
132 {
133     MsgHeader header = {MSG_VER, static_cast<uint8_t>(IoctlCmd::RSP_ERROR), code, 0};
134     (void)m_communicationSocket->Write(reinterpret_cast<char*>(&header), sizeof(MsgHeader));
135     return;
136 }
137 
WriteQueryResponse(OptCRef<HilogData> pData)138 int ServiceController::WriteQueryResponse(OptCRef<HilogData> pData)
139 {
140     OutputRsp rsp;
141     if (pData == std::nullopt) {
142         rsp.end = true; // tell client it's the last messsage
143         return m_communicationSocket->Write(reinterpret_cast<char*>(&rsp), sizeof(rsp));
144     }
145     const HilogData& data = pData->get();
146     rsp.len = data.len; /* data len, equals tagLen plus content length, include '\0' */
147     rsp.level = data.level;
148     rsp.type = data.type;
149     rsp.tagLen = data.tagLen; /* include '\0' */
150     rsp.pid = data.pid;
151     rsp.tid = data.tid;
152     rsp.domain = data.domain;
153     rsp.tv_sec = data.tv_sec;
154     rsp.tv_nsec = data.tv_nsec;
155     rsp.mono_sec = data.mono_sec;
156     rsp.end = false;
157     static const int vec_num = 2;
158     iovec vec[vec_num];
159     vec[0].iov_base = &rsp;
160     vec[0].iov_len = sizeof(OutputRsp);
161     vec[1].iov_base = data.tag;
162     vec[1].iov_len = data.len;
163     return m_communicationSocket->WriteV(vec, vec_num);
164 }
165 
StatsEntry2StatsRsp(const StatsEntry & entry,StatsRsp & rsp)166 static void StatsEntry2StatsRsp(const StatsEntry &entry, StatsRsp &rsp)
167 {
168     // can't use std::copy, because StatsRsp is a packet struct
169     int i = 0;
170     for (i = 0; i < LevelNum; i++) {
171         rsp.lines[i] = entry.lines[i];
172         rsp.len[i] = entry.len[i];
173     }
174     rsp.dropped = entry.dropped;
175     rsp.freqMax = entry.GetFreqMax();
176     rsp.freqMaxSec = entry.realTimeFreqMax.tv_sec;
177     rsp.freqMaxNsec = entry.realTimeFreqMax.tv_nsec;
178     rsp.throughputMax = entry.GetThroughputMax();
179     rsp.tpMaxSec = entry.realTimeThroughputMax.tv_sec;
180     rsp.tpMaxNsec = entry.realTimeThroughputMax.tv_nsec;
181 }
182 
SendOverallStats(const LogStats & stats)183 void ServiceController::SendOverallStats(const LogStats& stats)
184 {
185     StatsQueryRsp rsp;
186     const LogTypeDomainTable& ldTable = stats.GetDomainTable();
187     const PidTable& pTable = stats.GetPidTable();
188     const LogTimeStamp tsBegin = stats.GetBeginTs();
189     rsp.tsBeginSec = tsBegin.tv_sec;
190     rsp.tsBeginNsec = tsBegin.tv_nsec;
191     const LogTimeStamp monoBegin = stats.GetBeginMono();
192     LogTimeStamp monoNow(CLOCK_MONOTONIC);
193     monoNow -= monoBegin;
194     rsp.durationSec = monoNow.tv_sec;
195     rsp.durationNsec = monoNow.tv_nsec;
196     stats.GetTotalLines(rsp.totalLines);
197     stats.GetTotalLens(rsp.totalLens);
198     rsp.typeNum = 0;
199     for (const DomainTable &dt : ldTable) {
200         if (dt.size() == 0) {
201             continue;
202         }
203         rsp.typeNum++;
204     }
205     rsp.ldStats = nullptr;
206     rsp.procNum = pTable.size();
207     rsp.pStats = nullptr;
208     m_communicationSocket->Write(reinterpret_cast<char *>(&rsp), sizeof(StatsQueryRsp));
209 }
210 
SendLogTypeDomainStats(const LogStats & stats)211 void ServiceController::SendLogTypeDomainStats(const LogStats& stats)
212 {
213     const LogTypeDomainTable& ldTable = stats.GetDomainTable();
214     int typeNum = 0;
215     for (const DomainTable &dt : ldTable) {
216         if (dt.size() == 0) {
217             continue;
218         }
219         typeNum++;
220     }
221     int msgSize = typeNum * sizeof(LogTypeDomainStatsRsp);
222     if (msgSize == 0) {
223         return;
224     }
225     char* tmp = new (std::nothrow) char[msgSize];
226     if (tmp == nullptr) {
227         return;
228     }
229     if (memset_s(tmp, msgSize, 0, msgSize) != 0) {
230         delete []tmp;
231         tmp = nullptr;
232         return;
233     }
234     LogTypeDomainStatsRsp *ldStats = reinterpret_cast<LogTypeDomainStatsRsp *>(tmp);
235     int i = 0;
236     int j = 0;
237     for (const DomainTable &dt : ldTable) {
238         j++;
239         if (dt.size() == 0) {
240             continue;
241         }
242         ldStats[i].type = (j - 1);
243         ldStats[i].domainNum = dt.size();
244         i++;
245     }
246     m_communicationSocket->Write(tmp, msgSize);
247     delete []tmp;
248     tmp = nullptr;
249 }
250 
SendDomainStats(const LogStats & stats)251 void ServiceController::SendDomainStats(const LogStats& stats)
252 {
253     const LogTypeDomainTable& ldTable = stats.GetDomainTable();
254     for (const DomainTable &dt : ldTable) {
255         if (dt.size() == 0) {
256             continue;
257         }
258         int msgSize = dt.size() * sizeof(DomainStatsRsp);
259         char *tmp = new (std::nothrow) char[msgSize];
260         if (tmp == nullptr) {
261             return;
262         }
263         if (memset_s(tmp, msgSize, 0, msgSize) != 0) {
264             delete []tmp;
265             tmp = nullptr;
266             return;
267         }
268         DomainStatsRsp *dStats = reinterpret_cast<DomainStatsRsp *>(tmp);
269         int i = 0;
270         for (auto &it : dt) {
271             dStats[i].domain = it.first;
272             if (!stats.IsTagEnable()) {
273                 dStats[i].tagNum = 0;
274             } else {
275                 dStats[i].tagNum = it.second.tagStats.size();
276             }
277             if (dStats[i].tagNum == 0) {
278                 dStats[i].tStats = nullptr;
279             }
280             StatsEntry2StatsRsp(it.second.stats, dStats[i].stats);
281             i++;
282         }
283         m_communicationSocket->Write(tmp, msgSize);
284         delete []tmp;
285         tmp = nullptr;
286     }
287 }
288 
SendDomainTagStats(const LogStats & stats)289 void ServiceController::SendDomainTagStats(const LogStats& stats)
290 {
291     const LogTypeDomainTable& ldTable = stats.GetDomainTable();
292     for (const DomainTable &dt : ldTable) {
293         if (dt.size() == 0) {
294             continue;
295         }
296         for (auto &it : dt) {
297             SendTagStats(it.second.tagStats);
298         }
299     }
300 }
301 
SendProcStats(const LogStats & stats)302 void ServiceController::SendProcStats(const LogStats& stats)
303 {
304     const PidTable& pTable = stats.GetPidTable();
305     int msgSize =  pTable.size() * sizeof(ProcStatsRsp);
306     if (msgSize == 0) {
307         return;
308     }
309     char* tmp = new (std::nothrow) char[msgSize];
310     if (tmp == nullptr) {
311         return;
312     }
313     if (memset_s(tmp, msgSize, 0, msgSize) != 0) {
314         delete []tmp;
315         tmp = nullptr;
316         return;
317     }
318     ProcStatsRsp *pStats = reinterpret_cast<ProcStatsRsp *>(tmp);
319     int i = 0;
320     for (auto &it : pTable) {
321         ProcStatsRsp &procStats = pStats[i];
322         i++;
323         procStats.pid = it.first;
324         if (strncpy_s(procStats.name, MAX_PROC_NAME_LEN, it.second.name.c_str(), MAX_PROC_NAME_LEN - 1) != 0) {
325             continue;
326         }
327         StatsEntry2StatsRsp(it.second.statsAll, procStats.stats);
328         procStats.typeNum = 0;
329         for (auto &itt : it.second.stats) {
330             if (itt.GetTotalLines() == 0) {
331                 continue;
332             }
333             procStats.typeNum++;
334         }
335         if (!stats.IsTagEnable()) {
336             procStats.tagNum = 0;
337         } else {
338             procStats.tagNum = it.second.tagStats.size();
339         }
340         if (procStats.tagNum == 0) {
341             procStats.tStats = nullptr;
342         }
343     }
344     m_communicationSocket->Write(tmp, msgSize);
345     delete []tmp;
346     tmp = nullptr;
347 }
348 
SendProcLogTypeStats(const LogStats & stats)349 void ServiceController::SendProcLogTypeStats(const LogStats& stats)
350 {
351     const PidTable& pTable = stats.GetPidTable();
352     for (auto &it : pTable) {
353         int typeNum = 0;
354         for (auto &itt : it.second.stats) {
355             if (itt.GetTotalLines() == 0) {
356                 continue;
357             }
358             typeNum++;
359         }
360         int msgSize =  typeNum * sizeof(LogTypeStatsRsp);
361         if (msgSize == 0) {
362             return;
363         }
364         char* tmp = new (std::nothrow) char[msgSize];
365         if (tmp == nullptr) {
366             return;
367         }
368         if (memset_s(tmp, msgSize, 0, msgSize) != 0) {
369             delete []tmp;
370             tmp = nullptr;
371             return;
372         }
373         LogTypeStatsRsp *lStats = reinterpret_cast<LogTypeStatsRsp *>(tmp);
374         int i = 0;
375         int j = 0;
376         for (auto &itt : it.second.stats) {
377             j++;
378             if (itt.GetTotalLines() == 0) {
379                 continue;
380             }
381             LogTypeStatsRsp &logTypeStats = lStats[i];
382             logTypeStats.type = (j - 1);
383             StatsEntry2StatsRsp(itt, logTypeStats.stats);
384             i++;
385         }
386         m_communicationSocket->Write(tmp, msgSize);
387         delete []tmp;
388         tmp = nullptr;
389     }
390 }
391 
SendProcTagStats(const LogStats & stats)392 void ServiceController::SendProcTagStats(const LogStats& stats)
393 {
394     const PidTable& pTable = stats.GetPidTable();
395     for (auto &it : pTable) {
396         SendTagStats(it.second.tagStats);
397     }
398 }
399 
SendTagStats(const TagTable & tagTable)400 void ServiceController::SendTagStats(const TagTable &tagTable)
401 {
402     int msgSize =  tagTable.size() * sizeof(TagStatsRsp);
403     if (msgSize == 0) {
404         return;
405     }
406     char* tmp = new (std::nothrow) char[msgSize];
407     if (tmp == nullptr) {
408         return;
409     }
410     if (memset_s(tmp, msgSize, 0, msgSize) != 0) {
411         delete []tmp;
412         tmp = nullptr;
413         return;
414     }
415     TagStatsRsp *tStats = reinterpret_cast<TagStatsRsp *>(tmp);
416     int i = 0;
417     for (auto &itt : tagTable) {
418         TagStatsRsp &tagStats = tStats[i];
419         if (strncpy_s(tagStats.tag, MAX_TAG_LEN, itt.first.c_str(), MAX_TAG_LEN - 1) != 0) {
420             continue;
421         }
422         i++;
423         StatsEntry2StatsRsp(itt.second, tagStats.stats);
424     }
425     m_communicationSocket->Write(tmp, msgSize);
426     delete []tmp;
427     tmp = nullptr;
428 }
429 
CheckOutputRqst(const OutputRqst & rqst)430 int ServiceController::CheckOutputRqst(const OutputRqst& rqst)
431 {
432     if (((rqst.types & (0b01 << LOG_KMSG)) != 0) && (GetBitsCount(rqst.types) > 1)) {
433         return ERR_QUERY_TYPE_INVALID;
434     }
435     if (rqst.domainCount > MAX_DOMAINS) {
436         return ERR_TOO_MANY_DOMAINS;
437     }
438     if (rqst.tagCount > MAX_TAGS) {
439         return ERR_TOO_MANY_TAGS;
440     }
441     if (rqst.pidCount > MAX_PIDS) {
442         return ERR_TOO_MANY_PIDS;
443     }
444     // Check Uid permission
445     uid_t uid = m_communicationSocket->GetUid();
446     if (uid != ROOT_UID && uid != SHELL_UID && rqst.pidCount > 0 && uid != HIVIEW_UID && uid != PROFILER_UID) {
447         return ERR_NO_PID_PERMISSION;
448     }
449     return RET_SUCCESS;
450 }
451 
LogFilterFromOutputRqst(const OutputRqst & rqst,LogFilter & filter)452 void ServiceController::LogFilterFromOutputRqst(const OutputRqst& rqst, LogFilter& filter)
453 {
454     if (rqst.types == 0) {
455         filter.types = DEFAULT_LOG_TYPES;
456     } else {
457         filter.types = rqst.types;
458     }
459     if (rqst.levels == 0) {
460         filter.levels = ~rqst.levels; // 0 means all
461     } else {
462         filter.levels = rqst.levels;
463     }
464     int i;
465     filter.blackDomain = rqst.blackDomain;
466     filter.domainCount = rqst.domainCount;
467     for (i = 0; i < rqst.domainCount; i++) {
468         filter.domains[i] = rqst.domains[i];
469     }
470     filter.blackTag = rqst.blackTag;
471     filter.tagCount = rqst.tagCount;
472     for (i = 0; i < rqst.tagCount; i++) {
473         (void)strncpy_s(filter.tags[i], MAX_TAG_LEN, rqst.tags[i], MAX_TAG_LEN - 1);
474     }
475     filter.blackPid = rqst.blackPid;
476     filter.pidCount = rqst.pidCount;
477     for (i = 0; i < rqst.pidCount; i++) {
478         filter.pids[i] = rqst.pids[i];
479     }
480     (void)strncpy_s(filter.regex, MAX_REGEX_STR_LEN, rqst.regex, MAX_REGEX_STR_LEN - 1);
481     filter.Print();
482     // Permission check
483     uid_t uid = m_communicationSocket->GetUid();
484     uint32_t pid = static_cast<uint32_t>(m_communicationSocket->GetPid());
485     if (uid != ROOT_UID && uid != SHELL_UID && uid != LOGD_UID && uid != HIVIEW_UID && uid != PROFILER_UID) {
486         filter.blackPid = false;
487         filter.pidCount = 1;
488         filter.pids[0] = pid;
489         uint32_t ppid = GetPPidByPid(pid);
490         if (ppid > 0) {
491             filter.pidCount++;
492             filter.pids[1] = ppid;
493         }
494     }
495 }
496 
HandleOutputRqst(const OutputRqst & rqst)497 void ServiceController::HandleOutputRqst(const OutputRqst &rqst)
498 {
499     // check OutputRqst
500     int ret = CheckOutputRqst(rqst);
501     if (ret != RET_SUCCESS) {
502         WriteErrorRsp(ret);
503         return;
504     }
505     LogFilter filter = {0};
506     LogFilterFromOutputRqst(rqst, filter);
507     int lines = rqst.headLines ? rqst.headLines : rqst.tailLines;
508     int tailCount = rqst.tailLines;
509     int linesCountDown = lines;
510 
511     bool isKmsg = IsKmsg(filter.types);
512     HilogBuffer& logBuffer = isKmsg ? m_kmsgBuffer : m_hilogBuffer;
513     HilogBuffer::ReaderId readId = isKmsg ? m_kmsgBufferReader : m_hilogBufferReader;
514 
515     WriteRspHeader(IoctlCmd::OUTPUT_RSP, sizeof(OutputRsp));
516     for (;;) {
517         std::optional<HilogData> data = logBuffer.Query(filter, readId, tailCount);
518         if (!data.has_value()) {
519             if (rqst.noBlock) {
520                 // reach the end of buffer and don't block
521                 (void)WriteQueryResponse(std::nullopt);
522                 break;
523             }
524             std::unique_lock<decltype(m_notifyNewDataMtx)> ul(m_notifyNewDataMtx);
525             m_notifyNewDataCv.wait(ul);
526             continue;
527         }
528         int ret = WriteQueryResponse(data.value());
529         if (ret < 0) { // write socket failed, it means that client has disconnected
530             std::cerr << "Client disconnect" << std::endl;
531             break;
532         }
533         if (lines && (--linesCountDown) <= 0) {
534             (void)WriteQueryResponse(std::nullopt);
535             sleep(1); // let client receive all messages and exit gracefully
536             break;
537         }
538     }
539 }
540 
CheckPersistStartRqst(const PersistStartRqst & rqst)541 int ServiceController::CheckPersistStartRqst(const PersistStartRqst &rqst)
542 {
543     // check OutputFilter
544     int ret = CheckOutputRqst(rqst.outputFilter);
545     if (ret != RET_SUCCESS) {
546         return ret;
547     }
548     if (rqst.jobId && (rqst.jobId < JOB_ID_MIN || rqst.jobId == JOB_ID_MAX)) {
549         return ERR_LOG_PERSIST_JOBID_INVALID;
550     }
551     if (rqst.fileSize && (rqst.fileSize < MIN_LOG_FILE_SIZE || rqst.fileSize > MAX_LOG_FILE_SIZE)) {
552         return ERR_LOG_PERSIST_FILE_SIZE_INVALID;
553     }
554     if (rqst.fileName[0] && IsValidFileName(rqst.fileName) == false) {
555         return ERR_LOG_PERSIST_FILE_NAME_INVALID;
556     }
557     if (rqst.fileNum && (rqst.fileNum > MAX_LOG_FILE_NUM || rqst.fileNum < MIN_LOG_FILE_NUM)) {
558         return ERR_LOG_FILE_NUM_INVALID;
559     }
560     return RET_SUCCESS;
561 }
562 
PersistStartRqst2Msg(const PersistStartRqst & rqst,LogPersistStartMsg & msg)563 void ServiceController::PersistStartRqst2Msg(const PersistStartRqst &rqst, LogPersistStartMsg &msg)
564 {
565     LogFilterFromOutputRqst(rqst.outputFilter, msg.filter);
566     bool isKmsgType = rqst.outputFilter.types == (0b01 << LOG_KMSG);
567     msg.compressAlg = LogCompress::Str2CompressType(rqst.stream);
568     msg.fileSize = rqst.fileSize == 0 ? DEFAULT_PERSIST_FILE_SIZE : rqst.fileSize;
569     msg.fileNum = rqst.fileNum == 0 ? DEFAULT_PERSIST_FILE_NUM : rqst.fileNum;
570     msg.jobId = rqst.jobId;
571     if (msg.jobId == 0) {
572         msg.jobId = isKmsgType ? DEFAULT_PERSIST_KMSG_JOB_ID : DEFAULT_PERSIST_NORMAL_JOB_ID;
573     }
574     string fileName = rqst.fileName;
575     if (fileName == "") {
576         fileName = (isKmsgType ? "hilog_kmsg" : "hilog");
577     }
578     string filePath = LOG_PERSISTER_DIR + fileName;
579     (void)strncpy_s(msg.filePath, FILE_PATH_MAX_LEN, filePath.c_str(), filePath.length());
580 }
581 
StartPersistStoreJob(const PersistRecoveryInfo & info,HilogBuffer & hilogBuffer,bool restore)582 int StartPersistStoreJob(const PersistRecoveryInfo& info, HilogBuffer& hilogBuffer, bool restore)
583 {
584     std::shared_ptr<LogPersister> persister = LogPersister::CreateLogPersister(hilogBuffer);
585     if (persister == nullptr) {
586         return RET_FAIL;
587     }
588     int ret = persister->Init(info, restore);
589     if (ret != RET_SUCCESS) {
590         return ret;
591     }
592     persister->Start();
593     return RET_SUCCESS;
594 }
595 
HandlePersistStartRqst(const PersistStartRqst & rqst)596 void ServiceController::HandlePersistStartRqst(const PersistStartRqst &rqst)
597 {
598     int ret = WaitingToDo(WAITING_DATA_MS, HILOG_FILE_DIR, [](const string &path) {
599         struct stat s;
600         if (stat(path.c_str(), &s) != -1) {
601             return RET_SUCCESS;
602         }
603         return RET_FAIL;
604     });
605     if (ret != RET_SUCCESS) {
606         WriteErrorRsp(ERR_LOG_PERSIST_FILE_PATH_INVALID);
607         return;
608     }
609     ret = CheckPersistStartRqst(rqst);
610     if (ret != RET_SUCCESS) {
611         WriteErrorRsp(ret);
612         return;
613     }
614     list<LogPersistQueryResult> resultList;
615     LogPersister::Query(resultList);
616     if (resultList.size() >= MAX_JOBS) {
617         WriteErrorRsp(ERR_TOO_MANY_JOBS);
618         return;
619     }
620     LogPersistStartMsg msg = { 0 };
621     PersistStartRqst2Msg(rqst, msg);
622     PersistRecoveryInfo info = {0, msg};
623     HilogBuffer& logBuffer = IsKmsg(rqst.outputFilter.types) ? m_kmsgBuffer : m_hilogBuffer;
624     ret = StartPersistStoreJob(info, logBuffer, false);
625     if (ret != RET_SUCCESS) {
626         WriteErrorRsp(ret);
627         return;
628     }
629     PersistStartRsp rsp = { msg.jobId };
630     WriteRspHeader(IoctlCmd::PERSIST_START_RSP, sizeof(rsp));
631     (void)m_communicationSocket->Write(reinterpret_cast<char*>(&rsp), sizeof(rsp));
632 }
633 
HandlePersistStopRqst(const PersistStopRqst & rqst)634 void ServiceController::HandlePersistStopRqst(const PersistStopRqst &rqst)
635 {
636     PersistStopRsp rsp = { 0 };
637     list<LogPersistQueryResult> resultList;
638     LogPersister::Query(resultList);
639     if (rqst.jobId == 0 && resultList.empty()) {
640         WriteErrorRsp(ERR_PERSIST_TASK_EMPTY);
641         return;
642     }
643     for (auto it = resultList.begin(); it != resultList.end() && rsp.jobNum < MAX_JOBS; ++it) {
644         uint32_t jobId = it->jobId;
645         if (rqst.jobId == 0 || rqst.jobId == jobId) {
646             (void)LogPersister::Kill(jobId);
647             rsp.jobId[rsp.jobNum] = jobId;
648             rsp.jobNum++;
649         }
650     }
651     if (rsp.jobNum == 0) {
652         WriteErrorRsp(ERR_JOBID_NOT_EXSIST);
653         return;
654     }
655     WriteRspHeader(IoctlCmd::PERSIST_STOP_RSP, sizeof(rsp));
656     (void)m_communicationSocket->Write(reinterpret_cast<char*>(&rsp), sizeof(rsp));
657 }
658 
HandlePersistQueryRqst(const PersistQueryRqst & rqst)659 void ServiceController::HandlePersistQueryRqst(const PersistQueryRqst& rqst)
660 {
661     list<LogPersistQueryResult> resultList;
662     LogPersister::Query(resultList);
663     if (resultList.size() == 0) {
664         WriteErrorRsp(ERR_NO_RUNNING_TASK);
665         return;
666     }
667     PersistQueryRsp rsp = { 0 };
668     for (auto it = resultList.begin(); it != resultList.end() && rsp.jobNum < MAX_JOBS; ++it) {
669         PersistTaskInfo &task = rsp.taskInfo[rsp.jobNum];
670         task.jobId = it->jobId;
671         task.fileNum = it->fileNum;
672         task.fileSize = it->fileSize;
673         task.outputFilter.types = it->logType;
674         (void)strncpy_s(task.fileName, MAX_FILE_NAME_LEN, it->filePath, MAX_FILE_NAME_LEN - 1);
675         (void)strncpy_s(task.stream, MAX_STREAM_NAME_LEN,
676                         LogCompress::CompressType2Str(it->compressAlg).c_str(), MAX_STREAM_NAME_LEN - 1);
677         rsp.jobNum++;
678     }
679     WriteRspHeader(IoctlCmd::PERSIST_QUERY_RSP, sizeof(rsp));
680     (void)m_communicationSocket->Write(reinterpret_cast<char*>(&rsp), sizeof(rsp));
681 }
682 
HandlePersistRefreshRqst(const PersistRefreshRqst & rqst)683 void ServiceController::HandlePersistRefreshRqst(const PersistRefreshRqst& rqst)
684 {
685     PersistRefreshRsp rsp = { 0 };
686     list<LogPersistQueryResult> resultList;
687     LogPersister::Query(resultList);
688     if (rqst.jobId == 0 && resultList.empty()) {
689         WriteErrorRsp(ERR_PERSIST_TASK_EMPTY);
690         return;
691     }
692     for (auto it = resultList.begin(); it != resultList.end() && rsp.jobNum < MAX_JOBS; ++it) {
693         uint32_t jobId = it->jobId;
694         if (rqst.jobId == 0 || rqst.jobId == jobId) {
695             (void)LogPersister::Refresh(jobId);
696             rsp.jobId[rsp.jobNum] = jobId;
697             rsp.jobNum++;
698         }
699     }
700     if (rsp.jobNum == 0) {
701         WriteErrorRsp(ERR_JOBID_NOT_EXSIST);
702         return;
703     }
704     WriteRspHeader(IoctlCmd::PERSIST_REFRESH_RSP, sizeof(rsp));
705     (void)m_communicationSocket->Write(reinterpret_cast<char*>(&rsp), sizeof(rsp));
706 }
707 
HandlePersistClearRqst()708 void ServiceController::HandlePersistClearRqst()
709 {
710     LogPersister::Clear();
711     PersistClearRsp rsp = { 0 };
712     WriteRspHeader(IoctlCmd::PERSIST_CLEAR_RSP, sizeof(rsp));
713     (void)m_communicationSocket->Write(reinterpret_cast<char*>(&rsp), sizeof(rsp));
714 }
715 
HandleBufferSizeGetRqst(const BufferSizeGetRqst & rqst)716 void ServiceController::HandleBufferSizeGetRqst(const BufferSizeGetRqst& rqst)
717 {
718     vector<uint16_t> allTypes = GetAllLogTypes();
719     uint16_t types = rqst.types;
720     if (types == 0) {
721         types = DEFAULT_LOG_TYPES;
722     }
723     int i = 0;
724     BufferSizeGetRsp rsp = { 0 };
725     for (uint16_t t : allTypes) {
726         if ((1 << t) & types) {
727             HilogBuffer& hilogBuffer = t == LOG_KMSG ? m_kmsgBuffer : m_hilogBuffer;
728             rsp.size[t] = static_cast<uint32_t>(hilogBuffer.GetBuffLen(t));
729             i++;
730         }
731     }
732     if (i == 0) {
733         WriteErrorRsp(ERR_LOG_TYPE_INVALID);
734         return;
735     }
736     WriteRspHeader(IoctlCmd::BUFFERSIZE_GET_RSP, sizeof(rsp));
737     (void)m_communicationSocket->Write(reinterpret_cast<char*>(&rsp), sizeof(rsp));
738 }
739 
HandleBufferSizeSetRqst(const BufferSizeSetRqst & rqst)740 void ServiceController::HandleBufferSizeSetRqst(const BufferSizeSetRqst& rqst)
741 {
742     vector<uint16_t> allTypes = GetAllLogTypes();
743     uint16_t types = rqst.types;
744     if (types == 0) {
745         types = DEFAULT_LOG_TYPES;
746     }
747     int i = 0;
748     BufferSizeSetRsp rsp = { 0 };
749     for (uint16_t t : allTypes) {
750         if ((1 << t) & types) {
751             HilogBuffer& hilogBuffer = t == LOG_KMSG ? m_kmsgBuffer : m_hilogBuffer;
752             int ret = hilogBuffer.SetBuffLen(t, rqst.size);
753             if (ret != RET_SUCCESS) {
754                 rsp.size[t] = ret;
755             } else {
756                 SetBufferSize(t, true, rqst.size);
757                 rsp.size[t] = rqst.size;
758             }
759             i++;
760         }
761     }
762     if (i == 0) {
763         WriteErrorRsp(ERR_LOG_TYPE_INVALID);
764         return;
765     }
766     WriteRspHeader(IoctlCmd::BUFFERSIZE_SET_RSP, sizeof(rsp));
767     (void)m_communicationSocket->Write(reinterpret_cast<char*>(&rsp), sizeof(rsp));
768 }
769 
HandleStatsQueryRqst(const StatsQueryRqst & rqst)770 void ServiceController::HandleStatsQueryRqst(const StatsQueryRqst& rqst)
771 {
772     LogStats& stats = m_hilogBuffer.GetStatsInfo();
773     if (!stats.IsEnable()) {
774         WriteErrorRsp(ERR_STATS_NOT_ENABLE);
775         return;
776     }
777     std::unique_lock<std::mutex> lk(stats.GetLock());
778 
779     WriteRspHeader(IoctlCmd::STATS_QUERY_RSP, sizeof(StatsQueryRsp));
780     SendOverallStats(stats);
781     SendLogTypeDomainStats(stats);
782     SendDomainStats(stats);
783     if (stats.IsTagEnable()) {
784         SendDomainTagStats(stats);
785     }
786     SendProcStats(stats);
787     SendProcLogTypeStats(stats);
788     if (stats.IsTagEnable()) {
789         SendProcTagStats(stats);
790     }
791 }
792 
HandleStatsClearRqst(const StatsClearRqst & rqst)793 void ServiceController::HandleStatsClearRqst(const StatsClearRqst& rqst)
794 {
795     m_hilogBuffer.ResetStats();
796     StatsClearRsp rsp = { 0 };
797     WriteRspHeader(IoctlCmd::STATS_CLEAR_RSP, sizeof(rsp));
798     (void)m_communicationSocket->Write(reinterpret_cast<char*>(&rsp), sizeof(rsp));
799 }
800 
HandleDomainFlowCtrlRqst(const DomainFlowCtrlRqst & rqst)801 void ServiceController::HandleDomainFlowCtrlRqst(const DomainFlowCtrlRqst& rqst)
802 {
803     SetDomainSwitchOn(rqst.on);
804     m_logCollector.SetLogFlowControl(rqst.on);
805     // set domain flow control later
806     DomainFlowCtrlRsp rsp = { 0 };
807     WriteRspHeader(IoctlCmd::DOMAIN_FLOWCTRL_RSP, sizeof(rsp));
808     (void)m_communicationSocket->Write(reinterpret_cast<char*>(&rsp), sizeof(rsp));
809 }
810 
HandleLogRemoveRqst(const LogRemoveRqst & rqst)811 void ServiceController::HandleLogRemoveRqst(const LogRemoveRqst& rqst)
812 {
813     vector<uint16_t> allTypes = GetAllLogTypes();
814     uint16_t types = rqst.types;
815     if (types == 0) {
816         types = DEFAULT_REMOVE_LOG_TYPES;
817     }
818     int i = 0;
819     LogRemoveRsp rsp = { types };
820     for (uint16_t t : allTypes) {
821         if ((1 << t) & types) {
822             HilogBuffer& hilogBuffer = (t == LOG_KMSG) ? m_kmsgBuffer : m_hilogBuffer;
823             (void)hilogBuffer.Delete(t);
824             i++;
825         }
826     }
827     if (i == 0) {
828         WriteErrorRsp(ERR_LOG_TYPE_INVALID);
829         return;
830     }
831     WriteRspHeader(IoctlCmd::LOG_REMOVE_RSP, sizeof(rsp));
832     (void)m_communicationSocket->Write(reinterpret_cast<char*>(&rsp), sizeof(rsp));
833 }
834 
HandleLogKmsgEnableRqst(const KmsgEnableRqst & rqst)835 void ServiceController::HandleLogKmsgEnableRqst(const KmsgEnableRqst& rqst)
836 {
837     SetKmsgSwitchOn(rqst.on);
838 
839     LogKmsg& logKmsg = LogKmsg::GetInstance(m_kmsgBuffer);
840     if (rqst.on) {
841         logKmsg.Start();
842     } else {
843         logKmsg.Stop();
844     }
845     // set domain flow control later
846     KmsgEnableRsp rsp = { 0 };
847     WriteRspHeader(IoctlCmd::KMSG_ENABLE_RSP, sizeof(rsp));
848     (void)m_communicationSocket->Write(reinterpret_cast<char*>(&rsp), sizeof(rsp));
849 }
850 
IsValidCmd(const CmdList & list,IoctlCmd cmd)851 bool ServiceController::IsValidCmd(const CmdList& list, IoctlCmd cmd)
852 {
853     auto it = find(list.begin(), list.end(), cmd);
854     return (it != list.end());
855 }
856 
CommunicationLoop(std::atomic<bool> & stopLoop,const CmdList & list)857 void ServiceController::CommunicationLoop(std::atomic<bool>& stopLoop, const CmdList& list)
858 {
859     std::cout << "ServiceController Loop Begin" << std::endl;
860     MsgHeader hdr;
861     int ret = GetMsgHeader(hdr);
862     if (ret != RET_SUCCESS) {
863         return;
864     }
865     IoctlCmd cmd = static_cast<IoctlCmd>(hdr.cmd);
866     std::cout << "Receive cmd: " << static_cast<int>(cmd) << endl;
867     if (!IsValidCmd(list, cmd)) {
868         cout << "Not valid cmd for this executor" << endl;
869         WriteErrorRsp(ERR_INVALID_RQST_CMD);
870         return;
871     }
872     switch (cmd) {
873         case IoctlCmd::OUTPUT_RQST: {
874             RequestHandler<OutputRqst>(hdr, [this](const OutputRqst& rqst) {
875                 HandleOutputRqst(rqst);
876             });
877             break;
878         }
879         case IoctlCmd::PERSIST_START_RQST: {
880             RequestHandler<PersistStartRqst>(hdr, [this](const PersistStartRqst& rqst) {
881                 HandlePersistStartRqst(rqst);
882             });
883             break;
884         }
885         case IoctlCmd::PERSIST_STOP_RQST: {
886             RequestHandler<PersistStopRqst>(hdr, [this](const PersistStopRqst& rqst) {
887                 HandlePersistStopRqst(rqst);
888             });
889             break;
890         }
891         case IoctlCmd::PERSIST_QUERY_RQST: {
892             RequestHandler<PersistQueryRqst>(hdr, [this](const PersistQueryRqst& rqst) {
893                 HandlePersistQueryRqst(rqst);
894             });
895             break;
896         }
897         case IoctlCmd::BUFFERSIZE_GET_RQST: {
898             RequestHandler<BufferSizeGetRqst>(hdr, [this](const BufferSizeGetRqst& rqst) {
899                 HandleBufferSizeGetRqst(rqst);
900             });
901             break;
902         }
903         case IoctlCmd::BUFFERSIZE_SET_RQST: {
904             RequestHandler<BufferSizeSetRqst>(hdr, [this](const BufferSizeSetRqst& rqst) {
905                 HandleBufferSizeSetRqst(rqst);
906             });
907             break;
908         }
909         case IoctlCmd::STATS_QUERY_RQST: {
910             RequestHandler<StatsQueryRqst>(hdr, [this](const StatsQueryRqst& rqst) {
911                 HandleStatsQueryRqst(rqst);
912             });
913             break;
914         }
915         case IoctlCmd::PERSIST_REFRESH_RQST: {
916             RequestHandler<PersistRefreshRqst>(hdr, [this](const PersistRefreshRqst& rqst) {
917                 HandlePersistRefreshRqst(rqst);
918             });
919             break;
920         }
921         case IoctlCmd::PERSIST_CLEAR_RQST: {
922             RequestHandler<PersistClearRqst>(hdr, [this](const PersistClearRqst& rqst) {
923                 HandlePersistClearRqst();
924             });
925             break;
926         }
927         case IoctlCmd::STATS_CLEAR_RQST: {
928             RequestHandler<StatsClearRqst>(hdr, [this](const StatsClearRqst& rqst) {
929                 HandleStatsClearRqst(rqst);
930             });
931             break;
932         }
933         case IoctlCmd::DOMAIN_FLOWCTRL_RQST: {
934             RequestHandler<DomainFlowCtrlRqst>(hdr, [this](const DomainFlowCtrlRqst& rqst) {
935                 HandleDomainFlowCtrlRqst(rqst);
936             });
937             break;
938         }
939         case IoctlCmd::LOG_REMOVE_RQST: {
940             RequestHandler<LogRemoveRqst>(hdr, [this](const LogRemoveRqst& rqst) {
941                 HandleLogRemoveRqst(rqst);
942             });
943             break;
944         }
945         case IoctlCmd::KMSG_ENABLE_RQST: {
946             RequestHandler<KmsgEnableRqst>(hdr, [this](const KmsgEnableRqst& rqst) {
947                 HandleLogKmsgEnableRqst(rqst);
948             });
949             break;
950         }
951         default: {
952             std::cerr << " Unknown message. Skipped!" << endl;
953             break;
954         }
955     }
956     stopLoop.store(true);
957     std::cout << " ServiceController Loop End" << endl;
958 }
959 
NotifyForNewData()960 void ServiceController::NotifyForNewData()
961 {
962     m_notifyNewDataCv.notify_one();
963 }
964 
RestorePersistJobs(HilogBuffer & hilogBuffer,HilogBuffer & kmsgBuffer)965 int RestorePersistJobs(HilogBuffer& hilogBuffer, HilogBuffer& kmsgBuffer)
966 {
967     std::cout << " Start restoring persist jobs!\n";
968     DIR *dir = opendir(LOG_PERSISTER_DIR.c_str());
969     struct dirent *ent = nullptr;
970     if (dir == nullptr) {
971         perror("Failed to open persister directory!");
972         return ERR_LOG_PERSIST_DIR_OPEN_FAIL;
973     }
974     while ((ent = readdir(dir)) != nullptr) {
975         size_t length = strlen(ent->d_name);
976         std::string pPath(ent->d_name, length);
977         if (length >= INFO_SUFFIX && pPath.substr(length - INFO_SUFFIX, length) == ".info") {
978             if (pPath == "hilog.info") {
979                 continue;
980             }
981             std::cout << " Found a persist job! Path: " << LOG_PERSISTER_DIR + pPath << "\n";
982             FILE* infile = fopen((LOG_PERSISTER_DIR + pPath).c_str(), "r");
983             if (infile == nullptr) {
984                 std::cerr << " Error opening recovery info file!\n";
985                 continue;
986             }
987             PersistRecoveryInfo info = { 0 };
988             fread(&info, sizeof(PersistRecoveryInfo), 1, infile);
989             uint64_t hashSum = 0L;
990             fread(&hashSum, sizeof(hashSum), 1, infile);
991             fclose(infile);
992             uint64_t hash = GenerateHash(reinterpret_cast<char *>(&info), sizeof(PersistRecoveryInfo));
993             if (hash != hashSum) {
994                 std::cout << " Info file checksum Failed!\n";
995                 continue;
996             }
997             HilogBuffer& logBuffer = IsKmsg(info.msg.filter.types) ? kmsgBuffer : hilogBuffer;
998             int result = StartPersistStoreJob(info, logBuffer, true);
999             std::cout << " Recovery Info:\n"
1000                 << "  restoring result: " << (result == RET_SUCCESS
1001                     ? std::string("Success\n")
1002                     : std::string("Failed(") + std::to_string(result) + ")\n")
1003                 << "  jobId=" << (unsigned)(info.msg.jobId) << "\n"
1004                 << "  filePath=" << (info.msg.filePath) << "\n"
1005                 << "  index=" << (info.index) << "\n";
1006         }
1007     }
1008     closedir(dir);
1009     std::cout << " Finished restoring persist jobs!\n";
1010     return EXIT_SUCCESS;
1011 }
1012 } // namespace HiviewDFX
1013 } // namespace OHOS
1014