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 #include "ntp_trusted_time.h"
17 
18 #include <cinttypes>
19 #include <cstdint>
20 #include <cstdio>
21 #include <cstring>
22 #include <securec.h>
23 #include <unistd.h>
24 
25 #include "sntp_client.h"
26 #include "time_common.h"
27 
28 namespace OHOS {
29 namespace MiscServices {
30 namespace {
31 constexpr int64_t TIME_RESULT_UNINITED = -1;
32 constexpr int64_t HALF = 2;
33 const int NANO_TO_SECOND =  1000000000;
34 } // namespace
35 
GetInstance()36 NtpTrustedTime &NtpTrustedTime::GetInstance()
37 {
38     static NtpTrustedTime instance;
39     return instance;
40 }
41 
ForceRefresh(const std::string & ntpServer)42 bool NtpTrustedTime::ForceRefresh(const std::string &ntpServer)
43 {
44     TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
45     SNTPClient client;
46     if (client.RequestTime(ntpServer)) {
47         if (mTimeResult != nullptr) {
48             mTimeResult->Clear();
49         }
50         int64_t ntpCertainty = client.getRoundTripTime() / HALF;
51         mTimeResult = std::make_shared<TimeResult>(client.getNtpTime(), client.getNtpTimeReference(), ntpCertainty);
52         TIME_HILOGD(TIME_MODULE_SERVICE, "Get Ntp time result");
53         return true;
54     }
55     TIME_HILOGD(TIME_MODULE_SERVICE, "false end.");
56     return false;
57 }
58 
CurrentTimeMillis()59 int64_t NtpTrustedTime::CurrentTimeMillis()
60 {
61     TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
62     if (mTimeResult == nullptr) {
63         TIME_HILOGD(TIME_MODULE_SERVICE, "Missing authoritative time source");
64         return TIME_RESULT_UNINITED;
65     }
66     TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
67     return mTimeResult->CurrentTimeMillis();
68 }
69 
ElapsedRealtimeMillis()70 int64_t NtpTrustedTime::ElapsedRealtimeMillis()
71 {
72     TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
73     if (mTimeResult == nullptr) {
74         TIME_HILOGD(TIME_MODULE_SERVICE, "Missing authoritative time source");
75         return TIME_RESULT_UNINITED;
76     }
77     TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
78     return mTimeResult->GetElapsedRealtimeMillis();
79 }
80 
GetCacheAge()81 int64_t NtpTrustedTime::GetCacheAge()
82 {
83     if (mTimeResult != nullptr) {
84         return std::chrono::duration_cast<std::chrono::milliseconds>(
85                    std::chrono::steady_clock::now().time_since_epoch())
86                    .count() -
87                mTimeResult->GetElapsedRealtimeMillis();
88     } else {
89         return INT_MAX;
90     }
91 }
92 
GetBootTimeNs()93 std::chrono::steady_clock::time_point NtpTrustedTime::GetBootTimeNs()
94 {
95     int64_t timeNow = -1;
96     struct timespec tv {};
97     if (clock_gettime(CLOCK_BOOTTIME, &tv) < 0) {
98         return std::chrono::steady_clock::now();
99     }
100     timeNow = tv.tv_sec * NANO_TO_SECOND + tv.tv_nsec;
101     std::chrono::steady_clock::time_point tp_epoch ((std::chrono::nanoseconds(timeNow)));
102     return tp_epoch;
103 }
104 
105 
GetTimeMillis()106 int64_t NtpTrustedTime::TimeResult::GetTimeMillis()
107 {
108     return mTimeMillis;
109 }
110 
GetElapsedRealtimeMillis()111 int64_t NtpTrustedTime::TimeResult::GetElapsedRealtimeMillis()
112 {
113     return mElapsedRealtimeMillis;
114 }
115 
CurrentTimeMillis()116 int64_t NtpTrustedTime::TimeResult::CurrentTimeMillis()
117 {
118     if (mTimeMillis == 0 || mElapsedRealtimeMillis == 0) {
119         TIME_HILOGD(TIME_MODULE_SERVICE, "Missing authoritative time source");
120         return TIME_RESULT_UNINITED;
121     }
122     return mTimeMillis + GetAgeMillis();
123 }
124 
GetAgeMillis()125 int64_t NtpTrustedTime::TimeResult::GetAgeMillis()
126 {
127     return std::chrono::duration_cast<std::chrono::milliseconds>(
128         NtpTrustedTime::GetInstance().GetBootTimeNs().time_since_epoch()).count() - this->mElapsedRealtimeMillis;
129 }
130 
TimeResult()131 NtpTrustedTime::TimeResult::TimeResult()
132 {
133 }
~TimeResult()134 NtpTrustedTime::TimeResult::~TimeResult()
135 {
136 }
137 
TimeResult(int64_t mTimeMillis,int64_t mElapsedRealtimeMills,int64_t mCertaintyMillis)138 NtpTrustedTime::TimeResult::TimeResult(int64_t mTimeMillis, int64_t mElapsedRealtimeMills, int64_t mCertaintyMillis)
139 {
140     this->mTimeMillis = mTimeMillis;
141     this->mElapsedRealtimeMillis = mElapsedRealtimeMills;
142     this->mCertaintyMillis = mCertaintyMillis;
143     TIME_HILOGD(TIME_MODULE_SERVICE, "mTimeMillis %{public}" PRId64 "", mTimeMillis);
144     TIME_HILOGD(TIME_MODULE_SERVICE, "mElapsedRealtimeMills %{public}" PRId64 "", mElapsedRealtimeMills);
145     TIME_HILOGD(TIME_MODULE_SERVICE, "mCertaintyMillis %{public}" PRId64 "", mCertaintyMillis);
146 }
147 
Clear()148 void NtpTrustedTime::TimeResult::Clear()
149 {
150     mTimeMillis = 0;
151     mElapsedRealtimeMillis = 0;
152     mCertaintyMillis = 0;
153 }
154 } // namespace MiscServices
155 } // namespace OHOS