improved bad_msg_notification handle and local time shifts

This commit is contained in:
John Preston 2014-08-01 15:09:46 +04:00
parent 22e1a7b730
commit 0e031f042d
17 changed files with 381 additions and 95 deletions

View File

@ -95,7 +95,7 @@ namespace App {
return w ? w->mainWidget() : 0;
}
Settings *settings() {
SettingsWidget *settings() {
Window *w(wnd());
return w ? w->settingsWidget() : 0;
}

View File

@ -22,7 +22,7 @@ Copyright (c) 2014 John Preston, https://tdesktop.com
class Application;
class Window;
class MainWidget;
class Settings;
class SettingsWidget;
class Font;
class Color;
class FileUploader;
@ -38,7 +38,7 @@ namespace App {
Application *app();
Window *wnd();
MainWidget *main();
Settings *settings();
SettingsWidget *settings();
FileUploader *uploader();
void showSettings();

View File

@ -230,6 +230,7 @@ bool StorageImage::check() const {
h = data.height();
invalidateSizeCache();
loader->deleteLater();
loader->rpcInvalidate();
loader = 0;
saved = bytes;
@ -256,6 +257,7 @@ void StorageImage::setData(QByteArray &bytes, const QByteArray &format) {
invalidateSizeCache();
if (loader) {
loader->deleteLater();
loader->rpcInvalidate();
loader = 0;
}
this->saved = bytes;
@ -269,6 +271,7 @@ StorageImage::~StorageImage() {
}
if (loader) {
loader->deleteLater();
loader->rpcInvalidate();
loader = 0;
}
}

View File

@ -227,6 +227,7 @@ struct VideoData {
if (l) {
l->cancel();
l->deleteLater();
l->rpcInvalidate();
}
fileName = QString();
modDate = QDateTime();
@ -241,6 +242,7 @@ struct VideoData {
modDate = fileName.isEmpty() ? QDateTime() : QFileInfo(fileName).lastModified();
}
loader->deleteLater();
loader->rpcInvalidate();
loader = 0;
}
@ -328,6 +330,7 @@ struct AudioData {
if (l) {
l->cancel();
l->deleteLater();
l->rpcInvalidate();
}
fileName = QString();
modDate = QDateTime();
@ -342,6 +345,7 @@ struct AudioData {
modDate = fileName.isEmpty() ? QDateTime() : QFileInfo(fileName).lastModified();
}
loader->deleteLater();
loader->rpcInvalidate();
loader = 0;
}
@ -427,6 +431,7 @@ struct DocumentData {
if (l) {
l->cancel();
l->deleteLater();
l->rpcInvalidate();
}
fileName = QString();
modDate = QDateTime();
@ -441,6 +446,7 @@ struct DocumentData {
modDate = fileName.isEmpty() ? QDateTime() : QFileInfo(fileName).lastModified();
}
loader->deleteLater();
loader->rpcInvalidate();
loader = 0;
}

View File

@ -288,6 +288,12 @@ void IntroWidget::keyPressEvent(QKeyEvent *e) {
}
}
void IntroWidget::rpcInvalidate() {
if (phone) phone->rpcInvalidate();
if (code) code->rpcInvalidate();
if (signup) signup->rpcInvalidate();
}
IntroWidget::~IntroWidget() {
delete steps;
delete phone;

View File

@ -57,6 +57,8 @@ public:
void finish(const MTPUser &user, const QImage &photo = QImage());
void rpcInvalidate();
~IntroWidget();
public slots:

View File

@ -756,7 +756,10 @@ void MainWidget::showPeer(const PeerId &peerId, MsgId msgId, bool back, bool for
history.showPeer(peerId, msgId, force);
if (force || !selectingPeer()) {
if (profile) {
if (profile) profile->deleteLater();
if (profile) {
profile->deleteLater();
profile->rpcInvalidate();
}
profile = 0;
profileStack.clear();
if (!history.peer() || !history.peer()->id) {
@ -811,7 +814,10 @@ void MainWidget::showPeerProfile(const PeerData *peer, bool back) {
profileStack.push_back(history.peer());
}
}
if (profile) profile->deleteLater();
if (profile) {
profile->deleteLater();
profile->rpcInvalidate();
}
profile = new ProfileWidget(this, peer);
_topBar.show();
resizeEvent(0);

View File

@ -1034,7 +1034,8 @@ void MTProtoConnectionPrivate::createConn() {
MTProtoConnectionPrivate::MTProtoConnectionPrivate(QThread *thread, MTProtoConnection *owner, MTPSessionData *data, uint32 _dc)
: QObject(0)
, _state(MTProtoConnection::Disconnected)
, dc(_dc)
, _needSessionReset(false)
, dc(_dc)
, _owner(owner)
, conn(0)
, retryTimeout(1)
@ -1137,7 +1138,118 @@ bool MTProtoConnectionPrivate::setState(int32 state, int32 ifState) {
return true;
}
mtpMsgId MTProtoConnectionPrivate::prepareToSend(mtpRequest &request) {
void MTProtoConnectionPrivate::resetSession() { // recreate all msg_id and msg_seqno
_needSessionReset = false;
QWriteLocker locker1(sessionData->haveSentMutex());
QWriteLocker locker2(sessionData->toResendMutex());
QWriteLocker locker3(sessionData->toSendMutex());
QWriteLocker locker4(sessionData->wereAckedMutex());
mtpRequestMap &haveSent(sessionData->haveSentMap());
mtpRequestIdsMap &toResend(sessionData->toResendMap());
mtpPreRequestMap &toSend(sessionData->toSendMap());
mtpRequestIdsMap &wereAcked(sessionData->wereAckedMap());
mtpMsgId newId = msgid();
mtpRequestMap setSeqNumbers;
typedef QMap<mtpMsgId, mtpMsgId> Replaces;
Replaces replaces;
for (mtpRequestMap::const_iterator i = haveSent.cbegin(), e = haveSent.cend(); i != e; ++i) {
if (!mtpRequestData::isSentContainer(i.value())) {
if (!*(mtpMsgId*)(i.value()->constData() + 4)) continue;
mtpMsgId id = i.key();
if (id > newId) {
while (true) {
if (toResend.constFind(newId) == toResend.cend() && wereAcked.constFind(newId) == wereAcked.cend() && haveSent.constFind(newId) == haveSent.cend()) {
break;
}
mtpMsgId m = msgid();
if (m <= newId) break; // wtf
newId = m;
}
MTP_LOG(dc, ("Replacing msgId %1 to %2!").arg(id).arg(newId));
replaces.insert(id, newId);
id = newId;
*(mtpMsgId*)(i.value()->data() + 4) = id;
}
setSeqNumbers.insert(id, i.value());
}
}
for (mtpRequestIdsMap::const_iterator i = toResend.cbegin(), e = toResend.cend(); i != e; ++i) { // collect all non-container requests
mtpPreRequestMap::const_iterator j = toSend.constFind(i.value());
if (j == toSend.cend()) continue;
if (!mtpRequestData::isSentContainer(j.value())) {
if (!*(mtpMsgId*)(j.value()->constData() + 4)) continue;
mtpMsgId id = i.key();
if (id > newId) {
while (true) {
if (toResend.constFind(newId) == toResend.cend() && wereAcked.constFind(newId) == wereAcked.cend() && haveSent.constFind(newId) == haveSent.cend()) {
break;
}
mtpMsgId m = msgid();
if (m <= newId) break; // wtf
newId = m;
}
MTP_LOG(dc, ("Replacing msgId %1 to %2!").arg(id).arg(newId));
replaces.insert(id, newId);
id = newId;
*(mtpMsgId*)(j.value()->data() + 4) = id;
}
setSeqNumbers.insert(id, j.value());
}
}
uint64 session = MTP::nonce<uint64>();
DEBUG_LOG(("MTP Info: creating new session after bad_msg_notification, setting random server_session %1").arg(session));
sessionData->setSession(session);
for (mtpRequestMap::const_iterator i = setSeqNumbers.cbegin(), e = setSeqNumbers.cend(); i != e; ++i) { // generate new seq_numbers
bool wasNeedAck = (*(i.value()->data() + 6) & 1);
*(i.value()->data() + 6) = sessionData->nextRequestSeqNumber(wasNeedAck);
}
if (!replaces.isEmpty()) {
for (Replaces::const_iterator i = replaces.cbegin(), e = replaces.cend(); i != e; ++i) { // replace msgIds keys in all data structs
mtpRequestMap::iterator j = haveSent.find(i.key());
if (j != haveSent.cend()) {
mtpRequest req = j.value();
haveSent.erase(j);
haveSent.insert(i.value(), req);
}
mtpRequestIdsMap::iterator k = toResend.find(i.key());
if (k != toResend.cend()) {
mtpRequestId req = k.value();
toResend.erase(k);
toResend.insert(i.value(), req);
}
k = wereAcked.find(i.key());
if (k != wereAcked.cend()) {
mtpRequestId req = k.value();
wereAcked.erase(k);
wereAcked.insert(i.value(), req);
}
}
for (mtpRequestMap::const_iterator i = haveSent.cbegin(), e = haveSent.cend(); i != e; ++i) { // replace msgIds in saved containers
if (mtpRequestData::isSentContainer(i.value())) {
mtpMsgId *ids = (mtpMsgId *)(i.value()->data() + 8);
for (uint32 j = 0, l = (i.value()->size() - 8) >> 1; j < l; ++j) {
Replaces::const_iterator k = replaces.constFind(ids[j]);
if (k != replaces.cend()) {
ids[j] = k.value();
}
}
}
}
}
}
mtpMsgId MTProtoConnectionPrivate::prepareToSend(mtpRequest &request, mtpMsgId currentLastId) {
if (request->size() < 9) return 0;
mtpMsgId msgId = *(mtpMsgId*)(request->constData() + 4);
if (msgId) { // resending this request
@ -1148,12 +1260,75 @@ mtpMsgId MTProtoConnectionPrivate::prepareToSend(mtpRequest &request) {
toResend.erase(i);
}
} else {
msgId = *(mtpMsgId*)(request->data() + 4) = msgid();
msgId = *(mtpMsgId*)(request->data() + 4) = currentLastId;
*(request->data() + 6) = sessionData->nextRequestSeqNumber(mtpRequestData::needAck(request));
}
return msgId;
}
mtpMsgId MTProtoConnectionPrivate::replaceMsgId(mtpRequest &request, mtpMsgId newId) {
if (request->size() < 9) return 0;
mtpMsgId oldMsgId = *(mtpMsgId*)(request->constData() + 4);
if (oldMsgId != newId) {
if (oldMsgId) {
QWriteLocker locker(sessionData->toResendMutex());
// haveSentMutex() and wereAckedMutex() were locked in tryToSend()
mtpRequestIdsMap &toResend(sessionData->toResendMap());
mtpRequestIdsMap &wereAcked(sessionData->wereAckedMap());
mtpRequestMap &haveSent(sessionData->haveSentMap());
while (true) {
if (toResend.constFind(newId) == toResend.cend() && wereAcked.constFind(newId) == wereAcked.cend() && haveSent.constFind(newId) == haveSent.cend()) {
break;
}
mtpMsgId m = msgid();
if (m <= newId) break; // wtf
newId = m;
}
mtpRequestIdsMap::iterator i = toResend.find(oldMsgId);
if (i != toResend.cend()) {
mtpRequestId req = i.value();
toResend.erase(i);
toResend.insert(newId, req);
}
mtpRequestIdsMap::iterator j = wereAcked.find(oldMsgId);
if (j != wereAcked.cend()) {
mtpRequestId req = j.value();
wereAcked.erase(j);
wereAcked.insert(newId, req);
}
mtpRequestMap::iterator k = haveSent.find(oldMsgId);
if (k != haveSent.cend()) {
mtpRequest req = k.value();
haveSent.erase(k);
haveSent.insert(newId, req);
}
for (k = haveSent.begin(); k != haveSent.cend(); ++k) {
mtpRequest req(k.value());
if (mtpRequestData::isSentContainer(req)) {
mtpMsgId *ids = (mtpMsgId *)(req->data() + 8);
for (uint32 i = 0, l = (req->size() - 8) >> 1; i < l; ++i) {
if (ids[i] == oldMsgId) {
ids[i] = newId;
}
}
}
}
} else {
*(request->data() + 6) = sessionData->nextRequestSeqNumber(mtpRequestData::needAck(request));
}
*(mtpMsgId*)(request->data() + 4) = newId;
}
return newId;
}
void MTProtoConnectionPrivate::tryToSend() {
if (!conn) return;
@ -1211,7 +1386,7 @@ void MTProtoConnectionPrivate::tryToSend() {
locker1.unlock();
}
mtpMsgId msgId = prepareToSend(toSendRequest);
mtpMsgId msgId = prepareToSend(toSendRequest, msgid());
if (havePrepend) pingMsgId = msgId;
if (toSendRequest->requestId) {
@ -1237,10 +1412,12 @@ void MTProtoConnectionPrivate::tryToSend() {
toSendRequest->push_back(mtpc_msg_container);
toSendRequest->push_back(toSendCount);
QWriteLocker locker2(sessionData->haveSentMutex());
mtpMsgId bigMsgId = msgid(); // check for a valid container
QWriteLocker locker2(sessionData->haveSentMutex()); // the fact of this lock is used in replaceMsgId()
mtpRequestMap &haveSent(sessionData->haveSentMap());
QWriteLocker locker3(sessionData->wereAckedMutex());
QWriteLocker locker3(sessionData->wereAckedMutex()); // the fact of this lock is used in replaceMsgId()
mtpRequestIdsMap &wereAcked(sessionData->wereAckedMap());
mtpRequest haveSentIdsWrap(mtpRequestData::prepare(idsWrapSize)); // prepare "request-like" wrap for msgId vector
@ -1249,7 +1426,9 @@ void MTProtoConnectionPrivate::tryToSend() {
mtpMsgId *haveSentArr = (mtpMsgId*)(haveSentIdsWrap->data() + 8);
if (havePrepend) {
mtpMsgId msgId = prepareToSend(prepend);
mtpMsgId msgId = prepareToSend(prepend, bigMsgId);
if (msgId > bigMsgId) msgId = replaceMsgId(prepend, bigMsgId);
if (msgId >= bigMsgId) bigMsgId = msgid();
*(haveSentArr++) = msgId;
if (havePrepend) pingMsgId = msgId;
@ -1261,8 +1440,10 @@ void MTProtoConnectionPrivate::tryToSend() {
}
for (mtpPreRequestMap::iterator i = toSend.begin(), e = toSend.end(); i != e; ++i) {
mtpRequest &req(i.value());
mtpMsgId msgId = prepareToSend(req);
*(haveSentArr++) = msgId;
mtpMsgId msgId = prepareToSend(req, bigMsgId);
if (msgId > bigMsgId) msgId = replaceMsgId(req, bigMsgId);
if (msgId >= bigMsgId) bigMsgId = msgid();
*(haveSentArr++) = msgId;
if (req->requestId) {
if (mtpRequestData::needAck(req)) {
@ -1279,7 +1460,7 @@ void MTProtoConnectionPrivate::tryToSend() {
memcpy(toSendRequest->data() + from, req->constData() + 4, len * sizeof(mtpPrime));
}
mtpMsgId contMsgId = prepareToSend(toSendRequest);
mtpMsgId contMsgId = prepareToSend(toSendRequest, bigMsgId);
*(mtpMsgId*)(haveSentIdsWrap->data() + 4) = contMsgId;
(*haveSentIdsWrap)[6] = 0; // for container, msDate = 0, seqNo = 0
haveSent.insert(contMsgId, haveSentIdsWrap);
@ -1372,6 +1553,9 @@ void MTProtoConnectionPrivate::restart(bool maybeBadKey) {
}
doDisconnect();
if (_needSessionReset) {
resetSession();
}
restarted = true;
if (retryTimer.isActive()) return;
@ -1564,7 +1748,9 @@ void MTProtoConnectionPrivate::handleReceived() {
int32 res = 1; // if no need to handle, then succeed
end = data + 8 + (msgLen >> 2);
const mtpPrime *sfrom(data + 4);
MTP_LOG(dc, ("Recv: ") + mtpTextSerialize(sfrom, end, mtpc_core_message));
if (cDebug()) {
MTP_LOG(dc, ("Recv: ") + mtpTextSerialize(sfrom, end, mtpc_core_message));
}
bool needToHandle = false;
{
@ -1606,6 +1792,7 @@ void MTProtoConnectionPrivate::handleReceived() {
}
if (res < 0) {
_needSessionReset = (res < -1);
return restart();
}
@ -1714,29 +1901,71 @@ int32 MTProtoConnectionPrivate::handleOneReceived(const mtpPrime *from, const mt
const MTPDbad_msg_notification &data(msg.c_bad_msg_notification());
LOG(("Message Info: bad message notification received (error_code %3) for msg_id = %1, seq_no = %2").arg(data.vbad_msg_id.v).arg(data.vbad_msg_seqno.v).arg(data.verror_code.v));
bool needResend = (data.verror_code.v == 16 || data.verror_code.v == 17); // bad msg_id
mtpMsgId resendId = data.vbad_msg_id.v;
if (!wasSent(resendId)) {
DEBUG_LOG(("Message Error: such message was not sent recently %1").arg(resendId));
return (badTime ? 0 : 1);
}
int32 errorCode = data.verror_code.v;
if (errorCode == 16 || errorCode == 17 || errorCode == 32 || errorCode == 33 || errorCode == 64) { // can handle
bool needResend = (errorCode == 16 || errorCode == 17); // bad msg_id
if (errorCode == 64) { // bad container!
needResend = true;
if (cDebug()) {
mtpRequest request;
{
QWriteLocker locker(sessionData->haveSentMutex());
mtpRequestMap &haveSent(sessionData->haveSentMap());
if (needResend) { // bad msg_id
if (serverSalt) sessionData->setSalt(serverSalt);
unixtimeSet(serverTime, true);
mtpRequestMap::iterator i = haveSent.find(msgId);
if (i == haveSent.end()) {
LOG(("Message Error: Container not found!"));
}
DEBUG_LOG(("Message Info: unixtime updated, now %1, resending in container..").arg(serverTime));
resend(resendId, 0, true);
} else {
if (badTime) {
if (serverSalt) sessionData->setSalt(serverSalt);
unixtimeSet(serverTime);
badTime = false;
request = i.value();
}
if (request) {
if (mtpRequestData::isSentContainer(request)) {
QStringList lst;
const mtpMsgId *ids = (const mtpMsgId *)(request->constData() + 8);
for (uint32 i = 0, l = (request->size() - 8) >> 1; i < l; ++i) {
lst.push_back(QString::number(ids[i]));
}
LOG(("Message Info: bad container received! messages: %1").arg(lst.join(',')));
} else {
LOG(("Message Error: bad container received, but request is not a container!"));
}
}
}
}
LOG(("Message Error: bad message notification received, msgId %1, error_code %2").arg(data.vbad_msg_id.v).arg(data.verror_code.v));
return -1;
mtpMsgId resendId = data.vbad_msg_id.v;
if (!wasSent(resendId)) {
DEBUG_LOG(("Message Error: such message was not sent recently %1").arg(resendId));
return (badTime ? 0 : 1);
}
if (needResend) { // bad msg_id
if (serverSalt) sessionData->setSalt(serverSalt);
unixtimeSet(serverTime, true);
DEBUG_LOG(("Message Info: unixtime updated, now %1, resending in container..").arg(serverTime));
resend(resendId, 0, true);
} else { // must create new session, because msg_id and msg_seqno are inconsistent
if (badTime) {
if (serverSalt) sessionData->setSalt(serverSalt);
unixtimeSet(serverTime);
badTime = false;
}
LOG(("Message Info: bad message notification received, msgId %1, error_code %2").arg(data.vbad_msg_id.v).arg(errorCode));
return -2;
}
} else { // fatal (except 48, but it must not get here)
mtpMsgId resendId = data.vbad_msg_id.v;
mtpRequestId requestId = wasSent(resendId);
if (requestId) {
LOG(("Message Error: bad message notification received, msgId %1, error_code %2, fatal: clearing callbacks").arg(data.vbad_msg_id.v).arg(errorCode));
_mtp_internal::clearCallbacksDelayed(RPCCallbackClears(1, RPCCallbackClear(requestId, -errorCode)));
} else {
DEBUG_LOG(("Message Error: such message was not sent recently %1").arg(resendId));
}
return (badTime ? 0 : 1);
}
} return 1;
@ -1855,8 +2084,13 @@ int32 MTProtoConnectionPrivate::handleOneReceived(const mtpPrime *from, const mt
}
try {
const mtpPrime *rFrom = requestBuffer->constData() + 8, *rEnd = requestBuffer->constData() + requestBuffer->size();
MTPMsgsStateReq request(rFrom, rEnd);
handleMsgsStates(request.c_msgs_state_req().vmsg_ids.c_vector().v, states, toAck);
if (*rFrom == mtpc_msgs_state_req) {
MTPMsgsStateReq request(rFrom, rEnd);
handleMsgsStates(request.c_msgs_state_req().vmsg_ids.c_vector().v, states, toAck);
} else {
MTPMsgResendReq request(rFrom, rEnd);
handleMsgsStates(request.c_msg_resend_req().vmsg_ids.c_vector().v, states, toAck);
}
} catch(Exception &e) {
LOG(("Message Error: could not parse sent msgs_state_req"));
throw;
@ -2280,7 +2514,6 @@ mtpRequestId MTProtoConnectionPrivate::resend(mtpMsgId msgId, uint64 msCanWait,
return sessionData->owner()->resend(msgId, msCanWait, forceContainer, sendMsgStateInfo);
}
void MTProtoConnectionPrivate::onConnected() {
disconnect(conn, SIGNAL(connected()), this, SLOT(onConnected()));
if (!conn->isConnected()) {
@ -2874,7 +3107,9 @@ bool MTProtoConnectionPrivate::sendRequest(mtpRequest &request, bool needAnyResp
memcpy(request->data() + 2, &session, 2 * sizeof(mtpPrime));
const mtpPrime *from = request->constData() + 4;
MTP_LOG(dc, ("Send: ") + mtpTextSerialize(from, from + messageSize, mtpc_core_message));
if (cDebug()) {
MTP_LOG(dc, ("Send: ") + mtpTextSerialize(from, from + messageSize, mtpc_core_message));
}
uchar encryptedSHA[20];
MTPint128 &msgKey(*(MTPint128*)(encryptedSHA + 4));

View File

@ -332,7 +332,8 @@ private:
void createConn();
mtpMsgId prepareToSend(mtpRequest &request);
mtpMsgId prepareToSend(mtpRequest &request, mtpMsgId currentLastId);
mtpMsgId replaceMsgId(mtpRequest &request, mtpMsgId newId);
bool sendRequest(mtpRequest &request, bool needAnyResponse);
mtpRequestId wasSent(mtpMsgId msgId) const;
@ -347,6 +348,9 @@ private:
mutable QReadWriteLock stateMutex;
int32 _state;
bool _needSessionReset;
void resetSession();
uint32 dc;
MTProtoConnection *_owner;
MTPabstractConnection *conn;

View File

@ -19,17 +19,17 @@ Copyright (c) 2014 John Preston, https://tdesktop.com
#include "mtproto/mtpRPC.h"
RPCOwnedDoneHandler::RPCOwnedDoneHandler(RPCSender *owner) : _owner(owner) {
_owner->regHandler(this);
_owner->_rpcRegHandler(this);
}
RPCOwnedDoneHandler::~RPCOwnedDoneHandler() {
if (_owner) _owner->unregHandler(this);
if (_owner) _owner->_rpcUnregHandler(this);
}
RPCOwnedFailHandler::RPCOwnedFailHandler(RPCSender *owner) : _owner(owner) {
_owner->regHandler(this);
_owner->_rpcRegHandler(this);
}
RPCOwnedFailHandler::~RPCOwnedFailHandler() {
if (_owner) _owner->unregHandler(this);
if (_owner) _owner->_rpcUnregHandler(this);
}

View File

@ -654,9 +654,28 @@ private:
class RPCSender {
typedef QSet<RPCOwnedDoneHandler*> DoneHandlers;
DoneHandlers doneHandlers;
DoneHandlers _rpcDoneHandlers;
typedef QSet<RPCOwnedFailHandler*> FailHandlers;
FailHandlers failHandlers;
FailHandlers _rpcFailHandlers;
void _rpcRegHandler(RPCOwnedDoneHandler *handler) {
_rpcDoneHandlers.insert(handler);
}
void _rpcUnregHandler(RPCOwnedDoneHandler *handler) {
_rpcDoneHandlers.remove(handler);
}
void _rpcRegHandler(RPCOwnedFailHandler *handler) {
_rpcFailHandlers.insert(handler);
}
void _rpcUnregHandler(RPCOwnedFailHandler *handler) {
_rpcFailHandlers.remove(handler);
}
friend class RPCOwnedDoneHandler;
friend class RPCOwnedFailHandler;
public:
@ -760,29 +779,19 @@ public:
return RPCFailHandlerPtr(new RPCBindedFailHandlerOwnedNo<T, TReceiver>(b, static_cast<TReceiver*>(this), onFail));
}
void regHandler(RPCOwnedDoneHandler *handler) {
doneHandlers.insert(handler);
}
void unregHandler(RPCOwnedDoneHandler *handler) {
doneHandlers.remove(handler);
}
void regHandler(RPCOwnedFailHandler *handler) {
failHandlers.insert(handler);
}
void unregHandler(RPCOwnedFailHandler *handler) {
failHandlers.remove(handler);
void rpcInvalidate() {
for (DoneHandlers::iterator i = _rpcDoneHandlers.begin(), e = _rpcDoneHandlers.end(); i != e; ++i) {
(*i)->invalidate();
}
_rpcDoneHandlers.clear();
for (FailHandlers::iterator i = _rpcFailHandlers.begin(), e = _rpcFailHandlers.end(); i != e; ++i) {
(*i)->invalidate();
}
_rpcFailHandlers.clear();
}
~RPCSender() {
for (DoneHandlers::iterator i = doneHandlers.begin(), e = doneHandlers.end(); i != e; ++i) {
(*i)->invalidate();
}
for (FailHandlers::iterator i = failHandlers.begin(), e = failHandlers.end(); i != e; ++i) {
(*i)->invalidate();
}
rpcInvalidate();
}
};

View File

@ -61,8 +61,7 @@ public:
void setKey(const mtpAuthKeyPtr &key) {
if (authKey != key) {
uint64 session;
memset_rand(&session, sizeof(uint64));
memsetrnd(session);
authKey = key;
DEBUG_LOG(("MTP Info: new auth key set in SessionData, id %1, setting random server_session %2").arg(key ? key->keyId() : 0).arg(session));

View File

@ -95,7 +95,7 @@ bool scaleIs(DBIScale scale) {
return cRealScale() == scale || (cRealScale() == dbisAuto && cScreenScale() == scale);
}
SettingsInner::SettingsInner(Settings *parent) : QWidget(parent),
SettingsInner::SettingsInner(SettingsWidget *parent) : QWidget(parent),
_self(App::self()),
// profile
@ -1126,7 +1126,7 @@ void SettingsInner::onPhotoUpdateDone(PeerId peer) {
update();
}
Settings::Settings(Window *parent) : QWidget(parent),
SettingsWidget::SettingsWidget(Window *parent) : QWidget(parent),
_scroll(this, st::setScroll), _inner(this), _close(this, st::setClose) {
_scroll.setWidget(&_inner);
@ -1138,11 +1138,11 @@ Settings::Settings(Window *parent) : QWidget(parent),
showAll();
}
void Settings::onParentResize(const QSize &newSize) {
void SettingsWidget::onParentResize(const QSize &newSize) {
resize(newSize);
}
void Settings::animShow(const QPixmap &bgAnimCache, bool back) {
void SettingsWidget::animShow(const QPixmap &bgAnimCache, bool back) {
_bgAnimCache = bgAnimCache;
anim::stop(this);
@ -1159,7 +1159,7 @@ void Settings::animShow(const QPixmap &bgAnimCache, bool back) {
show();
}
bool Settings::animStep(float64 ms) {
bool SettingsWidget::animStep(float64 ms) {
float64 fullDuration = st::introSlideDelta + st::introSlideDuration, dt = ms / fullDuration;
float64 dt1 = (ms > st::introSlideDuration) ? 1 : (ms / st::introSlideDuration), dt2 = (ms > st::introSlideDelta) ? (ms - st::introSlideDelta) / (st::introSlideDuration) : 0;
bool res = true;
@ -1184,7 +1184,7 @@ bool Settings::animStep(float64 ms) {
return res;
}
void Settings::paintEvent(QPaintEvent *e) {
void SettingsWidget::paintEvent(QPaintEvent *e) {
QRect r(e->rect());
bool trivial = (rect() == r);
@ -1202,32 +1202,32 @@ void Settings::paintEvent(QPaintEvent *e) {
}
}
void Settings::showAll() {
void SettingsWidget::showAll() {
_scroll.show();
_inner.show();
_inner.showAll();
_close.show();
}
void Settings::hideAll() {
void SettingsWidget::hideAll() {
_scroll.hide();
_close.hide();
}
void Settings::resizeEvent(QResizeEvent *e) {
void SettingsWidget::resizeEvent(QResizeEvent *e) {
_scroll.resize(size());
_inner.updateSize(width());
_close.move(st::setClosePos.x(), st::setClosePos.y());
}
void Settings::dragEnterEvent(QDragEnterEvent *e) {
void SettingsWidget::dragEnterEvent(QDragEnterEvent *e) {
}
void Settings::dropEvent(QDropEvent *e) {
void SettingsWidget::dropEvent(QDropEvent *e) {
}
bool Settings::getPhotoCoords(PhotoData *photo, int32 &x, int32 &y, int32 &w) const {
bool SettingsWidget::getPhotoCoords(PhotoData *photo, int32 &x, int32 &y, int32 &w) const {
if (_inner.getPhotoCoords(photo, x, y, w)) {
x += _inner.x();
y += _inner.y();
@ -1236,14 +1236,18 @@ bool Settings::getPhotoCoords(PhotoData *photo, int32 &x, int32 &y, int32 &w) co
return false;
}
void Settings::updateOnlineDisplay() {
void SettingsWidget::updateOnlineDisplay() {
_inner.updateOnlineDisplay();
}
void Settings::updateConnectionType() {
void SettingsWidget::updateConnectionType() {
_inner.updateConnectionType();
}
Settings::~Settings() {
void SettingsWidget::rpcInvalidate() {
_inner.rpcInvalidate();
}
SettingsWidget::~SettingsWidget() {
if (App::wnd()) App::wnd()->noSettings(this);
}

View File

@ -59,7 +59,7 @@ class SettingsInner : public QWidget, public RPCSender, public Animated {
public:
SettingsInner(Settings *parent);
SettingsInner(SettingsWidget *parent);
void paintEvent(QPaintEvent *e);
void resizeEvent(QResizeEvent *e);
@ -218,12 +218,12 @@ private:
};
class Settings : public QWidget, public Animated {
class SettingsWidget : public QWidget, public Animated {
Q_OBJECT
public:
Settings(Window *parent);
SettingsWidget(Window *parent);
void paintEvent(QPaintEvent *e);
void resizeEvent(QResizeEvent *e);
@ -238,7 +238,9 @@ public:
void updateOnlineDisplay();
void updateConnectionType();
~Settings();
void rpcInvalidate();
~SettingsWidget();
public slots:

View File

@ -129,6 +129,11 @@ inline char *hashMd5Hex(const void *data, uint32 len, void *dest) { // dest = pt
void memset_rand(void *data, uint32 len);
template <typename T>
inline void memsetrnd(T &value) {
memset_rand(&value, sizeof(value));
}
class ReadLockerAttempt {
public:

View File

@ -395,18 +395,21 @@ void Window::clearWidgets() {
anim::stop(settings);
settings->hide();
settings->deleteLater();
settings->rpcInvalidate();
settings = 0;
}
if (main) {
anim::stop(main);
main->hide();
main->deleteLater();
main->rpcInvalidate();
main = 0;
}
if (intro) {
anim::stop(intro);
intro->hide();
intro->deleteLater();
intro->rpcInvalidate();
intro = 0;
}
}
@ -463,7 +466,7 @@ void Window::showSettings() {
anim::stop(main);
main->hide();
}
settings = new Settings(this);
settings = new SettingsWidget(this);
settings->animShow(bg);
fixOrder();
@ -476,6 +479,7 @@ void Window::hideSettings(bool fast) {
anim::stop(settings);
settings->hide();
settings->deleteLater();
settings->rpcInvalidate();
settings = 0;
if (intro) {
intro->show();
@ -488,6 +492,7 @@ void Window::hideSettings(bool fast) {
anim::stop(settings);
settings->hide();
settings->deleteLater();
settings->rpcInvalidate();
settings = 0;
if (intro) {
intro->animShow(bg, true);
@ -533,7 +538,7 @@ MainWidget *Window::mainWidget() {
return main;
}
Settings *Window::settingsWidget() {
SettingsWidget *Window::settingsWidget() {
return settings;
}
@ -798,7 +803,7 @@ void Window::noIntro(IntroWidget *was) {
}
}
void Window::noSettings(Settings *was) {
void Window::noSettings(SettingsWidget *was) {
if (was == settings) {
settings = 0;
}

View File

@ -25,7 +25,7 @@ Copyright (c) 2014 John Preston, https://tdesktop.com
class TitleWidget;
class IntroWidget;
class MainWidget;
class Settings;
class SettingsWidget;
class LayerWidget;
class BackgroundWidget;
class LayeredWidget;
@ -165,7 +165,7 @@ public:
IntroWidget *introWidget();
MainWidget *mainWidget();
Settings *settingsWidget();
SettingsWidget *settingsWidget();
void showConnecting(const QString &text, const QString &reconnect = QString());
void hideConnecting();
@ -191,7 +191,7 @@ public:
void activate();
void noIntro(IntroWidget *was);
void noSettings(Settings *was);
void noSettings(SettingsWidget *was);
void noMain(MainWidget *was);
void noLayer(LayerWidget *was);
void noBox(BackgroundWidget *was);
@ -259,7 +259,7 @@ private:
TitleWidget *title;
IntroWidget *intro;
MainWidget *main;
Settings *settings;
SettingsWidget *settings;
LayerWidget *layer;
BackgroundWidget *layerBG;