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