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