1800b99b8Sopenharmony_ci/*
2800b99b8Sopenharmony_ci * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3800b99b8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4800b99b8Sopenharmony_ci * you may not use this file except in compliance with the License.
5800b99b8Sopenharmony_ci * You may obtain a copy of the License at
6800b99b8Sopenharmony_ci *
7800b99b8Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8800b99b8Sopenharmony_ci *
9800b99b8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10800b99b8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11800b99b8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12800b99b8Sopenharmony_ci * See the License for the specific language governing permissions and
13800b99b8Sopenharmony_ci * limitations under the License.
14800b99b8Sopenharmony_ci */
15800b99b8Sopenharmony_ci
16800b99b8Sopenharmony_ci#include "fault_logger_pipe.h"
17800b99b8Sopenharmony_ci
18800b99b8Sopenharmony_ci#include <algorithm>
19800b99b8Sopenharmony_ci#include <cerrno>
20800b99b8Sopenharmony_ci#include <cstdio>
21800b99b8Sopenharmony_ci#include <cstdlib>
22800b99b8Sopenharmony_ci#include <cstring>
23800b99b8Sopenharmony_ci#include <ctime>
24800b99b8Sopenharmony_ci#include <fcntl.h>
25800b99b8Sopenharmony_ci#include <securec.h>
26800b99b8Sopenharmony_ci#include <string>
27800b99b8Sopenharmony_ci#include <sys/socket.h>
28800b99b8Sopenharmony_ci#include <sys/stat.h>
29800b99b8Sopenharmony_ci#include <sys/syscall.h>
30800b99b8Sopenharmony_ci#include <sys/types.h>
31800b99b8Sopenharmony_ci#include <sys/un.h>
32800b99b8Sopenharmony_ci#include <unistd.h>
33800b99b8Sopenharmony_ci#include <vector>
34800b99b8Sopenharmony_ci#include "dfx_define.h"
35800b99b8Sopenharmony_ci#include "dfx_log.h"
36800b99b8Sopenharmony_ci
37800b99b8Sopenharmony_cinamespace OHOS {
38800b99b8Sopenharmony_cinamespace HiviewDFX {
39800b99b8Sopenharmony_cinamespace {
40800b99b8Sopenharmony_ciconst std::string FAULTLOGGER_PIPE_TAG = "FaultLoggerPipe";
41800b99b8Sopenharmony_ciconst int PIPE_TIMEOUT = 10000; // 10 seconds
42800b99b8Sopenharmony_ci}
43800b99b8Sopenharmony_ci
44800b99b8Sopenharmony_ciFaultLoggerPipe::FaultLoggerPipe()
45800b99b8Sopenharmony_ci{
46800b99b8Sopenharmony_ci    init_ = false;
47800b99b8Sopenharmony_ci    write_ = false;
48800b99b8Sopenharmony_ci    Init();
49800b99b8Sopenharmony_ci}
50800b99b8Sopenharmony_ci
51800b99b8Sopenharmony_ciFaultLoggerPipe::~FaultLoggerPipe()
52800b99b8Sopenharmony_ci{
53800b99b8Sopenharmony_ci    Destroy();
54800b99b8Sopenharmony_ci}
55800b99b8Sopenharmony_ci
56800b99b8Sopenharmony_ciint FaultLoggerPipe::GetReadFd(void)
57800b99b8Sopenharmony_ci{
58800b99b8Sopenharmony_ci    DFXLOGD("%{public}s :: pipe read fd: %{public}d", __func__, fds_[PIPE_READ]);
59800b99b8Sopenharmony_ci    return fds_[PIPE_READ];
60800b99b8Sopenharmony_ci}
61800b99b8Sopenharmony_ci
62800b99b8Sopenharmony_ciint FaultLoggerPipe::GetWriteFd(void)
63800b99b8Sopenharmony_ci{
64800b99b8Sopenharmony_ci    DFXLOGD("%{public}s :: pipe write fd: %{public}d", __func__, fds_[PIPE_WRITE]);
65800b99b8Sopenharmony_ci    if (!write_) {
66800b99b8Sopenharmony_ci        write_ = true;
67800b99b8Sopenharmony_ci        return fds_[PIPE_WRITE];
68800b99b8Sopenharmony_ci    }
69800b99b8Sopenharmony_ci    return -1;
70800b99b8Sopenharmony_ci}
71800b99b8Sopenharmony_ci
72800b99b8Sopenharmony_cibool FaultLoggerPipe::Init(void)
73800b99b8Sopenharmony_ci{
74800b99b8Sopenharmony_ci    if (!init_) {
75800b99b8Sopenharmony_ci        if (pipe2(fds_, O_NONBLOCK) != 0) {
76800b99b8Sopenharmony_ci            DFXLOGE("%{public}s :: Failed to create pipe.", __func__);
77800b99b8Sopenharmony_ci            return false;
78800b99b8Sopenharmony_ci        }
79800b99b8Sopenharmony_ci        DFXLOGD("%{public}s :: create pipe.", __func__);
80800b99b8Sopenharmony_ci    }
81800b99b8Sopenharmony_ci    init_ = true;
82800b99b8Sopenharmony_ci    if (!SetSize(MAX_PIPE_SIZE)) {
83800b99b8Sopenharmony_ci        DFXLOGE("%{public}s :: Failed to set pipe size.", __func__);
84800b99b8Sopenharmony_ci    }
85800b99b8Sopenharmony_ci    return true;
86800b99b8Sopenharmony_ci}
87800b99b8Sopenharmony_ci
88800b99b8Sopenharmony_cibool FaultLoggerPipe::SetSize(long sz)
89800b99b8Sopenharmony_ci{
90800b99b8Sopenharmony_ci    if (!init_) {
91800b99b8Sopenharmony_ci        return false;
92800b99b8Sopenharmony_ci    }
93800b99b8Sopenharmony_ci    if (fcntl(fds_[PIPE_READ], F_SETPIPE_SZ, sz) < 0) {
94800b99b8Sopenharmony_ci        return false;
95800b99b8Sopenharmony_ci    }
96800b99b8Sopenharmony_ci    if (fcntl(fds_[PIPE_WRITE], F_SETPIPE_SZ, sz) < 0) {
97800b99b8Sopenharmony_ci        return false;
98800b99b8Sopenharmony_ci    }
99800b99b8Sopenharmony_ci    return true;
100800b99b8Sopenharmony_ci}
101800b99b8Sopenharmony_ci
102800b99b8Sopenharmony_civoid FaultLoggerPipe::Destroy(void)
103800b99b8Sopenharmony_ci{
104800b99b8Sopenharmony_ci    if (init_) {
105800b99b8Sopenharmony_ci        DFXLOGD("%{public}s :: close pipe.", __func__);
106800b99b8Sopenharmony_ci        Close(fds_[PIPE_READ]);
107800b99b8Sopenharmony_ci        Close(fds_[PIPE_WRITE]);
108800b99b8Sopenharmony_ci    }
109800b99b8Sopenharmony_ci    init_ = false;
110800b99b8Sopenharmony_ci}
111800b99b8Sopenharmony_ci
112800b99b8Sopenharmony_civoid FaultLoggerPipe::Close(int fd) const
113800b99b8Sopenharmony_ci{
114800b99b8Sopenharmony_ci    if (fd > 0) {
115800b99b8Sopenharmony_ci        syscall(SYS_close, fd);
116800b99b8Sopenharmony_ci    }
117800b99b8Sopenharmony_ci}
118800b99b8Sopenharmony_ci
119800b99b8Sopenharmony_ciFaultLoggerPipe2::FaultLoggerPipe2(uint64_t time, bool isJson)
120800b99b8Sopenharmony_ci{
121800b99b8Sopenharmony_ci    if (isJson) {
122800b99b8Sopenharmony_ci        faultLoggerJsonPipeBuf_ = std::unique_ptr<FaultLoggerPipe>(new FaultLoggerPipe());
123800b99b8Sopenharmony_ci        faultLoggerJsonPipeRes_ = std::unique_ptr<FaultLoggerPipe>(new FaultLoggerPipe());
124800b99b8Sopenharmony_ci    } else {
125800b99b8Sopenharmony_ci        faultLoggerPipeBuf_ = std::unique_ptr<FaultLoggerPipe>(new FaultLoggerPipe());
126800b99b8Sopenharmony_ci        faultLoggerPipeRes_ = std::unique_ptr<FaultLoggerPipe>(new FaultLoggerPipe());
127800b99b8Sopenharmony_ci    }
128800b99b8Sopenharmony_ci    time_ = time;
129800b99b8Sopenharmony_ci}
130800b99b8Sopenharmony_ci
131800b99b8Sopenharmony_ciFaultLoggerPipe2::~FaultLoggerPipe2()
132800b99b8Sopenharmony_ci{
133800b99b8Sopenharmony_ci    faultLoggerPipeBuf_.reset();
134800b99b8Sopenharmony_ci    faultLoggerPipeRes_.reset();
135800b99b8Sopenharmony_ci    faultLoggerJsonPipeBuf_.reset();
136800b99b8Sopenharmony_ci    faultLoggerJsonPipeRes_.reset();
137800b99b8Sopenharmony_ci    time_ = 0;
138800b99b8Sopenharmony_ci}
139800b99b8Sopenharmony_ci
140800b99b8Sopenharmony_ciFaultLoggerPipeMap::FaultLoggerPipeMap()
141800b99b8Sopenharmony_ci{
142800b99b8Sopenharmony_ci    std::lock_guard<std::mutex> lck(pipeMapsMutex_);
143800b99b8Sopenharmony_ci    faultLoggerPipes_.clear();
144800b99b8Sopenharmony_ci}
145800b99b8Sopenharmony_ci
146800b99b8Sopenharmony_ciFaultLoggerPipeMap::~FaultLoggerPipeMap()
147800b99b8Sopenharmony_ci{
148800b99b8Sopenharmony_ci    std::lock_guard<std::mutex> lck(pipeMapsMutex_);
149800b99b8Sopenharmony_ci    std::map<int, std::unique_ptr<FaultLoggerPipe2> >::iterator iter = faultLoggerPipes_.begin();
150800b99b8Sopenharmony_ci    while (iter != faultLoggerPipes_.end()) {
151800b99b8Sopenharmony_ci        faultLoggerPipes_.erase(iter++);
152800b99b8Sopenharmony_ci    }
153800b99b8Sopenharmony_ci}
154800b99b8Sopenharmony_ci
155800b99b8Sopenharmony_civoid FaultLoggerPipeMap::Set(int pid, uint64_t time, bool isJson)
156800b99b8Sopenharmony_ci{
157800b99b8Sopenharmony_ci    std::lock_guard<std::mutex> lck(pipeMapsMutex_);
158800b99b8Sopenharmony_ci    if (!Find(pid)) {
159800b99b8Sopenharmony_ci        std::unique_ptr<FaultLoggerPipe2> ptr = std::unique_ptr<FaultLoggerPipe2>(new FaultLoggerPipe2(time, isJson));
160800b99b8Sopenharmony_ci        faultLoggerPipes_.emplace(pid, std::move(ptr));
161800b99b8Sopenharmony_ci    }
162800b99b8Sopenharmony_ci}
163800b99b8Sopenharmony_ci
164800b99b8Sopenharmony_cibool FaultLoggerPipeMap::Check(int pid, uint64_t time)
165800b99b8Sopenharmony_ci{
166800b99b8Sopenharmony_ci    std::lock_guard<std::mutex> lck(pipeMapsMutex_);
167800b99b8Sopenharmony_ci    std::map<int, std::unique_ptr<FaultLoggerPipe2> >::const_iterator iter = faultLoggerPipes_.find(pid);
168800b99b8Sopenharmony_ci    if (iter != faultLoggerPipes_.end()) {
169800b99b8Sopenharmony_ci        if ((time > faultLoggerPipes_[pid]->time_) && (time - faultLoggerPipes_[pid]->time_) > PIPE_TIMEOUT) {
170800b99b8Sopenharmony_ci            faultLoggerPipes_.erase(iter);
171800b99b8Sopenharmony_ci            return false;
172800b99b8Sopenharmony_ci        }
173800b99b8Sopenharmony_ci        return true;
174800b99b8Sopenharmony_ci    }
175800b99b8Sopenharmony_ci    return false;
176800b99b8Sopenharmony_ci}
177800b99b8Sopenharmony_ci
178800b99b8Sopenharmony_ciFaultLoggerPipe2* FaultLoggerPipeMap::Get(int pid)
179800b99b8Sopenharmony_ci{
180800b99b8Sopenharmony_ci    std::lock_guard<std::mutex> lck(pipeMapsMutex_);
181800b99b8Sopenharmony_ci    if (!Find(pid)) {
182800b99b8Sopenharmony_ci        return nullptr;
183800b99b8Sopenharmony_ci    }
184800b99b8Sopenharmony_ci    return faultLoggerPipes_[pid].get();
185800b99b8Sopenharmony_ci}
186800b99b8Sopenharmony_ci
187800b99b8Sopenharmony_civoid FaultLoggerPipeMap::Del(int pid)
188800b99b8Sopenharmony_ci{
189800b99b8Sopenharmony_ci    std::lock_guard<std::mutex> lck(pipeMapsMutex_);
190800b99b8Sopenharmony_ci    std::map<int, std::unique_ptr<FaultLoggerPipe2> >::const_iterator iter = faultLoggerPipes_.find(pid);
191800b99b8Sopenharmony_ci    if (iter != faultLoggerPipes_.end()) {
192800b99b8Sopenharmony_ci        faultLoggerPipes_.erase(iter);
193800b99b8Sopenharmony_ci    }
194800b99b8Sopenharmony_ci}
195800b99b8Sopenharmony_ci
196800b99b8Sopenharmony_cibool FaultLoggerPipeMap::Find(int pid) const
197800b99b8Sopenharmony_ci{
198800b99b8Sopenharmony_ci    std::map<int, std::unique_ptr<FaultLoggerPipe2> >::const_iterator iter = faultLoggerPipes_.find(pid);
199800b99b8Sopenharmony_ci    if (iter != faultLoggerPipes_.end()) {
200800b99b8Sopenharmony_ci        return true;
201800b99b8Sopenharmony_ci    }
202800b99b8Sopenharmony_ci    return false;
203800b99b8Sopenharmony_ci}
204800b99b8Sopenharmony_ci} // namespace HiviewDfx
205800b99b8Sopenharmony_ci} // namespace OHOS
206