From 7883f97c9480f1d5ce2a1a6c01b83a4f605fc3cb Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 12 May 2020 17:31:57 +0400 Subject: [PATCH] Use precise sync of the server unixtime. --- .../SourceFiles/mtproto/session_private.cpp | 58 +++++++++++++++---- .../SourceFiles/mtproto/session_private.h | 6 ++ Telegram/lib_base | 2 +- 3 files changed, 54 insertions(+), 12 deletions(-) diff --git a/Telegram/SourceFiles/mtproto/session_private.cpp b/Telegram/SourceFiles/mtproto/session_private.cpp index 1b61590034..8f7aa7c590 100644 --- a/Telegram/SourceFiles/mtproto/session_private.cpp +++ b/Telegram/SourceFiles/mtproto/session_private.cpp @@ -40,6 +40,7 @@ constexpr auto kTestModeDcIdShift = 10000; constexpr auto kCheckSentRequestsEach = 1 * crl::time(1000); constexpr auto kKeyOldEnoughForDestroy = 60 * crl::time(1000); constexpr auto kSentContainerLives = 600 * crl::time(1000); +constexpr auto kFastRequestDuration = crl::time(500); // If we can't connect for this time we will ask _instance to update config. constexpr auto kRequestConfigTimeout = 8 * crl::time(1000); @@ -57,6 +58,8 @@ constexpr auto kSendStateRequestWaiting = crl::time(1000); // How much time to wait for some more requests, when sending msg acks. constexpr auto kAckSendWaiting = 10 * crl::time(1000); +auto SyncTimeRequestDuration = kFastRequestDuration; + using namespace details; [[nodiscard]] QString LogIdsVector(const QVector &ids) { @@ -1467,8 +1470,12 @@ SessionPrivate::HandleResult SessionPrivate::handleOneReceived( return badTime ? HandleResult::Ignored : HandleResult::Success; } - if (badTime && !requestsFixTimeSalt(ids, serverTime, serverSalt)) { - return HandleResult::Ignored; + if (badTime) { + if (!requestsFixTimeSalt(ids, serverTime, serverSalt)) { + return HandleResult::Ignored; + } + } else { + correctUnixtimeByFastRequest(ids, serverTime); } requestsAcked(ids); } return HandleResult::Success; @@ -1520,7 +1527,8 @@ SessionPrivate::HandleResult SessionPrivate::handleOneReceived( if (serverSalt) { _sessionSalt = serverSalt; } - base::unixtime::update(serverTime, true); + + correctUnixtimeWithBadLocal(serverTime); DEBUG_LOG(("Message Info: unixtime updated, now %1, resending in container...").arg(serverTime)); @@ -1530,7 +1538,7 @@ SessionPrivate::HandleResult SessionPrivate::handleOneReceived( if (serverSalt) { _sessionSalt = serverSalt; } - base::unixtime::update(serverTime, true); + correctUnixtimeWithBadLocal(serverTime); badTime = false; } LOG(("Message Info: bad message notification received, msgId %1, error_code %2").arg(data.vbad_msg_id().v).arg(errorCode)); @@ -1580,7 +1588,7 @@ SessionPrivate::HandleResult SessionPrivate::handleOneReceived( } _sessionSalt = data.vnew_server_salt().v; - base::unixtime::update(serverTime); + correctUnixtimeWithBadLocal(serverTime); if (setState(ConnectedState, ConnectingState)) { resendAll(); @@ -1612,7 +1620,7 @@ SessionPrivate::HandleResult SessionPrivate::handleOneReceived( if (serverSalt) { _sessionSalt = serverSalt; // requestsFixTimeSalt with no lookup } - base::unixtime::update(serverTime, true); + correctUnixtimeWithBadLocal(serverTime); DEBUG_LOG(("Message Info: unixtime updated from mtpc_msgs_state_info, now %1").arg(serverTime)); @@ -1956,20 +1964,48 @@ mtpBuffer SessionPrivate::ungzip(const mtpPrime *from, const mtpPrime *end) cons } bool SessionPrivate::requestsFixTimeSalt(const QVector &ids, int32 serverTime, uint64 serverSalt) { - uint32 idsCount = ids.size(); - - for (uint32 i = 0; i < idsCount; ++i) { - if (wasSent(ids[i].v)) {// found such msg_id in recent acked requests or in recent sent requests + for (const auto &id : ids) { + if (wasSent(id.v)) { + // Found such msg_id in recent acked or in recent sent requests. if (serverSalt) { _sessionSalt = serverSalt; } - base::unixtime::update(serverTime, true); + correctUnixtimeWithBadLocal(serverTime); return true; } } return false; } +void SessionPrivate::correctUnixtimeByFastRequest( + const QVector &ids, + TimeId serverTime) { + const auto now = crl::now(); + + QReadLocker locker(_sessionData->haveSentMutex()); + const auto &haveSent = _sessionData->haveSentMap(); + for (const auto &id : ids) { + const auto i = haveSent.find(id.v); + if (i == haveSent.end()) { + continue; + } + const auto duration = (now - i->second->lastSentTime); + if (duration < 0 || duration > SyncTimeRequestDuration) { + continue; + } + locker.unlock(); + + SyncTimeRequestDuration = duration; + base::unixtime::update(serverTime, true); + return; + } +} + +void SessionPrivate::correctUnixtimeWithBadLocal(TimeId serverTime) { + SyncTimeRequestDuration = kFastRequestDuration; + base::unixtime::update(serverTime, true); +} + void SessionPrivate::requestsAcked(const QVector &ids, bool byResponse) { uint32 idsCount = ids.size(); diff --git a/Telegram/SourceFiles/mtproto/session_private.h b/Telegram/SourceFiles/mtproto/session_private.h index fe39450f27..302067c653 100644 --- a/Telegram/SourceFiles/mtproto/session_private.h +++ b/Telegram/SourceFiles/mtproto/session_private.h @@ -139,6 +139,12 @@ private: // if badTime received - search for ids in sessionData->haveSent and sessionData->wereAcked and sync time/salt, return true if found bool requestsFixTimeSalt(const QVector &ids, int32 serverTime, uint64 serverSalt); + // if we had a confirmed fast request use its unixtime as a correct one. + void correctUnixtimeByFastRequest( + const QVector &ids, + TimeId serverTime); + void correctUnixtimeWithBadLocal(TimeId serverTime); + // remove msgs with such ids from sessionData->haveSent, add to sessionData->wereAcked void requestsAcked(const QVector &ids, bool byResponse = false); diff --git a/Telegram/lib_base b/Telegram/lib_base index 9e01ede666..b376282b65 160000 --- a/Telegram/lib_base +++ b/Telegram/lib_base @@ -1 +1 @@ -Subproject commit 9e01ede6661e2a74697283c7836d4fae433f50ce +Subproject commit b376282b656b13c54cd892e3c2742bb26acf42fe