• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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