1/*
2 * Copyright (c) 2022 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#ifndef LOG_IOCTL_H
17#define LOG_IOCTL_H
18
19#include <vector>
20#include <functional>
21#include <securec.h>
22
23#include "hilog_common.h"
24#include "log_utils.h"
25#include "hilog_cmd.h"
26#include "seq_packet_socket_client.h"
27
28namespace OHOS {
29namespace HiviewDFX {
30using namespace std;
31
32class LogIoctl {
33public:
34    LogIoctl(IoctlCmd rqst, IoctlCmd rsp);
35    ~LogIoctl() = default;
36
37    template<typename T1, typename T2>
38    int Request(const T1& rqst,  std::function<int(const T2& rsp)> handle);
39    int RequestOutput(const OutputRqst& rqst, std::function<int(const OutputRsp& rsp)> handle);
40    int RequestStatsQuery(const StatsQueryRqst& rqst, std::function<int(const StatsQueryRsp& rsp)> handle);
41
42private:
43    SeqPacketSocketClient socket;
44    int socketInit = -1;
45    IoctlCmd rqstCmd;
46    IoctlCmd rspCmd;
47    static constexpr int DEFAULT_RECV_BUF_LEN = MAX_LOG_LEN * 2;
48
49    int SendMsgHeader(IoctlCmd cmd, size_t len);
50    int ReceiveMsgHeaer(MsgHeader& hdr);
51    int GetRsp(char* rsp, int len);
52    template<typename T1, typename T2>
53    int RequestMsgHead(const T1& rqst);
54
55    int ReceiveAndProcessOutputRsp(std::function<int(const OutputRsp& rsp)> handle);
56    int ReceiveAndProcessStatsQueryRsp(std::function<int(const StatsQueryRsp& rsp)> handle);
57    int ReceiveProcTagStats(StatsQueryRsp &rsp);
58    int ReceiveProcLogTypeStats(StatsQueryRsp &rsp);
59    int ReceiveProcStats(StatsQueryRsp &rsp);
60    int ReceiveDomainTagStats(StatsQueryRsp &rsp);
61    int ReceiveDomainStats(StatsQueryRsp &rsp);
62    int ReceiveLogTypeDomainStats(StatsQueryRsp &rsp);
63    void DeleteLogStatsInfo(StatsQueryRsp &rsp);
64};
65
66template<typename T1, typename T2>
67int LogIoctl::RequestMsgHead(const T1& rqst)
68{
69    // 0. Send reqeust message and process the response header
70    int ret = SendMsgHeader(rqstCmd, sizeof(T1));
71    if (ret != RET_SUCCESS) {
72        return ret;
73    }
74    ret = socket.WriteAll(reinterpret_cast<const char*>(&rqst), sizeof(T1));
75    if (ret < 0) {
76        return ERR_SOCKET_WRITE_CMD_FAIL;
77    }
78    // 1. Receive msg header
79    MsgHeader hdr = { 0 };
80    ret = ReceiveMsgHeaer(hdr);
81    if (ret != RET_SUCCESS) {
82        return ret;
83    }
84    if (hdr.cmd == static_cast<uint8_t>(IoctlCmd::RSP_ERROR)) {
85        return hdr.err;
86    }
87    if (hdr.cmd != static_cast<uint8_t>(rspCmd)) {
88        return RET_FAIL;
89    }
90    if (hdr.len != sizeof(T2)) {
91        return ERR_MSG_LEN_INVALID;
92    }
93    return RET_SUCCESS;
94}
95
96template<typename T1, typename T2>
97int LogIoctl::Request(const T1& rqst, std::function<int(const T2& rsp)> handle)
98{
99    if (rqstCmd == IoctlCmd::OUTPUT_RQST || rqstCmd == IoctlCmd::STATS_QUERY_RQST) {
100        std::cout << "Request API not support this command" << endl;
101        return RET_FAIL;
102    }
103    int ret = RequestMsgHead<T1, T2>(rqst);
104    if (ret != RET_SUCCESS) {
105        return ret;
106    }
107    // common case, Get Response and callback
108    T2 rsp = { 0 };
109    ret = GetRsp(reinterpret_cast<char*>(&rsp), sizeof(T2));
110    if (ret != RET_SUCCESS) {
111        return ret;
112    }
113    return handle(rsp);
114}
115} // namespace HiviewDFX
116} // namespace OHOS
117#endif // LOG_IOCTL_H