mirror of https://github.com/procxx/kepka.git
				
				
				
			Make MTP::Session handle the connection thread.
This commit is contained in:
		
							parent
							
								
									06f5f7f7d9
								
							
						
					
					
						commit
						c742d7406c
					
				|  | @ -453,18 +453,14 @@ void Account::destroyMtpKeys(MTP::AuthKeysList &&keys) { | ||||||
| 		Core::App().dcOptions(), | 		Core::App().dcOptions(), | ||||||
| 		MTP::Instance::Mode::KeysDestroyer, | 		MTP::Instance::Mode::KeysDestroyer, | ||||||
| 		std::move(destroyConfig)); | 		std::move(destroyConfig)); | ||||||
| 	QObject::connect( | 	_mtpForKeysDestroy->allKeysDestroyed( | ||||||
| 		_mtpForKeysDestroy.get(), | 	) | rpl::start_with_next([=] { | ||||||
| 		&MTP::Instance::allKeysDestroyed, | 		LOG(("MTP Info: all keys scheduled for destroy are destroyed.")); | ||||||
| 		[=] { allKeysDestroyed(); }); | 		crl::on_main(this, [=] { | ||||||
| } | 			_mtpForKeysDestroy = nullptr; | ||||||
| 
 | 			Local::writeMtpData(); | ||||||
| void Account::allKeysDestroyed() { | 		}); | ||||||
| 	LOG(("MTP Info: all keys scheduled for destroy are destroyed.")); | 	}, _lifetime); | ||||||
| 	crl::on_main(this, [=] { |  | ||||||
| 		_mtpForKeysDestroy = nullptr; |  | ||||||
| 		Local::writeMtpData(); |  | ||||||
| 	}); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Account::suggestMainDcId(MTP::DcId mainDcId) { | void Account::suggestMainDcId(MTP::DcId mainDcId) { | ||||||
|  |  | ||||||
|  | @ -85,7 +85,6 @@ private: | ||||||
| 	void watchSessionChanges(); | 	void watchSessionChanges(); | ||||||
| 
 | 
 | ||||||
| 	void destroyMtpKeys(MTP::AuthKeysList &&keys); | 	void destroyMtpKeys(MTP::AuthKeysList &&keys); | ||||||
| 	void allKeysDestroyed(); |  | ||||||
| 	void resetAuthorizationKeys(); | 	void resetAuthorizationKeys(); | ||||||
| 
 | 
 | ||||||
| 	void loggedOut(); | 	void loggedOut(); | ||||||
|  |  | ||||||
|  | @ -114,75 +114,46 @@ void WrapInvokeAfter( | ||||||
| 
 | 
 | ||||||
| } // namespace
 | } // namespace
 | ||||||
| 
 | 
 | ||||||
| Connection::Connection(not_null<Instance*> instance) | Connection::Connection( | ||||||
| : _instance(instance) { | 	not_null<Instance*> instance, | ||||||
|  | 	not_null<QThread*> thread, | ||||||
|  | 	std::shared_ptr<SessionData> data, | ||||||
|  | 	ShiftedDcId shiftedDcId) | ||||||
|  | : QObject(nullptr) | ||||||
|  | , _instance(instance) | ||||||
|  | , _shiftedDcId(shiftedDcId) | ||||||
|  | , _realDcType(_instance->dcOptions()->dcType(_shiftedDcId)) | ||||||
|  | , _currentDcType(_realDcType) | ||||||
|  | , _state(DisconnectedState) | ||||||
|  | , _retryTimer(thread, [=] { retryByTimer(); }) | ||||||
|  | , _oldConnectionTimer(thread, [=] { markConnectionOld(); }) | ||||||
|  | , _waitForConnectedTimer(thread, [=] { waitConnectedFailed(); }) | ||||||
|  | , _waitForReceivedTimer(thread, [=] { waitReceivedFailed(); }) | ||||||
|  | , _waitForBetterTimer(thread, [=] { waitBetterFailed(); }) | ||||||
|  | , _waitForReceived(kMinReceiveTimeout) | ||||||
|  | , _waitForConnected(kMinConnectedTimeout) | ||||||
|  | , _pingSender(thread, [=] { sendPingByTimer(); }) | ||||||
|  | , _checkSentRequestsTimer(thread, [=] { checkSentRequests(); }) | ||||||
|  | , _sessionData(std::move(data)) { | ||||||
|  | 	Expects(_shiftedDcId != 0); | ||||||
|  | 
 | ||||||
|  | 	moveToThread(thread); | ||||||
|  | 
 | ||||||
|  | 	connect(thread, &QThread::started, this, [=] { | ||||||
|  | 		_checkSentRequestsTimer.callEach(kCheckSentRequestsEach); | ||||||
|  | 		connectToServer(); | ||||||
|  | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Connection::~Connection() { | Connection::~Connection() { | ||||||
| 	Expects(_private == nullptr); | 	releaseKeyCreationOnFail(); | ||||||
|  | 	doDisconnect(); | ||||||
| 
 | 
 | ||||||
| 	if (_thread) { | 	Expects(!_connection); | ||||||
| 		waitTillFinish(); | 	Expects(_testConnections.empty()); | ||||||
| 	} |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Connection::start( | void Connection::appendTestConnection( | ||||||
| 		std::shared_ptr<SessionData> sessionData, |  | ||||||
| 		ShiftedDcId shiftedDcId) { |  | ||||||
| 	Expects(_thread == nullptr && _private == nullptr); |  | ||||||
| 
 |  | ||||||
| 	_thread = std::make_unique<QThread>(); |  | ||||||
| 	auto newData = std::make_unique<ConnectionPrivate>( |  | ||||||
| 		_instance, |  | ||||||
| 		_thread.get(), |  | ||||||
| 		this, |  | ||||||
| 		std::move(sessionData), |  | ||||||
| 		shiftedDcId); |  | ||||||
| 
 |  | ||||||
| 	_instance->dcOptions()->changed( |  | ||||||
| 	) | rpl::filter([=](DcId dcId) { |  | ||||||
| 		return (BareDcId(shiftedDcId) == dcId) && (_private != nullptr); |  | ||||||
| 	}) | rpl::start_with_next([=] { |  | ||||||
| 		const auto raw = _private; |  | ||||||
| 		InvokeQueued(raw, [=] { |  | ||||||
| 			raw->dcOptionsChanged(); |  | ||||||
| 		}); |  | ||||||
| 	}, _lifetime); |  | ||||||
| 
 |  | ||||||
| 	// will be deleted in the thread::finished signal
 |  | ||||||
| 	_private = newData.release(); |  | ||||||
| 	_thread->start(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Connection::kill() { |  | ||||||
| 	Expects(_private != nullptr && _thread != nullptr); |  | ||||||
| 
 |  | ||||||
| 	_private->stop(); |  | ||||||
| 	_private = nullptr; |  | ||||||
| 	_thread->quit(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Connection::waitTillFinish() { |  | ||||||
| 	Expects(_private == nullptr && _thread != nullptr); |  | ||||||
| 
 |  | ||||||
| 	DEBUG_LOG(("Waiting for connectionThread to finish")); |  | ||||||
| 	_thread->wait(); |  | ||||||
| 	_thread.reset(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int32 Connection::state() const { |  | ||||||
| 	Expects(_private != nullptr && _thread != nullptr); |  | ||||||
| 
 |  | ||||||
| 	return _private->getState(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| QString Connection::transport() const { |  | ||||||
| 	Expects(_private != nullptr && _thread != nullptr); |  | ||||||
| 
 |  | ||||||
| 	return _private->transport(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ConnectionPrivate::appendTestConnection( |  | ||||||
| 		DcOptions::Variants::Protocol protocol, | 		DcOptions::Variants::Protocol protocol, | ||||||
| 		const QString &ip, | 		const QString &ip, | ||||||
| 		int port, | 		int port, | ||||||
|  | @ -231,7 +202,7 @@ void ConnectionPrivate::appendTestConnection( | ||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int16 ConnectionPrivate::getProtocolDcId() const { | int16 Connection::getProtocolDcId() const { | ||||||
| 	const auto dcId = BareDcId(_shiftedDcId); | 	const auto dcId = BareDcId(_shiftedDcId); | ||||||
| 	const auto simpleDcId = isTemporaryDcId(dcId) | 	const auto simpleDcId = isTemporaryDcId(dcId) | ||||||
| 		? getRealIdFromTemporaryDcId(dcId) | 		? getRealIdFromTemporaryDcId(dcId) | ||||||
|  | @ -244,7 +215,7 @@ int16 ConnectionPrivate::getProtocolDcId() const { | ||||||
| 		: testedDcId; | 		: testedDcId; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::checkSentRequests() { | void Connection::checkSentRequests() { | ||||||
| 	// Remove very old (10 minutes) containers and resend requests.
 | 	// Remove very old (10 minutes) containers and resend requests.
 | ||||||
| 	auto removingIds = std::vector<mtpMsgId>(); | 	auto removingIds = std::vector<mtpMsgId>(); | ||||||
| 	auto requesting = false; | 	auto requesting = false; | ||||||
|  | @ -285,7 +256,7 @@ void ConnectionPrivate::checkSentRequests() { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::destroyAllConnections() { | void Connection::destroyAllConnections() { | ||||||
| 	clearUnboundKeyCreator(); | 	clearUnboundKeyCreator(); | ||||||
| 	_waitForBetterTimer.cancel(); | 	_waitForBetterTimer.cancel(); | ||||||
| 	_waitForReceivedTimer.cancel(); | 	_waitForReceivedTimer.cancel(); | ||||||
|  | @ -294,67 +265,20 @@ void ConnectionPrivate::destroyAllConnections() { | ||||||
| 	_connection = nullptr; | 	_connection = nullptr; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ConnectionPrivate::ConnectionPrivate( | void Connection::cdnConfigChanged() { | ||||||
| 	not_null<Instance*> instance, | 	connectToServer(true); | ||||||
| 	not_null<QThread*> thread, |  | ||||||
| 	not_null<Connection*> owner, |  | ||||||
| 	std::shared_ptr<SessionData> data, |  | ||||||
| 	ShiftedDcId shiftedDcId) |  | ||||||
| : QObject(nullptr) |  | ||||||
| , _instance(instance) |  | ||||||
| , _owner(owner) |  | ||||||
| , _shiftedDcId(shiftedDcId) |  | ||||||
| , _realDcType(_instance->dcOptions()->dcType(_shiftedDcId)) |  | ||||||
| , _currentDcType(_realDcType) |  | ||||||
| , _state(DisconnectedState) |  | ||||||
| , _retryTimer(thread, [=] { retryByTimer(); }) |  | ||||||
| , _oldConnectionTimer(thread, [=] { markConnectionOld(); }) |  | ||||||
| , _waitForConnectedTimer(thread, [=] { waitConnectedFailed(); }) |  | ||||||
| , _waitForReceivedTimer(thread, [=] { waitReceivedFailed(); }) |  | ||||||
| , _waitForBetterTimer(thread, [=] { waitBetterFailed(); }) |  | ||||||
| , _waitForReceived(kMinReceiveTimeout) |  | ||||||
| , _waitForConnected(kMinConnectedTimeout) |  | ||||||
| , _pingSender(thread, [=] { sendPingByTimer(); }) |  | ||||||
| , _checkSentRequestsTimer(thread, [=] { checkSentRequests(); }) |  | ||||||
| , _sessionData(std::move(data)) { |  | ||||||
| 	Expects(_shiftedDcId != 0); |  | ||||||
| 
 |  | ||||||
| 	moveToThread(thread); |  | ||||||
| 
 |  | ||||||
| 	connect(thread, &QThread::started, this, [=] { |  | ||||||
| 		_checkSentRequestsTimer.callEach(kCheckSentRequestsEach); |  | ||||||
| 		connectToServer(); |  | ||||||
| 	}); |  | ||||||
| 	connect(thread, &QThread::finished, this, [=] { finishAndDestroy(); }); |  | ||||||
| 
 |  | ||||||
| 	connect(_sessionData->owner(), SIGNAL(authKeyChanged()), this, SLOT(updateAuthKey()), Qt::QueuedConnection); |  | ||||||
| 	connect(_sessionData->owner(), SIGNAL(needToRestart()), this, SLOT(restartNow()), Qt::QueuedConnection); |  | ||||||
| 	connect(_sessionData->owner(), SIGNAL(needToSend()), this, SLOT(tryToSend()), Qt::QueuedConnection); |  | ||||||
| 	connect(_sessionData->owner(), SIGNAL(needToPing()), this, SLOT(onPingSendForce()), Qt::QueuedConnection); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ConnectionPrivate::~ConnectionPrivate() { | int32 Connection::getShiftedDcId() const { | ||||||
| 	releaseKeyCreationOnFail(); |  | ||||||
| 
 |  | ||||||
| 	Expects(_finished); |  | ||||||
| 	Expects(!_connection); |  | ||||||
| 	Expects(_testConnections.empty()); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ConnectionPrivate::onCDNConfigLoaded() { |  | ||||||
| 	restart(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int32 ConnectionPrivate::getShiftedDcId() const { |  | ||||||
| 	return _shiftedDcId; | 	return _shiftedDcId; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::dcOptionsChanged() { | void Connection::dcOptionsChanged() { | ||||||
| 	_retryTimeout = 1; | 	_retryTimeout = 1; | ||||||
| 	connectToServer(true); | 	connectToServer(true); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int32 ConnectionPrivate::getState() const { | int32 Connection::getState() const { | ||||||
| 	QReadLocker lock(&_stateMutex); | 	QReadLocker lock(&_stateMutex); | ||||||
| 	int32 result = _state; | 	int32 result = _state; | ||||||
| 	if (_state < 0) { | 	if (_state < 0) { | ||||||
|  | @ -368,7 +292,7 @@ int32 ConnectionPrivate::getState() const { | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| QString ConnectionPrivate::transport() const { | QString Connection::transport() const { | ||||||
| 	QReadLocker lock(&_stateMutex); | 	QReadLocker lock(&_stateMutex); | ||||||
| 	if (!_connection || (_state < 0)) { | 	if (!_connection || (_state < 0)) { | ||||||
| 		return QString(); | 		return QString(); | ||||||
|  | @ -378,8 +302,8 @@ QString ConnectionPrivate::transport() const { | ||||||
| 	return _connection->transport(); | 	return _connection->transport(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool ConnectionPrivate::setState(int32 state, int32 ifState) { | bool Connection::setState(int state, int ifState) { | ||||||
| 	if (ifState != Connection::UpdateAlways) { | 	if (ifState != kUpdateStateAlways) { | ||||||
| 		QReadLocker lock(&_stateMutex); | 		QReadLocker lock(&_stateMutex); | ||||||
| 		if (_state != ifState) { | 		if (_state != ifState) { | ||||||
| 			return false; | 			return false; | ||||||
|  | @ -402,7 +326,7 @@ bool ConnectionPrivate::setState(int32 state, int32 ifState) { | ||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::resetSession() { | void Connection::resetSession() { | ||||||
| 	MTP_LOG(_shiftedDcId, ("Resetting session!")); | 	MTP_LOG(_shiftedDcId, ("Resetting session!")); | ||||||
| 	_needSessionReset = false; | 	_needSessionReset = false; | ||||||
| 
 | 
 | ||||||
|  | @ -412,7 +336,7 @@ void ConnectionPrivate::resetSession() { | ||||||
| 	_sessionData->queueResetDone(); | 	_sessionData->queueResetDone(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::changeSessionId() { | void Connection::changeSessionId() { | ||||||
| 	auto sessionId = _sessionId; | 	auto sessionId = _sessionId; | ||||||
| 	do { | 	do { | ||||||
| 		sessionId = openssl::RandomValue<uint64>(); | 		sessionId = openssl::RandomValue<uint64>(); | ||||||
|  | @ -429,13 +353,13 @@ void ConnectionPrivate::changeSessionId() { | ||||||
| 	_receivedMessageIds.clear(); | 	_receivedMessageIds.clear(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uint32 ConnectionPrivate::nextRequestSeqNumber(bool needAck) { | uint32 Connection::nextRequestSeqNumber(bool needAck) { | ||||||
| 	const auto result = _messagesCounter; | 	const auto result = _messagesCounter; | ||||||
| 	_messagesCounter += (needAck ? 1 : 0); | 	_messagesCounter += (needAck ? 1 : 0); | ||||||
| 	return result * 2 + (needAck ? 1 : 0); | 	return result * 2 + (needAck ? 1 : 0); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool ConnectionPrivate::realDcTypeChanged() { | bool Connection::realDcTypeChanged() { | ||||||
| 	const auto now = _instance->dcOptions()->dcType(_shiftedDcId); | 	const auto now = _instance->dcOptions()->dcType(_shiftedDcId); | ||||||
| 	if (_realDcType == now) { | 	if (_realDcType == now) { | ||||||
| 		return false; | 		return false; | ||||||
|  | @ -444,7 +368,7 @@ bool ConnectionPrivate::realDcTypeChanged() { | ||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool ConnectionPrivate::markSessionAsStarted() { | bool Connection::markSessionAsStarted() { | ||||||
| 	if (_sessionMarkedAsStarted) { | 	if (_sessionMarkedAsStarted) { | ||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
|  | @ -452,7 +376,7 @@ bool ConnectionPrivate::markSessionAsStarted() { | ||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| mtpMsgId ConnectionPrivate::prepareToSend( | mtpMsgId Connection::prepareToSend( | ||||||
| 		SerializedRequest &request, | 		SerializedRequest &request, | ||||||
| 		mtpMsgId currentLastId, | 		mtpMsgId currentLastId, | ||||||
| 		bool forceNewMsgId) { | 		bool forceNewMsgId) { | ||||||
|  | @ -477,7 +401,7 @@ mtpMsgId ConnectionPrivate::prepareToSend( | ||||||
| 	return currentLastId; | 	return currentLastId; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| mtpMsgId ConnectionPrivate::replaceMsgId(SerializedRequest &request, mtpMsgId newId) { | mtpMsgId Connection::replaceMsgId(SerializedRequest &request, mtpMsgId newId) { | ||||||
| 	Expects(request->size() > 8); | 	Expects(request->size() > 8); | ||||||
| 
 | 
 | ||||||
| 	const auto oldMsgId = request.getMsgId(); | 	const auto oldMsgId = request.getMsgId(); | ||||||
|  | @ -535,7 +459,7 @@ mtpMsgId ConnectionPrivate::replaceMsgId(SerializedRequest &request, mtpMsgId ne | ||||||
| 	return newId; | 	return newId; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| mtpMsgId ConnectionPrivate::placeToContainer( | mtpMsgId Connection::placeToContainer( | ||||||
| 		SerializedRequest &toSendRequest, | 		SerializedRequest &toSendRequest, | ||||||
| 		mtpMsgId &bigMsgId, | 		mtpMsgId &bigMsgId, | ||||||
| 		bool forceNewMsgId, | 		bool forceNewMsgId, | ||||||
|  | @ -554,7 +478,7 @@ mtpMsgId ConnectionPrivate::placeToContainer( | ||||||
| 	return msgId; | 	return msgId; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::tryToSend() { | void Connection::tryToSend() { | ||||||
| 	if (!_connection || !_keyId) { | 	if (!_connection || !_keyId) { | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  | @ -920,7 +844,7 @@ void ConnectionPrivate::tryToSend() { | ||||||
| 	sendSecureRequest(std::move(toSendRequest), needAnyResponse); | 	sendSecureRequest(std::move(toSendRequest), needAnyResponse); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::retryByTimer() { | void Connection::retryByTimer() { | ||||||
| 	if (_retryTimeout < 3) { | 	if (_retryTimeout < 3) { | ||||||
| 		++_retryTimeout; | 		++_retryTimeout; | ||||||
| 	} else if (_retryTimeout == 3) { | 	} else if (_retryTimeout == 3) { | ||||||
|  | @ -931,18 +855,14 @@ void ConnectionPrivate::retryByTimer() { | ||||||
| 	connectToServer(); | 	connectToServer(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::restartNow() { | void Connection::restartNow() { | ||||||
| 	_retryTimeout = 1; | 	_retryTimeout = 1; | ||||||
| 	_retryTimer.cancel(); | 	_retryTimer.cancel(); | ||||||
| 	restart(); | 	restart(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::connectToServer(bool afterConfig) { | void Connection::connectToServer(bool afterConfig) { | ||||||
| 	if (_finished) { | 	if (afterConfig && (!_testConnections.empty() || _connection)) { | ||||||
| 		DEBUG_LOG(("MTP Error: " |  | ||||||
| 			"connectToServer() called for finished connection!")); |  | ||||||
| 		return; |  | ||||||
| 	} else if (afterConfig && (!_testConnections.empty() || _connection)) { |  | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -1046,7 +966,7 @@ void ConnectionPrivate::connectToServer(bool afterConfig) { | ||||||
| 	_waitForConnectedTimer.callOnce(_waitForConnected); | 	_waitForConnectedTimer.callOnce(_waitForConnected); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::restart() { | void Connection::restart() { | ||||||
| 	DEBUG_LOG(("MTP Info: restarting Connection")); | 	DEBUG_LOG(("MTP Info: restarting Connection")); | ||||||
| 
 | 
 | ||||||
| 	_waitForReceivedTimer.cancel(); | 	_waitForReceivedTimer.cancel(); | ||||||
|  | @ -1066,7 +986,7 @@ void ConnectionPrivate::restart() { | ||||||
| 	setState(-_retryTimeout); | 	setState(-_retryTimeout); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::onSentSome(uint64 size) { | void Connection::onSentSome(uint64 size) { | ||||||
| 	if (!_waitForReceivedTimer.isActive()) { | 	if (!_waitForReceivedTimer.isActive()) { | ||||||
| 		auto remain = static_cast<uint64>(_waitForReceived); | 		auto remain = static_cast<uint64>(_waitForReceived); | ||||||
| 		if (!_oldConnection) { | 		if (!_oldConnection) { | ||||||
|  | @ -1087,7 +1007,7 @@ void ConnectionPrivate::onSentSome(uint64 size) { | ||||||
| 	if (!_firstSentAt) _firstSentAt = crl::now(); | 	if (!_firstSentAt) _firstSentAt = crl::now(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::onReceivedSome() { | void Connection::onReceivedSome() { | ||||||
| 	if (_oldConnection) { | 	if (_oldConnection) { | ||||||
| 		_oldConnection = false; | 		_oldConnection = false; | ||||||
| 		DEBUG_LOG(("This connection marked as not old!")); | 		DEBUG_LOG(("This connection marked as not old!")); | ||||||
|  | @ -1105,13 +1025,13 @@ void ConnectionPrivate::onReceivedSome() { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::markConnectionOld() { | void Connection::markConnectionOld() { | ||||||
| 	_oldConnection = true; | 	_oldConnection = true; | ||||||
| 	_waitForReceived = kMinReceiveTimeout; | 	_waitForReceived = kMinReceiveTimeout; | ||||||
| 	DEBUG_LOG(("This connection marked as old! _waitForReceived now %1ms").arg(_waitForReceived)); | 	DEBUG_LOG(("This connection marked as old! _waitForReceived now %1ms").arg(_waitForReceived)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::sendPingByTimer() { | void Connection::sendPingByTimer() { | ||||||
| 	if (_pingId) { | 	if (_pingId) { | ||||||
| 		// _pingSendAt: when to send next ping (lastPingAt + kPingSendAfter)
 | 		// _pingSendAt: when to send next ping (lastPingAt + kPingSendAfter)
 | ||||||
| 		// could be equal to zero.
 | 		// could be equal to zero.
 | ||||||
|  | @ -1130,7 +1050,7 @@ void ConnectionPrivate::sendPingByTimer() { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::onPingSendForce() { | void Connection::sendPingForce() { | ||||||
| 	if (!_pingId) { | 	if (!_pingId) { | ||||||
| 		_pingSendAt = 0; | 		_pingSendAt = 0; | ||||||
| 		DEBUG_LOG(("Will send ping!")); | 		DEBUG_LOG(("Will send ping!")); | ||||||
|  | @ -1138,7 +1058,7 @@ void ConnectionPrivate::onPingSendForce() { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::waitReceivedFailed() { | void Connection::waitReceivedFailed() { | ||||||
| 	Expects(_connectionOptions != nullptr); | 	Expects(_connectionOptions != nullptr); | ||||||
| 
 | 
 | ||||||
| 	if (!_connectionOptions->useTcp) { | 	if (!_connectionOptions->useTcp) { | ||||||
|  | @ -1158,7 +1078,7 @@ void ConnectionPrivate::waitReceivedFailed() { | ||||||
| 	InvokeQueued(this, [=] { connectToServer(); }); | 	InvokeQueued(this, [=] { connectToServer(); }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::waitConnectedFailed() { | void Connection::waitConnectedFailed() { | ||||||
| 	DEBUG_LOG(("MTP Info: can't connect in %1ms").arg(_waitForConnected)); | 	DEBUG_LOG(("MTP Info: can't connect in %1ms").arg(_waitForConnected)); | ||||||
| 	auto maxTimeout = kMaxConnectedTimeout; | 	auto maxTimeout = kMaxConnectedTimeout; | ||||||
| 	for (const auto &connection : _testConnections) { | 	for (const auto &connection : _testConnections) { | ||||||
|  | @ -1174,46 +1094,29 @@ void ConnectionPrivate::waitConnectedFailed() { | ||||||
| 	InvokeQueued(this, [=] { connectToServer(); }); | 	InvokeQueued(this, [=] { connectToServer(); }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::waitBetterFailed() { | void Connection::waitBetterFailed() { | ||||||
| 	confirmBestConnection(); | 	confirmBestConnection(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::connectingTimedOut() { | void Connection::connectingTimedOut() { | ||||||
| 	for (const auto &connection : _testConnections) { | 	for (const auto &connection : _testConnections) { | ||||||
| 		connection.data->timedOut(); | 		connection.data->timedOut(); | ||||||
| 	} | 	} | ||||||
| 	doDisconnect(); | 	doDisconnect(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::doDisconnect() { | void Connection::doDisconnect() { | ||||||
| 	destroyAllConnections(); | 	destroyAllConnections(); | ||||||
| 	setState(DisconnectedState); | 	setState(DisconnectedState); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::finishAndDestroy() { | void Connection::requestCDNConfig() { | ||||||
| 	doDisconnect(); |  | ||||||
| 	_finished = true; |  | ||||||
| 	const auto connection = _owner; |  | ||||||
| 	const auto instance = _instance; |  | ||||||
| 	InvokeQueued(instance, [=] { |  | ||||||
| 		instance->connectionFinished(connection); |  | ||||||
| 	}); |  | ||||||
| 	deleteLater(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ConnectionPrivate::requestCDNConfig() { |  | ||||||
| 	connect( |  | ||||||
| 		_instance, |  | ||||||
| 		SIGNAL(cdnConfigLoaded()), |  | ||||||
| 		this, |  | ||||||
| 		SLOT(onCDNConfigLoaded()), |  | ||||||
| 		Qt::UniqueConnection); |  | ||||||
| 	InvokeQueued(_instance, [instance = _instance] { | 	InvokeQueued(_instance, [instance = _instance] { | ||||||
| 		instance->requestCDNConfig(); | 		instance->requestCDNConfig(); | ||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::handleReceived() { | void Connection::handleReceived() { | ||||||
| 	Expects(_encryptionKey != nullptr); | 	Expects(_encryptionKey != nullptr); | ||||||
| 
 | 
 | ||||||
| 	onReceivedSome(); | 	onReceivedSome(); | ||||||
|  | @ -1413,7 +1316,7 @@ void ConnectionPrivate::handleReceived() { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived( | Connection::HandleResult Connection::handleOneReceived( | ||||||
| 		const mtpPrime *from, | 		const mtpPrime *from, | ||||||
| 		const mtpPrime *end, | 		const mtpPrime *end, | ||||||
| 		uint64 msgId, | 		uint64 msgId, | ||||||
|  | @ -1931,7 +1834,7 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived( | ||||||
| 	return HandleResult::Success; | 	return HandleResult::Success; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ConnectionPrivate::HandleResult ConnectionPrivate::handleBindResponse( | Connection::HandleResult Connection::handleBindResponse( | ||||||
| 		mtpMsgId requestMsgId, | 		mtpMsgId requestMsgId, | ||||||
| 		const mtpBuffer &response) { | 		const mtpBuffer &response) { | ||||||
| 	if (!_keyCreator || !_bindMsgId || _bindMsgId != requestMsgId) { | 	if (!_keyCreator || !_bindMsgId || _bindMsgId != requestMsgId) { | ||||||
|  | @ -1959,7 +1862,7 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleBindResponse( | ||||||
| 	Unexpected("Result of BoundKeyCreator::handleBindResponse."); | 	Unexpected("Result of BoundKeyCreator::handleBindResponse."); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| mtpBuffer ConnectionPrivate::ungzip(const mtpPrime *from, const mtpPrime *end) const { | mtpBuffer Connection::ungzip(const mtpPrime *from, const mtpPrime *end) const { | ||||||
| 	mtpBuffer result; // * 4 because of mtpPrime type
 | 	mtpBuffer result; // * 4 because of mtpPrime type
 | ||||||
| 	result.resize(0); | 	result.resize(0); | ||||||
| 
 | 
 | ||||||
|  | @ -2011,7 +1914,7 @@ mtpBuffer ConnectionPrivate::ungzip(const mtpPrime *from, const mtpPrime *end) c | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool ConnectionPrivate::requestsFixTimeSalt(const QVector<MTPlong> &ids, int32 serverTime, uint64 serverSalt) { | bool Connection::requestsFixTimeSalt(const QVector<MTPlong> &ids, int32 serverTime, uint64 serverSalt) { | ||||||
| 	uint32 idsCount = ids.size(); | 	uint32 idsCount = ids.size(); | ||||||
| 
 | 
 | ||||||
| 	for (uint32 i = 0; i < idsCount; ++i) { | 	for (uint32 i = 0; i < idsCount; ++i) { | ||||||
|  | @ -2026,7 +1929,7 @@ bool ConnectionPrivate::requestsFixTimeSalt(const QVector<MTPlong> &ids, int32 s | ||||||
| 	return false; | 	return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::requestsAcked(const QVector<MTPlong> &ids, bool byResponse) { | void Connection::requestsAcked(const QVector<MTPlong> &ids, bool byResponse) { | ||||||
| 	uint32 idsCount = ids.size(); | 	uint32 idsCount = ids.size(); | ||||||
| 
 | 
 | ||||||
| 	DEBUG_LOG(("Message Info: requests acked, ids %1").arg(LogIdsVector(ids))); | 	DEBUG_LOG(("Message Info: requests acked, ids %1").arg(LogIdsVector(ids))); | ||||||
|  | @ -2120,7 +2023,7 @@ void ConnectionPrivate::requestsAcked(const QVector<MTPlong> &ids, bool byRespon | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::handleMsgsStates(const QVector<MTPlong> &ids, const QByteArray &states, QVector<MTPlong> &acked) { | void Connection::handleMsgsStates(const QVector<MTPlong> &ids, const QByteArray &states, QVector<MTPlong> &acked) { | ||||||
| 	uint32 idsCount = ids.size(); | 	uint32 idsCount = ids.size(); | ||||||
| 	if (!idsCount) { | 	if (!idsCount) { | ||||||
| 		DEBUG_LOG(("Message Info: void ids vector in handleMsgsStates()")); | 		DEBUG_LOG(("Message Info: void ids vector in handleMsgsStates()")); | ||||||
|  | @ -2163,7 +2066,7 @@ void ConnectionPrivate::handleMsgsStates(const QVector<MTPlong> &ids, const QByt | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::clearSpecialMsgId(mtpMsgId msgId) { | void Connection::clearSpecialMsgId(mtpMsgId msgId) { | ||||||
| 	if (msgId == _pingMsgId) { | 	if (msgId == _pingMsgId) { | ||||||
| 		_pingMsgId = 0; | 		_pingMsgId = 0; | ||||||
| 		_pingId = 0; | 		_pingId = 0; | ||||||
|  | @ -2172,7 +2075,7 @@ void ConnectionPrivate::clearSpecialMsgId(mtpMsgId msgId) { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::resend( | void Connection::resend( | ||||||
| 		mtpMsgId msgId, | 		mtpMsgId msgId, | ||||||
| 		crl::time msCanWait, | 		crl::time msCanWait, | ||||||
| 		bool forceContainer) { | 		bool forceContainer) { | ||||||
|  | @ -2211,7 +2114,7 @@ void ConnectionPrivate::resend( | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::resendAll() { | void Connection::resendAll() { | ||||||
| 	auto toResend = std::vector<mtpMsgId>(); | 	auto toResend = std::vector<mtpMsgId>(); | ||||||
| 
 | 
 | ||||||
| 	auto lock = QReadLocker(_sessionData->haveSentMutex()); | 	auto lock = QReadLocker(_sessionData->haveSentMutex()); | ||||||
|  | @ -2230,7 +2133,7 @@ void ConnectionPrivate::resendAll() { | ||||||
| 	_sessionData->queueSendAnything(); | 	_sessionData->queueSendAnything(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::onConnected( | void Connection::onConnected( | ||||||
| 		not_null<AbstractConnection*> connection) { | 		not_null<AbstractConnection*> connection) { | ||||||
| 	disconnect(connection, &AbstractConnection::connected, nullptr, nullptr); | 	disconnect(connection, &AbstractConnection::connected, nullptr, nullptr); | ||||||
| 	if (!connection->isConnected()) { | 	if (!connection->isConnected()) { | ||||||
|  | @ -2264,7 +2167,7 @@ void ConnectionPrivate::onConnected( | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::onDisconnected( | void Connection::onDisconnected( | ||||||
| 		not_null<AbstractConnection*> connection) { | 		not_null<AbstractConnection*> connection) { | ||||||
| 	removeTestConnection(connection); | 	removeTestConnection(connection); | ||||||
| 
 | 
 | ||||||
|  | @ -2276,7 +2179,7 @@ void ConnectionPrivate::onDisconnected( | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::confirmBestConnection() { | void Connection::confirmBestConnection() { | ||||||
| 	if (_waitForBetterTimer.isActive()) { | 	if (_waitForBetterTimer.isActive()) { | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  | @ -2300,7 +2203,7 @@ void ConnectionPrivate::confirmBestConnection() { | ||||||
| 	checkAuthKey(); | 	checkAuthKey(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::removeTestConnection( | void Connection::removeTestConnection( | ||||||
| 		not_null<AbstractConnection*> connection) { | 		not_null<AbstractConnection*> connection) { | ||||||
| 	_testConnections.erase( | 	_testConnections.erase( | ||||||
| 		ranges::remove( | 		ranges::remove( | ||||||
|  | @ -2310,7 +2213,7 @@ void ConnectionPrivate::removeTestConnection( | ||||||
| 		end(_testConnections)); | 		end(_testConnections)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::checkAuthKey() { | void Connection::checkAuthKey() { | ||||||
| 	if (_keyId) { | 	if (_keyId) { | ||||||
| 		authKeyChecked(); | 		authKeyChecked(); | ||||||
| 	} else if (_instance->isKeysDestroyer()) { | 	} else if (_instance->isKeysDestroyer()) { | ||||||
|  | @ -2321,7 +2224,7 @@ void ConnectionPrivate::checkAuthKey() { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::updateAuthKey() { | void Connection::updateAuthKey() { | ||||||
| 	if (_instance->isKeysDestroyer() || _keyCreator || !_connection) { | 	if (_instance->isKeysDestroyer() || _keyCreator || !_connection) { | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  | @ -2339,7 +2242,7 @@ void ConnectionPrivate::updateAuthKey() { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::setCurrentKeyId(uint64 newKeyId) { | void Connection::setCurrentKeyId(uint64 newKeyId) { | ||||||
| 	if (_keyId == newKeyId) { | 	if (_keyId == newKeyId) { | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  | @ -2349,7 +2252,7 @@ void ConnectionPrivate::setCurrentKeyId(uint64 newKeyId) { | ||||||
| 	changeSessionId(); | 	changeSessionId(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::applyAuthKey(AuthKeyPtr &&encryptionKey) { | void Connection::applyAuthKey(AuthKeyPtr &&encryptionKey) { | ||||||
| 	_encryptionKey = std::move(encryptionKey); | 	_encryptionKey = std::move(encryptionKey); | ||||||
| 	const auto newKeyId = _encryptionKey ? _encryptionKey->keyId() : 0; | 	const auto newKeyId = _encryptionKey ? _encryptionKey->keyId() : 0; | ||||||
| 	if (_keyId) { | 	if (_keyId) { | ||||||
|  | @ -2391,7 +2294,7 @@ void ConnectionPrivate::applyAuthKey(AuthKeyPtr &&encryptionKey) { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool ConnectionPrivate::destroyOldEnoughPersistentKey() { | bool Connection::destroyOldEnoughPersistentKey() { | ||||||
| 	Expects(_keyCreator != nullptr); | 	Expects(_keyCreator != nullptr); | ||||||
| 
 | 
 | ||||||
| 	const auto key = _keyCreator->bindPersistentKey(); | 	const auto key = _keyCreator->bindPersistentKey(); | ||||||
|  | @ -2410,7 +2313,7 @@ bool ConnectionPrivate::destroyOldEnoughPersistentKey() { | ||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| DcType ConnectionPrivate::tryAcquireKeyCreation() { | DcType Connection::tryAcquireKeyCreation() { | ||||||
| 	if (_keyCreator) { | 	if (_keyCreator) { | ||||||
| 		return _currentDcType; | 		return _currentDcType; | ||||||
| 	} else if (_instance->isKeysDestroyer()) { | 	} else if (_instance->isKeysDestroyer()) { | ||||||
|  | @ -2484,7 +2387,7 @@ DcType ConnectionPrivate::tryAcquireKeyCreation() { | ||||||
| 	return forceUseRegular ? DcType::Regular : _realDcType; | 	return forceUseRegular ? DcType::Regular : _realDcType; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::authKeyChecked() { | void Connection::authKeyChecked() { | ||||||
| 	connect(_connection, &AbstractConnection::receivedData, [=] { | 	connect(_connection, &AbstractConnection::receivedData, [=] { | ||||||
| 		handleReceived(); | 		handleReceived(); | ||||||
| 	}); | 	}); | ||||||
|  | @ -2497,7 +2400,7 @@ void ConnectionPrivate::authKeyChecked() { | ||||||
| 	_sessionData->queueNeedToResumeAndSend(); | 	_sessionData->queueNeedToResumeAndSend(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::onError( | void Connection::onError( | ||||||
| 		not_null<AbstractConnection*> connection, | 		not_null<AbstractConnection*> connection, | ||||||
| 		qint32 errorCode) { | 		qint32 errorCode) { | ||||||
| 	if (errorCode == -429) { | 	if (errorCode == -429) { | ||||||
|  | @ -2517,7 +2420,7 @@ void ConnectionPrivate::onError( | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::handleError(int errorCode) { | void Connection::handleError(int errorCode) { | ||||||
| 	destroyAllConnections(); | 	destroyAllConnections(); | ||||||
| 	_waitForConnectedTimer.cancel(); | 	_waitForConnectedTimer.cancel(); | ||||||
| 
 | 
 | ||||||
|  | @ -2529,7 +2432,7 @@ void ConnectionPrivate::handleError(int errorCode) { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::destroyTemporaryKey() { | void Connection::destroyTemporaryKey() { | ||||||
| 	if (_instance->isKeysDestroyer()) { | 	if (_instance->isKeysDestroyer()) { | ||||||
| 		LOG(("MTP Info: -404 error received in destroyer %1, assuming key was destroyed.").arg(_shiftedDcId)); | 		LOG(("MTP Info: -404 error received in destroyer %1, assuming key was destroyed.").arg(_shiftedDcId)); | ||||||
| 		_instance->keyWasPossiblyDestroyed(_shiftedDcId); | 		_instance->keyWasPossiblyDestroyed(_shiftedDcId); | ||||||
|  | @ -2544,7 +2447,7 @@ void ConnectionPrivate::destroyTemporaryKey() { | ||||||
| 	restart(); | 	restart(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool ConnectionPrivate::sendSecureRequest( | bool Connection::sendSecureRequest( | ||||||
| 		SerializedRequest &&request, | 		SerializedRequest &&request, | ||||||
| 		bool needAnyResponse) { | 		bool needAnyResponse) { | ||||||
| #ifdef TDESKTOP_MTPROTO_OLD | #ifdef TDESKTOP_MTPROTO_OLD | ||||||
|  | @ -2628,7 +2531,7 @@ bool ConnectionPrivate::sendSecureRequest( | ||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| mtpRequestId ConnectionPrivate::wasSent(mtpMsgId msgId) const { | mtpRequestId Connection::wasSent(mtpMsgId msgId) const { | ||||||
| 	if (msgId == _pingMsgId || msgId == _bindMsgId) { | 	if (msgId == _pingMsgId || msgId == _bindMsgId) { | ||||||
| 		return mtpRequestId(0xFFFFFFFF); | 		return mtpRequestId(0xFFFFFFFF); | ||||||
| 	} | 	} | ||||||
|  | @ -2651,13 +2554,13 @@ mtpRequestId ConnectionPrivate::wasSent(mtpMsgId msgId) const { | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::clearUnboundKeyCreator() { | void Connection::clearUnboundKeyCreator() { | ||||||
| 	if (_keyCreator) { | 	if (_keyCreator) { | ||||||
| 		_keyCreator->stop(); | 		_keyCreator->stop(); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::releaseKeyCreationOnFail() { | void Connection::releaseKeyCreationOnFail() { | ||||||
| 	if (!_keyCreator) { | 	if (!_keyCreator) { | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  | @ -2665,8 +2568,5 @@ void ConnectionPrivate::releaseKeyCreationOnFail() { | ||||||
| 	_sessionData->releaseKeyCreationOnFail(); | 	_sessionData->releaseKeyCreationOnFail(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::stop() { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| } // namespace internal
 | } // namespace internal
 | ||||||
| } // namespace MTP
 | } // namespace MTP
 | ||||||
|  |  | ||||||
|  | @ -29,72 +29,34 @@ class Instance; | ||||||
| namespace internal { | namespace internal { | ||||||
| 
 | 
 | ||||||
| class AbstractConnection; | class AbstractConnection; | ||||||
| class ConnectionPrivate; |  | ||||||
| class SessionData; | class SessionData; | ||||||
| class RSAPublicKey; | class RSAPublicKey; | ||||||
| struct ConnectionOptions; | struct ConnectionOptions; | ||||||
| 
 | 
 | ||||||
| class Connection { | class Connection : public QObject { | ||||||
| public: | public: | ||||||
| 	enum ConnectionType { | 	Connection( | ||||||
| 		TcpConnection, |  | ||||||
| 		HttpConnection |  | ||||||
| 	}; |  | ||||||
| 
 |  | ||||||
| 	Connection(not_null<Instance*> instance); |  | ||||||
| 	~Connection(); |  | ||||||
| 
 |  | ||||||
| 	void start(std::shared_ptr<SessionData> data, ShiftedDcId shiftedDcId); |  | ||||||
| 
 |  | ||||||
| 	void kill(); |  | ||||||
| 	void waitTillFinish(); |  | ||||||
| 
 |  | ||||||
| 	static const int UpdateAlways = 666; |  | ||||||
| 
 |  | ||||||
| 	int32 state() const; |  | ||||||
| 	QString transport() const; |  | ||||||
| 
 |  | ||||||
| private: |  | ||||||
| 	not_null<Instance*> _instance; |  | ||||||
| 	std::unique_ptr<QThread> _thread; |  | ||||||
| 	ConnectionPrivate *_private = nullptr; |  | ||||||
| 	rpl::lifetime _lifetime; |  | ||||||
| 
 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| class ConnectionPrivate : public QObject { |  | ||||||
| 	Q_OBJECT |  | ||||||
| 
 |  | ||||||
| public: |  | ||||||
| 	ConnectionPrivate( |  | ||||||
| 		not_null<Instance*> instance, | 		not_null<Instance*> instance, | ||||||
| 		not_null<QThread*> thread, | 		not_null<QThread*> thread, | ||||||
| 		not_null<Connection*> owner, |  | ||||||
| 		std::shared_ptr<SessionData> data, | 		std::shared_ptr<SessionData> data, | ||||||
| 		ShiftedDcId shiftedDcId); | 		ShiftedDcId shiftedDcId); | ||||||
| 	~ConnectionPrivate(); | 	~Connection(); | ||||||
| 
 | 
 | ||||||
| 	void stop(); | 	[[nodiscard]] int32 getShiftedDcId() const; | ||||||
| 
 |  | ||||||
| 	int32 getShiftedDcId() const; |  | ||||||
| 	void dcOptionsChanged(); | 	void dcOptionsChanged(); | ||||||
|  | 	void cdnConfigChanged(); | ||||||
| 
 | 
 | ||||||
| 	int32 getState() const; | 	[[nodiscard]] int32 getState() const; | ||||||
| 	QString transport() const; | 	[[nodiscard]] QString transport() const; | ||||||
| 
 |  | ||||||
| public slots: |  | ||||||
| 	void restartNow(); |  | ||||||
| 
 |  | ||||||
| 	void onPingSendForce(); |  | ||||||
| 
 |  | ||||||
| 	// Sessions signals, when we need to send something
 |  | ||||||
| 	void tryToSend(); |  | ||||||
| 
 | 
 | ||||||
| 	void updateAuthKey(); | 	void updateAuthKey(); | ||||||
| 
 | 	void restartNow(); | ||||||
| 	void onCDNConfigLoaded(); | 	void sendPingForce(); | ||||||
|  | 	void tryToSend(); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|  | 	static constexpr auto kUpdateStateAlways = 666; | ||||||
|  | 
 | ||||||
| 	struct TestConnection { | 	struct TestConnection { | ||||||
| 		ConnectionPointer data; | 		ConnectionPointer data; | ||||||
| 		int priority = 0; | 		int priority = 0; | ||||||
|  | @ -113,7 +75,6 @@ private: | ||||||
| 	void connectingTimedOut(); | 	void connectingTimedOut(); | ||||||
| 	void doDisconnect(); | 	void doDisconnect(); | ||||||
| 	void restart(); | 	void restart(); | ||||||
| 	void finishAndDestroy(); |  | ||||||
| 	void requestCDNConfig(); | 	void requestCDNConfig(); | ||||||
| 	void handleError(int errorCode); | 	void handleError(int errorCode); | ||||||
| 	void onError( | 	void onError( | ||||||
|  | @ -167,7 +128,7 @@ private: | ||||||
| 	void handleMsgsStates(const QVector<MTPlong> &ids, const QByteArray &states, QVector<MTPlong> &acked); | 	void handleMsgsStates(const QVector<MTPlong> &ids, const QByteArray &states, QVector<MTPlong> &acked); | ||||||
| 
 | 
 | ||||||
| 	// _sessionDataMutex must be locked for read.
 | 	// _sessionDataMutex must be locked for read.
 | ||||||
| 	bool setState(int32 state, int32 ifState = Connection::UpdateAlways); | 	bool setState(int state, int ifState = kUpdateStateAlways); | ||||||
| 
 | 
 | ||||||
| 	void appendTestConnection( | 	void appendTestConnection( | ||||||
| 		DcOptions::Variants::Protocol protocol, | 		DcOptions::Variants::Protocol protocol, | ||||||
|  | @ -206,13 +167,12 @@ private: | ||||||
| 	[[nodiscard]] bool realDcTypeChanged(); | 	[[nodiscard]] bool realDcTypeChanged(); | ||||||
| 
 | 
 | ||||||
| 	const not_null<Instance*> _instance; | 	const not_null<Instance*> _instance; | ||||||
| 	const not_null<Connection*> _owner; |  | ||||||
| 	const ShiftedDcId _shiftedDcId = 0; | 	const ShiftedDcId _shiftedDcId = 0; | ||||||
| 	DcType _realDcType = DcType(); | 	DcType _realDcType = DcType(); | ||||||
| 	DcType _currentDcType = DcType(); | 	DcType _currentDcType = DcType(); | ||||||
| 
 | 
 | ||||||
| 	mutable QReadWriteLock _stateMutex; | 	mutable QReadWriteLock _stateMutex; | ||||||
| 	int32 _state = DisconnectedState; | 	int _state = DisconnectedState; | ||||||
| 
 | 
 | ||||||
| 	bool _needSessionReset = false; | 	bool _needSessionReset = false; | ||||||
| 
 | 
 | ||||||
|  | @ -241,8 +201,6 @@ private: | ||||||
| 	base::Timer _pingSender; | 	base::Timer _pingSender; | ||||||
| 	base::Timer _checkSentRequestsTimer; | 	base::Timer _checkSentRequestsTimer; | ||||||
| 
 | 
 | ||||||
| 	bool _finished = false; |  | ||||||
| 
 |  | ||||||
| 	std::shared_ptr<SessionData> _sessionData; | 	std::shared_ptr<SessionData> _sessionData; | ||||||
| 	std::unique_ptr<ConnectionOptions> _connectionOptions; | 	std::unique_ptr<ConnectionOptions> _connectionOptions; | ||||||
| 	AuthKeyPtr _encryptionKey; | 	AuthKeyPtr _encryptionKey; | ||||||
|  |  | ||||||
|  | @ -68,6 +68,11 @@ public: | ||||||
| 	: _that(that) | 	: _that(that) | ||||||
| 	, _lock(&_that->_useThroughLockers) { | 	, _lock(&_that->_useThroughLockers) { | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	void unlock() { | ||||||
|  | 		_lock.unlock(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	~WriteLocker() { | 	~WriteLocker() { | ||||||
| 		_that->computeCdnDcIds(); | 		_that->computeCdnDcIds(); | ||||||
| 	} | 	} | ||||||
|  | @ -84,6 +89,10 @@ public: | ||||||
| 	: _lock(&that->_useThroughLockers) { | 	: _lock(&that->_useThroughLockers) { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	void unlock() { | ||||||
|  | 		_lock.unlock(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
| 	QReadLocker _lock; | 	QReadLocker _lock; | ||||||
| 
 | 
 | ||||||
|  | @ -517,6 +526,10 @@ rpl::producer<DcId> DcOptions::changed() const { | ||||||
| 	return _changed.events(); | 	return _changed.events(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | rpl::producer<> DcOptions::cdnConfigChanged() const { | ||||||
|  | 	return _cdnConfigChanged.events(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| std::vector<DcId> DcOptions::configEnumDcIds() const { | std::vector<DcId> DcOptions::configEnumDcIds() const { | ||||||
| 	auto result = std::vector<DcId>(); | 	auto result = std::vector<DcId>(); | ||||||
| 	{ | 	{ | ||||||
|  | @ -553,20 +566,23 @@ DcType DcOptions::dcType(ShiftedDcId shiftedDcId) const { | ||||||
| void DcOptions::setCDNConfig(const MTPDcdnConfig &config) { | void DcOptions::setCDNConfig(const MTPDcdnConfig &config) { | ||||||
| 	WriteLocker lock(this); | 	WriteLocker lock(this); | ||||||
| 	_cdnPublicKeys.clear(); | 	_cdnPublicKeys.clear(); | ||||||
| 	for_const (auto &publicKey, config.vpublic_keys().v) { | 	for (const auto &key : config.vpublic_keys().v) { | ||||||
| 		Expects(publicKey.type() == mtpc_cdnPublicKey); | 		key.match([&](const MTPDcdnPublicKey &data) { | ||||||
| 		const auto &keyData = publicKey.c_cdnPublicKey(); | 			const auto keyBytes = bytes::make_span(data.vpublic_key().v); | ||||||
| 		const auto keyBytes = bytes::make_span(keyData.vpublic_key().v); | 			auto key = internal::RSAPublicKey(keyBytes); | ||||||
| 		auto key = internal::RSAPublicKey(keyBytes); | 			if (key.valid()) { | ||||||
| 		if (key.valid()) { | 				_cdnPublicKeys[data.vdc_id().v].emplace( | ||||||
| 			_cdnPublicKeys[keyData.vdc_id().v].emplace( | 					key.fingerprint(), | ||||||
| 				key.fingerprint(), | 					std::move(key)); | ||||||
| 				std::move(key)); | 			} else { | ||||||
| 		} else { | 				LOG(("MTP Error: could not read this public RSA key:")); | ||||||
| 			LOG(("MTP Error: could not read this public RSA key:")); | 				LOG((qs(data.vpublic_key()))); | ||||||
| 			LOG((qs(keyData.vpublic_key()))); | 			} | ||||||
| 		} | 		}); | ||||||
| 	} | 	} | ||||||
|  | 	lock.unlock(); | ||||||
|  | 
 | ||||||
|  | 	_cdnConfigChanged.fire({}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool DcOptions::hasCDNKeysForDc(DcId dcId) const { | bool DcOptions::hasCDNKeysForDc(DcId dcId) const { | ||||||
|  |  | ||||||
|  | @ -67,6 +67,7 @@ public: | ||||||
| 	QByteArray serialize() const; | 	QByteArray serialize() const; | ||||||
| 
 | 
 | ||||||
| 	[[nodiscard]] rpl::producer<DcId> changed() const; | 	[[nodiscard]] rpl::producer<DcId> changed() const; | ||||||
|  | 	[[nodiscard]] rpl::producer<> cdnConfigChanged() const; | ||||||
| 	void setFromList(const MTPVector<MTPDcOption> &options); | 	void setFromList(const MTPVector<MTPDcOption> &options); | ||||||
| 	void addFromList(const MTPVector<MTPDcOption> &options); | 	void addFromList(const MTPVector<MTPDcOption> &options); | ||||||
| 	void addFromOther(DcOptions &&options); | 	void addFromOther(DcOptions &&options); | ||||||
|  | @ -141,6 +142,7 @@ private: | ||||||
| 	mutable QReadWriteLock _useThroughLockers; | 	mutable QReadWriteLock _useThroughLockers; | ||||||
| 
 | 
 | ||||||
| 	rpl::event_stream<DcId> _changed; | 	rpl::event_stream<DcId> _changed; | ||||||
|  | 	rpl::event_stream<> _cdnConfigChanged; | ||||||
| 
 | 
 | ||||||
| 	// True when we have overriden options from a .tdesktop-endpoints file.
 | 	// True when we have overriden options from a .tdesktop-endpoints file.
 | ||||||
| 	bool _immutable = false; | 	bool _immutable = false; | ||||||
|  |  | ||||||
|  | @ -71,6 +71,7 @@ public: | ||||||
| 	[[nodiscard]] rpl::producer<DcId> dcTemporaryKeyChanged() const; | 	[[nodiscard]] rpl::producer<DcId> dcTemporaryKeyChanged() const; | ||||||
| 	[[nodiscard]] AuthKeysList getKeysForWrite() const; | 	[[nodiscard]] AuthKeysList getKeysForWrite() const; | ||||||
| 	void addKeysForDestroy(AuthKeysList &&keys); | 	void addKeysForDestroy(AuthKeysList &&keys); | ||||||
|  | 	[[nodiscard]] rpl::producer<> allKeysDestroyed() const; | ||||||
| 
 | 
 | ||||||
| 	[[nodiscard]] not_null<DcOptions*> dcOptions(); | 	[[nodiscard]] not_null<DcOptions*> dcOptions(); | ||||||
| 
 | 
 | ||||||
|  | @ -106,10 +107,6 @@ public: | ||||||
| 	void removeDc(ShiftedDcId shiftedDcId); | 	void removeDc(ShiftedDcId shiftedDcId); | ||||||
| 	void unpaused(); | 	void unpaused(); | ||||||
| 
 | 
 | ||||||
| 	void queueQuittingConnection( |  | ||||||
| 		std::unique_ptr<Connection> &&connection); |  | ||||||
| 	void connectionFinished(not_null<Connection*> connection); |  | ||||||
| 
 |  | ||||||
| 	void sendRequest( | 	void sendRequest( | ||||||
| 		mtpRequestId requestId, | 		mtpRequestId requestId, | ||||||
| 		SerializedRequest &&request, | 		SerializedRequest &&request, | ||||||
|  | @ -216,8 +213,6 @@ private: | ||||||
| 	base::flat_map<ShiftedDcId, std::unique_ptr<Session>> _sessions; | 	base::flat_map<ShiftedDcId, std::unique_ptr<Session>> _sessions; | ||||||
| 	std::vector<std::unique_ptr<Session>> _sessionsToDestroy; | 	std::vector<std::unique_ptr<Session>> _sessionsToDestroy; | ||||||
| 
 | 
 | ||||||
| 	std::vector<std::unique_ptr<Connection>> _connectionsToDestroy; |  | ||||||
| 
 |  | ||||||
| 	std::unique_ptr<ConfigLoader> _configLoader; | 	std::unique_ptr<ConfigLoader> _configLoader; | ||||||
| 	std::unique_ptr<DomainResolver> _domainResolver; | 	std::unique_ptr<DomainResolver> _domainResolver; | ||||||
| 	std::unique_ptr<SpecialConfigRequest> _httpUnixtimeLoader; | 	std::unique_ptr<SpecialConfigRequest> _httpUnixtimeLoader; | ||||||
|  | @ -229,6 +224,8 @@ private: | ||||||
| 	base::flat_map<DcId, AuthKeyPtr> _keysForWrite; | 	base::flat_map<DcId, AuthKeyPtr> _keysForWrite; | ||||||
| 	base::flat_map<ShiftedDcId, mtpRequestId> _logoutGuestRequestIds; | 	base::flat_map<ShiftedDcId, mtpRequestId> _logoutGuestRequestIds; | ||||||
| 
 | 
 | ||||||
|  | 	rpl::event_stream<> _allKeysDestroyed; | ||||||
|  | 
 | ||||||
| 	// holds dcWithShift for request to this dc or -dc for request to main dc
 | 	// holds dcWithShift for request to this dc or -dc for request to main dc
 | ||||||
| 	std::map<mtpRequestId, ShiftedDcId> _requestsByDc; | 	std::map<mtpRequestId, ShiftedDcId> _requestsByDc; | ||||||
| 	mutable QMutex _requestByDcLock; | 	mutable QMutex _requestByDcLock; | ||||||
|  | @ -480,13 +477,10 @@ void Instance::Private::requestCDNConfig() { | ||||||
| 		MTPhelp_GetCdnConfig() | 		MTPhelp_GetCdnConfig() | ||||||
| 	).done([this](const MTPCdnConfig &result) { | 	).done([this](const MTPCdnConfig &result) { | ||||||
| 		_cdnConfigLoadRequestId = 0; | 		_cdnConfigLoadRequestId = 0; | ||||||
| 
 | 		result.match([&](const MTPDcdnConfig &data) { | ||||||
| 		Expects(result.type() == mtpc_cdnConfig); | 			dcOptions()->setCDNConfig(data); | ||||||
| 		dcOptions()->setCDNConfig(result.c_cdnConfig()); | 		}); | ||||||
| 
 |  | ||||||
| 		Local::writeSettings(); | 		Local::writeSettings(); | ||||||
| 
 |  | ||||||
| 		emit _instance->cdnConfigLoaded(); |  | ||||||
| 	}).send(); | 	}).send(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -759,6 +753,10 @@ void Instance::Private::addKeysForDestroy(AuthKeysList &&keys) { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | rpl::producer<> Instance::Private::allKeysDestroyed() const { | ||||||
|  | 	return _allKeysDestroyed.events(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| not_null<DcOptions*> Instance::Private::dcOptions() { | not_null<DcOptions*> Instance::Private::dcOptions() { | ||||||
| 	return _dcOptions; | 	return _dcOptions; | ||||||
| } | } | ||||||
|  | @ -777,22 +775,6 @@ void Instance::Private::unpaused() { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Instance::Private::queueQuittingConnection( |  | ||||||
| 		std::unique_ptr<Connection> &&connection) { |  | ||||||
| 	_connectionsToDestroy.push_back(std::move(connection)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Instance::Private::connectionFinished( |  | ||||||
| 		not_null<Connection*> connection) { |  | ||||||
| 	const auto i = ranges::find( |  | ||||||
| 		_connectionsToDestroy, |  | ||||||
| 		connection.get(), |  | ||||||
| 		&std::unique_ptr<Connection>::get); |  | ||||||
| 	if (i != _connectionsToDestroy.end()) { |  | ||||||
| 		_connectionsToDestroy.erase(i); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Instance::Private::configLoadDone(const MTPConfig &result) { | void Instance::Private::configLoadDone(const MTPConfig &result) { | ||||||
| 	Expects(result.type() == mtpc_config); | 	Expects(result.type() == mtpc_config); | ||||||
| 
 | 
 | ||||||
|  | @ -1582,7 +1564,7 @@ void Instance::Private::completedKeyDestroy(ShiftedDcId shiftedDcId) { | ||||||
| 	_keysForWrite.erase(shiftedDcId); | 	_keysForWrite.erase(shiftedDcId); | ||||||
| 	killSession(shiftedDcId); | 	killSession(shiftedDcId); | ||||||
| 	if (_dcenters.empty()) { | 	if (_dcenters.empty()) { | ||||||
| 		emit _instance->allKeysDestroyed(); | 		_allKeysDestroyed.fire({}); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1674,6 +1656,10 @@ QString Instance::langPackName() const { | ||||||
| 	return Lang::Current().langPackName(); | 	return Lang::Current().langPackName(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | rpl::producer<> Instance::allKeysDestroyed() const { | ||||||
|  | 	return _private->allKeysDestroyed(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void Instance::requestConfig() { | void Instance::requestConfig() { | ||||||
| 	_private->requestConfig(); | 	_private->requestConfig(); | ||||||
| } | } | ||||||
|  | @ -1698,10 +1684,6 @@ void Instance::requestCDNConfig() { | ||||||
| 	_private->requestCDNConfig(); | 	_private->requestCDNConfig(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Instance::connectionFinished(not_null<Connection*> connection) { |  | ||||||
| 	_private->connectionFinished(connection); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Instance::restart() { | void Instance::restart() { | ||||||
| 	_private->restart(); | 	_private->restart(); | ||||||
| } | } | ||||||
|  | @ -1784,11 +1766,6 @@ void Instance::unpaused() { | ||||||
| 	_private->unpaused(); | 	_private->unpaused(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Instance::queueQuittingConnection( |  | ||||||
| 		std::unique_ptr<Connection> &&connection) { |  | ||||||
| 	_private->queueQuittingConnection(std::move(connection)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Instance::setUpdatesHandler(RPCDoneHandlerPtr onDone) { | void Instance::setUpdatesHandler(RPCDoneHandlerPtr onDone) { | ||||||
| 	_private->setUpdatesHandler(onDone); | 	_private->setUpdatesHandler(onDone); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -15,7 +15,6 @@ namespace internal { | ||||||
| 
 | 
 | ||||||
| class Dcenter; | class Dcenter; | ||||||
| class Session; | class Session; | ||||||
| class Connection; |  | ||||||
| 
 | 
 | ||||||
| [[nodiscard]] int GetNextRequestId(); | [[nodiscard]] int GetNextRequestId(); | ||||||
| 
 | 
 | ||||||
|  | @ -61,6 +60,8 @@ public: | ||||||
| 	[[nodiscard]] QString cloudLangCode() const; | 	[[nodiscard]] QString cloudLangCode() const; | ||||||
| 	[[nodiscard]] QString langPackName() const; | 	[[nodiscard]] QString langPackName() const; | ||||||
| 
 | 
 | ||||||
|  | 	[[nodiscard]] rpl::producer<> allKeysDestroyed() const; | ||||||
|  | 
 | ||||||
| 	// Thread-safe.
 | 	// Thread-safe.
 | ||||||
| 	[[nodiscard]] QString deviceModel() const; | 	[[nodiscard]] QString deviceModel() const; | ||||||
| 	[[nodiscard]] QString systemVersion() const; | 	[[nodiscard]] QString systemVersion() const; | ||||||
|  | @ -90,8 +91,6 @@ public: | ||||||
| 
 | 
 | ||||||
| 	void unpaused(); | 	void unpaused(); | ||||||
| 
 | 
 | ||||||
| 	void queueQuittingConnection(std::unique_ptr<internal::Connection> &&connection); |  | ||||||
| 
 |  | ||||||
| 	void setUpdatesHandler(RPCDoneHandlerPtr onDone); | 	void setUpdatesHandler(RPCDoneHandlerPtr onDone); | ||||||
| 	void setGlobalFailHandler(RPCFailHandlerPtr onFail); | 	void setGlobalFailHandler(RPCFailHandlerPtr onFail); | ||||||
| 	void setStateChangedHandler(Fn<void(ShiftedDcId shiftedDcId, int32 state)> handler); | 	void setStateChangedHandler(Fn<void(ShiftedDcId shiftedDcId, int32 state)> handler); | ||||||
|  | @ -126,8 +125,6 @@ public: | ||||||
| 
 | 
 | ||||||
| 	void syncHttpUnixtime(); | 	void syncHttpUnixtime(); | ||||||
| 
 | 
 | ||||||
| 	void connectionFinished(not_null<internal::Connection*> connection); |  | ||||||
| 
 |  | ||||||
| 	void sendAnything(ShiftedDcId shiftedDcId = 0, crl::time msCanWait = 0); | 	void sendAnything(ShiftedDcId shiftedDcId = 0, crl::time msCanWait = 0); | ||||||
| 
 | 
 | ||||||
| 	template <typename Request> | 	template <typename Request> | ||||||
|  | @ -199,8 +196,6 @@ public: | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| signals: | signals: | ||||||
| 	void cdnConfigLoaded(); |  | ||||||
| 	void allKeysDestroyed(); |  | ||||||
| 	void proxyDomainResolved( | 	void proxyDomainResolved( | ||||||
| 		QString host, | 		QString host, | ||||||
| 		QStringList ips, | 		QStringList ips, | ||||||
|  |  | ||||||
|  | @ -148,8 +148,7 @@ Session::Session( | ||||||
| 	not_null<Instance*> instance, | 	not_null<Instance*> instance, | ||||||
| 	ShiftedDcId shiftedDcId, | 	ShiftedDcId shiftedDcId, | ||||||
| 	not_null<Dcenter*> dc) | 	not_null<Dcenter*> dc) | ||||||
| : QObject() | : _instance(instance) | ||||||
| , _instance(instance) |  | ||||||
| , _shiftedDcId(shiftedDcId) | , _shiftedDcId(shiftedDcId) | ||||||
| , _dc(dc) | , _dc(dc) | ||||||
| , _data(std::make_shared<SessionData>(this)) | , _data(std::make_shared<SessionData>(this)) | ||||||
|  | @ -157,6 +156,19 @@ Session::Session( | ||||||
| 	_timeouter.callEach(1000); | 	_timeouter.callEach(1000); | ||||||
| 	refreshOptions(); | 	refreshOptions(); | ||||||
| 	watchDcKeyChanges(); | 	watchDcKeyChanges(); | ||||||
|  | 	watchDcOptionsChanges(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Session::~Session() { | ||||||
|  | 	Expects(!_connection); | ||||||
|  | 	Expects(!_thread); | ||||||
|  | 
 | ||||||
|  | 	if (_myKeyCreation != CreatingKeyType::None) { | ||||||
|  | 		releaseKeyCreationOnFail(); | ||||||
|  | 	} | ||||||
|  | 	for (const auto &thread : _destroyingThreads) { | ||||||
|  | 		thread->wait(); | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Session::watchDcKeyChanges() { | void Session::watchDcKeyChanges() { | ||||||
|  | @ -166,13 +178,59 @@ void Session::watchDcKeyChanges() { | ||||||
| 	}) | rpl::start_with_next([=] { | 	}) | rpl::start_with_next([=] { | ||||||
| 		DEBUG_LOG(("AuthKey Info: Session::authKeyCreatedForDC slot, " | 		DEBUG_LOG(("AuthKey Info: Session::authKeyCreatedForDC slot, " | ||||||
| 			"emitting authKeyChanged(), dcWithShift %1").arg(_shiftedDcId)); | 			"emitting authKeyChanged(), dcWithShift %1").arg(_shiftedDcId)); | ||||||
| 		emit authKeyChanged(); | 		if (const auto connection = _connection) { | ||||||
|  | 			InvokeQueued(connection, [=] { | ||||||
|  | 				connection->updateAuthKey(); | ||||||
|  | 			}); | ||||||
|  | 		} | ||||||
| 	}, _lifetime); | 	}, _lifetime); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void Session::watchDcOptionsChanges() { | ||||||
|  | 	_instance->dcOptions()->changed( | ||||||
|  | 	) | rpl::filter([=](DcId dcId) { | ||||||
|  | 		return (BareDcId(_shiftedDcId) == dcId) && (_connection != nullptr); | ||||||
|  | 	}) | rpl::start_with_next([=] { | ||||||
|  | 		InvokeQueued(_connection, [connection = _connection] { | ||||||
|  | 			connection->dcOptionsChanged(); | ||||||
|  | 		}); | ||||||
|  | 	}, _lifetime); | ||||||
|  | 
 | ||||||
|  | 	if (_instance->dcOptions()->dcType(_shiftedDcId) == DcType::Cdn) { | ||||||
|  | 		_instance->dcOptions()->cdnConfigChanged( | ||||||
|  | 		) | rpl::filter([=] { | ||||||
|  | 			return (_connection != nullptr); | ||||||
|  | 		}) | rpl::start_with_next([=] { | ||||||
|  | 			InvokeQueued(_connection, [connection = _connection] { | ||||||
|  | 				connection->cdnConfigChanged(); | ||||||
|  | 			}); | ||||||
|  | 		}, _lifetime); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void Session::start() { | void Session::start() { | ||||||
| 	_connection = std::make_unique<Connection>(_instance); | 	killConnection(); | ||||||
| 	_connection->start(_data, _shiftedDcId); | 
 | ||||||
|  | 	_thread = std::make_unique<QThread>(); | ||||||
|  | 	const auto thread = _thread.get(); | ||||||
|  | 
 | ||||||
|  | 	connect(thread, &QThread::finished, [=] { | ||||||
|  | 		InvokeQueued(this, [=] { | ||||||
|  | 			const auto i = ranges::find( | ||||||
|  | 				_destroyingThreads, | ||||||
|  | 				thread, | ||||||
|  | 				&std::unique_ptr<QThread>::get); | ||||||
|  | 			if (i != _destroyingThreads.end()) { | ||||||
|  | 				_destroyingThreads.erase(i); | ||||||
|  | 			} | ||||||
|  | 		}); | ||||||
|  | 	}); | ||||||
|  | 	_connection = new Connection( | ||||||
|  | 		_instance, | ||||||
|  | 		thread, | ||||||
|  | 		_data, | ||||||
|  | 		_shiftedDcId); | ||||||
|  | 	thread->start(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool Session::rpcErrorOccured( | bool Session::rpcErrorOccured( | ||||||
|  | @ -188,7 +246,11 @@ void Session::restart() { | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 	refreshOptions(); | 	refreshOptions(); | ||||||
| 	emit needToRestart(); | 	if (const auto connection = _connection) { | ||||||
|  | 		InvokeQueued(connection, [=] { | ||||||
|  | 			connection->restartNow(); | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Session::refreshOptions() { | void Session::refreshOptions() { | ||||||
|  | @ -221,14 +283,11 @@ void Session::reInitConnection() { | ||||||
| 
 | 
 | ||||||
| void Session::stop() { | void Session::stop() { | ||||||
| 	if (_killed) { | 	if (_killed) { | ||||||
| 		DEBUG_LOG(("Session Error: can't kill a killed session")); | 		DEBUG_LOG(("Session Error: can't stop a killed session")); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 	DEBUG_LOG(("Session Info: stopping session dcWithShift %1").arg(_shiftedDcId)); | 	DEBUG_LOG(("Session Info: stopping session dcWithShift %1").arg(_shiftedDcId)); | ||||||
| 	if (_connection) { | 	killConnection(); | ||||||
| 		_connection->kill(); |  | ||||||
| 		_instance->queueQuittingConnection(std::move(_connection)); |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Session::kill() { | void Session::kill() { | ||||||
|  | @ -286,12 +345,15 @@ void Session::needToResumeAndSend() { | ||||||
| 		DEBUG_LOG(("Session Info: resuming session dcWithShift %1").arg(_shiftedDcId)); | 		DEBUG_LOG(("Session Info: resuming session dcWithShift %1").arg(_shiftedDcId)); | ||||||
| 		start(); | 		start(); | ||||||
| 	} | 	} | ||||||
| 	if (_ping) { | 	const auto connection = _connection; | ||||||
| 		_ping = false; | 	const auto ping = base::take(_ping); | ||||||
| 		emit needToPing(); | 	InvokeQueued(connection, [=] { | ||||||
| 	} else { | 		if (ping) { | ||||||
| 		emit needToSend(); | 			connection->sendPingForce(); | ||||||
| 	} | 		} else { | ||||||
|  | 			connection->tryToSend(); | ||||||
|  | 		} | ||||||
|  | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Session::connectionStateChange(int newState) { | void Session::connectionStateChange(int newState) { | ||||||
|  | @ -323,7 +385,7 @@ int32 Session::requestState(mtpRequestId requestId) const { | ||||||
| 
 | 
 | ||||||
| 	bool connected = false; | 	bool connected = false; | ||||||
| 	if (_connection) { | 	if (_connection) { | ||||||
| 		int32 s = _connection->state(); | 		const auto s = _connection->getState(); | ||||||
| 		if (s == ConnectedState) { | 		if (s == ConnectedState) { | ||||||
| 			connected = true; | 			connected = true; | ||||||
| 		} else if (s == ConnectingState || s == DisconnectedState) { | 		} else if (s == ConnectingState || s == DisconnectedState) { | ||||||
|  | @ -352,7 +414,7 @@ int32 Session::getState() const { | ||||||
| 	int32 result = -86400000; | 	int32 result = -86400000; | ||||||
| 
 | 
 | ||||||
| 	if (_connection) { | 	if (_connection) { | ||||||
| 		int32 s = _connection->state(); | 		const auto s = _connection->getState(); | ||||||
| 		if (s == ConnectedState) { | 		if (s == ConnectedState) { | ||||||
| 			return s; | 			return s; | ||||||
| 		} else if (s == ConnectingState || s == DisconnectedState) { | 		} else if (s == ConnectingState || s == DisconnectedState) { | ||||||
|  | @ -448,7 +510,8 @@ void Session::releaseKeyCreationOnFail() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Session::notifyDcConnectionInited() { | void Session::notifyDcConnectionInited() { | ||||||
| 	DEBUG_LOG(("MTP Info: emitting MTProtoDC::connectionWasInited(), dcWithShift %1").arg(_shiftedDcId)); | 	DEBUG_LOG(("MTP Info: MTProtoDC::connectionWasInited(), dcWithShift %1" | ||||||
|  | 		).arg(_shiftedDcId)); | ||||||
| 	_dc->setConnectionInited(); | 	_dc->setConnectionInited(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -514,11 +577,19 @@ void Session::tryToReceive() { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Session::~Session() { | void Session::killConnection() { | ||||||
| 	if (_myKeyCreation != CreatingKeyType::None) { | 	Expects(!_thread || _connection); | ||||||
| 		releaseKeyCreationOnFail(); | 
 | ||||||
|  | 	if (!_connection) { | ||||||
|  | 		return; | ||||||
| 	} | 	} | ||||||
| 	Assert(_connection == nullptr); | 
 | ||||||
|  | 	base::take(_connection)->deleteLater(); | ||||||
|  | 	_destroyingThreads.push_back(base::take(_thread)); | ||||||
|  | 	_destroyingThreads.back()->quit(); | ||||||
|  | 
 | ||||||
|  | 	Ensures(_connection == nullptr); | ||||||
|  | 	Ensures(_thread == nullptr); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace internal
 | } // namespace internal
 | ||||||
|  |  | ||||||
|  | @ -56,7 +56,7 @@ struct ConnectionOptions { | ||||||
| class Session; | class Session; | ||||||
| class SessionData { | class SessionData { | ||||||
| public: | public: | ||||||
| 	SessionData(not_null<Session*> creator) : _owner(creator) { | 	explicit SessionData(not_null<Session*> creator) : _owner(creator) { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void notifyConnectionInited(const ConnectionOptions &options); | 	void notifyConnectionInited(const ConnectionOptions &options); | ||||||
|  | @ -92,11 +92,6 @@ public: | ||||||
| 		return _receivedUpdates; | 		return _receivedUpdates; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Warning! Valid only in constructor, _owner is guaranteed != null.
 |  | ||||||
| 	[[nodiscard]] not_null<Session*> owner() { |  | ||||||
| 		return _owner; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Connection -> Session interface.
 | 	// Connection -> Session interface.
 | ||||||
| 	void queueTryToReceive(); | 	void queueTryToReceive(); | ||||||
| 	void queueNeedToResumeAndSend(); | 	void queueNeedToResumeAndSend(); | ||||||
|  | @ -139,8 +134,6 @@ private: | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class Session : public QObject { | class Session : public QObject { | ||||||
| 	Q_OBJECT |  | ||||||
| 
 |  | ||||||
| public: | public: | ||||||
| 	// Main thread.
 | 	// Main thread.
 | ||||||
| 	Session( | 	Session( | ||||||
|  | @ -180,8 +173,8 @@ public: | ||||||
| 
 | 
 | ||||||
| 	void ping(); | 	void ping(); | ||||||
| 	void cancel(mtpRequestId requestId, mtpMsgId msgId); | 	void cancel(mtpRequestId requestId, mtpMsgId msgId); | ||||||
| 	int32 requestState(mtpRequestId requestId) const; | 	int requestState(mtpRequestId requestId) const; | ||||||
| 	int32 getState() const; | 	int getState() const; | ||||||
| 	QString transport() const; | 	QString transport() const; | ||||||
| 
 | 
 | ||||||
| 	void tryToReceive(); | 	void tryToReceive(); | ||||||
|  | @ -190,23 +183,26 @@ public: | ||||||
| 	void resetDone(); | 	void resetDone(); | ||||||
| 	void sendAnything(crl::time msCanWait = 0); | 	void sendAnything(crl::time msCanWait = 0); | ||||||
| 
 | 
 | ||||||
| signals: |  | ||||||
| 	void authKeyChanged(); |  | ||||||
| 	void needToSend(); |  | ||||||
| 	void needToPing(); |  | ||||||
| 	void needToRestart(); |  | ||||||
| 
 |  | ||||||
| private: | private: | ||||||
| 	void watchDcKeyChanges(); | 	void watchDcKeyChanges(); | ||||||
|  | 	void watchDcOptionsChanges(); | ||||||
| 
 | 
 | ||||||
| 	bool rpcErrorOccured(mtpRequestId requestId, const RPCFailHandlerPtr &onFail, const RPCError &err); | 	void killConnection(); | ||||||
|  | 
 | ||||||
|  | 	bool rpcErrorOccured( | ||||||
|  | 		mtpRequestId requestId, | ||||||
|  | 		const RPCFailHandlerPtr &onFail, | ||||||
|  | 		const RPCError &err); | ||||||
| 
 | 
 | ||||||
| 	const not_null<Instance*> _instance; | 	const not_null<Instance*> _instance; | ||||||
| 	const ShiftedDcId _shiftedDcId = 0; | 	const ShiftedDcId _shiftedDcId = 0; | ||||||
| 	const not_null<Dcenter*> _dc; | 	const not_null<Dcenter*> _dc; | ||||||
| 	const std::shared_ptr<SessionData> _data; | 	const std::shared_ptr<SessionData> _data; | ||||||
| 
 | 
 | ||||||
| 	std::unique_ptr<Connection> _connection; | 	std::unique_ptr<QThread> _thread; | ||||||
|  | 	std::vector<std::unique_ptr<QThread>> _destroyingThreads; | ||||||
|  | 
 | ||||||
|  | 	Connection *_connection = nullptr; | ||||||
| 
 | 
 | ||||||
| 	bool _killed = false; | 	bool _killed = false; | ||||||
| 	bool _needToReceive = false; | 	bool _needToReceive = false; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue