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