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 "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::__anon1bafc5850111::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 HIVIEW_LOGD("length of data received from client is %{public}d.", dataByteCnt);
225 EventRaw::DecodedEvent event(reinterpret_cast<uint8_t*>(buffer));
226 std::string eventJsonStr = event.AsJsonStr();
227 HIVIEW_LOGD("receive from client %{private}s", eventJsonStr.c_str());
228 if (!g_extraSocketPath.empty()) {
229 TransferEvent(eventJsonStr);
230 }
231 for (auto receiver = receivers.begin(); receiver != receivers.end(); receiver++) {
232 (*receiver)->HandlerEvent(event.GetRawData());
233 }
234 }
235 delete[] buffer;
236 return 0;
237 }
238
Close()239 int BBoxDevice::Close()
240 {
241 if (fd_ > 0) {
242 close(fd_);
243 fd_ = -1;
244 }
245 return 0;
246 }
247
Open()248 int BBoxDevice::Open()
249 {
250 fd_ = open("/dev/bbox", O_RDONLY, 0);
251 if (fd_ < 0) {
252 HIVIEW_LOGE("open bbox failed, error=%{public}d, msg=%{public}s", errno, strerror(errno));
253 return -1;
254 }
255 return fd_;
256 }
257
GetEvents()258 uint32_t BBoxDevice::GetEvents()
259 {
260 return EPOLLIN;
261 }
262
GetName()263 std::string BBoxDevice::GetName()
264 {
265 return "BBox";
266 }
267
ReceiveMsg(std::vector<std::shared_ptr<EventReceiver>> & receivers)268 int BBoxDevice::ReceiveMsg(std::vector<std::shared_ptr<EventReceiver>> &receivers)
269 {
270 char buffer[EVENT_READ_BUFFER];
271 (void)memset_s(buffer, sizeof(buffer), 0, sizeof(buffer));
272 int ret = read(fd_, buffer, EVENT_READ_BUFFER);
273 if (ret < static_cast<int>(EventRaw::GetValidDataMinimumByteCount())) {
274 return -1;
275 }
276 buffer[EVENT_READ_BUFFER - 1] = '\0';
277 int32_t dataByteCnt = *(reinterpret_cast<int32_t*>(buffer));
278 if (dataByteCnt != (ret - sizeof(struct Header) - 1)) { // extra bytes in kernel write
279 HIVIEW_LOGE("length of data received from kernel is invalid.");
280 return -1;
281 }
282 HIVIEW_LOGD("length of data received from kernel is %{public}d.", dataByteCnt);
283 EventRaw::DecodedEvent event(reinterpret_cast<uint8_t*>(buffer));
284 std::string eventJsonStr = event.AsJsonStr();
285 HIVIEW_LOGD("receive data from kernel %{private}s", eventJsonStr.c_str());
286 if (!g_extraSocketPath.empty()) {
287 TransferEvent(eventJsonStr);
288 }
289 for (auto receiver = receivers.begin(); receiver != receivers.end(); receiver++) {
290 (*receiver)->HandlerEvent(event.GetRawData());
291 }
292 return 0;
293 }
294
AddDev(std::shared_ptr<DeviceNode> dev)295 void EventServer::AddDev(std::shared_ptr<DeviceNode> dev)
296 {
297 int fd = dev->Open();
298 if (fd < 0) {
299 HIVIEW_LOGI("open device %{public}s failed", dev->GetName().c_str());
300 return;
301 }
302 devs_[fd] = dev;
303 }
304
OpenDevs()305 int EventServer::OpenDevs()
306 {
307 AddDev(std::make_shared<SocketDevice>());
308 AddDev(std::make_shared<BBoxDevice>());
309 if (devs_.empty()) {
310 HIVIEW_LOGE("can not open any device");
311 return -1;
312 }
313 HIVIEW_LOGI("has open %{public}u devices", devs_.size());
314 return 0;
315 }
316
AddToMonitor(int pollFd,struct epoll_event pollEvents[])317 int EventServer::AddToMonitor(int pollFd, struct epoll_event pollEvents[])
318 {
319 int index = 0;
320 auto it = devs_.begin();
321 while (it != devs_.end()) {
322 HIVIEW_LOGI("add to poll device %{public}s, fd=%{public}d", it->second->GetName().c_str(), it->first);
323 pollEvents[index].data.fd = it->first;
324 pollEvents[index].events = it->second->GetEvents();
325 int ret = epoll_ctl(pollFd, EPOLL_CTL_ADD, it->first, &pollEvents[index]);
326 if (ret < 0) {
327 HIVIEW_LOGE("add to poll fail device %{public}s error=%{public}d, msg=%{public}s",
328 it->second->GetName().c_str(), errno, strerror(errno));
329 it->second->Close();
330 it = devs_.erase(it);
331 } else {
332 it++;
333 }
334 index++;
335 }
336
337 if (devs_.empty()) {
338 HIVIEW_LOGE("can not monitor any device");
339 return -1;
340 }
341 HIVIEW_LOGI("monitor devices %{public}u", devs_.size());
342 return 0;
343 }
344
Start()345 void EventServer::Start()
346 {
347 HIVIEW_LOGD("start event server");
348 if (OpenDevs() < 0) {
349 return;
350 }
351
352 int pollFd = epoll_create1(EPOLL_CLOEXEC);
353 if (pollFd < 0) {
354 HIVIEW_LOGE("create poll failed, error=%{public}d, msg=%{public}s", errno, strerror(errno));
355 return;
356 }
357
358 struct epoll_event pollEvents[devs_.size()];
359 if (AddToMonitor(pollFd, pollEvents) < 0) {
360 return;
361 }
362
363 HIVIEW_LOGI("go into event loop");
364 isStart_ = true;
365 while (isStart_) {
366 struct epoll_event chkPollEvents[devs_.size()];
367 int eventCount = epoll_wait(pollFd, chkPollEvents, devs_.size(), -1); // -1: Wait indefinitely
368 if (eventCount <= 0) {
369 HIVIEW_LOGD("read event timeout");
370 continue;
371 }
372 for (int ii = 0; ii < eventCount; ii++) {
373 auto it = devs_.find(chkPollEvents[ii].data.fd);
374 it->second->ReceiveMsg(receivers_);
375 }
376 }
377 CloseDevs();
378 }
379
CloseDevs()380 void EventServer::CloseDevs()
381 {
382 for (auto devItem : devs_) {
383 devItem.second->Close();
384 }
385 }
386
Stop()387 void EventServer::Stop()
388 {
389 isStart_ = false;
390 }
391
AddReceiver(std::shared_ptr<EventReceiver> receiver)392 void EventServer::AddReceiver(std::shared_ptr<EventReceiver> receiver)
393 {
394 receivers_.emplace_back(receiver);
395 }
396 } // namespace HiviewDFX
397 } // namespace OHOS
398