all deinit moved to Application::aboutToQuit(), mtproto connection thread management refactored, disabled -style=0 fake argument for Application, beta 9028002

This commit is contained in:
John Preston 2016-02-29 19:53:26 +03:00
parent 08072346fd
commit 99b52d4cc1
21 changed files with 300 additions and 270 deletions

View File

@ -1,4 +1,5 @@
@echo OFF
setlocal
FOR /F "tokens=1,2* delims= " %%i in (Version) do set "%%i=%%j"

View File

@ -255,7 +255,7 @@ bool update() {
} else {
break;
}
} while (copyTries < 30);
} while (copyTries < 100);
if (!copyResult) {
writeLog(L"Error: failed to copy, asking to retry..");
WCHAR errMsg[2048];

View File

@ -110,6 +110,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
connect(&_localSocket, SIGNAL(readyRead()), this, SLOT(socketReading()));
connect(&_localServer, SIGNAL(newConnection()), this, SLOT(newInstanceConnected()));
QTimer::singleShot(0, this, SLOT(startApplication()));
connect(this, SIGNAL(aboutToQuit()), this, SLOT(closeApplication()));
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
@ -127,27 +128,6 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
}
}
Application::~Application() {
App::setQuiting();
Sandbox::finish();
delete AppObject;
_localSocket.close();
closeApplication();
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
delete _updateReply;
_updateReply = 0;
if (_updateChecker) _updateChecker->deleteLater();
_updateChecker = 0;
if (_updateThread) _updateThread->quit();
_updateThread = 0;
#endif
}
void Application::socketConnected() {
LOG(("Socket connected, this is not the first application instance, sending show command.."));
_secondInstance = true;
@ -333,13 +313,54 @@ void Application::removeClients() {
}
}
void Application::startApplication() {
if (App::quiting()) {
quit();
}
}
void Application::closeApplication() {
App::quit();
delete AppObject;
AppObject = 0;
Sandbox::finish();
_localServer.close();
for (LocalClients::iterator i = _localClients.begin(), e = _localClients.end(); i != e; ++i) {
disconnect(i->first, SIGNAL(disconnected()), this, SLOT(removeClients()));
i->first->close();
}
_localClients.clear();
_localSocket.close();
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
delete _updateReply;
_updateReply = 0;
if (_updateChecker) _updateChecker->deleteLater();
_updateChecker = 0;
if (_updateThread) _updateThread->quit();
_updateThread = 0;
#endif
DEBUG_LOG(("Telegram finished, result: %1").arg("unknown"));
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
if (cRestartingUpdate()) {
DEBUG_LOG(("Application Info: executing updater to install update.."));
psExecUpdater();
} else
#endif
if (cRestarting()) {
DEBUG_LOG(("Application Info: executing Telegram, because of restart.."));
psExecTelegram();
}
SignalHandlers::finish();
PlatformSpecific::finish();
Logs::finish();
}
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
@ -899,7 +920,7 @@ void AppClass::killDownloadSessions() {
for (QMap<int32, uint64>::iterator i = killDownloadSessionTimes.begin(); i != killDownloadSessionTimes.end(); ) {
if (i.value() <= ms) {
for (int j = 0; j < MTPDownloadSessionsCount; ++j) {
MTP::stopSession(MTP::dld[j] + i.key());
MTP::stopSession(MTP::dld(j) + i.key());
}
i = killDownloadSessionTimes.erase(i);
} else {

View File

@ -30,7 +30,6 @@ class Application : public QApplication {
public:
Application(int &argc, char **argv);
~Application();
// Single instance application
public slots:
@ -41,11 +40,13 @@ public slots:
void socketWritten(qint64 bytes);
void socketReading();
void newInstanceConnected();
void closeApplication();
void readClients();
void removeClients();
void startApplication(); // will be done in exec()
void closeApplication(); // will be done in aboutToQuit()
private:
typedef QPair<QLocalSocket*, QByteArray> LocalClient;

View File

@ -23,7 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
static const int32 AppVersion = 9028;
static const wchar_t *AppVersionStr = L"0.9.28";
static const bool DevVersion = false;
#define BETA_VERSION (9028001ULL) // just comment this line to build public version
#define BETA_VERSION (9028002ULL) // just comment this line to build public version
static const wchar_t *AppNameOld = L"Telegram Win (Unofficial)";
static const wchar_t *AppName = L"Telegram Desktop";

View File

@ -292,7 +292,7 @@ namespace SignalHandlers {
namespace Logs {
Initializer::Initializer() {
void start() {
t_assert(LogsData == 0);
if (!Sandbox::CheckBetaVersionDir()) {
@ -378,7 +378,7 @@ namespace Logs {
LOG(("Logs started"));
}
Initializer::~Initializer() {
void finish() {
delete LogsData;
LogsData = 0;

View File

@ -23,11 +23,9 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
class MTPlong;
namespace Logs {
struct Initializer {
Initializer();
~Initializer();
};
void start();
bool started();
void finish();
bool instanceChecked();
void multipleInstances();

View File

@ -25,8 +25,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "localstorage.h"
int main(int argc, char *argv[]) {
int result = 0;
settingsParseArgs(argc, argv);
if (cLaunchMode() == LaunchModeFixPrevious) {
return psFixPrevious();
@ -36,34 +34,15 @@ int main(int argc, char *argv[]) {
return showCrashReportWindow(QFileInfo(cStartUrl()).absoluteFilePath());
}
Logs::Initializer _logs;
{
PlatformSpecific::Initializer _ps;
// both are finished in Application::closeApplication
Logs::start(); // must be started before PlatformSpecific is started
PlatformSpecific::start(); // must be started before QApplication is created
QByteArray args[] = { "-style=0" }; // prepare fake args to disable QT_STYLE_OVERRIDE env variable
static const int a_cnt = sizeof(args) / sizeof(args[0]);
int a_argc = a_cnt + 1;
char *a_argv[a_cnt + 1] = { argv[0], args[0].data() };
//QByteArray args[] = { "-style=0" }; // prepare fake args to disable QT_STYLE_OVERRIDE env variable
//static const int a_cnt = sizeof(args) / sizeof(args[0]);
//int a_argc = a_cnt + 1;
//char *a_argv[a_cnt + 1] = { argv[0], args[0].data() };
Application app(a_argc, a_argv);
if (!App::quiting()) {
result = app.exec();
}
}
DEBUG_LOG(("Telegram finished, result: %1").arg(result));
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
if (cRestartingUpdate()) {
DEBUG_LOG(("Application Info: executing updater to install update.."));
psExecUpdater();
} else
#endif
if (cRestarting()) {
DEBUG_LOG(("Application Info: executing Telegram, because of restart.."));
psExecTelegram();
}
SignalHandlers::finish();
return result;
Application app(argc, argv);
return app.exec();
}

View File

@ -24,10 +24,9 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "localstorage.h"
namespace {
typedef QMap<int32, MTProtoSessionPtr> Sessions;
typedef QMap<int32, MTProtoSession*> Sessions;
Sessions sessions;
QVector<MTProtoSessionPtr> sessionsToKill;
MTProtoSessionPtr mainSession;
MTProtoSession *mainSession;
typedef QMap<mtpRequestId, int32> RequestsByDC; // holds dcWithShift for request to this dc or -dc for request to main dc
RequestsByDC requestsByDC;
@ -62,13 +61,16 @@ namespace {
typedef QMap<int32, DCAuthWaiters> AuthWaiters; // holds request ids waiting for auth import to specific dc
AuthWaiters authWaiters;
typedef OrderedSet<MTProtoConnection*> MTPQuittingConnections;
MTPQuittingConnections quittingConnections;
QMutex toClearLock;
RPCCallbackClears toClear;
RPCResponseHandler globalHandler;
MTPStateChangedHandler stateChangedHandler = 0;
MTPSessionResetHandler sessionResetHandler = 0;
_mtp_internal::RequestResender *resender = 0;
_mtp_internal::GlobalSlotCarrier *_globalSlotCarrier = 0;
void importDone(const MTPauth_Authorization &result, mtpRequestId req) {
QMutexLocker locker1(&requestByDCLock);
@ -111,7 +113,7 @@ namespace {
}
DEBUG_LOG(("MTP Info: resending request %1 to dc %2 after import auth").arg(requestId).arg(k.value()));
}
if (MTProtoSessionPtr session = _mtp_internal::getSession(dcWithShift)) {
if (MTProtoSession *session = _mtp_internal::getSession(dcWithShift)) {
session->sendPrepared(j.value());
}
}
@ -202,7 +204,7 @@ namespace {
}
req = i.value();
}
if (MTProtoSessionPtr session = _mtp_internal::getSession(newdcWithShift)) {
if (MTProtoSession *session = _mtp_internal::getSession(newdcWithShift)) {
_mtp_internal::registerRequest(requestId, (dcWithShift < 0) ? -newdcWithShift : newdcWithShift);
session->sendPrepared(req);
}
@ -230,7 +232,7 @@ namespace {
}
delayedRequests.insert(i, DelayedRequest(requestId, sendAt));
if (resender) resender->checkDelayed();
if (_globalSlotCarrier) _globalSlotCarrier->checkDelayed();
return true;
} else if (code == 401 || (badGuestDC && badGuestDCRequests.constFind(requestId) == badGuestDCRequests.cend())) {
@ -281,7 +283,7 @@ namespace {
}
if (!dcWithShift) return false;
if (MTProtoSessionPtr session = _mtp_internal::getSession(dcWithShift < 0 ? (-dcWithShift) : dcWithShift)) {
if (MTProtoSession *session = _mtp_internal::getSession(dcWithShift < 0 ? (-dcWithShift) : dcWithShift)) {
req->needsLayer = true;
session->sendPrepared(req);
}
@ -319,7 +321,7 @@ namespace {
if (!dcWithShift) return false;
if (!req->after) {
if (MTProtoSessionPtr session = _mtp_internal::getSession(dcWithShift < 0 ? (-dcWithShift) : dcWithShift)) {
if (MTProtoSession *session = _mtp_internal::getSession(dcWithShift < 0 ? (-dcWithShift) : dcWithShift)) {
req->needsLayer = true;
session->sendPrepared(req);
}
@ -346,7 +348,7 @@ namespace {
delayedRequests.insert(i, DelayedRequest(requestId, i->second));
}
if (resender) resender->checkDelayed();
if (_globalSlotCarrier) _globalSlotCarrier->checkDelayed();
}
}
return true;
@ -360,21 +362,18 @@ namespace {
}
namespace _mtp_internal {
MTProtoSessionPtr getSession(int32 dcWithShift) {
if (!_started) return MTProtoSessionPtr();
MTProtoSession *getSession(int32 dcWithShift) {
if (!_started) return 0;
if (!dcWithShift) return mainSession;
if (!(dcWithShift % _mtp_internal::dcShift)) {
dcWithShift += (mainSession->getDcWithShift() % _mtp_internal::dcShift);
}
Sessions::const_iterator i = sessions.constFind(dcWithShift);
if (i != sessions.cend()) return *i;
MTProtoSessionPtr result(new MTProtoSession());
result->start(dcWithShift);
sessions.insert(dcWithShift, result);
return result;
if (i == sessions.cend()) {
i = sessions.insert(dcWithShift, new MTProtoSession(dcWithShift));
}
return i.value();
}
bool paused() {
@ -580,11 +579,11 @@ namespace _mtp_internal {
return true;
}
RequestResender::RequestResender() {
GlobalSlotCarrier::GlobalSlotCarrier() {
connect(&_timer, SIGNAL(timeout()), this, SLOT(checkDelayed()));
}
void RequestResender::checkDelayed() {
void GlobalSlotCarrier::checkDelayed() {
uint64 now = getms(true);
while (!delayedRequests.isEmpty() && now >= delayedRequests.front().second) {
mtpRequestId requestId = delayedRequests.front().first;
@ -612,7 +611,7 @@ namespace _mtp_internal {
}
req = j.value();
}
if (MTProtoSessionPtr session = _mtp_internal::getSession(dcWithShift < 0 ? (-dcWithShift) : dcWithShift)) {
if (MTProtoSession *session = _mtp_internal::getSession(dcWithShift < 0 ? (-dcWithShift) : dcWithShift)) {
session->sendPrepared(req);
}
}
@ -621,6 +620,25 @@ namespace _mtp_internal {
_timer.start(delayedRequests.front().second - now);
}
}
void GlobalSlotCarrier::connectionFinished(MTProtoConnection *connection) {
MTPQuittingConnections::iterator i = quittingConnections.find(connection);
if (i != quittingConnections.cend()) {
quittingConnections.erase(i);
}
connection->waitTillFinish();
delete connection;
}
GlobalSlotCarrier *globalSlotCarrier() {
return _globalSlotCarrier;
}
void queueQuittingConnection(MTProtoConnection *connection) {
quittingConnections.insert(connection);
}
};
namespace MTP {
@ -637,12 +655,12 @@ namespace MTP {
MTProtoDCMap &dcs(mtpDCMap());
mainSession = MTProtoSessionPtr(new MTProtoSession());
mainSession->start(mtpMainDC());
sessions[mainSession->getDcWithShift()] = mainSession;
_globalSlotCarrier = new _mtp_internal::GlobalSlotCarrier();
mainSession = new MTProtoSession(mtpMainDC());
sessions.insert(mainSession->getDcWithShift(), mainSession);
_started = true;
resender = new _mtp_internal::RequestResender();
if (mtpNeedConfig()) {
mtpConfigLoader()->load();
@ -657,7 +675,7 @@ namespace MTP {
if (!_started) return;
for (Sessions::const_iterator i = sessions.cbegin(), e = sessions.cend(); i != e; ++i) {
(*i)->restart();
i.value()->restart();
}
}
@ -666,8 +684,8 @@ namespace MTP {
dcMask %= _mtp_internal::dcShift;
for (Sessions::const_iterator i = sessions.cbegin(), e = sessions.cend(); i != e; ++i) {
if (((*i)->getDcWithShift() % int(_mtp_internal::dcShift)) == dcMask) {
(*i)->restart();
if ((i.value()->getDcWithShift() % int(_mtp_internal::dcShift)) == dcMask) {
i.value()->restart();
}
}
}
@ -681,7 +699,7 @@ namespace MTP {
if (!_started) return;
_paused = false;
for (Sessions::const_iterator i = sessions.cbegin(), e = sessions.cend(); i != e; ++i) {
(*i)->unpaused();
i.value()->unpaused();
}
}
@ -714,7 +732,7 @@ namespace MTP {
}
Sessions::const_iterator i = sessions.constFind(dc);
if (i != sessions.cend()) return (*i)->getState();
if (i != sessions.cend()) return i.value()->getState();
return MTProtoConnection::Disconnected;
}
@ -728,13 +746,13 @@ namespace MTP {
}
Sessions::const_iterator i = sessions.constFind(dc);
if (i != sessions.cend()) return (*i)->transport();
if (i != sessions.cend()) return i.value()->transport();
return QString();
}
void ping() {
if (MTProtoSessionPtr session = _mtp_internal::getSession(0)) {
if (MTProtoSession *session = _mtp_internal::getSession(0)) {
session->ping();
}
}
@ -754,7 +772,7 @@ namespace MTP {
QMutexLocker locker(&requestByDCLock);
RequestsByDC::iterator i = requestsByDC.find(requestId);
if (i != requestsByDC.end()) {
if (MTProtoSessionPtr session = _mtp_internal::getSession(abs(i.value()))) {
if (MTProtoSession *session = _mtp_internal::getSession(abs(i.value()))) {
session->cancel(requestId, msgId);
}
requestsByDC.erase(i);
@ -763,26 +781,25 @@ namespace MTP {
_mtp_internal::clearCallbacks(requestId);
}
void killSessionsDelayed() {
if (!sessionsToKill.isEmpty()) {
sessionsToKill.clear();
}
}
void killSession(int32 dc) {
Sessions::iterator i = sessions.find(dc);
if (i != sessions.end()) {
if (i != sessions.cend()) {
bool wasMain = (i.value() == mainSession);
i.value()->kill();
if (sessionsToKill.isEmpty()) QTimer::singleShot(0, killSessionsDelayed);
sessionsToKill.push_back(i.value());
i.value()->deleteLater();
sessions.erase(i);
if (wasMain) {
mainSession = MTProtoSessionPtr(new MTProtoSession());
mainSession->start(mtpMainDC());
sessions[mainSession->getDcWithShift()] = mainSession;
mainSession = new MTProtoSession(mtpMainDC());
int32 newdc = mainSession->getDcWithShift();
i = sessions.find(newdc);
if (i != sessions.cend()) {
i.value()->kill();
i.value()->deleteLater();
sessions.erase(i);
}
sessions.insert(newdc, mainSession);
}
}
}
@ -801,14 +818,14 @@ namespace MTP {
QMutexLocker locker(&requestByDCLock);
RequestsByDC::iterator i = requestsByDC.find(requestId);
if (i != requestsByDC.end()) {
if (MTProtoSessionPtr session = _mtp_internal::getSession(abs(i.value()))) {
if (MTProtoSession *session = _mtp_internal::getSession(abs(i.value()))) {
return session->requestState(requestId);
}
return MTP::RequestConnecting;
}
return MTP::RequestSent;
}
if (MTProtoSessionPtr session = _mtp_internal::getSession(-requestId)) {
if (MTProtoSession *session = _mtp_internal::getSession(-requestId)) {
return session->requestState(0);
}
return MTP::RequestConnecting;
@ -817,11 +834,20 @@ namespace MTP {
void stop() {
for (Sessions::iterator i = sessions.begin(), e = sessions.end(); i != e; ++i) {
i.value()->kill();
delete i.value();
}
sessions.clear();
mainSession = MTProtoSessionPtr();
delete resender;
resender = 0;
mainSession = nullptr;
for (MTPQuittingConnections::const_iterator i = quittingConnections.cbegin(), e = quittingConnections.cend(); i != e; ++i) {
i.key()->waitTillFinish();
delete i.key();
}
quittingConnections.clear();
delete _globalSlotCarrier;
_globalSlotCarrier = nullptr;
mtpDestroyConfigLoader();
_started = false;

View File

@ -24,7 +24,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "mtproto/mtpFileLoader.h"
namespace _mtp_internal {
MTProtoSessionPtr getSession(int32 dc = 0); // 0 - current set dc
MTProtoSession *getSession(int32 dc); // 0 - current set dc
bool paused();
@ -49,21 +49,28 @@ namespace _mtp_internal {
return rpcErrorOccured(requestId, handler.onFail, err);
}
class RequestResender : public QObject {
// used for:
// - resending requests by timer which were postponed by flood delay
// - destroying MTProtoConnections whose thread has finished
class GlobalSlotCarrier : public QObject {
Q_OBJECT
public:
RequestResender();
GlobalSlotCarrier();
public slots:
void checkDelayed();
void connectionFinished(MTProtoConnection *connection);
private:
SingleTimer _timer;
};
GlobalSlotCarrier *globalSlotCarrier();
void queueQuittingConnection(MTProtoConnection *connection);
};
namespace MTP {
@ -99,7 +106,7 @@ namespace MTP {
template <typename TRequest>
inline mtpRequestId send(const TRequest &request, RPCResponseHandler callbacks = RPCResponseHandler(), int32 dc = 0, uint64 msCanWait = 0, mtpRequestId after = 0) {
if (MTProtoSessionPtr session = _mtp_internal::getSession(dc)) {
if (MTProtoSession *session = _mtp_internal::getSession(dc)) {
return session->send(request, callbacks, msCanWait, true, !dc, after);
}
return 0;
@ -109,7 +116,7 @@ namespace MTP {
return send(request, RPCResponseHandler(onDone, onFail), dc, msCanWait, after);
}
inline void sendAnything(int32 dc = 0, uint64 msCanWait = 0) {
if (MTProtoSessionPtr session = _mtp_internal::getSession(dc)) {
if (MTProtoSession *session = _mtp_internal::getSession(dc)) {
return session->sendAnything(msCanWait);
}
}

View File

@ -252,8 +252,6 @@ namespace {
typedef QMap<uint64, mtpPublicRSA> PublicRSAKeys;
PublicRSAKeys gPublicRSA;
MTProtoConnection gMainConnection;
bool gConfigInited = false;
void initRSAConfig() {
if (gConfigInited) return;
@ -277,66 +275,75 @@ namespace {
}
}
MTPThread::MTPThread(QObject *parent) : QThread(parent) {
static uint32 gThreadId = 0;
threadId = ++gThreadId;
uint32 MTPThreadIdIncrement = 0;
MTPThread::MTPThread() : QThread(0)
, _threadId(++MTPThreadIdIncrement) {
}
uint32 MTPThread::getThreadId() const {
return threadId;
return _threadId;
}
MTProtoConnection::MTProtoConnection() : thread(0), data(0) {
MTPThread::~MTPThread() {
}
MTProtoConnection::MTProtoConnection() : thread(nullptr), data(nullptr) {
}
int32 MTProtoConnection::start(MTPSessionData *sessionData, int32 dc) {
t_assert(thread == nullptr && data == nullptr);
initRSAConfig();
if (thread) {
DEBUG_LOG(("MTP Info: MTP start called for already working connection"));
return dc;
}
thread = new MTPThread(QApplication::instance());
thread = new MTPThread();
data = new MTProtoConnectionPrivate(thread, this, sessionData, dc);
dc = data->getDC();
if (!dc) {
delete data;
data = nullptr;
delete thread;
data = 0;
thread = 0;
thread = nullptr;
return 0;
}
thread->start();
return dc;
}
void MTProtoConnection::stop() {
if (data) data->stop();
if (thread) thread->quit();
void MTProtoConnection::kill() {
t_assert(data != nullptr && thread != nullptr);
data->stop();
data = nullptr; // will be deleted in thread::finished signal
thread->quit();
_mtp_internal::queueQuittingConnection(this);
}
void MTProtoConnection::stopped() {
if (thread) thread->deleteLater();
if (data) data->deleteLater();
thread = 0;
data = 0;
delete this;
void MTProtoConnection::waitTillFinish() {
t_assert(data == nullptr && thread != nullptr);
thread->wait();
delete thread;
thread = nullptr;
}
int32 MTProtoConnection::state() const {
if (!data) return Disconnected;
t_assert(data != nullptr && thread != nullptr);
return data->getState();
}
QString MTProtoConnection::transport() const {
if (!data) return QString();
t_assert(data != nullptr && thread != nullptr);
return data->transport();
}
MTProtoConnection::~MTProtoConnection() {
t_assert(data == nullptr && thread == nullptr);
}
namespace {
mtpBuffer _handleHttpResponse(QNetworkReply *reply) {
QByteArray response = reply->readAll();
@ -1311,30 +1318,31 @@ void MTProtoConnectionPrivate::destroyConn(MTPabstractConnection **conn) {
}
}
MTProtoConnectionPrivate::MTProtoConnectionPrivate(QThread *thread, MTProtoConnection *owner, MTPSessionData *data, uint32 _dc)
: QObject(0)
, _state(MTProtoConnection::Disconnected)
, _needSessionReset(false)
, dc(_dc)
, _owner(owner)
, _conn(0), _conn4(0), _conn6(0)
, retryTimeout(1)
, oldConnection(true)
, _waitForReceived(MTPMinReceiveDelay)
, _waitForConnected(MTPMinConnectDelay)
, firstSentAt(-1)
, _pingId(0)
, _pingIdToSend(0)
, _pingSendAt(0)
, _pingMsgId(0)
, restarted(false)
, keyId(0)
MTProtoConnectionPrivate::MTProtoConnectionPrivate(QThread *thread, MTProtoConnection *owner, MTPSessionData *data, uint32 _dc) : QObject(0)
, _state(MTProtoConnection::Disconnected)
, _needSessionReset(false)
, dc(_dc)
, _owner(owner)
, _conn(0)
, _conn4(0)
, _conn6(0)
, retryTimeout(1)
, oldConnection(true)
, _waitForReceived(MTPMinReceiveDelay)
, _waitForConnected(MTPMinConnectDelay)
, firstSentAt(-1)
, _pingId(0)
, _pingIdToSend(0)
, _pingSendAt(0)
, _pingMsgId(0)
, restarted(false)
, _finished(false)
, keyId(0)
// , sessionDataMutex(QReadWriteLock::Recursive)
, sessionData(data)
, myKeyLock(false)
, authKeyData(0)
, authKeyStrings(0) {
, sessionData(data)
, myKeyLock(false)
, authKeyData(0)
, authKeyStrings(0) {
oldConnectionTimer.moveToThread(thread);
_waitForConnectedTimer.moveToThread(thread);
_waitForReceivedTimer.moveToThread(thread);
@ -1357,6 +1365,7 @@ MTProtoConnectionPrivate::MTProtoConnectionPrivate(QThread *thread, MTProtoConne
connect(thread, SIGNAL(started()), this, SLOT(socketStart()));
connect(thread, SIGNAL(finished()), this, SLOT(doFinish()));
connect(this, SIGNAL(finished(MTProtoConnection*)), _mtp_internal::globalSlotCarrier(), SLOT(connectionFinished(MTProtoConnection*)), Qt::QueuedConnection);
connect(&retryTimer, SIGNAL(timeout()), this, SLOT(retryByTimer()));
connect(&_waitForConnectedTimer, SIGNAL(timeout()), this, SLOT(onWaitConnectedFailed()));
@ -1966,6 +1975,10 @@ void MTProtoConnectionPrivate::restartNow() {
}
void MTProtoConnectionPrivate::socketStart(bool afterConfig) {
if (_finished) {
DEBUG_LOG(("MTP Error: socketStart() called for finished connection!"));
return;
}
bool isDldDc = (dc >= MTP::dldStart) && (dc < MTP::dldEnd);
if (isDldDc) { // using media_only addresses only if key for this dc is already created
QReadLocker lockFinished(&sessionDataMutex);
@ -2231,7 +2244,9 @@ void MTProtoConnectionPrivate::doDisconnect() {
void MTProtoConnectionPrivate::doFinish() {
doDisconnect();
_owner->stopped();
_finished = true;
emit finished(_owner);
deleteLater();
}
void MTProtoConnectionPrivate::handleReceived() {
@ -3928,7 +3943,7 @@ void MTProtoConnectionPrivate::unlockKey() {
}
MTProtoConnectionPrivate::~MTProtoConnectionPrivate() {
doDisconnect();
t_assert(_finished && _conn == nullptr && _conn4 == nullptr && _conn6 == nullptr);
}
void MTProtoConnectionPrivate::stop() {
@ -3939,9 +3954,6 @@ void MTProtoConnectionPrivate::stop() {
sessionData->keyMutex()->unlock();
myKeyLock = false;
}
sessionData = 0;
sessionData = nullptr;
}
}
MTProtoConnection::~MTProtoConnection() {
}

View File

@ -58,11 +58,13 @@ class MTPThread : public QThread {
Q_OBJECT
public:
MTPThread(QObject *parent = 0);
MTPThread();
uint32 getThreadId() const;
~MTPThread();
private:
uint32 threadId;
uint32 _threadId;
};
class MTProtoConnection {
@ -75,8 +77,8 @@ public:
MTProtoConnection();
int32 start(MTPSessionData *data, int32 dc = 0); // return dc
void stop();
void stopped();
void kill();
void waitTillFinish();
~MTProtoConnection();
enum {
@ -358,6 +360,8 @@ signals:
void resendManyAsync(QVector<quint64> msgIds, quint64 msCanWait, bool forceContainer, bool sendMsgStateInfo);
void resendAllAsync();
void finished(MTProtoConnection *connection);
public slots:
void retryByTimer();
@ -466,7 +470,7 @@ private:
template <typename TResponse>
bool readResponseNotSecure(TResponse &response);
bool restarted;
bool restarted, _finished;
uint64 keyId;
QReadWriteLock sessionDataMutex;

View File

@ -66,7 +66,8 @@ void MTPSessionData::clear() {
}
MTProtoSession::MTProtoSession() : QObject()
MTProtoSession::MTProtoSession(int32 dcenter) : QObject()
, _connection(0)
, _killed(false)
, _needToReceive(false)
, data(this)
@ -75,9 +76,6 @@ MTProtoSession::MTProtoSession() : QObject()
, msSendCall(0)
, msWait(0)
, _ping(false) {
}
void MTProtoSession::start(int32 dcenter) {
if (_killed) {
DEBUG_LOG(("Session Error: can't start a killed session"));
return;
@ -96,37 +94,32 @@ void MTProtoSession::start(int32 dcenter) {
MTProtoDCMap &dcs(mtpDCMap());
connections.reserve(cConnectionsInSession());
for (uint32 i = 0; i < cConnectionsInSession(); ++i) {
connections.push_back(new MTProtoConnection());
dcWithShift = connections.back()->start(&data, dcenter);
if (!dcWithShift) {
for (MTProtoConnections::const_iterator j = connections.cbegin(), e = connections.cend(); j != e; ++j) {
delete *j;
}
connections.clear();
DEBUG_LOG(("Session Info: could not start connection %1 to dc %2").arg(i).arg(dcenter));
return;
_connection = new MTProtoConnection();
dcWithShift = _connection->start(&data, dcenter);
if (!dcWithShift) {
delete _connection;
_connection = 0;
DEBUG_LOG(("Session Info: could not start connection to dc %1").arg(dcenter));
return;
}
if (!dc) {
dcenter = dcWithShift;
int32 dcId = dcWithShift % _mtp_internal::dcShift;
MTProtoDCMap::const_iterator dcIndex = dcs.constFind(dcId);
if (dcIndex == dcs.cend()) {
dc = MTProtoDCPtr(new MTProtoDC(dcId, mtpAuthKeyPtr()));
dcs.insert(dcWithShift % _mtp_internal::dcShift, dc);
} else {
dc = dcIndex.value();
}
if (!dc) {
dcenter = dcWithShift;
int32 dcId = dcWithShift % _mtp_internal::dcShift;
MTProtoDCMap::const_iterator dcIndex = dcs.constFind(dcId);
if (dcIndex == dcs.cend()) {
dc = MTProtoDCPtr(new MTProtoDC(dcId, mtpAuthKeyPtr()));
dcs.insert(dcWithShift % _mtp_internal::dcShift, dc);
} else {
dc = dcIndex.value();
}
ReadLockerAttempt lock(keyMutex());
data.setKey(lock ? dc->getKey() : mtpAuthKeyPtr(0));
if (lock && dc->connectionInited()) {
data.setLayerWasInited(true);
}
connect(dc.data(), SIGNAL(authKeyCreated()), this, SLOT(authKeyCreatedForDC()), Qt::QueuedConnection);
connect(dc.data(), SIGNAL(layerWasInited(bool)), this, SLOT(layerWasInitedForDC(bool)), Qt::QueuedConnection);
ReadLockerAttempt lock(keyMutex());
data.setKey(lock ? dc->getKey() : mtpAuthKeyPtr(0));
if (lock && dc->connectionInited()) {
data.setLayerWasInited(true);
}
connect(dc.data(), SIGNAL(authKeyCreated()), this, SLOT(authKeyCreatedForDC()), Qt::QueuedConnection);
connect(dc.data(), SIGNAL(layerWasInited(bool)), this, SLOT(layerWasInitedForDC(bool)), Qt::QueuedConnection);
}
}
@ -139,10 +132,14 @@ void MTProtoSession::restart() {
}
void MTProtoSession::stop() {
if (_killed) {
DEBUG_LOG(("Session Error: can't kill a killed session"));
return;
}
DEBUG_LOG(("Session Info: stopping session dcWithShift %1").arg(dcWithShift));
while (!connections.isEmpty()) {
connections.back()->stop();
connections.pop_back();
if (_connection) {
_connection->kill();
_connection = 0;
}
}
@ -194,22 +191,17 @@ void MTProtoSession::needToResumeAndSend() {
DEBUG_LOG(("Session Info: can't resume a killed session"));
return;
}
if (connections.isEmpty()) {
if (!_connection) {
DEBUG_LOG(("Session Info: resuming session dcWithShift %1").arg(dcWithShift));
MTProtoDCMap &dcs(mtpDCMap());
connections.reserve(cConnectionsInSession());
for (uint32 i = 0; i < cConnectionsInSession(); ++i) {
connections.push_back(new MTProtoConnection());
if (!connections.back()->start(&data, dcWithShift)) {
for (MTProtoConnections::const_iterator j = connections.cbegin(), e = connections.cend(); j != e; ++j) {
delete *j;
}
connections.clear();
DEBUG_LOG(("Session Info: could not start connection %1 to dcWithShift %2").arg(i).arg(dcWithShift));
dcWithShift = 0;
return;
}
_connection = new MTProtoConnection();
if (!_connection->start(&data, dcWithShift)) {
delete _connection;
_connection = 0;
DEBUG_LOG(("Session Info: could not start connection to dcWithShift %1").arg(dcWithShift));
dcWithShift = 0;
return;
}
}
if (_ping) {
@ -324,12 +316,13 @@ void MTProtoSession::ping() {
}
int32 MTProtoSession::requestState(mtpRequestId requestId) const {
MTProtoConnections::const_iterator j = connections.cbegin(), e = connections.cend();
int32 result = MTP::RequestSent;
for (; j != e; ++j) {
int32 s = (*j)->state();
bool connected = false;
if (_connection) {
int32 s = _connection->state();
if (s == MTProtoConnection::Connected) {
break;
connected = true;
} else if (s == MTProtoConnection::Connecting || s == MTProtoConnection::Disconnected) {
if (result < 0 || result == MTP::RequestSent) {
result = MTP::RequestConnecting;
@ -340,7 +333,7 @@ int32 MTProtoSession::requestState(mtpRequestId requestId) const {
}
}
}
if (j == e) { // no one is connected
if (!connected) {
return result;
}
if (!requestId) return MTP::RequestSent;
@ -356,10 +349,10 @@ int32 MTProtoSession::requestState(mtpRequestId requestId) const {
}
int32 MTProtoSession::getState() const {
MTProtoConnections::const_iterator j = connections.cbegin(), e = connections.cend();
int32 result = -86400000;
for (; j != e; ++j) {
int32 s = (*j)->state();
if (_connection) {
int32 s = _connection->state();
if (s == MTProtoConnection::Connected) {
return s;
} else if (s == MTProtoConnection::Connecting || s == MTProtoConnection::Disconnected) {
@ -379,12 +372,7 @@ int32 MTProtoSession::getState() const {
}
QString MTProtoSession::transport() const {
MTProtoConnections::const_iterator j = connections.cbegin(), e = connections.cend();
for (; j != e; ++j) {
QString s = (*j)->transport();
if (!s.isEmpty()) return s;
}
return QString();
return _connection ? _connection->transport() : QString();
}
mtpRequestId MTProtoSession::resend(quint64 msgId, quint64 msCanWait, bool forceContainer, bool sendMsgStateInfo) {
@ -507,6 +495,10 @@ int32 MTProtoSession::getDcWithShift() const {
}
void MTProtoSession::tryToReceive() {
if (_killed) {
DEBUG_LOG(("Session Error: can't receive in a killed session"));
return;
}
if (_mtp_internal::paused()) {
_needToReceive = true;
return;
@ -537,9 +529,7 @@ void MTProtoSession::tryToReceive() {
}
MTProtoSession::~MTProtoSession() {
for (MTProtoConnections::const_iterator i = connections.cbegin(), e = connections.cend(); i != e; ++i) {
delete *i;
}
t_assert(_connection == 0);
}
MTPrpcError rpcClientError(const QString &type, const QString &description) {

View File

@ -28,7 +28,7 @@ class MTProtoSession;
class MTPSessionData {
public:
MTPSessionData(MTProtoSession *creator)
: _session(0), _salt(0)
, _messagesSent(0), _fakeRequestId(-2000000000)
@ -222,9 +222,8 @@ class MTProtoSession : public QObject {
public:
MTProtoSession();
MTProtoSession(int32 dcenter);
void start(int32 dcenter = 0);
void restart();
void stop();
void kill();
@ -278,13 +277,12 @@ public slots:
void sendMsgsStateInfo(quint64 msgId, QByteArray data);
private:
typedef QList<MTProtoConnection*> MTProtoConnections;
MTProtoConnections connections;
MTProtoConnection *_connection;
bool _killed;
bool _needToReceive;
MTPSessionData data;
int32 dcWithShift;
@ -304,7 +302,3 @@ inline QReadWriteLock *MTPSessionData::keyMutex() const {
}
MTPrpcError rpcClientError(const QString &type, const QString &description = QString());
// here
typedef QSharedPointer<MTProtoSession> MTProtoSessionPtr;

View File

@ -38,10 +38,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace PlatformSpecific {
struct Initializer {
Initializer();
~Initializer();
};
void start();
void finish();
namespace ThirdParty {
void start();

View File

@ -1237,10 +1237,10 @@ void psShowInFolder(const QString &name) {
namespace PlatformSpecific {
Initializer::Initializer() {
void start() {
}
Initializer::~Initializer() {
void finish() {
delete _psEventFilter;
_psEventFilter = 0;
}

View File

@ -850,11 +850,11 @@ void psShowInFolder(const QString &name) {
namespace PlatformSpecific {
Initializer::Initializer() {
void start() {
objc_start();
}
Initializer::~Initializer() {
void finish() {
delete _psEventFilter;
_psEventFilter = 0;

View File

@ -2159,10 +2159,10 @@ void psShowInFolder(const QString &name) {
namespace PlatformSpecific {
Initializer::Initializer() {
void start() {
}
Initializer::~Initializer() {
void finish() {
delete _psEventFilter;
_psEventFilter = 0;

View File

@ -77,7 +77,6 @@ inline QString cInlineGifBotUsername() {
return cTestMode() ? qstr("contextbot") : qstr("gif");
}
DeclareSetting(QString, LoggedPhoneNumber);
DeclareReadSetting(uint32, ConnectionsInSession);
DeclareSetting(bool, AutoStart);
DeclareSetting(bool, StartMinimized);
DeclareSetting(bool, StartInTray);

View File

@ -34,8 +34,8 @@ IDI_ICON1 ICON "SourceFiles\\art\\icon256.ico"
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,9,28,1
PRODUCTVERSION 0,9,28,1
FILEVERSION 0,9,28,2
PRODUCTVERSION 0,9,28,2
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -51,10 +51,10 @@ BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Telegram Messenger LLP"
VALUE "FileVersion", "0.9.28.1"
VALUE "FileVersion", "0.9.28.2"
VALUE "LegalCopyright", "Copyright (C) 2014-2016"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "0.9.28.1"
VALUE "ProductVersion", "0.9.28.2"
END
END
BLOCK "VarFileInfo"

View File

@ -3,4 +3,4 @@ AppVersionStrMajor 0.9
AppVersionStrSmall 0.9.28
AppVersionStr 0.9.28
DevChannel 0
BetaVersion 9028001
BetaVersion 9028002