From 385040b882465f52e3cf3df5a4a7e591a844ab66 Mon Sep 17 00:00:00 2001 From: xujunyang Date: Tue, 12 Aug 2025 12:27:18 +0800 Subject: [PATCH] =?UTF-8?q?NTP=E5=9C=A8=E6=97=A0=E7=BD=91=E6=83=85?= =?UTF-8?q?=E5=86=B5=E4=B8=8B=E5=A2=9E=E5=8A=A0=E9=87=8D=E8=AF=95=E6=9C=BA?= =?UTF-8?q?=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xujunyang Change-Id: I3daf2912d708840c79e23753ab79e6092333e02e --- services/time/include/ntp_trusted_time.h | 3 +- services/time/include/ntp_update_time.h | 5 ++ services/time/include/sntp_client.h | 10 +++- services/time/src/ntp_trusted_time.cpp | 9 ++-- services/time/src/ntp_update_time.cpp | 52 ++++++++++++++++++- services/time/src/sntp_client.cpp | 31 +++++++---- .../timesntp_fuzzer/timesntp_fuzzer.cpp | 2 +- .../src/time_service_time_test.cpp | 39 +++++++++++++- 8 files changed, 130 insertions(+), 21 deletions(-) diff --git a/services/time/include/ntp_trusted_time.h b/services/time/include/ntp_trusted_time.h index 56661134..b4d8cb78 100644 --- a/services/time/include/ntp_trusted_time.h +++ b/services/time/include/ntp_trusted_time.h @@ -18,6 +18,7 @@ #define SNTP_CLIENT_NTP_TRUSTED_TIME_H #include "time_common.h" +#include "sntp_client.h" #include namespace OHOS { @@ -25,7 +26,7 @@ namespace MiscServices { class NtpTrustedTime { public: static NtpTrustedTime &GetInstance(); - bool ForceRefresh(const std::string &ntpServer); + RequestTimeResult ForceRefresh(const std::string &ntpServer, uint64_t retryTimerId); int64_t GetCacheAge(); int64_t CurrentTimeMillis(); int64_t ElapsedRealtimeMillis(); diff --git a/services/time/include/ntp_update_time.h b/services/time/include/ntp_update_time.h index a4008fed..05f21e2a 100644 --- a/services/time/include/ntp_update_time.h +++ b/services/time/include/ntp_update_time.h @@ -18,6 +18,8 @@ #include +#include "sntp_client.h" + namespace OHOS { namespace MiscServices { struct AutoTimeInfo { @@ -48,7 +50,9 @@ public: private: NtpUpdateTime(); + static bool GetNtpTimeInnerSuccess(RequestTimeResult forceRefreshRes); static NtpRefreshCode GetNtpTimeInner(); + static void GetNtpTimeInnerRetry(); static bool CheckNeedSetTime(NtpRefreshCode code, int64_t time); static bool GetRealTimeInner(int64_t &time); static void ChangeNtpServerCallback(const char *key, const char *value, void *context); @@ -59,6 +63,7 @@ private: void RegisterSystemParameterListener(); static void ChangeAutoTimeCallback(const char *key, const char *value, void *context); + static uint64_t retryTimerId_; static AutoTimeInfo autoTimeInfo_; uint64_t timerId_; uint64_t nitzUpdateTimeMilli_; diff --git a/services/time/include/sntp_client.h b/services/time/include/sntp_client.h index 10dd4469..23ecebf3 100644 --- a/services/time/include/sntp_client.h +++ b/services/time/include/sntp_client.h @@ -21,9 +21,17 @@ namespace OHOS { namespace MiscServices { +enum RequestTimeResult { + SUCCESS, + GET_ADDRINFO_FAIL, + CREATE_SOCKET_FAIL, + SEND_SOCKET_FAIL, + RECEIVE_SOCKET_FAIL, +}; + class SNTPClient { public: - bool RequestTime(const std::string &host); + RequestTimeResult RequestTime(const std::string &host, uint64_t retryTimerId); int64_t getNtpTime(); int64_t getNtpTimeReference(); int64_t getRoundTripTime(); diff --git a/services/time/src/ntp_trusted_time.cpp b/services/time/src/ntp_trusted_time.cpp index edd931c4..540d5c6d 100644 --- a/services/time/src/ntp_trusted_time.cpp +++ b/services/time/src/ntp_trusted_time.cpp @@ -36,11 +36,12 @@ NtpTrustedTime &NtpTrustedTime::GetInstance() return instance; } -bool NtpTrustedTime::ForceRefresh(const std::string &ntpServer) +RequestTimeResult NtpTrustedTime::ForceRefresh(const std::string &ntpServer, uint64_t retryTimerId) { TIME_HILOGD(TIME_MODULE_SERVICE, "start"); SNTPClient client; - if (client.RequestTime(ntpServer)) { + auto requestTimeRes = client.RequestTime(ntpServer, retryTimerId); + if (requestTimeRes == RequestTimeResult::SUCCESS) { std::lock_guard lock(mTimeResultMutex_); if (mTimeResult != nullptr) { mTimeResult->Clear(); @@ -48,10 +49,10 @@ bool NtpTrustedTime::ForceRefresh(const std::string &ntpServer) int64_t ntpCertainty = client.getRoundTripTime() / HALF; mTimeResult = std::make_shared(client.getNtpTime(), client.getNtpTimeReference(), ntpCertainty); TIME_HILOGD(TIME_MODULE_SERVICE, "Get Ntp time result"); - return true; + return RequestTimeResult::SUCCESS; } TIME_HILOGD(TIME_MODULE_SERVICE, "false end"); - return false; + return requestTimeRes; } int64_t NtpTrustedTime::CurrentTimeMillis() diff --git a/services/time/src/ntp_update_time.cpp b/services/time/src/ntp_update_time.cpp index f5f2cd63..4a06c700 100644 --- a/services/time/src/ntp_update_time.cpp +++ b/services/time/src/ntp_update_time.cpp @@ -27,6 +27,7 @@ namespace { constexpr int64_t NANO_TO_MILLISECOND = 1000000; constexpr int64_t TWO_SECOND_TO_MILLISECOND = 2000; constexpr int64_t HALF_DAY_TO_MILLISECOND = 43200000; +constexpr int64_t TEN_SECOND_TO_MILLISECOND = 10000; constexpr const char* NTP_SERVER_SYSTEM_PARAMETER = "persist.time.ntpserver"; constexpr const char* NTP_SERVER_SPECIFIC_SYSTEM_PARAMETER = "persist.time.ntpserver_specific"; constexpr uint32_t NTP_MAX_SIZE = 5; @@ -38,6 +39,7 @@ constexpr const char* DEFAULT_NTP_SERVER = "1.cn.pool.ntp.org"; constexpr int32_t RETRY_TIMES = 2; } // namespace +uint64_t NtpUpdateTime::retryTimerId_ = 0; AutoTimeInfo NtpUpdateTime::autoTimeInfo_{}; std::mutex NtpUpdateTime::requestMutex_; @@ -147,6 +149,18 @@ bool NtpUpdateTime::IsInUpdateInterval() return false; } +bool NtpUpdateTime::GetNtpTimeInnerSuccess(RequestTimeResult forceRefreshRes) +{ + if (forceRefreshRes == RequestTimeResult::SUCCESS) { + if (retryTimerId_ != 0) { + TimeSystemAbility::GetInstance()->DestroyTimer(retryTimerId_); + retryTimerId_ = 0; + } + return true; + } + return false; +} + NtpRefreshCode NtpUpdateTime::GetNtpTimeInner() { if (IsInUpdateInterval()) { @@ -156,17 +170,47 @@ NtpRefreshCode NtpUpdateTime::GetNtpTimeInner() std::vector ntpSpecList = SplitNtpAddrs(autoTimeInfo_.ntpServerSpec); std::vector ntpList = SplitNtpAddrs(autoTimeInfo_.ntpServer); ntpSpecList.insert(ntpSpecList.end(), ntpList.begin(), ntpList.end()); + bool needRetry = true; + auto forceRefreshRes = RequestTimeResult::GET_ADDRINFO_FAIL; for (int i = 0; i < RETRY_TIMES; i++) { for (size_t j = 0; j < ntpSpecList.size(); j++) { - TIME_HILOGI(TIME_MODULE_SERVICE, "ntpServer is : %{public}s", ntpSpecList[j].c_str()); - if (NtpTrustedTime::GetInstance().ForceRefresh(ntpSpecList[j])) { + if (retryTimerId_ == 0) { + TIME_HILOGI(TIME_MODULE_SERVICE, "ntpServer is : %{public}s", ntpSpecList[j].c_str()); + } + forceRefreshRes = NtpTrustedTime::GetInstance().ForceRefresh(ntpSpecList[j], retryTimerId_); + if (forceRefreshRes != RequestTimeResult::GET_ADDRINFO_FAIL) { + needRetry = false; + } + if (GetNtpTimeInnerSuccess(forceRefreshRes)) { return REFRESH_SUCCESS; } } } + if (needRetry && retryTimerId_ == 0) { + GetNtpTimeInnerRetry(); + } return REFRESH_FAILED; } +void NtpUpdateTime::GetNtpTimeInnerRetry() +{ + auto callback = [](uint64_t timerId) -> int32_t { + NtpUpdateTime::SetSystemTime(); + return E_TIME_OK; + }; + TimerPara timerPara{}; + timerPara.timerType = static_cast(ITimerManager::TimerType::ELAPSED_REALTIME); + timerPara.windowLength = 0; + timerPara.interval = TEN_SECOND_TO_MILLISECOND; + timerPara.flag = 0; + TimeSystemAbility::GetInstance()->CreateTimer(timerPara, callback, retryTimerId_); + TIME_HILOGE(TIME_MODULE_SERVICE, "GetNtpTimeInnerRetry, retryTimerId_: %{public}" PRId64 "", retryTimerId_); + int64_t bootTime = 0; + TimeUtils::GetBootTimeMs(bootTime); + auto nextTriggerTime = bootTime + TEN_SECOND_TO_MILLISECOND; + TimeSystemAbility::GetInstance()->StartTimer(retryTimerId_, nextTriggerTime); +} + bool NtpUpdateTime::GetRealTimeInner(int64_t &time) { time = NtpTrustedTime::GetInstance().CurrentTimeMillis(); @@ -223,6 +267,10 @@ void NtpUpdateTime::SetSystemTime() { if (autoTimeInfo_.status != AUTO_TIME_STATUS_ON) { TIME_HILOGI(TIME_MODULE_SERVICE, "auto sync switch off"); + if (retryTimerId_ != 0) { + TimeSystemAbility::GetInstance()->DestroyTimer(retryTimerId_); + retryTimerId_ = 0; + } return; } diff --git a/services/time/src/sntp_client.cpp b/services/time/src/sntp_client.cpp index b8bb295f..fa5c223c 100644 --- a/services/time/src/sntp_client.cpp +++ b/services/time/src/sntp_client.cpp @@ -15,6 +15,7 @@ #include "sntp_client.h" #include "ntp_trusted_time.h" +#include "ntp_update_time.h" #include #include @@ -54,7 +55,18 @@ constexpr int32_t SNTP_MSG_OFFSET_SIX = 6; constexpr int32_t SNTP_MSG_OFFSET_THREE = 3; } // namespace -bool SNTPClient::RequestTime(const std::string &host) +bool IsGetAddrInfoFail(int error, uint64_t retryTimerId) +{ + if (error != 0) { + if (retryTimerId == 0) { + TIME_HILOGE(TIME_MODULE_SERVICE, "getaddrinfo failed error %{public}d", error); + } + return true; + } + return false; +} + +RequestTimeResult SNTPClient::RequestTime(const std::string &host, uint64_t retryTimerId) { int bufLen = NTP_PACKAGE_SIZE; struct addrinfo hints = { 0 }; @@ -63,9 +75,8 @@ bool SNTPClient::RequestTime(const std::string &host) hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; int error = getaddrinfo(host.c_str(), NTP_PORT, &hints, &addrs); - if (error != 0) { - TIME_HILOGE(TIME_MODULE_SERVICE, "getaddrinfo failed error %{public}d", error); - return false; + if (IsGetAddrInfoFail(error, retryTimerId)) { + return RequestTimeResult::GET_ADDRINFO_FAIL; } // Create a socket for sending data @@ -74,7 +85,7 @@ bool SNTPClient::RequestTime(const std::string &host) TIME_HILOGE(TIME_MODULE_SERVICE, "create socket failed: %{public}s family: %{public}d socktype: %{public}d protocol: %{public}d", strerror(errno), addrs->ai_family, addrs->ai_socktype, addrs->ai_protocol); - return false; + return RequestTimeResult::CREATE_SOCKET_FAIL; } // Set send and recv function timeout @@ -84,7 +95,7 @@ bool SNTPClient::RequestTime(const std::string &host) if (connect(sendSocket, addrs->ai_addr, addrs->ai_addrlen) < 0) { TIME_HILOGE(TIME_MODULE_SERVICE, "socket connect failed: %{public}s", strerror(errno)); close(sendSocket); - return false; + return RequestTimeResult::SEND_SOCKET_FAIL; } // Create the NTP tx timestamp and fill the fields in the msg to be tx @@ -94,7 +105,7 @@ bool SNTPClient::RequestTime(const std::string &host) TIME_HILOGE(TIME_MODULE_SERVICE, "Send socket message failed: %{public}s, Host: %{public}s", strerror(errno), host.c_str()); close(sendSocket); - return false; + return RequestTimeResult::SEND_SOCKET_FAIL; } char bufferRx[NTP_PACKAGE_SIZE] = { 0 }; @@ -103,14 +114,14 @@ bool SNTPClient::RequestTime(const std::string &host) TIME_HILOGE(TIME_MODULE_SERVICE, "Receive socket message failed: %{public}s, Host: %{public}s", strerror(errno), host.c_str()); close(sendSocket); - return false; + return RequestTimeResult::RECEIVE_SOCKET_FAIL; } close(sendSocket); if (!ReceivedMessage(bufferRx)) { TIME_HILOGE(TIME_MODULE_SERVICE, "ReceivedMessage failed: Host: %{public}s", host.c_str()); - return false; + return RequestTimeResult::RECEIVE_SOCKET_FAIL; } - return true; + return RequestTimeResult::SUCCESS; } void SNTPClient::SetClockOffset(int clockOffset) diff --git a/test/fuzztest/timeservice_fuzzer/timesntp_fuzzer/timesntp_fuzzer.cpp b/test/fuzztest/timeservice_fuzzer/timesntp_fuzzer/timesntp_fuzzer.cpp index 3ff40169..7f9d113b 100644 --- a/test/fuzztest/timeservice_fuzzer/timesntp_fuzzer/timesntp_fuzzer.cpp +++ b/test/fuzztest/timeservice_fuzzer/timesntp_fuzzer/timesntp_fuzzer.cpp @@ -67,7 +67,7 @@ bool FuzzTimeRequestTime(const uint8_t *data, size_t size) { std::string host(reinterpret_cast(data), size); SNTPClient client; - client.RequestTime(host); + client.RequestTime(host, 0); return true; } } // namespace OHOS diff --git a/test/unittest/service_test/src/time_service_time_test.cpp b/test/unittest/service_test/src/time_service_time_test.cpp index 9be85083..2287edc4 100644 --- a/test/unittest/service_test/src/time_service_time_test.cpp +++ b/test/unittest/service_test/src/time_service_time_test.cpp @@ -508,8 +508,8 @@ HWTEST_F(TimeServiceTimeTest, SntpClient004, TestSize.Level0) HWTEST_F(TimeServiceTimeTest, SntpClient005, TestSize.Level0) { std::shared_ptr ntpClient = std::make_shared(); - auto res = ntpClient -> RequestTime(""); - EXPECT_FALSE(res); + int res = static_cast(ntpClient -> RequestTime("", 0)); + EXPECT_EQ(res, 1); } /** @@ -759,6 +759,41 @@ HWTEST_F(TimeServiceTimeTest, NtpTime002, TestSize.Level0) NtpUpdateTime::GetInstance().autoTimeInfo_.status = status; } +/** +* @tc.name: NtpTime003 +* @tc.desc: test GetNtpTimeInnerSuccess. +* @tc.type: FUNC +*/ +HWTEST_F(TimeServiceTimeTest, NtpTime003, TestSize.Level0) +{ + auto forceRefreshRes = RequestTimeResult::SUCCESS; + auto res = NtpUpdateTime::GetNtpTimeInnerSuccess(forceRefreshRes); + EXPECT_TRUE(res); + forceRefreshRes = RequestTimeResult::GET_ADDRINFO_FAIL; + res = NtpUpdateTime::GetNtpTimeInnerSuccess(forceRefreshRes); + EXPECT_FALSE(res); + forceRefreshRes = RequestTimeResult::CREATE_SOCKET_FAIL; + res = NtpUpdateTime::GetNtpTimeInnerSuccess(forceRefreshRes); + EXPECT_FALSE(res); + forceRefreshRes = RequestTimeResult::SEND_SOCKET_FAIL; + res = NtpUpdateTime::GetNtpTimeInnerSuccess(forceRefreshRes); + EXPECT_FALSE(res); + forceRefreshRes = RequestTimeResult::RECEIVE_SOCKET_FAIL; + res = NtpUpdateTime::GetNtpTimeInnerSuccess(forceRefreshRes); + EXPECT_FALSE(res); +} + +/** +* @tc.name: NtpTime004 +* @tc.desc: test GetNtpTimeInnerRetry. +* @tc.type: FUNC +*/ +HWTEST_F(TimeServiceTimeTest, NtpTime004, TestSize.Level0) +{ + NtpUpdateTime::GetNtpTimeInnerRetry(); + EXPECT_NE(NtpUpdateTime::retryTimerId_, 0); +} + /** * @tc.name: GetNtpTimeMsWithNoPermission001 * @tc.desc: test GetNtpTimeMs with no permission. -- Gitee