2014-05-30 08:53:19 +00:00
|
|
|
/*
|
|
|
|
This file is part of Telegram Desktop,
|
2014-12-01 10:47:38 +00:00
|
|
|
the official desktop version of Telegram messaging app, see https://telegram.org
|
2014-05-30 08:53:19 +00:00
|
|
|
|
|
|
|
Telegram Desktop is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
It is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
2015-10-03 13:16:42 +00:00
|
|
|
In addition, as a special exception, the copyright holders give permission
|
|
|
|
to link the code of portions of this program with the OpenSSL library.
|
|
|
|
|
2014-05-30 08:53:19 +00:00
|
|
|
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
2017-01-11 18:31:31 +00:00
|
|
|
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
2014-05-30 08:53:19 +00:00
|
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
|
2016-03-23 18:43:12 +00:00
|
|
|
#include "mtproto/core_types.h"
|
|
|
|
#include "mtproto/auth_key.h"
|
2017-03-23 16:11:35 +00:00
|
|
|
#include "mtproto/dc_options.h"
|
2016-10-05 16:56:27 +00:00
|
|
|
#include "core/single_timer.h"
|
2014-05-30 08:53:19 +00:00
|
|
|
|
2016-03-24 08:57:11 +00:00
|
|
|
namespace MTP {
|
2017-02-24 17:15:41 +00:00
|
|
|
|
|
|
|
class Instance;
|
|
|
|
|
2017-04-24 12:16:38 +00:00
|
|
|
bool IsPrimeAndGood(base::const_byte_span primeBytes, int g);
|
|
|
|
struct ModExpFirst {
|
|
|
|
static constexpr auto kRandomPowerSize = 256;
|
|
|
|
|
|
|
|
std::vector<gsl::byte> modexp;
|
|
|
|
std::array<gsl::byte, kRandomPowerSize> randomPower;
|
|
|
|
};
|
|
|
|
ModExpFirst CreateModExp(int g, base::const_byte_span primeBytes, base::const_byte_span randomSeed);
|
|
|
|
std::vector<gsl::byte> CreateAuthKey(base::const_byte_span firstBytes, base::const_byte_span randomBytes, base::const_byte_span primeBytes);
|
2017-04-03 18:28:18 +00:00
|
|
|
|
2016-03-24 08:57:11 +00:00
|
|
|
namespace internal {
|
2014-05-30 08:53:19 +00:00
|
|
|
|
2017-02-23 06:57:04 +00:00
|
|
|
class AbstractConnection;
|
2016-03-24 08:57:11 +00:00
|
|
|
class ConnectionPrivate;
|
|
|
|
class SessionData;
|
2017-03-09 18:13:55 +00:00
|
|
|
class RSAPublicKey;
|
2014-05-30 08:53:19 +00:00
|
|
|
|
2016-03-24 08:57:11 +00:00
|
|
|
class Thread : public QThread {
|
2015-03-19 09:18:19 +00:00
|
|
|
Q_OBJECT
|
|
|
|
|
2014-05-30 08:53:19 +00:00
|
|
|
public:
|
2017-02-24 17:15:41 +00:00
|
|
|
Thread() {
|
|
|
|
static int ThreadCounter = 0;
|
|
|
|
_threadIndex = ++ThreadCounter;
|
|
|
|
}
|
|
|
|
int getThreadIndex() const {
|
|
|
|
return _threadIndex;
|
|
|
|
}
|
2014-05-30 08:53:19 +00:00
|
|
|
|
|
|
|
private:
|
2017-02-24 17:15:41 +00:00
|
|
|
int _threadIndex = 0;
|
2016-02-29 16:53:26 +00:00
|
|
|
|
2014-05-30 08:53:19 +00:00
|
|
|
};
|
|
|
|
|
2016-03-24 08:57:11 +00:00
|
|
|
class Connection {
|
2014-05-30 08:53:19 +00:00
|
|
|
public:
|
|
|
|
enum ConnectionType {
|
|
|
|
TcpConnection,
|
|
|
|
HttpConnection
|
|
|
|
};
|
|
|
|
|
2017-02-24 17:15:41 +00:00
|
|
|
Connection(Instance *instance);
|
2016-10-24 15:36:17 +00:00
|
|
|
|
2017-02-25 16:44:02 +00:00
|
|
|
void start(SessionData *data, ShiftedDcId shiftedDcId);
|
2016-10-24 15:36:17 +00:00
|
|
|
|
2016-02-29 16:53:26 +00:00
|
|
|
void kill();
|
|
|
|
void waitTillFinish();
|
2016-03-24 08:57:11 +00:00
|
|
|
~Connection();
|
2014-05-30 08:53:19 +00:00
|
|
|
|
2016-03-24 08:57:11 +00:00
|
|
|
static const int UpdateAlways = 666;
|
2014-05-30 08:53:19 +00:00
|
|
|
|
|
|
|
int32 state() const;
|
|
|
|
QString transport() const;
|
|
|
|
|
|
|
|
private:
|
2017-02-24 17:15:41 +00:00
|
|
|
Instance *_instance = nullptr;
|
|
|
|
std::unique_ptr<QThread> thread;
|
|
|
|
ConnectionPrivate *data = nullptr;
|
2014-05-30 08:53:19 +00:00
|
|
|
|
|
|
|
};
|
|
|
|
|
2016-03-24 08:57:11 +00:00
|
|
|
class ConnectionPrivate : public QObject {
|
2014-05-30 08:53:19 +00:00
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
public:
|
2017-02-25 16:44:02 +00:00
|
|
|
ConnectionPrivate(Instance *instance, QThread *thread, Connection *owner, SessionData *data, ShiftedDcId shiftedDcId);
|
2016-03-24 08:57:11 +00:00
|
|
|
~ConnectionPrivate();
|
2014-05-30 08:53:19 +00:00
|
|
|
|
2014-11-13 11:27:10 +00:00
|
|
|
void stop();
|
|
|
|
|
2017-02-25 16:44:02 +00:00
|
|
|
int32 getShiftedDcId() const;
|
2014-05-30 08:53:19 +00:00
|
|
|
|
|
|
|
int32 getState() const;
|
|
|
|
QString transport() const;
|
|
|
|
|
|
|
|
signals:
|
|
|
|
void needToReceive();
|
|
|
|
void needToRestart();
|
|
|
|
void stateChanged(qint32 newState);
|
2014-08-01 18:49:43 +00:00
|
|
|
void sessionResetDone();
|
2014-05-30 08:53:19 +00:00
|
|
|
|
2014-11-25 12:15:29 +00:00
|
|
|
void needToSendAsync();
|
2016-12-01 19:20:33 +00:00
|
|
|
void sendAnythingAsync(qint64 msWait);
|
2014-11-25 12:15:29 +00:00
|
|
|
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);
|
2014-11-25 12:15:29 +00:00
|
|
|
void resendAllAsync();
|
2014-11-24 13:21:27 +00:00
|
|
|
|
2017-02-24 17:15:41 +00:00
|
|
|
void finished(internal::Connection *connection);
|
2016-02-29 16:53:26 +00:00
|
|
|
|
2014-05-30 08:53:19 +00:00
|
|
|
public slots:
|
|
|
|
void retryByTimer();
|
|
|
|
void restartNow();
|
|
|
|
|
2015-03-12 10:28:10 +00:00
|
|
|
void onPingSender();
|
2015-04-16 14:59:42 +00:00
|
|
|
void onPingSendForce();
|
2015-06-10 12:48:26 +00:00
|
|
|
|
|
|
|
void onWaitConnectedFailed();
|
|
|
|
void onWaitReceivedFailed();
|
|
|
|
void onWaitIPv4Failed();
|
|
|
|
|
2014-05-30 08:53:19 +00:00
|
|
|
void onOldConnection();
|
|
|
|
void onSentSome(uint64 size);
|
|
|
|
void onReceivedSome();
|
|
|
|
|
|
|
|
void onReadyData();
|
2015-06-10 12:48:26 +00:00
|
|
|
|
|
|
|
void onConnected4();
|
|
|
|
void onConnected6();
|
|
|
|
void onDisconnected4();
|
|
|
|
void onDisconnected6();
|
2017-02-25 16:44:02 +00:00
|
|
|
void onError4(qint32 errorCode);
|
|
|
|
void onError6(qint32 errorCode);
|
2015-06-10 12:48:26 +00:00
|
|
|
|
2014-05-30 08:53:19 +00:00
|
|
|
// Auth key creation packet receive slots
|
|
|
|
void pqAnswered();
|
|
|
|
void dhParamsAnswered();
|
|
|
|
void dhClientParamsAnswered();
|
|
|
|
|
|
|
|
// General packet receive slot, connected to conn->receivedData signal
|
|
|
|
void handleReceived();
|
|
|
|
|
|
|
|
// Sessions signals, when we need to send something
|
|
|
|
void tryToSend();
|
|
|
|
|
2015-05-14 16:50:04 +00:00
|
|
|
void updateAuthKey();
|
2014-05-30 08:53:19 +00:00
|
|
|
|
|
|
|
void onConfigLoaded();
|
2017-03-23 16:11:35 +00:00
|
|
|
void onCDNConfigLoaded();
|
2014-05-30 08:53:19 +00:00
|
|
|
|
|
|
|
private:
|
2017-03-23 16:11:35 +00:00
|
|
|
void connectToServer(bool afterConfig = false);
|
2015-08-08 09:14:47 +00:00
|
|
|
void doDisconnect();
|
2017-02-25 16:44:02 +00:00
|
|
|
void restart();
|
2017-03-23 16:11:35 +00:00
|
|
|
void finishAndDestroy();
|
|
|
|
void requestCDNConfig();
|
|
|
|
void handleError(int errorCode);
|
2015-08-08 09:14:47 +00:00
|
|
|
|
2015-06-10 12:48:26 +00:00
|
|
|
void createConn(bool createIPv4, bool createIPv6);
|
2016-03-24 08:57:11 +00:00
|
|
|
void destroyConn(AbstractConnection **conn = 0); // 0 - destory all
|
2014-05-30 08:53:19 +00:00
|
|
|
|
2014-11-05 17:43:32 +00:00
|
|
|
mtpMsgId placeToContainer(mtpRequest &toSendRequest, mtpMsgId &bigMsgId, mtpMsgId *&haveSentArr, mtpRequest &req);
|
2014-08-01 11:09:46 +00:00
|
|
|
mtpMsgId prepareToSend(mtpRequest &request, mtpMsgId currentLastId);
|
|
|
|
mtpMsgId replaceMsgId(mtpRequest &request, mtpMsgId newId);
|
2014-05-30 08:53:19 +00:00
|
|
|
|
2015-08-08 09:14:47 +00:00
|
|
|
bool sendRequest(mtpRequest &request, bool needAnyResponse, QReadLocker &lockFinished);
|
2014-05-30 08:53:19 +00:00
|
|
|
mtpRequestId wasSent(mtpMsgId msgId) const;
|
|
|
|
|
2016-12-07 13:32:25 +00:00
|
|
|
enum class HandleResult {
|
|
|
|
Success,
|
|
|
|
Ignored,
|
|
|
|
RestartConnection,
|
|
|
|
ResetSession,
|
|
|
|
};
|
|
|
|
HandleResult handleOneReceived(const mtpPrime *from, const mtpPrime *end, uint64 msgId, int32 serverTime, uint64 serverSalt, bool badTime);
|
2014-05-30 08:53:19 +00:00
|
|
|
mtpBuffer ungzip(const mtpPrime *from, const mtpPrime *end) const;
|
2017-03-10 19:46:28 +00:00
|
|
|
void handleMsgsStates(const QVector<MTPlong> &ids, const QByteArray &states, QVector<MTPlong> &acked);
|
2014-05-30 08:53:19 +00:00
|
|
|
|
|
|
|
void clearMessages();
|
|
|
|
|
2016-03-24 08:57:11 +00:00
|
|
|
bool setState(int32 state, int32 ifState = Connection::UpdateAlways);
|
2017-02-24 17:15:41 +00:00
|
|
|
|
2017-04-24 12:16:38 +00:00
|
|
|
base::byte_vector encryptPQInnerRSA(const MTPP_Q_inner_data &data, const MTP::internal::RSAPublicKey &key);
|
2017-03-09 18:13:55 +00:00
|
|
|
std::string encryptClientDHInner(const MTPClient_DH_Inner_Data &data);
|
|
|
|
|
2017-02-24 17:15:41 +00:00
|
|
|
Instance *_instance = nullptr;
|
2017-03-23 16:11:35 +00:00
|
|
|
DcType _dcType = DcType::Regular;
|
2017-02-24 17:15:41 +00:00
|
|
|
|
2015-06-25 18:04:40 +00:00
|
|
|
mutable QReadWriteLock stateConnMutex;
|
2017-02-24 17:15:41 +00:00
|
|
|
int32 _state = DisconnectedState;
|
2014-05-30 08:53:19 +00:00
|
|
|
|
2016-12-07 13:32:25 +00:00
|
|
|
bool _needSessionReset = false;
|
2014-08-01 11:09:46 +00:00
|
|
|
void resetSession();
|
|
|
|
|
2017-02-25 16:44:02 +00:00
|
|
|
ShiftedDcId _shiftedDcId = 0;
|
2016-12-07 13:32:25 +00:00
|
|
|
Connection *_owner = nullptr;
|
|
|
|
AbstractConnection *_conn = nullptr;
|
|
|
|
AbstractConnection *_conn4 = nullptr;
|
|
|
|
AbstractConnection *_conn6 = nullptr;;
|
2014-05-30 08:53:19 +00:00
|
|
|
|
2014-11-12 20:30:26 +00:00
|
|
|
SingleTimer retryTimer; // exp retry timer
|
2016-12-07 13:32:25 +00:00
|
|
|
int retryTimeout = 1;
|
2016-12-01 19:20:33 +00:00
|
|
|
qint64 retryWillFinish;
|
2014-05-30 08:53:19 +00:00
|
|
|
|
2014-11-12 20:30:26 +00:00
|
|
|
SingleTimer oldConnectionTimer;
|
2016-12-07 13:32:25 +00:00
|
|
|
bool oldConnection = true;
|
2014-05-30 08:53:19 +00:00
|
|
|
|
2015-06-10 12:48:26 +00:00
|
|
|
SingleTimer _waitForConnectedTimer, _waitForReceivedTimer, _waitForIPv4Timer;
|
|
|
|
uint32 _waitForReceived, _waitForConnected;
|
2016-12-07 13:32:25 +00:00
|
|
|
TimeMs firstSentAt = -1;
|
2014-05-30 08:53:19 +00:00
|
|
|
|
2014-11-05 17:43:32 +00:00
|
|
|
QVector<MTPlong> ackRequestData, resendRequestData;
|
2014-05-30 08:53:19 +00:00
|
|
|
|
|
|
|
// 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);
|
2016-02-13 13:08:28 +00:00
|
|
|
|
2014-05-30 08:53:19 +00:00
|
|
|
// remove msgs with such ids from sessionData->haveSent, add to sessionData->wereAcked
|
2014-10-30 16:23:44 +00:00
|
|
|
void requestsAcked(const QVector<MTPlong> &ids, bool byResponse = false);
|
2014-05-30 08:53:19 +00:00
|
|
|
|
2016-12-07 13:32:25 +00:00
|
|
|
mtpPingId _pingId = 0;
|
|
|
|
mtpPingId _pingIdToSend = 0;
|
|
|
|
TimeMs _pingSendAt = 0;
|
|
|
|
mtpMsgId _pingMsgId = 0;
|
2015-03-12 10:28:10 +00:00
|
|
|
SingleTimer _pingSender;
|
2014-05-30 08:53:19 +00:00
|
|
|
|
2016-12-01 19:20:33 +00:00
|
|
|
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);
|
2014-05-30 08:53:19 +00:00
|
|
|
|
|
|
|
template <typename TRequest>
|
|
|
|
void sendRequestNotSecure(const TRequest &request);
|
|
|
|
|
|
|
|
template <typename TResponse>
|
|
|
|
bool readResponseNotSecure(TResponse &response);
|
|
|
|
|
2016-12-07 13:32:25 +00:00
|
|
|
bool restarted = false;
|
|
|
|
bool _finished = false;
|
2014-05-30 08:53:19 +00:00
|
|
|
|
2016-12-07 13:32:25 +00:00
|
|
|
uint64 keyId = 0;
|
2014-11-13 11:27:10 +00:00
|
|
|
QReadWriteLock sessionDataMutex;
|
2016-12-07 13:32:25 +00:00
|
|
|
SessionData *sessionData = nullptr;
|
2016-03-24 08:57:11 +00:00
|
|
|
|
2016-12-07 13:32:25 +00:00
|
|
|
bool myKeyLock = false;
|
2014-05-30 08:53:19 +00:00
|
|
|
void lockKey();
|
|
|
|
void unlockKey();
|
|
|
|
|
|
|
|
// Auth key creation fields and methods
|
|
|
|
struct AuthKeyCreateData {
|
|
|
|
AuthKeyCreateData()
|
2014-06-14 19:32:11 +00:00
|
|
|
: new_nonce(*(MTPint256*)((uchar*)new_nonce_buf))
|
2016-12-07 13:32:25 +00:00
|
|
|
, auth_key_aux_hash(*(MTPlong*)((uchar*)new_nonce_buf + 33)) {
|
2014-05-30 08:53:19 +00:00
|
|
|
}
|
|
|
|
MTPint128 nonce, server_nonce;
|
2016-12-07 13:32:25 +00:00
|
|
|
uchar new_nonce_buf[41] = { 0 }; // 32 bytes new_nonce + 1 check byte + 8 bytes of auth_key_aux_hash
|
2014-05-30 08:53:19 +00:00
|
|
|
MTPint256 &new_nonce;
|
|
|
|
MTPlong &auth_key_aux_hash;
|
|
|
|
|
2016-12-07 13:32:25 +00:00
|
|
|
uint32 retries = 0;
|
2014-05-30 08:53:19 +00:00
|
|
|
MTPlong retry_id;
|
|
|
|
|
2016-12-07 13:32:25 +00:00
|
|
|
int32 g = 0;
|
2016-02-13 13:08:28 +00:00
|
|
|
|
2016-12-07 13:32:25 +00:00
|
|
|
uchar aesKey[32] = { 0 };
|
|
|
|
uchar aesIV[32] = { 0 };
|
2014-05-30 08:53:19 +00:00
|
|
|
MTPlong auth_key_hash;
|
|
|
|
|
2016-12-07 13:32:25 +00:00
|
|
|
uint32 req_num = 0; // sent not encrypted request number
|
|
|
|
uint32 msgs_sent = 0;
|
2014-05-30 08:53:19 +00:00
|
|
|
};
|
2014-11-05 17:43:32 +00:00
|
|
|
struct AuthKeyCreateStrings {
|
2017-04-24 12:16:38 +00:00
|
|
|
std::vector<gsl::byte> dh_prime;
|
|
|
|
std::vector<gsl::byte> g_a;
|
|
|
|
AuthKey::Data auth_key = { { gsl::byte{} } };
|
2014-11-05 17:43:32 +00:00
|
|
|
};
|
2017-02-21 13:45:56 +00:00
|
|
|
std::unique_ptr<AuthKeyCreateData> _authKeyData;
|
|
|
|
std::unique_ptr<AuthKeyCreateStrings> _authKeyStrings;
|
2014-11-05 17:43:32 +00:00
|
|
|
|
2014-05-30 08:53:19 +00:00
|
|
|
void dhClientParamsSend();
|
|
|
|
void authKeyCreated();
|
|
|
|
void clearAuthKeyData();
|
|
|
|
|
|
|
|
};
|
2016-03-24 08:57:11 +00:00
|
|
|
|
|
|
|
} // namespace internal
|
|
|
|
} // namespace MTP
|