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