* Copyright (C) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mdns_client.h"
#include <condition_variable>
#include <mutex>
#include <unistd.h>
#include <thread>
#include "if_system_ability_manager.h"
#include "iservice_registry.h"
#include "netmgr_ext_log_wrapper.h"
#include "system_ability_definition.h"
#include "mdns_service_proxy.h"
#include "mdns_common.h"
#include "mdns_client_resume.h"
namespace OHOS {
namespace NetManagerStandard {
std::mutex g_loadMutex;
std::condition_variable g_cv;
void OnDemandLoadCallback::OnLoadSystemAbilitySuccess(int32_t systemAbilityId, const sptr<IRemoteObject> &remoteObject)
{
NETMGR_EXT_LOG_D("OnLoadSystemAbilitySuccess systemAbilityId: [%{public}d]", systemAbilityId);
std::lock_guard<std::mutex> lock(g_loadMutex);
remoteObject_ = remoteObject;
g_cv.notify_one();
}
void OnDemandLoadCallback::OnLoadSystemAbilityFail(int32_t systemAbilityId)
{
NETMGR_EXT_LOG_D("OnLoadSystemAbilityFail: [%{public}d]", systemAbilityId);
g_cv.notify_one();
}
const sptr<IRemoteObject> &OnDemandLoadCallback::GetRemoteObject() const
{
return remoteObject_;
}
MDnsClient::MDnsClient() : mdnsService_(nullptr), loadCallback_(nullptr) {}
MDnsClient::~MDnsClient()
{
NETMGR_EXT_LOG_E("~MDnsClient : Destroy MDnsClient");
sptr<IMdnsService> proxy = GetProxy();
if (proxy == nullptr) {
return;
}
auto serviceRemote = proxy->AsObject();
if (serviceRemote == nullptr) {
return;
}
if (deathRecipient_) {
serviceRemote->RemoveDeathRecipient(deathRecipient_);
}
}
int32_t MDnsClient::RegisterService(const MDnsServiceInfo &serviceInfo, const sptr<IRegistrationCallback> &cb)
{
if (!(IsNameValid(serviceInfo.name) && IsTypeValid(serviceInfo.type) && IsPortValid(serviceInfo.port))) {
NETMGR_EXT_LOG_E("RegisterService arguments are not valid");
return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
}
if (cb == nullptr) {
NETMGR_EXT_LOG_E("callback is null");
return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
}
sptr<IMdnsService> proxy = GetProxy();
if (proxy == nullptr) {
NETMGR_EXT_LOG_E("proxy is nullptr");
return NETMANAGER_EXT_ERR_LOCAL_PTR_NULL;
}
int32_t ret = proxy->RegisterService(serviceInfo, cb);
if (ret != NETMANAGER_EXT_SUCCESS) {
NETMGR_EXT_LOG_E("RegisterService return code: [%{public}d]", ret);
} else {
MDnsClientResume::GetInstance().SaveRegisterService(serviceInfo, cb);
}
return ret;
}
int32_t MDnsClient::UnRegisterService(const sptr<IRegistrationCallback> &cb)
{
if (cb == nullptr) {
NETMGR_EXT_LOG_E("callback is null");
return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
}
sptr<IMdnsService> proxy = GetProxy();
if (proxy == nullptr) {
NETMGR_EXT_LOG_E("MDnsClient::RemoveLocalService proxy is nullptr");
return IPC_PROXY_ERR;
}
int32_t ret = proxy->UnRegisterService(cb);
if (ret != NETMANAGER_EXT_SUCCESS) {
NETMGR_EXT_LOG_E("UnRegisterService return code: [%{public}d]", ret);
} else {
MDnsClientResume::GetInstance().RemoveRegisterService(cb);
}
return ret;
}
int32_t MDnsClient::StartDiscoverService(const std::string &serviceType, const sptr<IDiscoveryCallback> &cb)
{
if (!IsTypeValid(serviceType)) {
NETMGR_EXT_LOG_E("arguments are not valid, [%{public}s]", serviceType.c_str());
return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
}
if (cb == nullptr) {
NETMGR_EXT_LOG_E("callback is null");
return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
}
sptr<IMdnsService> proxy = GetProxy();
if (proxy == nullptr) {
NETMGR_EXT_LOG_E("MDnsClient::StartDiscoverService proxy is nullptr");
return IPC_PROXY_ERR;
}
int32_t ret = proxy->StartDiscoverService(serviceType, cb);
if (ret != NETMANAGER_EXT_SUCCESS) {
NETMGR_EXT_LOG_E("StartDiscoverService return code: [%{public}d]", ret);
} else {
MDnsClientResume::GetInstance().SaveStartDiscoverService(serviceType, cb);
}
return ret;
}
int32_t MDnsClient::StopDiscoverService(const sptr<IDiscoveryCallback> &cb)
{
if (cb == nullptr) {
NETMGR_EXT_LOG_E("callback is null");
return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
}
sptr<IMdnsService> proxy = GetProxy();
if (proxy == nullptr) {
NETMGR_EXT_LOG_E("MDnsClient::StopSearchingMDNS proxy is nullptr");
return IPC_PROXY_ERR;
}
int32_t ret = proxy->StopDiscoverService(cb);
if (ret != NETMANAGER_EXT_SUCCESS) {
NETMGR_EXT_LOG_E("StopDiscoverService return code: [%{public}d]", ret);
} else {
MDnsClientResume::GetInstance().RemoveStopDiscoverService(cb);
}
return ret;
}
int32_t MDnsClient::ResolveService(const MDnsServiceInfo &serviceInfo, const sptr<IResolveCallback> &cb)
{
if (!(IsNameValid(serviceInfo.name) && IsTypeValid(serviceInfo.type))) {
NETMGR_EXT_LOG_E("arguments are not valid");
return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
}
if (cb == nullptr) {
NETMGR_EXT_LOG_E("callback is null");
return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
}
sptr<IMdnsService> proxy = GetProxy();
if (proxy == nullptr) {
NETMGR_EXT_LOG_E("MDnsClient::ResolveService proxy is nullptr");
return IPC_PROXY_ERR;
}
int32_t ret = proxy->ResolveService(serviceInfo, cb);
if (ret != NETMANAGER_EXT_SUCCESS) {
NETMGR_EXT_LOG_E("ResolveService return code: [%{public}d]", ret);
}
return ret;
}
sptr<IRemoteObject> MDnsClient::LoadSaOnDemand()
{
if (loadCallback_->GetRemoteObject() == nullptr) {
sptr<ISystemAbilityManager> sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
if (sam == nullptr) {
NETMGR_EXT_LOG_E("GetSystemAbilityManager failed");
return nullptr;
}
int32_t result = sam->LoadSystemAbility(COMM_MDNS_MANAGER_SYS_ABILITY_ID, loadCallback_);
if (result != ERR_OK) {
NETMGR_EXT_LOG_E("LoadSystemAbility failed : [%{public}d]", result);
return nullptr;
}
std::unique_lock<std::mutex> lk(g_loadMutex);
if (!g_cv.wait_for(lk, std::chrono::seconds(LOAD_SA_TIMEOUT),
[this]() { return loadCallback_->GetRemoteObject() != nullptr; })) {
NETMGR_EXT_LOG_E("LoadSystemAbility timeout");
lk.unlock();
return nullptr;
}
lk.unlock();
}
return loadCallback_->GetRemoteObject();
}
sptr<IMdnsService> MDnsClient::GetProxy()
{
std::lock_guard lock(mutex_);
if (mdnsService_ != nullptr) {
NETMGR_EXT_LOG_D("get proxy is ok");
return mdnsService_;
}
loadCallback_ = new (std::nothrow) OnDemandLoadCallback();
if (loadCallback_ == nullptr) {
NETMGR_EXT_LOG_E("loadCallback_ is nullptr");
return nullptr;
}
sptr<IRemoteObject> remote = LoadSaOnDemand();
if (remote == nullptr) {
NETMGR_EXT_LOG_E("get Remote service failed");
return nullptr;
}
deathRecipient_ = new (std::nothrow) MDnsDeathRecipient(*this);
if (deathRecipient_ == nullptr) {
NETMGR_EXT_LOG_E("deathRecipient_ is nullptr");
return nullptr;
}
if ((remote->IsProxyObject()) && (!remote->AddDeathRecipient(deathRecipient_))) {
NETMGR_EXT_LOG_E("add death recipient failed");
return nullptr;
}
mdnsService_ = iface_cast<IMdnsService>(remote);
if (mdnsService_ == nullptr) {
NETMGR_EXT_LOG_E("get Remote service proxy failed");
return nullptr;
}
return mdnsService_;
}
void MDnsClient::RestartResume()
{
NETMGR_EXT_LOG_I("MDnsClient::RestartResume");
std::thread t([this]() {
MDnsClientResume::GetInstance().ReRegisterService();
MDnsClientResume::GetInstance().RestartDiscoverService();
});
std::string threadName = "mdnsGetProxy";
pthread_setname_np(t.native_handle(), threadName.c_str());
t.detach();
}
void MDnsClient::OnRemoteDied(const wptr<IRemoteObject> &remote)
{
NETMGR_EXT_LOG_D("on remote died");
if (remote == nullptr) {
NETMGR_EXT_LOG_E("remote object is nullptr");
return;
}
std::lock_guard lock(mutex_);
if (mdnsService_ == nullptr) {
NETMGR_EXT_LOG_E("mdnsService_ is nullptr");
return;
}
sptr<IRemoteObject> local = mdnsService_->AsObject();
if (local != remote.promote()) {
NETMGR_EXT_LOG_E("proxy and stub is not same remote object");
return;
}
local->RemoveDeathRecipient(deathRecipient_);
mdnsService_ = nullptr;
RestartResume();
}
}
}