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