1 /*
2  * Copyright (c) 2023 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_policy_file_event_handler.h"
17 
18 #include <fcntl.h>
19 #include <fstream>
20 #include <iostream>
21 #include <sys/stat.h>
22 #include <thread>
23 #include <unistd.h>
24 
25 #include "net_mgr_log_wrapper.h"
26 #include "net_policy_inner_define.h"
27 
28 namespace OHOS {
29 namespace NetManagerStandard {
30 namespace {
31 constexpr uint32_t MAX_TIME_MS_DELTA = 5000;
32 constexpr uint32_t SEND_TIME_MS_INTERVAL = 2000;
33 
GetNowMilliSeconds()34 int64_t GetNowMilliSeconds()
35 {
36     auto nowSys = AppExecFwk::InnerEvent::Clock::now();
37     auto epoch = nowSys.time_since_epoch();
38     return std::chrono::duration_cast<std::chrono::milliseconds>(epoch).count();
39 }
40 } // namespace
41 
NetPolicyFileEventHandler(const char * queueName)42 NetPolicyFileEventHandler::NetPolicyFileEventHandler(const char *queueName) : netPolicyFileEventQueue_(queueName) {}
43 
SendWriteEvent(AppExecFwk::InnerEvent::Pointer & event)44 void NetPolicyFileEventHandler::SendWriteEvent(AppExecFwk::InnerEvent::Pointer &event)
45 {
46     SendEvent(event);
47 }
48 
SendEvent(const AppExecFwk::InnerEvent::Pointer & event,uint32_t delayTime)49 void NetPolicyFileEventHandler::SendEvent(const AppExecFwk::InnerEvent::Pointer &event, uint32_t delayTime)
50 {
51     auto eventId = event->GetInnerEventId();
52     auto eventData = event->GetSharedObject<PolicyFileEvent>();
53     netPolicyFileEventQueue_.submit([this, eventId, eventData] { ProcessEvent(eventId, eventData); },
54                                     ffrt::task_attr().delay(static_cast<uint64_t>(delayTime)).name("FfrtSendEvent"));
55 }
56 
ProcessEvent(uint32_t eventId,std::shared_ptr<PolicyFileEvent> eventData)57 void NetPolicyFileEventHandler::ProcessEvent(uint32_t eventId, std::shared_ptr<PolicyFileEvent> eventData)
58 {
59     if (eventId == MSG_POLICY_FILE_WRITE) {
60         fileContent_ = eventData->json;
61         if (commitWait_) {
62             return;
63         }
64         int64_t timeDelta = GetNowMilliSeconds() - timeStamp_;
65         uint32_t delay = timeDelta >= MAX_TIME_MS_DELTA ? 0 : static_cast<uint32_t>(MAX_TIME_MS_DELTA - timeDelta);
66         commitWait_ = true;
67         NETMGR_LOG_D("SendEvent MSG_POLICY_FILE_COMMIT[delay=%{public}d, now=%{public}s]", delay,
68                      std::to_string(GetNowMilliSeconds()).c_str());
69         SendEvent(AppExecFwk::InnerEvent::Get(MSG_POLICY_FILE_COMMIT, std::make_shared<PolicyFileEvent>()), delay);
70         return;
71     }
72 
73     if (eventId == MSG_POLICY_FILE_COMMIT) {
74         commitWait_ = !Write();
75         timeStamp_ = GetNowMilliSeconds();
76         if (commitWait_) {
77             SendEvent(AppExecFwk::InnerEvent::Get(MSG_POLICY_FILE_COMMIT, std::make_shared<PolicyFileEvent>()),
78                       MAX_TIME_MS_DELTA);
79         }
80         SendEvent(AppExecFwk::InnerEvent::Get(MSG_POLICY_FILE_DELETE, std::make_shared<PolicyFileEvent>()),
81                   SEND_TIME_MS_INTERVAL);
82         return;
83     }
84 
85     if (MSG_POLICY_FILE_DELETE == eventId) {
86         DeleteBak();
87     }
88 }
89 
Write()90 bool NetPolicyFileEventHandler::Write()
91 {
92     NETMGR_LOG_D("write file to disk.");
93     struct stat buffer;
94     if (stat(POLICY_FILE_NAME, &buffer) == 0) {
95         std::ifstream oldFile(POLICY_FILE_NAME, std::ios::binary);
96         std::ofstream newFile(POLICY_FILE_BAK_NAME, std::ios::binary);
97         if (!oldFile.is_open() && !newFile.is_open()) {
98             NETMGR_LOG_E("File backup failed.");
99             return false;
100         }
101         newFile << oldFile.rdbuf();
102         oldFile.close();
103         newFile.close();
104     }
105     std::fstream file(POLICY_FILE_NAME, std::fstream::out | std::fstream::trunc);
106     if (!file.is_open()) {
107         NETMGR_LOG_E("open file error.");
108         return false;
109     }
110     file << fileContent_;
111     file.close();
112     return true;
113 }
114 
DeleteBak()115 bool NetPolicyFileEventHandler::DeleteBak()
116 {
117     struct stat buffer;
118     if (stat(POLICY_FILE_BAK_NAME, &buffer) == 0) {
119         int32_t err = remove(POLICY_FILE_BAK_NAME);
120         if (err != 0) {
121             NETMGR_LOG_E("remove file error.");
122             return false;
123         }
124         int fd = open(POLICY_FILE_BAK_PATH, O_RDONLY);
125         if (fd == -1) {
126             NETMGR_LOG_E("open the file path failed.");
127             return false;
128         }
129         if (fsync(fd) != 0) {
130             NETMGR_LOG_E("fsync the file path failed.");
131             close(fd);
132             return false;
133         }
134         close(fd);
135     }
136     return true;
137 }
138 } // namespace NetManagerStandard
139 } // namespace OHOS
140