• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "hisysevent_plugin.h"
16 
17 #include <cinttypes>
18 #include <csignal>
19 #include <cstdio>
20 #include <fcntl.h>
21 #include <sstream>
22 #include <sys/syscall.h>
23 #include <sys/types.h>
24 #include <sys/wait.h>
25 #include <unistd.h>
26 
27 namespace {
28 constexpr int PIPE_SIZE = 256 * 1024;
29 constexpr int MAX_STRING_LEN = 256 * 1024;
30 constexpr int MIN_STRING_LEN = 10;
31 constexpr int BYTE_BUFFER_SIZE = 1024;
32 } // namespace
33 
HisyseventPlugin()34 HisyseventPlugin::HisyseventPlugin() : fp_(nullptr, nullptr) {}
35 
~HisyseventPlugin()36 HisyseventPlugin::~HisyseventPlugin()
37 {
38     HILOG_INFO(LOG_CORE, "BEGN %s: ready!", __func__);
39     Stop();
40     HILOG_INFO(LOG_CORE, "END %s: success!", __func__);
41 }
42 
SetWriter(WriterStruct * writer)43 int HisyseventPlugin::SetWriter(WriterStruct* writer)
44 {
45     resultWriter_ = writer;
46 
47     HILOG_INFO(LOG_CORE, "END %s: success!", __func__);
48     return 0;
49 }
50 
Start(const uint8_t * configData,uint32_t configSize)51 int HisyseventPlugin::Start(const uint8_t* configData, uint32_t configSize)
52 {
53     HILOG_INFO(LOG_CORE, "BEGN %s: ready!", __func__);
54     CHECK_NOTNULL(configData, -1, "NOTE %s: param invalid", __func__);
55 
56     CHECK_TRUE(protoConfig_.ParseFromArray(configData, configSize) > 0, -1,
57                "NOTE HisyseventPlugin: ParseFromArray failed");
58 
59     HILOG_DEBUG(LOG_CORE, "NOTE configData ParseFromArray sucessed,sourse data:%s", protoConfig_.msg().c_str());
60 
61     CHECK_TRUE(InitHisyseventCmd(), -1, "HisyseventPlugin: Init HisyseventCmd failed");
62 
63     fp_ = std::unique_ptr<FILE, std::function<int (FILE*)>>(
64         COMMON::CustomPopen(fullCmd_, "r", pipeFds_, childPid_, true), [this](FILE* fp) -> int {
65             return COMMON::CustomPclose(fp, pipeFds_, childPid_, true);
66         });
67 
68     CHECK_NOTNULL(fp_.get(), -1, "HisyseventPlugin: fullCmd_ Failed, errno(%d)", errno);
69     CHECK_NOTNULL(resultWriter_, -1, "HisyseventPlugin: Writer is no set!!");
70     CHECK_NOTNULL(resultWriter_->write, -1, "HisyseventPlugin: Writer.write is no set!!");
71     CHECK_NOTNULL(resultWriter_->flush, -1, "HisyseventPlugin: Writer.flush is no set!!");
72     id_ = 1;
73     running_ = true;
74     workThread_ = std::thread(&HisyseventPlugin::Run, this);
75 
76     HILOG_INFO(LOG_CORE, "END %s: success!", __func__);
77     return 0;
78 }
79 
Stop()80 int HisyseventPlugin::Stop()
81 {
82     HILOG_INFO(LOG_CORE, "BEGN %s: ready!", __func__);
83     running_ = false;
84     COMMON::CustomPUnblock(pipeFds_);
85 
86     if (workThread_.joinable()) {
87         workThread_.join();
88     }
89 
90     if (fp_ != nullptr) {
91         fp_.reset();
92     }
93 
94     HILOG_INFO(LOG_CORE, "END %s: success!", __func__);
95     return 0;
96 }
97 
Run(void)98 void HisyseventPlugin::Run(void)
99 {
100     HILOG_INFO(LOG_CORE, "BEGN %s: ready!", __func__);
101     std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(MAX_STRING_LEN);
102 
103     HILOG_INFO(LOG_CORE, "NOTE hisysevent_plugin_result.proto->HisyseventInfo:dataProto;Ready to output the result!");
104     HisyseventInfo dataProto;
105 
106     fcntl(fileno(fp_.get()), F_SETPIPE_SZ, PIPE_SIZE);
107     int aPipeSize = fcntl(fileno(fp_.get()), F_GETPIPE_SZ);
108     HILOG_INFO(LOG_CORE, "{fp = %d, aPipeSize=%d, PIPE_SIZE=%d}", fileno(fp_.get()), aPipeSize, PIPE_SIZE);
109 
110     while (running_) {
111         if (fgets(reinterpret_cast<char*>(buffer.get()), MAX_STRING_LEN, fp_.get()) != nullptr) {
112             auto cptr = reinterpret_cast<char*>(buffer.get());
113             if (!ParseSyseventLineInfo(cptr, strlen(cptr), dataProto))
114                 continue;
115         }
116 
117         if (dataProto.ByteSizeLong() >= BYTE_BUFFER_SIZE) {
118             WriteResult(dataProto);
119             dataProto.clear_info();
120         }
121     }
122 
123     WriteResult(dataProto);
124     dataProto.clear_info();
125 
126     HILOG_INFO(LOG_CORE, "END %s: success!", __func__);
127 }
128 
GetFullCmd()129 std::string HisyseventPlugin::GetFullCmd()
130 {
131     std::string cmd;
132 
133     if (!fullCmd_.empty()) {
134         size_t i = 0;
135         for (size_t cmdSize = fullCmd_.size() - 1; i < cmdSize; i++) {
136             cmd.append(fullCmd_[i]).append(" ");
137         }
138         cmd.append(fullCmd_[i]);
139     }
140     return cmd;
141 }
142 
InitHisyseventCmd()143 inline bool HisyseventPlugin::InitHisyseventCmd()
144 {
145     HILOG_INFO(LOG_CORE, "BEGN %s: ready!", __func__);
146     if (!fullCmd_.empty()) {
147         HILOG_INFO(LOG_CORE, "fullCmd_ is dirty.Then clear().");
148         fullCmd_.clear();
149     }
150 
151     fullCmd_.emplace_back("/bin/hisysevent"); // exe file path
152     fullCmd_.emplace_back("hisysevent"); // exe file name
153     fullCmd_.emplace_back("-rd");
154 
155     HILOG_INFO(LOG_CORE, "END %s: success!", __func__);
156     return true;
157 }
158 
ParseSyseventLineInfo(const char * data,size_t len,HisyseventInfo & dataProto)159 inline bool HisyseventPlugin::ParseSyseventLineInfo(const char* data, size_t len, HisyseventInfo& dataProto)
160 {
161     CHECK_TRUE(data != nullptr && len >= MIN_STRING_LEN, false, "NOTE %s: param invalid", __func__);
162 
163     if (google::protobuf::internal::IsStructurallyValidUTF8(data, strlen(data) - 1)) {
164         auto* info = dataProto.add_info();
165         info->set_id(id_);
166         info->set_context(data, strlen(data) - 1); // - \n
167         id_++;
168     } else {
169         HILOG_ERROR(LOG_CORE, "NOTE HisyseventPlugin: hisysevent context include invalid UTF-8 data");
170         return false;
171     }
172 
173     return true;
174 }
175 
WriteResult(const HisyseventInfo & dataProto)176 inline bool HisyseventPlugin::WriteResult(const HisyseventInfo& dataProto)
177 {
178     // Cmd result resize and SerializeToArray and after save to protoBuffer_ ;Then write and flush;Then clear_info
179     protoBuffer_.resize(dataProto.ByteSizeLong());
180     dataProto.SerializeToArray(protoBuffer_.data(), protoBuffer_.size());
181     // SerializeToArray after data=%s",protoBuffer_.data()
182     resultWriter_->write(resultWriter_, protoBuffer_.data(), protoBuffer_.size());
183     resultWriter_->flush(resultWriter_);
184     return true;
185 }
186