• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
~SocketSessionManager()38 SocketSessionManager::~SocketSessionManager()
39 {
40     Disable();
41 }
42 
Enable()43 int32_t SocketSessionManager::Enable()
44 {
45     CALL_INFO_TRACE;
46     std::lock_guard<std::recursive_mutex> guard(mutex_);
47     if (!epollMgr_.Open()) {
48         FI_HILOGE("EpollMgr::Open fail");
49         return RET_ERR;
50     }
51     return RET_OK;
52 }
53 
Disable()54 void SocketSessionManager::Disable()
55 {
56     CALL_INFO_TRACE;
57     std::lock_guard<std::recursive_mutex> guard(mutex_);
58     epollMgr_.Close();
59     std::for_each(sessions_.cbegin(), sessions_.cend(), [this](const auto &item) {
60         CHKPV(item.second);
61         NotifySessionDeleted(item.second);
62     });
63     sessions_.clear();
64 }
65 
RegisterApplicationState()66 void SocketSessionManager::RegisterApplicationState()
67 {
68     CALL_DEBUG_ENTER;
69     auto appMgr = GetAppMgr();
70     CHKPV(appMgr);
71     appStateObserver_ = sptr<AppStateObserver>::MakeSptr(*this);
72     auto err = appMgr->RegisterApplicationStateObserver(appStateObserver_);
73     if (err != RET_OK) {
74         appStateObserver_ = nullptr;
75         FI_HILOGE("IAppMgr::RegisterApplicationStateObserver fail, error:%{public}d", err);
76     }
77 }
78 
OnProcessDied(const AppExecFwk::ProcessData & processData)79 void SocketSessionManager::AppStateObserver::OnProcessDied(const AppExecFwk::ProcessData &processData)
80 {
81     FI_HILOGI("\'%{public}s\' died, pid:%{public}d", processData.bundleName.c_str(), processData.pid);
82     socketSessionManager_.ReleaseSessionByPid(processData.pid);
83 }
84 
AllocSocketFd(const std::string & programName,int32_t moduleType,int32_t tokenType,int32_t uid,int32_t pid,int32_t & clientFd)85 int32_t SocketSessionManager::AllocSocketFd(const std::string& programName, int32_t moduleType, int32_t tokenType,
86                                             int32_t uid, int32_t pid, int32_t& clientFd)
87 {
88     CALL_INFO_TRACE;
89     int32_t sockFds[2] { -1, -1 };
90 
91     if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sockFds) != 0) {
92         FI_HILOGE("Call socketpair failed, errno:%{public}s", ::strerror(errno));
93         return RET_ERR;
94     }
95     static constexpr size_t BUFFER_SIZE { 32 * 1024 };
96     static constexpr size_t NATIVE_BUFFER_SIZE { 64 * 1024 };
97     std::shared_ptr<SocketSession> session { nullptr };
98 
99     if (!SetBufferSize(sockFds[0], BUFFER_SIZE)) {
100         goto CLOSE_SOCK;
101     }
102     if (!SetBufferSize(sockFds[1], tokenType == TokenType::TOKEN_NATIVE ? NATIVE_BUFFER_SIZE : BUFFER_SIZE)) {
103         goto CLOSE_SOCK;
104     }
105 
106     session = std::make_shared<SocketSession>(programName, moduleType, tokenType, sockFds[0], uid, pid);
107     if (!AddSession(session)) {
108         FI_HILOGE("AddSession failed, errCode:%{public}d", ADD_SESSION_FAIL);
109         if (sockFds[1] > 0 && ::close(sockFds[1]) != 0) {
110             FI_HILOGE("close(%{public}d) failed:%{public}s", sockFds[0], ::strerror(errno));
111         }
112         return RET_ERR;
113     }
114 
115     clientFd = sockFds[1];
116     return RET_OK;
117 
118 CLOSE_SOCK:
119     if (::close(sockFds[0]) != 0) {
120         FI_HILOGE("close(%{public}d) failed:%{public}s", sockFds[0], ::strerror(errno));
121     }
122     if (::close(sockFds[1]) != 0) {
123         FI_HILOGE("close(%{public}d) failed:%{public}s", sockFds[1], ::strerror(errno));
124     }
125     return RET_ERR;
126 }
127 
SetBufferSize(int32_t sockFd,int32_t bufSize)128 bool SocketSessionManager::SetBufferSize(int32_t sockFd, int32_t bufSize)
129 {
130     if (::setsockopt(sockFd, SOL_SOCKET, SO_SNDBUF, &bufSize, sizeof(bufSize)) != 0) {
131         FI_HILOGE("setsockopt(%{public}d) failed:%{public}s", sockFd, ::strerror(errno));
132         return false;
133     }
134     if (::setsockopt(sockFd, SOL_SOCKET, SO_RCVBUF, &bufSize, sizeof(bufSize)) != 0) {
135         FI_HILOGE("setsockopt(%{public}d) failed:%{public}s", sockFd, ::strerror(errno));
136         return false;
137     }
138     return true;
139 }
140 
FindSessionByPid(int32_t pid) const141 SocketSessionPtr SocketSessionManager::FindSessionByPid(int32_t pid) const
142 {
143     std::lock_guard<std::recursive_mutex> guard(mutex_);
144     auto iter = std::find_if(sessions_.cbegin(), sessions_.cend(),
145         [pid](const auto &item) {
146             return ((item.second != nullptr) && (item.second->GetPid() == pid));
147         });
148     return (iter != sessions_.cend() ? iter->second : nullptr);
149 }
150 
Dispatch(const struct epoll_event & ev)151 void SocketSessionManager::Dispatch(const struct epoll_event &ev)
152 {
153     if ((ev.events & EPOLLIN) == EPOLLIN) {
154         DispatchOne();
155     } else if ((ev.events & (EPOLLHUP | EPOLLERR)) != 0) {
156         FI_HILOGE("Epoll hangup:%{public}s", ::strerror(errno));
157     }
158 }
159 
DispatchOne()160 void SocketSessionManager::DispatchOne()
161 {
162     CALL_INFO_TRACE;
163     struct epoll_event evs[MAX_EPOLL_EVENTS];
164     std::lock_guard<std::recursive_mutex> guard(mutex_);
165     int32_t cnt = epollMgr_.WaitTimeout(evs, MAX_EPOLL_EVENTS, 0);
166 
167     for (int32_t index = 0; index < cnt; ++index) {
168         IEpollEventSource *source = reinterpret_cast<IEpollEventSource *>(evs[index].data.ptr);
169         CHKPC(source);
170         if ((evs[index].events & EPOLLIN) == EPOLLIN) {
171             OnEpollIn(*source);
172         } else if ((evs[index].events & (EPOLLHUP | EPOLLERR)) != 0) {
173             FI_HILOGW("Epoll hangup:%{public}s", ::strerror(errno));
174             ReleaseSession(source->GetFd());
175         }
176     }
177 }
178 
OnEpollIn(IEpollEventSource & source)179 void SocketSessionManager::OnEpollIn(IEpollEventSource &source)
180 {
181     CALL_DEBUG_ENTER;
182     char buf[MAX_PACKET_BUF_SIZE] {};
183     ssize_t numRead {};
184 
185     do {
186         numRead = ::recv(source.GetFd(), buf, sizeof(buf), MSG_DONTWAIT);
187         if (numRead > 0) {
188             FI_HILOGI("%{public}zd bytes received", numRead);
189         } else if (numRead < 0) {
190             if (errno == EINTR) {
191                 FI_HILOGD("recv was interrupted, read again");
192                 continue;
193             }
194             if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
195                 FI_HILOGW("No available data");
196             } else {
197                 FI_HILOGE("recv failed:%{public}s", ::strerror(errno));
198             }
199             break;
200         } else {
201             FI_HILOGE("EOF happened");
202             ReleaseSession(source.GetFd());
203             break;
204         }
205     } while (numRead == sizeof(buf));
206 }
207 
ReleaseSession(int32_t fd)208 void SocketSessionManager::ReleaseSession(int32_t fd)
209 {
210     CALL_DEBUG_ENTER;
211     std::lock_guard<std::recursive_mutex> guard(mutex_);
212     if (auto iter = sessions_.find(fd); iter != sessions_.end()) {
213         auto session = iter->second;
214         sessions_.erase(iter);
215 
216         if (session != nullptr) {
217             epollMgr_.Remove(session);
218             NotifySessionDeleted(session);
219         }
220     }
221     DumpSession("DelSession");
222 }
223 
DeleteCollaborationServiceByName()224 void SocketSessionManager::DeleteCollaborationServiceByName()
225 {
226     CALL_DEBUG_ENTER;
227     std::lock_guard<std::recursive_mutex> guard(mutex_);
228     auto iter = std::find_if(sessions_.cbegin(), sessions_.cend(),
229         [](const auto &item) {
230             return ((item.second != nullptr) && (item.second->GetProgramName() == "collaboration_service"));
231         });
232     if (iter != sessions_.end()) {
233         auto session = iter->second;
234         if (session != nullptr) {
235             epollMgr_.Remove(session);
236             NotifySessionDeleted(session);
237         }
238         sessions_.erase(iter);
239     }
240     DumpSession("DelSession");
241 }
242 
ReleaseSessionByPid(int32_t pid)243 void SocketSessionManager::ReleaseSessionByPid(int32_t pid)
244 {
245     CALL_DEBUG_ENTER;
246     std::lock_guard<std::recursive_mutex> guard(mutex_);
247     auto iter = std::find_if(sessions_.cbegin(), sessions_.cend(),
248         [pid](const auto &item) {
249             return ((item.second != nullptr) && (item.second->GetPid() == pid));
250         });
251     if (iter != sessions_.end()) {
252         auto session = iter->second;
253         if (session != nullptr) {
254             epollMgr_.Remove(session);
255             NotifySessionDeleted(session);
256         }
257         sessions_.erase(iter);
258     }
259     DumpSession("DelSession");
260 }
261 
GetAppMgr()262 sptr<AppExecFwk::IAppMgr> SocketSessionManager::GetAppMgr()
263 {
264     CALL_INFO_TRACE;
265     auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
266     CHKPP(saMgr);
267     auto appMgrObj = saMgr->GetSystemAbility(APP_MGR_SERVICE_ID);
268     CHKPP(appMgrObj);
269     return iface_cast<AppExecFwk::IAppMgr>(appMgrObj);
270 }
271 
FindSession(int32_t fd) const272 std::shared_ptr<SocketSession> SocketSessionManager::FindSession(int32_t fd) const
273 {
274     std::lock_guard<std::recursive_mutex> guard(mutex_);
275     auto iter = sessions_.find(fd);
276     return (iter != sessions_.cend() ? iter->second : nullptr);
277 }
278 
DumpSession(const std::string & title) const279 void SocketSessionManager::DumpSession(const std::string &title) const
280 {
281     FI_HILOGD("in %{public}s:%{public}s", __func__, title.c_str());
282     std::lock_guard<std::recursive_mutex> guard(mutex_);
283     int32_t i = 0;
284 
285     for (auto &[_, session] : sessions_) {
286         CHKPC(session);
287         FI_HILOGI("%{public}d, %{public}s", i, session->ToString().c_str());
288         i++;
289     }
290 }
291 
AddSession(std::shared_ptr<SocketSession> session)292 bool SocketSessionManager::AddSession(std::shared_ptr<SocketSession> session)
293 {
294     CALL_INFO_TRACE;
295     std::lock_guard<std::recursive_mutex> guard(mutex_);
296     CHKPF(session);
297     if (sessions_.size() >= MAX_SESSION_ALARM) {
298         FI_HILOGE("The number of connections exceeds limit(%{public}zu)", MAX_SESSION_ALARM);
299         return false;
300     }
301     auto [iter, inserted] = sessions_.emplace(session->GetFd(), session);
302     if (!inserted) {
303         FI_HILOGE("Session(%{public}d) has been recorded", session->GetFd());
304         return false;
305     }
306     if (!epollMgr_.Add(session)) {
307         FI_HILOGE("Failed to listening on session(%{public}d)", session->GetFd());
308         sessions_.erase(iter);
309         return false;
310     }
311     DumpSession("AddSession");
312     return true;
313 }
314 
AddSessionDeletedCallback(int32_t pid,std::function<void (SocketSessionPtr)> callback)315 void SocketSessionManager::AddSessionDeletedCallback(int32_t pid, std::function<void(SocketSessionPtr)> callback)
316 {
317     std::lock_guard<std::recursive_mutex> guard(mutex_);
318     if (callback == nullptr) {
319         FI_HILOGE("Callback is none");
320         return;
321     }
322     auto [_, inserted] = callbacks_.emplace(pid, callback);
323     if (!inserted) {
324         FI_HILOGW("Duplication of session-lost callback for (%{public}d)", pid);
325     }
326     FI_HILOGI("Start watching socket-session(%{public}d)", pid);
327 }
328 
RemoveSessionDeletedCallback(int32_t pid)329 void SocketSessionManager::RemoveSessionDeletedCallback(int32_t pid)
330 {
331     FI_HILOGI("Stop watching socket-session(%{public}d)", pid);
332     std::lock_guard<std::recursive_mutex> guard(mutex_);
333     callbacks_.erase(pid);
334 }
335 
NotifySessionDeleted(std::shared_ptr<SocketSession> session)336 void SocketSessionManager::NotifySessionDeleted(std::shared_ptr<SocketSession> session)
337 {
338     FI_HILOGI("Session lost, pid:%{public}d", session->GetPid());
339     if (auto iter = callbacks_.find(session->GetPid()); iter != callbacks_.end()) {
340         if (iter->second) {
341             iter->second(session);
342         }
343         callbacks_.erase(iter);
344     }
345 }
346 } // namespace DeviceStatus
347 } // namespace Msdp
348 } // namespace OHOS
349