* Copyright (c) 2021-2024 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.
*/
#ifndef KERNEL_TALKER_H
#define KERNEL_TALKER_H
#include <atomic>
#include <fcntl.h>
#include <functional>
#include <memory>
#include <mutex>
#include <poll.h>
#include <thread>
#include <unistd.h>
#include <unordered_set>
#include "dfs_radar.h"
#include "radar_report.h"
#include "mountpoint/mount_point.h"
#include "network/base_session.h"
#include "utils_log.h"
#undef LOG_DOMAIN
#define LOG_DOMAIN 0xD00430B
#define FDSAN_TAG 1
namespace OHOS {
namespace Storage {
namespace DistributedFile {
using namespace std;
using namespace FileManagement;
constexpr int CID_MAX_LEN = 64;
struct NotifyParam {
int32_t notify;
int32_t fd;
char remoteCid[CID_MAX_LEN];
} __attribute__((packed));
class KernelTalker final : protected NoCopyable, public std::enable_shared_from_this<KernelTalker> {
public:
explicit KernelTalker(std::weak_ptr<MountPoint> mountPoint,
std::function<void(NotifyParam &)> getSessionCallback,
std::function<void(const std::string &)> closeSessionCallback)
: mountPoint_(mountPoint), GetSessionCallback_(getSessionCallback), CloseSessionCallback_(closeSessionCallback)
{
}
KernelTalker() = default;
~KernelTalker();
void SinkSessionTokernel(std::shared_ptr<BaseSession> session, const std::string backStage);
void SinkDevslTokernel(const std::string &cid, uint32_t devsl);
void SinkOfflineCmdToKernel(std::string cid);
void CreatePollThread();
void WaitForPollThreadExited();
private:
template<typename T>
void SetCmd(T &cmd)
{
auto spt = mountPoint_.lock();
if (spt == nullptr) {
LOGE("mountPoint is not exist! bad weak_ptr");
return;
}
std::string ctrlPath = spt->GetMountArgument().GetCtrlPath();
LOGI("cmd path:%{public}s", GetAnonyString(ctrlPath).c_str());
std::lock_guard<std::mutex> lock(cmdMutex_);
char resolvedPath[PATH_MAX] = {'\0'};
char *realPath = realpath(ctrlPath.c_str(), resolvedPath);
if (realPath == nullptr) {
RadarParaInfo info = {"SetCmd", ReportLevel::INNER, DfxBizStage::KERNEL_NEG,
"kernel", "", DEFAULT_ERR, "realpath faile"};
RadarReportAdapter::GetInstance().ReportLinkConnectionAdapter(info);
return;
}
uint64_t new_tag = static_cast<uint64_t>(LOG_DOMAIN) << 32 | FDSAN_TAG;
int file = open(realPath, O_RDWR);
if (file < 0) {
LOGE("Open node file error. %{public}d", errno);
RadarParaInfo info = {"SetCmd", ReportLevel::INNER, DfxBizStage::KERNEL_NEG,
"kernel", "", file, "Open node file err, error=" + to_string(errno)};
RadarReportAdapter::GetInstance().ReportLinkConnectionAdapter(info);
return;
}
fdsan_exchange_owner_tag(file, 0, new_tag);
int err = write(file, &cmd, sizeof(T));
if (err < 0) {
LOGE("write return err. %{public}d", errno);
RadarParaInfo info = {"SetCmd", ReportLevel::INNER, DfxBizStage::KERNEL_NEG,
"kernel", "", err, "write return err, errno=" + to_string(errno)};
RadarReportAdapter::GetInstance().ReportLinkConnectionAdapter(info);
}
fdsan_close_with_tag(file, new_tag);
}
void PollRun();
void HandleAllNotify(int fd);
void NotifyHandler(NotifyParam ¶m);
uint8_t GetSecurityMode();
std::weak_ptr<MountPoint> mountPoint_;
std::mutex cmdMutex_;
std::atomic<bool> isRunning_ {true};
std::mutex pollThreadMutex_;
std::unique_ptr<std::thread> pollThread_ {nullptr};
std::function<void(NotifyParam &)> GetSessionCallback_ {nullptr};
std::function<void(const std::string &cid)> CloseSessionCallback_ {nullptr};
};
}
}
}
#endif