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