1 /*
2 * Copyright (C) 2024-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 "databus_socket_listener.h"
17
18 #include <charconv>
19 #include "dbinder_databus_invoker.h"
20 #include "dsoftbus_interface.h"
21 #include "ipc_debug.h"
22 #include "ipc_process_skeleton.h"
23 #include "ipc_thread_skeleton.h"
24 #include "log_tags.h"
25
26 namespace OHOS {
27 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_ID_RPC_REMOTE_LISTENER, "DatabusSocketListener" };
28
DBinderSocketInfo(const std::string & ownName,const std::string & peerName,const std::string & networkId)29 DBinderSocketInfo::DBinderSocketInfo(const std::string &ownName, const std::string &peerName,
30 const std::string &networkId)
31 : ownName_(ownName), peerName_(peerName), networkId_(networkId)
32 {
33 }
34
GetOwnName() const35 std::string DBinderSocketInfo::GetOwnName() const
36 {
37 return ownName_;
38 }
39
GetPeerName() const40 std::string DBinderSocketInfo::GetPeerName() const
41 {
42 return peerName_;
43 }
44
GetNetworkId() const45 std::string DBinderSocketInfo::GetNetworkId() const
46 {
47 return networkId_;
48 }
49
DatabusSocketListener()50 DatabusSocketListener::DatabusSocketListener()
51 {
52 serverListener_.OnBind = DatabusSocketListener::ServerOnBind;
53 serverListener_.OnShutdown = DatabusSocketListener::ServerOnShutdown;
54 serverListener_.OnBytes = DatabusSocketListener::OnBytesReceived;
55 serverListener_.OnMessage = DatabusSocketListener::OnBytesReceived;
56
57 clientListener_.OnBind = DatabusSocketListener::ClientOnBind;
58 clientListener_.OnShutdown = DatabusSocketListener::ClientOnShutdown;
59 clientListener_.OnBytes = DatabusSocketListener::OnBytesReceived;
60 clientListener_.OnMessage = DatabusSocketListener::OnBytesReceived;
61 }
62
~DatabusSocketListener()63 DatabusSocketListener::~DatabusSocketListener() {}
64
ServerOnBind(int32_t socket,PeerSocketInfo info)65 void DatabusSocketListener::ServerOnBind(int32_t socket, PeerSocketInfo info)
66 {
67 ZLOGI(LABEL, "socketId:%{public}d, deviceId:%{public}s, peerName:%{public}s", socket,
68 IPCProcessSkeleton::ConvertToSecureString(info.networkId).c_str(), info.name);
69
70 std::string networkId = info.networkId;
71 std::string peerName = info.name;
72 int32_t peerPid = -1;
73 int32_t peerUid = -1;
74 if (!GetPidAndUidFromServiceName(peerName, peerPid, peerUid)) {
75 ZLOGE(LOG_LABEL, "failed to get peerpid and peeruid from peerName");
76 return;
77 }
78
79 DBinderDatabusInvoker *invoker =
80 reinterpret_cast<DBinderDatabusInvoker *>(IPCThreadSkeleton::GetRemoteInvoker(IRemoteObject::IF_PROT_DATABUS));
81 if (invoker == nullptr) {
82 ZLOGE(LABEL, "fail to get invoker");
83 return;
84 }
85
86 invoker->OnReceiveNewConnection(socket, peerPid, peerUid, peerName, networkId);
87 }
88
ServerOnShutdown(int32_t socket,ShutdownReason reason)89 void DatabusSocketListener::ServerOnShutdown(int32_t socket, ShutdownReason reason)
90 {
91 ZLOGI(LABEL, "socketId:%{public}d, ShutdownReason:%{public}d", socket, reason);
92 DBinderDatabusInvoker *invoker =
93 reinterpret_cast<DBinderDatabusInvoker *>(IPCThreadSkeleton::GetRemoteInvoker(IRemoteObject::IF_PROT_DATABUS));
94 if (invoker == nullptr) {
95 ZLOGE(LABEL, "fail to get invoker");
96 return;
97 }
98 RemoveSessionName();
99 invoker->OnDatabusSessionServerSideClosed(socket);
100 }
101
ClientOnBind(int32_t socket,PeerSocketInfo info)102 void DatabusSocketListener::ClientOnBind(int32_t socket, PeerSocketInfo info)
103 {
104 return;
105 }
106
ClientOnShutdown(int32_t socket,ShutdownReason reason)107 void DatabusSocketListener::ClientOnShutdown(int32_t socket, ShutdownReason reason)
108 {
109 ZLOGI(LABEL, "socketId:%{public}d, ShutdownReason:%{public}d", socket, reason);
110 DBinderDatabusInvoker *invoker =
111 reinterpret_cast<DBinderDatabusInvoker *>(IPCThreadSkeleton::GetRemoteInvoker(IRemoteObject::IF_PROT_DATABUS));
112 if (invoker == nullptr) {
113 ZLOGE(LABEL, "fail to get invoker");
114 return;
115 }
116
117 DBinderSocketInfo socketInfo;
118 {
119 std::lock_guard<std::mutex> lockGuard(socketInfoMutex_);
120 for (auto it = socketInfoMap_.begin(); it != socketInfoMap_.end(); it++) {
121 if (it->second == socket) {
122 socketInfo = it->first;
123 ZLOGI(LOG_LABEL, "erase socketId:%{public}d ", it->second);
124 socketInfoMap_.erase(it);
125 break;
126 }
127 }
128 }
129 EraseDeviceLock(socketInfo);
130 RemoveSessionName();
131 invoker->OnDatabusSessionClientSideClosed(socket);
132 }
133
OnBytesReceived(int32_t socket,const void * data,uint32_t dataLen)134 void DatabusSocketListener::OnBytesReceived(int32_t socket, const void *data, uint32_t dataLen)
135 {
136 ZLOGI(LABEL, "socketId:%{public}d len:%{public}u", socket, dataLen);
137 DBinderDatabusInvoker *invoker =
138 reinterpret_cast<DBinderDatabusInvoker *>(IPCThreadSkeleton::GetRemoteInvoker(IRemoteObject::IF_PROT_DATABUS));
139 if (invoker == nullptr) {
140 ZLOGE(LABEL, "fail to get invoker");
141 return;
142 }
143
144 invoker->OnMessageAvailable(socket, static_cast<const char*>(data), dataLen);
145 }
146
StartServerListener(const std::string & ownName)147 int32_t DatabusSocketListener::StartServerListener(const std::string &ownName)
148 {
149 std::string pkgName = DBINDER_PKG_NAME + "_" + std::to_string(getpid());
150
151 SocketInfo serverSocketInfo = {
152 .name = const_cast<char*>(ownName.c_str()),
153 .pkgName = const_cast<char*>(pkgName.c_str()),
154 .dataType = TransDataType::DATA_TYPE_BYTES,
155 };
156 int32_t socketId = DBinderSoftbusClient::GetInstance().Socket(serverSocketInfo);
157 if (socketId <= 0) {
158 ZLOGE(LABEL, "create socket server error, socket is invalid");
159 return SOCKET_ID_INVALID;
160 }
161 int32_t ret = DBinderSoftbusClient::GetInstance().Listen(socketId, QOS_TV, QOS_COUNT, &serverListener_);
162 if (ret != SOFTBUS_OK && ret != SOFTBUS_TRANS_SOCKET_IN_USE) {
163 ZLOGE(LABEL, "Listen failed, ret:%{public}d", ret);
164 DBinderSoftbusClient::GetInstance().Shutdown(socketId);
165 return SOCKET_ID_INVALID;
166 }
167 ZLOGI(LABEL, "Listen ok, socketId:%{public}d, ownName:%{public}s", socketId, ownName.c_str());
168 return socketId;
169 }
170
QueryOrNewInfoMutex(DBinderSocketInfo socketInfo)171 std::shared_ptr<std::mutex> DatabusSocketListener::QueryOrNewInfoMutex(DBinderSocketInfo socketInfo)
172 {
173 std::lock_guard<std::mutex> lockGuard(deviceMutex_);
174 auto it = infoMutexMap_.find(socketInfo);
175 if (it != infoMutexMap_.end()) {
176 return it->second;
177 }
178 std::shared_ptr<std::mutex> infoMutex = std::make_shared<std::mutex>();
179 if (infoMutex == nullptr) {
180 ZLOGE(LOG_LABEL, "failed to create mutex, ownName:%{public}s, peerName:%{public}s, networkId:%{public}s",
181 socketInfo.GetOwnName().c_str(), socketInfo.GetPeerName().c_str(),
182 IPCProcessSkeleton::ConvertToSecureString(socketInfo.GetNetworkId()).c_str());
183 return nullptr;
184 }
185 infoMutexMap_[socketInfo] = infoMutex;
186 return infoMutex;
187 }
188
CreateClientSocket(const std::string & ownName,const std::string & peerName,const std::string & networkId)189 int32_t DatabusSocketListener::CreateClientSocket(const std::string &ownName, const std::string &peerName,
190 const std::string &networkId)
191 {
192 DBinderSocketInfo info(ownName, peerName, networkId);
193 std::shared_ptr<std::mutex> infoMutex = QueryOrNewInfoMutex(info);
194 if (infoMutex == nullptr) {
195 return SOCKET_ID_INVALID;
196 }
197 std::lock_guard<std::mutex> lockUnique(*infoMutex);
198
199 {
200 std::lock_guard<std::mutex> lockGuard(socketInfoMutex_);
201 auto it = socketInfoMap_.find(info);
202 if (it != socketInfoMap_.end()) {
203 return it->second;
204 }
205 }
206
207 std::string pkgName = std::string(DBINDER_PKG_NAME) + "_" + std::to_string(getpid());
208 SocketInfo socketInfo = {
209 .name = const_cast<char*>(ownName.c_str()),
210 .peerName = const_cast<char*>(peerName.c_str()),
211 .peerNetworkId = const_cast<char*>(networkId.c_str()),
212 .pkgName = const_cast<char*>(pkgName.c_str()),
213 .dataType = TransDataType::DATA_TYPE_BYTES,
214 };
215 int32_t socketId = DBinderSoftbusClient::GetInstance().Socket(socketInfo);
216 if (socketId <= 0) {
217 ZLOGE(LABEL, "create socket error, socket is invalid");
218 return SOCKET_ID_INVALID;
219 }
220 int32_t ret = DBinderSoftbusClient::GetInstance().Bind(socketId, QOS_TV, QOS_COUNT, &clientListener_);
221 if (ret != SOFTBUS_OK && ret != SOFTBUS_TRANS_SOCKET_IN_USE) {
222 ZLOGE(LABEL, "Bind failed, ret:%{public}d, socketId:%{public}d,"
223 "ownName:%{public}s, peerName:%{public}s, peerNetworkId:%{public}s",
224 ret, socketId, ownName.c_str(), peerName.c_str(),
225 IPCProcessSkeleton::ConvertToSecureString(networkId).c_str());
226 DBinderSoftbusClient::GetInstance().Shutdown(socketId);
227 EraseDeviceLock(info);
228 return SOCKET_ID_INVALID;
229 }
230 ZLOGI(LABEL, "Bind succ, ownName:%{public}s peer:%{public}s deviceId:%{public}s socketId:%{public}d",
231 ownName.c_str(), peerName.c_str(), IPCProcessSkeleton::ConvertToSecureString(networkId).c_str(), socketId);
232 {
233 std::lock_guard<std::mutex> lockGuard(socketInfoMutex_);
234 socketInfoMap_[info] = socketId;
235 }
236 return socketId;
237 }
238
ShutdownSocket(int32_t socketId)239 void DatabusSocketListener::ShutdownSocket(int32_t socketId)
240 {
241 DBinderSocketInfo socketInfo;
242 {
243 std::lock_guard<std::mutex> lockGuard(socketInfoMutex_);
244 for (auto it = socketInfoMap_.begin(); it != socketInfoMap_.end(); it++) {
245 if (it->second == socketId) {
246 ZLOGI(LOG_LABEL, "Shutdown socketId:%{public}d ", it->second);
247 DBinderSoftbusClient::GetInstance().Shutdown(it->second);
248 socketInfo = it->first;
249 it = socketInfoMap_.erase(it);
250 break;
251 }
252 }
253 }
254 EraseDeviceLock(socketInfo);
255 }
256
EraseDeviceLock(DBinderSocketInfo info)257 void DatabusSocketListener::EraseDeviceLock(DBinderSocketInfo info)
258 {
259 std::lock_guard<std::mutex> lockGuard(deviceMutex_);
260 auto it = infoMutexMap_.find(info);
261 if (it != infoMutexMap_.end()) {
262 infoMutexMap_.erase(it);
263 }
264 }
265
RemoveSessionName(void)266 void DatabusSocketListener::RemoveSessionName(void)
267 {
268 IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
269 if (current == nullptr) {
270 ZLOGE(LABEL, "get current is null");
271 return;
272 }
273 current->RemoveSoftbusServer();
274 }
275
GetPidAndUidFromServiceName(const std::string & serviceName,int32_t & pid,int32_t & uid)276 bool DatabusSocketListener::GetPidAndUidFromServiceName(const std::string &serviceName, int32_t &pid, int32_t &uid)
277 {
278 if (serviceName.length() <= DBINDER_SOCKET_NAME_PREFIX.length()) {
279 ZLOGE(LOG_LABEL, "serviceName:%{public}s format error", serviceName.c_str());
280 return false;
281 }
282
283 std::string str = serviceName.substr(DBINDER_SOCKET_NAME_PREFIX.length());
284 std::string::size_type pos = str.find(DBINDER_UID_PID_SEPARATOR);
285 if (pos == std::string::npos) {
286 ZLOGE(LOG_LABEL, "serviceName:%{public}s format error", serviceName.c_str());
287 return false;
288 }
289
290 std::string uidStr = str.substr(0, pos);
291 std::string pidStr = str.substr(pos + 1);
292 auto result = std::from_chars(uidStr.c_str(), uidStr.c_str() + uidStr.size(), uid);
293 if (result.ec != std::errc()) {
294 ZLOGE(LOG_LABEL, "uid:%{public}s is invalid", uidStr.c_str());
295 return false;
296 }
297 result = std::from_chars(pidStr.c_str(), pidStr.c_str() + pidStr.size(), pid);
298 if (result.ec != std::errc()) {
299 ZLOGE(LOG_LABEL, "pid:%{public}s is invalid", pidStr.c_str());
300 return false;
301 }
302 return true;
303 }
304 } // namespace OHOS
305