tdesktop/Telegram/SourceFiles/mtproto/connection.h

250 lines
6.4 KiB
C
Raw Normal View History

/*
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
2019-11-18 09:28:14 +00:00
#include "mtproto/mtproto_auth_key.h"
#include "mtproto/dc_options.h"
#include "mtproto/connection_abstract.h"
2019-11-13 08:31:12 +00:00
#include "mtproto/facade.h"
2018-08-10 19:19:46 +00:00
#include "base/openssl_help.h"
#include "base/timer.h"
namespace MTP {
2019-11-13 14:12:04 +00:00
namespace details {
class DcKeyCreator;
2019-11-14 07:13:17 +00:00
class DcKeyChecker;
2019-11-13 14:12:04 +00:00
} // namespace details
// How much time to wait for some more requests, when sending msg acks.
constexpr auto kAckSendWaiting = crl::time(10000);
class Instance;
namespace internal {
class AbstractConnection;
class ConnectionPrivate;
class SessionData;
class RSAPublicKey;
struct ConnectionOptions;
class Connection {
public:
enum ConnectionType {
TcpConnection,
HttpConnection
};
Connection(not_null<Instance*> instance);
~Connection();
void start(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;
};
class ConnectionPrivate : public QObject {
Q_OBJECT
public:
ConnectionPrivate(
not_null<Instance*> instance,
not_null<QThread*> thread,
not_null<Connection*> owner,
not_null<SessionData*> data,
ShiftedDcId shiftedDcId);
~ConnectionPrivate();
void stop();
int32 getShiftedDcId() const;
int32 getState() const;
QString transport() const;
signals:
void needToReceive();
void needToRestart();
void stateChanged(qint32 newState);
void sessionResetDone();
void needToSendAsync();
2016-12-01 19:20:33 +00:00
void sendAnythingAsync(qint64 msWait);
void sendHttpWaitAsync();
void sendPongAsync(quint64 msgId, quint64 pingId);
void sendMsgsStateInfoAsync(quint64 msgId, QByteArray data);
2016-12-01 19:20:33 +00:00
void resendAsync(quint64 msgId, qint64 msCanWait, bool forceContainer, bool sendMsgStateInfo);
void resendManyAsync(QVector<quint64> msgIds, qint64 msCanWait, bool forceContainer, bool sendMsgStateInfo);
void resendAllAsync();
2014-11-24 13:21:27 +00:00
public slots:
void restartNow();
void onPingSendForce();
// Sessions signals, when we need to send something
void tryToSend();
void updateAuthKey();
void onConfigLoaded();
void onCDNConfigLoaded();
private:
struct TestConnection {
ConnectionPointer data;
int priority = 0;
};
void connectToServer(bool afterConfig = false);
void connectingTimedOut();
2015-08-08 09:14:47 +00:00
void doDisconnect();
void restart();
void finishAndDestroy();
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();
2015-08-08 09:14:47 +00:00
// Locks _sessionDataMutex.
2018-04-23 10:24:03 +00:00
void destroyAllConnections();
void confirmBestConnection();
void removeTestConnection(not_null<AbstractConnection*> connection);
int16 getProtocolDcId() const;
mtpMsgId placeToContainer(
SecureRequest &toSendRequest,
mtpMsgId &bigMsgId,
mtpMsgId *&haveSentArr,
SecureRequest &req);
mtpMsgId prepareToSend(SecureRequest &request, mtpMsgId currentLastId);
mtpMsgId replaceMsgId(SecureRequest &request, mtpMsgId newId);
bool sendSecureRequest(
SecureRequest &&request,
bool needAnyResponse,
QReadLocker &lockFinished);
mtpRequestId wasSent(mtpMsgId msgId) const;
enum class HandleResult {
Success,
Ignored,
RestartConnection,
ResetSession,
2019-07-18 14:06:38 +00:00
ParseError,
};
2019-07-18 14:06:38 +00:00
[[nodiscard]] HandleResult handleOneReceived(const mtpPrime *from, const mtpPrime *end, uint64 msgId, int32 serverTime, uint64 serverSalt, bool badTime);
mtpBuffer ungzip(const mtpPrime *from, const mtpPrime *end) const;
void handleMsgsStates(const QVector<MTPlong> &ids, const QByteArray &states, QVector<MTPlong> &acked);
bool setState(int32 state, int32 ifState = Connection::UpdateAlways);
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, int32 serverTime, uint64 serverSalt);
// remove msgs with such ids from sessionData->haveSent, add to sessionData->wereAcked
void requestsAcked(const QVector<MTPlong> &ids, bool byResponse = false);
void resend(quint64 msgId, qint64 msCanWait = 0, bool forceContainer = false, bool sendMsgStateInfo = false);
void resendMany(QVector<quint64> msgIds, qint64 msCanWait = 0, bool forceContainer = false, bool sendMsgStateInfo = false);
2019-11-13 14:12:04 +00:00
void createDcKey();
void resetSession();
void checkAuthKey();
void authKeyChecked();
void destroyCdnKey();
// _sessionDataMutex must be locked for read.
void clearKeyCreatorOnFail();
not_null<Instance*> _instance;
DcType _dcType = DcType::Regular;
mutable QReadWriteLock stateConnMutex;
int32 _state = DisconnectedState;
bool _needSessionReset = false;
ShiftedDcId _shiftedDcId = 0;
not_null<Connection*> _owner;
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;
2019-11-14 07:13:17 +00:00
crl::time _firstSentAt = -1;
2019-11-14 07:13:17 +00:00
QVector<MTPlong> _ackRequestData;
QVector<MTPlong> _resendRequestData;
mtpPingId _pingId = 0;
mtpPingId _pingIdToSend = 0;
crl::time _pingSendAt = 0;
mtpMsgId _pingMsgId = 0;
base::Timer _pingSender;
2019-11-14 07:13:17 +00:00
bool _restarted = false;
bool _finished = false;
AuthKeyPtr _key;
2019-11-14 07:13:17 +00:00
uint64 _keyId = 0;
QReadWriteLock _sessionDataMutex;
SessionData *_sessionData = nullptr;
std::unique_ptr<ConnectionOptions> _connectionOptions;
2019-11-13 14:12:04 +00:00
std::unique_ptr<details::DcKeyCreator> _keyCreator;
std::unique_ptr<details::DcKeyChecker> _keyChecker;
};
} // namespace internal
} // namespace MTP