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