2
0
mirror of https://github.com/telegramdesktop/tdesktop synced 2025-09-05 00:46:08 +00:00

Fix resending requests after new session.

This commit is contained in:
John Preston
2019-11-19 19:14:50 +03:00
parent e7e1c9aa5a
commit e6d3b2b098
5 changed files with 276 additions and 345 deletions

View File

@@ -26,10 +26,6 @@ constexpr auto kCheckResendTimeout = crl::time(10000);
// when resending request or checking its state.
constexpr auto kCheckResendWaiting = crl::time(1000);
// How much ints should message contain for us not to resend,
// but instead to check its state.
constexpr auto kResendThreshold = 1;
// Container lives 10 minutes in haveSent map.
constexpr auto kContainerLives = 600;
@@ -76,15 +72,51 @@ void SessionData::withSession(Callback &&callback) {
}
}
void SessionData::setCurrentKeyId(uint64 keyId) {
bool SessionData::setCurrentKeyId(uint64 keyId) {
QWriteLocker locker(&_lock);
if (_keyId == keyId) {
return;
return false;
}
_keyId = keyId;
_sessionId = openssl::RandomValue<uint64>();
DEBUG_LOG(("MTP Info: auth key set in SessionData, id %1").arg(keyId));
changeSessionIdLocked();
return true;
}
void SessionData::changeSessionId() {
QWriteLocker locker(&_lock);
changeSessionIdLocked();
}
void SessionData::changeSessionIdLocked() {
auto sessionId = _sessionId;
do {
sessionId = openssl::RandomValue<uint64>();
} while (_sessionId == sessionId);
DEBUG_LOG(("MTP Info: setting server_session: %1").arg(sessionId));
_sessionId = sessionId;
_messagesSent = 0;
DEBUG_LOG(("MTP Info: new auth key set in SessionData, id %1, setting random server_session %2").arg(_keyId).arg(_sessionId));
_sessionMarkedAsStarted = false;
}
uint32 SessionData::nextRequestSeqNumber(bool needAck) {
QWriteLocker locker(&_lock);
auto result = _messagesSent;
_messagesSent += (needAck ? 1 : 0);
return result * 2 + (needAck ? 1 : 0);
}
bool SessionData::markSessionAsStarted() {
QWriteLocker locker(&_lock);
if (_sessionMarkedAsStarted) {
return false;
}
_sessionMarkedAsStarted = true;
return true;
}
void SessionData::setKeyForCheck(const AuthKeyPtr &key) {
@@ -166,12 +198,6 @@ void SessionData::queueConnectionStateChange(int newState) {
});
}
void SessionData::queueResendAll() {
withSession([](not_null<Session*> session) {
session->resendAll();
});
}
void SessionData::queueResetDone() {
withSession([](not_null<Session*> session) {
session->resetDone();
@@ -190,24 +216,21 @@ void SessionData::queueSendMsgsStateInfo(quint64 msgId, QByteArray data) {
});
}
void SessionData::queueResend(
void SessionData::resend(
mtpMsgId msgId,
crl::time msCanWait,
bool forceContainer) {
withSession([=](not_null<Session*> session) {
session->resend(msgId, msCanWait, forceContainer);
});
QMutexLocker lock(&_ownerMutex);
if (_owner) {
_owner->resend(msgId, msCanWait, forceContainer);
}
}
void SessionData::queueResendMany(
QVector<mtpMsgId> msgIds,
crl::time msCanWait,
bool forceContainer) {
withSession([=](not_null<Session*> session) {
for (const auto msgId : msgIds) {
session->resend(msgId, msCanWait, forceContainer);
}
});
void SessionData::resendAll() {
QMutexLocker lock(&_ownerMutex);
if (_owner) {
_owner->resendAll();
}
}
bool SessionData::connectionInited() const {
@@ -437,7 +460,6 @@ bool Session::sharedDc() const {
}
void Session::checkRequestsByTimer() {
QVector<mtpMsgId> resendingIds;
QVector<mtpMsgId> removingIds; // remove very old (10 minutes) containers and resend requests
QVector<mtpMsgId> stateRequestIds;
@@ -450,14 +472,9 @@ void Session::checkRequestsByTimer() {
auto &req = i.value();
if (req->msDate > 0) {
if (req->msDate + kCheckResendTimeout < ms) { // need to resend or check state
if (req.messageSize() < kResendThreshold) { // resend
resendingIds.reserve(haveSentCount);
resendingIds.push_back(i.key());
} else {
req->msDate = ms;
stateRequestIds.reserve(haveSentCount);
stateRequestIds.push_back(i.key());
}
req->msDate = ms;
stateRequestIds.reserve(haveSentCount);
stateRequestIds.push_back(i.key());
}
} else if (base::unixtime::now()
> int32(i.key() >> 32) + kContainerLives) {
@@ -477,12 +494,6 @@ void Session::checkRequestsByTimer() {
}
sendAnything(kCheckResendWaiting);
}
if (!resendingIds.isEmpty()) {
for (uint32 i = 0, l = resendingIds.size(); i < l; ++i) {
DEBUG_LOG(("MTP Info: resending request %1").arg(resendingIds[i]));
resend(resendingIds[i], kCheckResendWaiting);
}
}
if (!removingIds.isEmpty()) {
auto clearCallbacks = std::vector<RPCCallbackClear>();
{
@@ -586,40 +597,35 @@ QString Session::transport() const {
return _connection ? _connection->transport() : QString();
}
mtpRequestId Session::resend(
void Session::resend(
mtpMsgId msgId,
crl::time msCanWait,
bool forceContainer) {
SecureRequest request;
{
QWriteLocker locker(_data->haveSentMutex());
auto &haveSent = _data->haveSentMap();
auto lock = QWriteLocker(_data->haveSentMutex());
auto &haveSent = _data->haveSentMap();
auto i = haveSent.find(msgId);
if (i == haveSent.end()) {
return 0;
}
request = i.value();
haveSent.erase(i);
auto i = haveSent.find(msgId);
if (i == haveSent.end()) {
return;
}
if (request.isSentContainer()) { // for container just resend all messages we can
auto request = i.value();
haveSent.erase(i);
lock.unlock();
// For container just resend all messages we can.
if (request.isSentContainer()) {
DEBUG_LOG(("Message Info: resending container from haveSent, msgId %1").arg(msgId));
const mtpMsgId *ids = (const mtpMsgId *)(request->constData() + 8);
for (uint32 i = 0, l = (request->size() - 8) >> 1; i < l; ++i) {
resend(ids[i], 10, true);
}
return 0xFFFFFFFF;
} else if (!request.isStateRequest()) {
request->msDate = forceContainer ? 0 : crl::now();
sendPrepared(request, msCanWait, false);
{
QWriteLocker locker(_data->toResendMutex());
_data->toResendMap().insert(msgId, request->requestId);
}
return request->requestId;
} else {
return 0;
sendPrepared(request, msCanWait, false);
}
}
@@ -636,8 +642,11 @@ void Session::resendAll() {
}
}
for (uint32 i = 0, l = toResend.size(); i < l; ++i) {
resend(toResend[i], 10, true);
resend(toResend[i], -1, true);
}
InvokeQueued(this, [=] {
sendAnything();
});
}
void Session::sendPrepared(
@@ -657,8 +666,11 @@ void Session::sendPrepared(
}
DEBUG_LOG(("MTP Info: added, requestId %1").arg(request->requestId));
sendAnything(msCanWait);
if (msCanWait >= 0) {
InvokeQueued(this, [=] {
sendAnything(msCanWait);
});
}
}
bool Session::acquireKeyCreation() {