1 /*
2  * Copyright (c) 2024 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 "net_manager_constants.h"
17 #include "netmgr_ext_log_wrapper.h"
18 #include "netfirewall_intercept_recorder.h"
19 #include "netfirewall_db_helper.h"
20 #include "netsys_controller.h"
21 
22 namespace OHOS {
23 namespace NetManagerStandard {
24 constexpr int32_t RECORD_CACHE_SIZE = 100;
25 constexpr int64_t RECORD_TASK_DELAY_TIME_MS = 3 * 60 * 1000;
26 
27 std::shared_ptr<NetFirewallInterceptRecorder> NetFirewallInterceptRecorder::instance_ = nullptr;
28 
GetInstance()29 std::shared_ptr<NetFirewallInterceptRecorder> NetFirewallInterceptRecorder::GetInstance()
30 {
31     static std::mutex instanceMutex;
32     std::lock_guard<std::mutex> guard(instanceMutex);
33     if (instance_ == nullptr) {
34         instance_.reset(new NetFirewallInterceptRecorder());
35     }
36     return instance_;
37 }
38 
NetFirewallInterceptRecorder()39 NetFirewallInterceptRecorder::NetFirewallInterceptRecorder()
40 {
41     NETMGR_EXT_LOG_I("NetFirewallInterceptRecorder");
42 }
43 
~NetFirewallInterceptRecorder()44 NetFirewallInterceptRecorder::~NetFirewallInterceptRecorder()
45 {
46     NETMGR_EXT_LOG_I("~NetFirewallInterceptRecorder");
47 }
48 
GetInterceptRecords(const int32_t userId,const sptr<RequestParam> & requestParam,sptr<InterceptRecordPage> & info)49 int32_t NetFirewallInterceptRecorder::GetInterceptRecords(const int32_t userId, const sptr<RequestParam> &requestParam,
50     sptr<InterceptRecordPage> &info)
51 {
52     if (requestParam == nullptr) {
53         NETMGR_EXT_LOG_E("GetInterceptRecords requestParam is null");
54         return FIREWALL_ERR_PARAMETER_ERROR;
55     }
56     if (info == nullptr) {
57         NETMGR_EXT_LOG_E("GetInterceptRecords info is null");
58         return FIREWALL_ERR_INTERNAL;
59     }
60     std::lock_guard<std::shared_mutex> locker(setRecordMutex_);
61     info->pageSize = requestParam->pageSize;
62     int32_t ret = NetFirewallDbHelper::GetInstance().QueryInterceptRecord(userId, requestParam, info);
63     if (ret < 0) {
64         NETMGR_EXT_LOG_E("GetInterceptRecords error");
65         return FIREWALL_ERR_INTERNAL;
66     }
67     return FIREWALL_SUCCESS;
68 }
69 
SetCurrentUserId(int32_t userId)70 void NetFirewallInterceptRecorder::SetCurrentUserId(int32_t userId)
71 {
72     NETMGR_EXT_LOG_I("SetCurrentUserId userid = %{public}d", userId);
73     std::lock_guard<std::shared_mutex> locker(setRecordMutex_);
74     currentUserId_ = userId;
75 }
76 
GetRecordCacheSize()77 int32_t NetFirewallInterceptRecorder::GetRecordCacheSize()
78 {
79     std::shared_lock<std::shared_mutex> locker(setRecordMutex_);
80     return recordCache_.size();
81 }
82 
PutRecordCache(sptr<InterceptRecord> record)83 void NetFirewallInterceptRecorder::PutRecordCache(sptr<InterceptRecord> record)
84 {
85     std::lock_guard<std::shared_mutex> locker(setRecordMutex_);
86     if (record != nullptr) {
87         recordCache_.emplace_back(record);
88     }
89 }
90 
SyncRecordCache()91 void NetFirewallInterceptRecorder::SyncRecordCache()
92 {
93     std::lock_guard<std::shared_mutex> locker(setRecordMutex_);
94     if (!recordCache_.empty()) {
95         NetFirewallDbHelper::GetInstance().AddInterceptRecord(currentUserId_, recordCache_);
96         recordCache_.clear();
97     }
98 }
99 
RegisterInterceptCallback()100 int32_t NetFirewallInterceptRecorder::RegisterInterceptCallback()
101 {
102     NETMGR_EXT_LOG_I("RegisterInterceptCallback");
103     if (callback_ == nullptr) {
104         callback_ = new (std::nothrow) FirewallCallback(shared_from_this());
105     }
106     return NetsysController::GetInstance().RegisterNetFirewallCallback(callback_);
107 }
108 
UnRegisterInterceptCallback()109 int32_t NetFirewallInterceptRecorder::UnRegisterInterceptCallback()
110 {
111     NETMGR_EXT_LOG_I("UnRegisterInterceptCallback");
112     int32_t ret = FIREWALL_SUCCESS;
113     if (callback_) {
114         ret = NetsysController::GetInstance().UnRegisterNetFirewallCallback(callback_);
115         callback_ = nullptr;
116     }
117 
118     return ret;
119 }
120 
OnIntercept(sptr<InterceptRecord> & record)121 int32_t NetFirewallInterceptRecorder::FirewallCallback::OnIntercept(sptr<InterceptRecord> &record)
122 {
123     NETMGR_EXT_LOG_I("FirewallCallback::OnIntercept: time=%{public}d", record->time);
124     recorder_->PutRecordCache(record);
125     if (recordTaskHandle_ != nullptr) {
126         ffrtQueue_->cancel(recordTaskHandle_);
127         recordTaskHandle_ = nullptr;
128     }
129     auto callback = [this]() { recorder_->SyncRecordCache(); };
130     if (recorder_->GetRecordCacheSize() < RECORD_CACHE_SIZE) {
131         // Write every three minutes when dissatisfied
132         recordTaskHandle_ =
133             ffrtQueue_->submit_h(callback, ffrt::task_attr().delay(RECORD_TASK_DELAY_TIME_MS).name("OnIntercept"));
134     } else {
135         ffrtQueue_->submit(callback);
136     }
137     return FIREWALL_SUCCESS;
138 }
139 } // namespace NetManagerStandard
140 } // namespace OHOS
141