2014-05-30 12:53:19 +04:00
/*
This file is part of Telegram Desktop ,
2018-01-03 13:23:14 +03:00
the official desktop application for the Telegram messaging service .
2014-05-30 12:53:19 +04:00
2018-01-03 13:23:14 +03:00
For license and copyright information please follow this link :
https : //github.com/telegramdesktop/tdesktop/blob/master/LEGAL
2014-05-30 12:53:19 +04:00
*/
2016-03-23 21:43:12 +03:00
# include "mtproto/connection.h"
2016-03-23 21:12:07 +03:00
2019-11-13 17:12:04 +03:00
# include "mtproto/details/mtproto_dc_key_creator.h"
2017-12-18 16:40:15 +04:00
# include "mtproto/session.h"
2017-06-26 20:38:16 +03:00
# include "mtproto/rsa_public_key.h"
# include "mtproto/rpc_sender.h"
# include "mtproto/dc_options.h"
# include "mtproto/connection_abstract.h"
# include "zlib.h"
2019-01-21 17:42:21 +04:00
# include "core/application.h"
2018-06-03 22:52:23 +03:00
# include "core/launcher.h"
2017-06-26 20:38:16 +03:00
# include "lang/lang_keys.h"
# include "base/openssl_help.h"
2018-04-24 23:09:20 +04:00
# include "base/qthelp_url.h"
2019-07-10 19:28:33 +02:00
# include "base/unixtime.h"
2018-06-06 15:16:21 +03:00
extern " C " {
2016-03-23 21:12:07 +03:00
# include <openssl/bn.h>
# include <openssl/err.h>
# include <openssl/aes.h>
# include <openssl/sha.h>
# include <openssl/md5.h>
2014-05-30 12:53:19 +04:00
# include <openssl/rand.h>
2018-06-06 15:16:21 +03:00
} // extern "C"
2016-03-23 21:12:07 +03:00
2019-02-07 19:36:30 +03:00
# ifdef small
# undef small
# endif // small
2016-03-23 21:12:07 +03:00
namespace MTP {
namespace internal {
2016-03-24 11:57:11 +03:00
namespace {
2017-02-25 19:44:02 +03:00
constexpr auto kRecreateKeyId = AuthKey : : KeyId ( 0xFFFFFFFFFFFFFFFFULL ) ;
2017-02-27 12:51:03 +03:00
constexpr auto kIntSize = static_cast < int > ( sizeof ( mtpPrime ) ) ;
2019-02-19 10:57:53 +04:00
constexpr auto kWaitForBetterTimeout = crl : : time ( 2000 ) ;
constexpr auto kMinConnectedTimeout = crl : : time ( 1000 ) ;
constexpr auto kMaxConnectedTimeout = crl : : time ( 8000 ) ;
constexpr auto kMinReceiveTimeout = crl : : time ( 4000 ) ;
constexpr auto kMaxReceiveTimeout = crl : : time ( 64000 ) ;
constexpr auto kMarkConnectionOldTimeout = crl : : time ( 192000 ) ;
2018-04-24 23:09:20 +04:00
constexpr auto kPingDelayDisconnect = 60 ;
2019-11-14 10:13:17 +03:00
constexpr auto kPingSendAfter = 30 * crl : : time ( 1000 ) ;
constexpr auto kPingSendAfterForce = 45 * crl : : time ( 1000 ) ;
constexpr auto kCheckKeyExpiresIn = TimeId ( 3600 ) ;
2018-05-17 22:58:00 +03:00
constexpr auto kTestModeDcIdShift = 10000 ;
2017-04-24 15:16:38 +03:00
2018-04-24 11:21:19 +04:00
// If we can't connect for this time we will ask _instance to update config.
2019-02-19 10:57:53 +04:00
constexpr auto kRequestConfigTimeout = crl : : time ( 8000 ) ;
2018-04-24 11:21:19 +04:00
2016-12-31 12:58:56 +04:00
// Don't try to handle messages larger than this size.
constexpr auto kMaxMessageLength = 16 * 1024 * 1024 ;
2019-11-13 17:12:04 +03:00
using namespace details ;
2017-12-11 18:45:29 +04:00
QString LogIdsVector ( const QVector < MTPlong > & ids ) {
if ( ! ids . size ( ) ) return " [] " ;
auto idsStr = QString ( " [%1 " ) . arg ( ids . cbegin ( ) - > v ) ;
for ( const auto & id : ids ) {
idsStr + = QString ( " , %2 " ) . arg ( id . v ) ;
}
return idsStr + " ] " ;
}
2018-06-25 19:55:27 +01:00
void wrapInvokeAfter ( SecureRequest & to , const SecureRequest & from , const RequestMap & haveSent , int32 skipBeforeRequest = 0 ) {
const auto afterId = * ( mtpMsgId * ) ( from - > after - > data ( ) + 4 ) ;
const auto i = afterId ? haveSent . constFind ( afterId ) : haveSent . cend ( ) ;
2019-11-05 13:23:09 +03:00
int32 size = to - > size ( ) , lenInInts = ( tl : : count_length ( from ) > > 2 ) , headlen = 4 , fulllen = headlen + lenInInts ;
2017-02-24 20:15:41 +03:00
if ( i = = haveSent . constEnd ( ) ) { // no invoke after or such msg was not sent or was completed recently
to - > resize ( size + fulllen + skipBeforeRequest ) ;
if ( skipBeforeRequest ) {
memcpy ( to - > data ( ) + size , from - > constData ( ) + 4 , headlen * sizeof ( mtpPrime ) ) ;
memcpy ( to - > data ( ) + size + headlen + skipBeforeRequest , from - > constData ( ) + 4 + headlen , lenInInts * sizeof ( mtpPrime ) ) ;
} else {
memcpy ( to - > data ( ) + size , from - > constData ( ) + 4 , fulllen * sizeof ( mtpPrime ) ) ;
}
} else {
to - > resize ( size + fulllen + skipBeforeRequest + 3 ) ;
memcpy ( to - > data ( ) + size , from - > constData ( ) + 4 , headlen * sizeof ( mtpPrime ) ) ;
( * to ) [ size + 3 ] + = 3 * sizeof ( mtpPrime ) ;
* ( ( mtpTypeId * ) & ( ( * to ) [ size + headlen + skipBeforeRequest ] ) ) = mtpc_invokeAfterMsg ;
memcpy ( to - > data ( ) + size + headlen + skipBeforeRequest + 1 , & afterId , 2 * sizeof ( mtpPrime ) ) ;
memcpy ( to - > data ( ) + size + headlen + skipBeforeRequest + 3 , from - > constData ( ) + 4 + headlen , lenInInts * sizeof ( mtpPrime ) ) ;
if ( size + 3 ! = 7 ) ( * to ) [ 7 ] + = 3 * sizeof ( mtpPrime ) ;
}
}
2016-03-24 11:57:11 +03:00
} // namespace
2016-03-23 21:12:07 +03:00
2018-04-24 23:09:20 +04:00
Connection : : Connection ( not_null < Instance * > instance ) : _instance ( instance ) {
2014-05-30 12:53:19 +04:00
}
2017-02-25 19:44:02 +03:00
void Connection : : start ( SessionData * sessionData , ShiftedDcId shiftedDcId ) {
2018-04-24 23:09:20 +04:00
Expects ( _thread = = nullptr & & _private = = nullptr ) ;
2014-05-30 12:53:19 +04:00
2018-04-24 23:09:20 +04:00
_thread = std : : make_unique < Thread > ( ) ;
auto newData = std : : make_unique < ConnectionPrivate > (
_instance ,
_thread . get ( ) ,
this ,
sessionData ,
shiftedDcId ) ;
2016-02-29 19:53:26 +03:00
2017-02-25 19:44:02 +03:00
// will be deleted in the thread::finished signal
2018-04-24 23:09:20 +04:00
_private = newData . release ( ) ;
_thread - > start ( ) ;
2014-05-30 12:53:19 +04:00
}
2016-03-24 11:57:11 +03:00
void Connection : : kill ( ) {
2018-04-24 23:09:20 +04:00
Expects ( _private ! = nullptr & & _thread ! = nullptr ) ;
_private - > stop ( ) ;
_private = nullptr ;
_thread - > quit ( ) ;
2014-05-30 12:53:19 +04:00
}
2016-03-24 11:57:11 +03:00
void Connection : : waitTillFinish ( ) {
2018-04-24 23:09:20 +04:00
Expects ( _private = = nullptr & & _thread ! = nullptr ) ;
2016-02-29 19:53:26 +03:00
2016-03-01 05:36:23 +03:00
DEBUG_LOG ( ( " Waiting for connectionThread to finish " ) ) ;
2018-04-24 23:09:20 +04:00
_thread - > wait ( ) ;
_thread . reset ( ) ;
2014-05-30 12:53:19 +04:00
}
2016-03-24 11:57:11 +03:00
int32 Connection : : state ( ) const {
2018-04-24 23:09:20 +04:00
Expects ( _private ! = nullptr & & _thread ! = nullptr ) ;
2014-05-30 12:53:19 +04:00
2018-04-24 23:09:20 +04:00
return _private - > getState ( ) ;
2014-05-30 12:53:19 +04:00
}
2016-03-24 11:57:11 +03:00
QString Connection : : transport ( ) const {
2018-04-24 23:09:20 +04:00
Expects ( _private ! = nullptr & & _thread ! = nullptr ) ;
2014-05-30 12:53:19 +04:00
2018-04-24 23:09:20 +04:00
return _private - > transport ( ) ;
2014-05-30 12:53:19 +04:00
}
2016-03-24 11:57:11 +03:00
Connection : : ~ Connection ( ) {
2018-04-24 23:09:20 +04:00
Expects ( _private = = nullptr ) ;
2018-04-24 12:46:27 +04:00
2018-04-24 23:09:20 +04:00
if ( _thread ) {
2017-02-24 20:15:41 +03:00
waitTillFinish ( ) ;
}
2016-02-29 19:53:26 +03:00
}
2018-04-24 23:09:20 +04:00
void ConnectionPrivate : : appendTestConnection (
DcOptions : : Variants : : Protocol protocol ,
const QString & ip ,
int port ,
const bytes : : vector & protocolSecret ) {
QWriteLocker lock ( & stateConnMutex ) ;
const auto priority = ( qthelp : : is_ipv6 ( ip ) ? 0 : 1 )
2018-04-25 13:24:48 +04:00
+ ( protocol = = DcOptions : : Variants : : Tcp ? 1 : 0 )
+ ( protocolSecret . empty ( ) ? 0 : 1 ) ;
2018-04-24 23:09:20 +04:00
_testConnections . push_back ( {
2018-05-17 22:58:00 +03:00
AbstractConnection : : Create (
_instance ,
protocol ,
thread ( ) ,
2019-07-05 09:54:53 +02:00
protocolSecret ,
2018-05-17 22:58:00 +03:00
_connectionOptions - > proxy ) ,
2018-04-24 23:09:20 +04:00
priority
} ) ;
2019-07-11 12:20:37 +02:00
const auto weak = _testConnections . back ( ) . data . get ( ) ;
2018-04-24 23:09:20 +04:00
connect ( weak , & AbstractConnection : : error , [ = ] ( int errorCode ) {
onError ( weak , errorCode ) ;
} ) ;
connect ( weak , & AbstractConnection : : receivedSome , [ = ] {
onReceivedSome ( ) ;
} ) ;
2019-11-14 10:13:17 +03:00
_firstSentAt = 0 ;
2018-04-24 23:09:20 +04:00
if ( _oldConnection ) {
_oldConnection = false ;
2014-05-30 12:53:19 +04:00
DEBUG_LOG ( ( " This connection marked as not old! " ) ) ;
}
2018-04-24 23:09:20 +04:00
_oldConnectionTimer . callOnce ( kMarkConnectionOldTimeout ) ;
connect ( weak , & AbstractConnection : : connected , [ = ] {
onConnected ( weak ) ;
} ) ;
connect ( weak , & AbstractConnection : : disconnected , [ = ] {
onDisconnected ( weak ) ;
} ) ;
2019-07-10 17:03:48 +02:00
connect ( weak , & AbstractConnection : : syncTimeRequest , [ = ] {
2019-07-10 19:28:33 +02:00
InvokeQueued ( _instance , [ instance = _instance ] {
instance - > syncHttpUnixtime ( ) ;
} ) ;
2019-07-10 17:03:48 +02:00
} ) ;
2014-05-30 12:53:19 +04:00
2018-05-17 22:58:00 +03:00
InvokeQueued ( _testConnections . back ( ) . data , [ = ] {
weak - > connectToServer ( ip , port , protocolSecret , getProtocolDcId ( ) ) ;
} ) ;
}
int16 ConnectionPrivate : : getProtocolDcId ( ) const {
2018-06-11 21:35:27 +03:00
const auto dcId = BareDcId ( _shiftedDcId ) ;
const auto simpleDcId = isTemporaryDcId ( dcId )
? getRealIdFromTemporaryDcId ( dcId )
2018-05-02 22:27:03 +03:00
: dcId ;
2018-05-17 22:58:00 +03:00
const auto testedDcId = cTestMode ( )
? ( kTestModeDcIdShift + simpleDcId )
2018-05-02 22:27:03 +03:00
: simpleDcId ;
2018-05-17 22:58:00 +03:00
return ( _dcType = = DcType : : MediaDownload )
? - testedDcId
: testedDcId ;
2018-04-23 14:24:03 +04:00
}
2015-06-29 15:25:28 +03:00
2018-04-24 23:09:20 +04:00
void ConnectionPrivate : : destroyAllConnections ( ) {
_waitForBetterTimer . cancel ( ) ;
_waitForReceivedTimer . cancel ( ) ;
_waitForConnectedTimer . cancel ( ) ;
_testConnections . clear ( ) ;
2019-11-13 17:12:04 +03:00
_keyCreator = nullptr ;
2018-04-24 23:09:20 +04:00
_connection = nullptr ;
}
ConnectionPrivate : : ConnectionPrivate (
not_null < Instance * > instance ,
not_null < QThread * > thread ,
not_null < Connection * > owner ,
not_null < SessionData * > data ,
ShiftedDcId shiftedDcId )
: QObject ( nullptr )
2017-02-24 20:15:41 +03:00
, _instance ( instance )
2016-03-24 11:57:11 +03:00
, _state ( DisconnectedState )
2017-02-25 19:44:02 +03:00
, _shiftedDcId ( shiftedDcId )
2016-02-29 19:53:26 +03:00
, _owner ( owner )
2018-04-24 23:09:20 +04:00
, _retryTimer ( thread , [ = ] { retryByTimer ( ) ; } )
, _oldConnectionTimer ( thread , [ = ] { markConnectionOld ( ) ; } )
, _waitForConnectedTimer ( thread , [ = ] { waitConnectedFailed ( ) ; } )
, _waitForReceivedTimer ( thread , [ = ] { waitReceivedFailed ( ) ; } )
, _waitForBetterTimer ( thread , [ = ] { waitBetterFailed ( ) ; } )
, _waitForReceived ( kMinReceiveTimeout )
, _waitForConnected ( kMinConnectedTimeout )
, _pingSender ( thread , [ = ] { sendPingByTimer ( ) ; } )
2019-11-14 10:13:17 +03:00
, _sessionData ( data ) {
2017-03-23 19:11:35 +03:00
Expects ( _shiftedDcId ! = 0 ) ;
2014-05-30 12:53:19 +04:00
2018-04-24 23:09:20 +04:00
moveToThread ( thread ) ;
connect ( thread , & QThread : : started , this , [ = ] { connectToServer ( ) ; } ) ;
connect ( thread , & QThread : : finished , this , [ = ] { finishAndDestroy ( ) ; } ) ;
2017-02-24 20:15:41 +03:00
connect ( this , SIGNAL ( finished ( internal : : Connection * ) ) , _instance , SLOT ( connectionFinished ( internal : : Connection * ) ) , Qt : : QueuedConnection ) ;
2014-05-30 12:53:19 +04:00
2019-11-14 10:13:17 +03:00
connect ( _sessionData - > owner ( ) , SIGNAL ( authKeyCreated ( ) ) , this , SLOT ( updateAuthKey ( ) ) , Qt : : QueuedConnection ) ;
connect ( _sessionData - > owner ( ) , SIGNAL ( needToRestart ( ) ) , this , SLOT ( restartNow ( ) ) , Qt : : QueuedConnection ) ;
connect ( this , SIGNAL ( needToReceive ( ) ) , _sessionData - > owner ( ) , SLOT ( tryToReceive ( ) ) , Qt : : QueuedConnection ) ;
connect ( this , SIGNAL ( stateChanged ( qint32 ) ) , _sessionData - > owner ( ) , SLOT ( onConnectionStateChange ( qint32 ) ) , Qt : : QueuedConnection ) ;
connect ( _sessionData - > owner ( ) , SIGNAL ( needToSend ( ) ) , this , SLOT ( tryToSend ( ) ) , Qt : : QueuedConnection ) ;
connect ( _sessionData - > owner ( ) , SIGNAL ( needToPing ( ) ) , this , SLOT ( onPingSendForce ( ) ) , Qt : : QueuedConnection ) ;
connect ( this , SIGNAL ( sessionResetDone ( ) ) , _sessionData - > owner ( ) , SLOT ( onResetDone ( ) ) , Qt : : QueuedConnection ) ;
2014-11-25 15:15:29 +03:00
static bool _registered = false ;
if ( ! _registered ) {
_registered = true ;
2016-12-07 16:32:25 +03:00
qRegisterMetaType < QVector < quint64 > > ( " QVector<quint64> " ) ;
2014-11-25 15:15:29 +03:00
}
2019-11-14 10:13:17 +03:00
connect ( this , SIGNAL ( needToSendAsync ( ) ) , _sessionData - > owner ( ) , SLOT ( needToResumeAndSend ( ) ) , Qt : : QueuedConnection ) ;
connect ( this , SIGNAL ( sendAnythingAsync ( qint64 ) ) , _sessionData - > owner ( ) , SLOT ( sendAnything ( qint64 ) ) , Qt : : QueuedConnection ) ;
connect ( this , SIGNAL ( sendHttpWaitAsync ( ) ) , _sessionData - > owner ( ) , SLOT ( sendAnything ( ) ) , Qt : : QueuedConnection ) ;
connect ( this , SIGNAL ( sendPongAsync ( quint64 , quint64 ) ) , _sessionData - > owner ( ) , SLOT ( sendPong ( quint64 , quint64 ) ) , Qt : : QueuedConnection ) ;
connect ( this , SIGNAL ( sendMsgsStateInfoAsync ( quint64 , QByteArray ) ) , _sessionData - > owner ( ) , SLOT ( sendMsgsStateInfo ( quint64 , QByteArray ) ) , Qt : : QueuedConnection ) ;
connect ( this , SIGNAL ( resendAsync ( quint64 , qint64 , bool , bool ) ) , _sessionData - > owner ( ) , SLOT ( resend ( quint64 , qint64 , bool , bool ) ) , Qt : : QueuedConnection ) ;
connect ( this , SIGNAL ( resendManyAsync ( QVector < quint64 > , qint64 , bool , bool ) ) , _sessionData - > owner ( ) , SLOT ( resendMany ( QVector < quint64 > , qint64 , bool , bool ) ) , Qt : : QueuedConnection ) ;
connect ( this , SIGNAL ( resendAllAsync ( ) ) , _sessionData - > owner ( ) , SLOT ( resendAll ( ) ) , Qt : : QueuedConnection ) ;
2014-05-30 12:53:19 +04:00
}
2016-03-24 11:57:11 +03:00
void ConnectionPrivate : : onConfigLoaded ( ) {
2017-03-23 19:11:35 +03:00
connectToServer ( true ) ;
}
void ConnectionPrivate : : onCDNConfigLoaded ( ) {
restart ( ) ;
2014-05-30 12:53:19 +04:00
}
2017-02-25 19:44:02 +03:00
int32 ConnectionPrivate : : getShiftedDcId ( ) const {
return _shiftedDcId ;
2014-05-30 12:53:19 +04:00
}
2016-03-24 11:57:11 +03:00
int32 ConnectionPrivate : : getState ( ) const {
2015-06-25 21:04:40 +03:00
QReadLocker lock ( & stateConnMutex ) ;
2014-05-30 12:53:19 +04:00
int32 result = _state ;
if ( _state < 0 ) {
2018-04-24 23:09:20 +04:00
if ( _retryTimer . isActive ( ) ) {
2019-02-19 10:57:53 +04:00
result = int32 ( crl : : now ( ) - _retryWillFinish ) ;
2014-05-30 12:53:19 +04:00
if ( result > = 0 ) {
result = - 1 ;
}
}
}
return result ;
}
2016-03-24 11:57:11 +03:00
QString ConnectionPrivate : : transport ( ) const {
2015-06-25 21:04:40 +03:00
QReadLocker lock ( & stateConnMutex ) ;
2018-04-24 23:09:20 +04:00
if ( ! _connection | | ( _state < 0 ) ) {
2014-05-30 12:53:19 +04:00
return QString ( ) ;
}
2018-04-24 12:46:27 +04:00
Assert ( _connectionOptions ! = nullptr ) ;
2018-04-24 23:09:20 +04:00
return _connection - > transport ( ) ;
2014-05-30 12:53:19 +04:00
}
2016-03-24 11:57:11 +03:00
bool ConnectionPrivate : : setState ( int32 state , int32 ifState ) {
if ( ifState ! = Connection : : UpdateAlways ) {
2015-06-25 21:04:40 +03:00
QReadLocker lock ( & stateConnMutex ) ;
2014-05-30 12:53:19 +04:00
if ( _state ! = ifState ) return false ;
}
2015-06-25 21:04:40 +03:00
QWriteLocker lock ( & stateConnMutex ) ;
2014-05-30 12:53:19 +04:00
if ( _state = = state ) return false ;
_state = state ;
if ( state < 0 ) {
2018-04-24 23:09:20 +04:00
_retryTimeout = - state ;
_retryTimer . callOnce ( _retryTimeout ) ;
2019-02-19 10:57:53 +04:00
_retryWillFinish = crl : : now ( ) + _retryTimeout ;
2014-05-30 12:53:19 +04:00
}
emit stateChanged ( state ) ;
return true ;
}
2016-03-24 11:57:11 +03:00
void ConnectionPrivate : : resetSession ( ) { // recreate all msg_id and msg_seqno
2014-08-01 15:09:46 +04:00
_needSessionReset = false ;
2019-11-14 10:13:17 +03:00
QWriteLocker locker1 ( _sessionData - > haveSentMutex ( ) ) ;
QWriteLocker locker2 ( _sessionData - > toResendMutex ( ) ) ;
QWriteLocker locker3 ( _sessionData - > toSendMutex ( ) ) ;
QWriteLocker locker4 ( _sessionData - > wereAckedMutex ( ) ) ;
auto & haveSent = _sessionData - > haveSentMap ( ) ;
auto & toResend = _sessionData - > toResendMap ( ) ;
auto & toSend = _sessionData - > toSendMap ( ) ;
auto & wereAcked = _sessionData - > wereAckedMap ( ) ;
2018-06-25 19:55:27 +01:00
2019-07-10 19:28:33 +02:00
auto newId = base : : unixtime : : mtproto_msg_id ( ) ;
2018-06-25 19:55:27 +01:00
auto setSeqNumbers = RequestMap ( ) ;
auto replaces = QMap < mtpMsgId , mtpMsgId > ( ) ;
for ( auto i = haveSent . cbegin ( ) , e = haveSent . cend ( ) ; i ! = e ; + + i ) {
if ( ! i . value ( ) . isSentContainer ( ) ) {
2014-08-01 15:09:46 +04:00
if ( ! * ( mtpMsgId * ) ( i . value ( ) - > constData ( ) + 4 ) ) continue ;
mtpMsgId id = i . key ( ) ;
if ( id > newId ) {
while ( true ) {
2019-08-30 18:45:07 +03:00
if ( toResend . constFind ( newId ) = = toResend . cend ( )
& & wereAcked . constFind ( newId ) = = wereAcked . cend ( )
& & haveSent . constFind ( newId ) = = haveSent . cend ( ) ) {
2014-08-01 15:09:46 +04:00
break ;
}
2019-07-10 19:28:33 +02:00
const auto m = base : : unixtime : : mtproto_msg_id ( ) ;
2014-08-01 15:09:46 +04:00
if ( m < = newId ) break ; // wtf
newId = m ;
}
2019-08-30 18:45:07 +03:00
MTP_LOG ( _shiftedDcId , ( " Replacing msgId %1 to %2! "
) . arg ( id
) . arg ( newId ) ) ;
2014-08-01 15:09:46 +04:00
replaces . insert ( id , newId ) ;
id = newId ;
* ( mtpMsgId * ) ( i . value ( ) - > data ( ) + 4 ) = id ;
}
setSeqNumbers . insert ( id , i . value ( ) ) ;
}
}
2019-08-30 18:45:07 +03:00
// Collect all non-container requests.
for ( auto i = toResend . cbegin ( ) , e = toResend . cend ( ) ; i ! = e ; + + i ) {
2018-06-25 19:55:27 +01:00
const auto j = toSend . constFind ( i . value ( ) ) ;
2014-08-01 15:09:46 +04:00
if ( j = = toSend . cend ( ) ) continue ;
2018-06-25 19:55:27 +01:00
if ( ! j . value ( ) . isSentContainer ( ) ) {
2014-08-01 15:09:46 +04:00
if ( ! * ( mtpMsgId * ) ( j . value ( ) - > constData ( ) + 4 ) ) continue ;
mtpMsgId id = i . key ( ) ;
if ( id > newId ) {
while ( true ) {
2019-08-30 18:45:07 +03:00
if ( toResend . constFind ( newId ) = = toResend . cend ( )
& & wereAcked . constFind ( newId ) = = wereAcked . cend ( )
& & haveSent . constFind ( newId ) = = haveSent . cend ( ) ) {
2014-08-01 15:09:46 +04:00
break ;
}
2019-07-10 19:28:33 +02:00
const auto m = base : : unixtime : : mtproto_msg_id ( ) ;
2014-08-01 15:09:46 +04:00
if ( m < = newId ) break ; // wtf
newId = m ;
}
2019-08-30 18:45:07 +03:00
MTP_LOG ( _shiftedDcId , ( " Replacing msgId %1 to %2! "
) . arg ( id
) . arg ( newId ) ) ;
2014-08-01 15:09:46 +04:00
replaces . insert ( id , newId ) ;
id = newId ;
* ( mtpMsgId * ) ( j . value ( ) - > data ( ) + 4 ) = id ;
}
setSeqNumbers . insert ( id , j . value ( ) ) ;
}
}
2019-11-14 10:13:17 +03:00
const auto sessionId = rand_value < uint64 > ( ) ;
DEBUG_LOG ( ( " MTP Info: creating new session after bad_msg_notification, setting random server_session %1 " ) . arg ( sessionId ) ) ;
_sessionData - > setSessionId ( sessionId ) ;
2014-08-01 15:09:46 +04:00
2018-06-25 19:55:27 +01:00
for ( auto i = setSeqNumbers . cbegin ( ) , e = setSeqNumbers . cend ( ) ; i ! = e ; + + i ) { // generate new seq_numbers
2014-08-01 15:09:46 +04:00
bool wasNeedAck = ( * ( i . value ( ) - > data ( ) + 6 ) & 1 ) ;
2019-11-14 10:13:17 +03:00
* ( i . value ( ) - > data ( ) + 6 ) = _sessionData - > nextRequestSeqNumber ( wasNeedAck ) ;
2014-08-01 15:09:46 +04:00
}
if ( ! replaces . isEmpty ( ) ) {
2018-06-25 19:55:27 +01:00
for ( auto i = replaces . cbegin ( ) , e = replaces . cend ( ) ; i ! = e ; + + i ) { // replace msgIds keys in all data structs
const auto j = haveSent . find ( i . key ( ) ) ;
2014-08-01 15:09:46 +04:00
if ( j ! = haveSent . cend ( ) ) {
2018-06-25 19:55:27 +01:00
const auto req = j . value ( ) ;
2014-08-01 15:09:46 +04:00
haveSent . erase ( j ) ;
haveSent . insert ( i . value ( ) , req ) ;
}
2018-06-25 19:55:27 +01:00
const auto k = toResend . find ( i . key ( ) ) ;
2014-08-01 15:09:46 +04:00
if ( k ! = toResend . cend ( ) ) {
2018-06-25 19:55:27 +01:00
const auto req = k . value ( ) ;
2014-08-01 15:09:46 +04:00
toResend . erase ( k ) ;
toResend . insert ( i . value ( ) , req ) ;
}
2018-06-25 19:55:27 +01:00
const auto l = wereAcked . find ( i . key ( ) ) ;
if ( l ! = wereAcked . cend ( ) ) {
2019-08-30 18:45:07 +03:00
DEBUG_LOG ( ( " MTP Info: Replaced %1 with %2 in wereAcked. "
) . arg ( i . key ( )
) . arg ( i . value ( ) ) ) ;
2018-06-25 19:55:27 +01:00
const auto req = l . value ( ) ;
wereAcked . erase ( l ) ;
2014-08-01 15:09:46 +04:00
wereAcked . insert ( i . value ( ) , req ) ;
}
}
2018-06-25 19:55:27 +01:00
for ( auto i = haveSent . cbegin ( ) , e = haveSent . cend ( ) ; i ! = e ; + + i ) { // replace msgIds in saved containers
if ( i . value ( ) . isSentContainer ( ) ) {
mtpMsgId * ids = ( mtpMsgId * ) ( i . value ( ) - > data ( ) + 8 ) ;
2014-08-01 15:09:46 +04:00
for ( uint32 j = 0 , l = ( i . value ( ) - > size ( ) - 8 ) > > 1 ; j < l ; + + j ) {
2018-06-25 19:55:27 +01:00
const auto k = replaces . constFind ( ids [ j ] ) ;
2014-08-01 15:09:46 +04:00
if ( k ! = replaces . cend ( ) ) {
ids [ j ] = k . value ( ) ;
}
}
}
}
}
2014-08-01 22:49:43 +04:00
2019-11-14 10:13:17 +03:00
_ackRequestData . clear ( ) ;
_resendRequestData . clear ( ) ;
2014-11-05 20:43:32 +03:00
{
2019-11-14 10:13:17 +03:00
QWriteLocker locker5 ( _sessionData - > stateRequestMutex ( ) ) ;
_sessionData - > stateRequestMap ( ) . clear ( ) ;
2014-11-05 20:43:32 +03:00
}
2014-08-01 22:49:43 +04:00
emit sessionResetDone ( ) ;
2014-08-01 15:09:46 +04:00
}
2018-06-25 19:55:27 +01:00
mtpMsgId ConnectionPrivate : : prepareToSend ( SecureRequest & request , mtpMsgId currentLastId ) {
2014-05-30 12:53:19 +04:00
if ( request - > size ( ) < 9 ) return 0 ;
mtpMsgId msgId = * ( mtpMsgId * ) ( request - > constData ( ) + 4 ) ;
if ( msgId ) { // resending this request
2019-11-14 10:13:17 +03:00
QWriteLocker locker ( _sessionData - > toResendMutex ( ) ) ;
auto & toResend = _sessionData - > toResendMap ( ) ;
2018-06-25 19:55:27 +01:00
const auto i = toResend . find ( msgId ) ;
2014-05-30 12:53:19 +04:00
if ( i ! = toResend . cend ( ) ) {
toResend . erase ( i ) ;
}
} else {
2014-08-01 15:09:46 +04:00
msgId = * ( mtpMsgId * ) ( request - > data ( ) + 4 ) = currentLastId ;
2019-11-14 10:13:17 +03:00
* ( request - > data ( ) + 6 ) = _sessionData - > nextRequestSeqNumber ( request . needAck ( ) ) ;
2014-05-30 12:53:19 +04:00
}
return msgId ;
}
2018-06-25 19:55:27 +01:00
mtpMsgId ConnectionPrivate : : replaceMsgId ( SecureRequest & request , mtpMsgId newId ) {
2014-08-01 15:09:46 +04:00
if ( request - > size ( ) < 9 ) return 0 ;
mtpMsgId oldMsgId = * ( mtpMsgId * ) ( request - > constData ( ) + 4 ) ;
if ( oldMsgId ! = newId ) {
if ( oldMsgId ) {
2019-11-14 10:13:17 +03:00
QWriteLocker locker ( _sessionData - > toResendMutex ( ) ) ;
2014-08-01 15:09:46 +04:00
// haveSentMutex() and wereAckedMutex() were locked in tryToSend()
2019-11-14 10:13:17 +03:00
auto & toResend = _sessionData - > toResendMap ( ) ;
auto & wereAcked = _sessionData - > wereAckedMap ( ) ;
auto & haveSent = _sessionData - > haveSentMap ( ) ;
2014-08-01 15:09:46 +04:00
while ( true ) {
if ( toResend . constFind ( newId ) = = toResend . cend ( ) & & wereAcked . constFind ( newId ) = = wereAcked . cend ( ) & & haveSent . constFind ( newId ) = = haveSent . cend ( ) ) {
break ;
}
2019-07-10 19:28:33 +02:00
const auto m = base : : unixtime : : mtproto_msg_id ( ) ;
2014-08-01 15:09:46 +04:00
if ( m < = newId ) break ; // wtf
2016-01-11 23:43:29 +08:00
2014-08-01 15:09:46 +04:00
newId = m ;
}
2018-06-25 19:55:27 +01:00
const auto i = toResend . find ( oldMsgId ) ;
2014-08-01 15:09:46 +04:00
if ( i ! = toResend . cend ( ) ) {
2018-06-25 19:55:27 +01:00
const auto req = i . value ( ) ;
2014-08-01 15:09:46 +04:00
toResend . erase ( i ) ;
toResend . insert ( newId , req ) ;
}
2018-06-25 19:55:27 +01:00
const auto j = wereAcked . find ( oldMsgId ) ;
2014-08-01 15:09:46 +04:00
if ( j ! = wereAcked . cend ( ) ) {
2018-06-25 19:55:27 +01:00
const auto req = j . value ( ) ;
2014-08-01 15:09:46 +04:00
wereAcked . erase ( j ) ;
wereAcked . insert ( newId , req ) ;
}
2018-06-25 19:55:27 +01:00
const auto k = haveSent . find ( oldMsgId ) ;
2014-08-01 15:09:46 +04:00
if ( k ! = haveSent . cend ( ) ) {
2018-06-25 19:55:27 +01:00
const auto req = k . value ( ) ;
2014-08-01 15:09:46 +04:00
haveSent . erase ( k ) ;
haveSent . insert ( newId , req ) ;
}
2018-06-25 19:55:27 +01:00
for ( auto l = haveSent . begin ( ) ; l ! = haveSent . cend ( ) ; + + l ) {
const auto req = l . value ( ) ;
if ( req . isSentContainer ( ) ) {
const auto ids = ( mtpMsgId * ) ( req - > data ( ) + 8 ) ;
2014-08-01 15:09:46 +04:00
for ( uint32 i = 0 , l = ( req - > size ( ) - 8 ) > > 1 ; i < l ; + + i ) {
if ( ids [ i ] = = oldMsgId ) {
ids [ i ] = newId ;
}
}
}
}
} else {
2019-11-14 10:13:17 +03:00
* ( request - > data ( ) + 6 ) = _sessionData - > nextRequestSeqNumber ( request . needAck ( ) ) ;
2014-08-01 15:09:46 +04:00
}
* ( mtpMsgId * ) ( request - > data ( ) + 4 ) = newId ;
}
return newId ;
}
2018-06-25 19:55:27 +01:00
mtpMsgId ConnectionPrivate : : placeToContainer ( SecureRequest & toSendRequest , mtpMsgId & bigMsgId , mtpMsgId * & haveSentArr , SecureRequest & req ) {
2019-07-10 19:28:33 +02:00
auto msgId = prepareToSend ( req , bigMsgId ) ;
if ( msgId > bigMsgId ) {
msgId = replaceMsgId ( req , bigMsgId ) ;
}
if ( msgId > = bigMsgId ) {
bigMsgId = base : : unixtime : : mtproto_msg_id ( ) ;
}
2014-11-05 20:43:32 +03:00
* ( haveSentArr + + ) = msgId ;
2018-06-25 19:55:27 +01:00
uint32 from = toSendRequest - > size ( ) , len = req . messageSize ( ) ;
2014-11-05 20:43:32 +03:00
toSendRequest - > resize ( from + len ) ;
memcpy ( toSendRequest - > data ( ) + from , req - > constData ( ) + 4 , len * sizeof ( mtpPrime ) ) ;
return msgId ;
}
2016-03-24 11:57:11 +03:00
void ConnectionPrivate : : tryToSend ( ) {
2019-11-14 10:13:17 +03:00
QReadLocker lockFinished ( & _sessionDataMutex ) ;
if ( ! _sessionData | | ! _connection ) {
2014-11-13 14:27:10 +03:00
return ;
}
2014-05-30 12:53:19 +04:00
2018-06-25 19:55:27 +01:00
auto needsLayer = ! _connectionOptions - > inited ;
auto state = getState ( ) ;
auto prependOnly = ( state ! = ConnectedState ) ;
auto pingRequest = SecureRequest ( ) ;
2018-06-11 21:35:27 +03:00
if ( _shiftedDcId = = BareDcId ( _shiftedDcId ) ) { // main session
2019-02-19 10:57:53 +04:00
if ( ! prependOnly & & ! _pingIdToSend & & ! _pingId & & _pingSendAt < = crl : : now ( ) ) {
2016-03-24 13:12:18 +03:00
_pingIdToSend = rand_value < mtpPingId > ( ) ;
2015-03-12 13:28:10 +03:00
}
}
if ( _pingIdToSend ) {
2018-06-11 21:35:27 +03:00
if ( prependOnly | | _shiftedDcId ! = BareDcId ( _shiftedDcId ) ) {
2018-06-25 19:55:27 +01:00
pingRequest = SecureRequest : : Serialize ( MTPPing (
MTP_long ( _pingIdToSend )
) ) ;
DEBUG_LOG ( ( " MTP Info: sending ping, ping_id: %1 "
) . arg ( _pingIdToSend ) ) ;
2015-03-12 13:28:10 +03:00
} else {
2018-06-25 19:55:27 +01:00
pingRequest = SecureRequest : : Serialize ( MTPPing_delay_disconnect (
MTP_long ( _pingIdToSend ) ,
MTP_int ( kPingDelayDisconnect ) ) ) ;
DEBUG_LOG ( ( " MTP Info: sending ping_delay_disconnect, "
" ping_id: %1 " ) . arg ( _pingIdToSend ) ) ;
2015-03-12 13:28:10 +03:00
}
2014-05-30 12:53:19 +04:00
2019-02-19 10:57:53 +04:00
pingRequest - > msDate = crl : : now ( ) ; // > 0 - can send without container
2018-04-24 23:09:20 +04:00
_pingSendAt = pingRequest - > msDate + kPingSendAfter ;
2014-11-05 20:43:32 +03:00
pingRequest - > requestId = 0 ; // dont add to haveSent / wereAcked maps
2014-05-30 12:53:19 +04:00
2018-06-11 21:35:27 +03:00
if ( _shiftedDcId = = BareDcId ( _shiftedDcId ) & & ! prependOnly ) { // main session
2018-04-24 23:09:20 +04:00
_pingSender . callOnce ( kPingSendAfterForce ) ;
2015-03-12 13:28:10 +03:00
}
_pingId = _pingIdToSend ;
_pingIdToSend = 0 ;
2014-05-30 12:53:19 +04:00
} else {
2015-03-12 13:28:10 +03:00
if ( prependOnly ) {
2017-02-25 19:44:02 +03:00
DEBUG_LOG ( ( " MTP Info: dc %1 not sending, waiting for Connected state, state: %2 " ) . arg ( _shiftedDcId ) . arg ( state ) ) ;
2014-05-30 12:53:19 +04:00
return ; // just do nothing, if is not connected yet
2015-03-12 13:28:10 +03:00
} else {
2017-02-25 19:44:02 +03:00
DEBUG_LOG ( ( " MTP Info: dc %1 trying to send after ping, state: %2 " ) . arg ( _shiftedDcId ) . arg ( state ) ) ;
2014-05-30 12:53:19 +04:00
}
}
2018-06-25 19:55:27 +01:00
SecureRequest ackRequest , resendRequest , stateRequest , httpWaitRequest ;
2019-11-14 10:13:17 +03:00
if ( ! prependOnly & & ! _ackRequestData . isEmpty ( ) ) {
2018-06-25 19:55:27 +01:00
ackRequest = SecureRequest : : Serialize ( MTPMsgsAck (
2019-11-14 10:13:17 +03:00
MTP_msgs_ack ( MTP_vector < MTPlong > ( _ackRequestData ) ) ) ) ;
2019-02-19 10:57:53 +04:00
ackRequest - > msDate = crl : : now ( ) ; // > 0 - can send without container
2014-11-05 20:43:32 +03:00
ackRequest - > requestId = 0 ; // dont add to haveSent / wereAcked maps
2019-11-14 10:13:17 +03:00
_ackRequestData . clear ( ) ;
2014-11-05 20:43:32 +03:00
}
2019-11-14 10:13:17 +03:00
if ( ! prependOnly & & ! _resendRequestData . isEmpty ( ) ) {
2018-06-25 19:55:27 +01:00
resendRequest = SecureRequest : : Serialize ( MTPMsgResendReq (
2019-11-14 10:13:17 +03:00
MTP_msg_resend_req ( MTP_vector < MTPlong > ( _resendRequestData ) ) ) ) ;
2019-02-19 10:57:53 +04:00
resendRequest - > msDate = crl : : now ( ) ; // > 0 - can send without container
2014-11-05 20:43:32 +03:00
resendRequest - > requestId = 0 ; // dont add to haveSent / wereAcked maps
2019-11-14 10:13:17 +03:00
_resendRequestData . clear ( ) ;
2014-11-05 20:43:32 +03:00
}
if ( ! prependOnly ) {
QVector < MTPlong > stateReq ;
{
2019-11-14 10:13:17 +03:00
QWriteLocker locker ( _sessionData - > stateRequestMutex ( ) ) ;
auto & ids = _sessionData - > stateRequestMap ( ) ;
2014-11-05 20:43:32 +03:00
if ( ! ids . isEmpty ( ) ) {
stateReq . reserve ( ids . size ( ) ) ;
2018-06-25 19:55:27 +01:00
for ( auto i = ids . cbegin ( ) , e = ids . cend ( ) ; i ! = e ; + + i ) {
2014-11-05 20:43:32 +03:00
stateReq . push_back ( MTP_long ( i . key ( ) ) ) ;
}
}
ids . clear ( ) ;
}
if ( ! stateReq . isEmpty ( ) ) {
2018-06-25 19:55:27 +01:00
stateRequest = SecureRequest : : Serialize ( MTPMsgsStateReq (
MTP_msgs_state_req ( MTP_vector < MTPlong > ( stateReq ) ) ) ) ;
2019-02-19 10:57:53 +04:00
stateRequest - > msDate = crl : : now ( ) ; // > 0 - can send without container
2018-06-02 17:29:21 +03:00
stateRequest - > requestId = GetNextRequestId ( ) ; // add to haveSent / wereAcked maps, but don't add to requestMap
2014-11-05 20:43:32 +03:00
}
2018-04-24 23:09:20 +04:00
if ( _connection - > usingHttpWait ( ) ) {
2018-06-25 19:55:27 +01:00
httpWaitRequest = SecureRequest : : Serialize ( MTPHttpWait (
MTP_http_wait ( MTP_int ( 100 ) , MTP_int ( 30 ) , MTP_int ( 25000 ) ) ) ) ;
2019-02-19 10:57:53 +04:00
httpWaitRequest - > msDate = crl : : now ( ) ; // > 0 - can send without container
2015-03-12 13:28:10 +03:00
httpWaitRequest - > requestId = 0 ; // dont add to haveSent / wereAcked maps
}
2014-11-05 20:43:32 +03:00
}
2018-06-25 19:55:27 +01:00
MTPInitConnection < SecureRequest > initWrapper ;
2014-11-15 02:23:35 +03:00
int32 initSize = 0 , initSizeInInts = 0 ;
if ( needsLayer ) {
2018-04-24 12:46:27 +04:00
Assert ( _connectionOptions ! = nullptr ) ;
2018-05-11 17:03:53 +03:00
const auto systemLangCode = _connectionOptions - > systemLangCode ;
const auto cloudLangCode = _connectionOptions - > cloudLangCode ;
2018-08-20 14:31:40 +03:00
const auto langPackName = _connectionOptions - > langPackName ;
2018-05-11 17:03:53 +03:00
const auto deviceModel = ( _dcType = = DcType : : Cdn )
? " n/a "
2019-02-01 10:48:31 +03:00
: _instance - > deviceModel ( ) ;
2018-05-11 17:03:53 +03:00
const auto systemVersion = ( _dcType = = DcType : : Cdn )
? " n/a "
2019-02-01 10:48:31 +03:00
: _instance - > systemVersion ( ) ;
2019-06-03 13:54:25 +03:00
# if defined OS_MAC_STORE
2018-11-08 09:50:18 +04:00
const auto appVersion = QString : : fromLatin1 ( AppVersionStr )
2019-06-03 13:54:25 +03:00
+ " mac store " ;
# elif defined OS_WIN_STORE // OS_MAC_STORE
const auto appVersion = QString : : fromLatin1 ( AppVersionStr )
+ " win store " ;
2018-06-04 13:41:53 +03:00
# else // OS_MAC_STORE || OS_WIN_STORE
2018-11-08 09:50:18 +04:00
const auto appVersion = QString : : fromLatin1 ( AppVersionStr ) ;
2018-06-04 13:41:53 +03:00
# endif // OS_MAC_STORE || OS_WIN_STORE
2018-05-11 17:03:53 +03:00
const auto proxyType = _connectionOptions - > proxy . type ;
const auto mtprotoProxy = ( proxyType = = ProxyData : : Type : : Mtproto ) ;
const auto clientProxyFields = mtprotoProxy
? MTP_inputClientProxy (
MTP_string ( _connectionOptions - > proxy . host ) ,
MTP_int ( _connectionOptions - > proxy . port ) )
: MTPInputClientProxy ( ) ;
2018-06-25 19:55:27 +01:00
using Flag = MTPInitConnection < SecureRequest > : : Flag ;
initWrapper = MTPInitConnection < SecureRequest > (
2018-05-11 17:03:53 +03:00
MTP_flags ( mtprotoProxy ? Flag : : f_proxy : Flag ( 0 ) ) ,
MTP_int ( ApiId ) ,
MTP_string ( deviceModel ) ,
MTP_string ( systemVersion ) ,
2018-06-04 13:41:53 +03:00
MTP_string ( appVersion ) ,
2018-05-11 17:03:53 +03:00
MTP_string ( systemLangCode ) ,
2018-08-20 14:31:40 +03:00
MTP_string ( langPackName ) ,
2018-05-11 17:03:53 +03:00
MTP_string ( cloudLangCode ) ,
clientProxyFields ,
2018-06-25 19:55:27 +01:00
SecureRequest ( ) ) ;
2019-11-05 13:23:09 +03:00
initSizeInInts = ( tl : : count_length ( initWrapper ) > > 2 ) + 2 ;
2014-11-15 02:23:35 +03:00
initSize = initSizeInInts * sizeof ( mtpPrime ) ;
}
2014-05-30 12:53:19 +04:00
bool needAnyResponse = false ;
2018-06-25 19:55:27 +01:00
SecureRequest toSendRequest ;
2014-05-30 12:53:19 +04:00
{
2019-11-14 10:13:17 +03:00
QWriteLocker locker1 ( _sessionData - > toSendMutex ( ) ) ;
2014-05-30 12:53:19 +04:00
2018-06-25 19:55:27 +01:00
auto toSendDummy = PreRequestMap ( ) ;
2019-11-14 10:13:17 +03:00
auto & toSend = prependOnly ? toSendDummy : _sessionData - > toSendMap ( ) ;
2014-05-30 12:53:19 +04:00
if ( prependOnly ) locker1 . unlock ( ) ;
uint32 toSendCount = toSend . size ( ) ;
2014-11-05 20:43:32 +03:00
if ( pingRequest ) + + toSendCount ;
if ( ackRequest ) + + toSendCount ;
if ( resendRequest ) + + toSendCount ;
if ( stateRequest ) + + toSendCount ;
2015-03-12 13:28:10 +03:00
if ( httpWaitRequest ) + + toSendCount ;
2014-05-30 12:53:19 +04:00
if ( ! toSendCount ) return ; // nothing to send
2018-06-25 19:55:27 +01:00
auto first = pingRequest ? pingRequest : ( ackRequest ? ackRequest : ( resendRequest ? resendRequest : ( stateRequest ? stateRequest : ( httpWaitRequest ? httpWaitRequest : toSend . cbegin ( ) . value ( ) ) ) ) ) ;
2014-05-30 12:53:19 +04:00
if ( toSendCount = = 1 & & first - > msDate > 0 ) { // if can send without container
toSendRequest = first ;
if ( ! prependOnly ) {
toSend . clear ( ) ;
locker1 . unlock ( ) ;
}
2019-07-10 19:28:33 +02:00
const auto msgId = prepareToSend (
toSendRequest ,
base : : unixtime : : mtproto_msg_id ( ) ) ;
2014-11-05 20:43:32 +03:00
if ( pingRequest ) {
2015-03-12 13:28:10 +03:00
_pingMsgId = msgId ;
2014-11-05 20:43:32 +03:00
needAnyResponse = true ;
} else if ( resendRequest | | stateRequest ) {
needAnyResponse = true ;
}
2014-05-30 12:53:19 +04:00
if ( toSendRequest - > requestId ) {
2018-06-25 19:55:27 +01:00
if ( toSendRequest . needAck ( ) ) {
2019-02-19 10:57:53 +04:00
toSendRequest - > msDate = toSendRequest . isStateRequest ( ) ? 0 : crl : : now ( ) ;
2014-05-30 12:53:19 +04:00
2019-11-14 10:13:17 +03:00
QWriteLocker locker2 ( _sessionData - > haveSentMutex ( ) ) ;
auto & haveSent = _sessionData - > haveSentMap ( ) ;
2014-11-05 20:43:32 +03:00
haveSent . insert ( msgId , toSendRequest ) ;
2014-11-15 02:23:35 +03:00
if ( needsLayer & & ! toSendRequest - > needsLayer ) needsLayer = false ;
2014-11-05 20:43:32 +03:00
if ( toSendRequest - > after ) {
2019-11-05 13:23:09 +03:00
const auto toSendSize = tl : : count_length ( toSendRequest ) > > 2 ;
2018-06-25 19:55:27 +01:00
auto wrappedRequest = SecureRequest : : Prepare (
toSendSize ,
toSendSize + 3 ) ;
2014-11-05 20:43:32 +03:00
wrappedRequest - > resize ( 4 ) ;
memcpy ( wrappedRequest - > data ( ) , toSendRequest - > constData ( ) , 4 * sizeof ( mtpPrime ) ) ;
2016-03-24 11:57:11 +03:00
wrapInvokeAfter ( wrappedRequest , toSendRequest , haveSent ) ;
2018-06-25 19:55:27 +01:00
toSendRequest = std : : move ( wrappedRequest ) ;
2014-11-05 20:43:32 +03:00
}
2014-11-15 02:23:35 +03:00
if ( needsLayer ) {
2019-11-05 13:23:09 +03:00
const auto noWrapSize = ( tl : : count_length ( toSendRequest ) > > 2 ) ;
2018-06-25 19:55:27 +01:00
const auto toSendSize = noWrapSize + initSizeInInts ;
auto wrappedRequest = SecureRequest : : Prepare ( toSendSize ) ;
2014-11-15 02:23:35 +03:00
memcpy ( wrappedRequest - > data ( ) , toSendRequest - > constData ( ) , 7 * sizeof ( mtpPrime ) ) ; // all except length
wrappedRequest - > push_back ( mtpc_invokeWithLayer ) ;
2018-06-11 21:35:27 +03:00
wrappedRequest - > push_back ( internal : : CurrentLayer ) ;
2019-11-05 13:23:09 +03:00
initWrapper . write < mtpBuffer > ( * wrappedRequest ) ;
2014-11-15 02:23:35 +03:00
wrappedRequest - > resize ( wrappedRequest - > size ( ) + noWrapSize ) ;
memcpy ( wrappedRequest - > data ( ) + wrappedRequest - > size ( ) - noWrapSize , toSendRequest - > constData ( ) + 8 , noWrapSize * sizeof ( mtpPrime ) ) ;
2018-06-25 19:55:27 +01:00
toSendRequest = std : : move ( wrappedRequest ) ;
2014-11-15 02:23:35 +03:00
}
2014-05-30 12:53:19 +04:00
needAnyResponse = true ;
} else {
2019-11-14 10:13:17 +03:00
QWriteLocker locker3 ( _sessionData - > wereAckedMutex ( ) ) ;
_sessionData - > wereAckedMap ( ) . insert ( msgId , toSendRequest - > requestId ) ;
2014-05-30 12:53:19 +04:00
}
}
} else { // send in container
2014-11-15 02:23:35 +03:00
bool willNeedInit = false ;
2014-05-30 12:53:19 +04:00
uint32 containerSize = 1 + 1 , idsWrapSize = ( toSendCount < < 1 ) ; // cons + vector size, idsWrapSize - size of "request-like" wrap for msgId vector
2018-06-25 19:55:27 +01:00
if ( pingRequest ) containerSize + = pingRequest . messageSize ( ) ;
if ( ackRequest ) containerSize + = ackRequest . messageSize ( ) ;
if ( resendRequest ) containerSize + = resendRequest . messageSize ( ) ;
if ( stateRequest ) containerSize + = stateRequest . messageSize ( ) ;
if ( httpWaitRequest ) containerSize + = httpWaitRequest . messageSize ( ) ;
for ( auto i = toSend . begin ( ) , e = toSend . end ( ) ; i ! = e ; + + i ) {
containerSize + = i . value ( ) . messageSize ( ) ;
2014-11-15 02:23:35 +03:00
if ( needsLayer & & i . value ( ) - > needsLayer ) {
containerSize + = initSizeInInts ;
willNeedInit = true ;
}
}
mtpBuffer initSerialized ;
if ( willNeedInit ) {
initSerialized . reserve ( initSizeInInts ) ;
initSerialized . push_back ( mtpc_invokeWithLayer ) ;
2018-06-11 21:35:27 +03:00
initSerialized . push_back ( internal : : CurrentLayer ) ;
2019-11-05 13:23:09 +03:00
initWrapper . write < mtpBuffer > ( initSerialized ) ;
2014-05-30 12:53:19 +04:00
}
2018-06-25 19:55:27 +01:00
// prepare container + each in invoke after
toSendRequest = SecureRequest : : Prepare (
containerSize ,
containerSize + 3 * toSend . size ( ) ) ;
2014-05-30 12:53:19 +04:00
toSendRequest - > push_back ( mtpc_msg_container ) ;
toSendRequest - > push_back ( toSendCount ) ;
2019-07-10 19:28:33 +02:00
// check for a valid container
auto bigMsgId = base : : unixtime : : mtproto_msg_id ( ) ;
2014-08-01 15:09:46 +04:00
2018-06-25 19:55:27 +01:00
// the fact of this lock is used in replaceMsgId()
2019-11-14 10:13:17 +03:00
QWriteLocker locker2 ( _sessionData - > haveSentMutex ( ) ) ;
auto & haveSent = _sessionData - > haveSentMap ( ) ;
2014-05-30 12:53:19 +04:00
2018-06-25 19:55:27 +01:00
// the fact of this lock is used in replaceMsgId()
2019-11-14 10:13:17 +03:00
QWriteLocker locker3 ( _sessionData - > wereAckedMutex ( ) ) ;
auto & wereAcked = _sessionData - > wereAckedMap ( ) ;
2014-05-30 12:53:19 +04:00
2018-06-25 19:55:27 +01:00
// prepare "request-like" wrap for msgId vector
auto haveSentIdsWrap = SecureRequest : : Prepare ( idsWrapSize ) ;
2014-05-30 12:53:19 +04:00
haveSentIdsWrap - > requestId = 0 ;
haveSentIdsWrap - > resize ( haveSentIdsWrap - > size ( ) + idsWrapSize ) ;
2018-06-25 19:55:27 +01:00
auto haveSentArr = ( mtpMsgId * ) ( haveSentIdsWrap - > data ( ) + 8 ) ;
2014-05-30 12:53:19 +04:00
2014-11-05 20:43:32 +03:00
if ( pingRequest ) {
2015-03-12 13:28:10 +03:00
_pingMsgId = placeToContainer ( toSendRequest , bigMsgId , haveSentArr , pingRequest ) ;
2014-11-05 20:43:32 +03:00
needAnyResponse = true ;
} else if ( resendRequest | | stateRequest ) {
2014-05-30 12:53:19 +04:00
needAnyResponse = true ;
}
2018-06-25 19:55:27 +01:00
for ( auto i = toSend . begin ( ) , e = toSend . end ( ) ; i ! = e ; + + i ) {
auto & req = i . value ( ) ;
auto msgId = prepareToSend ( req , bigMsgId ) ;
2019-07-10 19:28:33 +02:00
if ( msgId > bigMsgId ) {
msgId = replaceMsgId ( req , bigMsgId ) ;
}
if ( msgId > = bigMsgId ) {
bigMsgId = base : : unixtime : : mtproto_msg_id ( ) ;
}
2014-08-01 15:09:46 +04:00
* ( haveSentArr + + ) = msgId ;
2014-11-05 20:43:32 +03:00
bool added = false ;
2014-05-30 12:53:19 +04:00
if ( req - > requestId ) {
2018-06-25 19:55:27 +01:00
if ( req . needAck ( ) ) {
2019-02-19 10:57:53 +04:00
req - > msDate = req . isStateRequest ( ) ? 0 : crl : : now ( ) ;
2014-11-15 02:23:35 +03:00
int32 reqNeedsLayer = ( needsLayer & & req - > needsLayer ) ? toSendRequest - > size ( ) : 0 ;
2014-11-05 20:43:32 +03:00
if ( req - > after ) {
2016-03-24 11:57:11 +03:00
wrapInvokeAfter ( toSendRequest , req , haveSent , reqNeedsLayer ? initSizeInInts : 0 ) ;
2014-11-15 02:23:35 +03:00
if ( reqNeedsLayer ) {
memcpy ( toSendRequest - > data ( ) + reqNeedsLayer + 4 , initSerialized . constData ( ) , initSize ) ;
* ( toSendRequest - > data ( ) + reqNeedsLayer + 3 ) + = initSize ;
}
added = true ;
} else if ( reqNeedsLayer ) {
2018-06-25 19:55:27 +01:00
toSendRequest - > resize ( reqNeedsLayer + initSizeInInts + req . messageSize ( ) ) ;
2014-11-15 02:23:35 +03:00
memcpy ( toSendRequest - > data ( ) + reqNeedsLayer , req - > constData ( ) + 4 , 4 * sizeof ( mtpPrime ) ) ;
memcpy ( toSendRequest - > data ( ) + reqNeedsLayer + 4 , initSerialized . constData ( ) , initSize ) ;
2019-11-05 13:23:09 +03:00
memcpy ( toSendRequest - > data ( ) + reqNeedsLayer + 4 + initSizeInInts , req - > constData ( ) + 8 , tl : : count_length ( req ) ) ;
2014-11-15 02:23:35 +03:00
* ( toSendRequest - > data ( ) + reqNeedsLayer + 3 ) + = initSize ;
2014-11-05 20:43:32 +03:00
added = true ;
}
2014-05-30 12:53:19 +04:00
haveSent . insert ( msgId , req ) ;
needAnyResponse = true ;
} else {
wereAcked . insert ( msgId , req - > requestId ) ;
}
}
2014-11-05 20:43:32 +03:00
if ( ! added ) {
2018-06-25 19:55:27 +01:00
uint32 from = toSendRequest - > size ( ) , len = req . messageSize ( ) ;
2014-11-05 20:43:32 +03:00
toSendRequest - > resize ( from + len ) ;
memcpy ( toSendRequest - > data ( ) + from , req - > constData ( ) + 4 , len * sizeof ( mtpPrime ) ) ;
}
}
if ( stateRequest ) {
mtpMsgId msgId = placeToContainer ( toSendRequest , bigMsgId , haveSentArr , stateRequest ) ;
stateRequest - > msDate = 0 ; // 0 for state request, do not request state of it
haveSent . insert ( msgId , stateRequest ) ;
2014-05-30 12:53:19 +04:00
}
2014-11-05 20:43:32 +03:00
if ( resendRequest ) placeToContainer ( toSendRequest , bigMsgId , haveSentArr , resendRequest ) ;
if ( ackRequest ) placeToContainer ( toSendRequest , bigMsgId , haveSentArr , ackRequest ) ;
2015-03-12 13:28:10 +03:00
if ( httpWaitRequest ) placeToContainer ( toSendRequest , bigMsgId , haveSentArr , httpWaitRequest ) ;
2014-05-30 12:53:19 +04:00
2014-08-01 15:09:46 +04:00
mtpMsgId contMsgId = prepareToSend ( toSendRequest , bigMsgId ) ;
2014-05-30 12:53:19 +04:00
* ( mtpMsgId * ) ( haveSentIdsWrap - > data ( ) + 4 ) = contMsgId ;
( * haveSentIdsWrap ) [ 6 ] = 0 ; // for container, msDate = 0, seqNo = 0
haveSent . insert ( contMsgId , haveSentIdsWrap ) ;
toSend . clear ( ) ;
}
}
2018-06-25 19:55:27 +01:00
sendSecureRequest (
std : : move ( toSendRequest ) ,
needAnyResponse ,
lockFinished ) ;
2014-05-30 12:53:19 +04:00
}
2016-03-24 11:57:11 +03:00
void ConnectionPrivate : : retryByTimer ( ) {
2019-11-14 10:13:17 +03:00
QReadLocker lockFinished ( & _sessionDataMutex ) ;
if ( ! _sessionData ) return ;
2014-11-13 14:27:10 +03:00
2018-04-24 23:09:20 +04:00
if ( _retryTimeout < 3 ) {
+ + _retryTimeout ;
} else if ( _retryTimeout = = 3 ) {
_retryTimeout = 1000 ;
} else if ( _retryTimeout < 64000 ) {
_retryTimeout * = 2 ;
2014-05-30 12:53:19 +04:00
}
2019-11-14 10:13:17 +03:00
if ( _keyId = = kRecreateKeyId ) {
if ( _sessionData - > getKey ( ) ) {
2015-05-14 19:50:04 +03:00
unlockKey ( ) ;
2019-11-14 10:13:17 +03:00
QWriteLocker lock ( _sessionData - > keyMutex ( ) ) ;
_sessionData - > owner ( ) - > destroyKey ( ) ;
2014-05-30 12:53:19 +04:00
}
2019-11-14 10:13:17 +03:00
_keyId = 0 ;
2014-05-30 12:53:19 +04:00
}
2017-03-23 19:11:35 +03:00
connectToServer ( ) ;
2014-05-30 12:53:19 +04:00
}
2016-03-24 11:57:11 +03:00
void ConnectionPrivate : : restartNow ( ) {
2018-04-24 23:09:20 +04:00
_retryTimeout = 1 ;
_retryTimer . cancel ( ) ;
2014-05-30 12:53:19 +04:00
restart ( ) ;
}
2017-03-23 19:11:35 +03:00
void ConnectionPrivate : : connectToServer ( bool afterConfig ) {
2016-02-29 19:53:26 +03:00
if ( _finished ) {
2018-04-24 12:46:27 +04:00
DEBUG_LOG ( ( " MTP Error: "
" connectToServer() called for finished connection! " ) ) ;
2016-02-29 19:53:26 +03:00
return ;
}
2019-11-14 10:13:17 +03:00
QReadLocker lockFinished ( & _sessionDataMutex ) ;
if ( ! _sessionData ) {
DEBUG_LOG ( ( " MTP Error: "
" connectToServer() called for stopped connection! " ) ) ;
return ;
2018-04-24 12:46:27 +04:00
}
2019-11-14 10:13:17 +03:00
_connectionOptions = std : : make_unique < ConnectionOptions > (
_sessionData - > connectionOptions ( ) ) ;
const auto hasKey = ( _sessionData - > getKey ( ) ! = nullptr ) ;
lockFinished . unlock ( ) ;
const auto bareDc = BareDcId ( _shiftedDcId ) ;
2018-04-24 12:46:27 +04:00
_dcType = _instance - > dcOptions ( ) - > dcType ( _shiftedDcId ) ;
// Use media_only addresses only if key for this dc is already created.
if ( _dcType = = DcType : : MediaDownload & & ! hasKey ) {
_dcType = DcType : : Regular ;
2017-03-23 19:11:35 +03:00
} else if ( _dcType = = DcType : : Cdn & & ! _instance - > isKeysDestroyer ( ) ) {
2017-06-26 20:38:16 +03:00
if ( ! _instance - > dcOptions ( ) - > hasCDNKeysForDc ( bareDc ) ) {
2017-03-23 19:11:35 +03:00
requestCDNConfig ( ) ;
return ;
2015-05-14 19:50:04 +03:00
}
}
2017-02-23 09:57:04 +03:00
2018-04-24 23:09:20 +04:00
if ( afterConfig & & ( ! _testConnections . empty ( ) | | _connection ) ) {
return ;
}
destroyAllConnections ( ) ;
2018-05-05 15:14:17 +03:00
if ( _connectionOptions - > proxy . type = = ProxyData : : Type : : Mtproto ) {
2018-05-17 22:58:00 +03:00
// host, port, secret for mtproto proxy are taken from proxy.
appendTestConnection ( DcOptions : : Variants : : Tcp , { } , 0 , { } ) ;
2018-04-24 23:09:20 +04:00
} else {
using Variants = DcOptions : : Variants ;
const auto special = ( _dcType = = DcType : : Temporary ) ;
const auto variants = _instance - > dcOptions ( ) - > lookup (
bareDc ,
_dcType ,
_connectionOptions - > proxy . type ! = ProxyData : : Type : : None ) ;
const auto useIPv4 = special ? true : _connectionOptions - > useIPv4 ;
const auto useIPv6 = special ? false : _connectionOptions - > useIPv6 ;
const auto useTcp = special ? true : _connectionOptions - > useTcp ;
const auto useHttp = special ? false : _connectionOptions - > useHttp ;
const auto skipAddress = ! useIPv4
? Variants : : IPv4
: ! useIPv6
? Variants : : IPv6
: Variants : : AddressTypeCount ;
const auto skipProtocol = ! useTcp
? Variants : : Tcp
: ! useHttp
? Variants : : Http
: Variants : : ProtocolCount ;
for ( auto address = 0 ; address ! = Variants : : AddressTypeCount ; + + address ) {
if ( address = = skipAddress ) {
continue ;
}
for ( auto protocol = 0 ; protocol ! = Variants : : ProtocolCount ; + + protocol ) {
if ( protocol = = skipProtocol ) {
continue ;
}
for ( const auto & endpoint : variants . data [ address ] [ protocol ] ) {
appendTestConnection (
static_cast < Variants : : Protocol > ( protocol ) ,
QString : : fromStdString ( endpoint . ip ) ,
endpoint . port ,
2018-05-02 22:07:34 +03:00
endpoint . secret ) ;
2018-04-24 23:09:20 +04:00
}
}
}
}
if ( _testConnections . empty ( ) ) {
2017-02-25 19:44:02 +03:00
if ( _instance - > isKeysDestroyer ( ) ) {
2018-04-24 23:09:20 +04:00
LOG ( ( " MTP Error: DC %1 options for not found for auth key destruction! " ) . arg ( _shiftedDcId ) ) ;
2019-11-13 11:31:12 +03:00
_instance - > checkIfKeyWasDestroyed ( _shiftedDcId ) ;
2017-02-25 19:44:02 +03:00
return ;
} else if ( afterConfig ) {
2018-04-24 23:09:20 +04:00
LOG ( ( " MTP Error: DC %1 options for not found right after config load! " ) . arg ( _shiftedDcId ) ) ;
2014-05-30 12:53:19 +04:00
return restart ( ) ;
}
2018-04-24 23:09:20 +04:00
DEBUG_LOG ( ( " MTP Info: DC %1 options not found, waiting for config " ) . arg ( _shiftedDcId ) ) ;
2017-02-24 20:15:41 +03:00
connect ( _instance , SIGNAL ( configLoaded ( ) ) , this , SLOT ( onConfigLoaded ( ) ) , Qt : : UniqueConnection ) ;
2018-04-24 11:21:19 +04:00
InvokeQueued ( _instance , [ instance = _instance ] {
instance - > requestConfig ( ) ;
} ) ;
2015-05-14 19:50:04 +03:00
return ;
2014-05-30 12:53:19 +04:00
}
2018-05-28 11:36:12 +03:00
DEBUG_LOG ( ( " Connection Info: Connecting to %1 with %2 test connections. "
) . arg ( _shiftedDcId
) . arg ( _testConnections . size ( ) ) ) ;
2014-05-30 12:53:19 +04:00
2018-05-02 22:07:34 +03:00
if ( ! _startedConnectingAt ) {
2019-02-19 10:57:53 +04:00
_startedConnectingAt = crl : : now ( ) ;
} else if ( crl : : now ( ) - _startedConnectingAt > kRequestConfigTimeout ) {
2018-04-24 11:21:19 +04:00
InvokeQueued ( _instance , [ instance = _instance ] {
instance - > requestConfigIfOld ( ) ;
} ) ;
}
2015-06-10 15:48:26 +03:00
2018-04-24 23:09:20 +04:00
_retryTimer . cancel ( ) ;
_waitForConnectedTimer . cancel ( ) ;
2015-06-10 15:48:26 +03:00
2016-03-24 11:57:11 +03:00
setState ( ConnectingState ) ;
2015-06-10 15:48:26 +03:00
_pingId = _pingMsgId = _pingIdToSend = _pingSendAt = 0 ;
2018-04-24 23:09:20 +04:00
_pingSender . cancel ( ) ;
_waitForConnectedTimer . callOnce ( _waitForConnected ) ;
2014-05-30 12:53:19 +04:00
}
2017-02-25 19:44:02 +03:00
void ConnectionPrivate : : restart ( ) {
2019-11-14 10:13:17 +03:00
QReadLocker lockFinished ( & _sessionDataMutex ) ;
if ( ! _sessionData ) return ;
2014-11-13 14:27:10 +03:00
2017-02-25 19:44:02 +03:00
DEBUG_LOG ( ( " MTP Info: restarting Connection " ) ) ;
2014-05-30 12:53:19 +04:00
2018-04-24 23:09:20 +04:00
_waitForReceivedTimer . cancel ( ) ;
_waitForConnectedTimer . cancel ( ) ;
2014-05-30 12:53:19 +04:00
2019-11-14 10:13:17 +03:00
auto key = _sessionData - > getKey ( ) ;
2014-05-30 12:53:19 +04:00
if ( key ) {
2019-11-14 10:13:17 +03:00
if ( ! _sessionData - > isCheckedKey ( ) ) {
2017-02-25 19:44:02 +03:00
// No destroying in case of an error.
//
//if (mayBeBadKey) {
// clearMessages();
2019-11-14 10:13:17 +03:00
// _keyId = kRecreateKeyId;
2015-12-08 23:41:04 +03:00
// retryTimeout = 1; // no ddos please
2017-02-25 19:44:02 +03:00
// LOG(("MTP Info: key may be bad and was not checked - but won't be destroyed, no log outs because of bad server right now..."));
//}
2014-05-30 12:53:19 +04:00
} else {
2019-11-14 10:13:17 +03:00
_sessionData - > setCheckedKey ( false ) ;
2014-05-30 12:53:19 +04:00
}
}
2015-08-08 12:14:47 +03:00
lockFinished . unlock ( ) ;
2014-05-30 12:53:19 +04:00
doDisconnect ( ) ;
2015-08-08 12:14:47 +03:00
lockFinished . relock ( ) ;
2019-11-14 10:13:17 +03:00
if ( _sessionData & & _needSessionReset ) {
2014-08-01 15:09:46 +04:00
resetSession ( ) ;
}
2019-11-14 10:13:17 +03:00
_restarted = true ;
2018-04-24 23:09:20 +04:00
if ( _retryTimer . isActive ( ) ) return ;
2014-05-30 12:53:19 +04:00
2018-04-24 23:09:20 +04:00
DEBUG_LOG ( ( " MTP Info: restart timeout: %1ms " ) . arg ( _retryTimeout ) ) ;
setState ( - _retryTimeout ) ;
2014-05-30 12:53:19 +04:00
}
2016-03-24 11:57:11 +03:00
void ConnectionPrivate : : onSentSome ( uint64 size ) {
2015-06-10 15:48:26 +03:00
if ( ! _waitForReceivedTimer . isActive ( ) ) {
2017-03-23 19:11:35 +03:00
auto remain = static_cast < uint64 > ( _waitForReceived ) ;
2018-04-24 23:09:20 +04:00
if ( ! _oldConnection ) {
// 8kb / sec, so 512 kb give 64 sec
auto remainBySize = size * _waitForReceived / 8192 ;
remain = snap ( remainBySize , remain , uint64 ( kMaxReceiveTimeout ) ) ;
2015-06-10 15:48:26 +03:00
if ( remain ! = _waitForReceived ) {
2014-05-30 12:53:19 +04:00
DEBUG_LOG ( ( " Checking connect for request with size %1 bytes, delay will be %2 " ) . arg ( size ) . arg ( remain ) ) ;
}
}
2017-02-25 19:44:02 +03:00
if ( isUploadDcId ( _shiftedDcId ) ) {
2017-03-23 19:11:35 +03:00
remain * = kUploadSessionsCount ;
2017-02-25 19:44:02 +03:00
} else if ( isDownloadDcId ( _shiftedDcId ) ) {
2017-03-23 19:11:35 +03:00
remain * = kDownloadSessionsCount ;
2014-10-30 19:23:44 +03:00
}
2018-04-24 23:09:20 +04:00
_waitForReceivedTimer . callOnce ( remain ) ;
2014-05-30 12:53:19 +04:00
}
2019-11-14 10:13:17 +03:00
if ( ! _firstSentAt ) _firstSentAt = crl : : now ( ) ;
2014-05-30 12:53:19 +04:00
}
2016-03-24 11:57:11 +03:00
void ConnectionPrivate : : onReceivedSome ( ) {
2018-04-24 23:09:20 +04:00
if ( _oldConnection ) {
_oldConnection = false ;
2014-05-30 12:53:19 +04:00
DEBUG_LOG ( ( " This connection marked as not old! " ) ) ;
}
2018-04-24 23:09:20 +04:00
_oldConnectionTimer . callOnce ( kMarkConnectionOldTimeout ) ;
_waitForReceivedTimer . cancel ( ) ;
2019-11-14 10:13:17 +03:00
if ( _firstSentAt > 0 ) {
const auto ms = crl : : now ( ) - _firstSentAt ;
2015-06-10 15:48:26 +03:00
DEBUG_LOG ( ( " MTP Info: response in %1ms, _waitForReceived: %2ms " ) . arg ( ms ) . arg ( _waitForReceived ) ) ;
2014-05-30 12:53:19 +04:00
2018-05-17 22:58:00 +03:00
if ( ms > 0 & & ms * 2 < _waitForReceived ) {
_waitForReceived = qMax ( ms * 2 , kMinReceiveTimeout ) ;
2018-04-24 23:09:20 +04:00
}
2019-11-14 10:13:17 +03:00
_firstSentAt = - 1 ;
2014-05-30 12:53:19 +04:00
}
}
2018-04-24 23:09:20 +04:00
void ConnectionPrivate : : markConnectionOld ( ) {
_oldConnection = true ;
_waitForReceived = kMinReceiveTimeout ;
2015-06-10 15:48:26 +03:00
DEBUG_LOG ( ( " This connection marked as old! _waitForReceived now %1ms " ) . arg ( _waitForReceived ) ) ;
2014-05-30 12:53:19 +04:00
}
2018-04-24 23:09:20 +04:00
void ConnectionPrivate : : sendPingByTimer ( ) {
2015-03-12 13:28:10 +03:00
if ( _pingId ) {
2018-06-04 22:48:17 +03:00
// _pingSendAt: when to send next ping (lastPingAt + kPingSendAfter)
// could be equal to zero.
2019-02-19 10:57:53 +04:00
const auto now = crl : : now ( ) ;
2018-06-04 22:48:17 +03:00
const auto mustSendTill = _pingSendAt
+ kPingSendAfterForce
- kPingSendAfter ;
if ( mustSendTill < now + 1000 ) {
2018-04-24 23:09:20 +04:00
LOG ( ( " Could not send ping for some seconds, restarting... " ) ) ;
2015-03-12 13:28:10 +03:00
return restart ( ) ;
} else {
2018-06-04 22:48:17 +03:00
_pingSender . callOnce ( mustSendTill - now ) ;
2015-03-12 13:28:10 +03:00
}
} else {
emit needToSendAsync ( ) ;
}
}
2016-03-24 11:57:11 +03:00
void ConnectionPrivate : : onPingSendForce ( ) {
2015-04-16 17:59:42 +03:00
if ( ! _pingId ) {
_pingSendAt = 0 ;
DEBUG_LOG ( ( " Will send ping! " ) ) ;
tryToSend ( ) ;
}
}
2018-04-24 23:09:20 +04:00
void ConnectionPrivate : : waitReceivedFailed ( ) {
2018-04-24 12:46:27 +04:00
Expects ( _connectionOptions ! = nullptr ) ;
if ( ! _connectionOptions - > useTcp ) {
2014-05-30 12:53:19 +04:00
return ;
}
2015-06-10 15:48:26 +03:00
DEBUG_LOG ( ( " MTP Info: bad connection, _waitForReceived: %1ms " ) . arg ( _waitForReceived ) ) ;
2018-04-24 23:09:20 +04:00
if ( _waitForReceived < kMaxReceiveTimeout ) {
2015-06-10 15:48:26 +03:00
_waitForReceived * = 2 ;
2014-05-30 12:53:19 +04:00
}
doDisconnect ( ) ;
2019-11-14 10:13:17 +03:00
_restarted = true ;
2018-04-24 23:09:20 +04:00
if ( _retryTimer . isActive ( ) ) {
return ;
}
2014-05-30 12:53:19 +04:00
DEBUG_LOG ( ( " MTP Info: immediate restart! " ) ) ;
2018-05-17 22:58:00 +03:00
InvokeQueued ( this , [ = ] { connectToServer ( ) ; } ) ;
2014-05-30 12:53:19 +04:00
}
2018-04-24 23:09:20 +04:00
void ConnectionPrivate : : waitConnectedFailed ( ) {
2015-06-10 15:48:26 +03:00
DEBUG_LOG ( ( " MTP Info: can't connect in %1ms " ) . arg ( _waitForConnected ) ) ;
2018-05-17 22:58:00 +03:00
auto maxTimeout = kMaxConnectedTimeout ;
for ( const auto & connection : _testConnections ) {
accumulate_max ( maxTimeout , connection . data - > fullConnectTimeout ( ) ) ;
}
if ( _waitForConnected < maxTimeout ) {
_waitForConnected = std : : min ( maxTimeout , 2 * _waitForConnected ) ;
2018-04-24 23:09:20 +04:00
}
2015-06-02 14:22:00 +03:00
2019-07-10 17:03:48 +02:00
connectingTimedOut ( ) ;
2019-11-14 10:13:17 +03:00
_restarted = true ;
2015-06-02 14:22:00 +03:00
DEBUG_LOG ( ( " MTP Info: immediate restart! " ) ) ;
2018-05-17 22:58:00 +03:00
InvokeQueued ( this , [ = ] { connectToServer ( ) ; } ) ;
2015-06-02 14:22:00 +03:00
}
2018-04-24 23:09:20 +04:00
void ConnectionPrivate : : waitBetterFailed ( ) {
confirmBestConnection ( ) ;
2015-06-10 15:48:26 +03:00
}
2019-07-10 17:03:48 +02:00
void ConnectionPrivate : : connectingTimedOut ( ) {
for ( const auto & connection : _testConnections ) {
connection . data - > timedOut ( ) ;
}
doDisconnect ( ) ;
}
2016-03-24 11:57:11 +03:00
void ConnectionPrivate : : doDisconnect ( ) {
2018-04-23 14:24:03 +04:00
destroyAllConnections ( ) ;
2014-05-30 12:53:19 +04:00
2015-08-08 12:14:47 +03:00
{
2019-11-14 10:13:17 +03:00
QReadLocker lockFinished ( & _sessionDataMutex ) ;
if ( _sessionData ) {
2015-08-08 12:14:47 +03:00
unlockKey ( ) ;
}
}
2014-05-30 12:53:19 +04:00
2016-03-24 11:57:11 +03:00
setState ( DisconnectedState ) ;
2019-11-14 10:13:17 +03:00
_restarted = false ;
2014-05-30 12:53:19 +04:00
}
2017-03-23 19:11:35 +03:00
void ConnectionPrivate : : finishAndDestroy ( ) {
2014-05-30 12:53:19 +04:00
doDisconnect ( ) ;
2016-02-29 19:53:26 +03:00
_finished = true ;
emit finished ( _owner ) ;
deleteLater ( ) ;
2014-05-30 12:53:19 +04:00
}
2017-03-23 19:11:35 +03:00
void ConnectionPrivate : : requestCDNConfig ( ) {
2018-05-17 22:58:00 +03:00
connect (
_instance ,
SIGNAL ( cdnConfigLoaded ( ) ) ,
this ,
SLOT ( onCDNConfigLoaded ( ) ) ,
Qt : : UniqueConnection ) ;
InvokeQueued ( _instance , [ instance = _instance ] {
instance - > requestCDNConfig ( ) ;
} ) ;
2017-03-23 19:11:35 +03:00
}
2016-03-24 11:57:11 +03:00
void ConnectionPrivate : : handleReceived ( ) {
2019-11-14 10:13:17 +03:00
QReadLocker lockFinished ( & _sessionDataMutex ) ;
if ( ! _sessionData ) return ;
2014-11-13 14:27:10 +03:00
2014-05-30 12:53:19 +04:00
onReceivedSome ( ) ;
2017-02-27 12:51:03 +03:00
auto restartOnError = [ this , & lockFinished ] {
lockFinished . unlock ( ) ;
restart ( ) ;
} ;
2019-11-14 10:13:17 +03:00
ReadLockerAttempt lock ( _sessionData - > keyMutex ( ) ) ;
2014-05-30 12:53:19 +04:00
if ( ! lock ) {
2017-02-25 19:44:02 +03:00
DEBUG_LOG ( ( " MTP Error: auth_key for dc %1 busy, cant lock " ) . arg ( _shiftedDcId ) ) ;
2014-05-30 12:53:19 +04:00
clearMessages ( ) ;
2019-11-14 10:13:17 +03:00
_keyId = 0 ;
2015-08-08 12:14:47 +03:00
2017-02-27 12:51:03 +03:00
return restartOnError ( ) ;
2014-05-30 12:53:19 +04:00
}
2019-11-14 10:13:17 +03:00
auto key = _sessionData - > getKey ( ) ;
if ( ! key | | key - > keyId ( ) ! = _keyId ) {
2017-02-25 19:44:02 +03:00
DEBUG_LOG ( ( " MTP Error: auth_key id for dc %1 changed " ) . arg ( _shiftedDcId ) ) ;
2017-02-27 12:51:03 +03:00
return restartOnError ( ) ;
2014-05-30 12:53:19 +04:00
}
2018-04-24 23:09:20 +04:00
while ( ! _connection - > received ( ) . empty ( ) ) {
auto intsBuffer = std : : move ( _connection - > received ( ) . front ( ) ) ;
_connection - > received ( ) . pop_front ( ) ;
2015-08-08 12:14:47 +03:00
2017-02-27 12:51:03 +03:00
constexpr auto kExternalHeaderIntsCount = 6U ; // 2 auth_key_id, 4 msg_key
constexpr auto kEncryptedHeaderIntsCount = 8U ; // 2 salt, 2 session, 2 msg_id, 1 seq_no, 1 length
constexpr auto kMinimalEncryptedIntsCount = kEncryptedHeaderIntsCount + 4U ; // + 1 data + 3 padding
constexpr auto kMinimalIntsCount = kExternalHeaderIntsCount + kMinimalEncryptedIntsCount ;
auto intsCount = uint32 ( intsBuffer . size ( ) ) ;
auto ints = intsBuffer . constData ( ) ;
2016-12-31 12:58:56 +04:00
if ( ( intsCount < kMinimalIntsCount ) | | ( intsCount > kMaxMessageLength / kIntSize ) ) {
2017-02-27 12:51:03 +03:00
LOG ( ( " TCP Error: bad message received, len %1 " ) . arg ( intsCount * kIntSize ) ) ;
TCP_LOG ( ( " TCP Error: bad message %1 " ) . arg ( Logs : : mb ( ints , intsCount * kIntSize ) . str ( ) ) ) ;
return restartOnError ( ) ;
2014-05-30 12:53:19 +04:00
}
2019-11-14 10:13:17 +03:00
if ( _keyId ! = * ( uint64 * ) ints ) {
LOG ( ( " TCP Error: bad auth_key_id %1 instead of %2 received " ) . arg ( _keyId ) . arg ( * ( uint64 * ) ints ) ) ;
2017-02-27 12:51:03 +03:00
TCP_LOG ( ( " TCP Error: bad message %1 " ) . arg ( Logs : : mb ( ints , intsCount * kIntSize ) . str ( ) ) ) ;
2015-08-08 12:14:47 +03:00
2017-02-27 12:51:03 +03:00
return restartOnError ( ) ;
2014-05-30 12:53:19 +04:00
}
2017-02-27 12:51:03 +03:00
auto encryptedInts = ints + kExternalHeaderIntsCount ;
2018-06-25 22:18:27 +01:00
auto encryptedIntsCount = ( intsCount - kExternalHeaderIntsCount ) & ~ 0x03U ;
2017-02-27 12:51:03 +03:00
auto encryptedBytesCount = encryptedIntsCount * kIntSize ;
auto decryptedBuffer = QByteArray ( encryptedBytesCount , Qt : : Uninitialized ) ;
auto msgKey = * ( MTPint128 * ) ( ints + 2 ) ;
2016-01-11 23:43:29 +08:00
2016-12-31 12:58:56 +04:00
# ifdef TDESKTOP_MTPROTO_OLD
aesIgeDecrypt_oldmtp ( encryptedInts , decryptedBuffer . data ( ) , encryptedBytesCount , key , msgKey ) ;
# else // TDESKTOP_MTPROTO_OLD
2017-02-27 12:51:03 +03:00
aesIgeDecrypt ( encryptedInts , decryptedBuffer . data ( ) , encryptedBytesCount , key , msgKey ) ;
2016-12-31 12:58:56 +04:00
# endif // TDESKTOP_MTPROTO_OLD
2014-05-30 12:53:19 +04:00
2017-02-27 12:51:03 +03:00
auto decryptedInts = reinterpret_cast < const mtpPrime * > ( decryptedBuffer . constData ( ) ) ;
auto serverSalt = * ( uint64 * ) & decryptedInts [ 0 ] ;
auto session = * ( uint64 * ) & decryptedInts [ 2 ] ;
auto msgId = * ( uint64 * ) & decryptedInts [ 4 ] ;
auto seqNo = * ( uint32 * ) & decryptedInts [ 6 ] ;
auto needAck = ( ( seqNo & 0x01 ) ! = 0 ) ;
2014-05-30 12:53:19 +04:00
2017-02-27 12:51:03 +03:00
auto messageLength = * ( uint32 * ) & decryptedInts [ 7 ] ;
2016-12-31 12:58:56 +04:00
if ( messageLength > kMaxMessageLength ) {
LOG ( ( " TCP Error: bad messageLength %1 " ) . arg ( messageLength ) ) ;
TCP_LOG ( ( " TCP Error: bad message %1 " ) . arg ( Logs : : mb ( ints , intsCount * kIntSize ) . str ( ) ) ) ;
return restartOnError ( ) ;
}
2017-02-27 12:51:03 +03:00
auto fullDataLength = kEncryptedHeaderIntsCount * kIntSize + messageLength ; // Without padding.
2015-08-08 12:14:47 +03:00
2016-12-31 12:58:56 +04:00
// Can underflow, but it is an unsigned type, so we just check the range later.
auto paddingSize = static_cast < uint32 > ( encryptedBytesCount ) - static_cast < uint32 > ( fullDataLength ) ;
# ifdef TDESKTOP_MTPROTO_OLD
constexpr auto kMinPaddingSize_oldmtp = 0U ;
constexpr auto kMaxPaddingSize_oldmtp = 15U ;
auto badMessageLength = ( /*paddingSize < kMinPaddingSize_oldmtp || */ paddingSize > kMaxPaddingSize_oldmtp ) ;
2017-02-27 12:51:03 +03:00
auto hashedDataLength = badMessageLength ? encryptedBytesCount : fullDataLength ;
auto sha1ForMsgKeyCheck = hashSha1 ( decryptedInts , hashedDataLength ) ;
2016-12-31 12:58:56 +04:00
constexpr auto kMsgKeyShift_oldmtp = 4U ;
if ( memcmp ( & msgKey , sha1ForMsgKeyCheck . data ( ) + kMsgKeyShift_oldmtp , sizeof ( msgKey ) ) ! = 0 ) {
2017-02-27 12:51:03 +03:00
LOG ( ( " TCP Error: bad SHA1 hash after aesDecrypt in message. " ) ) ;
TCP_LOG ( ( " TCP Error: bad message %1 " ) . arg ( Logs : : mb ( encryptedInts , encryptedBytesCount ) . str ( ) ) ) ;
return restartOnError ( ) ;
2014-05-30 12:53:19 +04:00
}
2016-12-31 12:58:56 +04:00
# else // TDESKTOP_MTPROTO_OLD
constexpr auto kMinPaddingSize = 12U ;
constexpr auto kMaxPaddingSize = 1024U ;
auto badMessageLength = ( paddingSize < kMinPaddingSize | | paddingSize > kMaxPaddingSize ) ;
std : : array < uchar , 32 > sha256Buffer = { { 0 } } ;
SHA256_CTX msgKeyLargeContext ;
SHA256_Init ( & msgKeyLargeContext ) ;
SHA256_Update ( & msgKeyLargeContext , key - > partForMsgKey ( false ) , 32 ) ;
SHA256_Update ( & msgKeyLargeContext , decryptedInts , encryptedBytesCount ) ;
SHA256_Final ( sha256Buffer . data ( ) , & msgKeyLargeContext ) ;
constexpr auto kMsgKeyShift = 8U ;
if ( memcmp ( & msgKey , sha256Buffer . data ( ) + kMsgKeyShift , sizeof ( msgKey ) ) ! = 0 ) {
LOG ( ( " TCP Error: bad SHA256 hash after aesDecrypt in message " ) ) ;
TCP_LOG ( ( " TCP Error: bad message %1 " ) . arg ( Logs : : mb ( encryptedInts , encryptedBytesCount ) . str ( ) ) ) ;
return restartOnError ( ) ;
}
# endif // TDESKTOP_MTPROTO_OLD
2017-02-27 12:51:03 +03:00
if ( badMessageLength | | ( messageLength & 0x03 ) ) {
LOG ( ( " TCP Error: bad msg_len received %1, data size: %2 " ) . arg ( messageLength ) . arg ( encryptedBytesCount ) ) ;
TCP_LOG ( ( " TCP Error: bad message %1 " ) . arg ( Logs : : mb ( encryptedInts , encryptedBytesCount ) . str ( ) ) ) ;
2015-08-08 12:14:47 +03:00
2017-02-27 12:51:03 +03:00
return restartOnError ( ) ;
2014-05-30 12:53:19 +04:00
}
2017-02-27 12:51:03 +03:00
TCP_LOG ( ( " TCP Info: decrypted message %1,%2,%3 is %4 len " ) . arg ( msgId ) . arg ( seqNo ) . arg ( Logs : : b ( needAck ) ) . arg ( fullDataLength ) ) ;
2014-05-30 12:53:19 +04:00
2019-11-14 10:13:17 +03:00
uint64 serverSession = _sessionData - > getSessionId ( ) ;
2014-05-30 12:53:19 +04:00
if ( session ! = serverSession ) {
LOG ( ( " MTP Error: bad server session received " ) ) ;
TCP_LOG ( ( " MTP Error: bad server session %1 instead of %2 in message received " ) . arg ( session ) . arg ( serverSession ) ) ;
2015-08-08 12:14:47 +03:00
2017-02-27 12:51:03 +03:00
return restartOnError ( ) ;
2014-05-30 12:53:19 +04:00
}
2019-07-10 19:28:33 +02:00
const auto serverTime = int32 ( msgId > > 32 ) ;
const auto clientTime = base : : unixtime : : now ( ) ;
const auto isReply = ( ( msgId & 0x03 ) = = 1 ) ;
2014-05-30 12:53:19 +04:00
if ( ! isReply & & ( ( msgId & 0x03 ) ! = 3 ) ) {
LOG ( ( " MTP Error: bad msg_id %1 in message received " ) . arg ( msgId ) ) ;
2015-08-08 12:14:47 +03:00
2017-02-27 12:51:03 +03:00
return restartOnError ( ) ;
2014-05-30 12:53:19 +04:00
}
bool badTime = false ;
2019-11-14 10:13:17 +03:00
uint64 mySalt = _sessionData - > getSalt ( ) ;
2014-05-30 12:53:19 +04:00
if ( serverTime > clientTime + 60 | | serverTime + 300 < clientTime ) {
DEBUG_LOG ( ( " MTP Info: bad server time from msg_id: %1, my time: %2 " ) . arg ( serverTime ) . arg ( clientTime ) ) ;
badTime = true ;
}
2016-03-24 11:57:11 +03:00
bool wasConnected = ( getState ( ) = = ConnectedState ) ;
2014-05-30 12:53:19 +04:00
if ( serverSalt ! = mySalt ) {
if ( ! badTime ) {
2016-03-24 18:07:13 +03:00
DEBUG_LOG ( ( " MTP Info: other salt received... received: %1, my salt: %2, updating... " ) . arg ( serverSalt ) . arg ( mySalt ) ) ;
2019-11-14 10:13:17 +03:00
_sessionData - > setSalt ( serverSalt ) ;
2016-03-24 11:57:11 +03:00
if ( setState ( ConnectedState , ConnectingState ) ) { // only connected
2019-11-14 10:13:17 +03:00
if ( _restarted ) {
2014-11-25 15:15:29 +03:00
emit resendAllAsync ( ) ;
2019-11-14 10:13:17 +03:00
_restarted = false ;
2014-05-30 12:53:19 +04:00
}
}
} else {
2016-03-24 18:07:13 +03:00
DEBUG_LOG ( ( " MTP Info: other salt received... received: %1, my salt: %2 " ) . arg ( serverSalt ) . arg ( mySalt ) ) ;
2014-05-30 12:53:19 +04:00
}
} else {
serverSalt = 0 ; // dont pass to handle method, so not to lock in setSalt()
}
2019-11-14 10:13:17 +03:00
if ( needAck ) _ackRequestData . push_back ( MTP_long ( msgId ) ) ;
2014-05-30 12:53:19 +04:00
2016-12-07 16:32:25 +03:00
auto res = HandleResult : : Success ; // if no need to handle, then succeed
2017-02-27 12:51:03 +03:00
auto from = decryptedInts + kEncryptedHeaderIntsCount ;
auto end = from + ( messageLength / kIntSize ) ;
auto sfrom = decryptedInts + 4U ; // msg_id + seq_no + length + message
2017-02-25 19:44:02 +03:00
MTP_LOG ( _shiftedDcId , ( " Recv: " ) + mtpTextSerialize ( sfrom , end ) ) ;
2014-05-30 12:53:19 +04:00
bool needToHandle = false ;
{
2019-11-14 10:13:17 +03:00
QWriteLocker lock ( _sessionData - > receivedIdsMutex ( ) ) ;
needToHandle = _sessionData - > receivedIdsSet ( ) . registerMsgId ( msgId , needAck ) ;
2014-05-30 12:53:19 +04:00
}
if ( needToHandle ) {
res = handleOneReceived ( from , end , msgId , serverTime , serverSalt , badTime ) ;
}
{
2019-11-14 10:13:17 +03:00
QWriteLocker lock ( _sessionData - > receivedIdsMutex ( ) ) ;
_sessionData - > receivedIdsSet ( ) . shrink ( ) ;
2014-05-30 12:53:19 +04:00
}
// send acks
2019-11-14 10:13:17 +03:00
uint32 toAckSize = _ackRequestData . size ( ) ;
2014-05-30 12:53:19 +04:00
if ( toAckSize ) {
2019-11-14 10:13:17 +03:00
DEBUG_LOG ( ( " MTP Info: will send %1 acks, ids: %2 " ) . arg ( toAckSize ) . arg ( LogIdsVector ( _ackRequestData ) ) ) ;
2019-01-21 17:42:21 +04:00
emit sendAnythingAsync ( kAckSendWaiting ) ;
2014-05-30 12:53:19 +04:00
}
bool emitSignal = false ;
{
2019-11-14 10:13:17 +03:00
QReadLocker locker ( _sessionData - > haveReceivedMutex ( ) ) ;
emitSignal = ! _sessionData - > haveReceivedResponses ( ) . isEmpty ( ) | | ! _sessionData - > haveReceivedUpdates ( ) . isEmpty ( ) ;
2014-05-30 12:53:19 +04:00
if ( emitSignal ) {
2019-11-14 10:13:17 +03:00
DEBUG_LOG ( ( " MTP Info: emitting needToReceive() - need to parse in another thread, %1 responses, %2 updates. " ) . arg ( _sessionData - > haveReceivedResponses ( ) . size ( ) ) . arg ( _sessionData - > haveReceivedUpdates ( ) . size ( ) ) ) ;
2014-05-30 12:53:19 +04:00
}
}
2016-01-11 23:43:29 +08:00
2014-05-30 12:53:19 +04:00
if ( emitSignal ) {
emit needToReceive ( ) ;
}
2016-12-07 16:32:25 +03:00
if ( res ! = HandleResult : : Success & & res ! = HandleResult : : Ignored ) {
_needSessionReset = ( res = = HandleResult : : ResetSession ) ;
2015-08-08 12:14:47 +03:00
2017-02-27 12:51:03 +03:00
return restartOnError ( ) ;
2014-05-30 12:53:19 +04:00
}
2018-04-24 23:09:20 +04:00
_retryTimeout = 1 ; // reset restart() timer
2014-05-30 12:53:19 +04:00
2019-11-14 10:13:17 +03:00
if ( ! _sessionData - > isCheckedKey ( ) ) {
2014-05-30 12:53:19 +04:00
DEBUG_LOG ( ( " MTP Info: marked auth key as checked " ) ) ;
2019-11-14 10:13:17 +03:00
_sessionData - > setCheckedKey ( true ) ;
2014-05-30 12:53:19 +04:00
}
2019-02-19 10:57:53 +04:00
_startedConnectingAt = crl : : time ( 0 ) ;
2014-05-30 12:53:19 +04:00
if ( ! wasConnected ) {
2016-03-24 11:57:11 +03:00
if ( getState ( ) = = ConnectedState ) {
2014-11-22 12:45:04 +03:00
emit needToSendAsync ( ) ;
2014-05-30 12:53:19 +04:00
}
}
}
2018-04-24 23:09:20 +04:00
if ( _connection - > needHttpWait ( ) ) {
2014-11-25 15:15:29 +03:00
emit sendHttpWaitAsync ( ) ;
2014-05-30 12:53:19 +04:00
}
}
2016-12-07 16:32:25 +03:00
ConnectionPrivate : : HandleResult ConnectionPrivate : : handleOneReceived ( const mtpPrime * from , const mtpPrime * end , uint64 msgId , int32 serverTime , uint64 serverSalt , bool badTime ) {
2019-07-19 17:39:36 +02:00
const auto cons = mtpTypeId ( * from ) ;
2014-05-30 12:53:19 +04:00
switch ( cons ) {
case mtpc_gzip_packed : {
DEBUG_LOG ( ( " Message Info: gzip container " ) ) ;
mtpBuffer response = ungzip ( + + from , end ) ;
2019-01-17 11:17:44 +04:00
if ( response . empty ( ) ) {
2016-12-07 16:32:25 +03:00
return HandleResult : : RestartConnection ;
2014-05-30 12:53:19 +04:00
}
return handleOneReceived ( response . data ( ) , response . data ( ) + response . size ( ) , msgId , serverTime , serverSalt , badTime ) ;
}
case mtpc_msg_container : {
2019-07-18 16:06:38 +02:00
if ( + + from > = end ) {
return HandleResult : : ParseError ;
}
2014-05-30 12:53:19 +04:00
const mtpPrime * otherEnd ;
2019-07-18 16:06:38 +02:00
const auto msgsCount = ( uint32 ) * ( from + + ) ;
2014-05-30 12:53:19 +04:00
DEBUG_LOG ( ( " Message Info: container received, count: %1 " ) . arg ( msgsCount ) ) ;
for ( uint32 i = 0 ; i < msgsCount ; + + i ) {
2019-07-18 16:06:38 +02:00
if ( from + 4 > = end ) {
return HandleResult : : ParseError ;
}
2014-05-30 12:53:19 +04:00
otherEnd = from + 4 ;
2017-03-09 22:15:31 +03:00
MTPlong inMsgId ;
2019-07-18 16:06:38 +02:00
if ( ! inMsgId . read ( from , otherEnd ) ) {
return HandleResult : : ParseError ;
}
2014-05-30 12:53:19 +04:00
bool isReply = ( ( inMsgId . v & 0x03 ) = = 1 ) ;
if ( ! isReply & & ( ( inMsgId . v & 0x03 ) ! = 3 ) ) {
LOG ( ( " Message Error: bad msg_id %1 in contained message received " ) . arg ( inMsgId . v ) ) ;
2016-12-07 16:32:25 +03:00
return HandleResult : : RestartConnection ;
2014-05-30 12:53:19 +04:00
}
2017-03-09 22:15:31 +03:00
MTPint inSeqNo ;
2019-07-18 16:06:38 +02:00
if ( ! inSeqNo . read ( from , otherEnd ) ) {
return HandleResult : : ParseError ;
}
2017-03-09 22:15:31 +03:00
MTPint bytes ;
2019-07-18 16:06:38 +02:00
if ( ! bytes . read ( from , otherEnd ) ) {
return HandleResult : : ParseError ;
}
2014-05-30 12:53:19 +04:00
if ( ( bytes . v & 0x03 ) | | bytes . v < 4 ) {
LOG ( ( " Message Error: bad length %1 of contained message received " ) . arg ( bytes . v ) ) ;
2016-12-07 16:32:25 +03:00
return HandleResult : : RestartConnection ;
2014-05-30 12:53:19 +04:00
}
bool needAck = ( inSeqNo . v & 0x01 ) ;
2019-11-14 10:13:17 +03:00
if ( needAck ) _ackRequestData . push_back ( inMsgId ) ;
2014-05-30 12:53:19 +04:00
2016-01-11 23:43:29 +08:00
DEBUG_LOG ( ( " Message Info: message from container, msg_id: %1, needAck: %2 " ) . arg ( inMsgId . v ) . arg ( Logs : : b ( needAck ) ) ) ;
2014-05-30 12:53:19 +04:00
otherEnd = from + ( bytes . v > > 2 ) ;
2019-07-18 16:06:38 +02:00
if ( otherEnd > end ) {
return HandleResult : : ParseError ;
}
2014-05-30 12:53:19 +04:00
bool needToHandle = false ;
{
2019-11-14 10:13:17 +03:00
QWriteLocker lock ( _sessionData - > receivedIdsMutex ( ) ) ;
needToHandle = _sessionData - > receivedIdsSet ( ) . registerMsgId ( inMsgId . v , needAck ) ;
2014-05-30 12:53:19 +04:00
}
2016-12-07 16:32:25 +03:00
auto res = HandleResult : : Success ; // if no need to handle, then succeed
2014-05-30 12:53:19 +04:00
if ( needToHandle ) {
res = handleOneReceived ( from , otherEnd , inMsgId . v , serverTime , serverSalt , badTime ) ;
badTime = false ;
}
2016-12-07 16:32:25 +03:00
if ( res ! = HandleResult : : Success ) {
2014-05-30 12:53:19 +04:00
return res ;
}
from = otherEnd ;
}
2016-12-07 16:32:25 +03:00
} return HandleResult : : Success ;
2014-05-30 12:53:19 +04:00
case mtpc_msgs_ack : {
2017-03-09 22:15:31 +03:00
MTPMsgsAck msg ;
2019-07-18 16:06:38 +02:00
if ( ! msg . read ( from , end ) ) {
return HandleResult : : ParseError ;
}
2019-07-05 15:38:38 +02:00
auto & ids = msg . c_msgs_ack ( ) . vmsg_ids ( ) . v ;
2014-05-30 12:53:19 +04:00
uint32 idsCount = ids . size ( ) ;
2017-12-11 18:45:29 +04:00
DEBUG_LOG ( ( " Message Info: acks received, ids: %1 " ) . arg ( LogIdsVector ( ids ) ) ) ;
2016-12-07 16:32:25 +03:00
if ( ! idsCount ) return ( badTime ? HandleResult : : Ignored : HandleResult : : Success ) ;
2014-05-30 12:53:19 +04:00
if ( badTime ) {
if ( requestsFixTimeSalt ( ids , serverTime , serverSalt ) ) {
badTime = false ;
} else {
2016-12-07 16:32:25 +03:00
return HandleResult : : Ignored ;
2014-05-30 12:53:19 +04:00
}
}
requestsAcked ( ids ) ;
2016-12-07 16:32:25 +03:00
} return HandleResult : : Success ;
2014-05-30 12:53:19 +04:00
case mtpc_bad_msg_notification : {
2017-03-09 22:15:31 +03:00
MTPBadMsgNotification msg ;
2019-07-18 16:06:38 +02:00
if ( ! msg . read ( from , end ) ) {
return HandleResult : : ParseError ;
}
2016-04-08 14:44:35 +04:00
const auto & data ( msg . c_bad_msg_notification ( ) ) ;
2019-07-05 15:38:38 +02:00
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 ) ) ;
2014-05-30 12:53:19 +04:00
2019-07-05 15:38:38 +02:00
mtpMsgId resendId = data . vbad_msg_id ( ) . v ;
2015-03-12 13:28:10 +03:00
if ( resendId = = _pingMsgId ) {
_pingId = 0 ;
}
2019-07-05 15:38:38 +02:00
int32 errorCode = data . verror_code ( ) . v ;
2018-01-02 16:44:12 +03:00
if ( false
| | errorCode = = 16
| | errorCode = = 17
| | errorCode = = 32
| | errorCode = = 33
| | errorCode = = 64 ) { // can handle
const auto needResend = false
| | ( errorCode = = 16 ) // bad msg_id
| | ( errorCode = = 17 ) // bad msg_id
| | ( errorCode = = 64 ) ; // bad container
2014-08-01 15:09:46 +04:00
if ( errorCode = = 64 ) { // bad container!
2018-06-05 16:32:26 +03:00
if ( Logs : : DebugEnabled ( ) ) {
2018-06-25 19:55:27 +01:00
SecureRequest request ;
2014-08-01 15:09:46 +04:00
{
2019-11-14 10:13:17 +03:00
QWriteLocker locker ( _sessionData - > haveSentMutex ( ) ) ;
auto & haveSent = _sessionData - > haveSentMap ( ) ;
2014-08-01 15:09:46 +04:00
2018-06-25 19:55:27 +01:00
const auto i = haveSent . constFind ( resendId ) ;
2014-11-05 20:43:32 +03:00
if ( i = = haveSent . cend ( ) ) {
2014-08-01 15:09:46 +04:00
LOG ( ( " Message Error: Container not found! " ) ) ;
2014-11-05 20:43:32 +03:00
} else {
request = i . value ( ) ;
2014-08-01 15:09:46 +04:00
}
}
if ( request ) {
2018-06-25 19:55:27 +01:00
if ( request . isSentContainer ( ) ) {
2014-08-01 15:09:46 +04:00
QStringList lst ;
2018-06-25 19:55:27 +01:00
const auto ids = ( const mtpMsgId * ) ( request - > constData ( ) + 8 ) ;
2014-08-01 15:09:46 +04:00
for ( uint32 i = 0 , l = ( request - > size ( ) - 8 ) > > 1 ; i < l ; + + i ) {
lst . push_back ( QString : : number ( ids [ i ] ) ) ;
}
LOG ( ( " Message Info: bad container received! messages: %1 " ) . arg ( lst . join ( ' , ' ) ) ) ;
} else {
LOG ( ( " Message Error: bad container received, but request is not a container! " ) ) ;
}
}
}
}
2014-05-30 12:53:19 +04:00
2014-08-01 15:09:46 +04:00
if ( ! wasSent ( resendId ) ) {
2018-01-02 16:44:12 +03:00
DEBUG_LOG ( ( " Message Error: "
" such message was not sent recently %1 " ) . arg ( resendId ) ) ;
return badTime
? HandleResult : : Ignored
: HandleResult : : Success ;
2014-08-01 15:09:46 +04:00
}
2014-05-30 12:53:19 +04:00
2018-01-02 16:44:12 +03:00
if ( needResend ) { // bad msg_id or bad container
2019-11-14 10:13:17 +03:00
if ( serverSalt ) _sessionData - > setSalt ( serverSalt ) ;
2019-07-10 19:28:33 +02:00
base : : unixtime : : update ( serverTime , true ) ;
2014-08-01 15:09:46 +04:00
2016-03-24 18:07:13 +03:00
DEBUG_LOG ( ( " Message Info: unixtime updated, now %1, resending in container... " ) . arg ( serverTime ) ) ;
2014-08-01 15:09:46 +04:00
resend ( resendId , 0 , true ) ;
} else { // must create new session, because msg_id and msg_seqno are inconsistent
if ( badTime ) {
2019-11-14 10:13:17 +03:00
if ( serverSalt ) _sessionData - > setSalt ( serverSalt ) ;
2019-07-10 19:28:33 +02:00
base : : unixtime : : update ( serverTime , true ) ;
2014-08-01 15:09:46 +04:00
badTime = false ;
}
2019-07-05 15:38:38 +02:00
LOG ( ( " Message Info: bad message notification received, msgId %1, error_code %2 " ) . arg ( data . vbad_msg_id ( ) . v ) . arg ( errorCode ) ) ;
2016-12-07 16:32:25 +03:00
return HandleResult : : ResetSession ;
2014-05-30 12:53:19 +04:00
}
2014-08-01 15:09:46 +04:00
} else { // fatal (except 48, but it must not get here)
2019-07-05 15:38:38 +02:00
const auto badMsgId = mtpMsgId ( data . vbad_msg_id ( ) . v ) ;
2018-01-02 16:44:12 +03:00
const auto requestId = wasSent ( resendId ) ;
2014-08-01 15:09:46 +04:00
if ( requestId ) {
2018-01-02 16:44:12 +03:00
LOG ( ( " Message Error: "
" bad message notification received, "
" msgId %1, error_code %2, fatal: clearing callbacks "
) . arg ( badMsgId
) . arg ( errorCode
) ) ;
_instance - > clearCallbacksDelayed ( { 1 , RPCCallbackClear (
requestId ,
- errorCode ) } ) ;
2014-08-01 15:09:46 +04:00
} else {
2018-01-02 16:44:12 +03:00
DEBUG_LOG ( ( " Message Error: "
" such message was not sent recently %1 " ) . arg ( badMsgId ) ) ;
2014-08-01 15:09:46 +04:00
}
2018-01-02 16:44:12 +03:00
return badTime
? HandleResult : : Ignored
: HandleResult : : Success ;
2014-05-30 12:53:19 +04:00
}
2016-12-07 16:32:25 +03:00
} return HandleResult : : Success ;
2014-05-30 12:53:19 +04:00
case mtpc_bad_server_salt : {
2017-03-09 22:15:31 +03:00
MTPBadMsgNotification msg ;
2019-07-18 16:06:38 +02:00
if ( ! msg . read ( from , end ) ) {
return HandleResult : : ParseError ;
}
2016-04-08 14:44:35 +04:00
const auto & data ( msg . c_bad_server_salt ( ) ) ;
2019-07-05 15:38:38 +02:00
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 ) ) ;
2014-05-30 12:53:19 +04:00
2019-07-05 15:38:38 +02:00
mtpMsgId resendId = data . vbad_msg_id ( ) . v ;
2015-03-12 13:28:10 +03:00
if ( resendId = = _pingMsgId ) {
_pingId = 0 ;
} else if ( ! wasSent ( resendId ) ) {
2014-05-30 12:53:19 +04:00
DEBUG_LOG ( ( " Message Error: such message was not sent recently %1 " ) . arg ( resendId ) ) ;
2016-12-07 16:32:25 +03:00
return ( badTime ? HandleResult : : Ignored : HandleResult : : Success ) ;
2014-05-30 12:53:19 +04:00
}
2019-07-05 15:38:38 +02:00
uint64 serverSalt = data . vnew_server_salt ( ) . v ;
2019-11-14 10:13:17 +03:00
_sessionData - > setSalt ( serverSalt ) ;
2019-07-10 19:28:33 +02:00
base : : unixtime : : update ( serverTime ) ;
2014-05-30 12:53:19 +04:00
2016-03-24 11:57:11 +03:00
if ( setState ( ConnectedState , ConnectingState ) ) { // maybe only connected
2019-11-14 10:13:17 +03:00
if ( _restarted ) {
2014-11-25 15:15:29 +03:00
emit resendAllAsync ( ) ;
2019-11-14 10:13:17 +03:00
_restarted = false ;
2014-05-30 12:53:19 +04:00
}
}
badTime = false ;
2016-03-24 18:07:13 +03:00
DEBUG_LOG ( ( " Message Info: unixtime updated, now %1, server_salt updated, now %2, resending... " ) . arg ( serverTime ) . arg ( serverSalt ) ) ;
2014-05-30 12:53:19 +04:00
resend ( resendId ) ;
2016-12-07 16:32:25 +03:00
} return HandleResult : : Success ;
2014-05-30 12:53:19 +04:00
case mtpc_msgs_state_req : {
if ( badTime ) {
2016-03-24 18:07:13 +03:00
DEBUG_LOG ( ( " Message Info: skipping with bad time... " ) ) ;
2016-12-07 16:32:25 +03:00
return HandleResult : : Ignored ;
2014-05-30 12:53:19 +04:00
}
2017-03-09 22:15:31 +03:00
MTPMsgsStateReq msg ;
2019-07-18 16:06:38 +02:00
if ( ! msg . read ( from , end ) ) {
return HandleResult : : ParseError ;
}
2019-07-05 15:38:38 +02:00
auto & ids = msg . c_msgs_state_req ( ) . vmsg_ids ( ) . v ;
2017-03-10 22:46:28 +03:00
auto idsCount = ids . size ( ) ;
2017-12-11 18:45:29 +04:00
DEBUG_LOG ( ( " Message Info: msgs_state_req received, ids: %1 " ) . arg ( LogIdsVector ( ids ) ) ) ;
2016-12-07 16:32:25 +03:00
if ( ! idsCount ) return HandleResult : : Success ;
2014-05-30 12:53:19 +04:00
2014-11-25 15:15:29 +03:00
QByteArray info ( idsCount , Qt : : Uninitialized ) ;
2014-05-30 12:53:19 +04:00
{
2019-11-14 10:13:17 +03:00
QReadLocker lock ( _sessionData - > receivedIdsMutex ( ) ) ;
auto & receivedIds = _sessionData - > receivedIdsSet ( ) ;
2016-12-07 16:32:25 +03:00
auto minRecv = receivedIds . min ( ) ;
auto maxRecv = receivedIds . max ( ) ;
2014-05-30 12:53:19 +04:00
2019-11-14 10:13:17 +03:00
QReadLocker locker ( _sessionData - > wereAckedMutex ( ) ) ;
const auto & wereAcked = _sessionData - > wereAckedMap ( ) ;
2018-06-25 19:55:27 +01:00
const auto wereAckedEnd = wereAcked . cend ( ) ;
2014-05-30 12:53:19 +04:00
for ( uint32 i = 0 , l = idsCount ; i < l ; + + i ) {
char state = 0 ;
uint64 reqMsgId = ids [ i ] . v ;
if ( reqMsgId < minRecv ) {
state | = 0x01 ;
} else if ( reqMsgId > maxRecv ) {
state | = 0x03 ;
} else {
2016-12-07 16:32:25 +03:00
auto msgIdState = receivedIds . lookup ( reqMsgId ) ;
if ( msgIdState = = ReceivedMsgIds : : State : : NotFound ) {
2014-05-30 12:53:19 +04:00
state | = 0x02 ;
} else {
state | = 0x04 ;
if ( wereAcked . constFind ( reqMsgId ) ! = wereAckedEnd ) {
state | = 0x80 ; // we know, that server knows, that we received request
}
2016-12-07 16:32:25 +03:00
if ( msgIdState = = ReceivedMsgIds : : State : : NeedsAck ) { // need ack, so we sent ack
2014-05-30 12:53:19 +04:00
state | = 0x08 ;
} else {
state | = 0x10 ;
}
}
}
info [ i ] = state ;
}
}
2014-11-25 15:15:29 +03:00
emit sendMsgsStateInfoAsync ( msgId , info ) ;
2016-12-07 16:32:25 +03:00
} return HandleResult : : Success ;
2014-05-30 12:53:19 +04:00
case mtpc_msgs_state_info : {
2017-03-09 22:15:31 +03:00
MTPMsgsStateInfo msg ;
2019-07-18 16:06:38 +02:00
if ( ! msg . read ( from , end ) ) {
return HandleResult : : ParseError ;
}
2017-03-10 22:46:28 +03:00
auto & data = msg . c_msgs_state_info ( ) ;
2016-01-11 23:43:29 +08:00
2019-07-05 15:38:38 +02:00
auto reqMsgId = data . vreq_msg_id ( ) . v ;
auto & states = data . vinfo ( ) . v ;
2014-05-30 12:53:19 +04:00
2016-01-11 23:43:29 +08:00
DEBUG_LOG ( ( " Message Info: msg state received, msgId %1, reqMsgId: %2, HEX states %3 " ) . arg ( msgId ) . arg ( reqMsgId ) . arg ( Logs : : mb ( states . data ( ) , states . length ( ) ) . str ( ) ) ) ;
2018-06-25 19:55:27 +01:00
SecureRequest requestBuffer ;
2014-05-30 12:53:19 +04:00
{ // find this request in session-shared sent requests map
2019-11-14 10:13:17 +03:00
QReadLocker locker ( _sessionData - > haveSentMutex ( ) ) ;
const auto & haveSent = _sessionData - > haveSentMap ( ) ;
2018-06-25 19:55:27 +01:00
const auto replyTo = haveSent . constFind ( reqMsgId ) ;
2014-05-30 12:53:19 +04:00
if ( replyTo = = haveSent . cend ( ) ) { // do not look in toResend, because we do not resend msgs_state_req requests
DEBUG_LOG ( ( " Message Error: such message was not sent recently %1 " ) . arg ( reqMsgId ) ) ;
2016-12-07 16:32:25 +03:00
return ( badTime ? HandleResult : : Ignored : HandleResult : : Success ) ;
2014-05-30 12:53:19 +04:00
}
2014-10-30 19:23:44 +03:00
if ( badTime ) {
2019-11-14 10:13:17 +03:00
if ( serverSalt ) _sessionData - > setSalt ( serverSalt ) ; // requestsFixTimeSalt with no lookup
2019-07-10 19:28:33 +02:00
base : : unixtime : : update ( serverTime , true ) ;
2014-05-30 12:53:19 +04:00
2014-10-30 19:23:44 +03:00
DEBUG_LOG ( ( " Message Info: unixtime updated from mtpc_msgs_state_info, now %1 " ) . arg ( serverTime ) ) ;
2014-05-30 12:53:19 +04:00
2014-10-30 19:23:44 +03:00
badTime = false ;
}
2014-05-30 12:53:19 +04:00
requestBuffer = replyTo . value ( ) ;
}
2014-10-30 19:23:44 +03:00
QVector < MTPlong > toAckReq ( 1 , MTP_long ( reqMsgId ) ) , toAck ;
requestsAcked ( toAck , true ) ;
2014-05-30 12:53:19 +04:00
if ( requestBuffer - > size ( ) < 9 ) {
LOG ( ( " Message Error: bad request %1 found in requestMap, size: %2 " ) . arg ( reqMsgId ) . arg ( requestBuffer - > size ( ) ) ) ;
2016-12-07 16:32:25 +03:00
return HandleResult : : RestartConnection ;
2014-05-30 12:53:19 +04:00
}
2019-07-18 16:06:38 +02:00
const mtpPrime * rFrom = requestBuffer - > constData ( ) + 8 , * rEnd = requestBuffer - > constData ( ) + requestBuffer - > size ( ) ;
if ( mtpTypeId ( * rFrom ) = = mtpc_msgs_state_req ) {
MTPMsgsStateReq request ;
if ( ! request . read ( rFrom , rEnd ) ) {
LOG ( ( " Message Error: could not parse sent msgs_state_req " ) ) ;
return HandleResult : : ParseError ;
}
handleMsgsStates ( request . c_msgs_state_req ( ) . vmsg_ids ( ) . v , states , toAck ) ;
} else {
MTPMsgResendReq request ;
if ( ! request . read ( rFrom , rEnd ) ) {
LOG ( ( " Message Error: could not parse sent msgs_state_req " ) ) ;
return HandleResult : : ParseError ;
2014-08-01 15:09:46 +04:00
}
2019-07-18 16:06:38 +02:00
handleMsgsStates ( request . c_msg_resend_req ( ) . vmsg_ids ( ) . v , states , toAck ) ;
2014-05-30 12:53:19 +04:00
}
requestsAcked ( toAck ) ;
2016-12-07 16:32:25 +03:00
} return HandleResult : : Success ;
2014-05-30 12:53:19 +04:00
case mtpc_msgs_all_info : {
if ( badTime ) {
2016-03-24 18:07:13 +03:00
DEBUG_LOG ( ( " Message Info: skipping with bad time... " ) ) ;
2016-12-07 16:32:25 +03:00
return HandleResult : : Ignored ;
2014-05-30 12:53:19 +04:00
}
2017-03-09 22:15:31 +03:00
MTPMsgsAllInfo msg ;
2019-07-18 16:06:38 +02:00
if ( ! msg . read ( from , end ) ) {
return HandleResult : : ParseError ;
}
2017-03-10 22:46:28 +03:00
auto & data = msg . c_msgs_all_info ( ) ;
2019-07-05 15:38:38 +02:00
auto & ids = data . vmsg_ids ( ) . v ;
auto & states = data . vinfo ( ) . v ;
2014-05-30 12:53:19 +04:00
QVector < MTPlong > toAck ;
2017-12-11 18:45:29 +04:00
DEBUG_LOG ( ( " Message Info: msgs all info received, msgId %1, reqMsgIds: %2, states %3 " ) . arg ( msgId ) . arg ( LogIdsVector ( ids ) ) . arg ( Logs : : mb ( states . data ( ) , states . length ( ) ) . str ( ) ) ) ;
2014-05-30 12:53:19 +04:00
handleMsgsStates ( ids , states , toAck ) ;
requestsAcked ( toAck ) ;
2016-12-07 16:32:25 +03:00
} return HandleResult : : Success ;
2014-05-30 12:53:19 +04:00
case mtpc_msg_detailed_info : {
2017-03-09 22:15:31 +03:00
MTPMsgDetailedInfo msg ;
2019-07-18 16:06:38 +02:00
if ( ! msg . read ( from , end ) ) {
return HandleResult : : ParseError ;
}
2016-04-08 14:44:35 +04:00
const auto & data ( msg . c_msg_detailed_info ( ) ) ;
2014-05-30 12:53:19 +04:00
2019-07-05 15:38:38 +02:00
DEBUG_LOG ( ( " Message Info: msg detailed info, sent msgId %1, answerId %2, status %3, bytes %4 " ) . arg ( data . vmsg_id ( ) . v ) . arg ( data . vanswer_msg_id ( ) . v ) . arg ( data . vstatus ( ) . v ) . arg ( data . vbytes ( ) . v ) ) ;
2014-05-30 12:53:19 +04:00
2019-07-05 15:38:38 +02:00
QVector < MTPlong > ids ( 1 , data . vmsg_id ( ) ) ;
2014-05-30 12:53:19 +04:00
if ( badTime ) {
if ( requestsFixTimeSalt ( ids , serverTime , serverSalt ) ) {
badTime = false ;
} else {
2019-07-05 15:38:38 +02:00
DEBUG_LOG ( ( " Message Info: error, such message was not sent recently %1 " ) . arg ( data . vmsg_id ( ) . v ) ) ;
2016-12-07 16:32:25 +03:00
return HandleResult : : Ignored ;
2014-05-30 12:53:19 +04:00
}
}
requestsAcked ( ids ) ;
bool received = false ;
2019-07-05 15:38:38 +02:00
MTPlong resMsgId = data . vanswer_msg_id ( ) ;
2014-05-30 12:53:19 +04:00
{
2019-11-14 10:13:17 +03:00
QReadLocker lock ( _sessionData - > receivedIdsMutex ( ) ) ;
received = ( _sessionData - > receivedIdsSet ( ) . lookup ( resMsgId . v ) ! = ReceivedMsgIds : : State : : NotFound ) ;
2014-05-30 12:53:19 +04:00
}
2014-11-05 20:43:32 +03:00
if ( received ) {
2019-11-14 10:13:17 +03:00
_ackRequestData . push_back ( resMsgId ) ;
2014-11-05 20:43:32 +03:00
} else {
2016-03-24 18:07:13 +03:00
DEBUG_LOG ( ( " Message Info: answer message %1 was not received, requesting... " ) . arg ( resMsgId . v ) ) ;
2019-11-14 10:13:17 +03:00
_resendRequestData . push_back ( resMsgId ) ;
2014-05-30 12:53:19 +04:00
}
2016-12-07 16:32:25 +03:00
} return HandleResult : : Success ;
2014-05-30 12:53:19 +04:00
case mtpc_msg_new_detailed_info : {
if ( badTime ) {
2016-03-24 18:07:13 +03:00
DEBUG_LOG ( ( " Message Info: skipping msg_new_detailed_info with bad time... " ) ) ;
2016-12-07 16:32:25 +03:00
return HandleResult : : Ignored ;
2014-05-30 12:53:19 +04:00
}
2017-03-09 22:15:31 +03:00
MTPMsgDetailedInfo msg ;
2019-07-18 16:06:38 +02:00
if ( ! msg . read ( from , end ) ) {
return HandleResult : : ParseError ;
}
2016-04-08 14:44:35 +04:00
const auto & data ( msg . c_msg_new_detailed_info ( ) ) ;
2014-05-30 12:53:19 +04:00
2019-07-05 15:38:38 +02:00
DEBUG_LOG ( ( " Message Info: msg new detailed info, answerId %2, status %3, bytes %4 " ) . arg ( data . vanswer_msg_id ( ) . v ) . arg ( data . vstatus ( ) . v ) . arg ( data . vbytes ( ) . v ) ) ;
2014-05-30 12:53:19 +04:00
bool received = false ;
2019-07-05 15:38:38 +02:00
MTPlong resMsgId = data . vanswer_msg_id ( ) ;
2014-05-30 12:53:19 +04:00
{
2019-11-14 10:13:17 +03:00
QReadLocker lock ( _sessionData - > receivedIdsMutex ( ) ) ;
received = ( _sessionData - > receivedIdsSet ( ) . lookup ( resMsgId . v ) ! = ReceivedMsgIds : : State : : NotFound ) ;
2014-05-30 12:53:19 +04:00
}
2014-11-05 20:43:32 +03:00
if ( received ) {
2019-11-14 10:13:17 +03:00
_ackRequestData . push_back ( resMsgId ) ;
2014-11-05 20:43:32 +03:00
} else {
2016-03-24 18:07:13 +03:00
DEBUG_LOG ( ( " Message Info: answer message %1 was not received, requesting... " ) . arg ( resMsgId . v ) ) ;
2019-11-14 10:13:17 +03:00
_resendRequestData . push_back ( resMsgId ) ;
2014-05-30 12:53:19 +04:00
}
2016-12-07 16:32:25 +03:00
} return HandleResult : : Success ;
2016-01-11 23:43:29 +08:00
2014-05-30 12:53:19 +04:00
case mtpc_msg_resend_req : {
2017-03-09 22:15:31 +03:00
MTPMsgResendReq msg ;
2019-07-18 16:06:38 +02:00
if ( ! msg . read ( from , end ) ) {
return HandleResult : : ParseError ;
}
2019-07-05 15:38:38 +02:00
auto & ids = msg . c_msg_resend_req ( ) . vmsg_ids ( ) . v ;
2014-05-30 12:53:19 +04:00
2017-03-10 22:46:28 +03:00
auto idsCount = ids . size ( ) ;
2017-12-11 18:45:29 +04:00
DEBUG_LOG ( ( " Message Info: resend of msgs requested, ids: %1 " ) . arg ( LogIdsVector ( ids ) ) ) ;
2016-12-07 16:32:25 +03:00
if ( ! idsCount ) return ( badTime ? HandleResult : : Ignored : HandleResult : : Success ) ;
2014-05-30 12:53:19 +04:00
2016-04-23 14:40:42 +03:00
QVector < quint64 > toResend ( ids . size ( ) ) ;
2014-11-25 15:15:29 +03:00
for ( int32 i = 0 , l = ids . size ( ) ; i < l ; + + i ) {
toResend [ i ] = ids . at ( i ) . v ;
2014-05-30 12:53:19 +04:00
}
2014-11-25 15:15:29 +03:00
resendMany ( toResend , 0 , false , true ) ;
2016-12-07 16:32:25 +03:00
} return HandleResult : : Success ;
2014-05-30 12:53:19 +04:00
case mtpc_rpc_result : {
2019-07-18 16:06:38 +02:00
if ( from + 3 > end ) {
return HandleResult : : ParseError ;
}
2017-04-30 17:23:57 +03:00
auto response = SerializedMessage ( ) ;
2014-05-30 12:53:19 +04:00
2017-03-09 22:15:31 +03:00
MTPlong reqMsgId ;
2019-07-18 16:06:38 +02:00
if ( ! reqMsgId . read ( + + from , end ) ) {
return HandleResult : : ParseError ;
}
2014-05-30 12:53:19 +04:00
mtpTypeId typeId = from [ 0 ] ;
2016-03-24 18:07:13 +03:00
DEBUG_LOG ( ( " RPC Info: response received for %1, queueing... " ) . arg ( reqMsgId . v ) ) ;
2014-05-30 12:53:19 +04:00
QVector < MTPlong > ids ( 1 , reqMsgId ) ;
if ( badTime ) {
if ( requestsFixTimeSalt ( ids , serverTime , serverSalt ) ) {
badTime = false ;
} else {
2014-08-15 15:19:32 +04:00
DEBUG_LOG ( ( " Message Info: error, such message was not sent recently %1 " ) . arg ( reqMsgId . v ) ) ;
2016-12-07 16:32:25 +03:00
return HandleResult : : Ignored ;
2014-05-30 12:53:19 +04:00
}
}
2014-10-30 19:23:44 +03:00
requestsAcked ( ids , true ) ;
2014-05-30 12:53:19 +04:00
if ( typeId = = mtpc_gzip_packed ) {
DEBUG_LOG ( ( " RPC Info: gzip container " ) ) ;
response = ungzip ( + + from , end ) ;
2019-07-18 16:06:38 +02:00
if ( response . empty ( ) ) {
2016-12-07 16:32:25 +03:00
return HandleResult : : RestartConnection ;
2014-05-30 12:53:19 +04:00
}
typeId = response [ 0 ] ;
} else {
response . resize ( end - from ) ;
memcpy ( response . data ( ) , from , ( end - from ) * sizeof ( mtpPrime ) ) ;
}
2017-05-17 14:01:58 +03:00
if ( typeId ! = mtpc_rpc_error ) {
// An error could be some RPC_CALL_FAIL or other error inside
// the initConnection, so we're not sure yet that it was inited.
// Wait till a good response is received.
2018-05-17 22:58:00 +03:00
if ( ! _connectionOptions - > inited ) {
_connectionOptions - > inited = true ;
2019-11-14 10:13:17 +03:00
_sessionData - > notifyConnectionInited ( * _connectionOptions ) ;
2017-05-17 14:01:58 +03:00
}
2014-11-15 02:23:35 +03:00
}
2014-05-30 12:53:19 +04:00
2017-04-30 17:23:57 +03:00
auto requestId = wasSent ( reqMsgId . v ) ;
2014-06-16 13:31:10 +04:00
if ( requestId & & requestId ! = mtpRequestId ( 0xFFFFFFFF ) ) {
2017-04-30 17:23:57 +03:00
// Save rpc_result for processing in the main thread.
2019-11-14 10:13:17 +03:00
QWriteLocker locker ( _sessionData - > haveReceivedMutex ( ) ) ;
_sessionData - > haveReceivedResponses ( ) . insert ( requestId , response ) ;
2014-05-30 12:53:19 +04:00
} else {
DEBUG_LOG ( ( " RPC Info: requestId not found for msgId %1 " ) . arg ( reqMsgId . v ) ) ;
}
2016-12-07 16:32:25 +03:00
} return HandleResult : : Success ;
2014-05-30 12:53:19 +04:00
case mtpc_new_session_created : {
2015-04-23 18:50:11 +03:00
const mtpPrime * start = from ;
2017-03-09 22:15:31 +03:00
MTPNewSession msg ;
2019-07-18 16:06:38 +02:00
if ( ! msg . read ( from , end ) ) {
return HandleResult : : ParseError ;
}
2016-04-08 14:44:35 +04:00
const auto & data ( msg . c_new_session_created ( ) ) ;
2015-10-01 17:19:27 +03:00
if ( badTime ) {
2019-07-05 15:38:38 +02:00
if ( requestsFixTimeSalt ( QVector < MTPlong > ( 1 , data . vfirst_msg_id ( ) ) , serverTime , serverSalt ) ) {
2015-10-01 17:19:27 +03:00
badTime = false ;
} else {
2019-07-05 15:38:38 +02:00
DEBUG_LOG ( ( " Message Info: error, such message was not sent recently %1 " ) . arg ( data . vfirst_msg_id ( ) . v ) ) ;
2016-12-07 16:32:25 +03:00
return HandleResult : : Ignored ;
2015-10-01 17:19:27 +03:00
}
}
2019-07-05 15:38:38 +02:00
DEBUG_LOG ( ( " Message Info: new server session created, unique_id %1, first_msg_id %2, server_salt %3 " ) . arg ( data . vunique_id ( ) . v ) . arg ( data . vfirst_msg_id ( ) . v ) . arg ( data . vserver_salt ( ) . v ) ) ;
2019-11-14 10:13:17 +03:00
_sessionData - > setSalt ( data . vserver_salt ( ) . v ) ;
2014-05-30 12:53:19 +04:00
2019-07-05 15:38:38 +02:00
mtpMsgId firstMsgId = data . vfirst_msg_id ( ) . v ;
2014-11-25 15:15:29 +03:00
QVector < quint64 > toResend ;
2014-05-30 12:53:19 +04:00
{
2019-11-14 10:13:17 +03:00
QReadLocker locker ( _sessionData - > haveSentMutex ( ) ) ;
const auto & haveSent = _sessionData - > haveSentMap ( ) ;
2014-05-30 12:53:19 +04:00
toResend . reserve ( haveSent . size ( ) ) ;
2018-06-25 19:55:27 +01:00
for ( auto i = haveSent . cbegin ( ) , e = haveSent . cend ( ) ; i ! = e ; + + i ) {
2014-05-30 12:53:19 +04:00
if ( i . key ( ) > = firstMsgId ) break ;
if ( i . value ( ) - > requestId ) toResend . push_back ( i . key ( ) ) ;
}
}
2014-11-25 15:15:29 +03:00
resendMany ( toResend , 10 , true ) ;
2014-05-30 12:53:19 +04:00
2015-04-23 18:50:11 +03:00
mtpBuffer update ( from - start ) ;
if ( from > start ) memcpy ( update . data ( ) , start , ( from - start ) * sizeof ( mtpPrime ) ) ;
2016-01-11 23:43:29 +08:00
2017-04-30 17:23:57 +03:00
// Notify main process about new session - need to get difference.
2019-11-14 10:13:17 +03:00
QWriteLocker locker ( _sessionData - > haveReceivedMutex ( ) ) ;
_sessionData - > haveReceivedUpdates ( ) . push_back ( SerializedMessage ( update ) ) ;
2016-12-07 16:32:25 +03:00
} return HandleResult : : Success ;
2014-05-30 12:53:19 +04:00
case mtpc_pong : {
2017-03-09 22:15:31 +03:00
MTPPong msg ;
2019-07-18 16:06:38 +02:00
if ( ! msg . read ( from , end ) ) {
return HandleResult : : ParseError ;
}
2016-04-08 14:44:35 +04:00
const auto & data ( msg . c_pong ( ) ) ;
2019-07-05 15:38:38 +02:00
DEBUG_LOG ( ( " Message Info: pong received, msg_id: %1, ping_id: %2 " ) . arg ( data . vmsg_id ( ) . v ) . arg ( data . vping_id ( ) . v ) ) ;
2016-01-11 23:43:29 +08:00
2019-07-05 15:38:38 +02:00
if ( ! wasSent ( data . vmsg_id ( ) . v ) ) {
DEBUG_LOG ( ( " Message Error: such msg_id %1 ping_id %2 was not sent recently " ) . arg ( data . vmsg_id ( ) . v ) . arg ( data . vping_id ( ) . v ) ) ;
2016-12-07 16:32:25 +03:00
return HandleResult : : Ignored ;
2014-05-30 12:53:19 +04:00
}
2019-07-05 15:38:38 +02:00
if ( data . vping_id ( ) . v = = _pingId ) {
2015-03-12 13:28:10 +03:00
_pingId = 0 ;
2014-05-30 12:53:19 +04:00
} else {
2016-03-24 18:07:13 +03:00
DEBUG_LOG ( ( " Message Info: just pong... " ) ) ;
2014-05-30 12:53:19 +04:00
}
2019-07-05 15:38:38 +02:00
QVector < MTPlong > ids ( 1 , data . vmsg_id ( ) ) ;
2014-05-30 12:53:19 +04:00
if ( badTime ) {
if ( requestsFixTimeSalt ( ids , serverTime , serverSalt ) ) {
badTime = false ;
} else {
2016-12-07 16:32:25 +03:00
return HandleResult : : Ignored ;
2014-05-30 12:53:19 +04:00
}
}
2014-10-30 19:23:44 +03:00
requestsAcked ( ids , true ) ;
2016-12-07 16:32:25 +03:00
} return HandleResult : : Success ;
2014-05-30 12:53:19 +04:00
}
if ( badTime ) {
2015-01-23 00:59:07 +03:00
DEBUG_LOG ( ( " Message Error: bad time in updates cons, must create new session " ) ) ;
2016-12-07 16:32:25 +03:00
return HandleResult : : ResetSession ;
2014-05-30 12:53:19 +04:00
}
2017-03-23 19:11:35 +03:00
if ( _dcType = = DcType : : Regular ) {
mtpBuffer update ( end - from ) ;
if ( end > from ) memcpy ( update . data ( ) , from , ( end - from ) * sizeof ( mtpPrime ) ) ;
2016-01-11 23:43:29 +08:00
2017-04-30 17:23:57 +03:00
// Notify main process about the new updates.
2019-11-14 10:13:17 +03:00
QWriteLocker locker ( _sessionData - > haveReceivedMutex ( ) ) ;
_sessionData - > haveReceivedUpdates ( ) . push_back ( SerializedMessage ( update ) ) ;
2014-05-30 12:53:19 +04:00
2018-03-04 23:04:13 +03:00
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?
2019-04-15 13:20:07 +04:00
LOG ( ( " Message Error: unknown constructor 0x%1 " ) . arg ( cons , 0 , 16 ) ) ;
2017-03-23 19:11:35 +03:00
}
} else {
LOG ( ( " Message Error: unexpected updates in dcType: %1 " ) . arg ( static_cast < int > ( _dcType ) ) ) ;
2014-05-30 12:53:19 +04:00
}
2016-12-07 16:32:25 +03:00
return HandleResult : : Success ;
2014-05-30 12:53:19 +04:00
}
2016-03-24 11:57:11 +03:00
mtpBuffer ConnectionPrivate : : ungzip ( const mtpPrime * from , const mtpPrime * end ) const {
2019-07-18 16:06:38 +02:00
mtpBuffer result ; // * 4 because of mtpPrime type
result . resize ( 0 ) ;
2017-03-09 22:15:31 +03:00
MTPstring packed ;
2019-07-18 16:06:38 +02:00
if ( ! packed . read ( from , end ) ) { // read packed string as serialized mtp string type
LOG ( ( " RPC Error: could not read gziped bytes. " ) ) ;
return result ;
}
2017-03-10 22:46:28 +03:00
uint32 packedLen = packed . v . size ( ) , unpackedChunk = packedLen , unpackedLen = 0 ;
2014-05-30 12:53:19 +04:00
z_stream stream ;
stream . zalloc = 0 ;
stream . zfree = 0 ;
stream . opaque = 0 ;
stream . avail_in = 0 ;
stream . next_in = 0 ;
int res = inflateInit2 ( & stream , 16 + MAX_WBITS ) ;
if ( res ! = Z_OK ) {
LOG ( ( " RPC Error: could not init zlib stream, code: %1 " ) . arg ( res ) ) ;
return result ;
}
stream . avail_in = packedLen ;
2017-03-10 22:46:28 +03:00
stream . next_in = reinterpret_cast < Bytef * > ( packed . v . data ( ) ) ;
2014-05-30 12:53:19 +04:00
stream . avail_out = 0 ;
while ( ! stream . avail_out ) {
result . resize ( result . size ( ) + unpackedChunk ) ;
stream . avail_out = unpackedChunk * sizeof ( mtpPrime ) ;
stream . next_out = ( Bytef * ) & result [ result . size ( ) - unpackedChunk ] ;
int res = inflate ( & stream , Z_NO_FLUSH ) ;
if ( res ! = Z_OK & & res ! = Z_STREAM_END ) {
inflateEnd ( & stream ) ;
LOG ( ( " RPC Error: could not unpack gziped data, code: %1 " ) . arg ( res ) ) ;
2017-03-11 17:13:57 +03:00
DEBUG_LOG ( ( " RPC Error: bad gzip: %1 " ) . arg ( Logs : : mb ( packed . v . constData ( ) , packedLen ) . str ( ) ) ) ;
2014-05-30 12:53:19 +04:00
return mtpBuffer ( ) ;
}
}
if ( stream . avail_out & 0x03 ) {
uint32 badSize = result . size ( ) * sizeof ( mtpPrime ) - stream . avail_out ;
LOG ( ( " RPC Error: bad length of unpacked data %1 " ) . arg ( badSize ) ) ;
2016-01-11 23:43:29 +08:00
DEBUG_LOG ( ( " RPC Error: bad unpacked data %1 " ) . arg ( Logs : : mb ( result . data ( ) , badSize ) . str ( ) ) ) ;
2014-05-30 12:53:19 +04:00
return mtpBuffer ( ) ;
}
result . resize ( result . size ( ) - ( stream . avail_out > > 2 ) ) ;
inflateEnd ( & stream ) ;
if ( ! result . size ( ) ) {
LOG ( ( " RPC Error: bad length of unpacked data 0 " ) ) ;
}
return result ;
}
2016-03-24 11:57:11 +03:00
bool ConnectionPrivate : : requestsFixTimeSalt ( const QVector < MTPlong > & ids , int32 serverTime , uint64 serverSalt ) {
2014-05-30 12:53:19 +04:00
uint32 idsCount = ids . size ( ) ;
for ( uint32 i = 0 ; i < idsCount ; + + i ) {
if ( wasSent ( ids [ i ] . v ) ) { // found such msg_id in recent acked requests or in recent sent requests
2019-11-14 10:13:17 +03:00
if ( serverSalt ) _sessionData - > setSalt ( serverSalt ) ;
2019-07-10 19:28:33 +02:00
base : : unixtime : : update ( serverTime , true ) ;
2014-05-30 12:53:19 +04:00
return true ;
}
}
return false ;
}
2016-03-24 11:57:11 +03:00
void ConnectionPrivate : : requestsAcked ( const QVector < MTPlong > & ids , bool byResponse ) {
2014-05-30 12:53:19 +04:00
uint32 idsCount = ids . size ( ) ;
2017-12-11 18:45:29 +04:00
DEBUG_LOG ( ( " Message Info: requests acked, ids %1 " ) . arg ( LogIdsVector ( ids ) ) ) ;
2014-05-30 12:53:19 +04:00
2018-01-02 16:44:12 +03:00
auto clearedBecauseTooOld = std : : vector < RPCCallbackClear > ( ) ;
2014-05-30 12:53:19 +04:00
QVector < MTPlong > toAckMore ;
{
2019-11-14 10:13:17 +03:00
QWriteLocker locker1 ( _sessionData - > wereAckedMutex ( ) ) ;
auto & wereAcked = _sessionData - > wereAckedMap ( ) ;
2014-05-30 12:53:19 +04:00
{
2019-11-14 10:13:17 +03:00
QWriteLocker locker2 ( _sessionData - > haveSentMutex ( ) ) ;
auto & haveSent = _sessionData - > haveSentMap ( ) ;
2014-05-30 12:53:19 +04:00
for ( uint32 i = 0 ; i < idsCount ; + + i ) {
mtpMsgId msgId = ids [ i ] . v ;
2018-06-25 19:55:27 +01:00
const auto req = haveSent . find ( msgId ) ;
2014-05-30 12:53:19 +04:00
if ( req ! = haveSent . cend ( ) ) {
if ( ! req . value ( ) - > msDate ) {
DEBUG_LOG ( ( " Message Info: container ack received, msgId %1 " ) . arg ( ids [ i ] . v ) ) ;
uint32 inContCount = ( ( * req ) - > size ( ) - 8 ) / 2 ;
const mtpMsgId * inContId = ( const mtpMsgId * ) ( req . value ( ) - > constData ( ) + 8 ) ;
toAckMore . reserve ( toAckMore . size ( ) + inContCount ) ;
for ( uint32 j = 0 ; j < inContCount ; + + j ) {
toAckMore . push_back ( MTP_long ( * ( inContId + + ) ) ) ;
}
2014-10-30 19:23:44 +03:00
haveSent . erase ( req ) ;
2014-05-30 12:53:19 +04:00
} else {
2014-10-30 19:23:44 +03:00
mtpRequestId reqId = req . value ( ) - > requestId ;
bool moveToAcked = byResponse ;
if ( ! moveToAcked ) { // ignore ACK, if we need a response (if we have a handler)
2017-02-24 20:15:41 +03:00
moveToAcked = ! _instance - > hasCallbacks ( reqId ) ;
2014-10-30 19:23:44 +03:00
}
if ( moveToAcked ) {
wereAcked . insert ( msgId , reqId ) ;
haveSent . erase ( req ) ;
} else {
DEBUG_LOG ( ( " Message Info: ignoring ACK for msgId %1 because request %2 requires a response " ) . arg ( msgId ) . arg ( reqId ) ) ;
}
2014-05-30 12:53:19 +04:00
}
} else {
2016-03-24 18:07:13 +03:00
DEBUG_LOG ( ( " Message Info: msgId %1 was not found in recent sent, while acking requests, searching in resend... " ) . arg ( msgId ) ) ;
2019-11-14 10:13:17 +03:00
QWriteLocker locker3 ( _sessionData - > toResendMutex ( ) ) ;
auto & toResend = _sessionData - > toResendMap ( ) ;
2018-06-25 19:55:27 +01:00
const auto reqIt = toResend . find ( msgId ) ;
2014-05-30 12:53:19 +04:00
if ( reqIt ! = toResend . cend ( ) ) {
2018-06-25 19:55:27 +01:00
const auto reqId = reqIt . value ( ) ;
2014-10-30 19:23:44 +03:00
bool moveToAcked = byResponse ;
if ( ! moveToAcked ) { // ignore ACK, if we need a response (if we have a handler)
2017-02-24 20:15:41 +03:00
moveToAcked = ! _instance - > hasCallbacks ( reqId ) ;
2014-10-30 19:23:44 +03:00
}
if ( moveToAcked ) {
2019-11-14 10:13:17 +03:00
QWriteLocker locker4 ( _sessionData - > toSendMutex ( ) ) ;
auto & toSend = _sessionData - > toSendMap ( ) ;
2018-06-25 19:55:27 +01:00
const auto req = toSend . find ( reqId ) ;
2014-10-30 19:23:44 +03:00
if ( req ! = toSend . cend ( ) ) {
wereAcked . insert ( msgId , req . value ( ) - > requestId ) ;
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 ) ) ;
} else {
DEBUG_LOG ( ( " Message Info: acked msgId %1 that was prepared to resend, requestId %2 " ) . arg ( msgId ) . arg ( reqId ) ) ;
}
toSend . erase ( req ) ;
2014-05-30 12:53:19 +04:00
} else {
2014-10-30 19:23:44 +03:00
DEBUG_LOG ( ( " Message Info: msgId %1 was found in recent resent, requestId %2 was not found in prepared to send " ) . arg ( msgId ) ) ;
2014-05-30 12:53:19 +04:00
}
2014-10-30 19:23:44 +03:00
toResend . erase ( reqIt ) ;
2014-05-30 12:53:19 +04:00
} else {
2014-10-30 19:23:44 +03:00
DEBUG_LOG ( ( " Message Info: ignoring ACK for msgId %1 because request %2 requires a response " ) . arg ( msgId ) . arg ( reqId ) ) ;
2014-05-30 12:53:19 +04:00
}
} else {
DEBUG_LOG ( ( " Message Info: msgId %1 was not found in recent resent either " ) . arg ( msgId ) ) ;
}
}
}
}
uint32 ackedCount = wereAcked . size ( ) ;
2019-01-21 17:42:21 +04:00
if ( ackedCount > kIdsBufferSize ) {
DEBUG_LOG ( ( " Message Info: removing some old acked sent msgIds %1 " ) . arg ( ackedCount - kIdsBufferSize ) ) ;
clearedBecauseTooOld . reserve ( ackedCount - kIdsBufferSize ) ;
while ( ackedCount - - > kIdsBufferSize ) {
2018-01-02 16:44:12 +03:00
auto i = wereAcked . begin ( ) ;
clearedBecauseTooOld . push_back ( RPCCallbackClear (
2018-07-18 22:21:09 +03:00
i . value ( ) ,
2017-12-18 16:40:15 +04:00
RPCError : : TimeoutError ) ) ;
2014-05-30 12:53:19 +04:00
wereAcked . erase ( i ) ;
}
}
}
2018-01-02 16:44:12 +03:00
if ( ! clearedBecauseTooOld . empty ( ) ) {
_instance - > clearCallbacksDelayed ( std : : move ( clearedBecauseTooOld ) ) ;
2014-05-30 12:53:19 +04:00
}
if ( toAckMore . size ( ) ) {
requestsAcked ( toAckMore ) ;
}
}
2017-03-10 22:46:28 +03:00
void ConnectionPrivate : : handleMsgsStates ( const QVector < MTPlong > & ids , const QByteArray & states , QVector < MTPlong > & acked ) {
2014-05-30 12:53:19 +04:00
uint32 idsCount = ids . size ( ) ;
if ( ! idsCount ) {
DEBUG_LOG ( ( " Message Info: void ids vector in handleMsgsStates() " ) ) ;
return ;
}
2017-03-10 22:46:28 +03:00
if ( states . size ( ) < idsCount ) {
LOG ( ( " Message Error: got less states than required ids count. " ) ) ;
return ;
}
2016-01-11 23:43:29 +08:00
2014-05-30 12:53:19 +04:00
acked . reserve ( acked . size ( ) + idsCount ) ;
for ( uint32 i = 0 , count = idsCount ; i < count ; + + i ) {
char state = states [ i ] ;
uint64 requestMsgId = ids [ i ] . v ;
{
2019-11-14 10:13:17 +03:00
QReadLocker locker ( _sessionData - > haveSentMutex ( ) ) ;
const auto & haveSent = _sessionData - > haveSentMap ( ) ;
2018-06-25 19:55:27 +01:00
const auto haveSentEnd = haveSent . cend ( ) ;
2014-05-30 12:53:19 +04:00
if ( haveSent . find ( requestMsgId ) = = haveSentEnd ) {
2016-03-24 18:07:13 +03:00
DEBUG_LOG ( ( " Message Info: state was received for msgId %1, but request is not found, looking in resent requests... " ) . arg ( requestMsgId ) ) ;
2019-11-14 10:13:17 +03:00
QWriteLocker locker2 ( _sessionData - > toResendMutex ( ) ) ;
auto & toResend = _sessionData - > toResendMap ( ) ;
2018-06-25 19:55:27 +01:00
const auto reqIt = toResend . find ( requestMsgId ) ;
2014-05-30 12:53:19 +04:00
if ( reqIt ! = toResend . cend ( ) ) {
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 ) ) ;
} else {
DEBUG_LOG ( ( " Message Info: state was received for msgId %1, state %2, ack, cancelling resend " ) . arg ( requestMsgId ) . arg ( ( int32 ) state ) ) ;
acked . push_back ( MTP_long ( requestMsgId ) ) ; // will remove from resend in requestsAcked
}
} else {
DEBUG_LOG ( ( " Message Info: msgId %1 was not found in recent resent either " ) . arg ( requestMsgId ) ) ;
}
continue ;
}
}
if ( ( state & 0x07 ) ! = 0x04 ) { // was received
DEBUG_LOG ( ( " Message Info: state was received for msgId %1, state %2, resending in container " ) . arg ( requestMsgId ) . arg ( ( int32 ) state ) ) ;
resend ( requestMsgId , 10 , true ) ;
} else {
DEBUG_LOG ( ( " Message Info: state was received for msgId %1, state %2, ack " ) . arg ( requestMsgId ) . arg ( ( int32 ) state ) ) ;
acked . push_back ( MTP_long ( requestMsgId ) ) ;
}
}
}
2016-12-01 22:20:33 +03:00
void ConnectionPrivate : : resend ( quint64 msgId , qint64 msCanWait , bool forceContainer , bool sendMsgStateInfo ) {
2015-03-12 13:28:10 +03:00
if ( msgId = = _pingMsgId ) return ;
2014-11-25 15:15:29 +03:00
emit resendAsync ( msgId , msCanWait , forceContainer , sendMsgStateInfo ) ;
}
2016-12-01 22:20:33 +03:00
void ConnectionPrivate : : resendMany ( QVector < quint64 > msgIds , qint64 msCanWait , bool forceContainer , bool sendMsgStateInfo ) {
2014-11-25 15:15:29 +03:00
for ( int32 i = 0 , l = msgIds . size ( ) ; i < l ; + + i ) {
2015-03-12 13:28:10 +03:00
if ( msgIds . at ( i ) = = _pingMsgId ) {
2014-11-25 15:15:29 +03:00
msgIds . remove ( i ) ;
- - l ;
}
}
emit resendManyAsync ( msgIds , msCanWait , forceContainer , sendMsgStateInfo ) ;
2014-05-30 12:53:19 +04:00
}
2018-04-24 23:09:20 +04:00
void ConnectionPrivate : : onConnected (
not_null < AbstractConnection * > connection ) {
2019-11-14 10:13:17 +03:00
QReadLocker lockFinished ( & _sessionDataMutex ) ;
if ( ! _sessionData ) return ;
2014-11-13 14:27:10 +03:00
2018-04-24 23:09:20 +04:00
disconnect ( connection , & AbstractConnection : : connected , nullptr , nullptr ) ;
if ( ! connection - > isConnected ( ) ) {
LOG ( ( " Connection Error: not connected in onConnected(), "
" state: %1 " ) . arg ( connection - > debugState ( ) ) ) ;
2015-08-08 12:14:47 +03:00
lockFinished . unlock ( ) ;
2014-05-30 12:53:19 +04:00
return restart ( ) ;
}
2018-04-24 23:09:20 +04:00
_waitForConnected = kMinConnectedTimeout ;
_waitForConnectedTimer . cancel ( ) ;
const auto i = ranges : : find (
_testConnections ,
connection . get ( ) ,
[ ] ( const TestConnection & test ) { return test . data . get ( ) ; } ) ;
Assert ( i ! = end ( _testConnections ) ) ;
const auto my = i - > priority ;
const auto j = ranges : : find_if (
_testConnections ,
[ & ] ( const TestConnection & test ) { return test . priority > my ; } ) ;
if ( j ! = end ( _testConnections ) ) {
DEBUG_LOG ( ( " MTP Info: connection %1 succeed, "
" waiting for %2. " ) . arg ( i - > data - > tag ( ) ) . arg ( j - > data - > tag ( ) ) ) ;
_waitForBetterTimer . callOnce ( kWaitForBetterTimeout ) ;
} else {
DEBUG_LOG ( ( " MTP Info: connection through IPv4 succeed. " ) ) ;
_waitForBetterTimer . cancel ( ) ;
_connection = std : : move ( i - > data ) ;
_testConnections . clear ( ) ;
2015-08-08 12:14:47 +03:00
lockFinished . unlock ( ) ;
2018-04-24 23:09:20 +04:00
updateAuthKey ( ) ;
2015-06-10 15:48:26 +03:00
}
}
2018-04-24 23:09:20 +04:00
void ConnectionPrivate : : onDisconnected (
not_null < AbstractConnection * > connection ) {
removeTestConnection ( connection ) ;
2015-06-10 15:48:26 +03:00
2018-04-24 23:09:20 +04:00
if ( _testConnections . empty ( ) ) {
2018-05-17 22:58:00 +03:00
destroyAllConnections ( ) ;
restart ( ) ;
2015-06-10 15:48:26 +03:00
} else {
2018-04-24 23:09:20 +04:00
confirmBestConnection ( ) ;
2015-06-10 15:48:26 +03:00
}
}
2018-04-24 23:09:20 +04:00
void ConnectionPrivate : : confirmBestConnection ( ) {
if ( _waitForBetterTimer . isActive ( ) ) {
return ;
2015-06-10 15:48:26 +03:00
}
2018-04-24 23:09:20 +04:00
const auto i = ranges : : max_element (
_testConnections ,
std : : less < > ( ) ,
[ ] ( const TestConnection & test ) {
return test . data - > isConnected ( ) ? test . priority : - 1 ;
} ) ;
Assert ( i ! = end ( _testConnections ) ) ;
if ( ! i - > data - > isConnected ( ) ) {
return ;
}
DEBUG_LOG ( ( " MTP Info: can't connect through better, using %1. "
) . arg ( i - > data - > tag ( ) ) ) ;
_connection = std : : move ( i - > data ) ;
_testConnections . clear ( ) ;
updateAuthKey ( ) ;
}
void ConnectionPrivate : : removeTestConnection (
not_null < AbstractConnection * > connection ) {
_testConnections . erase (
ranges : : remove (
_testConnections ,
connection . get ( ) ,
[ ] ( const TestConnection & test ) { return test . data . get ( ) ; } ) ,
end ( _testConnections ) ) ;
2015-06-10 15:48:26 +03:00
}
2019-11-13 17:12:04 +03:00
void ConnectionPrivate : : updateAuthKey ( ) {
2019-11-14 10:13:17 +03:00
QReadLocker lockFinished ( & _sessionDataMutex ) ;
if ( ! _sessionData | | ! _connection ) {
return ;
}
2015-05-14 19:50:04 +03:00
2017-02-25 19:44:02 +03:00
DEBUG_LOG ( ( " AuthKey Info: Connection updating key from Session, dc %1 " ) . arg ( _shiftedDcId ) ) ;
2015-05-14 19:50:04 +03:00
uint64 newKeyId = 0 ;
{
2019-11-14 10:13:17 +03:00
ReadLockerAttempt lock ( _sessionData - > keyMutex ( ) ) ;
2015-05-14 19:50:04 +03:00
if ( ! lock ) {
DEBUG_LOG ( ( " MTP Info: could not lock auth_key for read, waiting signal emit " ) ) ;
clearMessages ( ) ;
2019-11-14 10:13:17 +03:00
_keyId = newKeyId ;
2015-05-14 19:50:04 +03:00
return ; // some other connection is getting key
}
2019-11-14 10:13:17 +03:00
auto key = _sessionData - > getKey ( ) ;
2015-05-14 19:50:04 +03:00
newKeyId = key ? key - > keyId ( ) : 0 ;
}
2019-11-14 10:13:17 +03:00
if ( _keyId ! = newKeyId ) {
2015-05-14 19:50:04 +03:00
clearMessages ( ) ;
2019-11-14 10:13:17 +03:00
_keyId = newKeyId ;
2015-05-14 19:50:04 +03:00
}
2019-11-14 10:13:17 +03:00
DEBUG_LOG ( ( " AuthKey Info: Connection update key from Session, dc %1 result: %2 " ) . arg ( _shiftedDcId ) . arg ( Logs : : mb ( & _keyId , sizeof ( _keyId ) ) . str ( ) ) ) ;
if ( _keyId ) {
2015-05-14 19:50:04 +03:00
return authKeyCreated ( ) ;
2014-05-30 12:53:19 +04:00
}
2015-05-14 19:50:04 +03:00
DEBUG_LOG ( ( " AuthKey Info: No key in updateAuthKey(), will be creating auth_key " ) ) ;
2014-05-30 12:53:19 +04:00
lockKey ( ) ;
2019-11-14 10:13:17 +03:00
const auto & key = _sessionData - > getKey ( ) ;
2014-05-30 12:53:19 +04:00
if ( key ) {
2019-11-14 10:13:17 +03:00
if ( _keyId ! = key - > keyId ( ) ) clearMessages ( ) ;
_keyId = key - > keyId ( ) ;
2014-05-30 12:53:19 +04:00
unlockKey ( ) ;
return authKeyCreated ( ) ;
2017-02-25 19:44:02 +03:00
} else if ( _instance - > isKeysDestroyer ( ) ) {
// We are here to destroy an old key, so we're done.
LOG ( ( " MTP Error: No key %1 in updateAuthKey() for destroying. " ) . arg ( _shiftedDcId ) ) ;
2019-11-13 11:31:12 +03:00
_instance - > checkIfKeyWasDestroyed ( _shiftedDcId ) ;
2017-02-25 19:44:02 +03:00
return ;
2014-05-30 12:53:19 +04:00
}
2015-08-08 12:14:47 +03:00
lockFinished . unlock ( ) ;
2019-07-05 15:38:38 +02:00
2019-11-13 17:12:04 +03:00
createDcKey ( ) ;
2014-05-30 12:53:19 +04:00
}
2019-11-13 17:12:04 +03:00
void ConnectionPrivate : : createDcKey ( ) {
using Result = DcKeyCreator : : Result ;
using Error = DcKeyCreator : : Error ;
auto delegate = DcKeyCreator : : Delegate ( ) ;
delegate . done = [ = ] ( base : : expected < Result , Error > result ) {
_keyCreator = nullptr ;
2014-05-30 12:53:19 +04:00
2019-11-13 17:12:04 +03:00
if ( result ) {
2019-11-14 10:13:17 +03:00
QReadLocker lockFinished ( & _sessionDataMutex ) ;
if ( ! _sessionData ) return ;
2014-05-30 12:53:19 +04:00
2019-11-14 10:13:17 +03:00
_sessionData - > setSalt ( result - > serverSalt ) ;
2014-05-30 12:53:19 +04:00
2019-11-13 17:12:04 +03:00
auto authKey = std : : move ( result - > key ) ;
2014-05-30 12:53:19 +04:00
2019-11-13 17:12:04 +03:00
DEBUG_LOG ( ( " AuthKey Info: auth key gen succeed, id: %1, server salt: %2 " ) . arg ( authKey - > keyId ( ) ) . arg ( result - > serverSalt ) ) ;
2014-05-30 12:53:19 +04:00
2019-11-14 10:13:17 +03:00
_sessionData - > owner ( ) - > notifyKeyCreated ( std : : move ( authKey ) ) ; // slot will call authKeyCreated()
_sessionData - > clear ( _instance ) ;
2019-11-13 17:12:04 +03:00
unlockKey ( ) ;
} else if ( result . error ( ) = = Error : : UnknownPublicKey ) {
if ( _dcType = = DcType : : Cdn ) {
LOG ( ( " Warning: CDN public RSA key not found " ) ) ;
requestCDNConfig ( ) ;
} else {
LOG ( ( " AuthKey Error: could not choose public RSA key " ) ) ;
restart ( ) ;
}
} else {
restart ( ) ;
2014-05-30 12:53:19 +04:00
}
2019-11-13 17:12:04 +03:00
} ;
2019-11-14 10:13:17 +03:00
const auto expireIn = ( GetDcIdShift ( _shiftedDcId ) = = kCheckKeyDcShift )
? kCheckKeyExpiresIn
: TimeId ( 0 ) ;
2019-11-13 17:12:04 +03:00
_keyCreator = std : : make_unique < DcKeyCreator > (
BareDcId ( _shiftedDcId ) ,
getProtocolDcId ( ) ,
_connection . get ( ) ,
_instance - > dcOptions ( ) ,
2019-11-14 10:13:17 +03:00
std : : move ( delegate ) ,
expireIn ) ;
2014-05-30 12:53:19 +04:00
}
2019-11-13 17:12:04 +03:00
void ConnectionPrivate : : clearMessages ( ) {
2019-11-14 10:13:17 +03:00
if ( _keyId & & _keyId ! = kRecreateKeyId & & _connection ) {
2019-11-13 17:12:04 +03:00
_connection - > received ( ) . clear ( ) ;
2014-05-30 12:53:19 +04:00
}
}
2016-03-24 11:57:11 +03:00
void ConnectionPrivate : : authKeyCreated ( ) {
2019-11-13 17:12:04 +03:00
_keyCreator = nullptr ;
2014-05-30 12:53:19 +04:00
2018-04-24 23:09:20 +04:00
connect ( _connection , & AbstractConnection : : receivedData , [ = ] {
handleReceived ( ) ;
} ) ;
2014-05-30 12:53:19 +04:00
2019-11-14 10:13:17 +03:00
if ( _sessionData - > getSalt ( ) ) { // else receive salt in bad_server_salt first, then try to send all the requests
2016-03-24 11:57:11 +03:00
setState ( ConnectedState ) ;
2019-11-14 10:13:17 +03:00
if ( _restarted ) {
2014-11-25 15:15:29 +03:00
emit resendAllAsync ( ) ;
2019-11-14 10:13:17 +03:00
_restarted = false ;
2014-05-30 12:53:19 +04:00
}
}
2016-03-24 13:12:18 +03:00
_pingIdToSend = rand_value < uint64 > ( ) ; // get server_salt
2014-05-30 12:53:19 +04:00
2014-11-22 12:45:04 +03:00
emit needToSendAsync ( ) ;
2014-05-30 12:53:19 +04:00
}
2018-04-24 23:09:20 +04:00
void ConnectionPrivate : : onError (
not_null < AbstractConnection * > connection ,
qint32 errorCode ) {
2017-02-25 19:44:02 +03:00
if ( errorCode = = - 429 ) {
LOG ( ( " Protocol Error: -429 flood code returned! " ) ) ;
2018-05-24 16:40:19 +03:00
} else if ( errorCode = = - 444 ) {
LOG ( ( " Protocol Error: -444 bad dc_id code returned! " ) ) ;
InvokeQueued ( _instance , [ instance = _instance ] {
instance - > badConfigurationError ( ) ;
} ) ;
2017-02-25 19:44:02 +03:00
}
2018-04-24 23:09:20 +04:00
removeTestConnection ( connection ) ;
if ( _testConnections . empty ( ) ) {
2018-05-17 22:58:00 +03:00
handleError ( errorCode ) ;
2017-03-23 19:11:35 +03:00
} else {
2018-04-24 23:09:20 +04:00
confirmBestConnection ( ) ;
2017-03-23 19:11:35 +03:00
}
}
void ConnectionPrivate : : handleError ( int errorCode ) {
2018-04-23 14:24:03 +04:00
destroyAllConnections ( ) ;
2018-04-24 23:09:20 +04:00
_waitForConnectedTimer . cancel ( ) ;
2015-06-10 15:48:26 +03:00
2017-03-23 19:11:35 +03:00
if ( errorCode = = - 404 ) {
2019-11-13 17:12:04 +03:00
if ( _dcType = = DcType : : Cdn & & ! _instance - > isKeysDestroyer ( ) ) {
2017-03-23 19:11:35 +03:00
LOG ( ( " MTP Info: -404 error received in CDN dc %1, assuming it was destroyed, recreating. " ) . arg ( _shiftedDcId ) ) ;
clearMessages ( ) ;
2019-11-14 10:13:17 +03:00
_keyId = kRecreateKeyId ;
2017-02-25 19:44:02 +03:00
return restart ( ) ;
2019-11-13 11:31:12 +03:00
} else {
LOG ( ( " MTP Info: -404 error received, informing instance. " ) ) ;
_instance - > checkIfKeyWasDestroyed ( _shiftedDcId ) ;
if ( _instance - > isKeysDestroyer ( ) ) {
return ;
}
2017-02-25 19:44:02 +03:00
}
2015-06-10 15:48:26 +03:00
}
2017-03-23 19:11:35 +03:00
MTP_LOG ( _shiftedDcId , ( " Restarting after error in connection, error code: %1... " ) . arg ( errorCode ) ) ;
return restart ( ) ;
2014-05-30 12:53:19 +04:00
}
2016-03-24 11:57:11 +03:00
void ConnectionPrivate : : onReadyData ( ) {
2014-05-30 12:53:19 +04:00
}
2018-06-25 19:55:27 +01:00
bool ConnectionPrivate : : sendSecureRequest (
SecureRequest & & request ,
bool needAnyResponse ,
QReadLocker & lockFinished ) {
request . addPadding ( _connection - > requiresExtendedPadding ( ) ) ;
2014-05-30 12:53:19 +04:00
uint32 fullSize = request - > size ( ) ;
2018-06-25 19:55:27 +01:00
if ( fullSize < 9 ) {
return false ;
}
2014-05-30 12:53:19 +04:00
2018-06-25 19:55:27 +01:00
auto messageSize = request . messageSize ( ) ;
if ( messageSize < 5 | | fullSize < messageSize + 4 ) {
return false ;
}
2016-01-11 23:43:29 +08:00
2019-11-14 10:13:17 +03:00
auto lock = ReadLockerAttempt ( _sessionData - > keyMutex ( ) ) ;
2014-05-30 12:53:19 +04:00
if ( ! lock ) {
2017-02-25 19:44:02 +03:00
DEBUG_LOG ( ( " MTP Info: could not lock key for read in sendBuffer(), dc %1, restarting... " ) . arg ( _shiftedDcId ) ) ;
2015-08-08 12:14:47 +03:00
lockFinished . unlock ( ) ;
2014-05-30 12:53:19 +04:00
restart ( ) ;
return false ;
}
2019-11-14 10:13:17 +03:00
auto key = _sessionData - > getKey ( ) ;
if ( ! key | | key - > keyId ( ) ! = _keyId ) {
2017-02-25 19:44:02 +03:00
DEBUG_LOG ( ( " MTP Error: auth_key id for dc %1 changed " ) . arg ( _shiftedDcId ) ) ;
2015-08-08 12:14:47 +03:00
lockFinished . unlock ( ) ;
2014-05-30 12:53:19 +04:00
restart ( ) ;
return false ;
}
2019-11-14 10:13:17 +03:00
auto session = _sessionData - > getSessionId ( ) ;
auto salt = _sessionData - > getSalt ( ) ;
2014-05-30 12:53:19 +04:00
memcpy ( request - > data ( ) + 0 , & salt , 2 * sizeof ( mtpPrime ) ) ;
memcpy ( request - > data ( ) + 2 , & session , 2 * sizeof ( mtpPrime ) ) ;
2017-06-26 20:38:16 +03:00
auto from = request - > constData ( ) + 4 ;
2017-02-25 19:44:02 +03:00
MTP_LOG ( _shiftedDcId , ( " Send: " ) + mtpTextSerialize ( from , from + messageSize ) ) ;
2014-05-30 12:53:19 +04:00
2016-12-31 12:58:56 +04:00
# ifdef TDESKTOP_MTPROTO_OLD
uint32 padding = fullSize - 4 - messageSize ;
2014-05-30 12:53:19 +04:00
uchar encryptedSHA [ 20 ] ;
MTPint128 & msgKey ( * ( MTPint128 * ) ( encryptedSHA + 4 ) ) ;
2018-06-25 19:55:27 +01:00
hashSha1 (
request - > constData ( ) ,
( fullSize - padding ) * sizeof ( mtpPrime ) ,
encryptedSHA ) ;
2019-11-14 10:13:17 +03:00
auto packet = _connection - > prepareSecurePacket ( _keyId , msgKey , fullSize ) ;
2018-06-25 19:55:27 +01:00
const auto prefix = packet . size ( ) ;
packet . resize ( prefix + fullSize ) ;
aesIgeEncrypt_oldmtp (
request - > constData ( ) ,
& packet [ prefix ] ,
fullSize * sizeof ( mtpPrime ) ,
key ,
msgKey ) ;
2016-12-31 12:58:56 +04:00
# else // TDESKTOP_MTPROTO_OLD
uchar encryptedSHA256 [ 32 ] ;
MTPint128 & msgKey ( * ( MTPint128 * ) ( encryptedSHA256 + 8 ) ) ;
SHA256_CTX msgKeyLargeContext ;
SHA256_Init ( & msgKeyLargeContext ) ;
SHA256_Update ( & msgKeyLargeContext , key - > partForMsgKey ( true ) , 32 ) ;
SHA256_Update ( & msgKeyLargeContext , request - > constData ( ) , fullSize * sizeof ( mtpPrime ) ) ;
SHA256_Final ( encryptedSHA256 , & msgKeyLargeContext ) ;
2019-11-14 10:13:17 +03:00
auto packet = _connection - > prepareSecurePacket ( _keyId , msgKey , fullSize ) ;
2018-06-25 19:55:27 +01:00
const auto prefix = packet . size ( ) ;
packet . resize ( prefix + fullSize ) ;
2016-12-31 12:58:56 +04:00
2018-06-25 19:55:27 +01:00
aesIgeEncrypt (
request - > constData ( ) ,
& packet [ prefix ] ,
fullSize * sizeof ( mtpPrime ) ,
key ,
msgKey ) ;
2016-12-31 12:58:56 +04:00
# endif // TDESKTOP_MTPROTO_OLD
2016-01-11 23:43:29 +08:00
2014-05-30 12:53:19 +04:00
DEBUG_LOG ( ( " MTP Info: sending request, size: %1, num: %2, time: %3 " ) . arg ( fullSize + 6 ) . arg ( ( * request ) [ 4 ] ) . arg ( ( * request ) [ 5 ] ) ) ;
2018-04-24 23:09:20 +04:00
_connection - > setSentEncrypted ( ) ;
2018-06-25 19:55:27 +01:00
_connection - > sendData ( std : : move ( packet ) ) ;
2014-05-30 12:53:19 +04:00
if ( needAnyResponse ) {
2018-06-25 19:55:27 +01:00
onSentSome ( ( prefix + fullSize ) * sizeof ( mtpPrime ) ) ;
2014-05-30 12:53:19 +04:00
}
return true ;
}
2016-03-24 11:57:11 +03:00
mtpRequestId ConnectionPrivate : : wasSent ( mtpMsgId msgId ) const {
2015-03-12 13:28:10 +03:00
if ( msgId = = _pingMsgId ) return mtpRequestId ( 0xFFFFFFFF ) ;
2014-05-30 12:53:19 +04:00
{
2019-11-14 10:13:17 +03:00
QReadLocker locker ( _sessionData - > haveSentMutex ( ) ) ;
const auto & haveSent = _sessionData - > haveSentMap ( ) ;
2018-06-25 19:55:27 +01:00
const auto i = haveSent . constFind ( msgId ) ;
if ( i ! = haveSent . cend ( ) ) {
return i . value ( ) - > requestId
? i . value ( ) - > requestId
: mtpRequestId ( 0xFFFFFFFF ) ;
}
2014-05-30 12:53:19 +04:00
}
{
2019-11-14 10:13:17 +03:00
QReadLocker locker ( _sessionData - > toResendMutex ( ) ) ;
const auto & toResend = _sessionData - > toResendMap ( ) ;
2018-06-25 19:55:27 +01:00
const auto i = toResend . constFind ( msgId ) ;
2014-05-30 12:53:19 +04:00
if ( i ! = toResend . cend ( ) ) return i . value ( ) ;
}
{
2019-11-14 10:13:17 +03:00
QReadLocker locker ( _sessionData - > wereAckedMutex ( ) ) ;
const auto & wereAcked = _sessionData - > wereAckedMap ( ) ;
2018-06-25 19:55:27 +01:00
const auto i = wereAcked . constFind ( msgId ) ;
2014-05-30 12:53:19 +04:00
if ( i ! = wereAcked . cend ( ) ) return i . value ( ) ;
}
return 0 ;
}
2016-03-24 11:57:11 +03:00
void ConnectionPrivate : : lockKey ( ) {
2014-05-30 12:53:19 +04:00
unlockKey ( ) ;
2019-11-14 10:13:17 +03:00
_sessionData - > keyMutex ( ) - > lockForWrite ( ) ;
_myKeyLock = true ;
2014-05-30 12:53:19 +04:00
}
2016-03-24 11:57:11 +03:00
void ConnectionPrivate : : unlockKey ( ) {
2019-11-14 10:13:17 +03:00
if ( _myKeyLock ) {
_myKeyLock = false ;
_sessionData - > keyMutex ( ) - > unlock ( ) ;
2014-05-30 12:53:19 +04:00
}
}
2016-03-24 11:57:11 +03:00
ConnectionPrivate : : ~ ConnectionPrivate ( ) {
2019-11-13 17:12:04 +03:00
Expects ( _finished ) ;
Expects ( ! _connection ) ;
Expects ( _testConnections . empty ( ) ) ;
Expects ( ! _keyCreator ) ;
2014-05-30 12:53:19 +04:00
}
2016-03-24 11:57:11 +03:00
void ConnectionPrivate : : stop ( ) {
2019-11-14 10:13:17 +03:00
QWriteLocker lockFinished ( & _sessionDataMutex ) ;
if ( _sessionData ) {
if ( _myKeyLock ) {
_sessionData - > owner ( ) - > notifyKeyCreated ( AuthKeyPtr ( ) ) ; // release key lock, let someone else create it
_sessionData - > keyMutex ( ) - > unlock ( ) ;
_myKeyLock = false ;
}
_sessionData = nullptr ;
2015-05-14 19:50:04 +03:00
}
2014-11-13 14:27:10 +03:00
}
2016-03-24 11:57:11 +03:00
} // namespace internal
} // namespace MTP