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