added lock for dcOptions, emojibox large emoji display, session management improved, new emoji dropdown started

This commit is contained in:
John Preston 2015-05-14 19:50:04 +03:00
parent d92356ce28
commit 136fd5c8e1
18 changed files with 378 additions and 244 deletions

View File

@ -1362,7 +1362,7 @@ btnInfoClose: flatButton(aboutCloseButton) {
emojiTextFont: font(16px); emojiTextFont: font(16px);
emojiReplaceWidth: 56px; emojiReplaceWidth: 56px;
emojiReplaceHeight: 56px; emojiReplaceHeight: 56px;
emojiReplaceInnerHeight: 38px; emojiReplaceInnerHeight: 42px;
connectingBG: #fffe; connectingBG: #fffe;
connectingColor: #777; connectingColor: #777;
@ -1459,40 +1459,37 @@ emojiScroll: flatScroll(scrollDef) {
topsh: 0px; topsh: 0px;
bottomsh: 0px; bottomsh: 0px;
} }
emojiRecent: sprite(6px, 197px, 20px, 20px); emojiRecent: sprite(0px, 196px, 21px, 22px);
emojiRecentOver: sprite(290px, 221px, 20px, 20px); emojiRecentOver: sprite(287px, 220px, 21px, 22px);
emojiRecentActive: sprite(290px, 242px, 20px, 20px); emojiRecentActive: sprite(287px, 242px, 21px, 22px);
emojiPeople: sprite(27px, 197px, 20px, 20px); emojiPeople: sprite(21px, 196px, 21px, 22px);
emojiPeopleOver: sprite(311px, 221px, 20px, 20px); emojiPeopleOver: sprite(298px, 220px, 21px, 22px);
emojiPeopleActive: sprite(311px, 242px, 20px, 20px); emojiPeopleActive: sprite(298px, 242px, 21px, 22px);
emojiNature: sprite(48px, 197px, 20px, 20px); emojiNature: sprite(42px, 196px, 21px, 22px);
emojiNatureOver: sprite(245px, 266px, 20px, 20px); emojiNatureOver: sprite(245px, 264px, 21px, 22px);
emojiNatureActive: sprite(245px, 287px, 20px, 20px); emojiNatureActive: sprite(245px, 286px, 21px, 22px);
emojiFood: sprite(69px, 197px, 20px, 20px); emojiFood: sprite(63px, 196px, 21px, 22px);
emojiFoodOver: sprite(266px, 266px, 20px, 20px); emojiFoodOver: sprite(266px, 264px, 21px, 22px);
emojiFoodActive: sprite(266px, 287px, 20px, 20px); emojiFoodActive: sprite(266px, 286px, 21px, 22px);
emojiCelebration: sprite(90px, 197px, 20px, 20px); emojiCelebration: sprite(84px, 196px, 21px, 22px);
emojiCelebrationOver: sprite(290px, 266px, 20px, 20px); emojiCelebrationOver: sprite(287px, 264px, 21px, 22px);
emojiCelebrationActive: sprite(290px, 287px, 20px, 20px); emojiCelebrationActive: sprite(287px, 286px, 21px, 22px);
emojiActivity: sprite(111px, 197px, 20px, 20px); emojiActivity: sprite(105px, 196px, 21px, 22px);
emojiActivityOver: sprite(311px, 266px, 20px, 20px); emojiActivityOver: sprite(308px, 264px, 21px, 22px);
emojiActivityActive: sprite(311px, 287px, 20px, 20px); emojiActivityActive: sprite(308px, 286px, 21px, 22px);
emojiTravel: sprite(132px, 197px, 20px, 20px); emojiTravel: sprite(126px, 196px, 21px, 22px);
emojiTravelOver: sprite(321px, 344px, 20px, 20px); emojiTravelOver: sprite(321px, 344px, 21px, 22px);
emojiTravelActive: sprite(321px, 365px, 20px, 20px); emojiTravelActive: sprite(321px, 366px, 21px, 22px);
emojiObjects: sprite(153px, 197px, 20px, 20px); emojiObjects: sprite(147px, 196px, 21px, 22px);
emojiObjectsOver: sprite(342px, 344px, 20px, 20px); emojiObjectsOver: sprite(342px, 344px, 21px, 22px);
emojiObjectsActive: sprite(342px, 365px, 20px, 20px); emojiObjectsActive: sprite(342px, 366px, 21px, 22px);
emojiStickers: sprite(174px, 197px, 20px, 20px);
emojiStickersOver: sprite(363px, 344px, 20px, 20px);
emojiStickersActive: sprite(363px, 365px, 20px, 20px);
rbEmoji: flatCheckbox { rbEmoji: flatCheckbox {
textColor: transparent; textColor: transparent;
bgColor: transparent; bgColor: transparent;
disColor: transparent; disColor: transparent;
width: 28px; width: 36px;
height: 36px; height: 46px;
textTop: 0px; textTop: 0px;
textLeft: 0px; textLeft: 0px;
@ -1502,7 +1499,7 @@ rbEmoji: flatCheckbox {
cursor: cursor(pointer); cursor: cursor(pointer);
disabledCursor: cursor(default); disabledCursor: cursor(default);
imagePos: point(5px, 8px); imagePos: point(8px, 12px);
} }
rbEmojiRecent: flatCheckbox(rbEmoji) { rbEmojiRecent: flatCheckbox(rbEmoji) {
imageRect: emojiRecent; imageRect: emojiRecent;
@ -1568,16 +1565,8 @@ rbEmojiObjects: flatCheckbox(rbEmoji) {
disImageRect: emojiObjects; disImageRect: emojiObjects;
chkDisImageRect: emojiObjectsActive; chkDisImageRect: emojiObjectsActive;
} }
rbEmojiStickers: flatCheckbox(rbEmojiRecent) {
imageRect: emojiStickers;
chkImageRect: emojiStickersActive;
overImageRect: emojiStickersOver;
chkOverImageRect: emojiStickersActive;
disImageRect: emojiStickers;
chkDisImageRect: emojiStickersActive;
}
emojiPanPadding: margins(5px, 0px, 0px, 5px); emojiPanPadding: margins(5px, 0px, 0px, 5px);
emojiPanSize: size(35px, 35px); emojiPanSize: size(39px, 35px);
emojiPanDuration: 200; emojiPanDuration: 200;
emojiPanHover: #f0f0f0; emojiPanHover: #f0f0f0;
emojiPanRound: 2px; emojiPanRound: 2px;
@ -1593,6 +1582,8 @@ emojiColorsPadding: 5px;
emojiColorsSep: 1px; emojiColorsSep: 1px;
emojiColorsSepColor: #d5d5d5; emojiColorsSepColor: #d5d5d5;
toStickersImg: sprite();
toEmojiImg: sprite();
stickerPanRound: 3px; stickerPanRound: 3px;
stickerPanPadding: 2px; stickerPanPadding: 2px;
stickerPanDelete: sprite(123px, 132px, 12px, 12px); stickerPanDelete: sprite(123px, 132px, 12px, 12px);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 164 KiB

After

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 219 KiB

After

Width:  |  Height:  |  Size: 212 KiB

View File

@ -68,12 +68,12 @@ namespace {
const uint32 replacesCount = sizeof(replaces) / sizeof(EmojiReplace), replacesInRow = 7; const uint32 replacesCount = sizeof(replaces) / sizeof(EmojiReplace), replacesInRow = 7;
} }
EmojiBox::EmojiBox() : _done(this, lang(lng_about_done), st::aboutCloseButton) { EmojiBox::EmojiBox() : _esize(EmojiSizes[EIndex + 1]), _done(this, lang(lng_about_done), st::aboutCloseButton) {
fillBlocks(); fillBlocks();
_blockHeight = st::emojiReplaceInnerHeight; _blockHeight = st::emojiReplaceInnerHeight;
resizeMaxHeight(_blocks[0].size() * st::emojiReplaceWidth + (st::emojiReplaceWidth - st::emojiSize), st::boxPadding.top() + st::boxFont->height + _blocks.size() * st::emojiReplaceHeight + (st::emojiReplaceHeight - _blockHeight) + _done.height()); resizeMaxHeight(_blocks[0].size() * st::emojiReplaceWidth + (st::emojiReplaceWidth - _esize), st::boxPadding.top() + st::boxFont->height + _blocks.size() * st::emojiReplaceHeight + (st::emojiReplaceHeight - _blockHeight) + _done.height());
connect(&_done, SIGNAL(clicked()), this, SLOT(onClose())); connect(&_done, SIGNAL(clicked()), this, SLOT(onClose()));
@ -139,7 +139,7 @@ void EmojiBox::paintEvent(QPaintEvent *e) {
int32 rowSize = i->size(), left = (width() - rowSize * st::emojiReplaceWidth) / 2; int32 rowSize = i->size(), left = (width() - rowSize * st::emojiReplaceWidth) / 2;
for (BlockRow::const_iterator j = i->cbegin(), en = i->cend(); j != en; ++j) { for (BlockRow::const_iterator j = i->cbegin(), en = i->cend(); j != en; ++j) {
if (j->emoji) { if (j->emoji) {
emojiDraw(p, j->emoji, left + (st::emojiReplaceWidth - st::emojiSize) / 2, top + (st::emojiReplaceHeight - _blockHeight) / 2); p.drawPixmap(QPoint(left + (st::emojiReplaceWidth - _esize) / 2, top + (st::emojiReplaceHeight - _blockHeight) / 2), App::emojisLarge(), QRect(j->emoji->x * _esize, j->emoji->y * _esize, _esize, _esize));
} }
QRect trect(left, top + (st::emojiReplaceHeight + _blockHeight) / 2 - st::emojiTextFont->height, st::emojiReplaceWidth, st::emojiTextFont->height); QRect trect(left, top + (st::emojiReplaceHeight + _blockHeight) / 2 - st::emojiTextFont->height, st::emojiReplaceWidth, st::emojiTextFont->height);
p.drawText(trect, j->text, QTextOption(Qt::AlignHCenter | Qt::AlignTop)); p.drawText(trect, j->text, QTextOption(Qt::AlignHCenter | Qt::AlignTop));

View File

@ -38,6 +38,7 @@ private:
void fillBlocks(); void fillBlocks();
int32 _esize;
BottomButton _done; BottomButton _done;
int32 _blockHeight; int32 _blockHeight;

View File

@ -4879,7 +4879,7 @@ void HistoryMessage::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y)
lnk = _from->lnk; lnk = _from->lnk;
return; return;
} }
// width -= st::msgPhotoSkip; // width -= st::msgPhotoSkip;
left += st::msgPhotoSkip; left += st::msgPhotoSkip;
} }
if (width < 1) return; if (width < 1) return;
@ -4900,6 +4900,10 @@ void HistoryMessage::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y)
} }
r.setTop(r.top() + st::msgNameFont->height); r.setTop(r.top() + st::msgNameFont->height);
} }
return getStateFromMessageText(lnk, inText, x, y, r);
}
void HistoryMessage::getStateFromMessageText(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const QRect &r) const {
QRect trect(r.marginsAdded(-st::msgPadding)); QRect trect(r.marginsAdded(-st::msgPadding));
TextLinkPtr medialnk; TextLinkPtr medialnk;
if (_media) { if (_media) {
@ -5056,12 +5060,10 @@ void HistoryForwarded::drawForwardedFrom(QPainter &p, int32 x, int32 y, int32 w,
} }
void HistoryForwarded::drawMessageText(QPainter &p, const QRect &trect, uint32 selection) const { void HistoryForwarded::drawMessageText(QPainter &p, const QRect &trect, uint32 selection) const {
int32 h = st::msgServiceNameFont->height;
drawForwardedFrom(p, trect.x(), trect.y(), trect.width(), (selection == FullItemSel)); drawForwardedFrom(p, trect.x(), trect.y(), trect.width(), (selection == FullItemSel));
QRect realtrect(trect); QRect realtrect(trect);
realtrect.setY(trect.y() + h); realtrect.setY(trect.y() + st::msgServiceNameFont->height);
HistoryMessage::drawMessageText(p, realtrect, selection); HistoryMessage::drawMessageText(p, realtrect, selection);
} }
@ -5139,6 +5141,12 @@ void HistoryForwarded::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y
return HistoryMessage::getState(lnk, inText, x, y); return HistoryMessage::getState(lnk, inText, x, y);
} }
void HistoryForwarded::getStateFromMessageText(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const QRect &r) const {
QRect realr(r);
realr.setHeight(r.height() - st::msgServiceNameFont->height);
HistoryMessage::getStateFromMessageText(lnk, inText, x, y, realr);
}
void HistoryForwarded::getForwardedState(TextLinkPtr &lnk, bool &inText, int32 x, int32 w) const { void HistoryForwarded::getForwardedState(TextLinkPtr &lnk, bool &inText, int32 x, int32 w) const {
inText = false; inText = false;
if (x >= fromWidth && x < w && x < fromWidth + fwdFromName.maxWidth()) { if (x >= fromWidth && x < w && x < fromWidth + fwdFromName.maxWidth()) {
@ -5445,6 +5453,14 @@ void HistoryReply::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y) co
return HistoryMessage::getState(lnk, inText, x, y); return HistoryMessage::getState(lnk, inText, x, y);
} }
void HistoryReply::getStateFromMessageText(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const QRect &r) const {
int32 h = st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom();
QRect realr(r);
realr.setHeight(r.height() - h);
HistoryMessage::getStateFromMessageText(lnk, inText, x, y, realr);
}
void HistoryReply::getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y) const { void HistoryReply::getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y) const {
symbol = 0; symbol = 0;
after = false; after = false;

View File

@ -1238,7 +1238,10 @@ public:
int32 resize(int32 width, bool dontRecountText = false, const HistoryItem *parent = 0); int32 resize(int32 width, bool dontRecountText = false, const HistoryItem *parent = 0);
bool hasPoint(int32 x, int32 y) const; bool hasPoint(int32 x, int32 y) const;
void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y) const; void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y) const;
virtual void getStateFromMessageText(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const QRect &r) const;
void getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y) const; void getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y) const;
uint32 adjustSelection(uint16 from, uint16 to, TextSelectType type) const { uint32 adjustSelection(uint16 from, uint16 to, TextSelectType type) const {
return _text.adjustSelection(from, to, type); return _text.adjustSelection(from, to, type);
@ -1311,6 +1314,7 @@ public:
int32 resize(int32 width, bool dontRecountText = false, const HistoryItem *parent = 0); int32 resize(int32 width, bool dontRecountText = false, const HistoryItem *parent = 0);
bool hasPoint(int32 x, int32 y) const; bool hasPoint(int32 x, int32 y) const;
void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y) const; void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y) const;
void getStateFromMessageText(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const QRect &r) const;
void getForwardedState(TextLinkPtr &lnk, bool &inText, int32 x, int32 w) const; void getForwardedState(TextLinkPtr &lnk, bool &inText, int32 x, int32 w) const;
void getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y) const; void getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y) const;
@ -1363,6 +1367,7 @@ public:
int32 resize(int32 width, bool dontRecountText = false, const HistoryItem *parent = 0); int32 resize(int32 width, bool dontRecountText = false, const HistoryItem *parent = 0);
bool hasPoint(int32 x, int32 y) const; bool hasPoint(int32 x, int32 y) const;
void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y) const; void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y) const;
void getStateFromMessageText(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const QRect &r) const;
void getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y) const; void getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y) const;
UserData *replyTo() const { UserData *replyTo() const {

View File

@ -153,6 +153,7 @@ void IntroCode::activate() {
callTimer.start(1000); callTimer.start(1000);
error = ""; error = "";
errorAlpha = anim::fvalue(0); errorAlpha = anim::fvalue(0);
sentCode = QString();
show(); show();
code.setDisabled(false); code.setDisabled(false);
code.setFocus(); code.setFocus();

View File

@ -1077,10 +1077,17 @@ namespace {
LOG(("App Info: reading old user config..")); LOG(("App Info: reading old user config.."));
qint32 version = 0; qint32 version = 0;
mtpDcOptions dcOpts(cDcOptions()); mtpDcOptions dcOpts;
{
QReadLocker lock(MTP::dcOptionsMutex());
dcOpts = cDcOptions();
}
_dcOpts = &dcOpts; _dcOpts = &dcOpts;
_readOldUserSettingsFields(&file, version); _readOldUserSettingsFields(&file, version);
cSetDcOptions(dcOpts); {
QWriteLocker lock(MTP::dcOptionsMutex());
cSetDcOptions(dcOpts);
}
file.close(); file.close();
result = true; result = true;
@ -1157,10 +1164,17 @@ namespace {
LOG(("App Info: reading old keys..")); LOG(("App Info: reading old keys.."));
qint32 version = 0; qint32 version = 0;
mtpDcOptions dcOpts(cDcOptions()); mtpDcOptions dcOpts;
{
QReadLocker lock(MTP::dcOptionsMutex());
dcOpts = cDcOptions();
}
_dcOpts = &dcOpts; _dcOpts = &dcOpts;
_readOldMtpDataFields(&file, version); _readOldMtpDataFields(&file, version);
cSetDcOptions(dcOpts); {
QWriteLocker lock(MTP::dcOptionsMutex());
cSetDcOptions(dcOpts);
}
file.close(); file.close();
result = true; result = true;
@ -1648,7 +1662,11 @@ namespace Local {
LOG(("App Error: could not decrypt settings from settings file, maybe bad passcode..")); LOG(("App Error: could not decrypt settings from settings file, maybe bad passcode.."));
return writeSettings(); return writeSettings();
} }
mtpDcOptions dcOpts(cDcOptions()); mtpDcOptions dcOpts;
{
QReadLocker lock(MTP::dcOptionsMutex());
dcOpts = cDcOptions();
}
_dcOpts = &dcOpts; _dcOpts = &dcOpts;
LOG(("App Info: reading encrypted settings..")); LOG(("App Info: reading encrypted settings.."));
while (!settings.stream.atEnd()) { while (!settings.stream.atEnd()) {
@ -1669,7 +1687,10 @@ namespace Local {
DEBUG_LOG(("MTP Info: adding built in DC %1 connect option: %2:%3").arg(bdcs[i].id).arg(bdcs[i].ip).arg(bdcs[i].port)); DEBUG_LOG(("MTP Info: adding built in DC %1 connect option: %2:%3").arg(bdcs[i].id).arg(bdcs[i].ip).arg(bdcs[i].port));
} }
} }
cSetDcOptions(dcOpts); {
QWriteLocker lock(MTP::dcOptionsMutex());
cSetDcOptions(dcOpts);
}
_settingsSalt = salt; _settingsSalt = salt;
} }
@ -1690,13 +1711,19 @@ namespace Local {
} }
settings.writeData(_settingsSalt); settings.writeData(_settingsSalt);
mtpDcOptions dcOpts(cDcOptions()); mtpDcOptions dcOpts;
{
QReadLocker lock(MTP::dcOptionsMutex());
dcOpts = cDcOptions();
}
if (dcOpts.isEmpty()) { if (dcOpts.isEmpty()) {
const BuiltInDc *bdcs = builtInDcs(); const BuiltInDc *bdcs = builtInDcs();
for (int i = 0, l = builtInDcsCount(); i < l; ++i) { for (int i = 0, l = builtInDcsCount(); i < l; ++i) {
dcOpts.insert(bdcs[i].id, mtpDcOption(bdcs[i].id, "", bdcs[i].ip, bdcs[i].port)); dcOpts.insert(bdcs[i].id, mtpDcOption(bdcs[i].id, "", bdcs[i].ip, bdcs[i].port));
DEBUG_LOG(("MTP Info: adding built in DC %1 connect option: %2:%3").arg(bdcs[i].id).arg(bdcs[i].ip).arg(bdcs[i].port)); DEBUG_LOG(("MTP Info: adding built in DC %1 connect option: %2:%3").arg(bdcs[i].id).arg(bdcs[i].ip).arg(bdcs[i].port));
} }
QWriteLocker lock(MTP::dcOptionsMutex());
cSetDcOptions(dcOpts); cSetDcOptions(dcOpts);
} }

