1 /*
2  * Copyright (C) 2024 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 "dbinder_softbus_client.h"
17 
18 #include <dlfcn.h>
19 #include "check_instance_exit.h"
20 #include "ipc_debug.h"
21 #include "log_tags.h"
22 
23 namespace OHOS {
24 
25 using namespace OHOS::HiviewDFX;
26 static constexpr HiLogLabel LOG_LABEL = { LOG_CORE, LOG_ID_IPC_DBINDER_SOFTBUS_CLIENT, "DBinderSoftbusClient"};
27 
28 #ifdef __aarch64__
29 static constexpr const char *SOFTBUS_PATH_NAME = "/system/lib64/platformsdk/libsoftbus_client.z.so";
30 #else
31 static constexpr const char *SOFTBUS_PATH_NAME = "/system/lib/platformsdk/libsoftbus_client.z.so";
32 #endif
33 
GetInstance()34 DBinderSoftbusClient& DBinderSoftbusClient::GetInstance()
35 {
36     static DBinderSoftbusClient instance;
37     return instance;
38 }
39 
DBinderSoftbusClient()40 DBinderSoftbusClient::DBinderSoftbusClient()
41 {
42 }
43 
~DBinderSoftbusClient()44 DBinderSoftbusClient::~DBinderSoftbusClient()
45 {
46     exitFlag_ = true;
47     ZLOGI(LOG_LABEL, "destroy");
48 }
49 
OpenSoftbusClientSo()50 bool DBinderSoftbusClient::OpenSoftbusClientSo()
51 {
52     CHECK_INSTANCE_EXIT_WITH_RETVAL(exitFlag_, false);
53     std::lock_guard<std::mutex> lockGuard(loadSoMutex_);
54 
55     if (isLoaded_ && (soHandle_ != nullptr)) {
56         return true;
57     }
58 
59     soHandle_ = dlopen(SOFTBUS_PATH_NAME, RTLD_NOW | RTLD_NODELETE);
60     if (soHandle_ == nullptr) {
61         ZLOGE(LOG_LABEL, "dlopen %{public}s failed, err msg:%{public}s", SOFTBUS_PATH_NAME, dlerror());
62         return false;
63     }
64 
65     isLoaded_ = true;
66     ZLOGI(LOG_LABEL, "dlopen %{public}s SOFTBUS_CLIENT_SUCCESS", SOFTBUS_PATH_NAME);
67 
68     return true;
69 }
70 
DBinderGrantPermission(int32_t uid,int32_t pid,const std::string & socketName)71 int32_t DBinderSoftbusClient::DBinderGrantPermission(int32_t uid, int32_t pid, const std::string &socketName)
72 {
73     CHECK_INSTANCE_EXIT_WITH_RETVAL(exitFlag_, SOFTBUS_CLIENT_INSTANCE_EXIT);
74     if (grantPermissionFunc_ != nullptr) {
75         return grantPermissionFunc_(uid, pid, socketName.c_str());
76     }
77 
78     if (!OpenSoftbusClientSo()) {
79         return SOFTBUS_CLIENT_DLOPEN_FAILED;
80     }
81 
82     grantPermissionFunc_ = (DBinderGrantPermissionFunc)dlsym(soHandle_, "DBinderGrantPermission");
83     if (grantPermissionFunc_ == nullptr) {
84         ZLOGE(LOG_LABEL, "dlsym DBinderGrantPermission fail, err msg:%{public}s", dlerror());
85         return SOFTBUS_CLIENT_DLSYM_FAILED;
86     }
87 
88     return grantPermissionFunc_(uid, pid, socketName.c_str());
89 }
90 
DBinderRemovePermission(const std::string & socketName)91 int32_t DBinderSoftbusClient::DBinderRemovePermission(const std::string &socketName)
92 {
93     CHECK_INSTANCE_EXIT_WITH_RETVAL(exitFlag_, SOFTBUS_CLIENT_INSTANCE_EXIT);
94     if (removePermissionFunc_ != nullptr) {
95         return removePermissionFunc_(socketName.c_str());
96     }
97 
98     if (!OpenSoftbusClientSo()) {
99         return SOFTBUS_CLIENT_DLOPEN_FAILED;
100     }
101 
102     removePermissionFunc_ = (DBinderRemovePermissionFunc)dlsym(soHandle_, "DBinderRemovePermission");
103     if (removePermissionFunc_ == nullptr) {
104         ZLOGE(LOG_LABEL, "dlsym DBinderRemovePermission fail, err msg:%{public}s", dlerror());
105         return SOFTBUS_CLIENT_DLSYM_FAILED;
106     }
107 
108     return removePermissionFunc_(socketName.c_str());
109 }
110 
GetLocalNodeDeviceId(const std::string & pkgName,std::string & devId)111 int32_t DBinderSoftbusClient::GetLocalNodeDeviceId(const std::string &pkgName, std::string &devId)
112 {
113     CHECK_INSTANCE_EXIT_WITH_RETVAL(exitFlag_, SOFTBUS_CLIENT_INSTANCE_EXIT);
114     NodeBasicInfo nodeBasicInfo;
115     if (getLocalNodeDeviceInfoFunc_ != nullptr) {
116         if (getLocalNodeDeviceInfoFunc_(pkgName.c_str(), &nodeBasicInfo) != 0) {
117             ZLOGE(LOG_LABEL, "Get local node device info failed");
118             return SOFTBUS_CLIENT_GET_DEVICE_INFO_FAILED;
119         }
120         devId = nodeBasicInfo.networkId;
121         return SOFTBUS_CLIENT_SUCCESS;
122     }
123 
124     if (!OpenSoftbusClientSo()) {
125         return SOFTBUS_CLIENT_DLOPEN_FAILED;
126     }
127 
128     getLocalNodeDeviceInfoFunc_ = (GetLocalNodeDeviceInfoFunc)dlsym(soHandle_, "GetLocalNodeDeviceInfo");
129     if (getLocalNodeDeviceInfoFunc_ == nullptr) {
130         ZLOGE(LOG_LABEL, "dlsym GetLocalNodeDeviceInfo fail, err msg:%{public}s", dlerror());
131         return SOFTBUS_CLIENT_DLSYM_FAILED;
132     }
133 
134     if (getLocalNodeDeviceInfoFunc_(pkgName.c_str(), &nodeBasicInfo) != 0) {
135         ZLOGE(LOG_LABEL, "Get local node device info failed");
136         return SOFTBUS_CLIENT_GET_DEVICE_INFO_FAILED;
137     }
138     devId = nodeBasicInfo.networkId;
139     return SOFTBUS_CLIENT_SUCCESS;
140 }
141 
Socket(SocketInfo info)142 int32_t DBinderSoftbusClient::Socket(SocketInfo info)
143 {
144     CHECK_INSTANCE_EXIT_WITH_RETVAL(exitFlag_, SOFTBUS_CLIENT_INSTANCE_EXIT);
145     if (socketFunc_ != nullptr) {
146         return socketFunc_(info);
147     }
148 
149     if (!OpenSoftbusClientSo()) {
150         return SOFTBUS_CLIENT_DLOPEN_FAILED;
151     }
152 
153     socketFunc_ = (SocketFunc)dlsym(soHandle_, "Socket");
154     if (socketFunc_ == nullptr) {
155         ZLOGE(LOG_LABEL, "dlsym Socket fail, err msg:%{public}s", dlerror());
156         return SOFTBUS_CLIENT_DLSYM_FAILED;
157     }
158 
159     return socketFunc_(info);
160 }
161 
Listen(int32_t socket,const QosTV qos[],uint32_t qosCount,const ISocketListener * listener)162 int32_t DBinderSoftbusClient::Listen(
163     int32_t socket, const QosTV qos[], uint32_t qosCount, const ISocketListener *listener)
164 {
165     CHECK_INSTANCE_EXIT_WITH_RETVAL(exitFlag_, SOFTBUS_CLIENT_INSTANCE_EXIT);
166     if (listenFunc_ != nullptr) {
167         return listenFunc_(socket, qos, qosCount, listener);
168     }
169 
170     if (!OpenSoftbusClientSo()) {
171         return SOFTBUS_CLIENT_DLOPEN_FAILED;
172     }
173 
174     listenFunc_ = (ListenFunc)dlsym(soHandle_, "Listen");
175     if (listenFunc_ == nullptr) {
176         ZLOGE(LOG_LABEL, "dlsym Listen fail, err msg:%{public}s", dlerror());
177         return SOFTBUS_CLIENT_DLSYM_FAILED;
178     }
179 
180     return listenFunc_(socket, qos, qosCount, listener);
181 }
182 
Bind(int32_t socket,const QosTV qos[],uint32_t qosCount,const ISocketListener * listener)183 int32_t DBinderSoftbusClient::Bind(
184     int32_t socket, const QosTV qos[], uint32_t qosCount, const ISocketListener *listener)
185 {
186     CHECK_INSTANCE_EXIT_WITH_RETVAL(exitFlag_, SOFTBUS_CLIENT_INSTANCE_EXIT);
187     if (bindFunc_ != nullptr) {
188         return bindFunc_(socket, qos, qosCount, listener);
189     }
190 
191     if (!OpenSoftbusClientSo()) {
192         return SOFTBUS_CLIENT_DLOPEN_FAILED;
193     }
194 
195     bindFunc_ = (BindFunc)dlsym(soHandle_, "Bind");
196     if (bindFunc_ == nullptr) {
197         ZLOGE(LOG_LABEL, "dlsym Bind fail, err msg:%{public}s", dlerror());
198         return SOFTBUS_CLIENT_DLSYM_FAILED;
199     }
200 
201     return bindFunc_(socket, qos, qosCount, listener);
202 }
203 
SendBytes(int32_t socket,const void * data,uint32_t len)204 int32_t DBinderSoftbusClient::SendBytes(int32_t socket, const void *data, uint32_t len)
205 {
206     CHECK_INSTANCE_EXIT_WITH_RETVAL(exitFlag_, SOFTBUS_CLIENT_INSTANCE_EXIT);
207     if (sendBytesFunc_ != nullptr) {
208         return sendBytesFunc_(socket, data, len);
209     }
210 
211     if (!OpenSoftbusClientSo()) {
212         return SOFTBUS_CLIENT_DLOPEN_FAILED;
213     }
214 
215     sendBytesFunc_ = (SendBytesFunc)dlsym(soHandle_, "SendBytes");
216     if (sendBytesFunc_ == nullptr) {
217         ZLOGE(LOG_LABEL, "dlsym SendBytes fail, err msg:%{public}s", dlerror());
218         return SOFTBUS_CLIENT_DLSYM_FAILED;
219     }
220     return sendBytesFunc_(socket, data, len);
221 }
222 
SendMessage(int32_t socket,const void * data,uint32_t len)223 int32_t DBinderSoftbusClient::SendMessage(int32_t socket, const void *data, uint32_t len)
224 {
225     CHECK_INSTANCE_EXIT_WITH_RETVAL(exitFlag_, SOFTBUS_CLIENT_INSTANCE_EXIT);
226     if (sendMessageFunc_ != nullptr) {
227         return sendMessageFunc_(socket, data, len);
228     }
229 
230     if (!OpenSoftbusClientSo()) {
231         return SOFTBUS_CLIENT_DLOPEN_FAILED;
232     }
233 
234     sendMessageFunc_ = (SendMessageFunc)dlsym(soHandle_, "SendMessage");
235     if (sendMessageFunc_ == nullptr) {
236         ZLOGE(LOG_LABEL, "dlsym SendMessage fail, err msg:%{public}s", dlerror());
237         return SOFTBUS_CLIENT_DLSYM_FAILED;
238     }
239     return sendMessageFunc_(socket, data, len);
240 }
241 
Shutdown(int32_t socket)242 void DBinderSoftbusClient::Shutdown(int32_t socket)
243 {
244     CHECK_INSTANCE_EXIT(exitFlag_);
245     if (shutdownFunc_ != nullptr) {
246         shutdownFunc_(socket);
247         return;
248     }
249 
250     if (!OpenSoftbusClientSo()) {
251         return;
252     }
253 
254     shutdownFunc_ = (ShutdownFunc)dlsym(soHandle_, "Shutdown");
255     if (shutdownFunc_ == nullptr) {
256         ZLOGE(LOG_LABEL, "dlsym Shutdown fail, err msg:%{public}s", dlerror());
257         return;
258     }
259 
260     shutdownFunc_(socket);
261 }
262 } // namespace OHOS
263