From 5ce2e2b219a79b88a45b624376823a288157cfd3 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 1 Aug 2014 22:49:43 +0400 Subject: [PATCH] prepared 0.5.13 - greatly improved network support (bad_msg_notification handle, connecting notification, dc full config embed, getting config each launch, dc option notify handle, enum dc for new config --- Telegram/PrepareLinux.sh | 4 +- Telegram/PrepareLinux32.sh | 4 +- Telegram/PrepareMac.sh | 4 +- Telegram/Setup.iss | 6 +- Telegram/SourceFiles/application.cpp | 7 ++ Telegram/SourceFiles/config.h | 32 +++++- Telegram/SourceFiles/dialogswidget.cpp | 14 +-- Telegram/SourceFiles/dialogswidget.h | 3 - Telegram/SourceFiles/gui/boxshadow.cpp | 8 +- Telegram/SourceFiles/mainwidget.cpp | 5 + Telegram/SourceFiles/mtproto/mtp.cpp | 43 +++++++- Telegram/SourceFiles/mtproto/mtp.h | 7 ++ .../SourceFiles/mtproto/mtpConnection.cpp | 3 + Telegram/SourceFiles/mtproto/mtpConnection.h | 1 + Telegram/SourceFiles/mtproto/mtpDC.cpp | 104 ++++++++++++++---- Telegram/SourceFiles/mtproto/mtpDC.h | 15 +++ Telegram/SourceFiles/mtproto/mtpRPC.h | 1 + Telegram/SourceFiles/mtproto/mtpSession.cpp | 4 + Telegram/SourceFiles/mtproto/mtpSession.h | 1 + Telegram/SourceFiles/pspecific_wnd.cpp | 58 +++++++++- Telegram/SourceFiles/pspecific_wnd.h | 2 +- Telegram/SourceFiles/window.cpp | 2 + Telegram/Telegram.plist | 2 +- Telegram/Telegram.rc | Bin 5566 -> 5566 bytes Telegram/Telegram.xcodeproj/project.pbxproj | 12 +- 25 files changed, 266 insertions(+), 76 deletions(-) diff --git a/Telegram/PrepareLinux.sh b/Telegram/PrepareLinux.sh index 787684726..67618a7c8 100755 --- a/Telegram/PrepareLinux.sh +++ b/Telegram/PrepareLinux.sh @@ -1,5 +1,5 @@ -AppVersionStr=0.5.12 -AppVersion=5012 +AppVersionStr=0.5.13 +AppVersion=5013 if [ -d "./../Linux/Release/deploy/$AppVersionStr" ]; then echo "Deploy folder for version $AppVersionStr already exists!" diff --git a/Telegram/PrepareLinux32.sh b/Telegram/PrepareLinux32.sh index 4b0e9af46..a3b17f2f2 100755 --- a/Telegram/PrepareLinux32.sh +++ b/Telegram/PrepareLinux32.sh @@ -1,5 +1,5 @@ -AppVersionStr=0.5.12 -AppVersion=5012 +AppVersionStr=0.5.13 +AppVersion=5013 if [ -d "./../Linux/Release/deploy/$AppVersionStr" ]; then echo "Deploy folder for version $AppVersionStr already exists!" diff --git a/Telegram/PrepareMac.sh b/Telegram/PrepareMac.sh index 815cce9e7..cfe8bddc7 100755 --- a/Telegram/PrepareMac.sh +++ b/Telegram/PrepareMac.sh @@ -1,5 +1,5 @@ -AppVersionStr=0.5.12 -AppVersion=5012 +AppVersionStr=0.5.13 +AppVersion=5013 if [ -d "./../Mac/Release/deploy/$AppVersionStr" ]; then echo "Deploy folder for version $AppVersionStr already exists!" diff --git a/Telegram/Setup.iss b/Telegram/Setup.iss index 4f97c3832..a27580d90 100644 --- a/Telegram/Setup.iss +++ b/Telegram/Setup.iss @@ -3,9 +3,9 @@ #define MyAppShortName "Telegram" #define MyAppName "Telegram Win (Unofficial)" -#define MyAppVersion "0.5.12" -#define MyAppVersionZero "0.5.12" -#define MyAppFullVersion "0.5.12.0" +#define MyAppVersion "0.5.13" +#define MyAppVersionZero "0.5.13" +#define MyAppFullVersion "0.5.13.0" #define MyAppPublisher "Telegram (Unofficial)" #define MyAppURL "https://tdesktop.com" #define MyAppExeName "Telegram.exe" diff --git a/Telegram/SourceFiles/application.cpp b/Telegram/SourceFiles/application.cpp index 0ab1ac016..319d4bbbc 100644 --- a/Telegram/SourceFiles/application.cpp +++ b/Telegram/SourceFiles/application.cpp @@ -39,6 +39,12 @@ namespace { } } + void mtpSessionReset(int32 dc) { + if (App::main() && dc == MTP::maindc()) { + App::main()->getDifference(); + } + } + class _DebugWaiter : public QObject { public: @@ -569,6 +575,7 @@ void Application::startApp() { MTP::start(); MTP::setStateChangedHandler(mtpStateChanged); + MTP::setSessionResetHandler(mtpSessionReset); App::initMedia(); diff --git a/Telegram/SourceFiles/config.h b/Telegram/SourceFiles/config.h index 886c85538..15e5fc232 100644 --- a/Telegram/SourceFiles/config.h +++ b/Telegram/SourceFiles/config.h @@ -17,8 +17,8 @@ Copyright (c) 2014 John Preston, https://tdesktop.com */ #pragma once -static const int32 AppVersion = 5012; -static const wchar_t *AppVersionStr = L"0.5.12"; +static const int32 AppVersion = 5013; +static const wchar_t *AppVersionStr = L"0.5.13"; #ifdef Q_OS_WIN static const wchar_t *AppName = L"Telegram Win (Unofficial)"; #else @@ -42,6 +42,8 @@ enum { MTPTcpConnectionWaitTimeout = 3000, // 3 seconds waiting for tcp, until we accept http MTPMillerRabinIterCount = 30, // 30 Miller-Rabin iterations for dh_prime primality check + MTPEnumDCTimeout = 4000, // 4 seconds timeout for help_getConfig to work (them move to other dc) + MinReceiveDelay = 1000, // 1 seconds MaxSelectedItems = 100, @@ -94,12 +96,30 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB\n\ return keys; } -inline const char *cFirstDCIp() { - return cTestMode() ? "173.240.5.253" : "173.240.5.1"; +struct BuiltInDc { + int id; + const char *ip; + int port; +}; + +static const BuiltInDc _builtInDcs[] = { + { 1, "173.240.5.1", 443 }, + { 2, "149.154.167.50", 443 }, + { 3, "174.140.142.6", 443 }, + { 4, "149.154.167.90", 443 }, + { 5, "116.51.22.2", 443 } +}; + +static const BuiltInDc _builtInTestDcs[] = { + { 1, "173.240.5.253", 443 } +}; + +inline const BuiltInDc *builtInDcs() { + return cTestMode() ? _builtInTestDcs : _builtInDcs; } -inline int32 cFirstDCPort() { - return 443; +inline int builtInDcsCount() { + return (cTestMode() ? sizeof(_builtInTestDcs) : sizeof(_builtInDcs)) / sizeof(BuiltInDc); } static const char *UpdatesPublicKey = "\ diff --git a/Telegram/SourceFiles/dialogswidget.cpp b/Telegram/SourceFiles/dialogswidget.cpp index b85a38428..56f7b16b9 100644 --- a/Telegram/SourceFiles/dialogswidget.cpp +++ b/Telegram/SourceFiles/dialogswidget.cpp @@ -906,7 +906,6 @@ DialogsListWidget::SearchResults &DialogsListWidget::searchList() { } DialogsWidget::DialogsWidget(MainWidget *parent) : QWidget(parent) -, _configLoaded(false) , _drawShadow(true) , dlgOffset(0) , dlgCount(-1) @@ -1070,7 +1069,6 @@ void DialogsWidget::dialogsReceived(const MTPmessages_Dialogs &dialogs) { } } else { dlgCount = dlgOffset; - loadConfig(); } dlgPreloading = 0; @@ -1137,19 +1135,9 @@ void DialogsWidget::onSearchMore(MsgId minMsgId) { } } -void DialogsWidget::loadConfig() { - if (!_configLoaded) { - mtpConfigLoader()->load(); - _configLoaded = true; - } -} - void DialogsWidget::loadDialogs() { if (dlgPreloading) return; - if (dlgCount >= 0 && dlgOffset >= dlgCount) { - loadConfig(); - return; - } + if (dlgCount >= 0 && dlgOffset >= dlgCount) return; int32 loadCount = dlgOffset ? DialogsPerPage : DialogsFirstLoad; dlgPreloading = MTP::send(MTPmessages_GetDialogs(MTP_int(dlgOffset), MTP_int(0), MTP_int(loadCount)), rpcDone(&DialogsWidget::dialogsReceived), rpcFail(&DialogsWidget::dialogsFailed)); diff --git a/Telegram/SourceFiles/dialogswidget.h b/Telegram/SourceFiles/dialogswidget.h index 5355c44de..59ef5e396 100644 --- a/Telegram/SourceFiles/dialogswidget.h +++ b/Telegram/SourceFiles/dialogswidget.h @@ -195,9 +195,6 @@ public slots: private: - void loadConfig(); - bool _configLoaded; - bool _drawShadow; void unreadCountsReceived(const QVector &dialogs); diff --git a/Telegram/SourceFiles/gui/boxshadow.cpp b/Telegram/SourceFiles/gui/boxshadow.cpp index f90e06413..0ab919852 100644 --- a/Telegram/SourceFiles/gui/boxshadow.cpp +++ b/Telegram/SourceFiles/gui/boxshadow.cpp @@ -66,9 +66,9 @@ void BoxShadow::paint(QPainter &p, const QRect &box, const QPoint &shift, int32 if (left && bottom) p.drawPixmap(box.left() - _size + minus + shift.x(), box.bottom() - minus + 1 + shift.y(), _corners, 0, _size, _size, _size); for (int32 i = 1; i <= count; ++i) { p.setPen(_colors[i - 1]->p); - if (top) p.fillRect(box.left() + (left ? minus : 0) + shift.x(), box.top() - count + i + shift.y(), box.width() - (right ? minus : 0) - (left ? minus : 0), st::lineWidth, _colors[i - 1]->b); - if (right) p.fillRect(box.right() + count - i + shift.x(), box.top() + (top ? minus : 0) + shift.y(), st::lineWidth, box.height() - (bottom ? minus : 0) - (top ? minus : 0), _colors[i - 1]->b); - if (bottom) p.fillRect(box.left() + (left ? minus : 0) + shift.x(), box.bottom() + count - i + shift.y(), box.width() - (right ? minus : 0) - (left ? minus : 0), st::lineWidth, _colors[i - 1]->b); - if (left) p.fillRect(box.left() - count + i + shift.x(), box.top() + (top ? minus : 0) + shift.y(), st::lineWidth, box.height() - (bottom ? minus : 0) - (top ? minus : 0), _colors[i - 1]->b); + if (top) p.fillRect(box.left() + (left ? minus : 0) + shift.x(), box.top() - count + i + shift.y(), box.width() - (right ? minus : 0) - (left ? minus : 0), cIntRetinaFactor(), _colors[i - 1]->b); + if (right) p.fillRect(box.right() + count - i + shift.x(), box.top() + (top ? minus : 0) + shift.y(), cIntRetinaFactor(), box.height() - (bottom ? minus : 0) - (top ? minus : 0), _colors[i - 1]->b); + if (bottom) p.fillRect(box.left() + (left ? minus : 0) + shift.x(), box.bottom() + count - i + shift.y(), box.width() - (right ? minus : 0) - (left ? minus : 0), cIntRetinaFactor(), _colors[i - 1]->b); + if (left) p.fillRect(box.left() - count + i + shift.x(), box.top() + (top ? minus : 0) + shift.y(), cIntRetinaFactor(), box.height() - (bottom ? minus : 0) - (top ? minus : 0), _colors[i - 1]->b); } } diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 8fbf9ec77..7486c7ff2 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -1734,5 +1734,10 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { const MTPDupdateNotifySettings &d(update.c_updateNotifySettings()); applyNotifySetting(d.vpeer, d.vnotify_settings); } break; + + case mtpc_updateDcOptions: { + const MTPDupdateDcOptions &d(update.c_updateDcOptions()); + MTP::updateDcOptions(d.vdc_options.c_vector().v); + } break; } } diff --git a/Telegram/SourceFiles/mtproto/mtp.cpp b/Telegram/SourceFiles/mtproto/mtp.cpp index 1d257571d..3b45e3cd1 100644 --- a/Telegram/SourceFiles/mtproto/mtp.cpp +++ b/Telegram/SourceFiles/mtproto/mtp.cpp @@ -53,6 +53,7 @@ namespace { RPCResponseHandler globalHandler; MTPStateChangedHandler stateChangedHandler = 0; + MTPSessionResetHandler sessionResetHandler = 0; _mtp_internal::RequestResender *resender = 0; mtpAuthKey _localKey; @@ -342,6 +343,9 @@ namespace _mtp_internal { void execCallback(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) { ParserMap::iterator i = parserMap.find(requestId); if (i != parserMap.cend()) { + RPCResponseHandler h(i.value()); + parserMap.erase(i); + DEBUG_LOG(("RPC Info: found parser for request %1, trying to parse response..").arg(requestId)); try { if (from >= end) throw mtpErrorInsufficient(); @@ -349,18 +353,17 @@ namespace _mtp_internal { if (*from == mtpc_rpc_error) { RPCError err(MTPRpcError(from, end)); DEBUG_LOG(("RPC Info: error received, code %1, type %2, description: %3").arg(err.code()).arg(err.type()).arg(err.description())); - if (!rpcErrorOccured(requestId, i.value(), err)) { + if (!rpcErrorOccured(requestId, h, err)) { return; } } else { - if (i.value().onDone) (*i.value().onDone)(requestId, from, end); + if (h.onDone) (*h.onDone)(requestId, from, end); } } catch (Exception &e) { - if (!rpcErrorOccured(requestId, i.value(), rpcClientError("RESPONSE_PARSE_FAILED", QString("exception text: ") + e.what()))) { + if (!rpcErrorOccured(requestId, h, rpcClientError("RESPONSE_PARSE_FAILED", QString("exception text: ") + e.what()))) { return; } } - parserMap.erase(i); requestMap.remove(requestId); } else { DEBUG_LOG(("RPC Info: parser not found for %1").arg(requestId)); @@ -376,6 +379,10 @@ namespace _mtp_internal { if (stateChangedHandler) stateChangedHandler(dc, state); } + void onSessionReset(int32 dc) { + if (sessionResetHandler) sessionResetHandler(dc); + } + bool rpcErrorOccured(mtpRequestId requestId, const RPCFailHandlerPtr &onFail, const RPCError &err) { // return true if need to clean request data if (onErrorDefault(requestId, err)) { return false; @@ -469,6 +476,15 @@ namespace MTP { (*i)->restart(); } } + void restart(int32 dcMask) { + if (!started) return; + + for (Sessions::const_iterator i = sessions.cbegin(), e = sessions.cend(); i != e; ++i) { + if ((*i)->getDC() % _mtp_internal::dcShift == dcMask % _mtp_internal::dcShift) { + (*i)->restart(); + } + } + } void setLayer(uint32 l) { if (l > mtpLayerMax) { @@ -538,6 +554,14 @@ namespace MTP { _mtp_internal::clearCallbacks(requestId); } + void killSession(int32 dc) { + Sessions::iterator i = sessions.find(dc); + if (i != sessions.end()) { + i.value()->stop(); + sessions.erase(i); + } + } + int32 state(mtpRequestId requestId) { if (requestId > 0) { QMutexLocker locker(&requestByDCLock); @@ -556,6 +580,7 @@ namespace MTP { } delete resender; resender = 0; + mtpDestroyConfigLoader(); } void authed(int32 uid) { @@ -583,10 +608,20 @@ namespace MTP { stateChangedHandler = handler; } + void setSessionResetHandler(MTPSessionResetHandler handler) { + sessionResetHandler = handler; + } + void clearGlobalHandlers() { setGlobalDoneHandler(RPCDoneHandlerPtr()); setGlobalFailHandler(RPCFailHandlerPtr()); setStateChangedHandler(0); + setSessionResetHandler(0); + } + + void updateDcOptions(const QVector &options) { + mtpUpdateDcOptions(options); + App::writeUserConfig(); } void writeConfig(QDataStream &stream) { diff --git a/Telegram/SourceFiles/mtproto/mtp.h b/Telegram/SourceFiles/mtproto/mtp.h index d29114f3e..a815f229f 100644 --- a/Telegram/SourceFiles/mtproto/mtp.h +++ b/Telegram/SourceFiles/mtproto/mtp.h @@ -38,6 +38,7 @@ namespace _mtp_internal { void execCallback(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end); void globalCallback(const mtpPrime *from, const mtpPrime *end); void onStateChange(int32 dc, int32 state); + void onSessionReset(int32 dc); 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) { return rpcErrorOccured(requestId, handler.onFail, err); @@ -59,9 +60,11 @@ namespace MTP { static const uint32 dld = 1 * _mtp_internal::dcShift; // send(req, callbacks, MTP::dld + dc) - for download static const uint32 upl = 2 * _mtp_internal::dcShift; // send(req, callbacks, MTP::upl + dc) - for upload + static const uint32 cfg = 3 * _mtp_internal::dcShift; // send(MTPhelp_GetConfig(), MTP::cfg + dc) - for dc enum void start(); void restart(); + void restart(int32 dcMask); void setLayer(uint32 layer); @@ -79,6 +82,7 @@ namespace MTP { return send(request, RPCResponseHandler(onDone, onFail), dc, msCanWait); } void cancel(mtpRequestId req); + void killSession(int32 dc); enum { RequestSent = 0, @@ -98,8 +102,11 @@ namespace MTP { void setGlobalDoneHandler(RPCDoneHandlerPtr handler); void setGlobalFailHandler(RPCFailHandlerPtr handler); void setStateChangedHandler(MTPStateChangedHandler handler); + void setSessionResetHandler(MTPSessionResetHandler handler); void clearGlobalHandlers(); + void updateDcOptions(const QVector &options); + template T nonce() { T result; diff --git a/Telegram/SourceFiles/mtproto/mtpConnection.cpp b/Telegram/SourceFiles/mtproto/mtpConnection.cpp index e68571499..a7c151ab0 100644 --- a/Telegram/SourceFiles/mtproto/mtpConnection.cpp +++ b/Telegram/SourceFiles/mtproto/mtpConnection.cpp @@ -1086,6 +1086,7 @@ MTProtoConnectionPrivate::MTProtoConnectionPrivate(QThread *thread, MTProtoConne connect(this, SIGNAL(needToReceive()), sessionData->owner(), SLOT(tryToReceive())); connect(this, SIGNAL(stateChanged(qint32)), sessionData->owner(), SLOT(onConnectionStateChange(qint32))); connect(sessionData->owner(), SIGNAL(needToSend()), this, SLOT(tryToSend())); + connect(this, SIGNAL(sessionResetDone()), sessionData->owner(), SLOT(onResetDone())); oldConnectionTimer.setSingleShot(true); connCheckTimer.setSingleShot(true); @@ -1247,6 +1248,8 @@ void MTProtoConnectionPrivate::resetSession() { // recreate all msg_id and msg_s } } } + + emit sessionResetDone(); } mtpMsgId MTProtoConnectionPrivate::prepareToSend(mtpRequest &request, mtpMsgId currentLastId) { diff --git a/Telegram/SourceFiles/mtproto/mtpConnection.h b/Telegram/SourceFiles/mtproto/mtpConnection.h index 4c243bc5f..9d384d87b 100644 --- a/Telegram/SourceFiles/mtproto/mtpConnection.h +++ b/Telegram/SourceFiles/mtproto/mtpConnection.h @@ -292,6 +292,7 @@ signals: void needToReceive(); void needToRestart(); void stateChanged(qint32 newState); + void sessionResetDone(); public slots: diff --git a/Telegram/SourceFiles/mtproto/mtpDC.cpp b/Telegram/SourceFiles/mtproto/mtpDC.cpp index 8319c27e9..07e5452ed 100644 --- a/Telegram/SourceFiles/mtproto/mtpDC.cpp +++ b/Telegram/SourceFiles/mtproto/mtpDC.cpp @@ -20,10 +20,10 @@ Copyright (c) 2014 John Preston, https://tdesktop.com #include "mtp.h" namespace { - + MTProtoDCMap gDCs; bool configLoadedOnce = false; - int32 mainDC = 1; + int32 mainDC = 2; int userId = 0; mtpDcOptions gDCOptions; @@ -201,13 +201,15 @@ namespace { int32 oldFound = readAuthKeys(keysFile); if (gDCOptions.isEmpty() || (mainDC && gDCOptions.find(mainDC) == gDCOptions.cend())) { // load first dc info - gDCOptions.insert(1, mtpDcOption(1, "", cFirstDCIp(), cFirstDCPort())); + const BuiltInDc *bdcs = builtInDcs(); + for (int i = 0, l = builtInDcsCount(); i < l; ++i) { + gDCOptions.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)); + } userId = 0; - mainDC = 0; - DEBUG_LOG(("MTP Info: first DC connect options: %1:%2").arg(cFirstDCIp()).arg(cFirstDCPort())); + mainDC = (gDCOptions.constFind(2) == gDCOptions.cend()) ? gDCOptions.begin().key() : 2; } else { - configLoadedOnce = true; - DEBUG_LOG(("MTP Info: config loaded, dc option count: %1").arg(gDCOptions.size())); + DEBUG_LOG(("MTP Info: config from local, dc option count: %1").arg(gDCOptions.size())); } if (oldFound > 0) { @@ -219,8 +221,11 @@ namespace { } } else { DEBUG_LOG(("MTP Info: could not open keys file for reading")); - gDCOptions.insert(1, mtpDcOption(1, "", cFirstDCIp(), cFirstDCPort())); - DEBUG_LOG(("MTP Info: first DC connect options: %1:%2").arg(cFirstDCIp()).arg(cFirstDCPort())); + const BuiltInDc *bdcs = builtInDcs(); + for (int i = 0, l = builtInDcsCount(); i < l; ++i) { + gDCOptions.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)); + } } } @@ -392,7 +397,7 @@ void MTProtoDC::destroyKey() { } namespace { - MTProtoConfigLoader configLoader; + MTProtoConfigLoader *configLoader = 0; bool loadingConfig = false; void configLoaded(const MTPConfig &result) { loadingConfig = false; @@ -401,21 +406,13 @@ namespace { DEBUG_LOG(("MTP Info: got config, chat_size_max: %1, date: %2, test_mode: %3, this_dc: %4, dc_options.length: %5").arg(data.vchat_size_max.v).arg(data.vdate.v).arg(data.vtest_mode.v).arg(data.vthis_dc.v).arg(data.vdc_options.c_vector().v.size())); - QSet already; - const QVector &options(data.vdc_options.c_vector().v); - for (QVector::const_iterator i = options.cbegin(), e = options.cend(); i != e; ++i) { - const MTPDdcOption &optData(i->c_dcOption()); - if (already.constFind(optData.vid.v) == already.cend()) { - already.insert(optData.vid.v); - gDCOptions.insert(optData.vid.v, mtpDcOption(optData.vid.v, optData.vhostname.c_string().v, optData.vip_address.c_string().v, optData.vport.v)); - } - } + mtpUpdateDcOptions(data.vdc_options.c_vector().v); cSetMaxGroupCount(data.vchat_size_max.v); configLoadedOnce = true; App::writeUserConfig(); - emit mtpConfigLoader()->loaded(); + mtpConfigLoader()->done(); } bool configFailed(const RPCError &err) { loadingConfig = false; @@ -424,16 +421,77 @@ namespace { } }; +void mtpUpdateDcOptions(const QVector &options) { + QSet already, restart; + for (QVector::const_iterator i = options.cbegin(), e = options.cend(); i != e; ++i) { + const MTPDdcOption &optData(i->c_dcOption()); + if (already.constFind(optData.vid.v) == already.cend()) { + already.insert(optData.vid.v); + mtpDcOptions::const_iterator a = gDCOptions.constFind(optData.vid.v); + if (a != gDCOptions.cend()) { + if (a.value().ip != optData.vip_address.c_string().v || a.value().port != optData.vport.v) { + restart.insert(optData.vid.v); + } + } + gDCOptions.insert(optData.vid.v, mtpDcOption(optData.vid.v, optData.vhostname.c_string().v, optData.vip_address.c_string().v, optData.vport.v)); + } + } + for (QSet::const_iterator i = restart.cbegin(), e = restart.cend(); i != e; ++i) { + MTP::restart(*i); + } +} + +MTProtoConfigLoader::MTProtoConfigLoader() : _enumCurrent(0), _enumRequest(0) { + connect(&_enumDCTimer, SIGNAL(timeout()), this, SLOT(enumDC())); + _enumDCTimer.setSingleShot(true); +} + void MTProtoConfigLoader::load() { if (loadingConfig) return; loadingConfig = true; - MTPhelp_GetConfig request; - MTP::send(request, rpcDone(configLoaded), rpcFail(configFailed)); + MTP::send(MTPhelp_GetConfig(), rpcDone(configLoaded), rpcFail(configFailed)); + + _enumDCTimer.start(MTPEnumDCTimeout); +} + +void MTProtoConfigLoader::done() { + _enumDCTimer.stop(); + if (_enumRequest) MTP::cancel(_enumRequest); + if (_enumCurrent) MTP::killSession(_enumCurrent); + emit loaded(); +} + +void MTProtoConfigLoader::enumDC() { + if (!loadingConfig) return; + + if (_enumRequest) MTP::cancel(_enumRequest); + + if (!_enumCurrent) { + _enumCurrent = mainDC; + } else { + MTP::killSession(MTP::cfg + _enumCurrent); + } + for (mtpDcOptions::const_iterator i = gDCOptions.cbegin(), e = gDCOptions.cend(); i != e; ++i) { + if (i.key() == _enumCurrent) { + _enumCurrent = (++i == e) ? gDCOptions.cbegin().key() : i.key(); + break; + } + } + + _enumRequest = MTP::send(MTPhelp_GetConfig(), rpcDone(configLoaded), rpcFail(configFailed), MTP::cfg + _enumCurrent); + + _enumDCTimer.start(MTPEnumDCTimeout); } MTProtoConfigLoader *mtpConfigLoader() { - return &configLoader; + if (!configLoader) configLoader = new MTProtoConfigLoader(); + return configLoader; +} + +void mtpDestroyConfigLoader() { + delete configLoader; + configLoader = 0; } void mtpWriteConfig(QDataStream &stream) { diff --git a/Telegram/SourceFiles/mtproto/mtpDC.h b/Telegram/SourceFiles/mtproto/mtpDC.h index 2f937d1e1..c19bd6239 100644 --- a/Telegram/SourceFiles/mtproto/mtpDC.h +++ b/Telegram/SourceFiles/mtproto/mtpDC.h @@ -83,15 +83,28 @@ class MTProtoConfigLoader : public QObject { public: + MTProtoConfigLoader(); void load(); + void done(); + +public slots: + + void enumDC(); signals: void loaded(); +private: + + QTimer _enumDCTimer; + int32 _enumCurrent; + mtpRequestId _enumRequest; + }; MTProtoConfigLoader *mtpConfigLoader(); +void mtpDestroyConfigLoader(); const mtpDcOptions &mtpDCOptions(); MTProtoDCMap &mtpDCMap(); @@ -108,3 +121,5 @@ void mtpAuthed(int32 uid); void mtpWriteConfig(QDataStream &stream); bool mtpReadConfigElem(int32 blockId, QDataStream &stream); + +void mtpUpdateDcOptions(const QVector &options); diff --git a/Telegram/SourceFiles/mtproto/mtpRPC.h b/Telegram/SourceFiles/mtproto/mtpRPC.h index 00a4f977d..837d75455 100644 --- a/Telegram/SourceFiles/mtproto/mtpRPC.h +++ b/Telegram/SourceFiles/mtproto/mtpRPC.h @@ -797,3 +797,4 @@ public: }; typedef void (*MTPStateChangedHandler)(int32 dcId, int32 state); +typedef void(*MTPSessionResetHandler)(int32 dcId); diff --git a/Telegram/SourceFiles/mtproto/mtpSession.cpp b/Telegram/SourceFiles/mtproto/mtpSession.cpp index 0a69076bb..0b650ad0b 100644 --- a/Telegram/SourceFiles/mtproto/mtpSession.cpp +++ b/Telegram/SourceFiles/mtproto/mtpSession.cpp @@ -197,6 +197,10 @@ void MTProtoSession::onConnectionStateChange(qint32 newState) { _mtp_internal::onStateChange(dcId, newState); } +void MTProtoSession::onResetDone() { + _mtp_internal::onSessionReset(dcId); +} + void MTProtoSession::cancel(mtpRequestId requestId) { QWriteLocker locker(data.toSendMutex()); mtpPreRequestMap &toSend(data.toSendMap()); diff --git a/Telegram/SourceFiles/mtproto/mtpSession.h b/Telegram/SourceFiles/mtproto/mtpSession.h index bc64026c9..2ba95cb33 100644 --- a/Telegram/SourceFiles/mtproto/mtpSession.h +++ b/Telegram/SourceFiles/mtproto/mtpSession.h @@ -239,6 +239,7 @@ public slots: void tryToReceive(); void checkRequestsByTimer(); void onConnectionStateChange(qint32 newState); + void onResetDone(); private: diff --git a/Telegram/SourceFiles/pspecific_wnd.cpp b/Telegram/SourceFiles/pspecific_wnd.cpp index 6659da400..bc59d1a42 100644 --- a/Telegram/SourceFiles/pspecific_wnd.cpp +++ b/Telegram/SourceFiles/pspecific_wnd.cpp @@ -866,6 +866,7 @@ PsMainWindow::PsMainWindow(QWidget *parent) : QMainWindow(parent), ps_hWnd(0), p tbCreatedMsgId = RegisterWindowMessage(L"TaskbarButtonCreated"); icon16 = icon256.scaledToWidth(16, Qt::SmoothTransformation); icon32 = icon256.scaledToWidth(32, Qt::SmoothTransformation); + icon64 = icon256.scaledToWidth(64, Qt::SmoothTransformation); connect(&psIdleTimer, SIGNAL(timeout()), this, SLOT(psIdleTimeout())); psIdleTimer.setSingleShot(false); } @@ -986,9 +987,9 @@ void PsMainWindow::psUpdateCounter() { int32 counter = App::histories().unreadFull; style::color bg = (App::histories().unreadMuted < counter) ? st::counterBG : st::counterMuteBG; QIcon icon; - QImage cicon16(icon16), cicon32(icon32); + QImage cicon16(icon16), cicon32(icon32), cicon64(icon64); if (counter > 0) { - { + if (!tbListInterface) { QString cnt = (counter < 1000) ? QString("%1").arg(counter) : QString("..%1").arg(counter % 100, 2, 10, QChar('0')); QPainter p16(&cicon16); p16.setBrush(bg->b); @@ -1017,12 +1018,26 @@ void PsMainWindow::psUpdateCounter() { p32.setFont(f->f); p32.drawText(32 - w - d, f->ascent - 1, cnt); } + if (!tbListInterface) { + QString cnt = (counter < 10000) ? QString("%1").arg(counter) : ((counter < 1000000) ? QString("%1K").arg(counter / 1000) : QString("%1M").arg(counter / 1000000)); + QPainter p64(&cicon64); + style::font f(18); + int32 w = f->m.width(cnt), d = 6, r = 12; + p64.setBrush(bg->b); + p64.setPen(Qt::NoPen); + p64.setRenderHint(QPainter::Antialiasing); + p64.drawRoundedRect(QRect(64 - w - d * 2, 0, w + d * 2, f->height - 1), r, r); + p64.setPen(st::counterColor->p); + p64.setFont(f->f); + p64.drawText(64 - w - d, f->ascent - 1, cnt); + } } icon.addPixmap(QPixmap::fromImage(cicon16)); icon.addPixmap(QPixmap::fromImage(cicon32)); + icon.addPixmap(QPixmap::fromImage(cicon64)); if (trayIcon) { QIcon ticon; - QImage ticon16(icon16); + QImage ticon16(icon16), ticon32(icon32); if (counter > 0) { QString cnt = (counter < 1000) ? QString("%1").arg(counter) : QString("..%1").arg(counter % 100, 2, 10, QChar('0')); { @@ -1040,9 +1055,22 @@ void PsMainWindow::psUpdateCounter() { p16.drawText(16 - w - d, 16 - f->height + f->ascent, cnt); } + { + QString cnt = (counter < 10000) ? QString("%1").arg(counter) : ((counter < 1000000) ? QString("%1K").arg(counter / 1000) : QString("%1M").arg(counter / 1000000)); + QPainter p32(&ticon32); + style::font f(10); + int32 w = f->m.width(cnt), d = 3, r = 6; + p32.setBrush(bg->b); + p32.setPen(Qt::NoPen); + p32.setRenderHint(QPainter::Antialiasing); + p32.drawRoundedRect(QRect(32 - w - d * 2, 0, w + d * 2, f->height - 1), r, r); + p32.setPen(st::counterColor->p); + p32.setFont(f->f); + p32.drawText(32 - w - d, f->ascent - 1, cnt); + } } ticon.addPixmap(QPixmap::fromImage(ticon16)); - ticon.addPixmap(QPixmap::fromImage(cicon32)); + ticon.addPixmap(QPixmap::fromImage(ticon32)); trayIcon->setIcon(ticon); } @@ -1055,9 +1083,10 @@ void PsMainWindow::psUpdateCounter() { if (tbListInterface) { if (counter > 0) { QString cnt = (counter < 1000) ? QString("%1").arg(counter) : QString("..%1").arg(counter % 100, 2, 10, QChar('0')); - QImage oicon16(16, 16, QImage::Format_ARGB32); + QImage oicon16(16, 16, QImage::Format_ARGB32), oicon32(32, 32, QImage::Format_ARGB32); int32 cntSize = cnt.size(); oicon16.fill(st::transparent->c); + oicon32.fill(st::transparent->c); { QPainter p16(&oicon16); p16.setBrush(bg->b); @@ -1073,7 +1102,24 @@ void PsMainWindow::psUpdateCounter() { p16.drawText(16 - w - d, 16 - f->height + f->ascent, cnt); } - QIcon oicon(QPixmap::fromImage(oicon16)); + { + QPainter p32(&oicon32); + p32.setBrush(bg->b); + p32.setPen(Qt::NoPen); + p32.setRenderHint(QPainter::Antialiasing); + int32 fontSize = (cntSize < 2) ? 22 : ((cntSize < 3) ? 20 : 16); + style::font f(fontSize); + int32 w = f->m.width(cnt), d = (cntSize < 2) ? 9 : ((cntSize < 3) ? 4 : 4), r = (cntSize < 2) ? 16 : ((cntSize < 3) ? 14 : 6); + p32.drawRoundedRect(QRect(32 - w - d * 2, 32 - f->height, w + d * 2, f->height), r, r); + p32.setFont(f->f); + + p32.setPen(st::counterColor->p); + + p32.drawText(32 - w - d, 32 - f->height + f->ascent, cnt); + } + QIcon oicon; + oicon.addPixmap(QPixmap::fromImage(oicon16)); + oicon.addPixmap(QPixmap::fromImage(oicon32)); ps_iconOverlay = _qt_createHIcon(oicon, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON)); } QString description = counter > 0 ? QString("%1 unread messages").arg(counter) : qsl("No unread messages"); diff --git a/Telegram/SourceFiles/pspecific_wnd.h b/Telegram/SourceFiles/pspecific_wnd.h index 7bb2a58a4..6c1ae559f 100644 --- a/Telegram/SourceFiles/pspecific_wnd.h +++ b/Telegram/SourceFiles/pspecific_wnd.h @@ -86,7 +86,7 @@ protected: bool posInited; QSystemTrayIcon *trayIcon; QMenu *trayIconMenu; - QImage icon16, icon32, icon256; + QImage icon16, icon32, icon64, icon256; virtual void setupTrayIcon() { } diff --git a/Telegram/SourceFiles/window.cpp b/Telegram/SourceFiles/window.cpp index 8fedbf257..0e9920f9b 100644 --- a/Telegram/SourceFiles/window.cpp +++ b/Telegram/SourceFiles/window.cpp @@ -573,7 +573,9 @@ void Window::showConnecting(const QString &text, const QString &reconnect) { _connecting->set(text, reconnect); } else { _connecting = new ConnectingWidget(this, text, reconnect); + _connecting->show(); resizeEvent(0); + fixOrder(); } } diff --git a/Telegram/Telegram.plist b/Telegram/Telegram.plist index 78d5ff23c..65013559e 100644 --- a/Telegram/Telegram.plist +++ b/Telegram/Telegram.plist @@ -11,7 +11,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 0.5.12 + 0.5.13 CFBundleSignature ???? NOTE diff --git a/Telegram/Telegram.rc b/Telegram/Telegram.rc index ad303d9610623bab2d75edd026a4704beb52d182..989ee62b126647d5302932cb419eb50c6273f9ee 100644 GIT binary patch delta 58 zcmdm|y-$0C9yg=$WPNU9R$~So27}2Pxg|F@a2GKFxq3kETwdMHDtvN`aIW~~IQ|4S E0JgCX5&!@I delta 58 zcmdm|y-$0C9yg=WWPNU9RwD)-27}2Pxg|F@a2GKFxq3kETwdMHDtvN`aIW~~IQ|4S E0JbO&4gdfE diff --git a/Telegram/Telegram.xcodeproj/project.pbxproj b/Telegram/Telegram.xcodeproj/project.pbxproj index a36ed7e6e..5ad0dd8c1 100644 --- a/Telegram/Telegram.xcodeproj/project.pbxproj +++ b/Telegram/Telegram.xcodeproj/project.pbxproj @@ -1453,7 +1453,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 0.5.12; + CURRENT_PROJECT_VERSION = 0.5.13; DEBUG_INFORMATION_FORMAT = dwarf; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_OPTIMIZATION_LEVEL = 0; @@ -1471,7 +1471,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 0.5.12; + CURRENT_PROJECT_VERSION = 0.5.13; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_OPTIMIZATION_LEVEL = fast; GCC_PREFIX_HEADER = ./SourceFiles/stdafx.h; @@ -1495,9 +1495,9 @@ CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 0.5.12; + CURRENT_PROJECT_VERSION = 0.5.13; DYLIB_COMPATIBILITY_VERSION = 0.5; - DYLIB_CURRENT_VERSION = 0.5.12; + DYLIB_CURRENT_VERSION = 0.5.13; FRAMEWORK_SEARCH_PATHS = ""; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_OPTIMIZATION_LEVEL = fast; @@ -1620,10 +1620,10 @@ CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 0.5.12; + CURRENT_PROJECT_VERSION = 0.5.13; DEBUG_INFORMATION_FORMAT = dwarf; DYLIB_COMPATIBILITY_VERSION = 0.5; - DYLIB_CURRENT_VERSION = 0.5.12; + DYLIB_CURRENT_VERSION = 0.5.13; FRAMEWORK_SEARCH_PATHS = ""; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_OPTIMIZATION_LEVEL = 0;