mirror of https://github.com/procxx/kepka.git
				
				
				
			Fix lost bind key messages.
This commit is contained in:
		
							parent
							
								
									2597bc9f4e
								
							
						
					
					
						commit
						46a42e02bc
					
				|  | @ -443,13 +443,10 @@ mtpMsgId ConnectionPrivate::prepareToSend( | ||||||
| 
 | 
 | ||||||
| 	if (const auto msgId = request.getMsgId()) { | 	if (const auto msgId = request.getMsgId()) { | ||||||
| 		// resending this request
 | 		// resending this request
 | ||||||
| 		QWriteLocker lock(_sessionData->toResendMutex()); | 		const auto i = _resendingIds.find(msgId); | ||||||
| 		auto &toResend = _sessionData->toResendMap(); | 		if (i != _resendingIds.cend()) { | ||||||
| 		const auto i = toResend.find(msgId); | 			_resendingIds.erase(i); | ||||||
| 		if (i != toResend.cend()) { |  | ||||||
| 			toResend.erase(i); |  | ||||||
| 		} | 		} | ||||||
| 		lock.unlock(); |  | ||||||
| 
 | 
 | ||||||
| 		return (forceNewMsgId || msgId > currentLastId) | 		return (forceNewMsgId || msgId > currentLastId) | ||||||
| 			? replaceMsgId(request, currentLastId) | 			? replaceMsgId(request, currentLastId) | ||||||
|  | @ -470,33 +467,29 @@ mtpMsgId ConnectionPrivate::replaceMsgId(SecureRequest &request, mtpMsgId newId) | ||||||
| 	if (oldMsgId == newId) { | 	if (oldMsgId == newId) { | ||||||
| 		return newId; | 		return newId; | ||||||
| 	} | 	} | ||||||
| 	QWriteLocker locker(_sessionData->toResendMutex()); | 	// haveSentMutex() was locked in tryToSend()
 | ||||||
| 	// haveSentMutex() and wereAckedMutex() were locked in tryToSend()
 |  | ||||||
| 
 |  | ||||||
| 	auto &toResend = _sessionData->toResendMap(); |  | ||||||
| 	auto &wereAcked = _sessionData->wereAckedMap(); |  | ||||||
| 	auto &haveSent = _sessionData->haveSentMap(); | 	auto &haveSent = _sessionData->haveSentMap(); | ||||||
| 
 | 
 | ||||||
| 	while (toResend.constFind(newId) != toResend.cend() | 	while (_resendingIds.contains(newId) | ||||||
| 		|| wereAcked.constFind(newId) != wereAcked.cend() | 		|| _ackedIds.contains(newId) | ||||||
| 		|| haveSent.constFind(newId) != haveSent.cend()) { | 		|| haveSent.constFind(newId) != haveSent.cend()) { | ||||||
| 		newId = base::unixtime::mtproto_msg_id(); | 		newId = base::unixtime::mtproto_msg_id(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	MTP_LOG(_shiftedDcId, ("[r%1] msg_id %2 -> %3").arg(request->requestId).arg(oldMsgId).arg(newId)); | 	MTP_LOG(_shiftedDcId, ("[r%1] msg_id %2 -> %3").arg(request->requestId).arg(oldMsgId).arg(newId)); | ||||||
| 
 | 
 | ||||||
| 	const auto i = toResend.find(oldMsgId); | 	const auto i = _resendingIds.find(oldMsgId); | ||||||
| 	if (i != toResend.cend()) { | 	if (i != _resendingIds.end()) { | ||||||
| 		const auto req = i.value(); | 		const auto requestId = i->second; | ||||||
| 		toResend.erase(i); | 		_resendingIds.erase(i); | ||||||
| 		toResend.insert(newId, req); | 		_resendingIds.emplace(newId, requestId); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	const auto j = wereAcked.find(oldMsgId); | 	const auto j = _ackedIds.find(oldMsgId); | ||||||
| 	if (j != wereAcked.cend()) { | 	if (j != _ackedIds.cend()) { | ||||||
| 		const auto req = j.value(); | 		const auto requestId = j->second; | ||||||
| 		wereAcked.erase(j); | 		_ackedIds.erase(j); | ||||||
| 		wereAcked.insert(newId, req); | 		_ackedIds.emplace(newId, requestId); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	const auto k = haveSent.find(oldMsgId); | 	const auto k = haveSent.find(oldMsgId); | ||||||
|  | @ -618,14 +611,14 @@ void ConnectionPrivate::tryToSend() { | ||||||
| 			} | 			} | ||||||
| 			stateRequest = SecureRequest::Serialize(MTPMsgsStateReq( | 			stateRequest = SecureRequest::Serialize(MTPMsgsStateReq( | ||||||
| 				MTP_msgs_state_req(MTP_vector<MTPlong>(ids)))); | 				MTP_msgs_state_req(MTP_vector<MTPlong>(ids)))); | ||||||
| 			// Add to haveSent / wereAcked maps, but don't add to requestMap.
 | 			// Add to haveSent / _ackedIds, but don't add to requestMap.
 | ||||||
| 			stateRequest->requestId = GetNextRequestId(); | 			stateRequest->requestId = GetNextRequestId(); | ||||||
| 		} | 		} | ||||||
| 		if (_connection->usingHttpWait()) { | 		if (_connection->usingHttpWait()) { | ||||||
| 			httpWaitRequest = SecureRequest::Serialize(MTPHttpWait( | 			httpWaitRequest = SecureRequest::Serialize(MTPHttpWait( | ||||||
| 				MTP_http_wait(MTP_int(100), MTP_int(30), MTP_int(25000)))); | 				MTP_http_wait(MTP_int(100), MTP_int(30), MTP_int(25000)))); | ||||||
| 		} | 		} | ||||||
| 		if (_keyCreator && _keyCreator->bindReadyToRequest()) { | 		if (!_bindMsgId && _keyCreator && _keyCreator->readyToBind()) { | ||||||
| 			bindDcKeyRequest = _keyCreator->prepareBindRequest( | 			bindDcKeyRequest = _keyCreator->prepareBindRequest( | ||||||
| 				_encryptionKey, | 				_encryptionKey, | ||||||
| 				_sessionId); | 				_sessionId); | ||||||
|  | @ -635,22 +628,6 @@ void ConnectionPrivate::tryToSend() { | ||||||
| 			// seqNo for it manually here.
 | 			// seqNo for it manually here.
 | ||||||
| 			bindDcKeyRequest.setSeqNo( | 			bindDcKeyRequest.setSeqNo( | ||||||
| 				nextRequestSeqNumber(bindDcKeyRequest.needAck())); | 				nextRequestSeqNumber(bindDcKeyRequest.needAck())); | ||||||
| 		//} else if (!_keyChecker) {
 |  | ||||||
| 		//	if (const auto &keyForCheck = _sessionData->getKeyForCheck()) {
 |  | ||||||
| 		//		_keyChecker = std::make_unique<details::DcKeyChecker>(
 |  | ||||||
| 		//			_instance,
 |  | ||||||
| 		//			_shiftedDcId,
 |  | ||||||
| 		//			keyForCheck);
 |  | ||||||
| 		//		bindDcKeyRequest = _keyChecker->prepareRequest(
 |  | ||||||
| 		//			_encryptionKey,
 |  | ||||||
| 		//			_sessionId);
 |  | ||||||
| 
 |  | ||||||
| 		//		// This is a special request with msgId used inside the message
 |  | ||||||
| 		//		// body, so it is prepared already with a msgId and we place
 |  | ||||||
| 		//		// seqNo for it manually here.
 |  | ||||||
| 		//		bindDcKeyRequest.setSeqNo(
 |  | ||||||
| 		//			nextRequestSeqNumber(bindDcKeyRequest.needAck()));
 |  | ||||||
| 		//	}
 |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -750,8 +727,11 @@ void ConnectionPrivate::tryToSend() { | ||||||
| 			const auto msgId = prepareToSend( | 			const auto msgId = prepareToSend( | ||||||
| 				toSendRequest, | 				toSendRequest, | ||||||
| 				base::unixtime::mtproto_msg_id(), | 				base::unixtime::mtproto_msg_id(), | ||||||
| 				forceNewMsgId); | 				forceNewMsgId && !bindDcKeyRequest); | ||||||
| 			if (pingRequest) { | 			if (bindDcKeyRequest) { | ||||||
|  | 				_bindMsgId = msgId; | ||||||
|  | 				needAnyResponse = true; | ||||||
|  | 			} else if (pingRequest) { | ||||||
| 				_pingMsgId = msgId; | 				_pingMsgId = msgId; | ||||||
| 				needAnyResponse = true; | 				needAnyResponse = true; | ||||||
| 			} else if (resendRequest || stateRequest) { | 			} else if (resendRequest || stateRequest) { | ||||||
|  | @ -792,8 +772,7 @@ void ConnectionPrivate::tryToSend() { | ||||||
| 
 | 
 | ||||||
| 					needAnyResponse = true; | 					needAnyResponse = true; | ||||||
| 				} else { | 				} else { | ||||||
| 					QWriteLocker locker3(_sessionData->wereAckedMutex()); | 					_ackedIds.emplace(msgId, toSendRequest->requestId); | ||||||
| 					_sessionData->wereAckedMap().insert(msgId, toSendRequest->requestId); |  | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} else { // send in container
 | 		} else { // send in container
 | ||||||
|  | @ -833,10 +812,6 @@ void ConnectionPrivate::tryToSend() { | ||||||
| 			QWriteLocker locker2(_sessionData->haveSentMutex()); | 			QWriteLocker locker2(_sessionData->haveSentMutex()); | ||||||
| 			auto &haveSent = _sessionData->haveSentMap(); | 			auto &haveSent = _sessionData->haveSentMap(); | ||||||
| 
 | 
 | ||||||
| 			// the fact of this lock is used in replaceMsgId()
 |  | ||||||
| 			QWriteLocker locker3(_sessionData->wereAckedMutex()); |  | ||||||
| 			auto &wereAcked = _sessionData->wereAckedMap(); |  | ||||||
| 
 |  | ||||||
| 			// prepare "request-like" wrap for msgId vector
 | 			// prepare "request-like" wrap for msgId vector
 | ||||||
| 			auto haveSentIdsWrap = SecureRequest::Prepare(idsWrapSize); | 			auto haveSentIdsWrap = SecureRequest::Prepare(idsWrapSize); | ||||||
| 			haveSentIdsWrap->msDate = 0; // Container: msDate = 0, seqNo = 0.
 | 			haveSentIdsWrap->msDate = 0; // Container: msDate = 0, seqNo = 0.
 | ||||||
|  | @ -844,6 +819,15 @@ void ConnectionPrivate::tryToSend() { | ||||||
| 			haveSentIdsWrap->resize(haveSentIdsWrap->size() + idsWrapSize); | 			haveSentIdsWrap->resize(haveSentIdsWrap->size() + idsWrapSize); | ||||||
| 			auto haveSentArr = (mtpMsgId*)(haveSentIdsWrap->data() + 8); | 			auto haveSentArr = (mtpMsgId*)(haveSentIdsWrap->data() + 8); | ||||||
| 
 | 
 | ||||||
|  | 			if (bindDcKeyRequest) { | ||||||
|  | 				_bindMsgId = placeToContainer( | ||||||
|  | 					toSendRequest, | ||||||
|  | 					bigMsgId, | ||||||
|  | 					false, | ||||||
|  | 					haveSentArr, | ||||||
|  | 					bindDcKeyRequest); | ||||||
|  | 				needAnyResponse = true; | ||||||
|  | 			} | ||||||
| 			if (pingRequest) { | 			if (pingRequest) { | ||||||
| 				_pingMsgId = placeToContainer( | 				_pingMsgId = placeToContainer( | ||||||
| 					toSendRequest, | 					toSendRequest, | ||||||
|  | @ -852,7 +836,8 @@ void ConnectionPrivate::tryToSend() { | ||||||
| 					haveSentArr, | 					haveSentArr, | ||||||
| 					pingRequest); | 					pingRequest); | ||||||
| 				needAnyResponse = true; | 				needAnyResponse = true; | ||||||
| 			} else if (resendRequest || stateRequest || bindDcKeyRequest) { | 			} | ||||||
|  | 			if (resendRequest || stateRequest) { | ||||||
| 				needAnyResponse = true; | 				needAnyResponse = true; | ||||||
| 			} | 			} | ||||||
| 			for (auto i = toSend.begin(), e = toSend.end(); i != e; ++i) { | 			for (auto i = toSend.begin(), e = toSend.end(); i != e; ++i) { | ||||||
|  | @ -890,7 +875,7 @@ void ConnectionPrivate::tryToSend() { | ||||||
| 
 | 
 | ||||||
| 						needAnyResponse = true; | 						needAnyResponse = true; | ||||||
| 					} else { | 					} else { | ||||||
| 						wereAcked.insert(msgId, req->requestId); | 						_ackedIds.emplace(msgId, req->requestId); | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 				if (!added) { | 				if (!added) { | ||||||
|  | @ -908,7 +893,6 @@ void ConnectionPrivate::tryToSend() { | ||||||
| 			if (resendRequest) placeToContainer(toSendRequest, bigMsgId, forceNewMsgId, haveSentArr, resendRequest); | 			if (resendRequest) placeToContainer(toSendRequest, bigMsgId, forceNewMsgId, haveSentArr, resendRequest); | ||||||
| 			if (ackRequest) placeToContainer(toSendRequest, bigMsgId, forceNewMsgId, haveSentArr, ackRequest); | 			if (ackRequest) placeToContainer(toSendRequest, bigMsgId, forceNewMsgId, haveSentArr, ackRequest); | ||||||
| 			if (httpWaitRequest) placeToContainer(toSendRequest, bigMsgId, forceNewMsgId, haveSentArr, httpWaitRequest); | 			if (httpWaitRequest) placeToContainer(toSendRequest, bigMsgId, forceNewMsgId, haveSentArr, httpWaitRequest); | ||||||
| 			if (bindDcKeyRequest) placeToContainer(toSendRequest, bigMsgId, forceNewMsgId, haveSentArr, bindDcKeyRequest); |  | ||||||
| 
 | 
 | ||||||
| 			const auto containerMsgId = prepareToSend( | 			const auto containerMsgId = prepareToSend( | ||||||
| 				toSendRequest, | 				toSendRequest, | ||||||
|  | @ -1044,6 +1028,7 @@ void ConnectionPrivate::connectToServer(bool afterConfig) { | ||||||
| 
 | 
 | ||||||
| 	setState(ConnectingState); | 	setState(ConnectingState); | ||||||
| 
 | 
 | ||||||
|  | 	_bindMsgId = 0; | ||||||
| 	_pingId = _pingMsgId = _pingIdToSend = _pingSendAt = 0; | 	_pingId = _pingMsgId = _pingIdToSend = _pingSendAt = 0; | ||||||
| 	_pingSender.cancel(); | 	_pingSender.cancel(); | ||||||
| 
 | 
 | ||||||
|  | @ -1352,7 +1337,7 @@ void ConnectionPrivate::handleReceived() { | ||||||
| 				_sessionSalt = serverSalt; | 				_sessionSalt = serverSalt; | ||||||
| 
 | 
 | ||||||
| 				if (setState(ConnectedState, ConnectingState)) { | 				if (setState(ConnectedState, ConnectingState)) { | ||||||
| 					_sessionData->resendAll(); | 					resendAll(); | ||||||
| 				} | 				} | ||||||
| 			} else { | 			} else { | ||||||
| 				DEBUG_LOG(("MTP Info: other salt received... received: %1, my salt: %2").arg(serverSalt).arg(_sessionSalt)); | 				DEBUG_LOG(("MTP Info: other salt received... received: %1, my salt: %2").arg(serverSalt).arg(_sessionSalt)); | ||||||
|  | @ -1416,10 +1401,16 @@ void ConnectionPrivate::handleReceived() { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPrime *from, const mtpPrime *end, uint64 msgId, int32 serverTime, uint64 serverSalt, bool badTime) { | ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived( | ||||||
| 	const auto cons = mtpTypeId(*from); | 		const mtpPrime *from, | ||||||
|  | 		const mtpPrime *end, | ||||||
|  | 		uint64 msgId, | ||||||
|  | 		int32 serverTime, | ||||||
|  | 		uint64 serverSalt, | ||||||
|  | 		bool badTime) { | ||||||
|  | 	Expects(from < end); | ||||||
| 
 | 
 | ||||||
| 	switch (cons) { | 	switch (mtpTypeId(*from)) { | ||||||
| 
 | 
 | ||||||
| 	case mtpc_gzip_packed: { | 	case mtpc_gzip_packed: { | ||||||
| 		DEBUG_LOG(("Message Info: gzip container")); | 		DEBUG_LOG(("Message Info: gzip container")); | ||||||
|  | @ -1495,18 +1486,15 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPr | ||||||
| 		if (!msg.read(from, end)) { | 		if (!msg.read(from, end)) { | ||||||
| 			return HandleResult::ParseError; | 			return HandleResult::ParseError; | ||||||
| 		} | 		} | ||||||
| 		auto &ids = msg.c_msgs_ack().vmsg_ids().v; | 		const auto &ids = msg.c_msgs_ack().vmsg_ids().v; | ||||||
| 		uint32 idsCount = ids.size(); | 		DEBUG_LOG(("Message Info: acks received, ids: %1" | ||||||
| 
 | 			).arg(LogIdsVector(ids))); | ||||||
| 		DEBUG_LOG(("Message Info: acks received, ids: %1").arg(LogIdsVector(ids))); | 		if (ids.isEmpty()) { | ||||||
| 		if (!idsCount) return (badTime ? HandleResult::Ignored : HandleResult::Success); | 			return badTime ? HandleResult::Ignored : HandleResult::Success; | ||||||
| 
 |  | ||||||
| 		if (badTime) { |  | ||||||
| 			if (requestsFixTimeSalt(ids, serverTime, serverSalt)) { |  | ||||||
| 				badTime = false; |  | ||||||
| 			} else { |  | ||||||
| 				return HandleResult::Ignored; |  | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
|  | 		if (badTime && !requestsFixTimeSalt(ids, serverTime, serverSalt)) { | ||||||
|  | 			return HandleResult::Ignored; | ||||||
| 		} | 		} | ||||||
| 		requestsAcked(ids); | 		requestsAcked(ids); | ||||||
| 	} return HandleResult::Success; | 	} return HandleResult::Success; | ||||||
|  | @ -1519,11 +1507,8 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPr | ||||||
| 		const auto &data(msg.c_bad_msg_notification()); | 		const auto &data(msg.c_bad_msg_notification()); | ||||||
| 		LOG(("Message Info: bad message notification received (error_code %3) for msg_id = %1, seq_no = %2").arg(data.vbad_msg_id().v).arg(data.vbad_msg_seqno().v).arg(data.verror_code().v)); | 		LOG(("Message Info: bad message notification received (error_code %3) for msg_id = %1, seq_no = %2").arg(data.vbad_msg_id().v).arg(data.vbad_msg_seqno().v).arg(data.verror_code().v)); | ||||||
| 
 | 
 | ||||||
| 		mtpMsgId resendId = data.vbad_msg_id().v; | 		const auto resendId = data.vbad_msg_id().v; | ||||||
| 		if (resendId == _pingMsgId) { | 		const auto errorCode = data.verror_code().v; | ||||||
| 			_pingId = 0; |  | ||||||
| 		} |  | ||||||
| 		int32 errorCode = data.verror_code().v; |  | ||||||
| 		if (false | 		if (false | ||||||
| 			|| errorCode == 16 | 			|| errorCode == 16 | ||||||
| 			|| errorCode == 17 | 			|| errorCode == 17 | ||||||
|  | @ -1619,13 +1604,11 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPr | ||||||
| 		if (!msg.read(from, end)) { | 		if (!msg.read(from, end)) { | ||||||
| 			return HandleResult::ParseError; | 			return HandleResult::ParseError; | ||||||
| 		} | 		} | ||||||
| 		const auto &data(msg.c_bad_server_salt()); | 		const auto &data = msg.c_bad_server_salt(); | ||||||
| 		DEBUG_LOG(("Message Info: bad server salt received (error_code %4) for msg_id = %1, seq_no = %2, new salt: %3").arg(data.vbad_msg_id().v).arg(data.vbad_msg_seqno().v).arg(data.vnew_server_salt().v).arg(data.verror_code().v)); | 		DEBUG_LOG(("Message Info: bad server salt received (error_code %4) for msg_id = %1, seq_no = %2, new salt: %3").arg(data.vbad_msg_id().v).arg(data.vbad_msg_seqno().v).arg(data.vnew_server_salt().v).arg(data.verror_code().v)); | ||||||
| 
 | 
 | ||||||
| 		mtpMsgId resendId = data.vbad_msg_id().v; | 		const auto resendId = data.vbad_msg_id().v; | ||||||
| 		if (resendId == _pingMsgId) { | 		if (!wasSent(resendId)) { | ||||||
| 			_pingId = 0; |  | ||||||
| 		} else if (!wasSent(resendId)) { |  | ||||||
| 			DEBUG_LOG(("Message Error: such message was not sent recently %1").arg(resendId)); | 			DEBUG_LOG(("Message Error: such message was not sent recently %1").arg(resendId)); | ||||||
| 			return (badTime ? HandleResult::Ignored : HandleResult::Success); | 			return (badTime ? HandleResult::Ignored : HandleResult::Success); | ||||||
| 		} | 		} | ||||||
|  | @ -1634,7 +1617,7 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPr | ||||||
| 		base::unixtime::update(serverTime); | 		base::unixtime::update(serverTime); | ||||||
| 
 | 
 | ||||||
| 		if (setState(ConnectedState, ConnectingState)) { | 		if (setState(ConnectedState, ConnectingState)) { | ||||||
| 			_sessionData->resendAll(); | 			resendAll(); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		badTime = false; | 		badTime = false; | ||||||
|  | @ -1661,11 +1644,6 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPr | ||||||
| 		{ | 		{ | ||||||
| 			const auto minRecv = _receivedMessageIds.min(); | 			const auto minRecv = _receivedMessageIds.min(); | ||||||
| 			const auto maxRecv = _receivedMessageIds.max(); | 			const auto maxRecv = _receivedMessageIds.max(); | ||||||
| 
 |  | ||||||
| 			QReadLocker locker(_sessionData->wereAckedMutex()); |  | ||||||
| 			const auto &wereAcked = _sessionData->wereAckedMap(); |  | ||||||
| 			const auto wereAckedEnd = wereAcked.cend(); |  | ||||||
| 
 |  | ||||||
| 			for (uint32 i = 0, l = idsCount; i < l; ++i) { | 			for (uint32 i = 0, l = idsCount; i < l; ++i) { | ||||||
| 				char state = 0; | 				char state = 0; | ||||||
| 				uint64 reqMsgId = ids[i].v; | 				uint64 reqMsgId = ids[i].v; | ||||||
|  | @ -1679,7 +1657,7 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPr | ||||||
| 						state |= 0x02; | 						state |= 0x02; | ||||||
| 					} else { | 					} else { | ||||||
| 						state |= 0x04; | 						state |= 0x04; | ||||||
| 						if (wereAcked.constFind(reqMsgId) != wereAckedEnd) { | 						if (_ackedIds.contains(reqMsgId)) { | ||||||
| 							state |= 0x80; // we know, that server knows, that we received request
 | 							state |= 0x80; // we know, that server knows, that we received request
 | ||||||
| 						} | 						} | ||||||
| 						if (msgIdState == ReceivedIdsManager::State::NeedsAck) { // need ack, so we sent ack
 | 						if (msgIdState == ReceivedIdsManager::State::NeedsAck) { // need ack, so we sent ack
 | ||||||
|  | @ -1837,20 +1815,21 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPr | ||||||
| 		if (!reqMsgId.read(++from, end)) { | 		if (!reqMsgId.read(++from, end)) { | ||||||
| 			return HandleResult::ParseError; | 			return HandleResult::ParseError; | ||||||
| 		} | 		} | ||||||
| 		mtpTypeId typeId = from[0]; | 		const auto requestMsgId = reqMsgId.v; | ||||||
| 
 | 
 | ||||||
| 		DEBUG_LOG(("RPC Info: response received for %1, queueing...").arg(reqMsgId.v)); | 		DEBUG_LOG(("RPC Info: response received for %1, queueing...").arg(requestMsgId)); | ||||||
| 
 | 
 | ||||||
| 		QVector<MTPlong> ids(1, reqMsgId); | 		QVector<MTPlong> ids(1, reqMsgId); | ||||||
| 		if (badTime) { | 		if (badTime) { | ||||||
| 			if (requestsFixTimeSalt(ids, serverTime, serverSalt)) { | 			if (requestsFixTimeSalt(ids, serverTime, serverSalt)) { | ||||||
| 				badTime = false; | 				badTime = false; | ||||||
| 			} else { | 			} else { | ||||||
| 				DEBUG_LOG(("Message Info: error, such message was not sent recently %1").arg(reqMsgId.v)); | 				DEBUG_LOG(("Message Info: error, such message was not sent recently %1").arg(requestMsgId)); | ||||||
| 				return HandleResult::Ignored; | 				return HandleResult::Ignored; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		mtpTypeId typeId = from[0]; | ||||||
| 		if (typeId == mtpc_gzip_packed) { | 		if (typeId == mtpc_gzip_packed) { | ||||||
| 			DEBUG_LOG(("RPC Info: gzip container")); | 			DEBUG_LOG(("RPC Info: gzip container")); | ||||||
| 			response = ungzip(++from, end); | 			response = ungzip(++from, end); | ||||||
|  | @ -1874,36 +1853,17 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPr | ||||||
| 		} | 		} | ||||||
| 		requestsAcked(ids, true); | 		requestsAcked(ids, true); | ||||||
| 
 | 
 | ||||||
| 		if (_keyCreator) { | 		const auto bindResult = handleBindResponse(requestMsgId, response); | ||||||
| 			const auto result = _keyCreator->handleBindResponse( | 		if (bindResult != HandleResult::Ignored) { | ||||||
| 				reqMsgId, | 			return bindResult; | ||||||
| 				response); |  | ||||||
| 			switch (result) { |  | ||||||
| 			case DcKeyBindState::Success: |  | ||||||
| 				if (!_sessionData->releaseKeyCreationOnDone( |  | ||||||
| 					_encryptionKey, |  | ||||||
| 					base::take(_keyCreator)->bindPersistentKey())) { |  | ||||||
| 					return HandleResult::DestroyTemporaryKey; |  | ||||||
| 		} | 		} | ||||||
| 				_sessionData->queueNeedToResumeAndSend(); | 		const auto requestId = wasSent(requestMsgId); | ||||||
| 				return HandleResult::Success; |  | ||||||
| 			case DcKeyBindState::DefinitelyDestroyed: |  | ||||||
| 				if (destroyOldEnoughPersistentKey()) { |  | ||||||
| 					return HandleResult::DestroyTemporaryKey; |  | ||||||
| 				} |  | ||||||
| 				[[fallthrough]]; |  | ||||||
| 			case DcKeyBindState::Failed: |  | ||||||
| 				_sessionData->queueNeedToResumeAndSend(); |  | ||||||
| 				return HandleResult::Success; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		auto requestId = wasSent(reqMsgId.v); |  | ||||||
| 		if (requestId && requestId != mtpRequestId(0xFFFFFFFF)) { | 		if (requestId && requestId != mtpRequestId(0xFFFFFFFF)) { | ||||||
| 			// Save rpc_result for processing in the main thread.
 | 			// Save rpc_result for processing in the main thread.
 | ||||||
| 			QWriteLocker locker(_sessionData->haveReceivedMutex()); | 			QWriteLocker locker(_sessionData->haveReceivedMutex()); | ||||||
| 			_sessionData->haveReceivedResponses().insert(requestId, response); | 			_sessionData->haveReceivedResponses().insert(requestId, response); | ||||||
| 		} else { | 		} else { | ||||||
| 			DEBUG_LOG(("RPC Info: requestId not found for msgId %1").arg(reqMsgId.v)); | 			DEBUG_LOG(("RPC Info: requestId not found for msgId %1").arg(requestMsgId)); | ||||||
| 		} | 		} | ||||||
| 	} return HandleResult::Success; | 	} return HandleResult::Success; | ||||||
| 
 | 
 | ||||||
|  | @ -1942,7 +1902,7 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPr | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		for (const auto msgId : toResend) { | 		for (const auto msgId : toResend) { | ||||||
| 			_sessionData->resend(msgId, 10, true); | 			resend(msgId, 10, true); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		mtpBuffer update(from - start); | 		mtpBuffer update(from - start); | ||||||
|  | @ -1991,22 +1951,13 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPr | ||||||
| 
 | 
 | ||||||
| 	if (_currentDcType == DcType::Regular) { | 	if (_currentDcType == DcType::Regular) { | ||||||
| 		mtpBuffer update(end - from); | 		mtpBuffer update(end - from); | ||||||
| 		if (end > from) memcpy(update.data(), from, (end - from) * sizeof(mtpPrime)); | 		if (end > from) { | ||||||
|  | 			memcpy(update.data(), from, (end - from) * sizeof(mtpPrime)); | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		// Notify main process about the new updates.
 | 		// Notify main process about the new updates.
 | ||||||
| 		QWriteLocker locker(_sessionData->haveReceivedMutex()); | 		QWriteLocker locker(_sessionData->haveReceivedMutex()); | ||||||
| 		_sessionData->haveReceivedUpdates().push_back(SerializedMessage(update)); | 		_sessionData->haveReceivedUpdates().push_back(SerializedMessage(update)); | ||||||
| 
 |  | ||||||
| 		if (cons != mtpc_updatesTooLong |  | ||||||
| 			&& cons != mtpc_updateShortMessage |  | ||||||
| 			&& cons != mtpc_updateShortChatMessage |  | ||||||
| 			&& cons != mtpc_updateShortSentMessage |  | ||||||
| 			&& cons != mtpc_updateShort |  | ||||||
| 			&& cons != mtpc_updatesCombined |  | ||||||
| 			&& cons != mtpc_updates) { |  | ||||||
| 			// Maybe some new unknown update?
 |  | ||||||
| 			LOG(("Message Error: unknown constructor 0x%1").arg(cons, 0, 16)); |  | ||||||
| 		} |  | ||||||
| 	} else { | 	} else { | ||||||
| 		LOG(("Message Error: unexpected updates in dcType: %1" | 		LOG(("Message Error: unexpected updates in dcType: %1" | ||||||
| 			).arg(static_cast<int>(_currentDcType))); | 			).arg(static_cast<int>(_currentDcType))); | ||||||
|  | @ -2015,6 +1966,34 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPr | ||||||
| 	return HandleResult::Success; | 	return HandleResult::Success; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | ConnectionPrivate::HandleResult ConnectionPrivate::handleBindResponse( | ||||||
|  | 		mtpMsgId requestMsgId, | ||||||
|  | 		const mtpBuffer &response) { | ||||||
|  | 	if (!_keyCreator || !_bindMsgId || _bindMsgId != requestMsgId) { | ||||||
|  | 		return HandleResult::Ignored; | ||||||
|  | 	} | ||||||
|  | 	const auto result = _keyCreator->handleBindResponse(response); | ||||||
|  | 	switch (result) { | ||||||
|  | 	case DcKeyBindState::Success: | ||||||
|  | 		if (!_sessionData->releaseKeyCreationOnDone( | ||||||
|  | 			_encryptionKey, | ||||||
|  | 			base::take(_keyCreator)->bindPersistentKey())) { | ||||||
|  | 			return HandleResult::DestroyTemporaryKey; | ||||||
|  | 		} | ||||||
|  | 		_sessionData->queueNeedToResumeAndSend(); | ||||||
|  | 		return HandleResult::Success; | ||||||
|  | 	case DcKeyBindState::DefinitelyDestroyed: | ||||||
|  | 		if (destroyOldEnoughPersistentKey()) { | ||||||
|  | 			return HandleResult::DestroyTemporaryKey; | ||||||
|  | 		} | ||||||
|  | 		[[fallthrough]]; | ||||||
|  | 	case DcKeyBindState::Failed: | ||||||
|  | 		_sessionData->queueNeedToResumeAndSend(); | ||||||
|  | 		return HandleResult::Success; | ||||||
|  | 	} | ||||||
|  | 	Unexpected("Result of BoundKeyCreator::handleBindResponse."); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| mtpBuffer ConnectionPrivate::ungzip(const mtpPrime *from, const mtpPrime *end) const { | mtpBuffer ConnectionPrivate::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); | ||||||
|  | @ -2089,10 +2068,6 @@ void ConnectionPrivate::requestsAcked(const QVector<MTPlong> &ids, bool byRespon | ||||||
| 
 | 
 | ||||||
| 	auto clearedBecauseTooOld = std::vector<RPCCallbackClear>(); | 	auto clearedBecauseTooOld = std::vector<RPCCallbackClear>(); | ||||||
| 	QVector<MTPlong> toAckMore; | 	QVector<MTPlong> toAckMore; | ||||||
| 	{ |  | ||||||
| 		QWriteLocker locker1(_sessionData->wereAckedMutex()); |  | ||||||
| 		auto &wereAcked = _sessionData->wereAckedMap(); |  | ||||||
| 
 |  | ||||||
| 	{ | 	{ | ||||||
| 		QWriteLocker locker2(_sessionData->haveSentMutex()); | 		QWriteLocker locker2(_sessionData->haveSentMutex()); | ||||||
| 		auto &haveSent = _sessionData->haveSentMap(); | 		auto &haveSent = _sessionData->haveSentMap(); | ||||||
|  | @ -2117,7 +2092,7 @@ void ConnectionPrivate::requestsAcked(const QVector<MTPlong> &ids, bool byRespon | ||||||
| 						moveToAcked = !_instance->hasCallbacks(reqId); | 						moveToAcked = !_instance->hasCallbacks(reqId); | ||||||
| 					} | 					} | ||||||
| 					if (moveToAcked) { | 					if (moveToAcked) { | ||||||
| 							wereAcked.insert(msgId, reqId); | 						_ackedIds.emplace(msgId, reqId); | ||||||
| 						haveSent.erase(req); | 						haveSent.erase(req); | ||||||
| 					} else { | 					} else { | ||||||
| 						DEBUG_LOG(("Message Info: ignoring ACK for msgId %1 because request %2 requires a response").arg(msgId).arg(reqId)); | 						DEBUG_LOG(("Message Info: ignoring ACK for msgId %1 because request %2 requires a response").arg(msgId).arg(reqId)); | ||||||
|  | @ -2125,11 +2100,9 @@ void ConnectionPrivate::requestsAcked(const QVector<MTPlong> &ids, bool byRespon | ||||||
| 				} | 				} | ||||||
| 			} else { | 			} else { | ||||||
| 				DEBUG_LOG(("Message Info: msgId %1 was not found in recent sent, while acking requests, searching in resend...").arg(msgId)); | 				DEBUG_LOG(("Message Info: msgId %1 was not found in recent sent, while acking requests, searching in resend...").arg(msgId)); | ||||||
| 					QWriteLocker locker3(_sessionData->toResendMutex()); | 				const auto reqIt = _resendingIds.find(msgId); | ||||||
| 					auto &toResend = _sessionData->toResendMap(); | 				if (reqIt != _resendingIds.end()) { | ||||||
| 					const auto reqIt = toResend.find(msgId); | 					const auto reqId = reqIt->second; | ||||||
| 					if (reqIt != toResend.cend()) { |  | ||||||
| 						const auto reqId = reqIt.value(); |  | ||||||
| 					bool moveToAcked = byResponse; | 					bool moveToAcked = byResponse; | ||||||
| 					if (!moveToAcked) { // ignore ACK, if we need a response (if we have a handler)
 | 					if (!moveToAcked) { // ignore ACK, if we need a response (if we have a handler)
 | ||||||
| 						moveToAcked = !_instance->hasCallbacks(reqId); | 						moveToAcked = !_instance->hasCallbacks(reqId); | ||||||
|  | @ -2139,7 +2112,7 @@ void ConnectionPrivate::requestsAcked(const QVector<MTPlong> &ids, bool byRespon | ||||||
| 						auto &toSend = _sessionData->toSendMap(); | 						auto &toSend = _sessionData->toSendMap(); | ||||||
| 						const auto req = toSend.find(reqId); | 						const auto req = toSend.find(reqId); | ||||||
| 						if (req != toSend.cend()) { | 						if (req != toSend.cend()) { | ||||||
| 								wereAcked.insert(msgId, req.value()->requestId); | 							_ackedIds.emplace(msgId, req.value()->requestId); | ||||||
| 							if (req.value()->requestId != reqId) { | 							if (req.value()->requestId != reqId) { | ||||||
| 								DEBUG_LOG(("Message Error: for msgId %1 found resent request, requestId %2, contains requestId %3").arg(msgId).arg(reqId).arg(req.value()->requestId)); | 								DEBUG_LOG(("Message Error: for msgId %1 found resent request, requestId %2, contains requestId %3").arg(msgId).arg(reqId).arg(req.value()->requestId)); | ||||||
| 							} else { | 							} else { | ||||||
|  | @ -2149,7 +2122,7 @@ void ConnectionPrivate::requestsAcked(const QVector<MTPlong> &ids, bool byRespon | ||||||
| 						} else { | 						} else { | ||||||
| 							DEBUG_LOG(("Message Info: msgId %1 was found in recent resent, requestId %2 was not found in prepared to send").arg(msgId)); | 							DEBUG_LOG(("Message Info: msgId %1 was found in recent resent, requestId %2 was not found in prepared to send").arg(msgId)); | ||||||
| 						} | 						} | ||||||
| 							toResend.erase(reqIt); | 						_resendingIds.erase(reqIt); | ||||||
| 					} else { | 					} else { | ||||||
| 						DEBUG_LOG(("Message Info: ignoring ACK for msgId %1 because request %2 requires a response").arg(msgId).arg(reqId)); | 						DEBUG_LOG(("Message Info: ignoring ACK for msgId %1 because request %2 requires a response").arg(msgId).arg(reqId)); | ||||||
| 					} | 					} | ||||||
|  | @ -2160,17 +2133,16 @@ void ConnectionPrivate::requestsAcked(const QVector<MTPlong> &ids, bool byRespon | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 		uint32 ackedCount = wereAcked.size(); | 	auto ackedCount = _ackedIds.size(); | ||||||
| 	if (ackedCount > kIdsBufferSize) { | 	if (ackedCount > kIdsBufferSize) { | ||||||
| 		DEBUG_LOG(("Message Info: removing some old acked sent msgIds %1").arg(ackedCount - kIdsBufferSize)); | 		DEBUG_LOG(("Message Info: removing some old acked sent msgIds %1").arg(ackedCount - kIdsBufferSize)); | ||||||
| 		clearedBecauseTooOld.reserve(ackedCount - kIdsBufferSize); | 		clearedBecauseTooOld.reserve(ackedCount - kIdsBufferSize); | ||||||
| 		while (ackedCount-- > kIdsBufferSize) { | 		while (ackedCount-- > kIdsBufferSize) { | ||||||
| 				auto i = wereAcked.begin(); | 			auto i = _ackedIds.begin(); | ||||||
| 			clearedBecauseTooOld.push_back(RPCCallbackClear( | 			clearedBecauseTooOld.push_back(RPCCallbackClear( | ||||||
| 					i.value(), | 				i->second, | ||||||
| 				RPCError::TimeoutError)); | 				RPCError::TimeoutError)); | ||||||
| 				wereAcked.erase(i); | 			_ackedIds.erase(i); | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -2204,10 +2176,8 @@ void ConnectionPrivate::handleMsgsStates(const QVector<MTPlong> &ids, const QByt | ||||||
| 			const auto haveSentEnd = haveSent.cend(); | 			const auto haveSentEnd = haveSent.cend(); | ||||||
| 			if (haveSent.find(requestMsgId) == haveSentEnd) { | 			if (haveSent.find(requestMsgId) == haveSentEnd) { | ||||||
| 				DEBUG_LOG(("Message Info: state was received for msgId %1, but request is not found, looking in resent requests...").arg(requestMsgId)); | 				DEBUG_LOG(("Message Info: state was received for msgId %1, but request is not found, looking in resent requests...").arg(requestMsgId)); | ||||||
| 				QWriteLocker locker2(_sessionData->toResendMutex()); | 				const auto reqIt = _resendingIds.find(requestMsgId); | ||||||
| 				auto &toResend = _sessionData->toResendMap(); | 				if (reqIt != _resendingIds.cend()) { | ||||||
| 				const auto reqIt = toResend.find(requestMsgId); |  | ||||||
| 				if (reqIt != toResend.cend()) { |  | ||||||
| 					if ((state & 0x07) != 0x04) { // was received
 | 					if ((state & 0x07) != 0x04) { // was received
 | ||||||
| 						DEBUG_LOG(("Message Info: state was received for msgId %1, state %2, already resending in container").arg(requestMsgId).arg((int32)state)); | 						DEBUG_LOG(("Message Info: state was received for msgId %1, state %2, already resending in container").arg(requestMsgId).arg((int32)state)); | ||||||
| 					} else { | 					} else { | ||||||
|  | @ -2230,23 +2200,71 @@ void ConnectionPrivate::handleMsgsStates(const QVector<MTPlong> &ids, const QByt | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void ConnectionPrivate::clearSpecialMsgId(mtpMsgId msgId) { | ||||||
|  | 	if (msgId == _pingMsgId) { | ||||||
|  | 		_pingMsgId = 0; | ||||||
|  | 		_pingId = 0; | ||||||
|  | 	} else if (msgId == _bindMsgId) { | ||||||
|  | 		_bindMsgId = 0; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void ConnectionPrivate::resend( | void ConnectionPrivate::resend( | ||||||
| 		mtpMsgId msgId, | 		mtpMsgId msgId, | ||||||
| 		crl::time msCanWait, | 		crl::time msCanWait, | ||||||
| 		bool forceContainer) { | 		bool forceContainer) { | ||||||
| 	if (msgId != _pingMsgId) { | 	const auto guard = gsl::finally([&] { | ||||||
| 		_sessionData->resend(msgId, msCanWait, forceContainer); | 		clearSpecialMsgId(msgId); | ||||||
|  | 		if (msCanWait >= 0) { | ||||||
|  | 			_sessionData->queueSendAnything(msCanWait); | ||||||
|  | 		} | ||||||
|  | 	}); | ||||||
|  | 
 | ||||||
|  | 	auto lock = QWriteLocker(_sessionData->haveSentMutex()); | ||||||
|  | 	auto &haveSent = _sessionData->haveSentMap(); | ||||||
|  | 	auto i = haveSent.find(msgId); | ||||||
|  | 	if (i == haveSent.end()) { | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	auto request = i.value(); | ||||||
|  | 	haveSent.erase(i); | ||||||
|  | 	lock.unlock(); | ||||||
|  | 
 | ||||||
|  | 	// For container just resend all messages we can.
 | ||||||
|  | 	if (request.isSentContainer()) { | ||||||
|  | 		DEBUG_LOG(("Message Info: resending container from haveSent, msgId %1").arg(msgId)); | ||||||
|  | 		const mtpMsgId *ids = (const mtpMsgId *)(request->constData() + 8); | ||||||
|  | 		for (uint32 i = 0, l = (request->size() - 8) >> 1; i < l; ++i) { | ||||||
|  | 			resend(ids[i], -1, true); | ||||||
|  | 		} | ||||||
|  | 	} else if (!request.isStateRequest()) { | ||||||
|  | 		request->msDate = forceContainer ? 0 : crl::now(); | ||||||
|  | 		_resendingIds.emplace(msgId, request->requestId); | ||||||
|  | 		{ | ||||||
|  | 			QWriteLocker locker(_sessionData->toSendMutex()); | ||||||
|  | 			_sessionData->toSendMap().insert(request->requestId, request); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::resendMany( | void ConnectionPrivate::resendAll() { | ||||||
| 		QVector<mtpMsgId> msgIds, | 	auto toResend = std::vector<mtpMsgId>(); | ||||||
| 		crl::time msCanWait, | 
 | ||||||
| 		bool forceContainer) { | 	auto lock = QReadLocker(_sessionData->haveSentMutex()); | ||||||
| 	for (const auto msgId : msgIds) { | 	const auto &haveSent = _sessionData->haveSentMap(); | ||||||
| 		resend(msgId, msCanWait, forceContainer); | 	toResend.reserve(haveSent.size()); | ||||||
|  | 	for (auto i = haveSent.cbegin(), e = haveSent.cend(); i != e; ++i) { | ||||||
|  | 		if (!i.value().isSentContainer()) { | ||||||
|  | 			toResend.push_back(i.key()); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | 	lock.unlock(); | ||||||
|  | 
 | ||||||
|  | 	for (const auto msgId : toResend) { | ||||||
|  | 		resend(msgId, -1, true); | ||||||
|  | 	} | ||||||
|  | 	_sessionData->queueSendAnything(); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| void ConnectionPrivate::onConnected( | void ConnectionPrivate::onConnected( | ||||||
| 		not_null<AbstractConnection*> connection) { | 		not_null<AbstractConnection*> connection) { | ||||||
|  | @ -2470,10 +2488,6 @@ DcType ConnectionPrivate::tryAcquireKeyCreation() { | ||||||
| 			).arg(result->persistentServerSalt)); | 			).arg(result->persistentServerSalt)); | ||||||
| 
 | 
 | ||||||
| 		_sessionSalt = result->temporaryServerSalt; | 		_sessionSalt = result->temporaryServerSalt; | ||||||
| 		if (result->persistentKey) { |  | ||||||
| 			_sessionData->clearForNewKey(_instance); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		auto key = result->persistentKey | 		auto key = result->persistentKey | ||||||
| 			? std::move(result->persistentKey) | 			? std::move(result->persistentKey) | ||||||
| 			: _sessionData->getPersistentKey(); | 			: _sessionData->getPersistentKey(); | ||||||
|  | @ -2512,7 +2526,7 @@ void ConnectionPrivate::authKeyChecked() { | ||||||
| 	}); | 	}); | ||||||
| 
 | 
 | ||||||
| 	if (_sessionSalt && setState(ConnectedState)) { | 	if (_sessionSalt && setState(ConnectedState)) { | ||||||
| 		_sessionData->resendAll(); | 		resendAll(); | ||||||
| 	} // else receive salt in bad_server_salt first, then try to send all the requests
 | 	} // else receive salt in bad_server_salt first, then try to send all the requests
 | ||||||
| 
 | 
 | ||||||
| 	_pingIdToSend = rand_value<uint64>(); // get server_salt
 | 	_pingIdToSend = rand_value<uint64>(); // get server_salt
 | ||||||
|  | @ -2651,7 +2665,9 @@ bool ConnectionPrivate::sendSecureRequest( | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| mtpRequestId ConnectionPrivate::wasSent(mtpMsgId msgId) const { | mtpRequestId ConnectionPrivate::wasSent(mtpMsgId msgId) const { | ||||||
| 	if (msgId == _pingMsgId) return mtpRequestId(0xFFFFFFFF); | 	if (msgId == _pingMsgId || msgId == _bindMsgId) { | ||||||
|  | 		return mtpRequestId(0xFFFFFFFF); | ||||||
|  | 	} | ||||||
| 	{ | 	{ | ||||||
| 		QReadLocker locker(_sessionData->haveSentMutex()); | 		QReadLocker locker(_sessionData->haveSentMutex()); | ||||||
| 		const auto &haveSent = _sessionData->haveSentMap(); | 		const auto &haveSent = _sessionData->haveSentMap(); | ||||||
|  | @ -2662,17 +2678,11 @@ mtpRequestId ConnectionPrivate::wasSent(mtpMsgId msgId) const { | ||||||
| 				: mtpRequestId(0xFFFFFFFF); | 				: mtpRequestId(0xFFFFFFFF); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	{ | 	if (const auto i = _resendingIds.find(msgId); i != end(_resendingIds)) { | ||||||
| 		QReadLocker locker(_sessionData->toResendMutex()); | 		return i->second; | ||||||
| 		const auto &toResend = _sessionData->toResendMap(); |  | ||||||
| 		const auto i = toResend.constFind(msgId); |  | ||||||
| 		if (i != toResend.cend()) return i.value(); |  | ||||||
| 	} | 	} | ||||||
| 	{ | 	if (const auto i = _ackedIds.find(msgId); i != end(_ackedIds)) { | ||||||
| 		QReadLocker locker(_sessionData->wereAckedMutex()); | 		return i->second; | ||||||
| 		const auto &wereAcked = _sessionData->wereAckedMap(); |  | ||||||
| 		const auto i = wereAcked.constFind(msgId); |  | ||||||
| 		if (i != wereAcked.cend()) return i.value(); |  | ||||||
| 	} | 	} | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -154,6 +154,9 @@ private: | ||||||
| 	mtpRequestId wasSent(mtpMsgId msgId) const; | 	mtpRequestId wasSent(mtpMsgId msgId) const; | ||||||
| 
 | 
 | ||||||
| 	[[nodiscard]] HandleResult handleOneReceived(const mtpPrime *from, const mtpPrime *end, uint64 msgId, int32 serverTime, uint64 serverSalt, bool badTime); | 	[[nodiscard]] HandleResult handleOneReceived(const mtpPrime *from, const mtpPrime *end, uint64 msgId, int32 serverTime, uint64 serverSalt, bool badTime); | ||||||
|  | 	[[nodiscard]] HandleResult handleBindResponse( | ||||||
|  | 		mtpMsgId requestMsgId, | ||||||
|  | 		const mtpBuffer &response); | ||||||
| 	mtpBuffer ungzip(const mtpPrime *from, const mtpPrime *end) const; | 	mtpBuffer ungzip(const mtpPrime *from, const mtpPrime *end) const; | ||||||
| 	void handleMsgsStates(const QVector<MTPlong> &ids, const QByteArray &states, QVector<MTPlong> &acked); | 	void handleMsgsStates(const QVector<MTPlong> &ids, const QByteArray &states, QVector<MTPlong> &acked); | ||||||
| 
 | 
 | ||||||
|  | @ -176,10 +179,8 @@ private: | ||||||
| 		mtpMsgId msgId, | 		mtpMsgId msgId, | ||||||
| 		crl::time msCanWait = 0, | 		crl::time msCanWait = 0, | ||||||
| 		bool forceContainer = false); | 		bool forceContainer = false); | ||||||
| 	void resendMany( | 	void resendAll(); | ||||||
| 		QVector<mtpMsgId> msgIds, | 	void clearSpecialMsgId(mtpMsgId msgId); | ||||||
| 		crl::time msCanWait = 0, |  | ||||||
| 		bool forceContainer = false); |  | ||||||
| 
 | 
 | ||||||
| 	[[nodiscard]] DcType tryAcquireKeyCreation(); | 	[[nodiscard]] DcType tryAcquireKeyCreation(); | ||||||
| 	void resetSession(); | 	void resetSession(); | ||||||
|  | @ -249,8 +250,11 @@ private: | ||||||
| 	QVector<MTPlong> _resendRequestData; | 	QVector<MTPlong> _resendRequestData; | ||||||
| 	base::flat_set<mtpMsgId> _stateRequestData; | 	base::flat_set<mtpMsgId> _stateRequestData; | ||||||
| 	details::ReceivedIdsManager _receivedMessageIds; | 	details::ReceivedIdsManager _receivedMessageIds; | ||||||
|  | 	base::flat_map<mtpMsgId, mtpRequestId> _resendingIds; | ||||||
|  | 	base::flat_map<mtpMsgId, mtpRequestId> _ackedIds; | ||||||
| 
 | 
 | ||||||
| 	std::unique_ptr<details::BoundKeyCreator> _keyCreator; | 	std::unique_ptr<details::BoundKeyCreator> _keyCreator; | ||||||
|  | 	mtpMsgId _bindMsgId = 0; | ||||||
| 
 | 
 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -50,8 +50,8 @@ void BoundKeyCreator::restartBinder() { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool BoundKeyCreator::bindReadyToRequest() const { | bool BoundKeyCreator::readyToBind() const { | ||||||
| 	return _binder ? !_binder->requested() : false; | 	return _binder.has_value(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| SecureRequest BoundKeyCreator::prepareBindRequest( | SecureRequest BoundKeyCreator::prepareBindRequest( | ||||||
|  | @ -63,11 +63,10 @@ SecureRequest BoundKeyCreator::prepareBindRequest( | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| DcKeyBindState BoundKeyCreator::handleBindResponse( | DcKeyBindState BoundKeyCreator::handleBindResponse( | ||||||
| 		MTPlong requestMsgId, |  | ||||||
| 		const mtpBuffer &response) { | 		const mtpBuffer &response) { | ||||||
| 	return _binder | 	Expects(_binder.has_value()); | ||||||
| 		? _binder->handleResponse(requestMsgId, response) | 
 | ||||||
| 		: DcKeyBindState::Unknown; | 	return _binder->handleResponse(response); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| AuthKeyPtr BoundKeyCreator::bindPersistentKey() const { | AuthKeyPtr BoundKeyCreator::bindPersistentKey() const { | ||||||
|  |  | ||||||
|  | @ -31,12 +31,11 @@ public: | ||||||
| 
 | 
 | ||||||
| 	void bind(AuthKeyPtr &&persistentKey); | 	void bind(AuthKeyPtr &&persistentKey); | ||||||
| 	void restartBinder(); | 	void restartBinder(); | ||||||
| 	[[nodiscard]] bool bindReadyToRequest() const; | 	[[nodiscard]] bool readyToBind() const; | ||||||
| 	[[nodiscard]] SecureRequest prepareBindRequest( | 	[[nodiscard]] SecureRequest prepareBindRequest( | ||||||
| 		const AuthKeyPtr &temporaryKey, | 		const AuthKeyPtr &temporaryKey, | ||||||
| 		uint64 sessionId); | 		uint64 sessionId); | ||||||
| 	[[nodiscard]] DcKeyBindState handleBindResponse( | 	[[nodiscard]] DcKeyBindState handleBindResponse( | ||||||
| 		MTPlong requestMsgId, |  | ||||||
| 		const mtpBuffer &response); | 		const mtpBuffer &response); | ||||||
| 	[[nodiscard]] AuthKeyPtr bindPersistentKey() const; | 	[[nodiscard]] AuthKeyPtr bindPersistentKey() const; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -77,46 +77,34 @@ DcKeyBinder::DcKeyBinder(AuthKeyPtr &&persistentKey) | ||||||
| 	Expects(_persistentKey != nullptr); | 	Expects(_persistentKey != nullptr); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool DcKeyBinder::requested() const { |  | ||||||
| 	return _requestMsgId != 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| SecureRequest DcKeyBinder::prepareRequest( | SecureRequest DcKeyBinder::prepareRequest( | ||||||
| 		const AuthKeyPtr &temporaryKey, | 		const AuthKeyPtr &temporaryKey, | ||||||
| 		uint64 sessionId) { | 		uint64 sessionId) { | ||||||
| 	Expects(_requestMsgId == 0); |  | ||||||
| 	Expects(temporaryKey != nullptr); | 	Expects(temporaryKey != nullptr); | ||||||
| 	Expects(temporaryKey->expiresAt() != 0); | 	Expects(temporaryKey->expiresAt() != 0); | ||||||
| 
 | 
 | ||||||
| 	const auto nonce = openssl::RandomValue<uint64>(); | 	const auto nonce = openssl::RandomValue<uint64>(); | ||||||
| 	_requestMsgId = base::unixtime::mtproto_msg_id(); | 	const auto msgId = base::unixtime::mtproto_msg_id(); | ||||||
| 	auto result = SecureRequest::Serialize(MTPauth_BindTempAuthKey( | 	auto result = SecureRequest::Serialize(MTPauth_BindTempAuthKey( | ||||||
| 		MTP_long(_persistentKey->keyId()), | 		MTP_long(_persistentKey->keyId()), | ||||||
| 		MTP_long(nonce), | 		MTP_long(nonce), | ||||||
| 		MTP_int(temporaryKey->expiresAt()), | 		MTP_int(temporaryKey->expiresAt()), | ||||||
| 		MTP_bytes(EncryptBindAuthKeyInner( | 		MTP_bytes(EncryptBindAuthKeyInner( | ||||||
| 			_persistentKey, | 			_persistentKey, | ||||||
| 			_requestMsgId, | 			msgId, | ||||||
| 			MTP_bind_auth_key_inner( | 			MTP_bind_auth_key_inner( | ||||||
| 				MTP_long(nonce), | 				MTP_long(nonce), | ||||||
| 				MTP_long(temporaryKey->keyId()), | 				MTP_long(temporaryKey->keyId()), | ||||||
| 				MTP_long(_persistentKey->keyId()), | 				MTP_long(_persistentKey->keyId()), | ||||||
| 				MTP_long(sessionId), | 				MTP_long(sessionId), | ||||||
| 				MTP_int(temporaryKey->expiresAt())))))); | 				MTP_int(temporaryKey->expiresAt())))))); | ||||||
| 	result.setMsgId(_requestMsgId); | 	result.setMsgId(msgId); | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| DcKeyBindState DcKeyBinder::handleResponse( | DcKeyBindState DcKeyBinder::handleResponse(const mtpBuffer &response) { | ||||||
| 		MTPlong requestMsgId, |  | ||||||
| 		const mtpBuffer &response) { |  | ||||||
| 	Expects(!response.isEmpty()); | 	Expects(!response.isEmpty()); | ||||||
| 
 | 
 | ||||||
| 	if (!_requestMsgId || requestMsgId.v != _requestMsgId) { |  | ||||||
| 		return DcKeyBindState::Unknown; |  | ||||||
| 	} |  | ||||||
| 	_requestMsgId = 0; |  | ||||||
| 
 |  | ||||||
| 	auto from = response.begin(); | 	auto from = response.begin(); | ||||||
| 	const auto end = from + response.size(); | 	const auto end = from + response.size(); | ||||||
| 	auto error = MTPRpcError(); | 	auto error = MTPRpcError(); | ||||||
|  |  | ||||||
|  | @ -17,7 +17,6 @@ class Instance; | ||||||
| namespace MTP::details { | namespace MTP::details { | ||||||
| 
 | 
 | ||||||
| enum class DcKeyBindState { | enum class DcKeyBindState { | ||||||
| 	Unknown, |  | ||||||
| 	Success, | 	Success, | ||||||
| 	Failed, | 	Failed, | ||||||
| 	DefinitelyDestroyed, | 	DefinitelyDestroyed, | ||||||
|  | @ -27,18 +26,14 @@ class DcKeyBinder final { | ||||||
| public: | public: | ||||||
| 	explicit DcKeyBinder(AuthKeyPtr &&persistentKey); | 	explicit DcKeyBinder(AuthKeyPtr &&persistentKey); | ||||||
| 
 | 
 | ||||||
| 	[[nodiscard]] bool requested() const; |  | ||||||
| 	[[nodiscard]] SecureRequest prepareRequest( | 	[[nodiscard]] SecureRequest prepareRequest( | ||||||
| 		const AuthKeyPtr &temporaryKey, | 		const AuthKeyPtr &temporaryKey, | ||||||
| 		uint64 sessionId); | 		uint64 sessionId); | ||||||
| 	[[nodiscard]] DcKeyBindState handleResponse( | 	[[nodiscard]] DcKeyBindState handleResponse(const mtpBuffer &response); | ||||||
| 		MTPlong requestMsgId, |  | ||||||
| 		const mtpBuffer &response); |  | ||||||
| 	[[nodiscard]] AuthKeyPtr persistentKey() const; | 	[[nodiscard]] AuthKeyPtr persistentKey() const; | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
| 	AuthKeyPtr _persistentKey; | 	AuthKeyPtr _persistentKey; | ||||||
| 	mtpMsgId _requestMsgId = 0; |  | ||||||
| 
 | 
 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -64,48 +64,6 @@ void SessionData::notifyConnectionInited(const ConnectionOptions &options) { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SessionData::clearForNewKey(not_null<Instance*> instance) { |  | ||||||
| 	auto clearCallbacks = std::vector<RPCCallbackClear>(); |  | ||||||
| 	{ |  | ||||||
| 		QReadLocker locker1(haveSentMutex()); |  | ||||||
| 		QReadLocker locker2(toResendMutex()); |  | ||||||
| 		QReadLocker locker3(haveReceivedMutex()); |  | ||||||
| 		QReadLocker locker4(wereAckedMutex()); |  | ||||||
| 		clearCallbacks.reserve(_haveSent.size() + _toResend.size() + _wereAcked.size()); |  | ||||||
| 		for (auto i = _haveSent.cbegin(), e = _haveSent.cend(); i != e; ++i) { |  | ||||||
| 			auto requestId = i.value()->requestId; |  | ||||||
| 			if (!_receivedResponses.contains(requestId)) { |  | ||||||
| 				clearCallbacks.push_back(requestId); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		for (auto i = _toResend.cbegin(), e = _toResend.cend(); i != e; ++i) { |  | ||||||
| 			auto requestId = i.value(); |  | ||||||
| 			if (!_receivedResponses.contains(requestId)) { |  | ||||||
| 				clearCallbacks.push_back(requestId); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		for (auto i = _wereAcked.cbegin(), e = _wereAcked.cend(); i != e; ++i) { |  | ||||||
| 			auto requestId = i.value(); |  | ||||||
| 			if (!_receivedResponses.contains(requestId)) { |  | ||||||
| 				clearCallbacks.push_back(requestId); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	{ |  | ||||||
| 		QWriteLocker locker(haveSentMutex()); |  | ||||||
| 		_haveSent.clear(); |  | ||||||
| 	} |  | ||||||
| 	{ |  | ||||||
| 		QWriteLocker locker(toResendMutex()); |  | ||||||
| 		_toResend.clear(); |  | ||||||
| 	} |  | ||||||
| 	{ |  | ||||||
| 		QWriteLocker locker(wereAckedMutex()); |  | ||||||
| 		_wereAcked.clear(); |  | ||||||
| 	} |  | ||||||
| 	instance->clearCallbacksDelayed(std::move(clearCallbacks)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void SessionData::queueTryToReceive() { | void SessionData::queueTryToReceive() { | ||||||
| 	withSession([](not_null<Session*> session) { | 	withSession([](not_null<Session*> session) { | ||||||
| 		session->tryToReceive(); | 		session->tryToReceive(); | ||||||
|  | @ -142,23 +100,6 @@ void SessionData::queueSendMsgsStateInfo(quint64 msgId, QByteArray data) { | ||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SessionData::resend( |  | ||||||
| 		mtpMsgId msgId, |  | ||||||
| 		crl::time msCanWait, |  | ||||||
| 		bool forceContainer) { |  | ||||||
| 	QMutexLocker lock(&_ownerMutex); |  | ||||||
| 	if (_owner) { |  | ||||||
| 		_owner->resend(msgId, msCanWait, forceContainer); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void SessionData::resendAll() { |  | ||||||
| 	QMutexLocker lock(&_ownerMutex); |  | ||||||
| 	if (_owner) { |  | ||||||
| 		_owner->resendAll(); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool SessionData::connectionInited() const { | bool SessionData::connectionInited() const { | ||||||
| 	QMutexLocker lock(&_ownerMutex); | 	QMutexLocker lock(&_ownerMutex); | ||||||
| 	return _owner ? _owner->connectionInited() : false; | 	return _owner ? _owner->connectionInited() : false; | ||||||
|  | @ -455,73 +396,17 @@ QString Session::transport() const { | ||||||
| 	return _connection ? _connection->transport() : QString(); | 	return _connection ? _connection->transport() : QString(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Session::resend( |  | ||||||
| 		mtpMsgId msgId, |  | ||||||
| 		crl::time msCanWait, |  | ||||||
| 		bool forceContainer) { |  | ||||||
| 	auto lock = QWriteLocker(_data->haveSentMutex()); |  | ||||||
| 	auto &haveSent = _data->haveSentMap(); |  | ||||||
| 
 |  | ||||||
| 	auto i = haveSent.find(msgId); |  | ||||||
| 	if (i == haveSent.end()) { |  | ||||||
| 		return; |  | ||||||
| 	} |  | ||||||
| 	auto request = i.value(); |  | ||||||
| 	haveSent.erase(i); |  | ||||||
| 	lock.unlock(); |  | ||||||
| 
 |  | ||||||
| 	// For container just resend all messages we can.
 |  | ||||||
| 	if (request.isSentContainer()) { |  | ||||||
| 		DEBUG_LOG(("Message Info: resending container from haveSent, msgId %1").arg(msgId)); |  | ||||||
| 		const mtpMsgId *ids = (const mtpMsgId *)(request->constData() + 8); |  | ||||||
| 		for (uint32 i = 0, l = (request->size() - 8) >> 1; i < l; ++i) { |  | ||||||
| 			resend(ids[i], 10, true); |  | ||||||
| 		} |  | ||||||
| 	} else if (!request.isStateRequest()) { |  | ||||||
| 		request->msDate = forceContainer ? 0 : crl::now(); |  | ||||||
| 		{ |  | ||||||
| 			QWriteLocker locker(_data->toResendMutex()); |  | ||||||
| 			_data->toResendMap().insert(msgId, request->requestId); |  | ||||||
| 		} |  | ||||||
| 		sendPrepared(request, msCanWait, false); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Session::resendAll() { |  | ||||||
| 	QVector<mtpMsgId> toResend; |  | ||||||
| 	{ |  | ||||||
| 		QReadLocker locker(_data->haveSentMutex()); |  | ||||||
| 		const auto &haveSent = _data->haveSentMap(); |  | ||||||
| 		toResend.reserve(haveSent.size()); |  | ||||||
| 		for (auto i = haveSent.cbegin(), e = haveSent.cend(); i != e; ++i) { |  | ||||||
| 			if (i.value()->requestId) { |  | ||||||
| 				toResend.push_back(i.key()); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	for (uint32 i = 0, l = toResend.size(); i < l; ++i) { |  | ||||||
| 		resend(toResend[i], -1, true); |  | ||||||
| 	} |  | ||||||
| 	InvokeQueued(this, [=] { |  | ||||||
| 		sendAnything(); |  | ||||||
| 	}); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Session::sendPrepared( | void Session::sendPrepared( | ||||||
| 		const SecureRequest &request, | 		const SecureRequest &request, | ||||||
| 		crl::time msCanWait, | 		crl::time msCanWait) { | ||||||
| 		bool newRequest) { |  | ||||||
| 	DEBUG_LOG(("MTP Info: adding request to toSendMap, msCanWait %1" | 	DEBUG_LOG(("MTP Info: adding request to toSendMap, msCanWait %1" | ||||||
| 		).arg(msCanWait)); | 		).arg(msCanWait)); | ||||||
| 	{ | 	{ | ||||||
| 		QWriteLocker locker(_data->toSendMutex()); | 		QWriteLocker locker(_data->toSendMutex()); | ||||||
| 		_data->toSendMap().insert(request->requestId, request); | 		_data->toSendMap().insert(request->requestId, request); | ||||||
| 
 |  | ||||||
| 		if (newRequest) { |  | ||||||
| 		*(mtpMsgId*)(request->data() + 4) = 0; | 		*(mtpMsgId*)(request->data() + 4) = 0; | ||||||
| 		*(request->data() + 6) = 0; | 		*(request->data() + 6) = 0; | ||||||
| 	} | 	} | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	DEBUG_LOG(("MTP Info: added, requestId %1").arg(request->requestId)); | 	DEBUG_LOG(("MTP Info: added, requestId %1").arg(request->requestId)); | ||||||
| 	if (msCanWait >= 0) { | 	if (msCanWait >= 0) { | ||||||
|  |  | ||||||
|  | @ -29,22 +29,6 @@ enum class CreatingKeyType; | ||||||
| 
 | 
 | ||||||
| using PreRequestMap = QMap<mtpRequestId, SecureRequest>; | using PreRequestMap = QMap<mtpRequestId, SecureRequest>; | ||||||
| using RequestMap = QMap<mtpMsgId, SecureRequest>; | using RequestMap = QMap<mtpMsgId, SecureRequest>; | ||||||
| 
 |  | ||||||
| class RequestIdsMap : public QMap<mtpMsgId, mtpRequestId> { |  | ||||||
| public: |  | ||||||
| 	using ParentType = QMap<mtpMsgId, mtpRequestId>; |  | ||||||
| 
 |  | ||||||
| 	mtpMsgId min() const { |  | ||||||
| 		return size() ? cbegin().key() : 0; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	mtpMsgId max() const { |  | ||||||
| 		ParentType::const_iterator e(cend()); |  | ||||||
| 		return size() ? (--e).key() : 0; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| using SerializedMessage = mtpBuffer; | using SerializedMessage = mtpBuffer; | ||||||
| 
 | 
 | ||||||
| inline bool ResponseNeedsAck(const SerializedMessage &response) { | inline bool ResponseNeedsAck(const SerializedMessage &response) { | ||||||
|  | @ -102,12 +86,6 @@ public: | ||||||
| 	not_null<QReadWriteLock*> haveSentMutex() const { | 	not_null<QReadWriteLock*> haveSentMutex() const { | ||||||
| 		return &_haveSentLock; | 		return &_haveSentLock; | ||||||
| 	} | 	} | ||||||
| 	not_null<QReadWriteLock*> toResendMutex() const { |  | ||||||
| 		return &_toResendLock; |  | ||||||
| 	} |  | ||||||
| 	not_null<QReadWriteLock*> wereAckedMutex() const { |  | ||||||
| 		return &_wereAckedLock; |  | ||||||
| 	} |  | ||||||
| 	not_null<QReadWriteLock*> haveReceivedMutex() const { | 	not_null<QReadWriteLock*> haveReceivedMutex() const { | ||||||
| 		return &_haveReceivedLock; | 		return &_haveReceivedLock; | ||||||
| 	} | 	} | ||||||
|  | @ -124,18 +102,6 @@ public: | ||||||
| 	const RequestMap &haveSentMap() const { | 	const RequestMap &haveSentMap() const { | ||||||
| 		return _haveSent; | 		return _haveSent; | ||||||
| 	} | 	} | ||||||
| 	RequestIdsMap &toResendMap() { // msgId -> requestId, on which toSend: requestId -> request for resended requests
 |  | ||||||
| 		return _toResend; |  | ||||||
| 	} |  | ||||||
| 	const RequestIdsMap &toResendMap() const { |  | ||||||
| 		return _toResend; |  | ||||||
| 	} |  | ||||||
| 	RequestIdsMap &wereAckedMap() { |  | ||||||
| 		return _wereAcked; |  | ||||||
| 	} |  | ||||||
| 	const RequestIdsMap &wereAckedMap() const { |  | ||||||
| 		return _wereAcked; |  | ||||||
| 	} |  | ||||||
| 	QMap<mtpRequestId, SerializedMessage> &haveReceivedResponses() { | 	QMap<mtpRequestId, SerializedMessage> &haveReceivedResponses() { | ||||||
| 		return _receivedResponses; | 		return _receivedResponses; | ||||||
| 	} | 	} | ||||||
|  | @ -154,8 +120,6 @@ public: | ||||||
| 		return _owner; | 		return _owner; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void clearForNewKey(not_null<Instance*> instance); |  | ||||||
| 
 |  | ||||||
| 	// Connection -> Session interface.
 | 	// Connection -> Session interface.
 | ||||||
| 	void queueTryToReceive(); | 	void queueTryToReceive(); | ||||||
| 	void queueNeedToResumeAndSend(); | 	void queueNeedToResumeAndSend(); | ||||||
|  | @ -173,11 +137,6 @@ public: | ||||||
| 		const AuthKeyPtr &persistentKeyUsedForBind); | 		const AuthKeyPtr &persistentKeyUsedForBind); | ||||||
| 	void releaseKeyCreationOnFail(); | 	void releaseKeyCreationOnFail(); | ||||||
| 	void destroyTemporaryKey(uint64 keyId); | 	void destroyTemporaryKey(uint64 keyId); | ||||||
| 	void resend( |  | ||||||
| 		mtpMsgId msgId, |  | ||||||
| 		crl::time msCanWait, |  | ||||||
| 		bool forceContainer); |  | ||||||
| 	void resendAll(); |  | ||||||
| 
 | 
 | ||||||
| 	void detach(); | 	void detach(); | ||||||
| 
 | 
 | ||||||
|  | @ -192,8 +151,6 @@ private: | ||||||
| 
 | 
 | ||||||
| 	PreRequestMap _toSend; // map of request_id -> request, that is waiting to be sent
 | 	PreRequestMap _toSend; // map of request_id -> request, that is waiting to be sent
 | ||||||
| 	RequestMap _haveSent; // map of msg_id -> request, that was sent, msDate = 0 for msgs_state_req (no resend / state req), msDate = 0, seqNo = 0 for containers
 | 	RequestMap _haveSent; // map of msg_id -> request, that was sent, msDate = 0 for msgs_state_req (no resend / state req), msDate = 0, seqNo = 0 for containers
 | ||||||
| 	RequestIdsMap _toResend; // map of msg_id -> request_id, that request_id -> request lies in toSend and is waiting to be resent
 |  | ||||||
| 	RequestIdsMap _wereAcked; // map of msg_id -> request_id, this msg_ids already were acked or do not need ack
 |  | ||||||
| 
 | 
 | ||||||
| 	QMap<mtpRequestId, SerializedMessage> _receivedResponses; // map of request_id -> response that should be processed in the main thread
 | 	QMap<mtpRequestId, SerializedMessage> _receivedResponses; // map of request_id -> response that should be processed in the main thread
 | ||||||
| 	QList<SerializedMessage> _receivedUpdates; // list of updates that should be processed in the main thread
 | 	QList<SerializedMessage> _receivedUpdates; // list of updates that should be processed in the main thread
 | ||||||
|  | @ -202,8 +159,6 @@ private: | ||||||
| 	mutable QReadWriteLock _optionsLock; | 	mutable QReadWriteLock _optionsLock; | ||||||
| 	mutable QReadWriteLock _toSendLock; | 	mutable QReadWriteLock _toSendLock; | ||||||
| 	mutable QReadWriteLock _haveSentLock; | 	mutable QReadWriteLock _haveSentLock; | ||||||
| 	mutable QReadWriteLock _toResendLock; |  | ||||||
| 	mutable QReadWriteLock _wereAckedLock; |  | ||||||
| 	mutable QReadWriteLock _haveReceivedLock; | 	mutable QReadWriteLock _haveReceivedLock; | ||||||
| 
 | 
 | ||||||
| }; | }; | ||||||
|  | @ -234,18 +189,7 @@ public: | ||||||
| 	[[nodiscard]] AuthKeyPtr getPersistentKey() const; | 	[[nodiscard]] AuthKeyPtr getPersistentKey() const; | ||||||
| 	[[nodiscard]] AuthKeyPtr getTemporaryKey(TemporaryKeyType type) const; | 	[[nodiscard]] AuthKeyPtr getTemporaryKey(TemporaryKeyType type) const; | ||||||
| 	[[nodiscard]] bool connectionInited() const; | 	[[nodiscard]] bool connectionInited() const; | ||||||
| 	void resend( | 	void sendPrepared(const SecureRequest &request, crl::time msCanWait = 0); | ||||||
| 		mtpMsgId msgId, |  | ||||||
| 		crl::time msCanWait = 0, |  | ||||||
| 		bool forceContainer = false); |  | ||||||
| 	void resendAll(); |  | ||||||
| 
 |  | ||||||
| 	// Thread-safe.
 |  | ||||||
| 	// Nulls msgId and seqNo in request, if newRequest = true.
 |  | ||||||
| 	void sendPrepared( |  | ||||||
| 		const SecureRequest &request, |  | ||||||
| 		crl::time msCanWait = 0, |  | ||||||
| 		bool newRequest = true); |  | ||||||
| 
 | 
 | ||||||
| 	// Connection thread.
 | 	// Connection thread.
 | ||||||
| 	[[nodiscard]] CreatingKeyType acquireKeyCreation(TemporaryKeyType type); | 	[[nodiscard]] CreatingKeyType acquireKeyCreation(TemporaryKeyType type); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue