2014-05-30 08:53:19 +00:00
/*
This file is part of Telegram Desktop ,
2018-01-03 10:23:14 +00:00
the official desktop application for the Telegram messaging service .
2014-05-30 08:53:19 +00:00
2018-01-03 10:23:14 +00:00
For license and copyright information please follow this link :
https : //github.com/telegramdesktop/tdesktop/blob/master/LEGAL
2014-05-30 08:53:19 +00:00
*/
2019-12-02 13:10:19 +00:00
# include "mtproto/session_private.h"
2016-03-23 18:12:07 +00:00
2019-11-20 09:16:53 +00:00
# include "mtproto/details/mtproto_bound_key_creator.h"
2019-12-02 13:10:19 +00:00
# include "mtproto/details/mtproto_dcenter.h"
2019-11-14 15:29:45 +00:00
# include "mtproto/details/mtproto_dump_to_text.h"
2019-12-02 13:10:19 +00:00
# include "mtproto/details/mtproto_rsa_public_key.h"
2017-12-18 12:40:15 +00:00
# include "mtproto/session.h"
2019-11-18 09:28:14 +00:00
# include "mtproto/mtproto_rpc_sender.h"
2017-06-26 17:38:16 +00:00
# include "mtproto/dc_options.h"
# include "mtproto/connection_abstract.h"
# include "base/openssl_help.h"
2018-04-24 19:09:20 +00:00
# include "base/qthelp_url.h"
2019-07-10 17:28:33 +00:00
# include "base/unixtime.h"
2019-12-02 13:10:19 +00:00
# include "zlib.h"
2018-06-06 12:16:21 +00:00
2016-03-23 18:12:07 +00:00
namespace MTP {
2019-12-02 13:10:19 +00:00
namespace details {
2016-03-24 08:57:11 +00:00
namespace {
2017-02-27 09:51:03 +00:00
constexpr auto kIntSize = static_cast < int > ( sizeof ( mtpPrime ) ) ;
2019-02-19 06:57:53 +00: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 19:09:20 +00:00
constexpr auto kPingDelayDisconnect = 60 ;
2019-11-14 07:13:17 +00:00
constexpr auto kPingSendAfter = 30 * crl : : time ( 1000 ) ;
constexpr auto kPingSendAfterForce = 45 * crl : : time ( 1000 ) ;
2019-12-10 15:29:18 +00:00
constexpr auto kTemporaryExpiresIn = TimeId ( 86400 ) ;
2019-11-20 08:23:30 +00:00
constexpr auto kBindKeyAdditionalExpiresTimeout = TimeId ( 30 ) ;
2018-05-17 19:58:00 +00:00
constexpr auto kTestModeDcIdShift = 10000 ;
2019-11-20 10:41:14 +00:00
constexpr auto kCheckSentRequestsEach = 1 * crl : : time ( 1000 ) ;
2019-11-20 13:33:45 +00:00
constexpr auto kKeyOldEnoughForDestroy = 60 * crl : : time ( 1000 ) ;
2019-12-02 13:10:19 +00:00
constexpr auto kSentContainerLives = 600 * crl : : time ( 1000 ) ;
2017-04-24 12:16:38 +00:00
2018-04-24 07:21:19 +00:00
// If we can't connect for this time we will ask _instance to update config.
2019-11-20 08:23:30 +00:00
constexpr auto kRequestConfigTimeout = 8 * crl : : time ( 1000 ) ;
2018-04-24 07:21:19 +00:00
2016-12-31 08:58:56 +00:00
// Don't try to handle messages larger than this size.
constexpr auto kMaxMessageLength = 16 * 1024 * 1024 ;
2019-11-20 10:41:14 +00:00
// How much time passed from send till we resend request or check its state.
constexpr auto kCheckSentRequestTimeout = 10 * crl : : time ( 1000 ) ;
// How much time to wait for some more requests,
// when resending request or checking its state.
constexpr auto kSendStateRequestWaiting = crl : : time ( 1000 ) ;
2019-12-02 13:10:19 +00:00
// How much time to wait for some more requests, when sending msg acks.
constexpr auto kAckSendWaiting = 10 * crl : : time ( 1000 ) ;
2019-11-20 10:41:14 +00:00
2019-11-13 14:12:04 +00:00
using namespace details ;
2019-11-20 10:41:14 +00:00
[[nodiscard]] QString LogIdsVector ( const QVector < MTPlong > & ids ) {
2017-12-11 14:45:29 +00:00
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 + " ] " ;
}
2019-11-20 10:41:14 +00:00
[[nodiscard]] QString LogIds ( const QVector < uint64 > & ids ) {
if ( ! ids . size ( ) ) return " [] " ;
auto idsStr = QString ( " [%1 " ) . arg ( * ids . cbegin ( ) ) ;
for ( const auto id : ids ) {
idsStr + = QString ( " , %2 " ) . arg ( id ) ;
}
return idsStr + " ] " ;
}
2019-11-22 09:15:38 +00:00
void WrapInvokeAfter (
SerializedRequest & to ,
const SerializedRequest & from ,
const base : : flat_map < mtpMsgId , SerializedRequest > & haveSent ,
int32 skipBeforeRequest = 0 ) {
2018-06-25 18:55:27 +00:00
const auto afterId = * ( mtpMsgId * ) ( from - > after - > data ( ) + 4 ) ;
2019-11-22 09:15:38 +00:00
const auto i = afterId ? haveSent . find ( afterId ) : haveSent . end ( ) ;
2019-11-05 10:23:09 +00:00
int32 size = to - > size ( ) , lenInInts = ( tl : : count_length ( from ) > > 2 ) , headlen = 4 , fulllen = headlen + lenInInts ;
2019-11-22 09:15:38 +00:00
if ( i = = haveSent . end ( ) ) { // no invoke after or such msg was not sent or was completed recently
2017-02-24 17:15:41 +00:00
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 08:57:11 +00:00
} // namespace
2016-03-23 18:12:07 +00:00
2019-12-02 13:10:19 +00:00
SessionPrivate : : SessionPrivate (
2019-11-27 14:22:22 +00:00
not_null < Instance * > instance ,
not_null < QThread * > thread ,
std : : shared_ptr < SessionData > data ,
ShiftedDcId shiftedDcId )
: QObject ( nullptr )
, _instance ( instance )
, _shiftedDcId ( shiftedDcId )
, _realDcType ( _instance - > dcOptions ( ) - > dcType ( _shiftedDcId ) )
, _currentDcType ( _realDcType )
, _state ( DisconnectedState )
, _retryTimer ( thread , [ = ] { retryByTimer ( ) ; } )
, _oldConnectionTimer ( thread , [ = ] { markConnectionOld ( ) ; } )
, _waitForConnectedTimer ( thread , [ = ] { waitConnectedFailed ( ) ; } )
, _waitForReceivedTimer ( thread , [ = ] { waitReceivedFailed ( ) ; } )
, _waitForBetterTimer ( thread , [ = ] { waitBetterFailed ( ) ; } )
, _waitForReceived ( kMinReceiveTimeout )
, _waitForConnected ( kMinConnectedTimeout )
, _pingSender ( thread , [ = ] { sendPingByTimer ( ) ; } )
, _checkSentRequestsTimer ( thread , [ = ] { checkSentRequests ( ) ; } )
, _sessionData ( std : : move ( data ) ) {
Expects ( _shiftedDcId ! = 0 ) ;
2014-05-30 08:53:19 +00:00
2019-11-27 14:22:22 +00:00
moveToThread ( thread ) ;
2014-05-30 08:53:19 +00:00
2019-11-27 15:09:56 +00:00
InvokeQueued ( this , [ = ] {
2019-11-27 14:22:22 +00:00
_checkSentRequestsTimer . callEach ( kCheckSentRequestsEach ) ;
connectToServer ( ) ;
} ) ;
2014-05-30 08:53:19 +00:00
}
2019-12-02 13:10:19 +00:00
SessionPrivate : : ~ SessionPrivate ( ) {
2019-11-27 14:22:22 +00:00
releaseKeyCreationOnFail ( ) ;
doDisconnect ( ) ;
2014-05-30 08:53:19 +00:00
2019-11-27 14:22:22 +00:00
Expects ( ! _connection ) ;
Expects ( _testConnections . empty ( ) ) ;
2014-05-30 08:53:19 +00:00
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : appendTestConnection (
2018-04-24 19:09:20 +00:00
DcOptions : : Variants : : Protocol protocol ,
const QString & ip ,
int port ,
const bytes : : vector & protocolSecret ) {
2019-11-21 10:37:39 +00:00
QWriteLocker lock ( & _stateMutex ) ;
2018-04-24 19:09:20 +00:00
const auto priority = ( qthelp : : is_ipv6 ( ip ) ? 0 : 1 )
2018-04-25 09:24:48 +00:00
+ ( protocol = = DcOptions : : Variants : : Tcp ? 1 : 0 )
+ ( protocolSecret . empty ( ) ? 0 : 1 ) ;
2018-04-24 19:09:20 +00:00
_testConnections . push_back ( {
2018-05-17 19:58:00 +00:00
AbstractConnection : : Create (
_instance ,
protocol ,
thread ( ) ,
2019-07-05 07:54:53 +00:00
protocolSecret ,
2019-12-02 13:10:19 +00:00
_options - > proxy ) ,
2018-04-24 19:09:20 +00:00
priority
} ) ;
2019-07-11 10:20:37 +00:00
const auto weak = _testConnections . back ( ) . data . get ( ) ;
2018-04-24 19:09:20 +00:00
connect ( weak , & AbstractConnection : : error , [ = ] ( int errorCode ) {
onError ( weak , errorCode ) ;
} ) ;
connect ( weak , & AbstractConnection : : receivedSome , [ = ] {
onReceivedSome ( ) ;
} ) ;
2019-11-14 07:13:17 +00:00
_firstSentAt = 0 ;
2018-04-24 19:09:20 +00:00
if ( _oldConnection ) {
_oldConnection = false ;
2014-05-30 08:53:19 +00:00
DEBUG_LOG ( ( " This connection marked as not old! " ) ) ;
}
2018-04-24 19:09:20 +00:00
_oldConnectionTimer . callOnce ( kMarkConnectionOldTimeout ) ;
connect ( weak , & AbstractConnection : : connected , [ = ] {
onConnected ( weak ) ;
} ) ;
connect ( weak , & AbstractConnection : : disconnected , [ = ] {
onDisconnected ( weak ) ;
} ) ;
2019-07-10 15:03:48 +00:00
connect ( weak , & AbstractConnection : : syncTimeRequest , [ = ] {
2019-07-10 17:28:33 +00:00
InvokeQueued ( _instance , [ instance = _instance ] {
instance - > syncHttpUnixtime ( ) ;
} ) ;
2019-07-10 15:03:48 +00:00
} ) ;
2014-05-30 08:53:19 +00:00
2020-02-25 09:40:09 +00:00
const auto protocolDcId = getProtocolDcId ( ) ;
2018-05-17 19:58:00 +00:00
InvokeQueued ( _testConnections . back ( ) . data , [ = ] {
2020-02-25 09:40:09 +00:00
weak - > connectToServer ( ip , port , protocolSecret , protocolDcId ) ;
2018-05-17 19:58:00 +00:00
} ) ;
}
2019-12-02 13:10:19 +00:00
int16 SessionPrivate : : getProtocolDcId ( ) const {
2018-06-11 18:35:27 +00:00
const auto dcId = BareDcId ( _shiftedDcId ) ;
const auto simpleDcId = isTemporaryDcId ( dcId )
? getRealIdFromTemporaryDcId ( dcId )
2018-05-02 19:27:03 +00:00
: dcId ;
2018-05-17 19:58:00 +00:00
const auto testedDcId = cTestMode ( )
? ( kTestModeDcIdShift + simpleDcId )
2018-05-02 19:27:03 +00:00
: simpleDcId ;
2019-11-21 10:37:39 +00:00
return ( _currentDcType = = DcType : : MediaCluster )
2018-05-17 19:58:00 +00:00
? - testedDcId
: testedDcId ;
2018-04-23 10:24:03 +00:00
}
2015-06-29 12:25:28 +00:00
2019-12-02 13:10:19 +00:00
void SessionPrivate : : checkSentRequests ( ) {
2019-12-02 10:32:09 +00:00
clearOldContainers ( ) ;
2019-12-02 13:30:33 +00:00
const auto now = crl : : now ( ) ;
if ( _bindMsgId & & _bindMessageSent + kCheckSentRequestTimeout < now ) {
DEBUG_LOG ( ( " MTP Info: "
" Request state while key is not bound, restarting. " ) ) ;
restart ( ) ;
return ;
}
2019-11-20 10:41:14 +00:00
auto requesting = false ;
{
QReadLocker locker ( _sessionData - > haveSentMutex ( ) ) ;
auto & haveSent = _sessionData - > haveSentMap ( ) ;
const auto haveSentCount = haveSent . size ( ) ;
2019-12-02 09:40:53 +00:00
const auto checkAfter = kCheckSentRequestTimeout ;
2019-11-22 09:15:38 +00:00
for ( const auto & [ msgId , request ] : haveSent ) {
2019-12-02 11:34:14 +00:00
if ( request - > lastSentTime + checkAfter < now ) {
2019-11-22 09:15:38 +00:00
// Need to check state.
request - > lastSentTime = now ;
2019-12-02 13:30:33 +00:00
if ( _stateRequestData . emplace ( msgId ) . second ) {
2019-11-22 09:15:38 +00:00
requesting = true ;
2019-11-20 10:41:14 +00:00
}
}
}
}
2019-12-02 13:30:33 +00:00
if ( requesting ) {
2019-12-02 09:40:53 +00:00
_sessionData - > queueSendAnything ( kSendStateRequestWaiting ) ;
}
2019-11-20 10:41:14 +00:00
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : clearOldContainers ( ) {
2019-12-02 10:49:33 +00:00
auto resent = false ;
2019-12-02 10:32:09 +00:00
const auto now = crl : : now ( ) ;
for ( auto i = _sentContainers . begin ( ) ; i ! = _sentContainers . end ( ) ; ) {
if ( now > i - > second . sent + kSentContainerLives ) {
2019-12-02 10:49:33 +00:00
DEBUG_LOG ( ( " MTP Info: Removing old container with resending %1, "
2019-12-02 10:32:09 +00:00
" sent: %2, now: %3, current unixtime: %4 "
) . arg ( i - > first
) . arg ( i - > second . sent
) . arg ( now
) . arg ( base : : unixtime : : now ( ) ) ) ;
2019-12-02 10:49:33 +00:00
const auto ids = std : : move ( i - > second . messages ) ;
2019-12-02 10:32:09 +00:00
i = _sentContainers . erase ( i ) ;
2019-12-02 10:49:33 +00:00
resent = resent | | ! ids . empty ( ) ;
for ( const auto innerMsgId : ids ) {
resend ( innerMsgId , - 1 , true ) ;
}
2019-12-02 10:32:09 +00:00
} else {
+ + i ;
}
}
2019-12-02 10:49:33 +00:00
if ( resent ) {
_sessionData - > queueNeedToResumeAndSend ( ) ;
}
2019-12-02 10:32:09 +00:00
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : destroyAllConnections ( ) {
2019-11-20 09:16:53 +00:00
clearUnboundKeyCreator ( ) ;
2018-04-24 19:09:20 +00:00
_waitForBetterTimer . cancel ( ) ;
_waitForReceivedTimer . cancel ( ) ;
_waitForConnectedTimer . cancel ( ) ;
_testConnections . clear ( ) ;
_connection = nullptr ;
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : cdnConfigChanged ( ) {
2019-11-27 14:22:22 +00:00
connectToServer ( true ) ;
2014-05-30 08:53:19 +00:00
}
2019-12-02 13:10:19 +00:00
int32 SessionPrivate : : getShiftedDcId ( ) const {
2017-02-25 16:44:02 +00:00
return _shiftedDcId ;
2014-05-30 08:53:19 +00:00
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : dcOptionsChanged ( ) {
2019-11-27 10:41:17 +00:00
_retryTimeout = 1 ;
connectToServer ( true ) ;
}
2019-12-02 13:10:19 +00:00
int32 SessionPrivate : : getState ( ) const {
2019-11-21 10:37:39 +00:00
QReadLocker lock ( & _stateMutex ) ;
2014-05-30 08:53:19 +00:00
int32 result = _state ;
if ( _state < 0 ) {
2018-04-24 19:09:20 +00:00
if ( _retryTimer . isActive ( ) ) {
2019-02-19 06:57:53 +00:00
result = int32 ( crl : : now ( ) - _retryWillFinish ) ;
2014-05-30 08:53:19 +00:00
if ( result > = 0 ) {
result = - 1 ;
}
}
}
return result ;
}
2019-12-02 13:10:19 +00:00
QString SessionPrivate : : transport ( ) const {
2019-11-21 10:37:39 +00:00
QReadLocker lock ( & _stateMutex ) ;
2018-04-24 19:09:20 +00:00
if ( ! _connection | | ( _state < 0 ) ) {
2014-05-30 08:53:19 +00:00
return QString ( ) ;
}
2018-04-24 08:46:27 +00:00
2019-12-02 13:10:19 +00:00
Assert ( _options ! = nullptr ) ;
2018-04-24 19:09:20 +00:00
return _connection - > transport ( ) ;
2014-05-30 08:53:19 +00:00
}
2019-12-02 13:10:19 +00:00
bool SessionPrivate : : setState ( int state , int ifState ) {
2019-11-27 14:22:22 +00:00
if ( ifState ! = kUpdateStateAlways ) {
2019-11-21 10:37:39 +00:00
QReadLocker lock ( & _stateMutex ) ;
2019-11-19 16:14:50 +00:00
if ( _state ! = ifState ) {
return false ;
}
2014-05-30 08:53:19 +00:00
}
2019-11-18 12:53:37 +00:00
2019-11-21 10:37:39 +00:00
QWriteLocker lock ( & _stateMutex ) ;
2019-11-19 16:14:50 +00:00
if ( _state = = state ) {
return false ;
}
2014-05-30 08:53:19 +00:00
_state = state ;
if ( state < 0 ) {
2018-04-24 19:09:20 +00:00
_retryTimeout = - state ;
_retryTimer . callOnce ( _retryTimeout ) ;
2019-02-19 06:57:53 +00:00
_retryWillFinish = crl : : now ( ) + _retryTimeout ;
2014-05-30 08:53:19 +00:00
}
2019-11-18 12:53:37 +00:00
lock . unlock ( ) ;
_sessionData - > queueConnectionStateChange ( state ) ;
2014-05-30 08:53:19 +00:00
return true ;
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : resetSession ( ) {
2019-11-19 11:55:39 +00:00
MTP_LOG ( _shiftedDcId , ( " Resetting session! " ) ) ;
2019-11-19 16:14:50 +00:00
_needSessionReset = false ;
2019-11-19 11:55:39 +00:00
2019-11-19 16:14:50 +00:00
DEBUG_LOG ( ( " MTP Info: creating new session in resetSession. " ) ) ;
2019-11-20 10:41:14 +00:00
changeSessionId ( ) ;
_sessionData - > queueResetDone ( ) ;
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : changeSessionId ( ) {
2019-11-20 10:41:14 +00:00
auto sessionId = _sessionId ;
do {
sessionId = openssl : : RandomValue < uint64 > ( ) ;
} while ( _sessionId = = sessionId ) ;
2014-08-01 18:49:43 +00:00
2019-11-20 10:41:14 +00:00
DEBUG_LOG ( ( " MTP Info: setting server_session: %1 " ) . arg ( sessionId ) ) ;
_sessionId = sessionId ;
_messagesCounter = 0 ;
_sessionMarkedAsStarted = false ;
2019-11-14 07:13:17 +00:00
_ackRequestData . clear ( ) ;
_resendRequestData . clear ( ) ;
2019-11-20 10:41:14 +00:00
_stateRequestData . clear ( ) ;
_receivedMessageIds . clear ( ) ;
}
2014-11-05 17:43:32 +00:00
2019-12-02 13:10:19 +00:00
uint32 SessionPrivate : : nextRequestSeqNumber ( bool needAck ) {
2019-11-20 10:41:14 +00:00
const auto result = _messagesCounter ;
_messagesCounter + = ( needAck ? 1 : 0 ) ;
return result * 2 + ( needAck ? 1 : 0 ) ;
}
2019-12-02 13:10:19 +00:00
bool SessionPrivate : : realDcTypeChanged ( ) {
2019-11-21 10:37:39 +00:00
const auto now = _instance - > dcOptions ( ) - > dcType ( _shiftedDcId ) ;
if ( _realDcType = = now ) {
return false ;
}
_realDcType = now ;
return true ;
}
2019-12-02 13:10:19 +00:00
bool SessionPrivate : : markSessionAsStarted ( ) {
2019-11-20 10:41:14 +00:00
if ( _sessionMarkedAsStarted ) {
return false ;
}
_sessionMarkedAsStarted = true ;
return true ;
2014-08-01 11:09:46 +00:00
}
2019-12-02 13:10:19 +00:00
mtpMsgId SessionPrivate : : prepareToSend (
2019-11-22 09:15:38 +00:00
SerializedRequest & request ,
2019-11-19 16:14:50 +00:00
mtpMsgId currentLastId ,
bool forceNewMsgId ) {
Expects ( request - > size ( ) > 8 ) ;
2019-11-14 13:34:58 +00:00
if ( const auto msgId = request . getMsgId ( ) ) {
// resending this request
2019-11-22 09:06:48 +00:00
const auto i = _resendingIds . find ( msgId ) ;
if ( i ! = _resendingIds . cend ( ) ) {
_resendingIds . erase ( i ) ;
2014-05-30 08:53:19 +00:00
}
2019-11-19 16:14:50 +00:00
return ( forceNewMsgId | | msgId > currentLastId )
? replaceMsgId ( request , currentLastId )
: msgId ;
2014-05-30 08:53:19 +00:00
}
2019-11-14 13:34:58 +00:00
request . setMsgId ( currentLastId ) ;
2019-11-20 10:41:14 +00:00
request . setSeqNo ( nextRequestSeqNumber ( request . needAck ( ) ) ) ;
2019-11-19 16:14:50 +00:00
if ( request - > requestId ) {
MTP_LOG ( _shiftedDcId , ( " [r%1] msg_id 0 -> %2 " ) . arg ( request - > requestId ) . arg ( currentLastId ) ) ;
}
2019-11-14 13:34:58 +00:00
return currentLastId ;
2014-05-30 08:53:19 +00:00
}
2019-12-02 13:10:19 +00:00
mtpMsgId SessionPrivate : : replaceMsgId ( SerializedRequest & request , mtpMsgId newId ) {
2019-11-19 16:14:50 +00:00
Expects ( request - > size ( ) > 8 ) ;
2014-08-01 11:09:46 +00:00
2019-11-14 13:34:58 +00:00
const auto oldMsgId = request . getMsgId ( ) ;
2019-11-19 16:14:50 +00:00
if ( oldMsgId = = newId ) {
return newId ;
}
2019-11-22 09:06:48 +00:00
// haveSentMutex() was locked in tryToSend()
2019-11-19 16:14:50 +00:00
auto & haveSent = _sessionData - > haveSentMap ( ) ;
2014-08-01 11:09:46 +00:00
2019-11-22 09:06:48 +00:00
while ( _resendingIds . contains ( newId )
| | _ackedIds . contains ( newId )
2019-11-22 09:15:38 +00:00
| | haveSent . contains ( newId ) ) {
2019-11-19 16:14:50 +00:00
newId = base : : unixtime : : mtproto_msg_id ( ) ;
}
2016-01-11 15:43:29 +00:00
2019-11-22 09:15:38 +00:00
MTP_LOG ( _shiftedDcId , ( " [r%1] msg_id %2 -> %3 "
) . arg ( request - > requestId
) . arg ( oldMsgId
) . arg ( newId ) ) ;
2014-08-01 11:09:46 +00:00
2019-11-22 09:06:48 +00:00
const auto i = _resendingIds . find ( oldMsgId ) ;
if ( i ! = _resendingIds . end ( ) ) {
const auto requestId = i - > second ;
_resendingIds . erase ( i ) ;
_resendingIds . emplace ( newId , requestId ) ;
2019-11-19 16:14:50 +00:00
}
2014-08-01 11:09:46 +00:00
2019-11-22 09:06:48 +00:00
const auto j = _ackedIds . find ( oldMsgId ) ;
2019-11-22 09:15:38 +00:00
if ( j ! = _ackedIds . end ( ) ) {
2019-11-22 09:06:48 +00:00
const auto requestId = j - > second ;
_ackedIds . erase ( j ) ;
_ackedIds . emplace ( newId , requestId ) ;
2019-11-19 16:14:50 +00:00
}
2014-08-01 11:09:46 +00:00
2019-11-19 16:14:50 +00:00
const auto k = haveSent . find ( oldMsgId ) ;
2019-11-22 09:15:38 +00:00
if ( k ! = haveSent . end ( ) ) {
const auto request = k - > second ;
2019-11-19 16:14:50 +00:00
haveSent . erase ( k ) ;
2019-11-22 09:15:38 +00:00
haveSent . emplace ( newId , request ) ;
2019-11-19 16:14:50 +00:00
}
2019-12-02 10:32:09 +00:00
for ( auto & [ msgId , container ] : _sentContainers ) {
for ( auto & innerMsgId : container . messages ) {
if ( innerMsgId = = oldMsgId ) {
innerMsgId = newId ;
2014-08-01 11:09:46 +00:00
}
}
}
2019-11-19 16:14:50 +00:00
request . setMsgId ( newId ) ;
2019-11-20 10:41:14 +00:00
request . setSeqNo ( nextRequestSeqNumber ( request . needAck ( ) ) ) ;
2014-08-01 11:09:46 +00:00
return newId ;
}
2019-12-02 13:10:19 +00:00
mtpMsgId SessionPrivate : : placeToContainer (
2019-11-22 09:15:38 +00:00
SerializedRequest & toSendRequest ,
2019-11-19 16:14:50 +00:00
mtpMsgId & bigMsgId ,
bool forceNewMsgId ,
2019-11-22 09:15:38 +00:00
SerializedRequest & req ) {
2019-11-19 16:14:50 +00:00
const auto msgId = prepareToSend ( req , bigMsgId , forceNewMsgId ) ;
2019-07-10 17:28:33 +00:00
if ( msgId > = bigMsgId ) {
bigMsgId = base : : unixtime : : mtproto_msg_id ( ) ;
}
2014-11-05 17:43:32 +00:00
2018-06-25 18:55:27 +00:00
uint32 from = toSendRequest - > size ( ) , len = req . messageSize ( ) ;
2014-11-05 17:43:32 +00:00
toSendRequest - > resize ( from + len ) ;
memcpy ( toSendRequest - > data ( ) + from , req - > constData ( ) + 4 , len * sizeof ( mtpPrime ) ) ;
return msgId ;
}
2020-04-07 11:19:52 +00:00
MTPVector < MTPJSONObjectValue > SessionPrivate : : prepareInitParams ( ) {
const auto local = QDateTime : : currentDateTime ( ) ;
const auto utc = QDateTime ( local . date ( ) , local . time ( ) , Qt : : UTC ) ;
const auto shift = base : : unixtime : : now ( ) - ( TimeId ) : : time ( nullptr ) ;
const auto delta = int ( utc . toTime_t ( ) ) - int ( local . toTime_t ( ) ) - shift ;
auto sliced = delta ;
while ( sliced < - 12 * 3600 ) {
sliced + = 24 * 3600 ;
}
while ( sliced > 14 * 3600 ) {
sliced - = 24 * 3600 ;
}
const auto sign = ( sliced < 0 ) ? - 1 : 1 ;
const auto rounded = std : : round ( std : : abs ( sliced ) / 900. ) * 900 * sign ;
return MTP_vector < MTPJSONObjectValue > (
1 ,
MTP_jsonObjectValue (
MTP_string ( " tz_offset " ) ,
MTP_jsonNumber ( MTP_double ( rounded ) ) ) ) ;
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : tryToSend ( ) {
2019-12-02 09:40:53 +00:00
DEBUG_LOG ( ( " MTP Info: tryToSend for dc %1. " ) . arg ( _shiftedDcId ) ) ;
if ( ! _connection ) {
DEBUG_LOG ( ( " MTP Info: not yet connected in dc %1. " ) . arg ( _shiftedDcId ) ) ;
return ;
} else if ( ! _keyId ) {
DEBUG_LOG ( ( " MTP Info: not yet with auth key in dc %1. " ) . arg ( _shiftedDcId ) ) ;
2014-11-13 11:27:10 +00:00
return ;
}
2014-05-30 08:53:19 +00:00
2019-11-19 10:10:51 +00:00
const auto needsLayer = ! _sessionData - > connectionInited ( ) ;
const auto state = getState ( ) ;
const auto sendOnlyFirstPing = ( state ! = ConnectedState ) ;
2019-11-20 09:16:53 +00:00
const auto sendAll = ! sendOnlyFirstPing & & ! _keyCreator ;
2019-11-19 10:10:51 +00:00
const auto isMainSession = ( GetDcIdShift ( _shiftedDcId ) = = 0 ) ;
2019-11-14 13:34:58 +00:00
if ( sendOnlyFirstPing & & ! _pingIdToSend ) {
DEBUG_LOG ( ( " MTP Info: dc %1 not sending, waiting for Connected state, state: %2 " ) . arg ( _shiftedDcId ) . arg ( state ) ) ;
return ; // just do nothing, if is not connected yet
2019-11-19 10:10:51 +00:00
} else if ( isMainSession
& & ! sendOnlyFirstPing
& & ! _pingIdToSend
& & ! _pingId
& & _pingSendAt < = crl : : now ( ) ) {
_pingIdToSend = openssl : : RandomValue < mtpPingId > ( ) ;
2019-11-14 13:34:58 +00:00
}
2019-11-20 10:41:14 +00:00
const auto forceNewMsgId = sendAll & & markSessionAsStarted ( ) ;
2019-11-20 09:16:53 +00:00
if ( forceNewMsgId & & _keyCreator ) {
_keyCreator - > restartBinder ( ) ;
2019-11-19 16:14:50 +00:00
}
2019-11-20 09:16:53 +00:00
2019-11-22 09:15:38 +00:00
auto pingRequest = SerializedRequest ( ) ;
auto ackRequest = SerializedRequest ( ) ;
auto resendRequest = SerializedRequest ( ) ;
auto stateRequest = SerializedRequest ( ) ;
auto httpWaitRequest = SerializedRequest ( ) ;
auto bindDcKeyRequest = SerializedRequest ( ) ;
2015-03-12 10:28:10 +00:00
if ( _pingIdToSend ) {
2019-11-19 10:10:51 +00:00
if ( sendOnlyFirstPing | | ! isMainSession ) {
DEBUG_LOG ( ( " MTP Info: sending ping, ping_id: %1 "
) . arg ( _pingIdToSend ) ) ;
2019-11-22 09:15:38 +00:00
pingRequest = SerializedRequest : : Serialize ( MTPPing (
2018-06-25 18:55:27 +00:00
MTP_long ( _pingIdToSend )
) ) ;
2015-03-12 10:28:10 +00:00
} else {
2019-11-19 10:10:51 +00:00
DEBUG_LOG ( ( " MTP Info: sending ping_delay_disconnect, "
" ping_id: %1 " ) . arg ( _pingIdToSend ) ) ;
2019-11-22 09:15:38 +00:00
pingRequest = SerializedRequest : : Serialize ( MTPPing_delay_disconnect (
2018-06-25 18:55:27 +00:00
MTP_long ( _pingIdToSend ) ,
MTP_int ( kPingDelayDisconnect ) ) ) ;
2018-04-24 19:09:20 +00:00
_pingSender . callOnce ( kPingSendAfterForce ) ;
2015-03-12 10:28:10 +00:00
}
2019-11-22 09:15:38 +00:00
_pingSendAt = pingRequest - > lastSentTime + kPingSendAfter ;
2019-11-14 13:34:58 +00:00
_pingId = base : : take ( _pingIdToSend ) ;
2019-11-19 10:10:51 +00:00
} else if ( ! sendAll ) {
DEBUG_LOG ( ( " MTP Info: dc %1 sending only service or bind. "
) . arg ( _shiftedDcId ) ) ;
2014-05-30 08:53:19 +00:00
} else {
2019-11-19 10:10:51 +00:00
DEBUG_LOG ( ( " MTP Info: dc %1 trying to send after ping, state: %2 "
) . arg ( _shiftedDcId
) . arg ( state ) ) ;
2014-05-30 08:53:19 +00:00
}
2019-11-14 13:34:58 +00:00
if ( ! sendOnlyFirstPing ) {
if ( ! _ackRequestData . isEmpty ( ) ) {
2019-11-22 09:15:38 +00:00
ackRequest = SerializedRequest : : Serialize ( MTPMsgsAck (
2019-11-14 13:34:58 +00:00
MTP_msgs_ack ( MTP_vector < MTPlong > (
base : : take ( _ackRequestData ) ) ) ) ) ;
}
if ( ! _resendRequestData . isEmpty ( ) ) {
2019-11-22 09:15:38 +00:00
resendRequest = SerializedRequest : : Serialize ( MTPMsgResendReq (
2019-11-14 13:34:58 +00:00
MTP_msg_resend_req ( MTP_vector < MTPlong > (
base : : take ( _resendRequestData ) ) ) ) ) ;
}
2019-11-20 10:41:14 +00:00
if ( ! _stateRequestData . empty ( ) ) {
auto ids = QVector < MTPlong > ( ) ;
ids . reserve ( _stateRequestData . size ( ) ) ;
for ( const auto id : base : : take ( _stateRequestData ) ) {
ids . push_back ( MTP_long ( id ) ) ;
2014-11-05 17:43:32 +00:00
}
2019-11-22 09:15:38 +00:00
stateRequest = SerializedRequest : : Serialize ( MTPMsgsStateReq (
2019-11-20 10:41:14 +00:00
MTP_msgs_state_req ( MTP_vector < MTPlong > ( ids ) ) ) ) ;
2014-11-05 17:43:32 +00:00
}
2018-04-24 19:09:20 +00:00
if ( _connection - > usingHttpWait ( ) ) {
2019-11-22 09:15:38 +00:00
httpWaitRequest = SerializedRequest : : Serialize ( MTPHttpWait (
2018-06-25 18:55:27 +00:00
MTP_http_wait ( MTP_int ( 100 ) , MTP_int ( 30 ) , MTP_int ( 25000 ) ) ) ) ;
2019-11-14 13:34:58 +00:00
}
2019-11-22 09:06:48 +00:00
if ( ! _bindMsgId & & _keyCreator & & _keyCreator - > readyToBind ( ) ) {
2019-11-20 09:16:53 +00:00
bindDcKeyRequest = _keyCreator - > prepareBindRequest (
2019-11-20 11:50:19 +00:00
_encryptionKey ,
2019-11-20 10:41:14 +00:00
_sessionId ) ;
2019-11-19 10:10:51 +00:00
// This is a special request with msgId used inside the message
// body, so it is prepared already with a msgId and we place
// seqNo for it manually here.
bindDcKeyRequest . setSeqNo (
2019-11-20 10:41:14 +00:00
nextRequestSeqNumber ( bindDcKeyRequest . needAck ( ) ) ) ;
2015-03-12 10:28:10 +00:00
}
2014-11-05 17:43:32 +00:00
}
2019-11-22 09:15:38 +00:00
MTPInitConnection < SerializedRequest > initWrapper ;
2014-11-14 23:23:35 +00:00
int32 initSize = 0 , initSizeInInts = 0 ;
if ( needsLayer ) {
2019-12-02 13:10:19 +00:00
Assert ( _options ! = nullptr ) ;
const auto systemLangCode = _options - > systemLangCode ;
const auto cloudLangCode = _options - > cloudLangCode ;
const auto langPackName = _options - > langPackName ;
2019-11-21 10:37:39 +00:00
const auto deviceModel = ( _currentDcType = = DcType : : Cdn )
2018-05-11 14:03:53 +00:00
? " n/a "
2019-02-01 07:48:31 +00:00
: _instance - > deviceModel ( ) ;
2019-11-21 10:37:39 +00:00
const auto systemVersion = ( _currentDcType = = DcType : : Cdn )
2018-05-11 14:03:53 +00:00
? " n/a "
2019-02-01 07:48:31 +00:00
: _instance - > systemVersion ( ) ;
2019-06-03 10:54:25 +00:00
# if defined OS_MAC_STORE
2018-11-08 05:50:18 +00:00
const auto appVersion = QString : : fromLatin1 ( AppVersionStr )
2019-06-03 10:54:25 +00:00
+ " mac store " ;
# elif defined OS_WIN_STORE // OS_MAC_STORE
const auto appVersion = QString : : fromLatin1 ( AppVersionStr )
+ " win store " ;
2018-06-04 10:41:53 +00:00
# else // OS_MAC_STORE || OS_WIN_STORE
2018-11-08 05:50:18 +00:00
const auto appVersion = QString : : fromLatin1 ( AppVersionStr ) ;
2018-06-04 10:41:53 +00:00
# endif // OS_MAC_STORE || OS_WIN_STORE
2019-12-02 13:10:19 +00:00
const auto proxyType = _options - > proxy . type ;
2018-05-11 14:03:53 +00:00
const auto mtprotoProxy = ( proxyType = = ProxyData : : Type : : Mtproto ) ;
const auto clientProxyFields = mtprotoProxy
? MTP_inputClientProxy (
2019-12-02 13:10:19 +00:00
MTP_string ( _options - > proxy . host ) ,
MTP_int ( _options - > proxy . port ) )
2018-05-11 14:03:53 +00:00
: MTPInputClientProxy ( ) ;
2019-11-22 09:15:38 +00:00
using Flag = MTPInitConnection < SerializedRequest > : : Flag ;
initWrapper = MTPInitConnection < SerializedRequest > (
2020-04-07 11:19:52 +00:00
MTP_flags ( Flag : : f_params
| ( mtprotoProxy ? Flag : : f_proxy : Flag ( 0 ) ) ) ,
2018-05-11 14:03:53 +00:00
MTP_int ( ApiId ) ,
MTP_string ( deviceModel ) ,
MTP_string ( systemVersion ) ,
2018-06-04 10:41:53 +00:00
MTP_string ( appVersion ) ,
2018-05-11 14:03:53 +00:00
MTP_string ( systemLangCode ) ,
2018-08-20 11:31:40 +00:00
MTP_string ( langPackName ) ,
2018-05-11 14:03:53 +00:00
MTP_string ( cloudLangCode ) ,
clientProxyFields ,
2020-04-07 11:19:52 +00:00
MTP_jsonObject ( prepareInitParams ( ) ) ,
2019-11-22 09:15:38 +00:00
SerializedRequest ( ) ) ;
2019-11-05 10:23:09 +00:00
initSizeInInts = ( tl : : count_length ( initWrapper ) > > 2 ) + 2 ;
2014-11-14 23:23:35 +00:00
initSize = initSizeInInts * sizeof ( mtpPrime ) ;
}
2014-05-30 08:53:19 +00:00
bool needAnyResponse = false ;
2019-11-22 09:15:38 +00:00
SerializedRequest toSendRequest ;
2014-05-30 08:53:19 +00:00
{
2019-11-14 07:13:17 +00:00
QWriteLocker locker1 ( _sessionData - > toSendMutex ( ) ) ;
2014-05-30 08:53:19 +00:00
2019-11-22 09:15:38 +00:00
auto toSendDummy = base : : flat_map < mtpRequestId , SerializedRequest > ( ) ;
2019-11-19 10:10:51 +00:00
auto & toSend = sendAll
? _sessionData - > toSendMap ( )
: toSendDummy ;
if ( ! sendAll ) {
2019-11-14 13:34:58 +00:00
locker1 . unlock ( ) ;
}
2014-05-30 08:53:19 +00:00
uint32 toSendCount = toSend . size ( ) ;
2014-11-05 17:43:32 +00:00
if ( pingRequest ) + + toSendCount ;
if ( ackRequest ) + + toSendCount ;
if ( resendRequest ) + + toSendCount ;
if ( stateRequest ) + + toSendCount ;
2015-03-12 10:28:10 +00:00
if ( httpWaitRequest ) + + toSendCount ;
2019-11-19 10:10:51 +00:00
if ( bindDcKeyRequest ) + + toSendCount ;
2019-11-14 13:34:58 +00:00
if ( ! toSendCount ) {
return ; // nothing to send
}
const auto first = pingRequest
? pingRequest
: ackRequest
? ackRequest
: resendRequest
? resendRequest
: stateRequest
? stateRequest
: httpWaitRequest
? httpWaitRequest
2019-11-19 10:10:51 +00:00
: bindDcKeyRequest
? bindDcKeyRequest
2019-11-22 09:15:38 +00:00
: toSend . begin ( ) - > second ;
if ( toSendCount = = 1 & & ! first - > forceSendInContainer ) {
2014-05-30 08:53:19 +00:00
toSendRequest = first ;
2019-11-19 10:10:51 +00:00
if ( sendAll ) {
2014-05-30 08:53:19 +00:00
toSend . clear ( ) ;
locker1 . unlock ( ) ;
}
2019-07-10 17:28:33 +00:00
const auto msgId = prepareToSend (
toSendRequest ,
2019-11-19 16:14:50 +00:00
base : : unixtime : : mtproto_msg_id ( ) ,
2019-11-22 09:06:48 +00:00
forceNewMsgId & & ! bindDcKeyRequest ) ;
if ( bindDcKeyRequest ) {
_bindMsgId = msgId ;
2019-12-02 13:30:33 +00:00
_bindMessageSent = crl : : now ( ) ;
2019-11-22 09:06:48 +00:00
needAnyResponse = true ;
} else if ( pingRequest ) {
2015-03-12 10:28:10 +00:00
_pingMsgId = msgId ;
2014-11-05 17:43:32 +00:00
needAnyResponse = true ;
2019-12-02 11:34:14 +00:00
} else if ( stateRequest | | resendRequest ) {
_stateAndResendRequests . emplace (
msgId ,
stateRequest ? stateRequest : resendRequest ) ;
2014-11-05 17:43:32 +00:00
needAnyResponse = true ;
}
2014-05-30 08:53:19 +00:00
if ( toSendRequest - > requestId ) {
2018-06-25 18:55:27 +00:00
if ( toSendRequest . needAck ( ) ) {
2019-11-22 09:15:38 +00:00
toSendRequest - > lastSentTime = crl : : now ( ) ;
2014-05-30 08:53:19 +00:00
2019-11-14 07:13:17 +00:00
QWriteLocker locker2 ( _sessionData - > haveSentMutex ( ) ) ;
auto & haveSent = _sessionData - > haveSentMap ( ) ;
2019-11-22 09:15:38 +00:00
haveSent . emplace ( msgId , toSendRequest ) ;
2014-11-14 23:23:35 +00:00
2019-11-19 10:10:51 +00:00
const auto wrapLayer = needsLayer & & toSendRequest - > needsLayer ;
2014-11-05 17:43:32 +00:00
if ( toSendRequest - > after ) {
2019-11-05 10:23:09 +00:00
const auto toSendSize = tl : : count_length ( toSendRequest ) > > 2 ;
2019-11-22 09:15:38 +00:00
auto wrappedRequest = SerializedRequest : : Prepare (
2018-06-25 18:55:27 +00:00
toSendSize ,
toSendSize + 3 ) ;
2014-11-05 17:43:32 +00:00
wrappedRequest - > resize ( 4 ) ;
memcpy ( wrappedRequest - > data ( ) , toSendRequest - > constData ( ) , 4 * sizeof ( mtpPrime ) ) ;
2019-11-22 09:15:38 +00:00
WrapInvokeAfter ( wrappedRequest , toSendRequest , haveSent ) ;
2018-06-25 18:55:27 +00:00
toSendRequest = std : : move ( wrappedRequest ) ;
2014-11-05 17:43:32 +00:00
}
2019-11-19 10:10:51 +00:00
if ( wrapLayer ) {
2019-11-05 10:23:09 +00:00
const auto noWrapSize = ( tl : : count_length ( toSendRequest ) > > 2 ) ;
2018-06-25 18:55:27 +00:00
const auto toSendSize = noWrapSize + initSizeInInts ;
2019-11-22 09:15:38 +00:00
auto wrappedRequest = SerializedRequest : : Prepare ( toSendSize ) ;
2014-11-14 23:23:35 +00:00
memcpy ( wrappedRequest - > data ( ) , toSendRequest - > constData ( ) , 7 * sizeof ( mtpPrime ) ) ; // all except length
wrappedRequest - > push_back ( mtpc_invokeWithLayer ) ;
2019-12-02 13:10:19 +00:00
wrappedRequest - > push_back ( kCurrentLayer ) ;
2019-11-05 10:23:09 +00:00
initWrapper . write < mtpBuffer > ( * wrappedRequest ) ;
2014-11-14 23:23:35 +00:00
wrappedRequest - > resize ( wrappedRequest - > size ( ) + noWrapSize ) ;
memcpy ( wrappedRequest - > data ( ) + wrappedRequest - > size ( ) - noWrapSize , toSendRequest - > constData ( ) + 8 , noWrapSize * sizeof ( mtpPrime ) ) ;
2018-06-25 18:55:27 +00:00
toSendRequest = std : : move ( wrappedRequest ) ;
2014-11-14 23:23:35 +00:00
}
2014-05-30 08:53:19 +00:00
needAnyResponse = true ;
} else {
2019-11-22 09:06:48 +00:00
_ackedIds . emplace ( msgId , toSendRequest - > requestId ) ;
2014-05-30 08:53:19 +00:00
}
}
} else { // send in container
2014-11-14 23:23:35 +00:00
bool willNeedInit = false ;
2019-12-02 10:32:09 +00:00
uint32 containerSize = 1 + 1 ; // cons + vector size
2018-06-25 18:55:27 +00: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 ( ) ;
2019-11-19 10:10:51 +00:00
if ( bindDcKeyRequest ) containerSize + = bindDcKeyRequest . messageSize ( ) ;
2019-11-22 09:15:38 +00:00
for ( const auto & [ requestId , request ] : toSend ) {
containerSize + = request . messageSize ( ) ;
if ( needsLayer & & request - > needsLayer ) {
2014-11-14 23:23:35 +00:00
containerSize + = initSizeInInts ;
willNeedInit = true ;
}
}
mtpBuffer initSerialized ;
if ( willNeedInit ) {
initSerialized . reserve ( initSizeInInts ) ;
initSerialized . push_back ( mtpc_invokeWithLayer ) ;
2019-12-02 13:10:19 +00:00
initSerialized . push_back ( kCurrentLayer ) ;
2019-11-05 10:23:09 +00:00
initWrapper . write < mtpBuffer > ( initSerialized ) ;
2014-05-30 08:53:19 +00:00
}
2018-06-25 18:55:27 +00:00
// prepare container + each in invoke after
2019-11-22 09:15:38 +00:00
toSendRequest = SerializedRequest : : Prepare (
2018-06-25 18:55:27 +00:00
containerSize ,
containerSize + 3 * toSend . size ( ) ) ;
2014-05-30 08:53:19 +00:00
toSendRequest - > push_back ( mtpc_msg_container ) ;
toSendRequest - > push_back ( toSendCount ) ;
2019-07-10 17:28:33 +00:00
// check for a valid container
auto bigMsgId = base : : unixtime : : mtproto_msg_id ( ) ;
2014-08-01 11:09:46 +00:00
2018-06-25 18:55:27 +00:00
// the fact of this lock is used in replaceMsgId()
2019-11-14 07:13:17 +00:00
QWriteLocker locker2 ( _sessionData - > haveSentMutex ( ) ) ;
auto & haveSent = _sessionData - > haveSentMap ( ) ;
2014-05-30 08:53:19 +00:00
2019-12-02 10:32:09 +00:00
// prepare sent container
auto sentIdsWrap = SentContainer ( ) ;
sentIdsWrap . sent = crl : : now ( ) ;
sentIdsWrap . messages . reserve ( toSendCount ) ;
2014-05-30 08:53:19 +00:00
2019-11-22 09:06:48 +00:00
if ( bindDcKeyRequest ) {
_bindMsgId = placeToContainer (
toSendRequest ,
bigMsgId ,
false ,
bindDcKeyRequest ) ;
2019-12-02 13:30:33 +00:00
_bindMessageSent = crl : : now ( ) ;
2019-11-22 09:06:48 +00:00
needAnyResponse = true ;
}
2014-11-05 17:43:32 +00:00
if ( pingRequest ) {
2019-11-19 16:14:50 +00:00
_pingMsgId = placeToContainer (
toSendRequest ,
bigMsgId ,
forceNewMsgId ,
pingRequest ) ;
2014-11-05 17:43:32 +00:00
needAnyResponse = true ;
2019-11-22 09:06:48 +00:00
}
2019-12-02 11:34:14 +00:00
2019-11-22 09:15:38 +00:00
for ( auto & [ requestId , request ] : toSend ) {
2019-11-19 16:14:50 +00:00
const auto msgId = prepareToSend (
2019-11-22 09:15:38 +00:00
request ,
2019-11-19 16:14:50 +00:00
bigMsgId ,
forceNewMsgId ) ;
2019-07-10 17:28:33 +00:00
if ( msgId > = bigMsgId ) {
bigMsgId = base : : unixtime : : mtproto_msg_id ( ) ;
}
2014-11-05 17:43:32 +00:00
bool added = false ;
2019-11-22 09:15:38 +00:00
if ( request - > requestId ) {
if ( request . needAck ( ) ) {
request - > lastSentTime = crl : : now ( ) ;
int32 reqNeedsLayer = ( needsLayer & & request - > needsLayer ) ? toSendRequest - > size ( ) : 0 ;
if ( request - > after ) {
WrapInvokeAfter ( toSendRequest , request , haveSent , reqNeedsLayer ? initSizeInInts : 0 ) ;
2014-11-14 23:23:35 +00:00
if ( reqNeedsLayer ) {
memcpy ( toSendRequest - > data ( ) + reqNeedsLayer + 4 , initSerialized . constData ( ) , initSize ) ;
* ( toSendRequest - > data ( ) + reqNeedsLayer + 3 ) + = initSize ;
}
added = true ;
} else if ( reqNeedsLayer ) {
2019-11-22 09:15:38 +00:00
toSendRequest - > resize ( reqNeedsLayer + initSizeInInts + request . messageSize ( ) ) ;
memcpy ( toSendRequest - > data ( ) + reqNeedsLayer , request - > constData ( ) + 4 , 4 * sizeof ( mtpPrime ) ) ;
2014-11-14 23:23:35 +00:00
memcpy ( toSendRequest - > data ( ) + reqNeedsLayer + 4 , initSerialized . constData ( ) , initSize ) ;
2019-11-22 09:15:38 +00:00
memcpy ( toSendRequest - > data ( ) + reqNeedsLayer + 4 + initSizeInInts , request - > constData ( ) + 8 , tl : : count_length ( request ) ) ;
2014-11-14 23:23:35 +00:00
* ( toSendRequest - > data ( ) + reqNeedsLayer + 3 ) + = initSize ;
2014-11-05 17:43:32 +00:00
added = true ;
}
2019-12-02 10:49:33 +00:00
2019-12-31 14:26:05 +00:00
// #TODO rewrite so that it will always hold.
//Assert(!haveSent.contains(msgId));
2019-11-22 09:15:38 +00:00
haveSent . emplace ( msgId , request ) ;
2019-12-02 10:49:33 +00:00
sentIdsWrap . messages . push_back ( msgId ) ;
2014-05-30 08:53:19 +00:00
needAnyResponse = true ;
} else {
2019-11-22 09:15:38 +00:00
_ackedIds . emplace ( msgId , request - > requestId ) ;
2014-05-30 08:53:19 +00:00
}
}
2014-11-05 17:43:32 +00:00
if ( ! added ) {
2019-11-22 09:15:38 +00:00
uint32 from = toSendRequest - > size ( ) , len = request . messageSize ( ) ;
2014-11-05 17:43:32 +00:00
toSendRequest - > resize ( from + len ) ;
2019-11-22 09:15:38 +00:00
memcpy ( toSendRequest - > data ( ) + from , request - > constData ( ) + 4 , len * sizeof ( mtpPrime ) ) ;
2014-11-05 17:43:32 +00:00
}
}
2019-12-02 11:34:14 +00:00
toSend . clear ( ) ;
2014-11-05 17:43:32 +00:00
if ( stateRequest ) {
2019-12-02 10:32:09 +00:00
const auto msgId = placeToContainer (
toSendRequest ,
bigMsgId ,
forceNewMsgId ,
stateRequest ) ;
2019-12-02 11:34:14 +00:00
_stateAndResendRequests . emplace ( msgId , stateRequest ) ;
2019-12-02 10:49:33 +00:00
needAnyResponse = true ;
2014-05-30 08:53:19 +00:00
}
2019-12-02 10:32:09 +00:00
if ( resendRequest ) {
2019-12-02 10:49:33 +00:00
const auto msgId = placeToContainer (
2019-12-02 10:32:09 +00:00
toSendRequest ,
bigMsgId ,
forceNewMsgId ,
resendRequest ) ;
2019-12-02 11:34:14 +00:00
_stateAndResendRequests . emplace ( msgId , resendRequest ) ;
2019-12-02 10:49:33 +00:00
needAnyResponse = true ;
2019-12-02 10:32:09 +00:00
}
if ( ackRequest ) {
placeToContainer (
toSendRequest ,
bigMsgId ,
forceNewMsgId ,
ackRequest ) ;
}
if ( httpWaitRequest ) {
placeToContainer (
toSendRequest ,
bigMsgId ,
forceNewMsgId ,
httpWaitRequest ) ;
}
2014-05-30 08:53:19 +00:00
2019-11-19 16:14:50 +00:00
const auto containerMsgId = prepareToSend (
toSendRequest ,
bigMsgId ,
forceNewMsgId ) ;
2019-12-02 10:32:09 +00:00
_sentContainers . emplace ( containerMsgId , std : : move ( sentIdsWrap ) ) ;
2014-05-30 08:53:19 +00:00
}
}
2019-11-18 12:53:37 +00:00
sendSecureRequest ( std : : move ( toSendRequest ) , needAnyResponse ) ;
2014-05-30 08:53:19 +00:00
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : retryByTimer ( ) {
2018-04-24 19:09:20 +00:00
if ( _retryTimeout < 3 ) {
+ + _retryTimeout ;
} else if ( _retryTimeout = = 3 ) {
_retryTimeout = 1000 ;
} else if ( _retryTimeout < 64000 ) {
_retryTimeout * = 2 ;
2014-05-30 08:53:19 +00:00
}
2017-03-23 16:11:35 +00:00
connectToServer ( ) ;
2014-05-30 08:53:19 +00:00
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : restartNow ( ) {
2018-04-24 19:09:20 +00:00
_retryTimeout = 1 ;
_retryTimer . cancel ( ) ;
2014-05-30 08:53:19 +00:00
restart ( ) ;
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : connectToServer ( bool afterConfig ) {
2019-11-27 14:22:22 +00:00
if ( afterConfig & & ( ! _testConnections . empty ( ) | | _connection ) ) {
2019-11-21 10:37:39 +00:00
return ;
}
destroyAllConnections ( ) ;
if ( realDcTypeChanged ( ) & & _keyCreator ) {
destroyTemporaryKey ( ) ;
return ;
2016-02-29 16:53:26 +00:00
}
2019-11-14 07:13:17 +00:00
2019-12-02 13:10:19 +00:00
_options = std : : make_unique < SessionOptions > ( _sessionData - > options ( ) ) ;
2019-11-18 12:53:37 +00:00
2019-11-14 07:13:17 +00:00
const auto bareDc = BareDcId ( _shiftedDcId ) ;
2018-04-24 08:46:27 +00:00
2019-11-21 10:37:39 +00:00
_currentDcType = tryAcquireKeyCreation ( ) ;
if ( _currentDcType = = DcType : : Cdn & & ! _instance - > isKeysDestroyer ( ) ) {
2017-06-26 17:38:16 +00:00
if ( ! _instance - > dcOptions ( ) - > hasCDNKeysForDc ( bareDc ) ) {
2017-03-23 16:11:35 +00:00
requestCDNConfig ( ) ;
return ;
2015-05-14 16:50:04 +00:00
}
}
2019-12-02 13:10:19 +00:00
if ( _options - > proxy . type = = ProxyData : : Type : : Mtproto ) {
2018-05-17 19:58:00 +00:00
// host, port, secret for mtproto proxy are taken from proxy.
appendTestConnection ( DcOptions : : Variants : : Tcp , { } , 0 , { } ) ;
2018-04-24 19:09:20 +00:00
} else {
using Variants = DcOptions : : Variants ;
2019-11-21 10:37:39 +00:00
const auto special = ( _currentDcType = = DcType : : Temporary ) ;
2018-04-24 19:09:20 +00:00
const auto variants = _instance - > dcOptions ( ) - > lookup (
bareDc ,
2019-11-21 10:37:39 +00:00
_currentDcType ,
2019-12-02 13:10:19 +00:00
_options - > proxy . type ! = ProxyData : : Type : : None ) ;
const auto useIPv4 = special ? true : _options - > useIPv4 ;
const auto useIPv6 = special ? false : _options - > useIPv6 ;
const auto useTcp = special ? true : _options - > useTcp ;
const auto useHttp = special ? false : _options - > useHttp ;
2018-04-24 19:09:20 +00:00
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 19:07:34 +00:00
endpoint . secret ) ;
2018-04-24 19:09:20 +00:00
}
}
}
}
if ( _testConnections . empty ( ) ) {
2017-02-25 16:44:02 +00:00
if ( _instance - > isKeysDestroyer ( ) ) {
2018-04-24 19:09:20 +00:00
LOG ( ( " MTP Error: DC %1 options for not found for auth key destruction! " ) . arg ( _shiftedDcId ) ) ;
2019-11-20 13:33:45 +00:00
_instance - > keyWasPossiblyDestroyed ( _shiftedDcId ) ;
2017-02-25 16:44:02 +00:00
return ;
} else if ( afterConfig ) {
2018-04-24 19:09:20 +00:00
LOG ( ( " MTP Error: DC %1 options for not found right after config load! " ) . arg ( _shiftedDcId ) ) ;
2014-05-30 08:53:19 +00:00
return restart ( ) ;
}
2018-04-24 19:09:20 +00:00
DEBUG_LOG ( ( " MTP Info: DC %1 options not found, waiting for config " ) . arg ( _shiftedDcId ) ) ;
2018-04-24 07:21:19 +00:00
InvokeQueued ( _instance , [ instance = _instance ] {
instance - > requestConfig ( ) ;
} ) ;
2015-05-14 16:50:04 +00:00
return ;
2014-05-30 08:53:19 +00:00
}
2018-05-28 08:36:12 +00:00
DEBUG_LOG ( ( " Connection Info: Connecting to %1 with %2 test connections. "
) . arg ( _shiftedDcId
) . arg ( _testConnections . size ( ) ) ) ;
2014-05-30 08:53:19 +00:00
2018-05-02 19:07:34 +00:00
if ( ! _startedConnectingAt ) {
2019-02-19 06:57:53 +00:00
_startedConnectingAt = crl : : now ( ) ;
} else if ( crl : : now ( ) - _startedConnectingAt > kRequestConfigTimeout ) {
2018-04-24 07:21:19 +00:00
InvokeQueued ( _instance , [ instance = _instance ] {
instance - > requestConfigIfOld ( ) ;
} ) ;
}
2015-06-10 12:48:26 +00:00
2018-04-24 19:09:20 +00:00
_retryTimer . cancel ( ) ;
_waitForConnectedTimer . cancel ( ) ;
2015-06-10 12:48:26 +00:00
2016-03-24 08:57:11 +00:00
setState ( ConnectingState ) ;
2019-11-18 12:53:37 +00:00
2019-11-22 09:06:48 +00:00
_bindMsgId = 0 ;
2015-06-10 12:48:26 +00:00
_pingId = _pingMsgId = _pingIdToSend = _pingSendAt = 0 ;
2018-04-24 19:09:20 +00:00
_pingSender . cancel ( ) ;
_waitForConnectedTimer . callOnce ( _waitForConnected ) ;
2014-05-30 08:53:19 +00:00
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : restart ( ) {
2017-02-25 16:44:02 +00:00
DEBUG_LOG ( ( " MTP Info: restarting Connection " ) ) ;
2014-05-30 08:53:19 +00:00
2018-04-24 19:09:20 +00:00
_waitForReceivedTimer . cancel ( ) ;
_waitForConnectedTimer . cancel ( ) ;
2014-05-30 08:53:19 +00:00
doDisconnect ( ) ;
2015-08-08 09:14:47 +00:00
2019-11-18 12:53:37 +00:00
if ( _needSessionReset ) {
2014-08-01 11:09:46 +00:00
resetSession ( ) ;
}
2019-11-18 12:53:37 +00:00
if ( _retryTimer . isActive ( ) ) {
return ;
}
2014-05-30 08:53:19 +00:00
2018-04-24 19:09:20 +00:00
DEBUG_LOG ( ( " MTP Info: restart timeout: %1ms " ) . arg ( _retryTimeout ) ) ;
2019-11-18 12:53:37 +00:00
2018-04-24 19:09:20 +00:00
setState ( - _retryTimeout ) ;
2014-05-30 08:53:19 +00:00
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : onSentSome ( uint64 size ) {
2015-06-10 12:48:26 +00:00
if ( ! _waitForReceivedTimer . isActive ( ) ) {
2017-03-23 16:11:35 +00:00
auto remain = static_cast < uint64 > ( _waitForReceived ) ;
2018-04-24 19:09:20 +00: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 12:48:26 +00:00
if ( remain ! = _waitForReceived ) {
2014-05-30 08:53:19 +00:00
DEBUG_LOG ( ( " Checking connect for request with size %1 bytes, delay will be %2 " ) . arg ( size ) . arg ( remain ) ) ;
}
}
2017-02-25 16:44:02 +00:00
if ( isUploadDcId ( _shiftedDcId ) ) {
2017-03-23 16:11:35 +00:00
remain * = kUploadSessionsCount ;
2014-10-30 16:23:44 +00:00
}
2018-04-24 19:09:20 +00:00
_waitForReceivedTimer . callOnce ( remain ) ;
2014-05-30 08:53:19 +00:00
}
2019-12-05 11:46:28 +00:00
if ( ! _firstSentAt ) {
_firstSentAt = crl : : now ( ) ;
}
2014-05-30 08:53:19 +00:00
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : onReceivedSome ( ) {
2018-04-24 19:09:20 +00:00
if ( _oldConnection ) {
_oldConnection = false ;
2014-05-30 08:53:19 +00:00
DEBUG_LOG ( ( " This connection marked as not old! " ) ) ;
}
2018-04-24 19:09:20 +00:00
_oldConnectionTimer . callOnce ( kMarkConnectionOldTimeout ) ;
_waitForReceivedTimer . cancel ( ) ;
2019-11-14 07:13:17 +00:00
if ( _firstSentAt > 0 ) {
const auto ms = crl : : now ( ) - _firstSentAt ;
2019-12-05 11:46:28 +00:00
DEBUG_LOG ( ( " MTP Info: response in %1ms, _waitForReceived: %2ms "
) . arg ( ms
) . arg ( _waitForReceived ) ) ;
2014-05-30 08:53:19 +00:00
2018-05-17 19:58:00 +00:00
if ( ms > 0 & & ms * 2 < _waitForReceived ) {
_waitForReceived = qMax ( ms * 2 , kMinReceiveTimeout ) ;
2018-04-24 19:09:20 +00:00
}
2019-11-14 07:13:17 +00:00
_firstSentAt = - 1 ;
2014-05-30 08:53:19 +00:00
}
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : markConnectionOld ( ) {
2018-04-24 19:09:20 +00:00
_oldConnection = true ;
_waitForReceived = kMinReceiveTimeout ;
2019-12-05 11:46:28 +00:00
DEBUG_LOG ( ( " This connection marked as old! _waitForReceived now %1ms "
) . arg ( _waitForReceived ) ) ;
2014-05-30 08:53:19 +00:00
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : sendPingByTimer ( ) {
2015-03-12 10:28:10 +00:00
if ( _pingId ) {
2018-06-04 19:48:17 +00:00
// _pingSendAt: when to send next ping (lastPingAt + kPingSendAfter)
// could be equal to zero.
2019-02-19 06:57:53 +00:00
const auto now = crl : : now ( ) ;
2018-06-04 19:48:17 +00:00
const auto mustSendTill = _pingSendAt
+ kPingSendAfterForce
- kPingSendAfter ;
if ( mustSendTill < now + 1000 ) {
2018-04-24 19:09:20 +00:00
LOG ( ( " Could not send ping for some seconds, restarting... " ) ) ;
2015-03-12 10:28:10 +00:00
return restart ( ) ;
} else {
2018-06-04 19:48:17 +00:00
_pingSender . callOnce ( mustSendTill - now ) ;
2015-03-12 10:28:10 +00:00
}
} else {
2019-11-18 12:53:37 +00:00
_sessionData - > queueNeedToResumeAndSend ( ) ;
2015-03-12 10:28:10 +00:00
}
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : sendPingForce ( ) {
2019-12-02 09:40:53 +00:00
DEBUG_LOG ( ( " MTP Info: send ping force for dcWithShift %1. " ) . arg ( _shiftedDcId ) ) ;
2015-04-16 14:59:42 +00:00
if ( ! _pingId ) {
_pingSendAt = 0 ;
DEBUG_LOG ( ( " Will send ping! " ) ) ;
tryToSend ( ) ;
}
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : waitReceivedFailed ( ) {
Expects ( _options ! = nullptr ) ;
2018-04-24 08:46:27 +00:00
2015-06-10 12:48:26 +00:00
DEBUG_LOG ( ( " MTP Info: bad connection, _waitForReceived: %1ms " ) . arg ( _waitForReceived ) ) ;
2018-04-24 19:09:20 +00:00
if ( _waitForReceived < kMaxReceiveTimeout ) {
2015-06-10 12:48:26 +00:00
_waitForReceived * = 2 ;
2014-05-30 08:53:19 +00:00
}
doDisconnect ( ) ;
2018-04-24 19:09:20 +00:00
if ( _retryTimer . isActive ( ) ) {
return ;
}
2014-05-30 08:53:19 +00:00
DEBUG_LOG ( ( " MTP Info: immediate restart! " ) ) ;
2018-05-17 19:58:00 +00:00
InvokeQueued ( this , [ = ] { connectToServer ( ) ; } ) ;
2019-12-05 11:46:28 +00:00
const auto instance = _instance ;
const auto shiftedDcId = _shiftedDcId ;
InvokeQueued ( instance , [ = ] {
instance - > restartedByTimeout ( shiftedDcId ) ;
} ) ;
2014-05-30 08:53:19 +00:00
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : waitConnectedFailed ( ) {
2015-06-10 12:48:26 +00:00
DEBUG_LOG ( ( " MTP Info: can't connect in %1ms " ) . arg ( _waitForConnected ) ) ;
2018-05-17 19:58:00 +00: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 19:09:20 +00:00
}
2015-06-02 11:22:00 +00:00
2019-07-10 15:03:48 +00:00
connectingTimedOut ( ) ;
2015-06-02 11:22:00 +00:00
DEBUG_LOG ( ( " MTP Info: immediate restart! " ) ) ;
2018-05-17 19:58:00 +00:00
InvokeQueued ( this , [ = ] { connectToServer ( ) ; } ) ;
2015-06-02 11:22:00 +00:00
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : waitBetterFailed ( ) {
2018-04-24 19:09:20 +00:00
confirmBestConnection ( ) ;
2015-06-10 12:48:26 +00:00
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : connectingTimedOut ( ) {
2019-07-10 15:03:48 +00:00
for ( const auto & connection : _testConnections ) {
connection . data - > timedOut ( ) ;
}
doDisconnect ( ) ;
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : doDisconnect ( ) {
2018-04-23 10:24:03 +00:00
destroyAllConnections ( ) ;
2016-03-24 08:57:11 +00:00
setState ( DisconnectedState ) ;
2014-05-30 08:53:19 +00:00
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : requestCDNConfig ( ) {
2018-05-17 19:58:00 +00:00
InvokeQueued ( _instance , [ instance = _instance ] {
instance - > requestCDNConfig ( ) ;
} ) ;
2017-03-23 16:11:35 +00:00
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : handleReceived ( ) {
2019-11-20 11:50:19 +00:00
Expects ( _encryptionKey ! = nullptr ) ;
2019-11-19 16:14:50 +00:00
2014-05-30 08:53:19 +00:00
onReceivedSome ( ) ;
2018-04-24 19:09:20 +00:00
while ( ! _connection - > received ( ) . empty ( ) ) {
auto intsBuffer = std : : move ( _connection - > received ( ) . front ( ) ) ;
_connection - > received ( ) . pop_front ( ) ;
2015-08-08 09:14:47 +00:00
2017-02-27 09:51:03 +00: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 08:58:56 +00:00
if ( ( intsCount < kMinimalIntsCount ) | | ( intsCount > kMaxMessageLength / kIntSize ) ) {
2017-02-27 09:51:03 +00: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 ( ) ) ) ;
2019-11-18 12:53:37 +00:00
return restart ( ) ;
2014-05-30 08:53:19 +00:00
}
2019-11-14 07:13:17 +00: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 09:51:03 +00:00
TCP_LOG ( ( " TCP Error: bad message %1 " ) . arg ( Logs : : mb ( ints , intsCount * kIntSize ) . str ( ) ) ) ;
2015-08-08 09:14:47 +00:00
2019-11-18 12:53:37 +00:00
return restart ( ) ;
2014-05-30 08:53:19 +00:00
}
2017-02-27 09:51:03 +00:00
auto encryptedInts = ints + kExternalHeaderIntsCount ;
2018-06-25 21:18:27 +00:00
auto encryptedIntsCount = ( intsCount - kExternalHeaderIntsCount ) & ~ 0x03U ;
2017-02-27 09:51:03 +00:00
auto encryptedBytesCount = encryptedIntsCount * kIntSize ;
auto decryptedBuffer = QByteArray ( encryptedBytesCount , Qt : : Uninitialized ) ;
auto msgKey = * ( MTPint128 * ) ( ints + 2 ) ;
2016-01-11 15:43:29 +00:00
2016-12-31 08:58:56 +00:00
# ifdef TDESKTOP_MTPROTO_OLD
2019-11-20 11:50:19 +00:00
aesIgeDecrypt_oldmtp ( encryptedInts , decryptedBuffer . data ( ) , encryptedBytesCount , _encryptionKey , msgKey ) ;
2016-12-31 08:58:56 +00:00
# else // TDESKTOP_MTPROTO_OLD
2019-11-20 11:50:19 +00:00
aesIgeDecrypt ( encryptedInts , decryptedBuffer . data ( ) , encryptedBytesCount , _encryptionKey , msgKey ) ;
2016-12-31 08:58:56 +00:00
# endif // TDESKTOP_MTPROTO_OLD
2014-05-30 08:53:19 +00:00
2017-02-27 09:51:03 +00: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 08:53:19 +00:00
2017-02-27 09:51:03 +00:00
auto messageLength = * ( uint32 * ) & decryptedInts [ 7 ] ;
2016-12-31 08:58:56 +00: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 ( ) ) ) ;
2019-11-18 12:53:37 +00:00
return restart ( ) ;
2016-12-31 08:58:56 +00:00
}
2017-02-27 09:51:03 +00:00
auto fullDataLength = kEncryptedHeaderIntsCount * kIntSize + messageLength ; // Without padding.
2015-08-08 09:14:47 +00:00
2016-12-31 08:58:56 +00: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 09:51:03 +00:00
auto hashedDataLength = badMessageLength ? encryptedBytesCount : fullDataLength ;
auto sha1ForMsgKeyCheck = hashSha1 ( decryptedInts , hashedDataLength ) ;
2016-12-31 08:58:56 +00:00
constexpr auto kMsgKeyShift_oldmtp = 4U ;
if ( memcmp ( & msgKey , sha1ForMsgKeyCheck . data ( ) + kMsgKeyShift_oldmtp , sizeof ( msgKey ) ) ! = 0 ) {
2017-02-27 09:51:03 +00:00
LOG ( ( " TCP Error: bad SHA1 hash after aesDecrypt in message. " ) ) ;
TCP_LOG ( ( " TCP Error: bad message %1 " ) . arg ( Logs : : mb ( encryptedInts , encryptedBytesCount ) . str ( ) ) ) ;
2019-11-18 12:53:37 +00:00
return restart ( ) ;
2014-05-30 08:53:19 +00:00
}
2016-12-31 08:58:56 +00: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 ) ;
2019-11-20 11:50:19 +00:00
SHA256_Update ( & msgKeyLargeContext , _encryptionKey - > partForMsgKey ( false ) , 32 ) ;
2016-12-31 08:58:56 +00:00
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 ( ) ) ) ;
2019-11-18 12:53:37 +00:00
return restart ( ) ;
2016-12-31 08:58:56 +00:00
}
# endif // TDESKTOP_MTPROTO_OLD
2017-02-27 09:51:03 +00: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 09:14:47 +00:00
2019-11-18 12:53:37 +00:00
return restart ( ) ;
2014-05-30 08:53:19 +00:00
}
2017-02-27 09:51:03 +00: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 08:53:19 +00:00
2019-11-20 10:41:14 +00:00
if ( session ! = _sessionId ) {
2014-05-30 08:53:19 +00:00
LOG ( ( " MTP Error: bad server session received " ) ) ;
2019-11-20 10:41:14 +00:00
TCP_LOG ( ( " MTP Error: bad server session %1 instead of %2 in message received " ) . arg ( session ) . arg ( _sessionId ) ) ;
2015-08-08 09:14:47 +00:00
2019-11-18 12:53:37 +00:00
return restart ( ) ;
2014-05-30 08:53:19 +00:00
}
2019-07-10 17:28:33 +00:00
const auto serverTime = int32 ( msgId > > 32 ) ;
const auto isReply = ( ( msgId & 0x03 ) = = 1 ) ;
2014-05-30 08:53:19 +00:00
if ( ! isReply & & ( ( msgId & 0x03 ) ! = 3 ) ) {
LOG ( ( " MTP Error: bad msg_id %1 in message received " ) . arg ( msgId ) ) ;
2015-08-08 09:14:47 +00:00
2019-11-18 12:53:37 +00:00
return restart ( ) ;
2014-05-30 08:53:19 +00:00
}
2019-11-20 14:23:39 +00:00
const auto clientTime = base : : unixtime : : now ( ) ;
const auto badTime = ( serverTime > clientTime + 60 )
| | ( serverTime + 300 < clientTime ) ;
if ( badTime ) {
2014-05-30 08:53:19 +00:00
DEBUG_LOG ( ( " MTP Info: bad server time from msg_id: %1, my time: %2 " ) . arg ( serverTime ) . arg ( clientTime ) ) ;
}
2016-03-24 08:57:11 +00:00
bool wasConnected = ( getState ( ) = = ConnectedState ) ;
2019-11-20 10:41:14 +00:00
if ( serverSalt ! = _sessionSalt ) {
2014-05-30 08:53:19 +00:00
if ( ! badTime ) {
2019-11-20 10:41:14 +00:00
DEBUG_LOG ( ( " MTP Info: other salt received... received: %1, my salt: %2, updating... " ) . arg ( serverSalt ) . arg ( _sessionSalt ) ) ;
_sessionSalt = serverSalt ;
2019-11-18 12:53:37 +00:00
2019-11-19 16:14:50 +00:00
if ( setState ( ConnectedState , ConnectingState ) ) {
2019-11-22 09:06:48 +00:00
resendAll ( ) ;
2014-05-30 08:53:19 +00:00
}
} else {
2019-11-20 10:41:14 +00:00
DEBUG_LOG ( ( " MTP Info: other salt received... received: %1, my salt: %2 " ) . arg ( serverSalt ) . arg ( _sessionSalt ) ) ;
2014-05-30 08:53:19 +00:00
}
} else {
serverSalt = 0 ; // dont pass to handle method, so not to lock in setSalt()
}
2019-11-14 07:13:17 +00:00
if ( needAck ) _ackRequestData . push_back ( MTP_long ( msgId ) ) ;
2014-05-30 08:53:19 +00:00
2016-12-07 13:32:25 +00:00
auto res = HandleResult : : Success ; // if no need to handle, then succeed
2017-02-27 09:51:03 +00:00
auto from = decryptedInts + kEncryptedHeaderIntsCount ;
auto end = from + ( messageLength / kIntSize ) ;
auto sfrom = decryptedInts + 4U ; // msg_id + seq_no + length + message
2019-11-21 10:37:39 +00:00
MTP_LOG ( _shiftedDcId , ( " Recv: " )
2019-12-02 13:10:19 +00:00
+ DumpToText ( sfrom , end )
2019-11-21 10:37:39 +00:00
+ QString ( " (protocolDcId:%1,key:%2) "
) . arg ( getProtocolDcId ( )
) . arg ( _encryptionKey - > keyId ( ) ) ) ;
2014-05-30 08:53:19 +00:00
2019-11-20 10:41:14 +00:00
if ( _receivedMessageIds . registerMsgId ( msgId , needAck ) ) {
2014-05-30 08:53:19 +00:00
res = handleOneReceived ( from , end , msgId , serverTime , serverSalt , badTime ) ;
}
2019-11-20 10:41:14 +00:00
_receivedMessageIds . shrink ( ) ;
2014-05-30 08:53:19 +00:00
// send acks
2019-11-18 12:53:37 +00:00
if ( const auto toAckSize = _ackRequestData . size ( ) ) {
2019-11-14 07:13:17 +00:00
DEBUG_LOG ( ( " MTP Info: will send %1 acks, ids: %2 " ) . arg ( toAckSize ) . arg ( LogIdsVector ( _ackRequestData ) ) ) ;
2019-11-18 12:53:37 +00:00
_sessionData - > queueSendAnything ( kAckSendWaiting ) ;
2014-05-30 08:53:19 +00:00
}
2019-11-18 12:53:37 +00:00
auto lock = QReadLocker ( _sessionData - > haveReceivedMutex ( ) ) ;
2019-11-22 09:15:38 +00:00
const auto tryToReceive = ! _sessionData - > haveReceivedResponses ( ) . empty ( )
| | ! _sessionData - > haveReceivedUpdates ( ) . empty ( ) ;
2019-11-18 12:53:37 +00:00
lock . unlock ( ) ;
2016-01-11 15:43:29 +00:00
2019-11-18 12:53:37 +00:00
if ( tryToReceive ) {
DEBUG_LOG ( ( " MTP Info: queueTryToReceive() - need to parse in another thread, %1 responses, %2 updates. " ) . arg ( _sessionData - > haveReceivedResponses ( ) . size ( ) ) . arg ( _sessionData - > haveReceivedUpdates ( ) . size ( ) ) ) ;
_sessionData - > queueTryToReceive ( ) ;
2014-05-30 08:53:19 +00:00
}
2016-12-07 13:32:25 +00:00
if ( res ! = HandleResult : : Success & & res ! = HandleResult : : Ignored ) {
2019-11-19 10:10:51 +00:00
if ( res = = HandleResult : : DestroyTemporaryKey ) {
destroyTemporaryKey ( ) ;
2019-11-19 16:14:50 +00:00
} else if ( res = = HandleResult : : ResetSession ) {
_needSessionReset = true ;
2019-11-19 10:10:51 +00:00
}
2019-11-18 12:53:37 +00:00
return restart ( ) ;
2014-05-30 08:53:19 +00:00
}
2018-04-24 19:09:20 +00:00
_retryTimeout = 1 ; // reset restart() timer
2014-05-30 08:53:19 +00:00
2019-02-19 06:57:53 +00:00
_startedConnectingAt = crl : : time ( 0 ) ;
2014-05-30 08:53:19 +00:00
if ( ! wasConnected ) {
2016-03-24 08:57:11 +00:00
if ( getState ( ) = = ConnectedState ) {
2019-11-18 12:53:37 +00:00
_sessionData - > queueNeedToResumeAndSend ( ) ;
2014-05-30 08:53:19 +00:00
}
}
}
2018-04-24 19:09:20 +00:00
if ( _connection - > needHttpWait ( ) ) {
2019-11-18 12:53:37 +00:00
_sessionData - > queueSendAnything ( ) ;
2014-05-30 08:53:19 +00:00
}
}
2019-12-02 13:10:19 +00:00
SessionPrivate : : HandleResult SessionPrivate : : handleOneReceived (
2019-11-22 09:06:48 +00:00
const mtpPrime * from ,
const mtpPrime * end ,
uint64 msgId ,
int32 serverTime ,
uint64 serverSalt ,
bool badTime ) {
Expects ( from < end ) ;
2014-05-30 08:53:19 +00:00
2019-11-22 09:06:48 +00:00
switch ( mtpTypeId ( * from ) ) {
2014-05-30 08:53:19 +00:00
case mtpc_gzip_packed : {
DEBUG_LOG ( ( " Message Info: gzip container " ) ) ;
mtpBuffer response = ungzip ( + + from , end ) ;
2019-01-17 07:17:44 +00:00
if ( response . empty ( ) ) {
2016-12-07 13:32:25 +00:00
return HandleResult : : RestartConnection ;
2014-05-30 08:53:19 +00:00
}
return handleOneReceived ( response . data ( ) , response . data ( ) + response . size ( ) , msgId , serverTime , serverSalt , badTime ) ;
}
case mtpc_msg_container : {
2019-07-18 14:06:38 +00:00
if ( + + from > = end ) {
return HandleResult : : ParseError ;
}
2014-05-30 08:53:19 +00:00
const mtpPrime * otherEnd ;
2019-07-18 14:06:38 +00:00
const auto msgsCount = ( uint32 ) * ( from + + ) ;
2014-05-30 08:53:19 +00:00
DEBUG_LOG ( ( " Message Info: container received, count: %1 " ) . arg ( msgsCount ) ) ;
for ( uint32 i = 0 ; i < msgsCount ; + + i ) {
2019-07-18 14:06:38 +00:00
if ( from + 4 > = end ) {
return HandleResult : : ParseError ;
}
2014-05-30 08:53:19 +00:00
otherEnd = from + 4 ;
2017-03-09 19:15:31 +00:00
MTPlong inMsgId ;
2019-07-18 14:06:38 +00:00
if ( ! inMsgId . read ( from , otherEnd ) ) {
return HandleResult : : ParseError ;
}
2014-05-30 08:53:19 +00: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 13:32:25 +00:00
return HandleResult : : RestartConnection ;
2014-05-30 08:53:19 +00:00
}
2017-03-09 19:15:31 +00:00
MTPint inSeqNo ;
2019-07-18 14:06:38 +00:00
if ( ! inSeqNo . read ( from , otherEnd ) ) {
return HandleResult : : ParseError ;
}
2017-03-09 19:15:31 +00:00
MTPint bytes ;
2019-07-18 14:06:38 +00:00
if ( ! bytes . read ( from , otherEnd ) ) {
return HandleResult : : ParseError ;
}
2014-05-30 08:53:19 +00:00
if ( ( bytes . v & 0x03 ) | | bytes . v < 4 ) {
LOG ( ( " Message Error: bad length %1 of contained message received " ) . arg ( bytes . v ) ) ;
2016-12-07 13:32:25 +00:00
return HandleResult : : RestartConnection ;
2014-05-30 08:53:19 +00:00
}
bool needAck = ( inSeqNo . v & 0x01 ) ;
2019-11-14 07:13:17 +00:00
if ( needAck ) _ackRequestData . push_back ( inMsgId ) ;
2014-05-30 08:53:19 +00:00
2016-01-11 15:43:29 +00:00
DEBUG_LOG ( ( " Message Info: message from container, msg_id: %1, needAck: %2 " ) . arg ( inMsgId . v ) . arg ( Logs : : b ( needAck ) ) ) ;
2014-05-30 08:53:19 +00:00
otherEnd = from + ( bytes . v > > 2 ) ;
2019-07-18 14:06:38 +00:00
if ( otherEnd > end ) {
return HandleResult : : ParseError ;
}
2014-05-30 08:53:19 +00:00
2016-12-07 13:32:25 +00:00
auto res = HandleResult : : Success ; // if no need to handle, then succeed
2019-11-20 10:41:14 +00:00
if ( _receivedMessageIds . registerMsgId ( inMsgId . v , needAck ) ) {
2014-05-30 08:53:19 +00:00
res = handleOneReceived ( from , otherEnd , inMsgId . v , serverTime , serverSalt , badTime ) ;
badTime = false ;
}
2016-12-07 13:32:25 +00:00
if ( res ! = HandleResult : : Success ) {
2014-05-30 08:53:19 +00:00
return res ;
}
from = otherEnd ;
}
2016-12-07 13:32:25 +00:00
} return HandleResult : : Success ;
2014-05-30 08:53:19 +00:00
case mtpc_msgs_ack : {
2017-03-09 19:15:31 +00:00
MTPMsgsAck msg ;
2019-07-18 14:06:38 +00:00
if ( ! msg . read ( from , end ) ) {
return HandleResult : : ParseError ;
}
2019-11-22 09:06:48 +00:00
const auto & ids = msg . c_msgs_ack ( ) . vmsg_ids ( ) . v ;
DEBUG_LOG ( ( " Message Info: acks received, ids: %1 "
) . arg ( LogIdsVector ( ids ) ) ) ;
if ( ids . isEmpty ( ) ) {
return badTime ? HandleResult : : Ignored : HandleResult : : Success ;
}
2014-05-30 08:53:19 +00:00
2019-11-22 09:06:48 +00:00
if ( badTime & & ! requestsFixTimeSalt ( ids , serverTime , serverSalt ) ) {
return HandleResult : : Ignored ;
2014-05-30 08:53:19 +00:00
}
requestsAcked ( ids ) ;
2016-12-07 13:32:25 +00:00
} return HandleResult : : Success ;
2014-05-30 08:53:19 +00:00
case mtpc_bad_msg_notification : {
2017-03-09 19:15:31 +00:00
MTPBadMsgNotification msg ;
2019-07-18 14:06:38 +00:00
if ( ! msg . read ( from , end ) ) {
return HandleResult : : ParseError ;
}
2016-04-08 10:44:35 +00:00
const auto & data ( msg . c_bad_msg_notification ( ) ) ;
2019-07-05 13:38:38 +00: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 08:53:19 +00:00
2019-11-22 09:06:48 +00:00
const auto resendId = data . vbad_msg_id ( ) . v ;
const auto errorCode = data . verror_code ( ) . v ;
2018-01-02 13:44:12 +00: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 11:09:46 +00:00
if ( errorCode = = 64 ) { // bad container!
2018-06-05 13:32:26 +00:00
if ( Logs : : DebugEnabled ( ) ) {
2019-12-02 10:32:09 +00:00
const auto i = _sentContainers . find ( resendId ) ;
if ( i = = _sentContainers . end ( ) ) {
LOG ( ( " Message Error: Container not found! " ) ) ;
} else {
auto idsList = QStringList ( ) ;
for ( const auto innerMsgId : i - > second . messages ) {
idsList . push_back ( QString : : number ( innerMsgId ) ) ;
2014-08-01 11:09:46 +00:00
}
2019-12-02 10:32:09 +00:00
LOG ( ( " Message Info: bad container received! messages: %1 " ) . arg ( idsList . join ( ' , ' ) ) ) ;
2014-08-01 11:09:46 +00:00
}
}
}
2014-05-30 08:53:19 +00:00
2014-08-01 11:09:46 +00:00
if ( ! wasSent ( resendId ) ) {
2018-01-02 13:44:12 +00:00
DEBUG_LOG ( ( " Message Error: "
" such message was not sent recently %1 " ) . arg ( resendId ) ) ;
return badTime
? HandleResult : : Ignored
: HandleResult : : Success ;
2014-08-01 11:09:46 +00:00
}
2014-05-30 08:53:19 +00:00
2018-01-02 13:44:12 +00:00
if ( needResend ) { // bad msg_id or bad container
2019-11-20 10:41:14 +00:00
if ( serverSalt ) {
_sessionSalt = serverSalt ;
}
2019-07-10 17:28:33 +00:00
base : : unixtime : : update ( serverTime , true ) ;
2014-08-01 11:09:46 +00:00
2016-03-24 15:07:13 +00:00
DEBUG_LOG ( ( " Message Info: unixtime updated, now %1, resending in container... " ) . arg ( serverTime ) ) ;
2014-08-01 11:09:46 +00:00
resend ( resendId , 0 , true ) ;
} else { // must create new session, because msg_id and msg_seqno are inconsistent
if ( badTime ) {
2019-11-20 10:41:14 +00:00
if ( serverSalt ) {
_sessionSalt = serverSalt ;
}
2019-07-10 17:28:33 +00:00
base : : unixtime : : update ( serverTime , true ) ;
2014-08-01 11:09:46 +00:00
badTime = false ;
}
2019-07-05 13:38:38 +00:00
LOG ( ( " Message Info: bad message notification received, msgId %1, error_code %2 " ) . arg ( data . vbad_msg_id ( ) . v ) . arg ( errorCode ) ) ;
2016-12-07 13:32:25 +00:00
return HandleResult : : ResetSession ;
2014-05-30 08:53:19 +00:00
}
2014-08-01 11:09:46 +00:00
} else { // fatal (except 48, but it must not get here)
2019-07-05 13:38:38 +00:00
const auto badMsgId = mtpMsgId ( data . vbad_msg_id ( ) . v ) ;
2018-01-02 13:44:12 +00:00
const auto requestId = wasSent ( resendId ) ;
2014-08-01 11:09:46 +00:00
if ( requestId ) {
2018-01-02 13:44:12 +00:00
LOG ( ( " Message Error: "
2019-12-02 09:40:53 +00:00
" fatal bad message notification received, "
" msgId %1, error_code %2, requestId: %3 "
2018-01-02 13:44:12 +00:00
) . arg ( badMsgId
) . arg ( errorCode
2019-12-02 09:40:53 +00:00
) . arg ( requestId ) ) ;
auto response = mtpBuffer ( ) ;
MTPRpcError ( MTP_rpc_error (
MTP_int ( 500 ) ,
MTP_string ( " PROTOCOL_ERROR " )
) ) . write ( response ) ;
// Save rpc_error for processing in the main thread.
QWriteLocker locker ( _sessionData - > haveReceivedMutex ( ) ) ;
_sessionData - > haveReceivedResponses ( ) . emplace ( requestId , response ) ;
2014-08-01 11:09:46 +00:00
} else {
2018-01-02 13:44:12 +00:00
DEBUG_LOG ( ( " Message Error: "
" such message was not sent recently %1 " ) . arg ( badMsgId ) ) ;
2014-08-01 11:09:46 +00:00
}
2018-01-02 13:44:12 +00:00
return badTime
? HandleResult : : Ignored
: HandleResult : : Success ;
2014-05-30 08:53:19 +00:00
}
2016-12-07 13:32:25 +00:00
} return HandleResult : : Success ;
2014-05-30 08:53:19 +00:00
case mtpc_bad_server_salt : {
2017-03-09 19:15:31 +00:00
MTPBadMsgNotification msg ;
2019-07-18 14:06:38 +00:00
if ( ! msg . read ( from , end ) ) {
return HandleResult : : ParseError ;
}
2019-11-22 09:06:48 +00:00
const auto & data = msg . c_bad_server_salt ( ) ;
2019-07-05 13:38:38 +00: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 08:53:19 +00:00
2019-11-22 09:06:48 +00:00
const auto resendId = data . vbad_msg_id ( ) . v ;
if ( ! wasSent ( resendId ) ) {
2014-05-30 08:53:19 +00:00
DEBUG_LOG ( ( " Message Error: such message was not sent recently %1 " ) . arg ( resendId ) ) ;
2016-12-07 13:32:25 +00:00
return ( badTime ? HandleResult : : Ignored : HandleResult : : Success ) ;
2014-05-30 08:53:19 +00:00
}
2019-11-20 10:41:14 +00:00
_sessionSalt = data . vnew_server_salt ( ) . v ;
2019-07-10 17:28:33 +00:00
base : : unixtime : : update ( serverTime ) ;
2014-05-30 08:53:19 +00:00
2019-11-19 16:14:50 +00:00
if ( setState ( ConnectedState , ConnectingState ) ) {
2019-11-22 09:06:48 +00:00
resendAll ( ) ;
2014-05-30 08:53:19 +00:00
}
badTime = false ;
2016-03-24 15:07:13 +00:00
DEBUG_LOG ( ( " Message Info: unixtime updated, now %1, server_salt updated, now %2, resending... " ) . arg ( serverTime ) . arg ( serverSalt ) ) ;
2014-05-30 08:53:19 +00:00
resend ( resendId ) ;
2016-12-07 13:32:25 +00:00
} return HandleResult : : Success ;
2014-05-30 08:53:19 +00:00
case mtpc_msgs_state_info : {
2017-03-09 19:15:31 +00:00
MTPMsgsStateInfo msg ;
2019-07-18 14:06:38 +00:00
if ( ! msg . read ( from , end ) ) {
return HandleResult : : ParseError ;
}
2017-03-10 19:46:28 +00:00
auto & data = msg . c_msgs_state_info ( ) ;
2016-01-11 15:43:29 +00:00
2019-07-05 13:38:38 +00:00
auto reqMsgId = data . vreq_msg_id ( ) . v ;
auto & states = data . vinfo ( ) . v ;
2014-05-30 08:53:19 +00:00
2016-01-11 15:43:29 +00: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 ( ) ) ) ;
2019-12-02 11:34:14 +00:00
const auto i = _stateAndResendRequests . find ( reqMsgId ) ;
if ( i = = _stateAndResendRequests . end ( ) ) {
DEBUG_LOG ( ( " Message Error: such message was not sent recently %1 " ) . arg ( reqMsgId ) ) ;
return ( badTime ? HandleResult : : Ignored : HandleResult : : Success ) ;
}
if ( badTime ) {
if ( serverSalt ) {
_sessionSalt = serverSalt ; // requestsFixTimeSalt with no lookup
2014-05-30 08:53:19 +00:00
}
2019-12-02 11:34:14 +00:00
base : : unixtime : : update ( serverTime , true ) ;
2014-05-30 08:53:19 +00:00
2019-12-02 11:34:14 +00:00
DEBUG_LOG ( ( " Message Info: unixtime updated from mtpc_msgs_state_info, now %1 " ) . arg ( serverTime ) ) ;
2014-05-30 08:53:19 +00:00
2019-12-02 11:34:14 +00:00
badTime = false ;
2014-05-30 08:53:19 +00:00
}
2019-12-02 11:34:14 +00:00
const auto originalRequest = i - > second ;
Assert ( originalRequest - > size ( ) > 8 ) ;
2014-10-30 16:23:44 +00:00
2019-12-02 11:34:14 +00:00
requestsAcked ( QVector < MTPlong > ( 1 , MTP_long ( reqMsgId ) ) , true ) ;
auto rFrom = originalRequest - > constData ( ) + 8 ;
const auto rEnd = originalRequest - > constData ( ) + originalRequest - > size ( ) ;
auto toAck = QVector < MTPlong > ( ) ;
2019-07-18 14:06:38 +00:00
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 ;
}
2019-12-02 11:34:14 +00:00
handleMsgsStates ( request . c_msgs_state_req ( ) . vmsg_ids ( ) . v , states ) ;
2019-07-18 14:06:38 +00:00
} else {
MTPMsgResendReq request ;
if ( ! request . read ( rFrom , rEnd ) ) {
2019-12-02 10:32:09 +00:00
LOG ( ( " Message Error: could not parse sent msgs_resend_req " ) ) ;
2019-07-18 14:06:38 +00:00
return HandleResult : : ParseError ;
2014-08-01 11:09:46 +00:00
}
2019-12-02 11:34:14 +00:00
handleMsgsStates ( request . c_msg_resend_req ( ) . vmsg_ids ( ) . v , states ) ;
2014-05-30 08:53:19 +00:00
}
2016-12-07 13:32:25 +00:00
} return HandleResult : : Success ;
2014-05-30 08:53:19 +00:00
case mtpc_msgs_all_info : {
if ( badTime ) {
2016-03-24 15:07:13 +00:00
DEBUG_LOG ( ( " Message Info: skipping with bad time... " ) ) ;
2016-12-07 13:32:25 +00:00
return HandleResult : : Ignored ;
2014-05-30 08:53:19 +00:00
}
2017-03-09 19:15:31 +00:00
MTPMsgsAllInfo msg ;
2019-07-18 14:06:38 +00:00
if ( ! msg . read ( from , end ) ) {
return HandleResult : : ParseError ;
}
2017-03-10 19:46:28 +00:00
auto & data = msg . c_msgs_all_info ( ) ;
2019-07-05 13:38:38 +00:00
auto & ids = data . vmsg_ids ( ) . v ;
auto & states = data . vinfo ( ) . v ;
2014-05-30 08:53:19 +00:00
2017-12-11 14:45:29 +00: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 ( ) ) ) ;
2019-12-02 11:34:14 +00:00
handleMsgsStates ( ids , states ) ;
2016-12-07 13:32:25 +00:00
} return HandleResult : : Success ;
2014-05-30 08:53:19 +00:00
case mtpc_msg_detailed_info : {
2017-03-09 19:15:31 +00:00
MTPMsgDetailedInfo msg ;
2019-07-18 14:06:38 +00:00
if ( ! msg . read ( from , end ) ) {
return HandleResult : : ParseError ;
}
2016-04-08 10:44:35 +00:00
const auto & data ( msg . c_msg_detailed_info ( ) ) ;
2014-05-30 08:53:19 +00:00
2019-07-05 13:38:38 +00: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 08:53:19 +00:00
2019-07-05 13:38:38 +00:00
QVector < MTPlong > ids ( 1 , data . vmsg_id ( ) ) ;
2014-05-30 08:53:19 +00:00
if ( badTime ) {
if ( requestsFixTimeSalt ( ids , serverTime , serverSalt ) ) {
badTime = false ;
} else {
2019-07-05 13:38:38 +00:00
DEBUG_LOG ( ( " Message Info: error, such message was not sent recently %1 " ) . arg ( data . vmsg_id ( ) . v ) ) ;
2016-12-07 13:32:25 +00:00
return HandleResult : : Ignored ;
2014-05-30 08:53:19 +00:00
}
}
requestsAcked ( ids ) ;
2019-11-20 10:41:14 +00:00
const auto resMsgId = data . vanswer_msg_id ( ) ;
if ( _receivedMessageIds . lookup ( resMsgId . v ) ! = ReceivedIdsManager : : State : : NotFound ) {
2019-11-14 07:13:17 +00:00
_ackRequestData . push_back ( resMsgId ) ;
2014-11-05 17:43:32 +00:00
} else {
2016-03-24 15:07:13 +00:00
DEBUG_LOG ( ( " Message Info: answer message %1 was not received, requesting... " ) . arg ( resMsgId . v ) ) ;
2019-11-14 07:13:17 +00:00
_resendRequestData . push_back ( resMsgId ) ;
2014-05-30 08:53:19 +00:00
}
2016-12-07 13:32:25 +00:00
} return HandleResult : : Success ;
2014-05-30 08:53:19 +00:00
case mtpc_msg_new_detailed_info : {
if ( badTime ) {
2016-03-24 15:07:13 +00:00
DEBUG_LOG ( ( " Message Info: skipping msg_new_detailed_info with bad time... " ) ) ;
2016-12-07 13:32:25 +00:00
return HandleResult : : Ignored ;
2014-05-30 08:53:19 +00:00
}
2017-03-09 19:15:31 +00:00
MTPMsgDetailedInfo msg ;
2019-07-18 14:06:38 +00:00
if ( ! msg . read ( from , end ) ) {
return HandleResult : : ParseError ;
}
2016-04-08 10:44:35 +00:00
const auto & data ( msg . c_msg_new_detailed_info ( ) ) ;
2014-05-30 08:53:19 +00:00
2019-07-05 13:38:38 +00: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 08:53:19 +00:00
2019-11-20 10:41:14 +00:00
const auto resMsgId = data . vanswer_msg_id ( ) ;
if ( _receivedMessageIds . lookup ( resMsgId . v ) ! = ReceivedIdsManager : : State : : NotFound ) {
2019-11-14 07:13:17 +00:00
_ackRequestData . push_back ( resMsgId ) ;
2014-11-05 17:43:32 +00:00
} else {
2016-03-24 15:07:13 +00:00
DEBUG_LOG ( ( " Message Info: answer message %1 was not received, requesting... " ) . arg ( resMsgId . v ) ) ;
2019-11-14 07:13:17 +00:00
_resendRequestData . push_back ( resMsgId ) ;
2014-05-30 08:53:19 +00:00
}
2016-12-07 13:32:25 +00:00
} return HandleResult : : Success ;
2016-01-11 15:43:29 +00:00
2014-05-30 08:53:19 +00:00
case mtpc_rpc_result : {
2019-07-18 14:06:38 +00:00
if ( from + 3 > end ) {
return HandleResult : : ParseError ;
}
2019-11-22 09:15:38 +00:00
auto response = mtpBuffer ( ) ;
2014-05-30 08:53:19 +00:00
2017-03-09 19:15:31 +00:00
MTPlong reqMsgId ;
2019-07-18 14:06:38 +00:00
if ( ! reqMsgId . read ( + + from , end ) ) {
return HandleResult : : ParseError ;
}
2019-11-22 09:06:48 +00:00
const auto requestMsgId = reqMsgId . v ;
2014-05-30 08:53:19 +00:00
2019-11-22 09:06:48 +00:00
DEBUG_LOG ( ( " RPC Info: response received for %1, queueing... " ) . arg ( requestMsgId ) ) ;
2014-05-30 08:53:19 +00:00
QVector < MTPlong > ids ( 1 , reqMsgId ) ;
if ( badTime ) {
if ( requestsFixTimeSalt ( ids , serverTime , serverSalt ) ) {
badTime = false ;
} else {
2019-11-22 09:06:48 +00:00
DEBUG_LOG ( ( " Message Info: error, such message was not sent recently %1 " ) . arg ( requestMsgId ) ) ;
2016-12-07 13:32:25 +00:00
return HandleResult : : Ignored ;
2014-05-30 08:53:19 +00:00
}
}
2019-11-22 09:06:48 +00:00
mtpTypeId typeId = from [ 0 ] ;
2014-05-30 08:53:19 +00:00
if ( typeId = = mtpc_gzip_packed ) {
DEBUG_LOG ( ( " RPC Info: gzip container " ) ) ;
response = ungzip ( + + from , end ) ;
2019-07-18 14:06:38 +00:00
if ( response . empty ( ) ) {
2016-12-07 13:32:25 +00:00
return HandleResult : : RestartConnection ;
2014-05-30 08:53:19 +00:00
}
typeId = response [ 0 ] ;
} else {
response . resize ( end - from ) ;
memcpy ( response . data ( ) , from , ( end - from ) * sizeof ( mtpPrime ) ) ;
}
2019-11-19 10:10:51 +00:00
if ( typeId = = mtpc_rpc_error ) {
2019-11-20 09:16:53 +00:00
if ( IsDestroyedTemporaryKeyError ( response ) ) {
2019-11-19 10:10:51 +00:00
return HandleResult : : DestroyTemporaryKey ;
}
2017-05-17 11:01:58 +00:00
// 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.
2019-11-19 16:14:50 +00:00
} else {
2019-12-02 13:10:19 +00:00
_sessionData - > notifyConnectionInited ( * _options ) ;
2014-11-14 23:23:35 +00:00
}
2019-11-19 16:14:50 +00:00
requestsAcked ( ids , true ) ;
2014-05-30 08:53:19 +00:00
2019-11-22 09:06:48 +00:00
const auto bindResult = handleBindResponse ( requestMsgId , response ) ;
if ( bindResult ! = HandleResult : : Ignored ) {
return bindResult ;
2019-11-14 13:34:58 +00:00
}
2019-11-22 09:06:48 +00:00
const auto requestId = wasSent ( requestMsgId ) ;
2014-06-16 09:31:10 +00:00
if ( requestId & & requestId ! = mtpRequestId ( 0xFFFFFFFF ) ) {
2017-04-30 14:23:57 +00:00
// Save rpc_result for processing in the main thread.
2019-11-14 07:13:17 +00:00
QWriteLocker locker ( _sessionData - > haveReceivedMutex ( ) ) ;
2019-11-22 09:15:38 +00:00
_sessionData - > haveReceivedResponses ( ) . emplace ( requestId , response ) ;
2014-05-30 08:53:19 +00:00
} else {
2019-11-22 09:06:48 +00:00
DEBUG_LOG ( ( " RPC Info: requestId not found for msgId %1 " ) . arg ( requestMsgId ) ) ;
2014-05-30 08:53:19 +00:00
}
2016-12-07 13:32:25 +00:00
} return HandleResult : : Success ;
2014-05-30 08:53:19 +00:00
case mtpc_new_session_created : {
2015-04-23 15:50:11 +00:00
const mtpPrime * start = from ;
2017-03-09 19:15:31 +00:00
MTPNewSession msg ;
2019-07-18 14:06:38 +00:00
if ( ! msg . read ( from , end ) ) {
return HandleResult : : ParseError ;
}
2016-04-08 10:44:35 +00:00
const auto & data ( msg . c_new_session_created ( ) ) ;
2015-10-01 14:19:27 +00:00
if ( badTime ) {
2019-07-05 13:38:38 +00:00
if ( requestsFixTimeSalt ( QVector < MTPlong > ( 1 , data . vfirst_msg_id ( ) ) , serverTime , serverSalt ) ) {
2015-10-01 14:19:27 +00:00
badTime = false ;
} else {
2019-07-05 13:38:38 +00:00
DEBUG_LOG ( ( " Message Info: error, such message was not sent recently %1 " ) . arg ( data . vfirst_msg_id ( ) . v ) ) ;
2016-12-07 13:32:25 +00:00
return HandleResult : : Ignored ;
2015-10-01 14:19:27 +00:00
}
}
2019-07-05 13:38:38 +00: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-20 10:41:14 +00:00
_sessionSalt = data . vserver_salt ( ) . v ;
2014-05-30 08:53:19 +00:00
2019-07-05 13:38:38 +00:00
mtpMsgId firstMsgId = data . vfirst_msg_id ( ) . v ;
2014-11-25 12:15:29 +00:00
QVector < quint64 > toResend ;
2014-05-30 08:53:19 +00:00
{
2019-11-14 07:13:17 +00:00
QReadLocker locker ( _sessionData - > haveSentMutex ( ) ) ;
const auto & haveSent = _sessionData - > haveSentMap ( ) ;
2014-05-30 08:53:19 +00:00
toResend . reserve ( haveSent . size ( ) ) ;
2019-11-22 09:15:38 +00:00
for ( const auto & [ msgId , request ] : haveSent ) {
if ( msgId > = firstMsgId ) {
2019-11-19 16:14:50 +00:00
break ;
2019-11-22 09:15:38 +00:00
} else if ( request - > requestId ) {
toResend . push_back ( msgId ) ;
2019-11-19 16:14:50 +00:00
}
2014-05-30 08:53:19 +00:00
}
}
2019-11-19 16:14:50 +00:00
for ( const auto msgId : toResend ) {
2019-11-22 09:06:48 +00:00
resend ( msgId , 10 , true ) ;
2019-11-19 16:14:50 +00:00
}
2014-05-30 08:53:19 +00:00
2015-04-23 15:50:11 +00:00
mtpBuffer update ( from - start ) ;
if ( from > start ) memcpy ( update . data ( ) , start , ( from - start ) * sizeof ( mtpPrime ) ) ;
2016-01-11 15:43:29 +00:00
2017-04-30 14:23:57 +00:00
// Notify main process about new session - need to get difference.
2019-11-14 07:13:17 +00:00
QWriteLocker locker ( _sessionData - > haveReceivedMutex ( ) ) ;
2019-11-22 09:15:38 +00:00
_sessionData - > haveReceivedUpdates ( ) . push_back ( mtpBuffer ( update ) ) ;
2016-12-07 13:32:25 +00:00
} return HandleResult : : Success ;
2014-05-30 08:53:19 +00:00
case mtpc_pong : {
2017-03-09 19:15:31 +00:00
MTPPong msg ;
2019-07-18 14:06:38 +00:00
if ( ! msg . read ( from , end ) ) {
return HandleResult : : ParseError ;
}
2016-04-08 10:44:35 +00:00
const auto & data ( msg . c_pong ( ) ) ;
2019-07-05 13:38:38 +00: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 15:43:29 +00:00
2019-07-05 13:38:38 +00: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 13:32:25 +00:00
return HandleResult : : Ignored ;
2014-05-30 08:53:19 +00:00
}
2019-07-05 13:38:38 +00:00
if ( data . vping_id ( ) . v = = _pingId ) {
2015-03-12 10:28:10 +00:00
_pingId = 0 ;
2014-05-30 08:53:19 +00:00
} else {
2016-03-24 15:07:13 +00:00
DEBUG_LOG ( ( " Message Info: just pong... " ) ) ;
2014-05-30 08:53:19 +00:00
}
2019-07-05 13:38:38 +00:00
QVector < MTPlong > ids ( 1 , data . vmsg_id ( ) ) ;
2014-05-30 08:53:19 +00:00
if ( badTime ) {
if ( requestsFixTimeSalt ( ids , serverTime , serverSalt ) ) {
badTime = false ;
} else {
2016-12-07 13:32:25 +00:00
return HandleResult : : Ignored ;
2014-05-30 08:53:19 +00:00
}
}
2014-10-30 16:23:44 +00:00
requestsAcked ( ids , true ) ;
2016-12-07 13:32:25 +00:00
} return HandleResult : : Success ;
2014-05-30 08:53:19 +00:00
}
if ( badTime ) {
2015-01-22 21:59:07 +00:00
DEBUG_LOG ( ( " Message Error: bad time in updates cons, must create new session " ) ) ;
2016-12-07 13:32:25 +00:00
return HandleResult : : ResetSession ;
2014-05-30 08:53:19 +00:00
}
2019-11-21 10:37:39 +00:00
if ( _currentDcType = = DcType : : Regular ) {
2017-03-23 16:11:35 +00:00
mtpBuffer update ( end - from ) ;
2019-11-22 09:06:48 +00:00
if ( end > from ) {
memcpy ( update . data ( ) , from , ( end - from ) * sizeof ( mtpPrime ) ) ;
}
2016-01-11 15:43:29 +00:00
2017-04-30 14:23:57 +00:00
// Notify main process about the new updates.
2019-11-14 07:13:17 +00:00
QWriteLocker locker ( _sessionData - > haveReceivedMutex ( ) ) ;
2019-11-22 09:15:38 +00:00
_sessionData - > haveReceivedUpdates ( ) . push_back ( mtpBuffer ( update ) ) ;
2017-03-23 16:11:35 +00:00
} else {
2019-11-21 10:37:39 +00:00
LOG ( ( " Message Error: unexpected updates in dcType: %1 "
) . arg ( static_cast < int > ( _currentDcType ) ) ) ;
2014-05-30 08:53:19 +00:00
}
2016-12-07 13:32:25 +00:00
return HandleResult : : Success ;
2014-05-30 08:53:19 +00:00
}
2019-12-02 13:10:19 +00:00
SessionPrivate : : HandleResult SessionPrivate : : handleBindResponse (
2019-11-22 09:06:48 +00:00
mtpMsgId requestMsgId ,
const mtpBuffer & response ) {
if ( ! _keyCreator | | ! _bindMsgId | | _bindMsgId ! = requestMsgId ) {
return HandleResult : : Ignored ;
}
2019-12-02 13:30:33 +00:00
_bindMsgId = 0 ;
2019-11-22 09:06:48 +00:00
const auto result = _keyCreator - > handleBindResponse ( response ) ;
switch ( result ) {
case DcKeyBindState : : Success :
if ( ! _sessionData - > releaseKeyCreationOnDone (
_encryptionKey ,
base : : take ( _keyCreator ) - > bindPersistentKey ( ) ) ) {
return HandleResult : : DestroyTemporaryKey ;
}
_sessionData - > queueNeedToResumeAndSend ( ) ;
return HandleResult : : Success ;
case DcKeyBindState : : DefinitelyDestroyed :
if ( destroyOldEnoughPersistentKey ( ) ) {
return HandleResult : : DestroyTemporaryKey ;
}
[[fallthrough]] ;
case DcKeyBindState : : Failed :
_sessionData - > queueNeedToResumeAndSend ( ) ;
return HandleResult : : Success ;
}
Unexpected ( " Result of BoundKeyCreator::handleBindResponse. " ) ;
}
2019-12-02 13:10:19 +00:00
mtpBuffer SessionPrivate : : ungzip ( const mtpPrime * from , const mtpPrime * end ) const {
2019-07-18 14:06:38 +00:00
mtpBuffer result ; // * 4 because of mtpPrime type
result . resize ( 0 ) ;
2017-03-09 19:15:31 +00:00
MTPstring packed ;
2019-07-18 14:06:38 +00: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 19:46:28 +00:00
uint32 packedLen = packed . v . size ( ) , unpackedChunk = packedLen , unpackedLen = 0 ;
2014-05-30 08:53:19 +00: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 19:46:28 +00:00
stream . next_in = reinterpret_cast < Bytef * > ( packed . v . data ( ) ) ;
2014-05-30 08:53:19 +00: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 14:13:57 +00:00
DEBUG_LOG ( ( " RPC Error: bad gzip: %1 " ) . arg ( Logs : : mb ( packed . v . constData ( ) , packedLen ) . str ( ) ) ) ;
2014-05-30 08:53:19 +00: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 15:43:29 +00:00
DEBUG_LOG ( ( " RPC Error: bad unpacked data %1 " ) . arg ( Logs : : mb ( result . data ( ) , badSize ) . str ( ) ) ) ;
2014-05-30 08:53:19 +00: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 ;
}
2019-12-02 13:10:19 +00:00
bool SessionPrivate : : requestsFixTimeSalt ( const QVector < MTPlong > & ids , int32 serverTime , uint64 serverSalt ) {
2014-05-30 08:53:19 +00: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-20 10:41:14 +00:00
if ( serverSalt ) {
_sessionSalt = serverSalt ;
}
2019-07-10 17:28:33 +00:00
base : : unixtime : : update ( serverTime , true ) ;
2014-05-30 08:53:19 +00:00
return true ;
}
}
return false ;
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : requestsAcked ( const QVector < MTPlong > & ids , bool byResponse ) {
2014-05-30 08:53:19 +00:00
uint32 idsCount = ids . size ( ) ;
2017-12-11 14:45:29 +00:00
DEBUG_LOG ( ( " Message Info: requests acked, ids %1 " ) . arg ( LogIdsVector ( ids ) ) ) ;
2014-05-30 08:53:19 +00:00
QVector < MTPlong > toAckMore ;
{
2019-11-22 09:06:48 +00:00
QWriteLocker locker2 ( _sessionData - > haveSentMutex ( ) ) ;
auto & haveSent = _sessionData - > haveSentMap ( ) ;
2014-05-30 08:53:19 +00:00
2019-12-02 10:32:09 +00:00
for ( const auto & wrappedMsgId : ids ) {
const auto msgId = wrappedMsgId . v ;
if ( const auto i = _sentContainers . find ( msgId ) ; i ! = end ( _sentContainers ) ) {
DEBUG_LOG ( ( " Message Info: container ack received, msgId %1 " ) . arg ( msgId ) ) ;
const auto & list = i - > second . messages ;
toAckMore . reserve ( toAckMore . size ( ) + list . size ( ) ) ;
for ( const auto msgId : list ) {
toAckMore . push_back ( MTP_long ( msgId ) ) ;
2019-11-22 09:06:48 +00:00
}
2019-12-02 10:32:09 +00:00
_sentContainers . erase ( i ) ;
continue ;
}
2019-12-02 11:34:14 +00:00
if ( const auto i = _stateAndResendRequests . find ( msgId ) ; i ! = end ( _stateAndResendRequests ) ) {
_stateAndResendRequests . erase ( i ) ;
continue ;
}
2019-12-02 10:32:09 +00:00
if ( const auto i = haveSent . find ( msgId ) ; i ! = end ( haveSent ) ) {
const auto requestId = i - > second - > requestId ;
if ( ! byResponse & & _instance - > hasCallbacks ( requestId ) ) {
DEBUG_LOG ( ( " Message Info: ignoring ACK for msgId %1 because request %2 requires a response " ) . arg ( msgId ) . arg ( requestId ) ) ;
continue ;
}
haveSent . erase ( i ) ;
_ackedIds . emplace ( msgId , requestId ) ;
continue ;
}
DEBUG_LOG ( ( " Message Info: msgId %1 was not found in recent sent, while acking requests, searching in resend... " ) . arg ( msgId ) ) ;
if ( const auto i = _resendingIds . find ( msgId ) ; i ! = end ( _resendingIds ) ) {
const auto requestId = i - > second ;
if ( ! byResponse & & _instance - > hasCallbacks ( requestId ) ) {
DEBUG_LOG ( ( " Message Info: ignoring ACK for msgId %1 because request %2 requires a response " ) . arg ( msgId ) . arg ( requestId ) ) ;
continue ;
}
_resendingIds . erase ( i ) ;
QWriteLocker locker4 ( _sessionData - > toSendMutex ( ) ) ;
auto & toSend = _sessionData - > toSendMap ( ) ;
const auto j = toSend . find ( requestId ) ;
if ( j = = end ( toSend ) ) {
DEBUG_LOG ( ( " Message Info: msgId %1 was found in recent resent, requestId %2 was not found in prepared to send " ) . arg ( msgId ) . arg ( requestId ) ) ;
continue ;
}
if ( j - > second - > requestId ! = requestId ) {
DEBUG_LOG ( ( " Message Error: for msgId %1 found resent request, requestId %2, contains requestId %3 " ) . arg ( msgId ) . arg ( requestId ) . arg ( j - > second - > requestId ) ) ;
2019-11-22 09:06:48 +00:00
} else {
2019-12-02 10:32:09 +00:00
DEBUG_LOG ( ( " Message Info: acked msgId %1 that was prepared to resend, requestId %2 " ) . arg ( msgId ) . arg ( requestId ) ) ;
2014-05-30 08:53:19 +00:00
}
2020-04-06 09:07:49 +00:00
2019-12-02 10:32:09 +00:00
_ackedIds . emplace ( msgId , j - > second - > requestId ) ;
2020-04-06 09:07:49 +00:00
2020-03-20 05:02:36 +00:00
toSend . erase ( j ) ;
2019-12-02 10:32:09 +00:00
continue ;
2014-05-30 08:53:19 +00:00
}
2019-12-02 10:32:09 +00:00
DEBUG_LOG ( ( " Message Info: msgId %1 was not found in recent resent either " ) . arg ( msgId ) ) ;
2014-05-30 08:53:19 +00:00
}
2019-11-22 09:06:48 +00:00
}
2014-05-30 08:53:19 +00:00
2019-11-22 09:06:48 +00:00
auto ackedCount = _ackedIds . size ( ) ;
if ( ackedCount > kIdsBufferSize ) {
DEBUG_LOG ( ( " Message Info: removing some old acked sent msgIds %1 " ) . arg ( ackedCount - kIdsBufferSize ) ) ;
while ( ackedCount - - > kIdsBufferSize ) {
2019-12-02 09:40:53 +00:00
_ackedIds . erase ( _ackedIds . begin ( ) ) ;
2014-05-30 08:53:19 +00:00
}
}
if ( toAckMore . size ( ) ) {
requestsAcked ( toAckMore ) ;
}
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : handleMsgsStates ( const QVector < MTPlong > & ids , const QByteArray & states ) {
2019-12-02 11:34:14 +00:00
const auto idsCount = ids . size ( ) ;
2014-05-30 08:53:19 +00:00
if ( ! idsCount ) {
DEBUG_LOG ( ( " Message Info: void ids vector in handleMsgsStates() " ) ) ;
return ;
}
2019-12-02 11:34:14 +00:00
if ( states . size ( ) ! = idsCount ) {
2017-03-10 19:46:28 +00:00
LOG ( ( " Message Error: got less states than required ids count. " ) ) ;
return ;
}
2016-01-11 15:43:29 +00:00
2019-12-02 11:34:14 +00:00
auto acked = QVector < MTPlong > ( ) ;
acked . reserve ( idsCount ) ;
for ( auto i = 0 ; i ! = idsCount ; + + i ) {
const auto state = states [ i ] ;
const auto requestMsgId = ids [ i ] . v ;
2014-05-30 08:53:19 +00:00
{
2019-11-14 07:13:17 +00:00
QReadLocker locker ( _sessionData - > haveSentMutex ( ) ) ;
2019-11-22 09:15:38 +00:00
if ( ! _sessionData - > haveSentMap ( ) . contains ( requestMsgId ) ) {
2016-03-24 15:07:13 +00:00
DEBUG_LOG ( ( " Message Info: state was received for msgId %1, but request is not found, looking in resent requests... " ) . arg ( requestMsgId ) ) ;
2019-11-22 09:06:48 +00:00
const auto reqIt = _resendingIds . find ( requestMsgId ) ;
if ( reqIt ! = _resendingIds . cend ( ) ) {
2014-05-30 08:53:19 +00:00
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 ) ) ;
}
}
2019-12-02 11:34:14 +00:00
requestsAcked ( acked ) ;
2014-05-30 08:53:19 +00:00
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : clearSpecialMsgId ( mtpMsgId msgId ) {
2019-11-22 09:06:48 +00:00
if ( msgId = = _pingMsgId ) {
_pingMsgId = 0 ;
_pingId = 0 ;
} else if ( msgId = = _bindMsgId ) {
_bindMsgId = 0 ;
}
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : resend (
2019-11-18 12:53:37 +00:00
mtpMsgId msgId ,
crl : : time msCanWait ,
2019-11-19 11:55:39 +00:00
bool forceContainer ) {
2019-11-22 09:06:48 +00:00
const auto guard = gsl : : finally ( [ & ] {
clearSpecialMsgId ( msgId ) ;
if ( msCanWait > = 0 ) {
_sessionData - > queueSendAnything ( msCanWait ) ;
}
} ) ;
2019-12-02 10:32:09 +00:00
if ( const auto i = _sentContainers . find ( msgId ) ; i ! = end ( _sentContainers ) ) {
DEBUG_LOG ( ( " Message Info: resending container, msgId %1 " ) . arg ( msgId ) ) ;
const auto ids = std : : move ( i - > second . messages ) ;
_sentContainers . erase ( i ) ;
for ( const auto innerMsgId : ids ) {
resend ( innerMsgId , - 1 , true ) ;
}
return ;
}
2019-11-22 09:06:48 +00:00
auto lock = QWriteLocker ( _sessionData - > haveSentMutex ( ) ) ;
auto & haveSent = _sessionData - > haveSentMap ( ) ;
auto i = haveSent . find ( msgId ) ;
if ( i = = haveSent . end ( ) ) {
return ;
}
2019-11-22 09:15:38 +00:00
auto request = i - > second ;
2019-11-22 09:06:48 +00:00
haveSent . erase ( i ) ;
lock . unlock ( ) ;
2019-12-02 11:34:14 +00:00
request - > lastSentTime = crl : : now ( ) ;
request - > forceSendInContainer = forceContainer ;
_resendingIds . emplace ( msgId , request - > requestId ) ;
{
QWriteLocker locker ( _sessionData - > toSendMutex ( ) ) ;
_sessionData - > toSendMap ( ) . emplace ( request - > requestId , request ) ;
2019-11-18 12:53:37 +00:00
}
2014-11-25 12:15:29 +00:00
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : resendAll ( ) {
2019-12-02 11:34:14 +00:00
auto lock = QWriteLocker ( _sessionData - > haveSentMutex ( ) ) ;
auto haveSent = base : : take ( _sessionData - > haveSentMap ( ) ) ;
lock . unlock ( ) ;
{
auto lock = QWriteLocker ( _sessionData - > toSendMutex ( ) ) ;
auto & toSend = _sessionData - > toSendMap ( ) ;
const auto now = crl : : now ( ) ;
for ( auto & [ msgId , request ] : haveSent ) {
const auto requestId = request - > requestId ;
request - > lastSentTime = now ;
request - > forceSendInContainer = true ;
_resendingIds . emplace ( msgId , requestId ) ;
toSend . emplace ( requestId , std : : move ( request ) ) ;
2019-11-22 09:06:48 +00:00
}
}
_sessionData - > queueSendAnything ( ) ;
2014-05-30 08:53:19 +00:00
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : onConnected (
2018-04-24 19:09:20 +00:00
not_null < AbstractConnection * > connection ) {
disconnect ( connection , & AbstractConnection : : connected , nullptr , nullptr ) ;
if ( ! connection - > isConnected ( ) ) {
LOG ( ( " Connection Error: not connected in onConnected(), "
" state: %1 " ) . arg ( connection - > debugState ( ) ) ) ;
2014-05-30 08:53:19 +00:00
return restart ( ) ;
}
2018-04-24 19:09:20 +00: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 ( ) ;
2019-11-15 13:04:32 +00:00
checkAuthKey ( ) ;
2015-06-10 12:48:26 +00:00
}
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : onDisconnected (
2018-04-24 19:09:20 +00:00
not_null < AbstractConnection * > connection ) {
removeTestConnection ( connection ) ;
2015-06-10 12:48:26 +00:00
2018-04-24 19:09:20 +00:00
if ( _testConnections . empty ( ) ) {
2018-05-17 19:58:00 +00:00
destroyAllConnections ( ) ;
restart ( ) ;
2015-06-10 12:48:26 +00:00
} else {
2018-04-24 19:09:20 +00:00
confirmBestConnection ( ) ;
2015-06-10 12:48:26 +00:00
}
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : confirmBestConnection ( ) {
2018-04-24 19:09:20 +00:00
if ( _waitForBetterTimer . isActive ( ) ) {
return ;
2015-06-10 12:48:26 +00:00
}
2018-04-24 19:09:20 +00: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 ( ) ;
2019-11-15 13:04:32 +00:00
checkAuthKey ( ) ;
2018-04-24 19:09:20 +00:00
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : removeTestConnection (
2018-04-24 19:09:20 +00:00
not_null < AbstractConnection * > connection ) {
_testConnections . erase (
ranges : : remove (
_testConnections ,
connection . get ( ) ,
[ ] ( const TestConnection & test ) { return test . data . get ( ) ; } ) ,
end ( _testConnections ) ) ;
2015-06-10 12:48:26 +00:00
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : checkAuthKey ( ) {
2019-11-19 16:14:50 +00:00
if ( _keyId ) {
2019-11-15 13:04:32 +00:00
authKeyChecked ( ) ;
2019-11-20 11:50:19 +00:00
} else if ( _instance - > isKeysDestroyer ( ) ) {
applyAuthKey ( _sessionData - > getPersistentKey ( ) ) ;
2019-11-19 16:14:50 +00:00
} else {
2019-11-21 10:37:39 +00:00
applyAuthKey ( _sessionData - > getTemporaryKey (
TemporaryKeyTypeByDcType ( _currentDcType ) ) ) ;
2019-11-15 13:04:32 +00:00
}
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : updateAuthKey ( ) {
2019-11-21 10:37:39 +00:00
if ( _instance - > isKeysDestroyer ( ) | | _keyCreator | | ! _connection ) {
2019-11-14 07:13:17 +00:00
return ;
}
2015-05-14 16:50:04 +00:00
2019-11-21 10:37:39 +00:00
DEBUG_LOG ( ( " AuthKey Info: Connection updating key from Session, dc %1 "
) . arg ( _shiftedDcId ) ) ;
2019-12-09 14:32:51 +00:00
applyAuthKey ( _sessionData - > getTemporaryKey (
TemporaryKeyTypeByDcType ( _currentDcType ) ) ) ;
2019-11-18 12:53:37 +00:00
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : setCurrentKeyId ( uint64 newKeyId ) {
2019-11-20 10:41:14 +00:00
if ( _keyId = = newKeyId ) {
return ;
}
_keyId = newKeyId ;
DEBUG_LOG ( ( " MTP Info: auth key id set to id %1 " ) . arg ( newKeyId ) ) ;
changeSessionId ( ) ;
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : applyAuthKey ( AuthKeyPtr & & encryptionKey ) {
2019-11-20 11:50:19 +00:00
_encryptionKey = std : : move ( encryptionKey ) ;
const auto newKeyId = _encryptionKey ? _encryptionKey - > keyId ( ) : 0 ;
2019-11-19 16:14:50 +00:00
if ( _keyId ) {
2019-11-15 13:04:32 +00:00
if ( _keyId = = newKeyId ) {
return ;
2015-05-14 16:50:04 +00:00
}
2019-11-20 10:41:14 +00:00
setCurrentKeyId ( 0 ) ;
2019-12-02 09:40:53 +00:00
DEBUG_LOG ( ( " MTP Info: auth_key id for dc %1 changed, restarting... "
2019-11-19 16:14:50 +00:00
) . arg ( _shiftedDcId ) ) ;
if ( _connection ) {
restart ( ) ;
}
return ;
2015-05-14 16:50:04 +00:00
}
2019-11-15 13:04:32 +00:00
if ( ! _connection ) {
return ;
}
2019-11-20 10:41:14 +00:00
setCurrentKeyId ( newKeyId ) ;
2019-11-19 16:14:50 +00:00
Assert ( ! _connection - > sentEncryptedWithKeyId ( ) ) ;
2019-12-09 14:32:51 +00:00
DEBUG_LOG ( ( " AuthKey Info: Connection update key from Session, "
" dc %1 result: %2 "
) . arg ( _shiftedDcId
) . arg ( Logs : : mb ( & _keyId , sizeof ( _keyId ) ) . str ( ) ) ) ;
2019-11-14 07:13:17 +00:00
if ( _keyId ) {
2019-11-15 13:04:32 +00:00
return authKeyChecked ( ) ;
2014-05-30 08:53:19 +00:00
}
2019-11-15 13:04:32 +00:00
if ( _instance - > isKeysDestroyer ( ) ) {
2017-02-25 16:44:02 +00:00
// We are here to destroy an old key, so we're done.
2019-12-09 14:32:51 +00:00
LOG ( ( " MTP Error: No key %1 in updateAuthKey() for destroying. "
) . arg ( _shiftedDcId ) ) ;
2019-11-20 13:33:45 +00:00
_instance - > keyWasPossiblyDestroyed ( _shiftedDcId ) ;
2019-12-09 14:32:51 +00:00
} else if ( noMediaKeyWithExistingRegularKey ( ) ) {
DEBUG_LOG ( ( " AuthKey Info: No key in updateAuthKey() for media, "
" but someone has created regular, trying to acquire. " ) ) ;
const auto dcType = tryAcquireKeyCreation ( ) ;
if ( _keyCreator & & dcType ! = _currentDcType ) {
DEBUG_LOG ( ( " AuthKey Info: "
" Dc type changed for creation, restarting. " ) ) ;
restart ( ) ;
return ;
}
}
if ( _keyCreator ) {
2019-11-20 09:16:53 +00:00
DEBUG_LOG ( ( " AuthKey Info: No key in updateAuthKey(), creating. " ) ) ;
_keyCreator - > start (
BareDcId ( _shiftedDcId ) ,
getProtocolDcId ( ) ,
_connection . get ( ) ,
_instance - > dcOptions ( ) ) ;
} else {
2019-12-09 14:32:51 +00:00
DEBUG_LOG ( ( " AuthKey Info: No key in updateAuthKey(), "
" but someone is creating already, waiting. " ) ) ;
2014-05-30 08:53:19 +00:00
}
2019-11-20 09:16:53 +00:00
}
2019-07-05 13:38:38 +00:00
2019-12-09 14:32:51 +00:00
bool SessionPrivate : : noMediaKeyWithExistingRegularKey ( ) const {
return ( TemporaryKeyTypeByDcType ( _currentDcType )
= = TemporaryKeyType : : MediaCluster )
& & _sessionData - > getTemporaryKey ( TemporaryKeyType : : Regular ) ;
}
2019-12-02 13:10:19 +00:00
bool SessionPrivate : : destroyOldEnoughPersistentKey ( ) {
2019-11-20 13:33:45 +00:00
Expects ( _keyCreator ! = nullptr ) ;
const auto key = _keyCreator - > bindPersistentKey ( ) ;
Assert ( key ! = nullptr ) ;
const auto created = key - > creationTime ( ) ;
if ( created > 0 & & crl : : now ( ) - created < kKeyOldEnoughForDestroy ) {
return false ;
}
const auto instance = _instance ;
const auto shiftedDcId = _shiftedDcId ;
const auto keyId = key - > keyId ( ) ;
InvokeQueued ( instance , [ = ] {
instance - > keyDestroyedOnServer ( shiftedDcId , keyId ) ;
} ) ;
return true ;
}
2019-12-02 13:10:19 +00:00
DcType SessionPrivate : : tryAcquireKeyCreation ( ) {
2019-11-21 10:37:39 +00:00
if ( _keyCreator ) {
return _currentDcType ;
} else if ( _instance - > isKeysDestroyer ( ) ) {
return _realDcType ;
}
2019-12-28 10:52:29 +00:00
const auto acquired = _sessionData - > acquireKeyCreation ( _realDcType ) ;
2019-11-21 10:37:39 +00:00
if ( acquired = = CreatingKeyType : : None ) {
return _realDcType ;
2019-11-20 09:16:53 +00:00
}
2014-05-30 08:53:19 +00:00
2019-11-20 09:16:53 +00:00
using Result = DcKeyResult ;
using Error = DcKeyError ;
auto delegate = BoundKeyCreator : : Delegate ( ) ;
delegate . unboundReady = [ = ] ( base : : expected < Result , Error > result ) {
if ( ! result ) {
releaseKeyCreationOnFail ( ) ;
if ( result . error ( ) = = Error : : UnknownPublicKey ) {
2019-11-21 10:37:39 +00:00
if ( _realDcType = = DcType : : Cdn ) {
2019-11-20 09:16:53 +00:00
LOG ( ( " Warning: CDN public RSA key not found " ) ) ;
requestCDNConfig ( ) ;
return ;
}
LOG ( ( " AuthKey Error: could not choose public RSA key " ) ) ;
2019-11-19 10:10:51 +00:00
}
2019-11-20 09:16:53 +00:00
restart ( ) ;
2019-11-15 13:04:32 +00:00
return ;
}
2019-11-20 09:16:53 +00:00
DEBUG_LOG ( ( " AuthKey Info: unbound key creation succeed, "
" ids: (%1, %2) server salts: (%3, %4) "
) . arg ( result - > temporaryKey
? result - > temporaryKey - > keyId ( )
: 0
) . arg ( result - > persistentKey
? result - > persistentKey - > keyId ( )
: 0
) . arg ( result - > temporaryServerSalt
) . arg ( result - > persistentServerSalt ) ) ;
2019-11-20 10:41:14 +00:00
_sessionSalt = result - > temporaryServerSalt ;
2019-11-20 09:16:53 +00:00
result - > temporaryKey - > setExpiresAt ( base : : unixtime : : now ( )
+ kTemporaryExpiresIn
+ kBindKeyAdditionalExpiresTimeout ) ;
2019-12-28 10:52:29 +00:00
if ( _realDcType ! = DcType : : Cdn ) {
auto key = result - > persistentKey
? std : : move ( result - > persistentKey )
: _sessionData - > getPersistentKey ( ) ;
if ( ! key ) {
releaseKeyCreationOnFail ( ) ;
restart ( ) ;
return ;
}
_keyCreator - > bind ( std : : move ( key ) ) ;
}
2019-11-20 09:16:53 +00:00
applyAuthKey ( std : : move ( result - > temporaryKey ) ) ;
2019-12-28 10:52:29 +00:00
if ( _realDcType = = DcType : : Cdn ) {
_keyCreator = nullptr ;
if ( ! _sessionData - > releaseCdnKeyCreationOnDone ( _encryptionKey ) ) {
restart ( ) ;
} else {
_sessionData - > queueNeedToResumeAndSend ( ) ;
}
}
2019-11-13 14:12:04 +00:00
} ;
2019-11-19 10:10:51 +00:00
delegate . sentSome = [ = ] ( uint64 size ) {
onSentSome ( size ) ;
} ;
delegate . receivedSome = [ = ] {
onReceivedSome ( ) ;
} ;
2019-11-20 09:16:53 +00:00
auto request = DcKeyRequest ( ) ;
2019-11-21 10:37:39 +00:00
request . persistentNeeded = ( acquired = = CreatingKeyType : : Persistent ) ;
2019-11-19 10:10:51 +00:00
request . temporaryExpiresIn = kTemporaryExpiresIn ;
2019-11-20 09:16:53 +00:00
_keyCreator = std : : make_unique < BoundKeyCreator > (
request ,
std : : move ( delegate ) ) ;
2019-11-21 10:37:39 +00:00
const auto forceUseRegular = ( _realDcType = = DcType : : MediaCluster )
& & ( acquired ! = CreatingKeyType : : TemporaryMediaCluster ) ;
return forceUseRegular ? DcType : : Regular : _realDcType ;
2014-05-30 08:53:19 +00:00
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : authKeyChecked ( ) {
2018-04-24 19:09:20 +00:00
connect ( _connection , & AbstractConnection : : receivedData , [ = ] {
handleReceived ( ) ;
} ) ;
2014-05-30 08:53:19 +00:00
2019-11-20 10:41:14 +00:00
if ( _sessionSalt & & setState ( ConnectedState ) ) {
2019-11-22 09:06:48 +00:00
resendAll ( ) ;
2019-11-15 13:04:32 +00:00
} // else receive salt in bad_server_salt first, then try to send all the requests
2014-05-30 08:53:19 +00:00
2016-03-24 10:12:18 +00:00
_pingIdToSend = rand_value < uint64 > ( ) ; // get server_salt
2019-11-18 12:53:37 +00:00
_sessionData - > queueNeedToResumeAndSend ( ) ;
2014-05-30 08:53:19 +00:00
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : onError (
2018-04-24 19:09:20 +00:00
not_null < AbstractConnection * > connection ,
qint32 errorCode ) {
2017-02-25 16:44:02 +00:00
if ( errorCode = = - 429 ) {
LOG ( ( " Protocol Error: -429 flood code returned! " ) ) ;
2018-05-24 13:40:19 +00:00
} else if ( errorCode = = - 444 ) {
LOG ( ( " Protocol Error: -444 bad dc_id code returned! " ) ) ;
InvokeQueued ( _instance , [ instance = _instance ] {
instance - > badConfigurationError ( ) ;
} ) ;
2017-02-25 16:44:02 +00:00
}
2018-04-24 19:09:20 +00:00
removeTestConnection ( connection ) ;
if ( _testConnections . empty ( ) ) {
2018-05-17 19:58:00 +00:00
handleError ( errorCode ) ;
2017-03-23 16:11:35 +00:00
} else {
2018-04-24 19:09:20 +00:00
confirmBestConnection ( ) ;
2017-03-23 16:11:35 +00:00
}
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : handleError ( int errorCode ) {
2018-04-23 10:24:03 +00:00
destroyAllConnections ( ) ;
2018-04-24 19:09:20 +00:00
_waitForConnectedTimer . cancel ( ) ;
2015-06-10 12:48:26 +00:00
2017-03-23 16:11:35 +00:00
if ( errorCode = = - 404 ) {
2019-11-20 11:50:19 +00:00
destroyTemporaryKey ( ) ;
} else {
MTP_LOG ( _shiftedDcId , ( " Restarting after error in connection, error code: %1... " ) . arg ( errorCode ) ) ;
return restart ( ) ;
2015-06-10 12:48:26 +00:00
}
2014-05-30 08:53:19 +00:00
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : destroyTemporaryKey ( ) {
2019-11-20 11:50:19 +00:00
if ( _instance - > isKeysDestroyer ( ) ) {
LOG ( ( " MTP Info: -404 error received in destroyer %1, assuming key was destroyed. " ) . arg ( _shiftedDcId ) ) ;
2019-11-20 13:33:45 +00:00
_instance - > keyWasPossiblyDestroyed ( _shiftedDcId ) ;
2019-11-20 11:50:19 +00:00
return ;
}
LOG ( ( " MTP Info: -404 error received in %1 with temporary key, assuming it was destroyed. " ) . arg ( _shiftedDcId ) ) ;
2019-11-20 09:16:53 +00:00
releaseKeyCreationOnFail ( ) ;
2019-11-20 11:50:19 +00:00
if ( _encryptionKey ) {
_sessionData - > destroyTemporaryKey ( _encryptionKey - > keyId ( ) ) ;
2019-11-15 13:04:32 +00:00
}
2019-11-19 10:10:51 +00:00
applyAuthKey ( nullptr ) ;
2019-11-20 11:50:19 +00:00
restart ( ) ;
2014-05-30 08:53:19 +00:00
}
2019-12-02 13:10:19 +00:00
bool SessionPrivate : : sendSecureRequest (
2019-11-22 09:15:38 +00:00
SerializedRequest & & request ,
2019-11-18 12:53:37 +00:00
bool needAnyResponse ) {
2019-11-14 13:34:58 +00:00
# ifdef TDESKTOP_MTPROTO_OLD
const auto oldPadding = true ;
# else // TDESKTOP_MTPROTO_OLD
const auto oldPadding = false ;
# endif // TDESKTOP_MTPROTO_OLD
request . addPadding ( _connection - > requiresExtendedPadding ( ) , oldPadding ) ;
2014-05-30 08:53:19 +00:00
uint32 fullSize = request - > size ( ) ;
2018-06-25 18:55:27 +00:00
if ( fullSize < 9 ) {
return false ;
}
2014-05-30 08:53:19 +00:00
2018-06-25 18:55:27 +00:00
auto messageSize = request . messageSize ( ) ;
if ( messageSize < 5 | | fullSize < messageSize + 4 ) {
return false ;
}
2016-01-11 15:43:29 +00:00
2019-11-20 10:41:14 +00:00
memcpy ( request - > data ( ) + 0 , & _sessionSalt , 2 * sizeof ( mtpPrime ) ) ;
memcpy ( request - > data ( ) + 2 , & _sessionId , 2 * sizeof ( mtpPrime ) ) ;
2014-05-30 08:53:19 +00:00
2017-06-26 17:38:16 +00:00
auto from = request - > constData ( ) + 4 ;
2019-11-21 10:37:39 +00:00
MTP_LOG ( _shiftedDcId , ( " Send: " )
2019-12-02 13:10:19 +00:00
+ DumpToText ( from , from + messageSize )
2019-11-21 10:37:39 +00:00
+ QString ( " (protocolDcId:%1,key:%2) "
) . arg ( getProtocolDcId ( )
) . arg ( _encryptionKey - > keyId ( ) ) ) ;
2014-05-30 08:53:19 +00:00
2016-12-31 08:58:56 +00:00
# ifdef TDESKTOP_MTPROTO_OLD
uint32 padding = fullSize - 4 - messageSize ;
2014-05-30 08:53:19 +00:00
uchar encryptedSHA [ 20 ] ;
MTPint128 & msgKey ( * ( MTPint128 * ) ( encryptedSHA + 4 ) ) ;
2018-06-25 18:55:27 +00:00
hashSha1 (
request - > constData ( ) ,
( fullSize - padding ) * sizeof ( mtpPrime ) ,
encryptedSHA ) ;
2019-11-14 07:13:17 +00:00
auto packet = _connection - > prepareSecurePacket ( _keyId , msgKey , fullSize ) ;
2018-06-25 18:55:27 +00:00
const auto prefix = packet . size ( ) ;
packet . resize ( prefix + fullSize ) ;
aesIgeEncrypt_oldmtp (
request - > constData ( ) ,
& packet [ prefix ] ,
fullSize * sizeof ( mtpPrime ) ,
2019-11-20 11:50:19 +00:00
_encryptionKey ,
2018-06-25 18:55:27 +00:00
msgKey ) ;
2016-12-31 08:58:56 +00:00
# else // TDESKTOP_MTPROTO_OLD
uchar encryptedSHA256 [ 32 ] ;
MTPint128 & msgKey ( * ( MTPint128 * ) ( encryptedSHA256 + 8 ) ) ;
SHA256_CTX msgKeyLargeContext ;
SHA256_Init ( & msgKeyLargeContext ) ;
2019-11-20 11:50:19 +00:00
SHA256_Update ( & msgKeyLargeContext , _encryptionKey - > partForMsgKey ( true ) , 32 ) ;
2016-12-31 08:58:56 +00:00
SHA256_Update ( & msgKeyLargeContext , request - > constData ( ) , fullSize * sizeof ( mtpPrime ) ) ;
SHA256_Final ( encryptedSHA256 , & msgKeyLargeContext ) ;
2019-11-14 07:13:17 +00:00
auto packet = _connection - > prepareSecurePacket ( _keyId , msgKey , fullSize ) ;
2018-06-25 18:55:27 +00:00
const auto prefix = packet . size ( ) ;
packet . resize ( prefix + fullSize ) ;
2016-12-31 08:58:56 +00:00
2018-06-25 18:55:27 +00:00
aesIgeEncrypt (
request - > constData ( ) ,
& packet [ prefix ] ,
fullSize * sizeof ( mtpPrime ) ,
2019-11-20 11:50:19 +00:00
_encryptionKey ,
2018-06-25 18:55:27 +00:00
msgKey ) ;
2016-12-31 08:58:56 +00:00
# endif // TDESKTOP_MTPROTO_OLD
2016-01-11 15:43:29 +00:00
2014-05-30 08:53:19 +00:00
DEBUG_LOG ( ( " MTP Info: sending request, size: %1, num: %2, time: %3 " ) . arg ( fullSize + 6 ) . arg ( ( * request ) [ 4 ] ) . arg ( ( * request ) [ 5 ] ) ) ;
2019-11-15 13:04:32 +00:00
_connection - > setSentEncryptedWithKeyId ( _keyId ) ;
2018-06-25 18:55:27 +00:00
_connection - > sendData ( std : : move ( packet ) ) ;
2014-05-30 08:53:19 +00:00
if ( needAnyResponse ) {
2018-06-25 18:55:27 +00:00
onSentSome ( ( prefix + fullSize ) * sizeof ( mtpPrime ) ) ;
2014-05-30 08:53:19 +00:00
}
return true ;
}
2019-12-02 13:10:19 +00:00
mtpRequestId SessionPrivate : : wasSent ( mtpMsgId msgId ) const {
2019-11-22 09:06:48 +00:00
if ( msgId = = _pingMsgId | | msgId = = _bindMsgId ) {
return mtpRequestId ( 0xFFFFFFFF ) ;
}
2019-12-02 10:32:09 +00:00
if ( const auto i = _resendingIds . find ( msgId ) ; i ! = end ( _resendingIds ) ) {
return i - > second ;
}
if ( const auto i = _ackedIds . find ( msgId ) ; i ! = end ( _ackedIds ) ) {
return i - > second ;
}
if ( const auto i = _sentContainers . find ( msgId ) ; i ! = end ( _sentContainers ) ) {
return mtpRequestId ( 0xFFFFFFFF ) ;
}
2014-05-30 08:53:19 +00:00
{
2019-11-14 07:13:17 +00:00
QReadLocker locker ( _sessionData - > haveSentMutex ( ) ) ;
const auto & haveSent = _sessionData - > haveSentMap ( ) ;
2019-11-22 09:15:38 +00:00
const auto i = haveSent . find ( msgId ) ;
if ( i ! = haveSent . end ( ) ) {
return i - > second - > requestId
? i - > second - > requestId
2018-06-25 18:55:27 +00:00
: mtpRequestId ( 0xFFFFFFFF ) ;
}
2014-05-30 08:53:19 +00:00
}
return 0 ;
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : clearUnboundKeyCreator ( ) {
2019-11-20 09:16:53 +00:00
if ( _keyCreator ) {
_keyCreator - > stop ( ) ;
2014-05-30 08:53:19 +00:00
}
}
2019-12-02 13:10:19 +00:00
void SessionPrivate : : releaseKeyCreationOnFail ( ) {
2019-11-20 09:16:53 +00:00
if ( ! _keyCreator ) {
2019-11-19 10:10:51 +00:00
return ;
}
2019-11-20 09:16:53 +00:00
_keyCreator = nullptr ;
2019-11-19 10:10:51 +00:00
_sessionData - > releaseKeyCreationOnFail ( ) ;
}
2019-12-02 13:10:19 +00:00
} // namespace details
2016-03-24 08:57:11 +00:00
} // namespace MTP