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 "mdns_client.h"
17
18 #include <condition_variable>
19 #include <mutex>
20 #include <unistd.h>
21 #include <thread>
22
23 #include "if_system_ability_manager.h"
24 #include "iservice_registry.h"
25 #include "netmgr_ext_log_wrapper.h"
26 #include "system_ability_definition.h"
27 #include "mdns_service_proxy.h"
28
29 #include "mdns_common.h"
30 #include "mdns_client_resume.h"
31
32 namespace OHOS {
33 namespace NetManagerStandard {
34
35 std::mutex g_loadMutex;
36 std::condition_variable g_cv;
37
OnLoadSystemAbilitySuccess(int32_t systemAbilityId,const sptr<IRemoteObject> & remoteObject)38 void OnDemandLoadCallback::OnLoadSystemAbilitySuccess(int32_t systemAbilityId, const sptr<IRemoteObject> &remoteObject)
39 {
40 NETMGR_EXT_LOG_D("OnLoadSystemAbilitySuccess systemAbilityId: [%{public}d]", systemAbilityId);
41 g_loadMutex.lock();
42 remoteObject_ = remoteObject;
43 g_loadMutex.unlock();
44 g_cv.notify_one();
45 }
46
OnLoadSystemAbilityFail(int32_t systemAbilityId)47 void OnDemandLoadCallback::OnLoadSystemAbilityFail(int32_t systemAbilityId)
48 {
49 NETMGR_EXT_LOG_D("OnLoadSystemAbilityFail: [%{public}d]", systemAbilityId);
50 g_cv.notify_one();
51 }
52
GetRemoteObject() const53 const sptr<IRemoteObject> &OnDemandLoadCallback::GetRemoteObject() const
54 {
55 return remoteObject_;
56 }
57
MDnsClient()58 MDnsClient::MDnsClient() : mdnsService_(nullptr), loadCallback_(nullptr) {}
59
~MDnsClient()60 MDnsClient::~MDnsClient()
61 {
62 NETMGR_EXT_LOG_E("~MDnsClient : Destroy MDnsClient");
63 sptr<IMdnsService> proxy = GetProxy();
64 if (proxy == nullptr) {
65 return;
66 }
67
68 auto serviceRemote = proxy->AsObject();
69 if (serviceRemote == nullptr) {
70 return;
71 }
72 if (deathRecipient_) {
73 serviceRemote->RemoveDeathRecipient(deathRecipient_);
74 }
75 }
76
RegisterService(const MDnsServiceInfo & serviceInfo,const sptr<IRegistrationCallback> & cb)77 int32_t MDnsClient::RegisterService(const MDnsServiceInfo &serviceInfo, const sptr<IRegistrationCallback> &cb)
78 {
79 if (!(IsNameValid(serviceInfo.name) && IsTypeValid(serviceInfo.type) && IsPortValid(serviceInfo.port))) {
80 NETMGR_EXT_LOG_E("RegisterService arguments are not valid");
81 return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
82 }
83 if (cb == nullptr) {
84 NETMGR_EXT_LOG_E("callback is null");
85 return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
86 }
87
88 sptr<IMdnsService> proxy = GetProxy();
89 if (proxy == nullptr) {
90 NETMGR_EXT_LOG_E("proxy is nullptr");
91 return NETMANAGER_EXT_ERR_LOCAL_PTR_NULL;
92 }
93 int32_t ret = proxy->RegisterService(serviceInfo, cb);
94 if (ret != NETMANAGER_EXT_SUCCESS) {
95 NETMGR_EXT_LOG_E("RegisterService return code: [%{public}d]", ret);
96 } else {
97 MDnsClientResume::GetInstance().SaveRegisterService(serviceInfo, cb);
98 }
99 return ret;
100 }
101
UnRegisterService(const sptr<IRegistrationCallback> & cb)102 int32_t MDnsClient::UnRegisterService(const sptr<IRegistrationCallback> &cb)
103 {
104 if (cb == nullptr) {
105 NETMGR_EXT_LOG_E("callback is null");
106 return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
107 }
108
109 sptr<IMdnsService> proxy = GetProxy();
110 if (proxy == nullptr) {
111 NETMGR_EXT_LOG_E("MDnsClient::RemoveLocalService proxy is nullptr");
112 return IPC_PROXY_ERR;
113 }
114 int32_t ret = proxy->UnRegisterService(cb);
115 if (ret != NETMANAGER_EXT_SUCCESS) {
116 NETMGR_EXT_LOG_E("UnRegisterService return code: [%{public}d]", ret);
117 } else {
118 MDnsClientResume::GetInstance().RemoveRegisterService(cb);
119 }
120 return ret;
121 }
122
StartDiscoverService(const std::string & serviceType,const sptr<IDiscoveryCallback> & cb)123 int32_t MDnsClient::StartDiscoverService(const std::string &serviceType, const sptr<IDiscoveryCallback> &cb)
124 {
125 if (!IsTypeValid(serviceType)) {
126 NETMGR_EXT_LOG_E("arguments are not valid, [%{public}s]", serviceType.c_str());
127 return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
128 }
129 if (cb == nullptr) {
130 NETMGR_EXT_LOG_E("callback is null");
131 return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
132 }
133
134 sptr<IMdnsService> proxy = GetProxy();
135 if (proxy == nullptr) {
136 NETMGR_EXT_LOG_E("MDnsClient::StartDiscoverService proxy is nullptr");
137 return IPC_PROXY_ERR;
138 }
139 int32_t ret = proxy->StartDiscoverService(serviceType, cb);
140 if (ret != NETMANAGER_EXT_SUCCESS) {
141 NETMGR_EXT_LOG_E("StartDiscoverService return code: [%{public}d]", ret);
142 } else {
143 MDnsClientResume::GetInstance().SaveStartDiscoverService(serviceType, cb);
144 }
145 return ret;
146 }
147
StopDiscoverService(const sptr<IDiscoveryCallback> & cb)148 int32_t MDnsClient::StopDiscoverService(const sptr<IDiscoveryCallback> &cb)
149 {
150 if (cb == nullptr) {
151 NETMGR_EXT_LOG_E("callback is null");
152 return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
153 }
154
155 sptr<IMdnsService> proxy = GetProxy();
156 if (proxy == nullptr) {
157 NETMGR_EXT_LOG_E("MDnsClient::StopSearchingMDNS proxy is nullptr");
158 return IPC_PROXY_ERR;
159 }
160 int32_t ret = proxy->StopDiscoverService(cb);
161 if (ret != NETMANAGER_EXT_SUCCESS) {
162 NETMGR_EXT_LOG_E("StopDiscoverService return code: [%{public}d]", ret);
163 } else {
164 MDnsClientResume::GetInstance().RemoveStopDiscoverService(cb);
165 }
166 return ret;
167 }
168
ResolveService(const MDnsServiceInfo & serviceInfo,const sptr<IResolveCallback> & cb)169 int32_t MDnsClient::ResolveService(const MDnsServiceInfo &serviceInfo, const sptr<IResolveCallback> &cb)
170 {
171 if (!(IsNameValid(serviceInfo.name) && IsTypeValid(serviceInfo.type))) {
172 NETMGR_EXT_LOG_E("arguments are not valid");
173 return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
174 }
175 if (cb == nullptr) {
176 NETMGR_EXT_LOG_E("callback is null");
177 return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
178 }
179
180 sptr<IMdnsService> proxy = GetProxy();
181 if (proxy == nullptr) {
182 NETMGR_EXT_LOG_E("MDnsClient::ResolveService proxy is nullptr");
183 return IPC_PROXY_ERR;
184 }
185
186 int32_t ret = proxy->ResolveService(serviceInfo, cb);
187 if (ret != NETMANAGER_EXT_SUCCESS) {
188 NETMGR_EXT_LOG_E("ResolveService return code: [%{public}d]", ret);
189 }
190 return ret;
191 }
192
LoadSaOnDemand()193 sptr<IRemoteObject> MDnsClient::LoadSaOnDemand()
194 {
195 if (loadCallback_->GetRemoteObject() == nullptr) {
196 sptr<ISystemAbilityManager> sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
197 if (sam == nullptr) {
198 NETMGR_EXT_LOG_E("GetSystemAbilityManager failed");
199 return nullptr;
200 }
201 int32_t result = sam->LoadSystemAbility(COMM_MDNS_MANAGER_SYS_ABILITY_ID, loadCallback_);
202 if (result != ERR_OK) {
203 NETMGR_EXT_LOG_E("LoadSystemAbility failed : [%{public}d]", result);
204 return nullptr;
205 }
206 std::unique_lock<std::mutex> lk(g_loadMutex);
207 if (!g_cv.wait_for(lk, std::chrono::seconds(LOAD_SA_TIMEOUT),
208 [this]() { return loadCallback_->GetRemoteObject() != nullptr; })) {
209 NETMGR_EXT_LOG_E("LoadSystemAbility timeout");
210 lk.unlock();
211 return nullptr;
212 }
213 lk.unlock();
214 }
215 return loadCallback_->GetRemoteObject();
216 }
217
GetProxy()218 sptr<IMdnsService> MDnsClient::GetProxy()
219 {
220 std::lock_guard lock(mutex_);
221 if (mdnsService_ != nullptr) {
222 NETMGR_EXT_LOG_D("get proxy is ok");
223 return mdnsService_;
224 }
225 loadCallback_ = new (std::nothrow) OnDemandLoadCallback();
226 if (loadCallback_ == nullptr) {
227 NETMGR_EXT_LOG_E("loadCallback_ is nullptr");
228 return nullptr;
229 }
230 sptr<IRemoteObject> remote = LoadSaOnDemand();
231 if (remote == nullptr) {
232 NETMGR_EXT_LOG_E("get Remote service failed");
233 return nullptr;
234 }
235 deathRecipient_ = new (std::nothrow) MDnsDeathRecipient(*this);
236 if (deathRecipient_ == nullptr) {
237 NETMGR_EXT_LOG_E("deathRecipient_ is nullptr");
238 return nullptr;
239 }
240 if ((remote->IsProxyObject()) && (!remote->AddDeathRecipient(deathRecipient_))) {
241 NETMGR_EXT_LOG_E("add death recipient failed");
242 return nullptr;
243 }
244 mdnsService_ = iface_cast<IMdnsService>(remote);
245 if (mdnsService_ == nullptr) {
246 NETMGR_EXT_LOG_E("get Remote service proxy failed");
247 return nullptr;
248 }
249 return mdnsService_;
250 }
251
RestartResume()252 void MDnsClient::RestartResume()
253 {
254 NETMGR_EXT_LOG_I("MDnsClient::RestartResume");
255 std::thread t([this]() {
256 MDnsClientResume::GetInstance().ReRegisterService();
257 MDnsClientResume::GetInstance().RestartDiscoverService();
258 });
259 std::string threadName = "mdnsGetProxy";
260 pthread_setname_np(t.native_handle(), threadName.c_str());
261 t.detach();
262 }
263
OnRemoteDied(const wptr<IRemoteObject> & remote)264 void MDnsClient::OnRemoteDied(const wptr<IRemoteObject> &remote)
265 {
266 NETMGR_EXT_LOG_D("on remote died");
267 if (remote == nullptr) {
268 NETMGR_EXT_LOG_E("remote object is nullptr");
269 return;
270 }
271 std::lock_guard lock(mutex_);
272 if (mdnsService_ == nullptr) {
273 NETMGR_EXT_LOG_E("mdnsService_ is nullptr");
274 return;
275 }
276 sptr<IRemoteObject> local = mdnsService_->AsObject();
277 if (local != remote.promote()) {
278 NETMGR_EXT_LOG_E("proxy and stub is not same remote object");
279 return;
280 }
281 local->RemoveDeathRecipient(deathRecipient_);
282 mdnsService_ = nullptr;
283
284 RestartResume();
285 }
286 } // namespace NetManagerStandard
287 } // namespace OHOS