View File

@ -23,13 +23,14 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
namespace { namespace {
typedef QMap<int32, MTProtoSessionPtr> Sessions; typedef QMap<int32, MTProtoSessionPtr> Sessions;
Sessions sessions; Sessions sessions;
QVector<MTProtoSessionPtr> sessionsToKill;
MTProtoSessionPtr mainSession; MTProtoSessionPtr mainSession;
typedef QMap<mtpRequestId, int32> RequestsByDC; // holds dc for request to this dc or -dc for request to main dc typedef QMap<mtpRequestId, int32> RequestsByDC; // holds dcWithShift for request to this dc or -dc for request to main dc
RequestsByDC requestsByDC; RequestsByDC requestsByDC;
QMutex requestByDCLock; QMutex requestByDCLock;
typedef QMap<mtpRequestId, int32> AuthExportRequests; // holds target dc for auth export request typedef QMap<mtpRequestId, int32> AuthExportRequests; // holds target dcWithShift for auth export request
AuthExportRequests authExportRequests; AuthExportRequests authExportRequests;
bool _started = false; bool _started = false;
@ -55,7 +56,7 @@ namespace {
BadGuestDCRequests badGuestDCRequests; BadGuestDCRequests badGuestDCRequests;
typedef QVector<mtpRequestId> DCAuthWaiters; typedef QVector<mtpRequestId> DCAuthWaiters;
typedef QMap<int32, DCAuthWaiters> AuthWaiters; typedef QMap<int32, DCAuthWaiters> AuthWaiters; // holds request ids waiting for auth import to specific dc
AuthWaiters authWaiters; AuthWaiters authWaiters;
QMutex toClearLock; QMutex toClearLock;
@ -76,12 +77,11 @@ namespace {
if (globalHandler.onFail && MTP::authedId()) (*globalHandler.onFail)(req, error); // auth failed in main dc if (globalHandler.onFail && MTP::authedId()) (*globalHandler.onFail)(req, error); // auth failed in main dc
return; return;
} }
int32 newdc = i.value(); int32 newdc = i.value() % _mtp_internal::dcShift;
DEBUG_LOG(("MTP Info: auth import to dc %1 succeeded").arg(newdc)); DEBUG_LOG(("MTP Info: auth import to dc %1 succeeded").arg(newdc));
DCAuthWaiters &waiters(authWaiters[newdc]); DCAuthWaiters &waiters(authWaiters[newdc]);
MTProtoSessionPtr session(_mtp_internal::getSession(newdc));
if (waiters.size()) { if (waiters.size()) {
QReadLocker locker(&requestMapLock); QReadLocker locker(&requestMapLock);
for (DCAuthWaiters::iterator i = waiters.begin(), e = waiters.end(); i != e; ++i) { for (DCAuthWaiters::iterator i = waiters.begin(), e = waiters.end(); i != e; ++i) {
@ -91,6 +91,7 @@ namespace {
LOG(("MTP Error: could not find request %1 for resending").arg(requestId)); LOG(("MTP Error: could not find request %1 for resending").arg(requestId));
continue; continue;
} }
int32 dcWithShift = newdc;
{ {
RequestsByDC::iterator k = requestsByDC.find(requestId); RequestsByDC::iterator k = requestsByDC.find(requestId);
if (k == requestsByDC.cend()) { if (k == requestsByDC.cend()) {
@ -101,11 +102,15 @@ namespace {
MTP::setdc(newdc); MTP::setdc(newdc);
k.value() = -newdc; k.value() = -newdc;
} else { } else {
k.value() = k.value() - (k.value() % _mtp_internal::dcShift) + newdc; int32 shift = k.value() - (k.value() % _mtp_internal::dcShift);
dcWithShift += shift;
k.value() = dcWithShift;
} }
DEBUG_LOG(("MTP Info: resending request %1 to dc %2 after import auth").arg(requestId).arg(k.value())); DEBUG_LOG(("MTP Info: resending request %1 to dc %2 after import auth").arg(requestId).arg(k.value()));
} }
session->sendPrepared(j.value()); if (MTProtoSessionPtr session = _mtp_internal::getSession(dcWithShift)) {
session->sendPrepared(j.value());
}
} }
waiters.clear(); waiters.clear();
} }
@ -121,8 +126,8 @@ namespace {
void exportDone(const MTPauth_ExportedAuthorization &result, mtpRequestId req) { void exportDone(const MTPauth_ExportedAuthorization &result, mtpRequestId req) {
AuthExportRequests::const_iterator i = authExportRequests.constFind(req); AuthExportRequests::const_iterator i = authExportRequests.constFind(req);
if (i == authExportRequests.cend()) { if (i == authExportRequests.cend()) {
LOG(("MTP Error: auth export request target dc not found, requestId: %1").arg(req)); LOG(("MTP Error: auth export request target dcWithShift not found, requestId: %1").arg(req));
RPCError error(rpcClientError("AUTH_IMPORT_FAIL", QString("did not find target dc, request %1").arg(req))); RPCError error(rpcClientError("AUTH_IMPORT_FAIL", QString("did not find target dcWithShift, request %1").arg(req)));
if (globalHandler.onFail && MTP::authedId()) (*globalHandler.onFail)(req, error); // auth failed in main dc if (globalHandler.onFail && MTP::authedId()) (*globalHandler.onFail)(req, error); // auth failed in main dc
return; return;
} }
@ -137,7 +142,7 @@ namespace {
AuthExportRequests::const_iterator i = authExportRequests.constFind(req); AuthExportRequests::const_iterator i = authExportRequests.constFind(req);
if (i != authExportRequests.cend()) { if (i != authExportRequests.cend()) {
authWaiters[i.value()].clear(); authWaiters[i.value() % _mtp_internal::dcShift].clear();
} }
if (globalHandler.onFail && MTP::authedId()) (*globalHandler.onFail)(req, error); // auth failed in main dc if (globalHandler.onFail && MTP::authedId()) (*globalHandler.onFail)(req, error); // auth failed in main dc
return true; return true;
@ -151,31 +156,34 @@ namespace {
if ((m = QRegularExpression("^(FILE|PHONE|NETWORK|USER)_MIGRATE_(\\d+)$").match(err)).hasMatch()) { if ((m = QRegularExpression("^(FILE|PHONE|NETWORK|USER)_MIGRATE_(\\d+)$").match(err)).hasMatch()) {
if (!requestId) return false; if (!requestId) return false;
int32 dc = 0, newdc = m.captured(2).toInt(); int32 dcWithShift = 0, newdcWithShift = m.captured(2).toInt();
{ {
QMutexLocker locker(&requestByDCLock); QMutexLocker locker(&requestByDCLock);
RequestsByDC::iterator i = requestsByDC.find(requestId); RequestsByDC::iterator i = requestsByDC.find(requestId);
if (i == requestsByDC.end()) { if (i == requestsByDC.end()) {
LOG(("MTP Error: could not find request %1 for migrating to %2").arg(requestId).arg(newdc)); LOG(("MTP Error: could not find request %1 for migrating to %2").arg(requestId).arg(newdcWithShift));
} else { } else {
dc = i.value(); dcWithShift = i.value();
} }
} }
if (!dc || !newdc) return false; if (!dcWithShift || !newdcWithShift) return false;
DEBUG_LOG(("MTP Info: changing request %1 dc%2 to %3").arg(requestId).arg((dc > 0) ? "" : " and main dc").arg(newdc)); DEBUG_LOG(("MTP Info: changing request %1 from dcWithShift%2 to dc%3").arg(requestId).arg(dcWithShift).arg(newdcWithShift));
if (dc < 0) { if (dcWithShift < 0) { // newdc shift = 0
if (MTP::authedId() && !authExportRequests.contains(requestId)) { // import auth, set dc and resend if (false && MTP::authedId() && !authExportRequests.contains(requestId)) { // migrate not supported at this moment
DEBUG_LOG(("MTP Info: importing auth to dc %1").arg(newdc)); DEBUG_LOG(("MTP Info: importing auth to dc %1").arg(newdcWithShift));
DCAuthWaiters &waiters(authWaiters[newdc]); DCAuthWaiters &waiters(authWaiters[newdcWithShift]);
if (!waiters.size()) { if (!waiters.size()) {
authExportRequests.insert(MTP::send(MTPauth_ExportAuthorization(MTP_int(newdc)), rpcDone(exportDone), rpcFail(exportFail)), newdc); authExportRequests.insert(MTP::send(MTPauth_ExportAuthorization(MTP_int(newdcWithShift)), rpcDone(exportDone), rpcFail(exportFail)), newdcWithShift);
} }
waiters.push_back(requestId); waiters.push_back(requestId);
return true; return true;
} else { } else {
MTP::setdc(newdc); MTP::setdc(newdcWithShift);
} }
} else {
int32 shift = dcWithShift - (dcWithShift % _mtp_internal::dcShift);
newdcWithShift += shift;
} }
mtpRequest req; mtpRequest req;
@ -188,8 +196,10 @@ namespace {
} }
req = i.value(); req = i.value();
} }
_mtp_internal::registerRequest(requestId, (dc < 0) ? -newdc : newdc); if (MTProtoSessionPtr session = _mtp_internal::getSession(newdcWithShift)) {
_mtp_internal::getSession(newdc)->sendPrepared(req); _mtp_internal::registerRequest(requestId, (dcWithShift < 0) ? -newdcWithShift : newdcWithShift);
session->sendPrepared(req);
}
return true; return true;
} else if (code < 0 || code >= 500 || (m = QRegularExpression("^FLOOD_WAIT_(\\d+)$").match(err)).hasMatch()) { } else if (code < 0 || code >= 500 || (m = QRegularExpression("^FLOOD_WAIT_(\\d+)$").match(err)).hasMatch()) {
if (!requestId) return false; if (!requestId) return false;
@ -218,26 +228,26 @@ namespace {
return true; return true;
} else if (code == 401 || (badGuestDC && badGuestDCRequests.constFind(requestId) == badGuestDCRequests.cend())) { } else if (code == 401 || (badGuestDC && badGuestDCRequests.constFind(requestId) == badGuestDCRequests.cend())) {
int32 dc = 0; int32 dcWithShift = 0;
{ {
QMutexLocker locker(&requestByDCLock); QMutexLocker locker(&requestByDCLock);
RequestsByDC::iterator i = requestsByDC.find(requestId); RequestsByDC::iterator i = requestsByDC.find(requestId);
if (i != requestsByDC.end()) { if (i != requestsByDC.end()) {
dc = i.value(); dcWithShift = i.value();
} else { } else {
LOG(("MTP Error: unauthorized request without dc info, requestId %1").arg(requestId)); LOG(("MTP Error: unauthorized request without dc info, requestId %1").arg(requestId));
} }
} }
int32 newdc = abs(dc) % _mtp_internal::dcShift; int32 newdc = abs(dcWithShift) % _mtp_internal::dcShift;
if (!newdc || newdc == mtpMainDC() || !MTP::authedId()) { if (!newdc || newdc == mtpMainDC() || !MTP::authedId()) {
if (!badGuestDC && globalHandler.onFail) (*globalHandler.onFail)(requestId, error); // auth failed in main dc if (!badGuestDC && globalHandler.onFail) (*globalHandler.onFail)(requestId, error); // auth failed in main dc
return false; return false;
} }
DEBUG_LOG(("MTP Info: importing auth to dc %1").arg(dc)); DEBUG_LOG(("MTP Info: importing auth to dcWithShift %1").arg(dcWithShift));
DCAuthWaiters &waiters(authWaiters[newdc]); DCAuthWaiters &waiters(authWaiters[newdc]);
if (!waiters.size()) { if (!waiters.size()) {
authExportRequests.insert(MTP::send(MTPauth_ExportAuthorization(MTP_int(newdc)), rpcDone(exportDone), rpcFail(exportFail)), newdc); authExportRequests.insert(MTP::send(MTPauth_ExportAuthorization(MTP_int(newdc)), rpcDone(exportDone), rpcFail(exportFail)), abs(dcWithShift));
} }
waiters.push_back(requestId); waiters.push_back(requestId);
if (badGuestDC) badGuestDCRequests.insert(requestId); if (badGuestDC) badGuestDCRequests.insert(requestId);
@ -253,20 +263,22 @@ namespace {
} }
req = i.value(); req = i.value();
} }
int32 dc = 0; int32 dcWithShift = 0;
{ {
QMutexLocker locker(&requestByDCLock); QMutexLocker locker(&requestByDCLock);
RequestsByDC::iterator i = requestsByDC.find(requestId); RequestsByDC::iterator i = requestsByDC.find(requestId);
if (i == requestsByDC.end()) { if (i == requestsByDC.end()) {
LOG(("MTP Error: could not find request %1 for resending with init connection").arg(requestId)); LOG(("MTP Error: could not find request %1 for resending with init connection").arg(requestId));
} else { } else {
dc = i.value(); dcWithShift = i.value();
} }
} }
if (!dc) return false; if (!dcWithShift) return false;
req->needsLayer = true; if (MTProtoSessionPtr session = _mtp_internal::getSession(dcWithShift < 0 ? (-dcWithShift) : dcWithShift)) {
_mtp_internal::getSession(dc < 0 ? (-dc) : dc)->sendPrepared(req); req->needsLayer = true;
session->sendPrepared(req);
}
return true; return true;
} else if (err == qsl("MSG_WAIT_FAILED")) { } else if (err == qsl("MSG_WAIT_FAILED")) {
mtpRequest req; mtpRequest req;
@ -283,7 +295,7 @@ namespace {
LOG(("MTP Error: wait failed for not dependent request %1").arg(requestId)); LOG(("MTP Error: wait failed for not dependent request %1").arg(requestId));
return false; return false;
} }
int32 dc = 0; int32 dcWithShift = 0;
{ {
QMutexLocker locker(&requestByDCLock); QMutexLocker locker(&requestByDCLock);
RequestsByDC::iterator i = requestsByDC.find(requestId), j = requestsByDC.find(req->after->requestId); RequestsByDC::iterator i = requestsByDC.find(requestId), j = requestsByDC.find(req->after->requestId);
@ -292,19 +304,21 @@ namespace {
} else if (j == requestsByDC.end()) { } else if (j == requestsByDC.end()) {
LOG(("MTP Error: could not find dependent request %1 by dc").arg(req->after->requestId)); LOG(("MTP Error: could not find dependent request %1 by dc").arg(req->after->requestId));
} else { } else {
dc = i.value(); dcWithShift = i.value();
if (i.value() != j.value()) { if (i.value() != j.value()) {
req->after = mtpRequest(); req->after = mtpRequest();
} }
} }
} }
if (!dc) return false; if (!dcWithShift) return false;
if (!req->after) { if (!req->after) {
req->needsLayer = true; if (MTProtoSessionPtr session = _mtp_internal::getSession(dcWithShift < 0 ? (-dcWithShift) : dcWithShift)) {
_mtp_internal::getSession(dc < 0 ? (-dc) : dc)->sendPrepared(req); req->needsLayer = true;
session->sendPrepared(req);
}
} else { } else {
int32 newdc = abs(dc) % _mtp_internal::dcShift; int32 newdc = abs(dcWithShift) % _mtp_internal::dcShift;
DCAuthWaiters &waiters(authWaiters[newdc]); DCAuthWaiters &waiters(authWaiters[newdc]);
if (waiters.indexOf(req->after->requestId) >= 0) { if (waiters.indexOf(req->after->requestId) >= 0) {
if (waiters.indexOf(requestId) < 0) { if (waiters.indexOf(requestId) < 0) {
@ -338,27 +352,27 @@ namespace {
} }
namespace _mtp_internal { namespace _mtp_internal {
MTProtoSessionPtr getSession(int32 dc) { MTProtoSessionPtr getSession(int32 dcWithShift) {
if (!_started) return MTProtoSessionPtr(); if (!_started) return MTProtoSessionPtr();
if (!dc) return mainSession; if (!dcWithShift) return mainSession;
if (!(dc % _mtp_internal::dcShift)) { if (!(dcWithShift % _mtp_internal::dcShift)) {
dc += mainSession->getDC(); dcWithShift += (mainSession->getDcWithShift() % _mtp_internal::dcShift);
} }
Sessions::const_iterator i = sessions.constFind(dc); Sessions::const_iterator i = sessions.constFind(dcWithShift);
if (i != sessions.cend()) return *i; if (i != sessions.cend()) return *i;
MTProtoSessionPtr result(new MTProtoSession()); MTProtoSessionPtr result(new MTProtoSession());
result->start(dc); result->start(dcWithShift);
sessions.insert(dc, result); sessions.insert(dcWithShift, result);
return result; return result;
} }
void registerRequest(mtpRequestId requestId, int32 dc) { void registerRequest(mtpRequestId requestId, int32 dcWithShift) {
{ {
QMutexLocker locker(&requestByDCLock); QMutexLocker locker(&requestByDCLock);
requestsByDC.insert(requestId, dc); requestsByDC.insert(requestId, dcWithShift);
} }
_mtp_internal::performDelayedClear(); // need to do it somewhere.. _mtp_internal::performDelayedClear(); // need to do it somewhere..
} }
@ -530,12 +544,12 @@ namespace _mtp_internal {
if (globalHandler.onDone) (*globalHandler.onDone)(0, from, end); // some updates were received if (globalHandler.onDone) (*globalHandler.onDone)(0, from, end); // some updates were received
} }
void onStateChange(int32 dc, int32 state) { void onStateChange(int32 dcWithShift, int32 state) {
if (stateChangedHandler) stateChangedHandler(dc, state); if (stateChangedHandler) stateChangedHandler(dcWithShift, state);
} }
void onSessionReset(int32 dc) { void onSessionReset(int32 dcWithShift) {
if (sessionResetHandler) sessionResetHandler(dc); if (sessionResetHandler) sessionResetHandler(dcWithShift);
} }
bool rpcErrorOccured(mtpRequestId requestId, const RPCFailHandlerPtr &onFail, const RPCError &err) { // return true if need to clean request data bool rpcErrorOccured(mtpRequestId requestId, const RPCFailHandlerPtr &onFail, const RPCError &err) { // return true if need to clean request data
@ -561,12 +575,12 @@ namespace _mtp_internal {
mtpRequestId requestId = delayedRequests.front().first; mtpRequestId requestId = delayedRequests.front().first;
delayedRequests.pop_front(); delayedRequests.pop_front();
int32 dc = 0; int32 dcWithShift = 0;
{ {
QMutexLocker locker(&requestByDCLock); QMutexLocker locker(&requestByDCLock);
RequestsByDC::const_iterator i = requestsByDC.constFind(requestId); RequestsByDC::const_iterator i = requestsByDC.constFind(requestId);
if (i != requestsByDC.cend()) { if (i != requestsByDC.cend()) {
dc = i.value(); dcWithShift = i.value();
} else { } else {
LOG(("MTP Error: could not find request dc for delayed resend, requestId %1").arg(requestId)); LOG(("MTP Error: could not find request dc for delayed resend, requestId %1").arg(requestId));
continue; continue;
@ -583,7 +597,9 @@ namespace _mtp_internal {
} }
req = j.value(); req = j.value();
} }
_mtp_internal::getSession(dc < 0 ? (-dc) : dc)->sendPrepared(req); if (MTProtoSessionPtr session = _mtp_internal::getSession(dcWithShift < 0 ? (-dcWithShift) : dcWithShift)) {
session->sendPrepared(req);
}
} }
if (!delayedRequests.isEmpty()) { if (!delayedRequests.isEmpty()) {
@ -595,13 +611,15 @@ namespace _mtp_internal {
namespace MTP { namespace MTP {
void start() { void start() {
if (started()) return;
unixtimeInit(); unixtimeInit();
MTProtoDCMap &dcs(mtpDCMap()); MTProtoDCMap &dcs(mtpDCMap());
mainSession = MTProtoSessionPtr(new MTProtoSession()); mainSession = MTProtoSessionPtr(new MTProtoSession());
mainSession->start(mtpMainDC()); mainSession->start(mtpMainDC());
sessions[mainSession->getDC()] = mainSession; sessions[mainSession->getDcWithShift()] = mainSession;
_started = true; _started = true;
resender = new _mtp_internal::RequestResender(); resender = new _mtp_internal::RequestResender();
@ -625,8 +643,9 @@ namespace MTP {
void restart(int32 dcMask) { void restart(int32 dcMask) {
if (!_started) return; if (!_started) return;
dcMask %= _mtp_internal::dcShift;
for (Sessions::const_iterator i = sessions.cbegin(), e = sessions.cend(); i != e; ++i) { for (Sessions::const_iterator i = sessions.cbegin(), e = sessions.cend(); i != e; ++i) {
if ((*i)->getDC() % _mtp_internal::dcShift == dcMask % _mtp_internal::dcShift) { if (((*i)->getDcWithShift() % _mtp_internal::dcShift) == dcMask) {
(*i)->restart(); (*i)->restart();
} }
} }
@ -641,8 +660,9 @@ namespace MTP {
void setdc(int32 dc, bool fromZeroOnly) { void setdc(int32 dc, bool fromZeroOnly) {
if (!dc || !_started) return; if (!dc || !_started) return;
mtpSetDC(dc, fromZeroOnly); mtpSetDC(dc, fromZeroOnly);
if (maindc() != mainSession->getDC()) { int32 oldMainDc = mainSession->getDcWithShift();
mainSession = _mtp_internal::getSession(maindc()); if (maindc() != oldMainDc) {
killSession(oldMainDc);
} }
Local::writeMtpData(); Local::writeMtpData();
} }
@ -656,7 +676,7 @@ namespace MTP {
if (!dc) return mainSession->getState(); if (!dc) return mainSession->getState();
if (!(dc % _mtp_internal::dcShift)) { if (!(dc % _mtp_internal::dcShift)) {
dc += mainSession->getDC(); dc += (mainSession->getDcWithShift() % _mtp_internal::dcShift);
} }
Sessions::const_iterator i = sessions.constFind(dc); Sessions::const_iterator i = sessions.constFind(dc);
@ -670,7 +690,7 @@ namespace MTP {
if (!dc) return mainSession->transport(); if (!dc) return mainSession->transport();
if (!(dc % _mtp_internal::dcShift)) { if (!(dc % _mtp_internal::dcShift)) {
dc += mainSession->getDC(); dc += (mainSession->getDcWithShift() % _mtp_internal::dcShift);
} }
Sessions::const_iterator i = sessions.constFind(dc); Sessions::const_iterator i = sessions.constFind(dc);
@ -679,16 +699,10 @@ namespace MTP {
return QString(); return QString();
} }
void initdc(int32 dc) {
if (!_started) return;
_mtp_internal::getSession(dc);
}
void ping() { void ping() {
MTProtoSessionPtr session = _mtp_internal::getSession(0); if (MTProtoSessionPtr session = _mtp_internal::getSession(0)) {
if (!session) return; session->ping();
}
return session->ping();
} }
void cancel(mtpRequestId requestId) { void cancel(mtpRequestId requestId) {
@ -706,25 +720,35 @@ namespace MTP {
QMutexLocker locker(&requestByDCLock); QMutexLocker locker(&requestByDCLock);
RequestsByDC::iterator i = requestsByDC.find(requestId); RequestsByDC::iterator i = requestsByDC.find(requestId);
if (i != requestsByDC.end()) { if (i != requestsByDC.end()) {
_mtp_internal::getSession(abs(i.value()))->cancel(requestId, msgId); if (MTProtoSessionPtr session = _mtp_internal::getSession(abs(i.value()))) {
session->cancel(requestId, msgId);
}
requestsByDC.erase(i); requestsByDC.erase(i);
} }
} }
_mtp_internal::clearCallbacks(requestId); _mtp_internal::clearCallbacks(requestId);
} }
void killSessionsDelayed() {
if (!sessionsToKill.isEmpty()) {
sessionsToKill.clear();
}
}
void killSession(int32 dc) { void killSession(int32 dc) {
Sessions::iterator i = sessions.find(dc); Sessions::iterator i = sessions.find(dc);
if (i != sessions.end()) { if (i != sessions.end()) {
bool wasMain = (i.value() == mainSession); bool wasMain = (i.value() == mainSession);
i.value()->stop(); i.value()->kill();
if (sessionsToKill.isEmpty()) QTimer::singleShot(0, killSessionsDelayed);
sessionsToKill.push_back(i.value());
sessions.erase(i); sessions.erase(i);
if (wasMain) { if (wasMain) {
mainSession = MTProtoSessionPtr(new MTProtoSession()); mainSession = MTProtoSessionPtr(new MTProtoSession());
mainSession->start(mtpMainDC()); mainSession->start(mtpMainDC());
sessions[mainSession->getDC()] = mainSession; sessions[mainSession->getDcWithShift()] = mainSession;
} }
} }
} }
@ -743,22 +767,30 @@ namespace MTP {
QMutexLocker locker(&requestByDCLock); QMutexLocker locker(&requestByDCLock);
RequestsByDC::iterator i = requestsByDC.find(requestId); RequestsByDC::iterator i = requestsByDC.find(requestId);
if (i != requestsByDC.end()) { if (i != requestsByDC.end()) {
return _mtp_internal::getSession(abs(i.value()))->requestState(requestId); if (MTProtoSessionPtr session = _mtp_internal::getSession(abs(i.value()))) {
return session->requestState(requestId);
}
return MTP::RequestConnecting;
} }
return MTP::RequestSent; return MTP::RequestSent;
} }
return _mtp_internal::getSession(-requestId)->requestState(0); if (MTProtoSessionPtr session = _mtp_internal::getSession(-requestId)) {
return session->requestState(0);
}
return MTP::RequestConnecting;
} }
void stop() { void stop() {
for (Sessions::iterator i = sessions.begin(), e = sessions.end(); i != e; ++i) { for (Sessions::iterator i = sessions.begin(), e = sessions.end(); i != e; ++i) {
i.value()->stop(); i.value()->kill();
} }
sessions.clear(); sessions.clear();
mainSession = MTProtoSessionPtr(); mainSession = MTProtoSessionPtr();
delete resender; delete resender;
resender = 0; resender = 0;
mtpDestroyConfigLoader(); mtpDestroyConfigLoader();
_started = false;
} }
void authed(int32 uid) { void authed(int32 uid) {
@ -810,4 +842,8 @@ namespace MTP {
return mtpSetKey(dc, key); return mtpSetKey(dc, key);
} }
QReadWriteLock *dcOptionsMutex() {
return mtpDcOptionsMutex();
}
}; };

View File

@ -37,8 +37,8 @@ namespace _mtp_internal {
void execCallback(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end); void execCallback(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end);
bool hasCallbacks(mtpRequestId requestId); bool hasCallbacks(mtpRequestId requestId);
void globalCallback(const mtpPrime *from, const mtpPrime *end); void globalCallback(const mtpPrime *from, const mtpPrime *end);
void onStateChange(int32 dc, int32 state); void onStateChange(int32 dcWithShift, int32 state);
void onSessionReset(int32 dc); void onSessionReset(int32 dcWithShift);
bool rpcErrorOccured(mtpRequestId requestId, const RPCFailHandlerPtr &onFail, const RPCError &err); // return true if need to clean request data bool rpcErrorOccured(mtpRequestId requestId, const RPCFailHandlerPtr &onFail, const RPCError &err); // return true if need to clean request data
inline bool rpcErrorOccured(mtpRequestId requestId, const RPCResponseHandler &handler, const RPCError &err) { inline bool rpcErrorOccured(mtpRequestId requestId, const RPCResponseHandler &handler, const RPCError &err) {
return rpcErrorOccured(requestId, handler.onFail, err); return rpcErrorOccured(requestId, handler.onFail, err);
@ -64,6 +64,7 @@ namespace _mtp_internal {
namespace MTP { namespace MTP {
static const uint32 cfg = 1 * _mtp_internal::dcShift; // send(MTPhelp_GetConfig(), MTP::cfg + dc) - for dc enum static const uint32 cfg = 1 * _mtp_internal::dcShift; // send(MTPhelp_GetConfig(), MTP::cfg + dc) - for dc enum
static const uint32 lgt = 2 * _mtp_internal::dcShift; // send(MTPauth_LogOut(), MTP::lgt + dc) - for logout of guest dcs enum
static const uint32 dld[MTPDownloadSessionsCount] = { // send(req, callbacks, MTP::dld[i] + dc) - for download static const uint32 dld[MTPDownloadSessionsCount] = { // send(req, callbacks, MTP::dld[i] + dc) - for download
0x10 * _mtp_internal::dcShift, 0x10 * _mtp_internal::dcShift,
0x11 * _mtp_internal::dcShift, 0x11 * _mtp_internal::dcShift,
@ -89,13 +90,13 @@ namespace MTP {
int32 dcstate(int32 dc = 0); int32 dcstate(int32 dc = 0);
QString dctransport(int32 dc = 0); QString dctransport(int32 dc = 0);
void initdc(int32 dc);
template <typename TRequest> template <typename TRequest>
inline mtpRequestId send(const TRequest &request, RPCResponseHandler callbacks = RPCResponseHandler(), int32 dc = 0, uint64 msCanWait = 0, mtpRequestId after = 0) { inline mtpRequestId send(const TRequest &request, RPCResponseHandler callbacks = RPCResponseHandler(), int32 dc = 0, uint64 msCanWait = 0, mtpRequestId after = 0) {
MTProtoSessionPtr session = _mtp_internal::getSession(dc); if (MTProtoSessionPtr session = _mtp_internal::getSession(dc)) {
if (!session) return 0; return session->send(request, callbacks, msCanWait, true, !dc, after);
}
return session->send(request, callbacks, msCanWait, true, !dc, after); return 0;
} }
template <typename TRequest> template <typename TRequest>
inline mtpRequestId send(const TRequest &request, RPCDoneHandlerPtr onDone, RPCFailHandlerPtr onFail = RPCFailHandlerPtr(), int32 dc = 0, uint64 msCanWait = 0, mtpRequestId after = 0) { inline mtpRequestId send(const TRequest &request, RPCDoneHandlerPtr onDone, RPCFailHandlerPtr onFail = RPCFailHandlerPtr(), int32 dc = 0, uint64 msCanWait = 0, mtpRequestId after = 0) {
@ -139,6 +140,8 @@ namespace MTP {
mtpKeysMap getKeys(); mtpKeysMap getKeys();
void setKey(int32 dc, mtpAuthKeyPtr key); void setKey(int32 dc, mtpAuthKeyPtr key);
QReadWriteLock *dcOptionsMutex();
}; };
#include "mtproto/mtpSessionImpl.h" #include "mtproto/mtpSessionImpl.h"

View File

@ -1114,6 +1114,7 @@ MTProtoConnectionPrivate::MTProtoConnectionPrivate(QThread *thread, MTProtoConne
// createConn(); // createConn();
if (!dc) { if (!dc) {
QReadLocker lock(mtpDcOptionsMutex());
const mtpDcOptions &options(cDcOptions()); const mtpDcOptions &options(cDcOptions());
if (options.isEmpty()) { if (options.isEmpty()) {
LOG(("MTP Error: connect failed, no DCs")); LOG(("MTP Error: connect failed, no DCs"));
@ -1713,6 +1714,8 @@ void MTProtoConnectionPrivate::retryByTimer() {
} }
if (keyId == mtpAuthKey::RecreateKeyId) { if (keyId == mtpAuthKey::RecreateKeyId) {
if (sessionData->getKey()) { if (sessionData->getKey()) {
unlockKey();
QWriteLocker lock(sessionData->keyMutex()); QWriteLocker lock(sessionData->keyMutex());
sessionData->owner()->destroyKey(); sessionData->owner()->destroyKey();
} }
@ -1738,31 +1741,34 @@ void MTProtoConnectionPrivate::socketStart(bool afterConfig) {
_pingId = _pingMsgId = _pingIdToSend = _pingSendAt = 0; _pingId = _pingMsgId = _pingIdToSend = _pingSendAt = 0;
_pingSender.stop(); _pingSender.stop();
const mtpDcOption *dcOption = 0; std::string ip;
const mtpDcOptions &options(cDcOptions()); uint32 port = 0;
mtpDcOptions::const_iterator dcIndex = options.constFind(dc % _mtp_internal::dcShift); {
DEBUG_LOG(("MTP Info: connecting to DC %1..").arg(dc)); QReadLocker lock(mtpDcOptionsMutex());
if (dcIndex == options.cend()) { const mtpDcOptions &options(cDcOptions());
mtpDcOptions::const_iterator dcIndex = options.constFind(dc % _mtp_internal::dcShift);
DEBUG_LOG(("MTP Info: connecting to DC %1..").arg(dc));
if (dcIndex != options.cend()) {
ip = dcIndex->ip;
port = dcIndex->port;
}
}
if (!port || ip.empty()) {
if (afterConfig) { if (afterConfig) {
LOG(("MTP Error: DC %1 options not found right after config load!").arg(dc)); LOG(("MTP Error: DC %1 options not found right after config load!").arg(dc));
return restart(); return restart();
} else {
DEBUG_LOG(("MTP Info: DC %1 options not found, waiting for config").arg(dc));
connect(mtpConfigLoader(), SIGNAL(loaded()), this, SLOT(onConfigLoaded()));
mtpConfigLoader()->load();
return;
} }
DEBUG_LOG(("MTP Info: DC %1 options not found, waiting for config").arg(dc));
connect(mtpConfigLoader(), SIGNAL(loaded()), this, SLOT(onConfigLoaded()));
mtpConfigLoader()->load();
return;
} }
dcOption = &dcIndex.value(); DEBUG_LOG(("MTP Info: socket connection to %1:%2..").arg(ip.c_str()).arg(port));
const char *ip(dcOption->ip.c_str());
uint32 port(dcOption->port);
DEBUG_LOG(("MTP Info: socket connection to %1:%2..").arg(ip).arg(port));
connect(conn, SIGNAL(connected()), this, SLOT(onConnected())); connect(conn, SIGNAL(connected()), this, SLOT(onConnected()));
connect(conn, SIGNAL(disconnected()), this, SLOT(restart())); connect(conn, SIGNAL(disconnected()), this, SLOT(restart()));
conn->connectToServer(ip, port); conn->connectToServer(ip.c_str(), port);
} }
void MTProtoConnectionPrivate::restart(bool maybeBadKey) { void MTProtoConnectionPrivate::restart(bool maybeBadKey) {
@ -2824,12 +2830,36 @@ void MTProtoConnectionPrivate::onConnected() {
TCP_LOG(("Connection Info: connection succeed.")); TCP_LOG(("Connection Info: connection succeed."));
if (updateAuthKey()) { updateAuthKey();
DEBUG_LOG(("MTP Info: returning from socketConnected..")); }
return;
void MTProtoConnectionPrivate::updateAuthKey() {
QReadLocker lockFinished(&sessionDataMutex);
if (!sessionData || !conn) return;
DEBUG_LOG(("AuthKey Info: MTProtoConnection updating key from MTProtoSession, dc %1").arg(dc));
uint64 newKeyId = 0;
{
ReadLockerAttempt lock(sessionData->keyMutex());
if (!lock) {
DEBUG_LOG(("MTP Info: could not lock auth_key for read, waiting signal emit"));
clearMessages();
keyId = newKeyId;
return; // some other connection is getting key
}
const mtpAuthKeyPtr &key(sessionData->getKey());
newKeyId = key ? key->keyId() : 0;
}
if (keyId != newKeyId) {
clearMessages();
keyId = newKeyId;
}
DEBUG_LOG(("AuthKey Info: MTProtoConnection update key from MTProtoSession, dc %1 result: %2").arg(dc).arg(mb(&keyId, sizeof(keyId)).str()));
if (keyId) {
return authKeyCreated();
} }
DEBUG_LOG(("MTP Info: will be creating auth_key")); DEBUG_LOG(("AuthKey Info: No key in updateAuthKey(), will be creating auth_key"));
lockKey(); lockKey();
const mtpAuthKeyPtr &key(sessionData->getKey()); const mtpAuthKeyPtr &key(sessionData->getKey());
@ -2854,36 +2884,6 @@ void MTProtoConnectionPrivate::onConnected() {
sendRequestNotSecure(req_pq); sendRequestNotSecure(req_pq);
} }
bool MTProtoConnectionPrivate::updateAuthKey() {
QReadLocker lockFinished(&sessionDataMutex);
if (!sessionData || !conn) return false;
DEBUG_LOG(("AuthKey Info: MTProtoConnection updating key from MTProtoSession, dc %1").arg(dc));
uint64 newKeyId = 0;
{
ReadLockerAttempt lock(sessionData->keyMutex());
if (!lock) {
DEBUG_LOG(("MTP Info: could not lock auth_key for read, waiting signal emit"));
clearMessages();
keyId = newKeyId;
return true; // some other connection is getting key
}
const mtpAuthKeyPtr &key(sessionData->getKey());
newKeyId = key ? key->keyId() : 0;
}
if (keyId != newKeyId) {
clearMessages();
keyId = newKeyId;
}
DEBUG_LOG(("AuthKey Info: MTProtoConnection update key from MTProtoSession, dc %1 result: %2").arg(dc).arg(mb(&keyId, sizeof(keyId)).str()));
if (keyId) {
authKeyCreated();
return true;
}
DEBUG_LOG(("AuthKey Info: Key update failed"));
return false;
}
void MTProtoConnectionPrivate::clearMessages() { void MTProtoConnectionPrivate::clearMessages() {
if (keyId && keyId != mtpAuthKey::RecreateKeyId && conn) { if (keyId && keyId != mtpAuthKey::RecreateKeyId && conn) {
conn->received().clear(); conn->received().clear();
@ -3481,7 +3481,14 @@ MTProtoConnectionPrivate::~MTProtoConnectionPrivate() {
void MTProtoConnectionPrivate::stop() { void MTProtoConnectionPrivate::stop() {
QWriteLocker lockFinished(&sessionDataMutex); QWriteLocker lockFinished(&sessionDataMutex);
sessionData = 0; if (sessionData) {
if (myKeyLock) {
sessionData->owner()->notifyKeyCreated(mtpAuthKeyPtr()); // release key lock, let someone else create it
sessionData->keyMutex()->unlock();
myKeyLock = false;
}
sessionData = 0;
}
} }
MTProtoConnection::~MTProtoConnection() { MTProtoConnection::~MTProtoConnection() {

View File

@ -366,7 +366,7 @@ public slots:
// Sessions signals, when we need to send something // Sessions signals, when we need to send something
void tryToSend(); void tryToSend();
bool updateAuthKey(); void updateAuthKey();
void onConfigLoaded(); void onConfigLoaded();

View File

@ -56,6 +56,20 @@ int32 mtpMainDC() {
return mainDC; return mainDC;
} }
namespace {
QMap<int32, mtpRequestId> logoutGuestMap; // dcWithShift to logout request id
bool logoutDone(mtpRequestId req) {
for (QMap<int32, mtpRequestId>::iterator i = logoutGuestMap.begin(); i != logoutGuestMap.end(); ++i) {
if (i.value() == req) {
MTP::killSession(i.key());
logoutGuestMap.erase(i);
return true;
}
}
return false;
}
}
void mtpLogoutOtherDCs() { void mtpLogoutOtherDCs() {
QList<int32> dcs; QList<int32> dcs;
{ {
@ -64,7 +78,7 @@ void mtpLogoutOtherDCs() {
} }
for (int32 i = 0, cnt = dcs.size(); i != cnt; ++i) { for (int32 i = 0, cnt = dcs.size(); i != cnt; ++i) {
if (dcs[i] != MTP::maindc()) { if (dcs[i] != MTP::maindc()) {
MTP::send(MTPauth_LogOut(), RPCResponseHandler(), dcs[i]); logoutGuestMap.insert(MTP::lgt + dcs[i], MTP::send(MTPauth_LogOut(), rpcDone(&logoutDone), rpcFail(&logoutDone), MTP::lgt + dcs[i]));
} }
} }
} }
@ -154,7 +168,11 @@ namespace {
void mtpUpdateDcOptions(const QVector<MTPDcOption> &options) { void mtpUpdateDcOptions(const QVector<MTPDcOption> &options) {
QSet<int32> already, restart; QSet<int32> already, restart;
{ {
mtpDcOptions opts(cDcOptions()); mtpDcOptions opts;
{
QReadLocker lock(mtpDcOptionsMutex());
opts = cDcOptions();
}
for (QVector<MTPDcOption>::const_iterator i = options.cbegin(), e = options.cend(); i != e; ++i) { for (QVector<MTPDcOption>::const_iterator i = options.cbegin(), e = options.cend(); i != e; ++i) {
const MTPDdcOption &optData(i->c_dcOption()); const MTPDdcOption &optData(i->c_dcOption());
if (already.constFind(optData.vid.v) == already.cend()) { if (already.constFind(optData.vid.v) == already.cend()) {
@ -168,16 +186,26 @@ void mtpUpdateDcOptions(const QVector<MTPDcOption> &options) {
opts.insert(optData.vid.v, mtpDcOption(optData.vid.v, optData.vhostname.c_string().v, optData.vip_address.c_string().v, optData.vport.v)); opts.insert(optData.vid.v, mtpDcOption(optData.vid.v, optData.vhostname.c_string().v, optData.vip_address.c_string().v, optData.vport.v));
} }
} }
cSetDcOptions(opts); {
QWriteLocker lock(mtpDcOptionsMutex());
cSetDcOptions(opts);
}
} }
for (QSet<int32>::const_iterator i = restart.cbegin(), e = restart.cend(); i != e; ++i) { for (QSet<int32>::const_iterator i = restart.cbegin(), e = restart.cend(); i != e; ++i) {
MTP::restart(*i); MTP::restart(*i);
} }
} }
namespace {
QReadWriteLock _dcOptionsMutex;
}
QReadWriteLock *mtpDcOptionsMutex() {
return &_dcOptionsMutex;
}
MTProtoConfigLoader::MTProtoConfigLoader() : _enumCurrent(0), _enumRequest(0) { MTProtoConfigLoader::MTProtoConfigLoader() : _enumCurrent(0), _enumRequest(0) {
connect(&_enumDCTimer, SIGNAL(timeout()), this, SLOT(enumDC())); connect(&_enumDCTimer, SIGNAL(timeout()), this, SLOT(enumDC()));
connect(this, SIGNAL(killCurrentSession(qint32,qint32)), this, SLOT(onKillCurrentSession(qint32,qint32)), Qt::QueuedConnection);
} }
void MTProtoConfigLoader::load() { void MTProtoConfigLoader::load() {
@ -189,23 +217,15 @@ void MTProtoConfigLoader::load() {
_enumDCTimer.start(MTPEnumDCTimeout); _enumDCTimer.start(MTPEnumDCTimeout);
} }
void MTProtoConfigLoader::onKillCurrentSession(qint32 request, qint32 current) {
if (request == _enumRequest && current == _enumCurrent) {
if (_enumRequest) {
MTP::cancel(_enumRequest);
_enumRequest = 0;
}
if (_enumCurrent) {
MTP::killSession(MTP::cfg + _enumCurrent);
_enumCurrent = 0;
}
}
}
void MTProtoConfigLoader::done() { void MTProtoConfigLoader::done() {
_enumDCTimer.stop(); _enumDCTimer.stop();
if (_enumRequest || _enumCurrent) { if (_enumRequest) {
emit killCurrentSession(_enumRequest, _enumCurrent); MTP::cancel(_enumRequest);
_enumRequest = 0;
}
if (_enumCurrent) {
MTP::killSession(MTP::cfg + _enumCurrent);
_enumCurrent = 0;
} }
emit loaded(); emit loaded();
} }
@ -220,14 +240,16 @@ void MTProtoConfigLoader::enumDC() {
} else { } else {
MTP::killSession(MTP::cfg + _enumCurrent); MTP::killSession(MTP::cfg + _enumCurrent);
} }
const mtpDcOptions &options(cDcOptions()); {
for (mtpDcOptions::const_iterator i = options.cbegin(), e = options.cend(); i != e; ++i) { QReadLocker lock(mtpDcOptionsMutex());
if (i.key() == _enumCurrent) { const mtpDcOptions &options(cDcOptions());
_enumCurrent = (++i == e) ? options.cbegin().key() : i.key(); for (mtpDcOptions::const_iterator i = options.cbegin(), e = options.cend(); i != e; ++i) {
break; if (i.key() == _enumCurrent) {
_enumCurrent = (++i == e) ? options.cbegin().key() : i.key();
break;
}
} }
} }
_enumRequest = MTP::send(MTPhelp_GetConfig(), rpcDone(configLoaded), rpcFail(configFailed), MTP::cfg + _enumCurrent); _enumRequest = MTP::send(MTPhelp_GetConfig(), rpcDone(configLoaded), rpcFail(configFailed), MTP::cfg + _enumCurrent);
_enumDCTimer.start(MTPEnumDCTimeout); _enumDCTimer.start(MTPEnumDCTimeout);

View File

@ -72,12 +72,10 @@ public:
public slots: public slots:
void enumDC(); void enumDC();
void onKillCurrentSession(qint32 request, qint32 session);
signals: signals:
void loaded(); void loaded();
void killCurrentSession(qint32 request, qint32 session);
private: private:
@ -104,3 +102,4 @@ mtpKeysMap mtpGetKeys();
void mtpSetKey(int32 dc, mtpAuthKeyPtr key); void mtpSetKey(int32 dc, mtpAuthKeyPtr key);
void mtpUpdateDcOptions(const QVector<MTPDcOption> &options); void mtpUpdateDcOptions(const QVector<MTPDcOption> &options);
QReadWriteLock *mtpDcOptionsMutex();

View File

@ -63,11 +63,15 @@ void MTPSessionData::clear() {
} }
MTProtoSession::MTProtoSession() : data(this), dcId(0), dc(0), msSendCall(0), msWait(0), _ping(false) { MTProtoSession::MTProtoSession() : _killed(false), data(this), dcWithShift(0), dc(0), msSendCall(0), msWait(0), _ping(false) {
} }
void MTProtoSession::start(int32 dcenter) { void MTProtoSession::start(int32 dcenter) {
if (dcId) { if (_killed) {
DEBUG_LOG(("Session Error: can't start a killed session"));
return;
}
if (dcWithShift) {
DEBUG_LOG(("Session Info: MTProtoSession::start called on already started session")); DEBUG_LOG(("Session Info: MTProtoSession::start called on already started session"));
return; return;
} }
@ -84,8 +88,8 @@ void MTProtoSession::start(int32 dcenter) {
connections.reserve(cConnectionsInSession()); connections.reserve(cConnectionsInSession());
for (uint32 i = 0; i < cConnectionsInSession(); ++i) { for (uint32 i = 0; i < cConnectionsInSession(); ++i) {
connections.push_back(new MTProtoConnection()); connections.push_back(new MTProtoConnection());
dcId = connections.back()->start(&data, dcenter); dcWithShift = connections.back()->start(&data, dcenter);
if (!dcId) { if (!dcWithShift) {
for (MTProtoConnections::const_iterator j = connections.cbegin(), e = connections.cend(); j != e; ++j) { for (MTProtoConnections::const_iterator j = connections.cbegin(), e = connections.cend(); j != e; ++j) {
delete *j; delete *j;
} }
@ -94,11 +98,12 @@ void MTProtoSession::start(int32 dcenter) {
return; return;
} }
if (!dc) { if (!dc) {
dcenter = dcId; dcenter = dcWithShift;
MTProtoDCMap::const_iterator dcIndex = dcs.constFind(dcId % _mtp_internal::dcShift); int32 dcId = dcWithShift % _mtp_internal::dcShift;
MTProtoDCMap::const_iterator dcIndex = dcs.constFind(dcId);
if (dcIndex == dcs.cend()) { if (dcIndex == dcs.cend()) {
dc = MTProtoDCPtr(new MTProtoDC(dcId % _mtp_internal::dcShift, mtpAuthKeyPtr())); dc = MTProtoDCPtr(new MTProtoDC(dcId, mtpAuthKeyPtr()));
dcs.insert(dcId % _mtp_internal::dcShift, dc); dcs.insert(dcWithShift % _mtp_internal::dcShift, dc);
} else { } else {
dc = dcIndex.value(); dc = dcIndex.value();
} }
@ -115,18 +120,32 @@ void MTProtoSession::start(int32 dcenter) {
} }
void MTProtoSession::restart() { void MTProtoSession::restart() {
if (_killed) {
DEBUG_LOG(("Session Error: can't restart a killed session"));
return;
}
emit needToRestart(); emit needToRestart();
} }
void MTProtoSession::stop() { void MTProtoSession::stop() {
DEBUG_LOG(("Session Info: stopping session %1").arg(dcId)); DEBUG_LOG(("Session Info: stopping session dcWithShift %1").arg(dcWithShift));
while (!connections.isEmpty()) { while (!connections.isEmpty()) {
connections.back()->stop(); connections.back()->stop();
connections.pop_back(); connections.pop_back();
} }
} }
void MTProtoSession::kill() {
stop();
_killed = true;
DEBUG_LOG(("Session Info: marked session dcWithShift %1 as killed").arg(dcWithShift));
}
void MTProtoSession::sendAnything(quint64 msCanWait) { void MTProtoSession::sendAnything(quint64 msCanWait) {
if (_killed) {
DEBUG_LOG(("Session Error: can't send anything in a killed session"));
return;
}
uint64 ms = getms(true); uint64 ms = getms(true);
if (msSendCall) { if (msSendCall) {
if (ms > msSendCall + msWait) { if (ms > msSendCall + msWait) {
@ -141,11 +160,11 @@ void MTProtoSession::sendAnything(quint64 msCanWait) {
msWait = msCanWait; msWait = msCanWait;
} }
if (msWait) { if (msWait) {
DEBUG_LOG(("MTP Info: dc %1 can wait for %2ms from current %3").arg(dcId).arg(msWait).arg(msSendCall)); DEBUG_LOG(("MTP Info: dcWithShift %1 can wait for %2ms from current %3").arg(dcWithShift).arg(msWait).arg(msSendCall));
msSendCall = ms; msSendCall = ms;
sender.start(msWait); sender.start(msWait);
} else { } else {
DEBUG_LOG(("MTP Info: dc %1 stopped send timer, can wait for %2ms from current %3").arg(dcId).arg(msWait).arg(msSendCall)); DEBUG_LOG(("MTP Info: dcWithShift %1 stopped send timer, can wait for %2ms from current %3").arg(dcWithShift).arg(msWait).arg(msSendCall));
sender.stop(); sender.stop();
msSendCall = 0; msSendCall = 0;
needToResumeAndSend(); needToResumeAndSend();
@ -153,20 +172,24 @@ void MTProtoSession::sendAnything(quint64 msCanWait) {
} }
void MTProtoSession::needToResumeAndSend() { void MTProtoSession::needToResumeAndSend() {
if (_killed) {
DEBUG_LOG(("Session Info: can't resume a killed session"));
return;
}
if (connections.isEmpty()) { if (connections.isEmpty()) {
DEBUG_LOG(("Session Info: resuming session %1").arg(dcId)); DEBUG_LOG(("Session Info: resuming session dcWithShift %1").arg(dcWithShift));
MTProtoDCMap &dcs(mtpDCMap()); MTProtoDCMap &dcs(mtpDCMap());
connections.reserve(cConnectionsInSession()); connections.reserve(cConnectionsInSession());
for (uint32 i = 0; i < cConnectionsInSession(); ++i) { for (uint32 i = 0; i < cConnectionsInSession(); ++i) {
connections.push_back(new MTProtoConnection()); connections.push_back(new MTProtoConnection());
if (!connections.back()->start(&data, dcId)) { if (!connections.back()->start(&data, dcWithShift)) {
for (MTProtoConnections::const_iterator j = connections.cbegin(), e = connections.cend(); j != e; ++j) { for (MTProtoConnections::const_iterator j = connections.cbegin(), e = connections.cend(); j != e; ++j) {
delete *j; delete *j;
} }
connections.clear(); connections.clear();
DEBUG_LOG(("Session Info: could not start connection %1 to dc %2").arg(i).arg(dcId)); DEBUG_LOG(("Session Info: could not start connection %1 to dcWithShift %2").arg(i).arg(dcWithShift));
dcId = 0; dcWithShift = 0;
return; return;
} }
} }
@ -259,11 +282,11 @@ void MTProtoSession::checkRequestsByTimer() {
} }
void MTProtoSession::onConnectionStateChange(qint32 newState) { void MTProtoSession::onConnectionStateChange(qint32 newState) {
_mtp_internal::onStateChange(dcId, newState); _mtp_internal::onStateChange(dcWithShift, newState);
} }
void MTProtoSession::onResetDone() { void MTProtoSession::onResetDone() {
_mtp_internal::onSessionReset(dcId); _mtp_internal::onSessionReset(dcWithShift);
} }
void MTProtoSession::cancel(mtpRequestId requestId, mtpMsgId msgId) { void MTProtoSession::cancel(mtpRequestId requestId, mtpMsgId msgId) {
@ -428,23 +451,23 @@ QReadWriteLock *MTProtoSession::keyMutex() const {
} }
void MTProtoSession::authKeyCreatedForDC() { void MTProtoSession::authKeyCreatedForDC() {
DEBUG_LOG(("AuthKey Info: MTProtoSession::authKeyCreatedForDC slot, emitting authKeyCreated(), dc %1").arg(dcId)); DEBUG_LOG(("AuthKey Info: MTProtoSession::authKeyCreatedForDC slot, emitting authKeyCreated(), dcWithShift %1").arg(dcWithShift));
data.setKey(dc->getKey()); data.setKey(dc->getKey());
emit authKeyCreated(); emit authKeyCreated();
} }
void MTProtoSession::notifyKeyCreated(const mtpAuthKeyPtr &key) { void MTProtoSession::notifyKeyCreated(const mtpAuthKeyPtr &key) {
DEBUG_LOG(("AuthKey Info: MTProtoSession::keyCreated(), setting, dc %1").arg(dcId)); DEBUG_LOG(("AuthKey Info: MTProtoSession::keyCreated(), setting, dcWithShift %1").arg(dcWithShift));
dc->setKey(key); dc->setKey(key);
} }
void MTProtoSession::layerWasInitedForDC(bool wasInited) { void MTProtoSession::layerWasInitedForDC(bool wasInited) {
DEBUG_LOG(("MTP Info: MTProtoSession::layerWasInitedForDC slot, dc %1").arg(dcId)); DEBUG_LOG(("MTP Info: MTProtoSession::layerWasInitedForDC slot, dcWithShift %1").arg(dcWithShift));
data.setLayerWasInited(wasInited); data.setLayerWasInited(wasInited);
} }
void MTProtoSession::notifyLayerInited(bool wasInited) { void MTProtoSession::notifyLayerInited(bool wasInited) {
DEBUG_LOG(("MTP Info: emitting MTProtoDC::layerWasInited(%1), dc %2").arg(logBool(wasInited)).arg(dcId)); DEBUG_LOG(("MTP Info: emitting MTProtoDC::layerWasInited(%1), dcWithShift %2").arg(logBool(wasInited)).arg(dcWithShift));
dc->setConnectionInited(wasInited); dc->setConnectionInited(wasInited);
emit dc->layerWasInited(wasInited); emit dc->layerWasInited(wasInited);
} }
@ -453,7 +476,7 @@ void MTProtoSession::destroyKey() {
if (!dc) return; if (!dc) return;
if (data.getKey()) { if (data.getKey()) {
DEBUG_LOG(("MTP Info: destroying auth_key for dc %1").arg(dcId)); DEBUG_LOG(("MTP Info: destroying auth_key for dcWithShift %1").arg(dcWithShift));
if (data.getKey() == dc->getKey()) { if (data.getKey() == dc->getKey()) {
dc->destroyKey(); dc->destroyKey();
} }
@ -461,8 +484,8 @@ void MTProtoSession::destroyKey() {
} }
} }
int32 MTProtoSession::getDC() const { int32 MTProtoSession::getDcWithShift() const {
return dcId; return dcWithShift;
} }
void MTProtoSession::tryToReceive() { void MTProtoSession::tryToReceive() {
@ -481,7 +504,7 @@ void MTProtoSession::tryToReceive() {
responses.erase(i); responses.erase(i);
} }
if (requestId <= 0) { if (requestId <= 0) {
if (dcId < int(_mtp_internal::dcShift)) { // call globalCallback only in main session if (dcWithShift < int(_mtp_internal::dcShift)) { // call globalCallback only in main session
_mtp_internal::globalCallback(response.constData(), response.constData() + response.size()); _mtp_internal::globalCallback(response.constData(), response.constData() + response.size());
} }
} else { } else {

View File

@ -224,8 +224,9 @@ public:
void start(int32 dcenter = 0); void start(int32 dcenter = 0);
void restart(); void restart();
void stop(); void stop();
void kill();
int32 getDC() const; int32 getDcWithShift() const;
~MTProtoSession(); ~MTProtoSession();
QReadWriteLock *keyMutex() const; QReadWriteLock *keyMutex() const;
@ -275,10 +276,12 @@ private:
typedef QList<MTProtoConnection*> MTProtoConnections; typedef QList<MTProtoConnection*> MTProtoConnections;
MTProtoConnections connections; MTProtoConnections connections;
bool _killed;
MTPSessionData data; MTPSessionData data;
int32 dcId; int32 dcWithShift;
MTProtoDCPtr dc; MTProtoDCPtr dc;
uint64 msSendCall, msWait; uint64 msSendCall, msWait;

View File

@ -37,6 +37,6 @@ mtpRequestId MTProtoSession::send(const TRequest &request, RPCResponseHandler ca
requestId = 0; requestId = 0;
_mtp_internal::rpcErrorOccured(requestId, callbacks, rpcClientError("NO_REQUEST_ID", QString("send() failed to queue request, exception: %1").arg(e.what()))); _mtp_internal::rpcErrorOccured(requestId, callbacks, rpcClientError("NO_REQUEST_ID", QString("send() failed to queue request, exception: %1").arg(e.what())));
} }
if (requestId) _mtp_internal::registerRequest(requestId, toMainDC ? -getDC() : getDC()); if (requestId) _mtp_internal::registerRequest(requestId, toMainDC ? -getDcWithShift() : getDcWithShift());
return requestId; return requestId;
} }