1020a203aSopenharmony_ci/*
2020a203aSopenharmony_ci * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3020a203aSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4020a203aSopenharmony_ci * you may not use this file except in compliance with the License.
5020a203aSopenharmony_ci * You may obtain a copy of the License at
6020a203aSopenharmony_ci *
7020a203aSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8020a203aSopenharmony_ci *
9020a203aSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10020a203aSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11020a203aSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12020a203aSopenharmony_ci * See the License for the specific language governing permissions and
13020a203aSopenharmony_ci * limitations under the License.
14020a203aSopenharmony_ci */
15020a203aSopenharmony_ci
16020a203aSopenharmony_ci#include "event_server.h"
17020a203aSopenharmony_ci
18020a203aSopenharmony_ci#include <fstream>
19020a203aSopenharmony_ci#include <memory>
20020a203aSopenharmony_ci#include <string>
21020a203aSopenharmony_ci#include <vector>
22020a203aSopenharmony_ci
23020a203aSopenharmony_ci#include <fcntl.h>
24020a203aSopenharmony_ci#include <sys/epoll.h>
25020a203aSopenharmony_ci#include <sys/socket.h>
26020a203aSopenharmony_ci#include <sys/stat.h>
27020a203aSopenharmony_ci#include <sys/types.h>
28020a203aSopenharmony_ci#include <sys/un.h>
29020a203aSopenharmony_ci#include <unistd.h>
30020a203aSopenharmony_ci
31020a203aSopenharmony_ci#include <securec.h>
32020a203aSopenharmony_ci
33020a203aSopenharmony_ci#include "base/raw_data_base_def.h"
34020a203aSopenharmony_ci#include "decoded/decoded_event.h"
35020a203aSopenharmony_ci#include "device_node.h"
36020a203aSopenharmony_ci#include "init_socket.h"
37020a203aSopenharmony_ci#include "hiview_logger.h"
38020a203aSopenharmony_ci#include "socket_util.h"
39020a203aSopenharmony_ci
40020a203aSopenharmony_ci#define SOCKET_FILE_DIR "/dev/unix/socket/hisysevent"
41020a203aSopenharmony_ci
42020a203aSopenharmony_cinamespace OHOS {
43020a203aSopenharmony_cinamespace HiviewDFX {
44020a203aSopenharmony_ciDEFINE_LOG_TAG("HiView-EventServer");
45020a203aSopenharmony_cinamespace {
46020a203aSopenharmony_ciconstexpr int BUFFER_SIZE = 384 * 1024;
47020a203aSopenharmony_ci#ifndef KERNEL_DEVICE_BUFFER
48020a203aSopenharmony_ciconstexpr int EVENT_READ_BUFFER = 2048;
49020a203aSopenharmony_ci#else
50020a203aSopenharmony_ciconstexpr int EVENT_READ_BUFFER = KERNEL_DEVICE_BUFFER;
51020a203aSopenharmony_ci#endif
52020a203aSopenharmony_ci
53020a203aSopenharmony_cistruct Header {
54020a203aSopenharmony_ci    unsigned short len;
55020a203aSopenharmony_ci    unsigned short headerSize;
56020a203aSopenharmony_ci    char msg[0];
57020a203aSopenharmony_ci};
58020a203aSopenharmony_ci
59020a203aSopenharmony_civoid InitSocketBuf(int socketId, int optName)
60020a203aSopenharmony_ci{
61020a203aSopenharmony_ci    int bufferSizeOld = 0;
62020a203aSopenharmony_ci    socklen_t sizeOfInt = static_cast<socklen_t>(sizeof(int));
63020a203aSopenharmony_ci    if (getsockopt(socketId, SOL_SOCKET, optName, static_cast<void *>(&bufferSizeOld), &sizeOfInt) < 0) {
64020a203aSopenharmony_ci        HIVIEW_LOGE("get socket buffer error=%{public}d, msg=%{public}s", errno, strerror(errno));
65020a203aSopenharmony_ci    }
66020a203aSopenharmony_ci
67020a203aSopenharmony_ci    int bufferSizeSet = BUFFER_SIZE;
68020a203aSopenharmony_ci    if (setsockopt(socketId, SOL_SOCKET, optName, static_cast<void *>(&bufferSizeSet), sizeof(int)) < 0) {
69020a203aSopenharmony_ci        HIVIEW_LOGE("set socket buffer error=%{public}d, msg=%{public}s", errno, strerror(errno));
70020a203aSopenharmony_ci    }
71020a203aSopenharmony_ci
72020a203aSopenharmony_ci    int bufferSizeNew = 0;
73020a203aSopenharmony_ci    sizeOfInt = static_cast<socklen_t>(sizeof(int));
74020a203aSopenharmony_ci    if (getsockopt(socketId, SOL_SOCKET, optName, static_cast<void *>(&bufferSizeNew), &sizeOfInt) < 0) {
75020a203aSopenharmony_ci        HIVIEW_LOGE("get new socket buffer error=%{public}d, msg=%{public}s", errno, strerror(errno));
76020a203aSopenharmony_ci    }
77020a203aSopenharmony_ci    HIVIEW_LOGI("reset buffer size old=%{public}d, new=%{public}d", bufferSizeOld, bufferSizeNew);
78020a203aSopenharmony_ci}
79020a203aSopenharmony_ci
80020a203aSopenharmony_civoid InitRecvBuffer(int socketId)
81020a203aSopenharmony_ci{
82020a203aSopenharmony_ci    InitSocketBuf(socketId, SO_RCVBUF);
83020a203aSopenharmony_ci}
84020a203aSopenharmony_ci
85020a203aSopenharmony_cistd::shared_ptr<EventRaw::RawData> ConverRawData(char* source)
86020a203aSopenharmony_ci{
87020a203aSopenharmony_ci    if (source == nullptr) {
88020a203aSopenharmony_ci        HIVIEW_LOGE("invalid source.");
89020a203aSopenharmony_ci        return nullptr;
90020a203aSopenharmony_ci    }
91020a203aSopenharmony_ci    uint32_t sourceLen = *(reinterpret_cast<uint32_t*>(source));
92020a203aSopenharmony_ci    uint32_t desLen = sourceLen + sizeof(uint8_t);
93020a203aSopenharmony_ci    uint8_t* des = reinterpret_cast<uint8_t*>(malloc(desLen));
94020a203aSopenharmony_ci    if (des == nullptr) {
95020a203aSopenharmony_ci        HIVIEW_LOGE("malloc failed.");
96020a203aSopenharmony_ci        return nullptr;
97020a203aSopenharmony_ci    }
98020a203aSopenharmony_ci    uint32_t sourceHeaderLen = sizeof(int32_t) + sizeof(EventRaw::HiSysEventHeader) - sizeof(uint8_t);
99020a203aSopenharmony_ci    if (memcpy_s(des, desLen, source, sourceHeaderLen) != EOK) {
100020a203aSopenharmony_ci        HIVIEW_LOGE("copy failed.");
101020a203aSopenharmony_ci        free(des);
102020a203aSopenharmony_ci        return nullptr;
103020a203aSopenharmony_ci    }
104020a203aSopenharmony_ci    *(reinterpret_cast<uint8_t*>(des + sourceHeaderLen)) = 0; // init header.log flag
105020a203aSopenharmony_ci    uint32_t desPos = sourceHeaderLen + sizeof(uint8_t);
106020a203aSopenharmony_ci    if (memcpy_s(des + desPos, desLen - desPos, source + sourceHeaderLen, sourceLen - sourceHeaderLen) != EOK) {
107020a203aSopenharmony_ci        HIVIEW_LOGE("copy failed.");
108020a203aSopenharmony_ci        free(des);
109020a203aSopenharmony_ci        return nullptr;
110020a203aSopenharmony_ci    }
111020a203aSopenharmony_ci    *(reinterpret_cast<int32_t*>(des)) = desLen;
112020a203aSopenharmony_ci    auto rawData = std::make_shared<EventRaw::RawData>(des, desLen);
113020a203aSopenharmony_ci    free(des);
114020a203aSopenharmony_ci    return rawData;
115020a203aSopenharmony_ci}
116020a203aSopenharmony_ci
117020a203aSopenharmony_civoid InitMsgh(char* buffer, int bufferLen, std::array<char, CMSG_SPACE(sizeof(struct ucred))>& control,
118020a203aSopenharmony_ci    struct msghdr& msgh, struct iovec& iov)
119020a203aSopenharmony_ci{
120020a203aSopenharmony_ci    iov.iov_base = buffer;
121020a203aSopenharmony_ci    iov.iov_len = static_cast<uint32_t>(bufferLen);
122020a203aSopenharmony_ci    msgh.msg_iov = &iov;
123020a203aSopenharmony_ci    msgh.msg_iovlen = 1; // 1 is length of io vector
124020a203aSopenharmony_ci
125020a203aSopenharmony_ci    msgh.msg_control = control.data();
126020a203aSopenharmony_ci    msgh.msg_controllen = control.size();
127020a203aSopenharmony_ci
128020a203aSopenharmony_ci    msgh.msg_name = nullptr;
129020a203aSopenharmony_ci    msgh.msg_namelen = 0;
130020a203aSopenharmony_ci    msgh.msg_flags = 0;
131020a203aSopenharmony_ci}
132020a203aSopenharmony_ci
133020a203aSopenharmony_cipid_t ReadPidFromMsgh(struct msghdr& msgh)
134020a203aSopenharmony_ci{
135020a203aSopenharmony_ci    struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msgh);
136020a203aSopenharmony_ci    if (cmsg == nullptr) {
137020a203aSopenharmony_ci        return UN_INIT_INT_TYPE_VAL;
138020a203aSopenharmony_ci    }
139020a203aSopenharmony_ci    struct ucred* uCredRecv = reinterpret_cast<struct ucred*>(CMSG_DATA(cmsg));
140020a203aSopenharmony_ci    if (uCredRecv == nullptr) {
141020a203aSopenharmony_ci        return UN_INIT_INT_TYPE_VAL;
142020a203aSopenharmony_ci    }
143020a203aSopenharmony_ci    return uCredRecv->pid;
144020a203aSopenharmony_ci}
145020a203aSopenharmony_ci}
146020a203aSopenharmony_ci
147020a203aSopenharmony_civoid SocketDevice::InitSocket(int &socketId)
148020a203aSopenharmony_ci{
149020a203aSopenharmony_ci    struct sockaddr_un serverAddr;
150020a203aSopenharmony_ci    serverAddr.sun_family = AF_UNIX;
151020a203aSopenharmony_ci    if (strcpy_s(serverAddr.sun_path, sizeof(serverAddr.sun_path), SOCKET_FILE_DIR) != EOK) {
152020a203aSopenharmony_ci        socketId = -1;
153020a203aSopenharmony_ci        HIVIEW_LOGE("copy hisysevent dev path failed, error=%{public}d, msg=%{public}s", errno, strerror(errno));
154020a203aSopenharmony_ci        return;
155020a203aSopenharmony_ci    }
156020a203aSopenharmony_ci    serverAddr.sun_path[sizeof(serverAddr.sun_path) - 1] = '\0';
157020a203aSopenharmony_ci    socketId = TEMP_FAILURE_RETRY(socket(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0));
158020a203aSopenharmony_ci    if (socketId < 0) {
159020a203aSopenharmony_ci        HIVIEW_LOGE("create hisysevent socket failed, error=%{public}d, msg=%{public}s", errno, strerror(errno));
160020a203aSopenharmony_ci        return;
161020a203aSopenharmony_ci    }
162020a203aSopenharmony_ci    InitRecvBuffer(socketId_);
163020a203aSopenharmony_ci    unlink(serverAddr.sun_path);
164020a203aSopenharmony_ci    if (TEMP_FAILURE_RETRY(bind(socketId, reinterpret_cast<sockaddr*>(&serverAddr), sizeof(serverAddr))) < 0) {
165020a203aSopenharmony_ci        close(socketId);
166020a203aSopenharmony_ci        socketId = -1;
167020a203aSopenharmony_ci        HIVIEW_LOGE("bind hisysevent socket failed, error=%{public}d, msg=%{public}s", errno, strerror(errno));
168020a203aSopenharmony_ci        return;
169020a203aSopenharmony_ci    }
170020a203aSopenharmony_ci}
171020a203aSopenharmony_ci
172020a203aSopenharmony_ciint SocketDevice::Open()
173020a203aSopenharmony_ci{
174020a203aSopenharmony_ci    socketId_ = GetControlSocket("hisysevent");
175020a203aSopenharmony_ci    if (socketId_ < 0) {
176020a203aSopenharmony_ci        HIVIEW_LOGI("create hisysevent socket");
177020a203aSopenharmony_ci        InitSocket(socketId_);
178020a203aSopenharmony_ci    } else {
179020a203aSopenharmony_ci        InitRecvBuffer(socketId_);
180020a203aSopenharmony_ci        HIVIEW_LOGI("use hisysevent exist socket");
181020a203aSopenharmony_ci    }
182020a203aSopenharmony_ci
183020a203aSopenharmony_ci    if (socketId_ < 0) {
184020a203aSopenharmony_ci        HIVIEW_LOGE("hisysevent create socket failed");
185020a203aSopenharmony_ci        return -1;
186020a203aSopenharmony_ci    }
187020a203aSopenharmony_ci    return socketId_;
188020a203aSopenharmony_ci}
189020a203aSopenharmony_ci
190020a203aSopenharmony_ciint SocketDevice::Close()
191020a203aSopenharmony_ci{
192020a203aSopenharmony_ci    if (socketId_ > 0) {
193020a203aSopenharmony_ci        close(socketId_);
194020a203aSopenharmony_ci        socketId_ = -1;
195020a203aSopenharmony_ci    }
196020a203aSopenharmony_ci    return 0;
197020a203aSopenharmony_ci}
198020a203aSopenharmony_ci
199020a203aSopenharmony_ciuint32_t SocketDevice::GetEvents()
200020a203aSopenharmony_ci{
201020a203aSopenharmony_ci    return EPOLLIN | EPOLLET;
202020a203aSopenharmony_ci}
203020a203aSopenharmony_ci
204020a203aSopenharmony_cistd::string SocketDevice::GetName()
205020a203aSopenharmony_ci{
206020a203aSopenharmony_ci    return "SysEventSocket";
207020a203aSopenharmony_ci}
208020a203aSopenharmony_ci
209020a203aSopenharmony_cibool SocketDevice::IsValidMsg(char* msg, int32_t len)
210020a203aSopenharmony_ci{
211020a203aSopenharmony_ci    if (len < static_cast<int32_t>(EventRaw::GetValidDataMinimumByteCount())) {
212020a203aSopenharmony_ci        HIVIEW_LOGD("the data length=%{public}d is invalid", len);
213020a203aSopenharmony_ci        return false;
214020a203aSopenharmony_ci    }
215020a203aSopenharmony_ci    int32_t dataByteCnt = *(reinterpret_cast<int32_t*>(msg));
216020a203aSopenharmony_ci    if (dataByteCnt != len) {
217020a203aSopenharmony_ci        HIVIEW_LOGW("the data byte count=%{public}d are not equal to read length %{public}d", dataByteCnt, len);
218020a203aSopenharmony_ci        return false;
219020a203aSopenharmony_ci    }
220020a203aSopenharmony_ci    int32_t pid = *(reinterpret_cast<int32_t*>(msg + sizeof(int32_t) + EventRaw::POS_OF_PID_IN_HEADER));
221020a203aSopenharmony_ci    if (uCredPid_ > 0 && pid != uCredPid_) {
222020a203aSopenharmony_ci        HIVIEW_LOGW("failed to verify the consistensy of process id: [%{public}" PRId32
223020a203aSopenharmony_ci            ", %{public}" PRId32 "]", pid, uCredPid_);
224020a203aSopenharmony_ci        return false;
225020a203aSopenharmony_ci    }
226020a203aSopenharmony_ci    msg[len] = '\0';
227020a203aSopenharmony_ci    return true;
228020a203aSopenharmony_ci}
229020a203aSopenharmony_ci
230020a203aSopenharmony_civoid SocketDevice::SetUCredPid(const pid_t pid)
231020a203aSopenharmony_ci{
232020a203aSopenharmony_ci    uCredPid_ = pid;
233020a203aSopenharmony_ci}
234020a203aSopenharmony_ci
235020a203aSopenharmony_ciint SocketDevice::ReceiveMsg(std::vector<std::shared_ptr<EventReceiver>> &receivers)
236020a203aSopenharmony_ci{
237020a203aSopenharmony_ci    char* buffer = new char[BUFFER_SIZE + 1]();
238020a203aSopenharmony_ci    std::array<char, CMSG_SPACE(sizeof(struct ucred))> control = {0};
239020a203aSopenharmony_ci    struct msghdr msgh = {0};
240020a203aSopenharmony_ci    struct iovec iov = {
241020a203aSopenharmony_ci        .iov_base = nullptr,
242020a203aSopenharmony_ci        .iov_len = 0
243020a203aSopenharmony_ci    };
244020a203aSopenharmony_ci    InitMsgh(buffer, BUFFER_SIZE, control, msgh, iov);
245020a203aSopenharmony_ci    while (true) {
246020a203aSopenharmony_ci        int ret = recvmsg(socketId_, &msgh, 0);
247020a203aSopenharmony_ci        if (ret <= 0) {
248020a203aSopenharmony_ci            HIVIEW_LOGD("failed to recv msg from socket");
249020a203aSopenharmony_ci            break;
250020a203aSopenharmony_ci        }
251020a203aSopenharmony_ci        pid_t uCredPid = ReadPidFromMsgh(msgh);
252020a203aSopenharmony_ci        SetUCredPid(uCredPid);
253020a203aSopenharmony_ci        if (!IsValidMsg(buffer, ret)) {
254020a203aSopenharmony_ci            break;
255020a203aSopenharmony_ci        }
256020a203aSopenharmony_ci        for (auto receiver = receivers.begin(); receiver != receivers.end(); receiver++) {
257020a203aSopenharmony_ci            (*receiver)->HandlerEvent(ConverRawData(buffer));
258020a203aSopenharmony_ci        }
259020a203aSopenharmony_ci    }
260020a203aSopenharmony_ci    delete[] buffer;
261020a203aSopenharmony_ci    return 0;
262020a203aSopenharmony_ci}
263020a203aSopenharmony_ci
264020a203aSopenharmony_ciint BBoxDevice::Close()
265020a203aSopenharmony_ci{
266020a203aSopenharmony_ci    if (fd_ > 0) {
267020a203aSopenharmony_ci        close(fd_);
268020a203aSopenharmony_ci        fd_ = -1;
269020a203aSopenharmony_ci    }
270020a203aSopenharmony_ci    return 0;
271020a203aSopenharmony_ci}
272020a203aSopenharmony_ci
273020a203aSopenharmony_ciint BBoxDevice::Open()
274020a203aSopenharmony_ci{
275020a203aSopenharmony_ci    fd_ = open("/dev/sysevent", O_RDONLY | O_NONBLOCK, 0);
276020a203aSopenharmony_ci    if (fd_ < 0) {
277020a203aSopenharmony_ci        fd_ = open("/dev/bbox", O_RDONLY | O_NONBLOCK, 0);
278020a203aSopenharmony_ci    } else {
279020a203aSopenharmony_ci        hasBbox_ = true;
280020a203aSopenharmony_ci    }
281020a203aSopenharmony_ci
282020a203aSopenharmony_ci    if (fd_ < 0) {
283020a203aSopenharmony_ci        HIVIEW_LOGE("open bbox failed, error=%{public}d, msg=%{public}s", errno, strerror(errno));
284020a203aSopenharmony_ci        return -1;
285020a203aSopenharmony_ci    }
286020a203aSopenharmony_ci    return fd_;
287020a203aSopenharmony_ci}
288020a203aSopenharmony_ci
289020a203aSopenharmony_ciuint32_t BBoxDevice::GetEvents()
290020a203aSopenharmony_ci{
291020a203aSopenharmony_ci    return EPOLLIN;
292020a203aSopenharmony_ci}
293020a203aSopenharmony_ci
294020a203aSopenharmony_cistd::string BBoxDevice::GetName()
295020a203aSopenharmony_ci{
296020a203aSopenharmony_ci    return "BBox";
297020a203aSopenharmony_ci}
298020a203aSopenharmony_ci
299020a203aSopenharmony_cibool BBoxDevice::IsValidMsg(char* msg, int32_t len)
300020a203aSopenharmony_ci{
301020a203aSopenharmony_ci    if (len < static_cast<int32_t>(EventRaw::GetValidDataMinimumByteCount())) {
302020a203aSopenharmony_ci        HIVIEW_LOGW("the data length=%{public}d is invalid", len);
303020a203aSopenharmony_ci        return false;
304020a203aSopenharmony_ci    }
305020a203aSopenharmony_ci    int32_t dataByteCnt = *(reinterpret_cast<int32_t*>(msg));
306020a203aSopenharmony_ci    if ((hasBbox_ && dataByteCnt != len) ||
307020a203aSopenharmony_ci        (!hasBbox_ && dataByteCnt != (len - sizeof(struct Header) - 1))) { // extra bytes in kernel write
308020a203aSopenharmony_ci        HIVIEW_LOGW("the data lengths=%{public}d are not equal", len);
309020a203aSopenharmony_ci        return false;
310020a203aSopenharmony_ci    }
311020a203aSopenharmony_ci    msg[EVENT_READ_BUFFER - 1] = '\0';
312020a203aSopenharmony_ci    return true;
313020a203aSopenharmony_ci}
314020a203aSopenharmony_ci
315020a203aSopenharmony_ciint BBoxDevice::ReceiveMsg(std::vector<std::shared_ptr<EventReceiver>> &receivers)
316020a203aSopenharmony_ci{
317020a203aSopenharmony_ci    char buffer[EVENT_READ_BUFFER];
318020a203aSopenharmony_ci    (void)memset_s(buffer, sizeof(buffer), 0, sizeof(buffer));
319020a203aSopenharmony_ci    int ret = read(fd_, buffer, EVENT_READ_BUFFER);
320020a203aSopenharmony_ci    if (!IsValidMsg(buffer, ret)) {
321020a203aSopenharmony_ci        return -1;
322020a203aSopenharmony_ci    }
323020a203aSopenharmony_ci    for (auto receiver = receivers.begin(); receiver != receivers.end(); receiver++) {
324020a203aSopenharmony_ci        (*receiver)->HandlerEvent(ConverRawData(buffer));
325020a203aSopenharmony_ci    }
326020a203aSopenharmony_ci    return 0;
327020a203aSopenharmony_ci}
328020a203aSopenharmony_ci
329020a203aSopenharmony_civoid EventServer::AddDev(std::shared_ptr<DeviceNode> dev)
330020a203aSopenharmony_ci{
331020a203aSopenharmony_ci    int fd = dev->Open();
332020a203aSopenharmony_ci    if (fd < 0) {
333020a203aSopenharmony_ci        HIVIEW_LOGI("open device %{public}s failed", dev->GetName().c_str());
334020a203aSopenharmony_ci        return;
335020a203aSopenharmony_ci    }
336020a203aSopenharmony_ci    devs_[fd] = dev;
337020a203aSopenharmony_ci}
338020a203aSopenharmony_ci
339020a203aSopenharmony_ciint EventServer::OpenDevs()
340020a203aSopenharmony_ci{
341020a203aSopenharmony_ci    AddDev(std::make_shared<SocketDevice>());
342020a203aSopenharmony_ci    AddDev(std::make_shared<BBoxDevice>());
343020a203aSopenharmony_ci    if (devs_.empty()) {
344020a203aSopenharmony_ci        HIVIEW_LOGE("can not open any device");
345020a203aSopenharmony_ci        return -1;
346020a203aSopenharmony_ci    }
347020a203aSopenharmony_ci    HIVIEW_LOGI("has open %{public}zu devices", devs_.size());
348020a203aSopenharmony_ci    return 0;
349020a203aSopenharmony_ci}
350020a203aSopenharmony_ci
351020a203aSopenharmony_ciint EventServer::AddToMonitor(int pollFd, struct epoll_event pollEvents[])
352020a203aSopenharmony_ci{
353020a203aSopenharmony_ci    int index = 0;
354020a203aSopenharmony_ci    auto it = devs_.begin();
355020a203aSopenharmony_ci    while (it != devs_.end()) {
356020a203aSopenharmony_ci        HIVIEW_LOGI("add to poll device %{public}s, fd=%{public}d", it->second->GetName().c_str(), it->first);
357020a203aSopenharmony_ci        pollEvents[index].data.fd = it->first;
358020a203aSopenharmony_ci        pollEvents[index].events = it->second->GetEvents();
359020a203aSopenharmony_ci        int ret = epoll_ctl(pollFd, EPOLL_CTL_ADD, it->first, &pollEvents[index]);
360020a203aSopenharmony_ci        if (ret < 0) {
361020a203aSopenharmony_ci            HIVIEW_LOGE("add to poll fail device %{public}s error=%{public}d, msg=%{public}s",
362020a203aSopenharmony_ci                it->second->GetName().c_str(), errno, strerror(errno));
363020a203aSopenharmony_ci            it->second->Close();
364020a203aSopenharmony_ci            it = devs_.erase(it);
365020a203aSopenharmony_ci        } else {
366020a203aSopenharmony_ci            it++;
367020a203aSopenharmony_ci        }
368020a203aSopenharmony_ci        index++;
369020a203aSopenharmony_ci    }
370020a203aSopenharmony_ci
371020a203aSopenharmony_ci    if (devs_.empty()) {
372020a203aSopenharmony_ci        HIVIEW_LOGE("can not monitor any device");
373020a203aSopenharmony_ci        return -1;
374020a203aSopenharmony_ci    }
375020a203aSopenharmony_ci    HIVIEW_LOGI("monitor devices %{public}zu", devs_.size());
376020a203aSopenharmony_ci    return 0;
377020a203aSopenharmony_ci}
378020a203aSopenharmony_ci
379020a203aSopenharmony_civoid EventServer::Start()
380020a203aSopenharmony_ci{
381020a203aSopenharmony_ci    HIVIEW_LOGD("start event server");
382020a203aSopenharmony_ci    if (OpenDevs() < 0) {
383020a203aSopenharmony_ci        return;
384020a203aSopenharmony_ci    }
385020a203aSopenharmony_ci
386020a203aSopenharmony_ci    int pollFd = epoll_create1(EPOLL_CLOEXEC);
387020a203aSopenharmony_ci    if (pollFd < 0) {
388020a203aSopenharmony_ci        HIVIEW_LOGE("create poll failed, error=%{public}d, msg=%{public}s", errno, strerror(errno));
389020a203aSopenharmony_ci        return;
390020a203aSopenharmony_ci    }
391020a203aSopenharmony_ci
392020a203aSopenharmony_ci    struct epoll_event pollEvents[devs_.size()];
393020a203aSopenharmony_ci    if (AddToMonitor(pollFd, pollEvents) < 0) {
394020a203aSopenharmony_ci        return;
395020a203aSopenharmony_ci    }
396020a203aSopenharmony_ci
397020a203aSopenharmony_ci    HIVIEW_LOGI("go into event loop");
398020a203aSopenharmony_ci    isStart_ = true;
399020a203aSopenharmony_ci    while (isStart_) {
400020a203aSopenharmony_ci        struct epoll_event chkPollEvents[devs_.size()];
401020a203aSopenharmony_ci        int eventCount = epoll_wait(pollFd, chkPollEvents, devs_.size(), -1); // -1: Wait indefinitely
402020a203aSopenharmony_ci        if (eventCount <= 0) {
403020a203aSopenharmony_ci            HIVIEW_LOGD("read event timeout");
404020a203aSopenharmony_ci            continue;
405020a203aSopenharmony_ci        }
406020a203aSopenharmony_ci        for (int ii = 0; ii < eventCount; ii++) {
407020a203aSopenharmony_ci            auto it = devs_.find(chkPollEvents[ii].data.fd);
408020a203aSopenharmony_ci            it->second->ReceiveMsg(receivers_);
409020a203aSopenharmony_ci        }
410020a203aSopenharmony_ci    }
411020a203aSopenharmony_ci    CloseDevs();
412020a203aSopenharmony_ci}
413020a203aSopenharmony_ci
414020a203aSopenharmony_civoid EventServer::CloseDevs()
415020a203aSopenharmony_ci{
416020a203aSopenharmony_ci    for (auto devItem : devs_) {
417020a203aSopenharmony_ci        devItem.second->Close();
418020a203aSopenharmony_ci    }
419020a203aSopenharmony_ci}
420020a203aSopenharmony_ci
421020a203aSopenharmony_civoid EventServer::Stop()
422020a203aSopenharmony_ci{
423020a203aSopenharmony_ci    isStart_ = false;
424020a203aSopenharmony_ci}
425020a203aSopenharmony_ci
426020a203aSopenharmony_civoid EventServer::AddReceiver(std::shared_ptr<EventReceiver> receiver)
427020a203aSopenharmony_ci{
428020a203aSopenharmony_ci    receivers_.emplace_back(receiver);
429020a203aSopenharmony_ci}
430020a203aSopenharmony_ci} // namespace HiviewDFX
431020a203aSopenharmony_ci} // namespace OHOS
432