• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 "dfx_hisysevent.h"
17 #include "i_multimodal_input_connect.h"
18 #include "util_ex.h"
19 
20 #undef MMI_LOG_DOMAIN
21 #define MMI_LOG_DOMAIN MMI_LOG_SERVER
22 #undef MMI_LOG_TAG
23 #define MMI_LOG_TAG "UDSServer"
24 
25 namespace OHOS {
26 namespace MMI {
~UDSServer()27 UDSServer::~UDSServer()
28 {
29     CALL_DEBUG_ENTER;
30     UdsStop();
31 }
32 
UdsStop()33 void UDSServer::UdsStop()
34 {
35     if (epollFd_ != -1) {
36         close(epollFd_);
37         epollFd_ = -1;
38     }
39 
40     for (const auto &item : sessionsMap_) {
41         item.second->Close();
42     }
43     sessionsMap_.clear();
44 }
45 
GetClientFd(int32_t pid) const46 int32_t UDSServer::GetClientFd(int32_t pid) const
47 {
48     auto it = idxPidMap_.find(pid);
49     if (it == idxPidMap_.end()) {
50         if (pid_ != pid) {
51             pid_ = pid;
52             MMI_HILOGE("Not found pid:%{public}d", pid);
53         }
54         return INVALID_FD;
55     }
56     return it->second;
57 }
58 
GetClientPid(int32_t fd) const59 int32_t UDSServer::GetClientPid(int32_t fd) const
60 {
61     auto it = sessionsMap_.find(fd);
62     if (it == sessionsMap_.end()) {
63         MMI_HILOGE("Not found fd:%{public}d", fd);
64         return INVALID_PID;
65     }
66     return it->second->GetPid();
67 }
68 
SendMsg(int32_t fd,NetPacket & pkt)69 bool UDSServer::SendMsg(int32_t fd, NetPacket& pkt)
70 {
71     if (fd < 0) {
72         MMI_HILOGE("The fd is less than 0");
73         return false;
74     }
75     auto ses = GetSession(fd);
76     if (ses == nullptr) {
77         MMI_HILOGE("The fd:%{public}d not found, The message was discarded. errCode:%{public}d",
78                    fd, SESSION_NOT_FOUND);
79         return false;
80     }
81     return ses->SendMsg(pkt);
82 }
83 
Multicast(const std::vector<int32_t> & fdList,NetPacket & pkt)84 void UDSServer::Multicast(const std::vector<int32_t>& fdList, NetPacket& pkt)
85 {
86     for (const auto &item : fdList) {
87         SendMsg(item, pkt);
88     }
89 }
90 
AddSocketPairInfo(const std::string & programName,const int32_t moduleType,const int32_t uid,const int32_t pid,int32_t & serverFd,int32_t & toReturnClientFd,int32_t & tokenType)91 int32_t UDSServer::AddSocketPairInfo(const std::string& programName,
92     const int32_t moduleType, const int32_t uid, const int32_t pid,
93     int32_t& serverFd, int32_t& toReturnClientFd, int32_t& tokenType)
94 {
95     CALL_DEBUG_ENTER;
96     int32_t sockFds[2] = { -1 };
97 
98     if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockFds) != 0) {
99         MMI_HILOGE("Call socketpair failed, errno:%{public}d", errno);
100         return RET_ERR;
101     }
102     serverFd = sockFds[0];
103     toReturnClientFd = sockFds[1];
104     if (serverFd < 0 || toReturnClientFd < 0) {
105         MMI_HILOGE("Call fcntl failed, errno:%{public}d", errno);
106         return RET_ERR;
107     }
108 
109     SessionPtr sess = nullptr;
110     bool readOnly = false;
111     if (SetFdProperty(tokenType, serverFd, toReturnClientFd, programName, readOnly) != RET_OK) {
112         MMI_HILOGE("SetFdProperty failed");
113         goto CLOSE_SOCK;
114     }
115 
116     if (AddEpoll(EPOLL_EVENT_SOCKET, serverFd, readOnly) != RET_OK) {
117         MMI_HILOGE("Add epoll failed, errCode:%{public}d", EPOLL_MODIFY_FAIL);
118         goto CLOSE_SOCK;
119     }
120     sess = std::make_shared<UDSSession>(programName, moduleType, serverFd, uid, pid);
121     if (sess == nullptr) {
122         MMI_HILOGE("Make shared pointer fail. programName:%{public}s, pid:%{public}d, errCode:%{public}d",
123             programName.c_str(), pid, MAKE_SHARED_FAIL);
124         goto CLOSE_SOCK;
125     }
126     sess->SetTokenType(tokenType);
127     if (!AddSession(sess)) {
128         MMI_HILOGE("AddSession fail errCode:%{public}d", ADD_SESSION_FAIL);
129         goto CLOSE_SOCK;
130     }
131     OnConnected(sess);
132     return RET_OK;
133 
134     CLOSE_SOCK:
135     close(serverFd);
136     serverFd = IMultimodalInputConnect::INVALID_SOCKET_FD;
137     close(toReturnClientFd);
138     toReturnClientFd = IMultimodalInputConnect::INVALID_SOCKET_FD;
139     return RET_ERR;
140 }
141 
SetFdProperty(int32_t & tokenType,int32_t & serverFd,int32_t & toReturnClientFd,const std::string & programName,bool & readOnly)142 int32_t UDSServer::SetFdProperty(int32_t &tokenType, int32_t &serverFd, int32_t &toReturnClientFd,
143     const std::string &programName, bool &readOnly)
144 {
145     static size_t bufferSize = 64 * 1024;
146     static size_t serverBufferSize = 64 * 1024;
147     static size_t nativeBufferSize = 128 * 1024;
148 #ifdef OHOS_BUILD_ENABLE_ANCO
149     bufferSize = 512 * 1024;
150     nativeBufferSize = 1024 * 1024;
151 #endif // OHOS_BUILD_ENABLE_ANCO
152 
153     if (setsockopt(serverFd, SOL_SOCKET, SO_SNDBUF, &serverBufferSize, sizeof(bufferSize)) != 0) {
154         MMI_HILOGE("Setsockopt serverFd failed, errno:%{public}d", errno);
155         return RET_ERR;
156     }
157     if (setsockopt(serverFd, SOL_SOCKET, SO_RCVBUF, &serverBufferSize, sizeof(bufferSize)) != 0) {
158         MMI_HILOGE("Setsockopt serverFd failed, errno:%{public}d", errno);
159         return RET_ERR;
160     }
161     if (tokenType == TokenType::TOKEN_NATIVE) {
162         if (setsockopt(toReturnClientFd, SOL_SOCKET, SO_SNDBUF, &nativeBufferSize, sizeof(nativeBufferSize)) != 0) {
163             MMI_HILOGE("Setsockopt toReturnClientFd failed, errno:%{public}d", errno);
164             return RET_ERR;
165         }
166         if (setsockopt(toReturnClientFd, SOL_SOCKET, SO_RCVBUF, &nativeBufferSize, sizeof(nativeBufferSize)) != 0) {
167             MMI_HILOGE("Setsockopt toReturnClientFd failed, errno:%{public}d", errno);
168             return RET_ERR;
169         }
170     } else {
171         if (setsockopt(toReturnClientFd, SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize)) != 0) {
172             MMI_HILOGE("Setsockopt toReturnClientFd failed, errno:%{public}d", errno);
173             return RET_ERR;
174         }
175         if (setsockopt(toReturnClientFd, SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize)) != 0) {
176             MMI_HILOGE("Setsockopt toReturnClientFd failed, errno:%{public}d", errno);
177             return RET_ERR;
178         }
179     }
180     const std::vector<std::string> programWhitelist = {
181         "com.ohos.systemui", "security_component_service"};
182     if (std::find(programWhitelist.begin(), programWhitelist.end(), programName) == programWhitelist.end()) {
183         MMI_HILOGD("toReturnClientFd shutdown SHUT_WR , programName:%{public}s", programName.c_str());
184     }
185     return RET_OK;
186 }
187 
Dump(int32_t fd,const std::vector<std::string> & args)188 void UDSServer::Dump(int32_t fd, const std::vector<std::string> &args)
189 {
190     CALL_DEBUG_ENTER;
191     mprintf(fd, "Uds_server information:\t");
192     mprintf(fd, "uds_server: count=%zu", sessionsMap_.size());
193     for (const auto &item : sessionsMap_) {
194         std::shared_ptr<UDSSession> udsSession = item.second;
195         CHKPV(udsSession);
196         mprintf(fd,
197                 "Uid:%d | Pid:%d | Fd:%d | TokenType:%d | Descript:%s\t",
198                 udsSession->GetUid(), udsSession->GetPid(), udsSession->GetFd(),
199                 udsSession->GetTokenType(), udsSession->GetDescript().c_str());
200     }
201 }
202 
OnConnected(SessionPtr sess)203 void UDSServer::OnConnected(SessionPtr sess)
204 {
205     CHKPV(sess);
206     MMI_HILOGI("Session desc:%{public}s", sess->GetDescript().c_str());
207 }
208 
OnDisconnected(SessionPtr sess)209 void UDSServer::OnDisconnected(SessionPtr sess)
210 {
211     CHKPV(sess);
212     MMI_HILOGI("Session desc:%{public}s", sess->GetDescript().c_str());
213 }
214 
AddEpoll(EpollEventType type,int32_t fd,bool readOnly)215 int32_t UDSServer::AddEpoll(EpollEventType type, int32_t fd, bool readOnly)
216 {
217     MMI_HILOGE("This information should not exist. Subclasses should implement this function");
218     return RET_ERR;
219 }
220 
SetRecvFun(MsgServerFunCallback fun)221 void UDSServer::SetRecvFun(MsgServerFunCallback fun)
222 {
223     recvFun_ = fun;
224 }
225 
ReleaseSession(int32_t fd,epoll_event & ev)226 void UDSServer::ReleaseSession(int32_t fd, epoll_event& ev)
227 {
228     CALL_DEBUG_ENTER;
229     auto secPtr = GetSession(fd);
230     if (secPtr != nullptr) {
231         OnDisconnected(secPtr);
232         DelSession(fd);
233     } else {
234         MMI_HILOGE("Get session secPtr is nullptr, fd:%{public}d", fd);
235         DfxHisysevent::OnClientDisconnect(secPtr, fd, OHOS::HiviewDFX::HiSysEvent::EventType::FAULT);
236     }
237     if (ev.data.ptr) {
238         RemoveEpollEvent(fd);
239         ev.data.ptr = nullptr;
240     }
241     if (auto it = circleBufMap_.find(fd); it != circleBufMap_.end()) {
242         circleBufMap_.erase(it);
243     } else {
244         MMI_HILOGE("Can't find fd");
245     }
246     if (close(fd) == RET_OK) {
247         DfxHisysevent::OnClientDisconnect(secPtr, fd, OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR);
248     } else {
249         DfxHisysevent::OnClientDisconnect(secPtr, fd, OHOS::HiviewDFX::HiSysEvent::EventType::FAULT);
250     }
251 }
252 
OnPacket(int32_t fd,NetPacket & pkt)253 void UDSServer::OnPacket(int32_t fd, NetPacket& pkt)
254 {
255     auto sess = GetSession(fd);
256     CHKPV(sess);
257     recvFun_(sess, pkt);
258 }
259 
OnEpollRecv(int32_t fd,epoll_event & ev)260 void UDSServer::OnEpollRecv(int32_t fd, epoll_event& ev)
261 {
262     if (fd < 0) {
263         MMI_HILOGE("Invalid input param fd:%{public}d", fd);
264         return;
265     }
266     auto& buf = circleBufMap_[fd];
267     char szBuf[MAX_PACKET_BUF_SIZE] = {};
268     for (int32_t i = 0; i < MAX_RECV_LIMIT; i++) {
269         auto size = recv(fd, szBuf, MAX_PACKET_BUF_SIZE, MSG_DONTWAIT | MSG_NOSIGNAL);
270         if (size > 0) {
271             if (!buf.Write(szBuf, size)) {
272                 MMI_HILOGW("Write data failed. size:%{public}zu", size);
273             }
274             OnReadPackets(buf, [this, fd] (NetPacket& pkt) { return this->OnPacket(fd, pkt); });
275         } else if (size < 0) {
276             if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK) {
277                 MMI_HILOGD("Continue for errno EAGAIN|EINTR|EWOULDBLOCK size:%{public}zu, errno:%{public}d",
278                     size, errno);
279                 continue;
280             }
281             MMI_HILOGE("Recv return %{public}zu errno:%{public}d", size, errno);
282             break;
283         } else {
284             MMI_HILOGE("The client side disconnect with the server. size:0 errno:%{public}d", errno);
285             ReleaseSession(fd, ev);
286             break;
287         }
288         if (size < MAX_PACKET_BUF_SIZE) {
289             break;
290         }
291     }
292 }
293 
OnEpollEvent(epoll_event & ev)294 void UDSServer::OnEpollEvent(epoll_event& ev)
295 {
296     CHKPV(ev.data.ptr);
297     auto fd = ev.data.fd;
298     if (fd < 0) {
299         MMI_HILOGE("The fd less than 0, errCode:%{public}d", PARAM_INPUT_INVALID);
300         return;
301     }
302     if ((ev.events & EPOLLERR) || (ev.events & EPOLLHUP)) {
303         MMI_HILOGI("EPOLLERR or EPOLLHUP fd:%{public}d, ev.events:0x%{public}x", fd, ev.events);
304         ReleaseSession(fd, ev);
305     } else if (ev.events & EPOLLIN) {
306         OnEpollRecv(fd, ev);
307     }
308 }
309 
AddEpollEvent(int32_t fd,std::shared_ptr<mmi_epoll_event> epollEvent)310 void UDSServer::AddEpollEvent(int32_t fd, std::shared_ptr<mmi_epoll_event> epollEvent)
311 {
312     MMI_HILOGI("Add %{public}d in epollEvent map", fd);
313     epollEventMap_[fd] = epollEvent;
314 }
315 
RemoveEpollEvent(int32_t fd)316 void UDSServer::RemoveEpollEvent(int32_t fd)
317 {
318     MMI_HILOGI("Remove %{public}d in epollEvent map", fd);
319     epollEventMap_.erase(fd);
320 }
321 
DumpSession(const std::string & title)322 void UDSServer::DumpSession(const std::string &title)
323 {
324     MMI_HILOGD("in %s: %s", __func__, title.c_str());
325     int32_t i = 0;
326     for (auto &[key, value] : sessionsMap_) {
327         CHKPV(value);
328         MMI_HILOGD("%d, %s", i, value->GetDescript().c_str());
329         i++;
330     }
331 }
332 
GetSession(int32_t fd) const333 SessionPtr UDSServer::GetSession(int32_t fd) const
334 {
335     auto it = sessionsMap_.find(fd);
336     if (it == sessionsMap_.end()) {
337         MMI_HILOGE("Session not found. fd:%{public}d", fd);
338         return nullptr;
339     }
340     CHKPP(it->second);
341     return it->second->GetSharedPtr();
342 }
343 
GetSessionByPid(int32_t pid) const344 SessionPtr UDSServer::GetSessionByPid(int32_t pid) const
345 {
346     int32_t fd = GetClientFd(pid);
347     if (fd <= 0) {
348         if (pid_ != pid) {
349             pid_ = pid;
350             MMI_HILOGE("Session not found. pid:%{public}d", pid);
351         }
352         return nullptr;
353     }
354     return GetSession(fd);
355 }
356 
AddSession(SessionPtr ses)357 bool UDSServer::AddSession(SessionPtr ses)
358 {
359     CHKPF(ses);
360     MMI_HILOGI("The pid:%{public}d, fd:%{public}d", ses->GetPid(), ses->GetFd());
361     auto fd = ses->GetFd();
362     if (fd < 0) {
363         MMI_HILOGE("The fd is less than 0");
364         return false;
365     }
366     auto pid = ses->GetPid();
367     if (pid <= 0) {
368         MMI_HILOGE("Get process failed");
369         return false;
370     }
371     idxPidMap_[pid] = fd;
372     sessionsMap_[fd] = ses;
373     DumpSession("AddSession");
374     if (sessionsMap_.size() > MAX_SESSON_ALARM) {
375         MMI_HILOGW("Too many clients. Warning Value:%{public}d, Current Value:%{public}zd",
376                    MAX_SESSON_ALARM, sessionsMap_.size());
377     }
378     MMI_HILOGI("AddSession end");
379     return true;
380 }
381 
DelSession(int32_t fd)382 void UDSServer::DelSession(int32_t fd)
383 {
384     CALL_DEBUG_ENTER;
385     MMI_HILOGI("The fd:%{public}d", fd);
386     if (fd < 0) {
387         MMI_HILOGE("The fd less than 0, errCode:%{public}d", PARAM_INPUT_INVALID);
388         return;
389     }
390     auto pid = GetClientPid(fd);
391     MMI_HILOGI("The pid:%{public}d", pid);
392     if (pid > 0) {
393         idxPidMap_.erase(pid);
394     }
395     auto it = sessionsMap_.find(fd);
396     if (it != sessionsMap_.end()) {
397         NotifySessionDeleted(it->second);
398         sessionsMap_.erase(it);
399     }
400     DumpSession("DelSession");
401 }
402 
AddSessionDeletedCallback(std::function<void (SessionPtr)> callback)403 void UDSServer::AddSessionDeletedCallback(std::function<void(SessionPtr)> callback)
404 {
405     CALL_DEBUG_ENTER;
406     callbacks_.push_back(callback);
407 }
408 
NotifySessionDeleted(SessionPtr ses)409 void UDSServer::NotifySessionDeleted(SessionPtr ses)
410 {
411     CALL_DEBUG_ENTER;
412     for (const auto &callback : callbacks_) {
413         callback(ses);
414     }
415 }
416 } // namespace MMI
417 } // namespace OHOS
418