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 31namespace OHOS { 32namespace Msdp { 33namespace DeviceStatus { 34namespace { 35constexpr int32_t MAX_EPOLL_EVENTS { 64 }; 36} // namespace 37 38int32_t SocketSessionManager::Init() 39{ 40 return epollMgr_.Open(); 41} 42 43void 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 56void 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 62int32_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 95CLOSE_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 105bool SocketSessionManager::SetBufferSize(int32_t sockFd, int32_t bufSize) 106{ 107 if (::setsockopt(sockFd, SOL_SOCKET, SO_SNDBUF, &bufSize, sizeof(bufSize)) != 0) { 108 FI_HILOGE("Set sockopt(%{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("Set sockopt(%{public}d) failed:%{public}s", sockFd, ::strerror(errno)); 113 return false; 114 } 115 return true; 116} 117 118SocketSessionPtr 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 127void 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 136void 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 153void 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 168void 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 186sptr<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 196std::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 202void 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 214bool 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 231void 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 244void SocketSessionManager::RemoveSessionDeletedCallback(int32_t pid) 245{ 246 FI_HILOGI("Stop watching socket-session(%{public}d)", pid); 247 callbacks_.erase(pid); 248} 249 250void 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