• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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