• 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 "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