1 /*
2  * Copyright (c) 2023 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 "socket_session_manager.h"
17 
18 #include <algorithm>
19 
20 #include <sys/socket.h>
21 #include <unistd.h>
22 
23 #include "iservice_registry.h"
24 #include "system_ability_definition.h"
25 
26 #include "devicestatus_define.h"
27 
28 #undef LOG_TAG
29 #define LOG_TAG "SocketSessionManager"
30 
31 namespace OHOS {
32 namespace Msdp {
33 namespace DeviceStatus {
34 namespace {
35 constexpr int32_t MAX_EPOLL_EVENTS { 64 };
36 } // namespace
37 
38 std::recursive_mutex SocketSessionManager::mutex_;
39 
Init()40 int32_t SocketSessionManager::Init()
41 {
42     CALL_INFO_TRACE;
43     return epollMgr_.Open();
44 }
45 
RegisterApplicationState()46 void SocketSessionManager::RegisterApplicationState()
47 {
48     CALL_DEBUG_ENTER;
49     auto appMgr = GetAppMgr();
50     CHKPV(appMgr);
51     appStateObserver_ = sptr<AppStateObserver>::MakeSptr(*this);
52     auto err = appMgr->RegisterApplicationStateObserver(appStateObserver_);
53     if (err != RET_OK) {
54         appStateObserver_ = nullptr;
55         FI_HILOGE("IAppMgr::RegisterApplicationStateObserver fail, error:%{public}d", err);
56     }
57 }
58 
OnProcessDied(const AppExecFwk::ProcessData & processData)59 void SocketSessionManager::AppStateObserver::OnProcessDied(const AppExecFwk::ProcessData &processData)
60 {
61     FI_HILOGI("\'%{public}s\' died, pid:%{public}d", processData.bundleName.c_str(), processData.pid);
62     socketSessionManager_.ReleaseSessionByPid(processData.pid);
63 }
64 
AllocSocketFd(const std::string & programName,int32_t moduleType,int32_t tokenType,int32_t uid,int32_t pid,int32_t & clientFd)65 int32_t SocketSessionManager::AllocSocketFd(const std::string& programName, int32_t moduleType, int32_t tokenType,
66                                             int32_t uid, int32_t pid, int32_t& clientFd)
67 {
68     CALL_DEBUG_ENTER;
69     int32_t sockFds[2] { -1, -1 };
70 
71     if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sockFds) != 0) {
72         FI_HILOGE("Call socketpair failed, errno:%{public}s", ::strerror(errno));
73         return RET_ERR;
74     }
75     static constexpr size_t BUFFER_SIZE { 32 * 1024 };
76     static constexpr size_t NATIVE_BUFFER_SIZE { 64 * 1024 };
77     std::shared_ptr<SocketSession> session { nullptr };
78 
79     if (!SetBufferSize(sockFds[0], BUFFER_SIZE)) {
80         goto CLOSE_SOCK;
81     }
82     if (!SetBufferSize(sockFds[1], tokenType == TokenType::TOKEN_NATIVE ? NATIVE_BUFFER_SIZE : BUFFER_SIZE)) {
83         goto CLOSE_SOCK;
84     }
85 
86     session = std::make_shared<SocketSession>(programName, moduleType, tokenType, sockFds[0], uid, pid);
87     if (epollMgr_.Add(*session) != RET_OK) {
88         goto CLOSE_SOCK;
89     }
90     if (!AddSession(session)) {
91         FI_HILOGE("AddSession failed, errCode:%{public}d", ADD_SESSION_FAIL);
92         goto CLOSE_SOCK;
93     }
94 
95     clientFd = sockFds[1];
96     return RET_OK;
97 
98 CLOSE_SOCK:
99     if (::close(sockFds[0]) != 0) {
100         FI_HILOGE("close(%{public}d) failed:%{public}s", sockFds[0], ::strerror(errno));
101     }
102     if (::close(sockFds[1]) != 0) {
103         FI_HILOGE("close(%{public}d) failed:%{public}s", sockFds[1], ::strerror(errno));
104     }
105     return RET_ERR;
106 }
107 
SetBufferSize(int32_t sockFd,int32_t bufSize)108 bool SocketSessionManager::SetBufferSize(int32_t sockFd, int32_t bufSize)
109 {
110     if (::setsockopt(sockFd, SOL_SOCKET, SO_SNDBUF, &bufSize, sizeof(bufSize)) != 0) {
111         FI_HILOGE("setsockopt(%{public}d) failed:%{public}s", sockFd, ::strerror(errno));
112         return false;
113     }
114     if (::setsockopt(sockFd, SOL_SOCKET, SO_RCVBUF, &bufSize, sizeof(bufSize)) != 0) {
115         FI_HILOGE("setsockopt(%{public}d) failed:%{public}s", sockFd, ::strerror(errno));
116         return false;
117     }
118     return true;
119 }
120 
FindSessionByPid(int32_t pid) const121 SocketSessionPtr SocketSessionManager::FindSessionByPid(int32_t pid) const
122 {
123     std::lock_guard<std::recursive_mutex> guard(mutex_);
124     auto iter = std::find_if(sessions_.cbegin(), sessions_.cend(),
125         [pid](const auto &item) {
126             return ((item.second != nullptr) && (item.second->GetPid() == pid));
127         });
128     return (iter != sessions_.cend() ? iter->second : nullptr);
129 }
130 
Dispatch(const struct epoll_event & ev)131 void SocketSessionManager::Dispatch(const struct epoll_event &ev)
132 {
133     if ((ev.events & EPOLLIN) == EPOLLIN) {
134         DispatchOne();
135     } else if ((ev.events & (EPOLLHUP | EPOLLERR)) != 0) {
136         FI_HILOGE("Epoll hangup:%{public}s", ::strerror(errno));
137     }
138 }
139 
DispatchOne()140 void SocketSessionManager::DispatchOne()
141 {
142     struct epoll_event evs[MAX_EPOLL_EVENTS];
143     int32_t cnt = epollMgr_.WaitTimeout(evs, MAX_EPOLL_EVENTS, 0);
144 
145     for (int32_t index = 0; index < cnt; ++index) {
146         IEpollEventSource *source = reinterpret_cast<IEpollEventSource *>(evs[index].data.ptr);
147         CHKPC(source);
148         if ((evs[index].events & EPOLLIN) == EPOLLIN) {
149             source->Dispatch(evs[index]);
150         } else if ((evs[index].events & (EPOLLHUP | EPOLLERR)) != 0) {
151             FI_HILOGE("Epoll hangup:%{public}s", ::strerror(errno));
152             ReleaseSession(source->GetFd());
153         }
154     }
155 }
156 
ReleaseSession(int32_t fd)157 void SocketSessionManager::ReleaseSession(int32_t fd)
158 {
159     CALL_DEBUG_ENTER;
160     std::lock_guard<std::recursive_mutex> guard(mutex_);
161     if (auto iter = sessions_.find(fd); iter != sessions_.end()) {
162         auto session = iter->second;
163         sessions_.erase(iter);
164 
165         if (session != nullptr) {
166             epollMgr_.Remove(*session);
167             NotifySessionDeleted(session);
168         }
169     }
170     DumpSession("DelSession");
171 }
172 
DeleteCollaborationServiceByName()173 void SocketSessionManager::DeleteCollaborationServiceByName()
174 {
175     CALL_DEBUG_ENTER;
176     std::lock_guard<std::recursive_mutex> guard(mutex_);
177     auto iter = std::find_if(sessions_.cbegin(), sessions_.cend(),
178         [](const auto &item) {
179             return ((item.second != nullptr) && (item.second->GetProgramName() == "collaboration_service"));
180         });
181     if (iter != sessions_.end()) {
182         auto session = iter->second;
183         if (session != nullptr) {
184             epollMgr_.Remove(*session);
185             NotifySessionDeleted(session);
186         }
187         sessions_.erase(iter);
188     }
189     DumpSession("DelSession");
190 }
191 
ReleaseSessionByPid(int32_t pid)192 void SocketSessionManager::ReleaseSessionByPid(int32_t pid)
193 {
194     CALL_DEBUG_ENTER;
195     std::lock_guard<std::recursive_mutex> guard(mutex_);
196     auto iter = std::find_if(sessions_.cbegin(), sessions_.cend(),
197         [pid](const auto &item) {
198             return ((item.second != nullptr) && (item.second->GetPid() == pid));
199         });
200     if (iter != sessions_.end()) {
201         auto session = iter->second;
202         if (session != nullptr) {
203             epollMgr_.Remove(*session);
204             NotifySessionDeleted(session);
205         }
206         sessions_.erase(iter);
207     }
208     DumpSession("DelSession");
209 }
210 
GetAppMgr()211 sptr<AppExecFwk::IAppMgr> SocketSessionManager::GetAppMgr()
212 {
213     CALL_INFO_TRACE;
214     auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
215     CHKPP(saMgr);
216     auto appMgrObj = saMgr->GetSystemAbility(APP_MGR_SERVICE_ID);
217     CHKPP(appMgrObj);
218     return iface_cast<AppExecFwk::IAppMgr>(appMgrObj);
219 }
220 
FindSession(int32_t fd) const221 std::shared_ptr<SocketSession> SocketSessionManager::FindSession(int32_t fd) const
222 {
223     std::lock_guard<std::recursive_mutex> guard(mutex_);
224     auto iter = sessions_.find(fd);
225     return (iter != sessions_.cend() ? iter->second : nullptr);
226 }
227 
DumpSession(const std::string & title) const228 void SocketSessionManager::DumpSession(const std::string &title) const
229 {
230     FI_HILOGD("in %{public}s:%{public}s", __func__, title.c_str());
231     std::lock_guard<std::recursive_mutex> guard(mutex_);
232     int32_t i = 0;
233 
234     for (auto &[_, session] : sessions_) {
235         CHKPC(session);
236         FI_HILOGI("%{public}d, %{public}s", i, session->ToString().c_str());
237         i++;
238     }
239 }
240 
AddSession(std::shared_ptr<SocketSession> session)241 bool SocketSessionManager::AddSession(std::shared_ptr<SocketSession> session)
242 {
243     CALL_DEBUG_ENTER;
244     std::lock_guard<std::recursive_mutex> guard(mutex_);
245     CHKPF(session);
246     if (sessions_.size() >= MAX_SESSION_ALARM) {
247         FI_HILOGE("The number of connections exceeds limit(%{public}zu)", MAX_SESSION_ALARM);
248         return false;
249     }
250     auto [_, inserted] = sessions_.emplace(session->GetFd(), session);
251     if (!inserted) {
252         FI_HILOGE("Session(%{public}d) has been recorded", session->GetFd());
253         return false;
254     }
255     DumpSession("AddSession");
256     return true;
257 }
258 
AddSessionDeletedCallback(int32_t pid,std::function<void (SocketSessionPtr)> callback)259 void SocketSessionManager::AddSessionDeletedCallback(int32_t pid, std::function<void(SocketSessionPtr)> callback)
260 {
261     std::lock_guard<std::recursive_mutex> guard(mutex_);
262     if (callback == nullptr) {
263         FI_HILOGE("Callback is none");
264         return;
265     }
266     auto [_, inserted] = callbacks_.emplace(pid, callback);
267     if (!inserted) {
268         FI_HILOGW("Duplication of session-lost callback for (%{public}d)", pid);
269     }
270     FI_HILOGI("Start watching socket-session(%{public}d)", pid);
271 }
272 
RemoveSessionDeletedCallback(int32_t pid)273 void SocketSessionManager::RemoveSessionDeletedCallback(int32_t pid)
274 {
275     FI_HILOGI("Stop watching socket-session(%{public}d)", pid);
276     std::lock_guard<std::recursive_mutex> guard(mutex_);
277     callbacks_.erase(pid);
278 }
279 
NotifySessionDeleted(std::shared_ptr<SocketSession> session)280 void SocketSessionManager::NotifySessionDeleted(std::shared_ptr<SocketSession> session)
281 {
282     std::lock_guard<std::recursive_mutex> guard(mutex_);
283     CHKPV(session);
284     FI_HILOGI("Session lost, pid:%{public}d", session->GetPid());
285     if (auto iter = callbacks_.find(session->GetPid()); iter != callbacks_.end()) {
286         if (iter->second) {
287             iter->second(session);
288         }
289         callbacks_.erase(iter);
290     }
291 }
292 } // namespace DeviceStatus
293 } // namespace Msdp
294 } // namespace OHOS
295