tdesktop/Telegram/SourceFiles/mtproto/session_private.h

245 lines
6.6 KiB
C++

/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "mtproto/details/mtproto_received_ids_manager.h"
#include "mtproto/details/mtproto_serialized_request.h"
#include "mtproto/mtproto_auth_key.h"
#include "mtproto/mtproto_dc_options.h"
#include "mtproto/connection_abstract.h"
#include "mtproto/facade.h"
#include "base/timer.h"
namespace MTP {
namespace details {
class BoundKeyCreator;
} // namespace details
class Instance;
namespace details {
class AbstractConnection;
class SessionData;
class RSAPublicKey;
struct SessionOptions;
class SessionPrivate final : public QObject {
public:
SessionPrivate(
not_null<Instance*> instance,
not_null<QThread*> thread,
std::shared_ptr<SessionData> data,
ShiftedDcId shiftedDcId);
~SessionPrivate();
[[nodiscard]] int32 getShiftedDcId() const;
void dcOptionsChanged();
void cdnConfigChanged();
[[nodiscard]] int32 getState() const;
[[nodiscard]] QString transport() const;
void updateAuthKey();
void restartNow();
void sendPingForce();
void tryToSend();
private:
static constexpr auto kUpdateStateAlways = 666;
struct TestConnection {
ConnectionPointer data;
int priority = 0;
};
struct SentContainer {
crl::time sent = 0;
std::vector<mtpMsgId> messages;
};
enum class HandleResult {
Success,
Ignored,
RestartConnection,
ResetSession,
DestroyTemporaryKey,
ParseError,
};
void connectToServer(bool afterConfig = false);
void connectingTimedOut();
void doDisconnect();
void restart();
void requestCDNConfig();
void handleError(int errorCode);
void onError(
not_null<AbstractConnection*> connection,
qint32 errorCode);
void onConnected(not_null<AbstractConnection*> connection);
void onDisconnected(not_null<AbstractConnection*> connection);
void onSentSome(uint64 size);
void onReceivedSome();
void handleReceived();
void retryByTimer();
void waitConnectedFailed();
void waitReceivedFailed();
void waitBetterFailed();
void markConnectionOld();
void sendPingByTimer();
void destroyAllConnections();
void confirmBestConnection();
void removeTestConnection(not_null<AbstractConnection*> connection);
[[nodiscard]] int16 getProtocolDcId() const;
void checkSentRequests();
void clearOldContainers();
mtpMsgId placeToContainer(
SerializedRequest &toSendRequest,
mtpMsgId &bigMsgId,
bool forceNewMsgId,
SerializedRequest &req);
mtpMsgId prepareToSend(
SerializedRequest &request,
mtpMsgId currentLastId,
bool forceNewMsgId);
mtpMsgId replaceMsgId(
SerializedRequest &request,
mtpMsgId newId);
bool sendSecureRequest(
SerializedRequest &&request,
bool needAnyResponse);
mtpRequestId wasSent(mtpMsgId msgId) const;
struct OuterInfo {
mtpMsgId outerMsgId = 0;
uint64 serverSalt = 0;
int32 serverTime = 0;
bool badTime = false;
};
[[nodiscard]] HandleResult handleOneReceived(
const mtpPrime *from,
const mtpPrime *end,
uint64 msgId,
OuterInfo info);
[[nodiscard]] HandleResult handleBindResponse(
mtpMsgId requestMsgId,
const mtpBuffer &response);
mtpBuffer ungzip(const mtpPrime *from, const mtpPrime *end) const;
void handleMsgsStates(const QVector<MTPlong> &ids, const QByteArray &states);
// _sessionDataMutex must be locked for read.
bool setState(int state, int ifState = kUpdateStateAlways);
void appendTestConnection(
DcOptions::Variants::Protocol protocol,
const QString &ip,
int port,
const bytes::vector &protocolSecret);
// if badTime received - search for ids in sessionData->haveSent and sessionData->wereAcked and sync time/salt, return true if found
bool requestsFixTimeSalt(const QVector<MTPlong> &ids, const OuterInfo &info);
// if we had a confirmed fast request use its unixtime as a correct one.
void correctUnixtimeByFastRequest(
const QVector<MTPlong> &ids,
TimeId serverTime);
void correctUnixtimeWithBadLocal(TimeId serverTime);
// remove msgs with such ids from sessionData->haveSent, add to sessionData->wereAcked
void requestsAcked(const QVector<MTPlong> &ids, bool byResponse = false);
void resend(mtpMsgId msgId, crl::time msCanWait = 0);
void resendAll();
void clearSpecialMsgId(mtpMsgId msgId);
[[nodiscard]] DcType tryAcquireKeyCreation();
void resetSession();
void checkAuthKey();
void authKeyChecked();
void destroyTemporaryKey();
void clearUnboundKeyCreator();
void releaseKeyCreationOnFail();
void applyAuthKey(AuthKeyPtr &&encryptionKey);
[[nodiscard]] bool noMediaKeyWithExistingRegularKey() const;
bool destroyOldEnoughPersistentKey();
void setCurrentKeyId(uint64 newKeyId);
void changeSessionId();
[[nodiscard]] bool markSessionAsStarted();
[[nodiscard]] uint32 nextRequestSeqNumber(bool needAck);
[[nodiscard]] bool realDcTypeChanged();
[[nodiscard]] MTPVector<MTPJSONObjectValue> prepareInitParams();
const not_null<Instance*> _instance;
const ShiftedDcId _shiftedDcId = 0;
DcType _realDcType = DcType();
DcType _currentDcType = DcType();
mutable QReadWriteLock _stateMutex;
int _state = DisconnectedState;
bool _needSessionReset = false;
ConnectionPointer _connection;
std::vector<TestConnection> _testConnections;
crl::time _startedConnectingAt = 0;
base::Timer _retryTimer; // exp retry timer
int _retryTimeout = 1;
qint64 _retryWillFinish = 0;
base::Timer _oldConnectionTimer;
bool _oldConnection = true;
base::Timer _waitForConnectedTimer;
base::Timer _waitForReceivedTimer;
base::Timer _waitForBetterTimer;
crl::time _waitForReceived = 0;
crl::time _waitForConnected = 0;
crl::time _firstSentAt = -1;
mtpPingId _pingId = 0;
mtpPingId _pingIdToSend = 0;
crl::time _pingSendAt = 0;
mtpMsgId _pingMsgId = 0;
base::Timer _pingSender;
base::Timer _checkSentRequestsTimer;
base::Timer _clearOldContainersTimer;
std::shared_ptr<SessionData> _sessionData;
std::unique_ptr<SessionOptions> _options;
AuthKeyPtr _encryptionKey;
uint64 _keyId = 0;
uint64 _sessionId = 0;
uint64 _sessionSalt = 0;
uint32 _messagesCounter = 0;
bool _sessionMarkedAsStarted = false;
QVector<MTPlong> _ackRequestData;
QVector<MTPlong> _resendRequestData;
base::flat_set<mtpMsgId> _stateRequestData;
ReceivedIdsManager _receivedMessageIds;
base::flat_map<mtpMsgId, mtpRequestId> _resendingIds;
base::flat_map<mtpMsgId, mtpRequestId> _ackedIds;
base::flat_map<mtpMsgId, SerializedRequest> _stateAndResendRequests;
base::flat_map<mtpMsgId, SentContainer> _sentContainers;
std::unique_ptr<BoundKeyCreator> _keyCreator;
mtpMsgId _bindMsgId = 0;
crl::time _bindMessageSent = 0;
};
} // namespace details
} // namespace MTP