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 <fstream>
19 #include <memory>
20 #include <string>
21 #include <vector>
22
23 #include <fcntl.h>
24 #include <sys/epoll.h>
25 #include <sys/socket.h>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 #include <sys/un.h>
29 #include <unistd.h>
30
31 #include <securec.h>
32
33 #include "device_node.h"
34 #include "init_socket.h"
35 #include "logger.h"
36 #include "socket_util.h"
37
38 #define SOCKET_FILE_DIR "/dev/unix/socket/hisysevent"
39
40 namespace OHOS {
41 namespace HiviewDFX {
42 DEFINE_LOG_TAG("HiView-EventServer");
43 namespace {
44 constexpr int BUFFER_SIZE = 384 * 1024;
45 #ifndef KERNEL_DEVICE_BUFFER
46 constexpr int EVENT_READ_BUFFER = 2048;
47 #else
48 constexpr int EVENT_READ_BUFFER = KERNEL_DEVICE_BUFFER;
49 #endif
50 constexpr char SOCKET_CONFIG_FILE[] = "/system/etc/hiview/hisysevent_extra_socket";
51 std::string g_extraSocketPath;
52
53 struct Initializer {
InitializerOHOS::HiviewDFX::__anond836358e0111::Initializer54 Initializer()
55 {
56 if (access(SOCKET_CONFIG_FILE, F_OK) != 0) {
57 HIVIEW_LOGE("socket config file does not exist");
58 return;
59 }
60 std::ifstream file;
61 file.open(SOCKET_CONFIG_FILE);
62 if (file.fail()) {
63 HIVIEW_LOGE("open socket config file failed");
64 return;
65 }
66 g_extraSocketPath.clear();
67 file >> g_extraSocketPath;
68 HIVIEW_LOGI("read extra socket path: %{public}s", g_extraSocketPath.c_str());
69 }
70 };
71 Initializer g_initializer;
72
InitSocketBuf(int socketId,int optName)73 void InitSocketBuf(int socketId, int optName)
74 {
75 int bufferSizeOld = 0;
76 socklen_t sizeOfInt = static_cast<socklen_t>(sizeof(int));
77 if (getsockopt(socketId, SOL_SOCKET, optName, static_cast<void *>(&bufferSizeOld), &sizeOfInt) < 0) {
78 HIVIEW_LOGE("get socket buffer error=%{public}d, msg=%{public}s", errno, strerror(errno));
79 }
80
81 int bufferSizeSet = BUFFER_SIZE;
82 if (setsockopt(socketId, SOL_SOCKET, optName, static_cast<void *>(&bufferSizeSet), sizeof(int)) < 0) {
83 HIVIEW_LOGE("set socket buffer error=%{public}d, msg=%{public}s", errno, strerror(errno));
84 }
85
86 int bufferSizeNew = 0;
87 sizeOfInt = static_cast<socklen_t>(sizeof(int));
88 if (getsockopt(socketId, SOL_SOCKET, optName, static_cast<void *>(&bufferSizeNew), &sizeOfInt) < 0) {
89 HIVIEW_LOGE("get new socket buffer error=%{public}d, msg=%{public}s", errno, strerror(errno));
90 }
91 HIVIEW_LOGI("reset buffer size old=%{public}d, new=%{public}d", bufferSizeOld, bufferSizeNew);
92 }
93
InitSendBuffer(int socketId)94 void InitSendBuffer(int socketId)
95 {
96 InitSocketBuf(socketId, SO_SNDBUF);
97 }
98
InitRecvBuffer(int socketId)99 void InitRecvBuffer(int socketId)
100 {
101 InitSocketBuf(socketId, SO_RCVBUF);
102 }
103
TransferEvent(std::string & text)104 void TransferEvent(std::string& text)
105 {
106 HIVIEW_LOGD("event need to transfer: %{public}s", text.c_str());
107 if (text.back() == '}') {
108 text.pop_back();
109 text += ", \"transfer_\":1}";
110 }
111 struct sockaddr_un serverAddr;
112 serverAddr.sun_family = AF_UNIX;
113 if (strcpy_s(serverAddr.sun_path, sizeof(serverAddr.sun_path), g_extraSocketPath.c_str()) != EOK) {
114 HIVIEW_LOGE("can not assign server path");
115 return;
116 }
117 serverAddr.sun_path[sizeof(serverAddr.sun_path) - 1] = '\0';
118
119 int socketId = TEMP_FAILURE_RETRY(socket(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0));
120 if (socketId < 0) {
121 HIVIEW_LOGE("create hisysevent socket failed, error=%{public}d, msg=%{public}s", errno, strerror(errno));
122 return;
123 }
124 InitSendBuffer(socketId);
125 if (TEMP_FAILURE_RETRY(sendto(socketId, text.c_str(), text.size(), 0, reinterpret_cast<sockaddr*>(&serverAddr),
126 sizeof(serverAddr))) < 0) {
127 close(socketId);
128 socketId = -1;
129 HIVIEW_LOGE("send data failed, error=%{public}d, msg=%{public}s", errno, strerror(errno));
130 return;
131 }
132 close(socketId);
133 HIVIEW_LOGD("send data successful");
134 }
135 }
136
InitSocket(int & socketId)137 void SocketDevice::InitSocket(int &socketId)
138 {
139 struct sockaddr_un serverAddr;
140 serverAddr.sun_family = AF_UNIX;
141 if (strcpy_s(serverAddr.sun_path, sizeof(serverAddr.sun_path), SOCKET_FILE_DIR) != EOK) {
142 socketId = -1;
143 HIVIEW_LOGE("copy hisysevent dev path failed, error=%{public}d, msg=%{public}s", errno, strerror(errno));
144 return;
145 }
146 serverAddr.sun_path[sizeof(serverAddr.sun_path) - 1] = '\0';
147 socketId = TEMP_FAILURE_RETRY(socket(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0));
148 if (socketId < 0) {
149 HIVIEW_LOGE("create hisysevent socket failed, error=%{public}d, msg=%{public}s", errno, strerror(errno));
150 return;
151 }
152 InitRecvBuffer(socketId_);
153 unlink(serverAddr.sun_path);
154 if (TEMP_FAILURE_RETRY(bind(socketId, reinterpret_cast<sockaddr*>(&serverAddr), sizeof(serverAddr))) < 0) {
155 close(socketId);
156 socketId = -1;
157 HIVIEW_LOGE("bind hisysevent socket failed, error=%{public}d, msg=%{public}s", errno, strerror(errno));
158 return;
159 }
160 }
161
Open()162 int SocketDevice::Open()
163 {
164 socketId_ = GetControlSocket("hisysevent");
165 if (socketId_ < 0) {
166 HIVIEW_LOGI("create hisysevent socket");
167 InitSocket(socketId_);
168 } else {
169 InitRecvBuffer(socketId_);
170 HIVIEW_LOGI("use hisysevent exist socket");
171 }
172
173 if (socketId_ < 0) {
174 HIVIEW_LOGE("hisysevent create socket failed");
175 return -1;
176 }
177 return socketId_;
178 }
179
Close()180 int SocketDevice::Close()
181 {
182 if (socketId_ > 0) {
183 close(socketId_);
184 socketId_ = -1;
185 }
186 return 0;
187 }
188
GetEvents()189 uint32_t SocketDevice::GetEvents()
190 {
191 return EPOLLIN | EPOLLET;
192 }
193
GetName()194 std::string SocketDevice::GetName()
195 {
196 return "SysEventSocket";
197 }
198
ReceiveMsg(std::vector<std::shared_ptr<EventReceiver>> & receivers)199 int SocketDevice::ReceiveMsg(std::vector<std::shared_ptr<EventReceiver>> &receivers)
200 {
201 char* buffer = new char[BUFFER_SIZE + 1]();
202 while (true) {
203 struct sockaddr_un clientAddr;
204 socklen_t clientLen = static_cast<socklen_t>(sizeof(clientAddr));
205 int n = recvfrom(socketId_, buffer, sizeof(char) * BUFFER_SIZE, 0,
206 reinterpret_cast<sockaddr*>(&clientAddr), &clientLen);
207 if (n <= 0) {
208 break;
209 }
210 buffer[n] = 0;
211 HIVIEW_LOGD("receive data from client %s", buffer);
212 std::string event(buffer);
213 if (!g_extraSocketPath.empty()) {
214 TransferEvent(event);
215 }
216 for (auto receiver = receivers.begin(); receiver != receivers.end(); receiver++) {
217 (*receiver)->HandlerEvent(std::string(buffer));
218 }
219 }
220 delete[] buffer;
221 return 0;
222 }
223
Close()224 int BBoxDevice::Close()
225 {
226 if (fd_ > 0) {
227 close(fd_);
228 fd_ = -1;
229 }
230 return 0;
231 }
232
Open()233 int BBoxDevice::Open()
234 {
235 fd_ = open("/dev/bbox", O_RDONLY, 0);
236 if (fd_ < 0) {
237 HIVIEW_LOGE("open bbox failed, error=%{public}d, msg=%{public}s", errno, strerror(errno));
238 return -1;
239 }
240 return fd_;
241 }
242
GetEvents()243 uint32_t BBoxDevice::GetEvents()
244 {
245 return EPOLLIN;
246 }
247
GetName()248 std::string BBoxDevice::GetName()
249 {
250 return "BBox";
251 }
252
ReceiveMsg(std::vector<std::shared_ptr<EventReceiver>> & receivers)253 int BBoxDevice::ReceiveMsg(std::vector<std::shared_ptr<EventReceiver>> &receivers)
254 {
255 char buffer[EVENT_READ_BUFFER];
256 (void)memset_s(buffer, sizeof(buffer), 0, sizeof(buffer));
257 int ret = read(fd_, buffer, EVENT_READ_BUFFER);
258 if (ret <= 0) {
259 return -1;
260 }
261 buffer[EVENT_READ_BUFFER - 1] = '\0';
262 HIVIEW_LOGD("receive from kernel %{public}s", buffer);
263 std::string event(buffer);
264 if (!g_extraSocketPath.empty()) {
265 TransferEvent(event);
266 }
267 for (auto receiver = receivers.begin(); receiver != receivers.end(); receiver++) {
268 (*receiver)->HandlerEvent(std::string(buffer));
269 }
270 return 0;
271 }
272
AddDev(std::shared_ptr<DeviceNode> dev)273 void EventServer::AddDev(std::shared_ptr<DeviceNode> dev)
274 {
275 int fd = dev->Open();
276 if (fd < 0) {
277 HIVIEW_LOGI("open device %{public}s failed", dev->GetName().c_str());
278 return;
279 }
280 devs_[fd] = dev;
281 }
282
OpenDevs()283 int EventServer::OpenDevs()
284 {
285 AddDev(std::make_shared<SocketDevice>());
286 AddDev(std::make_shared<BBoxDevice>());
287 if (devs_.empty()) {
288 HIVIEW_LOGE("can not open any device");
289 return -1;
290 }
291 HIVIEW_LOGI("has open %{public}u devices", devs_.size());
292 return 0;
293 }
294
AddToMonitor(int pollFd,struct epoll_event pollEvents[])295 int EventServer::AddToMonitor(int pollFd, struct epoll_event pollEvents[])
296 {
297 int index = 0;
298 auto it = devs_.begin();
299 while (it != devs_.end()) {
300 HIVIEW_LOGI("add to poll device %{public}s, fd=%{public}d", it->second->GetName().c_str(), it->first);
301 pollEvents[index].data.fd = it->first;
302 pollEvents[index].events = it->second->GetEvents();
303 int ret = epoll_ctl(pollFd, EPOLL_CTL_ADD, it->first, &pollEvents[index]);
304 if (ret < 0) {
305 HIVIEW_LOGE("add to poll fail device %{public}s error=%{public}d, msg=%{public}s",
306 it->second->GetName().c_str(), errno, strerror(errno));
307 it->second->Close();
308 it = devs_.erase(it);
309 } else {
310 it++;
311 }
312 index++;
313 }
314
315 if (devs_.empty()) {
316 HIVIEW_LOGE("can not monitor any device");
317 return -1;
318 }
319 HIVIEW_LOGI("monitor devices %{public}u", devs_.size());
320 return 0;
321 }
322
Start()323 void EventServer::Start()
324 {
325 HIVIEW_LOGD("start event server");
326 if (OpenDevs() < 0) {
327 return;
328 }
329
330 int pollFd = epoll_create1(EPOLL_CLOEXEC);
331 if (pollFd < 0) {
332 HIVIEW_LOGE("create poll failed, error=%{public}d, msg=%{public}s", errno, strerror(errno));
333 return;
334 }
335
336 struct epoll_event pollEvents[devs_.size()];
337 if (AddToMonitor(pollFd, pollEvents) < 0) {
338 return;
339 }
340
341 HIVIEW_LOGI("go into event loop");
342 isStart_ = true;
343 while (isStart_) {
344 struct epoll_event chkPollEvents[devs_.size()];
345 int eventCount = epoll_wait(pollFd, chkPollEvents, devs_.size(), -1); // -1: Wait indefinitely
346 if (eventCount <= 0) {
347 HIVIEW_LOGD("read event timeout");
348 continue;
349 }
350 for (int ii = 0; ii < eventCount; ii++) {
351 auto it = devs_.find(chkPollEvents[ii].data.fd);
352 it->second->ReceiveMsg(receivers_);
353 }
354 }
355 CloseDevs();
356 }
357
CloseDevs()358 void EventServer::CloseDevs()
359 {
360 for (auto devItem : devs_) {
361 devItem.second->Close();
362 }
363 }
364
Stop()365 void EventServer::Stop()
366 {
367 isStart_ = false;
368 }
369
AddReceiver(std::shared_ptr<EventReceiver> receiver)370 void EventServer::AddReceiver(std::shared_ptr<EventReceiver> receiver)
371 {
372 receivers_.emplace_back(receiver);
373 }
374 } // namespace HiviewDFX
375 } // namespace OHOS
376