• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 #include "event_server.h"
17 
18 #include <memory>
19 #include <string>
20 #include <vector>
21 
22 #include <fcntl.h>
23 #include <sys/epoll.h>
24 #include <sys/socket.h>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <sys/un.h>
28 #include <unistd.h>
29 
30 #include <securec.h>
31 
32 extern "C" {
33 #include "init_socket.h"
34 }
35 
36 #include "device_node.h"
37 #include "logger.h"
38 #include "socket_util.h"
39 
40 #define SOCKET_FILE_DIR "/dev/unix/socket/hisysevent"
41 
42 namespace OHOS {
43 namespace HiviewDFX {
44 DEFINE_LOG_TAG("HiView-EventServer");
45 namespace {
46 constexpr int BUFFER_SIZE = 384 * 1024;
47 #ifndef KERNEL_DEVICE_BUFFER
48 constexpr int EVENT_READ_BUFFER = 2048;
49 #else
50 constexpr int EVENT_READ_BUFFER = KERNEL_DEVICE_BUFFER;
51 #endif
52 
InitRecvBuffer(int socketId)53 void InitRecvBuffer(int socketId)
54 {
55     int oldN = 0;
56     socklen_t oldOutSize = static_cast<socklen_t>(sizeof(int));
57     if (getsockopt(socketId, SOL_SOCKET, SO_RCVBUF, static_cast<void *>(&oldN), &oldOutSize) < 0) {
58         HIVIEW_LOGE("get socket buffer error=%{public}d, msg=%{public}s", errno, strerror(errno));
59     }
60 
61     int sendBuffSize = BUFFER_SIZE;
62     if (setsockopt(socketId, SOL_SOCKET, SO_RCVBUF, static_cast<void *>(&sendBuffSize), sizeof(int)) < 0) {
63         HIVIEW_LOGE("set socket buffer error=%{public}d, msg=%{public}s", errno, strerror(errno));
64     }
65 
66     int newN = 0;
67     socklen_t newOutSize = static_cast<socklen_t>(sizeof(int));
68     if (getsockopt(socketId, SOL_SOCKET, SO_RCVBUF, static_cast<void *>(&newN), &newOutSize) < 0) {
69         HIVIEW_LOGE("get new socket buffer error=%{public}d, msg=%{public}s", errno, strerror(errno));
70     }
71     HIVIEW_LOGI("reset recv buffer size old=%{public}d, new=%{public}d", oldN, newN);
72 }
73 }
74 
InitSocket(int & socketId)75 void SocketDevice::InitSocket(int &socketId)
76 {
77     struct sockaddr_un serverAddr;
78     serverAddr.sun_family = AF_UNIX;
79     if (strcpy_s(serverAddr.sun_path, sizeof(serverAddr.sun_path), SOCKET_FILE_DIR) != EOK) {
80         socketId = -1;
81         HIVIEW_LOGE("copy hisysevent dev path fail %{public}d, msg=%{public}s", errno, strerror(errno));
82         return;
83     }
84     serverAddr.sun_path[sizeof(serverAddr.sun_path) - 1] = '\0';
85     socketId = TEMP_FAILURE_RETRY(socket(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0));
86     if (socketId < 0) {
87         HIVIEW_LOGE("create hisysevent socket fail %{public}d, msg=%{public}s", errno, strerror(errno));
88         return;
89     }
90     InitRecvBuffer(socketId_);
91     unlink(serverAddr.sun_path);
92     if (TEMP_FAILURE_RETRY(bind(socketId, reinterpret_cast<sockaddr*>(&serverAddr), sizeof(serverAddr))) < 0) {
93         close(socketId);
94         socketId = -1;
95         HIVIEW_LOGE("bind hisysevent socket fail %{public}d, msg=%{public}s", errno, strerror(errno));
96         return;
97     }
98 }
99 
Open()100 int SocketDevice::Open()
101 {
102     socketId_ = GetControlSocket("hisysevent");
103     if (socketId_ < 0) {
104         HIVIEW_LOGI("create hisysevent socket");
105         InitSocket(socketId_);
106     } else {
107         InitRecvBuffer(socketId_);
108         HIVIEW_LOGI("use hisysevent exist socket");
109     }
110 
111     if (socketId_ < 0) {
112         HIVIEW_LOGE("hisysevent create socket fail");
113         return -1;
114     }
115     return socketId_;
116 }
117 
Close()118 int SocketDevice::Close()
119 {
120     if (socketId_ > 0) {
121         close(socketId_);
122         socketId_ = -1;
123     }
124     return 0;
125 }
126 
GetEvents()127 uint32_t SocketDevice::GetEvents()
128 {
129     return EPOLLIN | EPOLLET;
130 }
131 
GetName()132 std::string SocketDevice::GetName()
133 {
134     return "SysEventSocket";
135 }
136 
ReceiveMsg(std::vector<std::shared_ptr<EventReceiver>> & receivers)137 int SocketDevice::ReceiveMsg(std::vector<std::shared_ptr<EventReceiver>> &receivers)
138 {
139     while (true) {
140         struct sockaddr_un clientAddr;
141         socklen_t clientLen = static_cast<socklen_t>(sizeof(clientAddr));
142         char* recvbuf = new char[BUFFER_SIZE];
143         int n = recvfrom(socketId_, recvbuf, sizeof(char) * BUFFER_SIZE, 0,
144             reinterpret_cast<sockaddr*>(&clientAddr), &clientLen);
145         if (n <= 0) {
146             delete[] recvbuf;
147             break;
148         }
149         recvbuf[BUFFER_SIZE - 1] = 0;
150         HIVIEW_LOGD("receive data from client %s", recvbuf);
151         for (auto receiver = receivers.begin(); receiver != receivers.end(); receiver++) {
152             (*receiver)->HandlerEvent(std::string(recvbuf));
153         }
154         delete[] recvbuf;
155     }
156     return 0;
157 }
158 
Close()159 int BBoxDevice::Close()
160 {
161     if (fd_ > 0) {
162         close(fd_);
163         fd_ = -1;
164     }
165     return 0;
166 }
167 
Open()168 int BBoxDevice::Open()
169 {
170     fd_ = open("/dev/bbox", O_RDONLY, 0);
171     if (fd_ < 0) {
172         HIVIEW_LOGE("open bbox fail error=%{public}d, msg=%{public}s", errno, strerror(errno));
173         return -1;
174     }
175     return fd_;
176 }
177 
GetEvents()178 uint32_t BBoxDevice::GetEvents()
179 {
180     return EPOLLIN;
181 }
182 
GetName()183 std::string BBoxDevice::GetName()
184 {
185     return "BBox";
186 }
187 
ReceiveMsg(std::vector<std::shared_ptr<EventReceiver>> & receivers)188 int BBoxDevice::ReceiveMsg(std::vector<std::shared_ptr<EventReceiver>> &receivers)
189 {
190     char buffer[EVENT_READ_BUFFER];
191     (void)memset_s(buffer, sizeof(buffer), 0, sizeof(buffer));
192     int ret = read(fd_, buffer, EVENT_READ_BUFFER);
193     if (ret <= 0) {
194         return -1;
195     }
196     buffer[EVENT_READ_BUFFER - 1] = '\0';
197     HIVIEW_LOGD("receive from kernal %{public}s", buffer);
198     for (auto receiver = receivers.begin(); receiver != receivers.end(); receiver++) {
199         (*receiver)->HandlerEvent(std::string(buffer));
200     }
201     return 0;
202 }
203 
AddDev(std::shared_ptr<DeviceNode> dev)204 void EventServer::AddDev(std::shared_ptr<DeviceNode> dev)
205 {
206     int fd = dev->Open();
207     if (fd < 0) {
208         HIVIEW_LOGI("open device %{public}s failed", dev->GetName().c_str());
209         return;
210     }
211     devs_[fd] = dev;
212 }
213 
OpenDevs()214 int EventServer::OpenDevs()
215 {
216     AddDev(std::make_shared<SocketDevice>());
217     AddDev(std::make_shared<BBoxDevice>());
218     if (devs_.empty()) {
219         HIVIEW_LOGE("can not open any device");
220         return -1;
221     }
222     HIVIEW_LOGI("has open %{public}u devices", devs_.size());
223     return 0;
224 }
225 
AddToMonitor(int pollFd,struct epoll_event pollEvents[])226 int EventServer::AddToMonitor(int pollFd, struct epoll_event pollEvents[])
227 {
228     int index = 0;
229     auto it = devs_.begin();
230     while (it != devs_.end()) {
231         HIVIEW_LOGI("add to poll device %{public}s, fd=%{public}d", it->second->GetName().c_str(), it->first);
232         pollEvents[index].data.fd = it->first;
233         pollEvents[index].events = it->second->GetEvents();
234         int ret = epoll_ctl(pollFd, EPOLL_CTL_ADD, it->first, &pollEvents[index]);
235         if (ret < 0) {
236             HIVIEW_LOGE("add to poll fail device %{public}s error=%{public}d, msg=%{public}s",
237                 it->second->GetName().c_str(), errno, strerror(errno));
238             it->second->Close();
239             it = devs_.erase(it);
240         } else {
241             it++;
242         }
243         index++;
244     }
245 
246     if (devs_.empty()) {
247         HIVIEW_LOGE("can not monitor any device");
248         return -1;
249     }
250     HIVIEW_LOGI("monitor devices %{public}u", devs_.size());
251     return 0;
252 }
253 
Start()254 void EventServer::Start()
255 {
256     HIVIEW_LOGD("start event server");
257     if (OpenDevs() < 0) {
258         return;
259     }
260 
261     int pollFd = epoll_create1(EPOLL_CLOEXEC);
262     if (pollFd < 0) {
263         HIVIEW_LOGE("create poll fail error=%{public}d, msg=%{public}s", errno, strerror(errno));
264         return;
265     }
266 
267     struct epoll_event pollEvents[devs_.size()];
268     if (AddToMonitor(pollFd, pollEvents) < 0) {
269         return;
270     }
271 
272     HIVIEW_LOGI("go into event loop");
273     isStart_ = true;
274     while (isStart_) {
275         struct epoll_event chkPollEvents[devs_.size()];
276         int eventCount = epoll_wait(pollFd, chkPollEvents, devs_.size(), 10000); // 10000: 10 seconds
277         if (eventCount <= 0) {
278             HIVIEW_LOGD("read event timeout");
279             continue;
280         }
281         for (int ii = 0; ii < eventCount; ii++) {
282             auto it = devs_.find(chkPollEvents[ii].data.fd);
283             it->second->ReceiveMsg(receivers_);
284         }
285     }
286     CloseDevs();
287 }
288 
CloseDevs()289 void EventServer::CloseDevs()
290 {
291     for (auto devItem : devs_) {
292         devItem.second->Close();
293     }
294 }
295 
Stop()296 void EventServer::Stop()
297 {
298     isStart_ = false;
299 }
300 
AddReceiver(std::shared_ptr<EventReceiver> receiver)301 void EventServer::AddReceiver(std::shared_ptr<EventReceiver> receiver)
302 {
303     receivers_.emplace_back(receiver);
304 }
305 } // namespace HiviewDFX
306 } // namespace OHOS
307