diff --git a/Telegram/SourceFiles/application.cpp b/Telegram/SourceFiles/application.cpp index 3189c73f8..e3a454a11 100644 --- a/Telegram/SourceFiles/application.cpp +++ b/Telegram/SourceFiles/application.cpp @@ -910,7 +910,7 @@ void AppClass::killDownloadSessions() { for (QMap::iterator i = killDownloadSessionTimes.begin(); i != killDownloadSessionTimes.end(); ) { if (i.value() <= ms) { for (int j = 0; j < MTPDownloadSessionsCount; ++j) { - MTP::stopSession(MTP::dld(j) + i.key()); + MTP::stopSession(MTP::dldDcId(i.key(), j)); } i = killDownloadSessionTimes.erase(i); } else { diff --git a/Telegram/SourceFiles/fileuploader.cpp b/Telegram/SourceFiles/fileuploader.cpp index a9388ad85..e16bdc98d 100644 --- a/Telegram/SourceFiles/fileuploader.cpp +++ b/Telegram/SourceFiles/fileuploader.cpp @@ -103,7 +103,7 @@ void FileUploader::currentFailed() { void FileUploader::killSessions() { for (int i = 0; i < MTPUploadSessionsCount; ++i) { - MTP::stopSession(MTP::upl(i)); + MTP::stopSession(MTP::uplDcId(i)); } } @@ -187,9 +187,9 @@ void FileUploader::sendNext() { } mtpRequestId requestId; if (i->docSize > UseBigFilesFrom) { - requestId = MTP::send(MTPupload_SaveBigFilePart(MTP_long(i->id()), MTP_int(i->docSentParts), MTP_int(i->docPartsCount), MTP_string(toSend)), rpcDone(&FileUploader::partLoaded), rpcFail(&FileUploader::partFailed), MTP::upl(todc)); + requestId = MTP::send(MTPupload_SaveBigFilePart(MTP_long(i->id()), MTP_int(i->docSentParts), MTP_int(i->docPartsCount), MTP_string(toSend)), rpcDone(&FileUploader::partLoaded), rpcFail(&FileUploader::partFailed), MTP::uplDcId(todc)); } else { - requestId = MTP::send(MTPupload_SaveFilePart(MTP_long(i->id()), MTP_int(i->docSentParts), MTP_string(toSend)), rpcDone(&FileUploader::partLoaded), rpcFail(&FileUploader::partFailed), MTP::upl(todc)); + requestId = MTP::send(MTPupload_SaveFilePart(MTP_long(i->id()), MTP_int(i->docSentParts), MTP_string(toSend)), rpcDone(&FileUploader::partLoaded), rpcFail(&FileUploader::partFailed), MTP::uplDcId(todc)); } docRequestsSent.insert(requestId, i->docSentParts); dcMap.insert(requestId, todc); @@ -200,7 +200,7 @@ void FileUploader::sendNext() { } else { UploadFileParts::iterator part = parts.begin(); - mtpRequestId requestId = MTP::send(MTPupload_SaveFilePart(MTP_long(partsOfId), MTP_int(part.key()), MTP_string(part.value())), rpcDone(&FileUploader::partLoaded), rpcFail(&FileUploader::partFailed), MTP::upl(todc)); + mtpRequestId requestId = MTP::send(MTPupload_SaveFilePart(MTP_long(partsOfId), MTP_int(part.key()), MTP_string(part.value())), rpcDone(&FileUploader::partLoaded), rpcFail(&FileUploader::partFailed), MTP::uplDcId(todc)); requestsSent.insert(requestId, part.value()); dcMap.insert(requestId, todc); sentSize += part.value().size(); @@ -246,7 +246,7 @@ void FileUploader::clear() { dcMap.clear(); sentSize = 0; for (int32 i = 0; i < MTPUploadSessionsCount; ++i) { - MTP::stopSession(MTP::upl(i)); + MTP::stopSession(MTP::uplDcId(i)); sentSizes[i] = 0; } killSessionsTimer.stop(); diff --git a/Telegram/SourceFiles/localstorage.cpp b/Telegram/SourceFiles/localstorage.cpp index 8c4bdcb1e..102e5a9c0 100644 --- a/Telegram/SourceFiles/localstorage.cpp +++ b/Telegram/SourceFiles/localstorage.cpp @@ -886,7 +886,7 @@ namespace { stream >> dcIdWithShift >> flags >> ip >> port; if (!_checkStreamStatus(stream)) return false; - if (_dcOpts) _dcOpts->insert(dcIdWithShift, MTP::DcOption(dcIdWithShift % _mtp_internal::dcShift, MTPDdcOption::Flags(flags), ip.toUtf8().constData(), port)); + if (_dcOpts) _dcOpts->insert(dcIdWithShift, MTP::DcOption(MTP::bareDcId(dcIdWithShift), MTPDdcOption::Flags(flags), ip.toUtf8().constData(), port)); } break; case dbiChatSizeMax: { @@ -931,7 +931,7 @@ namespace { if (!_checkStreamStatus(stream)) return false; DEBUG_LOG(("MTP Info: key found, dc %1, key: %2").arg(dcId).arg(Logs::mb(key, 256).str())); - dcId = dcId % _mtp_internal::dcShift; + dcId = MTP::bareDcId(dcId); mtpAuthKeyPtr keyPtr(new mtpAuthKey()); keyPtr->setKey(key); keyPtr->setDC(dcId); @@ -2142,7 +2142,7 @@ namespace Local { const BuiltInDc *bdcs = builtInDcs(); for (int i = 0, l = builtInDcsCount(); i < l; ++i) { MTPDdcOption::Flags flags = 0; - int idWithShift = bdcs[i].id + (flags * _mtp_internal::dcShift); + MTP::ShiftedDcId idWithShift = MTP::shiftDcId(bdcs[i].id, flags); dcOpts.insert(idWithShift, MTP::DcOption(bdcs[i].id, flags, bdcs[i].ip, bdcs[i].port)); DEBUG_LOG(("MTP Info: adding built in DC %1 connect option: %2:%3").arg(bdcs[i].id).arg(bdcs[i].ip).arg(bdcs[i].port)); } @@ -2150,7 +2150,7 @@ namespace Local { const BuiltInDc *bdcsipv6 = builtInDcsIPv6(); for (int i = 0, l = builtInDcsCountIPv6(); i < l; ++i) { MTPDdcOption::Flags flags = MTPDdcOption::Flag::f_ipv6; - int idWithShift = bdcsipv6[i].id + (flags * _mtp_internal::dcShift); + MTP::ShiftedDcId idWithShift = MTP::shiftDcId(bdcsipv6[i].id, flags); dcOpts.insert(idWithShift, MTP::DcOption(bdcsipv6[i].id, flags, bdcsipv6[i].ip, bdcsipv6[i].port)); DEBUG_LOG(("MTP Info: adding built in DC %1 IPv6 connect option: %2:%3").arg(bdcsipv6[i].id).arg(bdcsipv6[i].ip).arg(bdcsipv6[i].port)); } @@ -2189,7 +2189,7 @@ namespace Local { const BuiltInDc *bdcs = builtInDcs(); for (int i = 0, l = builtInDcsCount(); i < l; ++i) { MTPDdcOption::Flags flags = 0; - int idWithShift = bdcs[i].id + (flags * _mtp_internal::dcShift); + MTP::ShiftedDcId idWithShift = MTP::shiftDcId(bdcs[i].id, flags); dcOpts.insert(idWithShift, MTP::DcOption(bdcs[i].id, flags, bdcs[i].ip, bdcs[i].port)); DEBUG_LOG(("MTP Info: adding built in DC %1 connect option: %2:%3").arg(bdcs[i].id).arg(bdcs[i].ip).arg(bdcs[i].port)); } @@ -2197,7 +2197,7 @@ namespace Local { const BuiltInDc *bdcsipv6 = builtInDcsIPv6(); for (int i = 0, l = builtInDcsCountIPv6(); i < l; ++i) { MTPDdcOption::Flags flags = MTPDdcOption::Flag::f_ipv6; - int idWithShift = bdcsipv6[i].id + (flags * _mtp_internal::dcShift); + MTP::ShiftedDcId idWithShift = MTP::shiftDcId(bdcsipv6[i].id, flags); dcOpts.insert(idWithShift, MTP::DcOption(bdcsipv6[i].id, flags, bdcsipv6[i].ip, bdcsipv6[i].port)); DEBUG_LOG(("MTP Info: adding built in DC %1 IPv6 connect option: %2:%3").arg(bdcsipv6[i].id).arg(bdcsipv6[i].ip).arg(bdcsipv6[i].port)); } diff --git a/Telegram/SourceFiles/logs.cpp b/Telegram/SourceFiles/logs.cpp index 612eebff1..371c8e20b 100644 --- a/Telegram/SourceFiles/logs.cpp +++ b/Telegram/SourceFiles/logs.cpp @@ -83,7 +83,7 @@ QString _logsEntryStart() { QDateTime tm(QDateTime::currentDateTime()); QThread *thread = QThread::currentThread(); - MTPThread *mtpThread = qobject_cast(thread); + MTP::internal::Thread *mtpThread = qobject_cast(thread); uint threadId = mtpThread ? mtpThread->getThreadId() : 0; return QString("[%1 %2-%3]").arg(tm.toString("hh:mm:ss.zzz")).arg(QString("%1").arg(threadId, 2, 10, QChar('0'))).arg(++index, 7, 10, QChar('0')); diff --git a/Telegram/SourceFiles/mtproto/connection.cpp b/Telegram/SourceFiles/mtproto/connection.cpp index ab307b48a..a5cb1d6bf 100644 --- a/Telegram/SourceFiles/mtproto/connection.cpp +++ b/Telegram/SourceFiles/mtproto/connection.cpp @@ -36,6 +36,8 @@ using std::string; namespace MTP { namespace internal { +namespace { + bool parsePQ(const string &pqStr, string &pStr, string &qStr) { if (pqStr.length() > 8) return false; // more than 64 bit pq @@ -262,7 +264,7 @@ private: BN_CTX *ctx; }; -typedef QMap RSAPublicKeys; +typedef QMap RSAPublicKeys; RSAPublicKeys InitRSAPublicKeys() { DEBUG_LOG(("MTP Info: RSA public keys list creation")); @@ -283,30 +285,29 @@ RSAPublicKeys InitRSAPublicKeys() { return result; } -} // namespace internal -} // namespace MTP +} // namespace -uint32 MTPThreadIdIncrement = 0; +uint32 ThreadIdIncrement = 0; -MTPThread::MTPThread() : QThread(0) -, _threadId(++MTPThreadIdIncrement) { +Thread::Thread() : QThread(nullptr) +, _threadId(++ThreadIdIncrement) { } -uint32 MTPThread::getThreadId() const { +uint32 Thread::getThreadId() const { return _threadId; } -MTPThread::~MTPThread() { +Thread::~Thread() { } -MTProtoConnection::MTProtoConnection() : thread(nullptr), data(nullptr) { +Connection::Connection() : thread(nullptr), data(nullptr) { } -int32 MTProtoConnection::start(MTPSessionData *sessionData, int32 dc) { +int32 Connection::start(SessionData *sessionData, int32 dc) { t_assert(thread == nullptr && data == nullptr); - thread = new MTPThread(); - data = new MTProtoConnectionPrivate(thread, this, sessionData, dc); + thread = new Thread(); + data = new ConnectionPrivate(thread, this, sessionData, dc); dc = data->getDC(); if (!dc) { @@ -321,15 +322,15 @@ int32 MTProtoConnection::start(MTPSessionData *sessionData, int32 dc) { return dc; } -void MTProtoConnection::kill() { +void Connection::kill() { t_assert(data != nullptr && thread != nullptr); data->stop(); data = nullptr; // will be deleted in thread::finished signal thread->quit(); - _mtp_internal::queueQuittingConnection(this); + queueQuittingConnection(this); } -void MTProtoConnection::waitTillFinish() { +void Connection::waitTillFinish() { t_assert(data == nullptr && thread != nullptr); DEBUG_LOG(("Waiting for connectionThread to finish")); @@ -338,224 +339,229 @@ void MTProtoConnection::waitTillFinish() { thread = nullptr; } -int32 MTProtoConnection::state() const { +int32 Connection::state() const { t_assert(data != nullptr && thread != nullptr); return data->getState(); } -QString MTProtoConnection::transport() const { +QString Connection::transport() const { t_assert(data != nullptr && thread != nullptr); return data->transport(); } -MTProtoConnection::~MTProtoConnection() { +Connection::~Connection() { t_assert(data == nullptr && thread == nullptr); } namespace { - mtpBuffer _handleHttpResponse(QNetworkReply *reply) { - QByteArray response = reply->readAll(); - TCP_LOG(("HTTP Info: read %1 bytes").arg(response.size())); - if (response.isEmpty()) return mtpBuffer(); +mtpBuffer _handleHttpResponse(QNetworkReply *reply) { + QByteArray response = reply->readAll(); + TCP_LOG(("HTTP Info: read %1 bytes").arg(response.size())); - if (response.size() & 0x03 || response.size() < 8) { - LOG(("HTTP Error: bad response size %1").arg(response.size())); - return mtpBuffer(1, -500); - } + if (response.isEmpty()) return mtpBuffer(); - mtpBuffer data(response.size() >> 2); - memcpy(data.data(), response.constData(), response.size()); - - return data; + if (response.size() & 0x03 || response.size() < 8) { + LOG(("HTTP Error: bad response size %1").arg(response.size())); + return mtpBuffer(1, -500); } - bool _handleHttpError(QNetworkReply *reply) { // returnes "maybe bad key" - bool mayBeBadKey = false; - - QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute); - if (statusCode.isValid()) { - int status = statusCode.toInt(); - mayBeBadKey = (status == 410); - if (status == 429) { - LOG(("Protocol Error: 429 flood code returned!")); - } - } - - switch (reply->error()) { - case QNetworkReply::ConnectionRefusedError: LOG(("HTTP Error: connection refused - %1").arg(reply->errorString())); break; - case QNetworkReply::RemoteHostClosedError: LOG(("HTTP Error: remote host closed - %1").arg(reply->errorString())); break; - case QNetworkReply::HostNotFoundError: LOG(("HTTP Error: host not found - %2").arg(reply->error()).arg(reply->errorString())); break; - case QNetworkReply::TimeoutError: LOG(("HTTP Error: timeout - %2").arg(reply->error()).arg(reply->errorString())); break; - case QNetworkReply::OperationCanceledError: LOG(("HTTP Error: cancelled - %2").arg(reply->error()).arg(reply->errorString())); break; - case QNetworkReply::SslHandshakeFailedError: - case QNetworkReply::TemporaryNetworkFailureError: - case QNetworkReply::NetworkSessionFailedError: - case QNetworkReply::BackgroundRequestNotAllowedError: - case QNetworkReply::UnknownNetworkError: LOG(("HTTP Error: network error %1 - %2").arg(reply->error()).arg(reply->errorString())); break; - - // proxy errors (101-199): - case QNetworkReply::ProxyConnectionRefusedError: - case QNetworkReply::ProxyConnectionClosedError: - case QNetworkReply::ProxyNotFoundError: - case QNetworkReply::ProxyTimeoutError: - case QNetworkReply::ProxyAuthenticationRequiredError: - case QNetworkReply::UnknownProxyError:LOG(("HTTP Error: proxy error %1 - %2").arg(reply->error()).arg(reply->errorString())); break; - - // content errors (201-299): - case QNetworkReply::ContentAccessDenied: - case QNetworkReply::ContentOperationNotPermittedError: - case QNetworkReply::ContentNotFoundError: - case QNetworkReply::AuthenticationRequiredError: - case QNetworkReply::ContentReSendError: - case QNetworkReply::UnknownContentError: LOG(("HTTP Error: content error %1 - %2").arg(reply->error()).arg(reply->errorString())); break; - - // protocol errors - case QNetworkReply::ProtocolUnknownError: - case QNetworkReply::ProtocolInvalidOperationError: - case QNetworkReply::ProtocolFailure: LOG(("HTTP Error: protocol error %1 - %2").arg(reply->error()).arg(reply->errorString())); break; - }; - TCP_LOG(("HTTP Error %1, restarting! - %2").arg(reply->error()).arg(reply->errorString())); - - return mayBeBadKey; - } - - uint32 _tcpPacketSize(const char *packet) { // must have at least 4 bytes readable - uint32 result = (packet[0] > 0) ? packet[0] : 0; - if (result == 0x7f) { - const uchar *bytes = reinterpret_cast(packet); - result = (((uint32(bytes[3]) << 8) | uint32(bytes[2])) << 8) | uint32(bytes[1]); - return (result << 2) + 4; - } - return (result << 2) + 1; - } - - mtpBuffer _handleTcpResponse(const char *packet, uint32 length) { - if (length < 5 || length > MTPPacketSizeMax) { - LOG(("TCP Error: bad packet size %1").arg(length)); - return mtpBuffer(1, -500); - } - int32 size = packet[0], len = length - 1; - if (size == 0x7f) { - const uchar *bytes = reinterpret_cast(packet); - size = (((uint32(bytes[3]) << 8) | uint32(bytes[2])) << 8) | uint32(bytes[1]); - len -= 3; - } - if (size * int32(sizeof(mtpPrime)) != len) { - LOG(("TCP Error: bad packet header")); - TCP_LOG(("TCP Error: bad packet header, packet: %1").arg(Logs::mb(packet, length).str())); - return mtpBuffer(1, -500); - } - const mtpPrime *packetdata = reinterpret_cast(packet + (length - len)); - TCP_LOG(("TCP Info: packet received, size = %1").arg(size * sizeof(mtpPrime))); - if (size == 1) { - if (*packetdata == -429) { - LOG(("Protocol Error: -429 flood code returned!")); - } else { - LOG(("TCP Error: error packet received, code = %1").arg(*packetdata)); - } - return mtpBuffer(1, *packetdata); - } - - mtpBuffer data(size); - memcpy(data.data(), packetdata, size * sizeof(mtpPrime)); - - return data; - } - - void _handleTcpError(QAbstractSocket::SocketError e, QTcpSocket &sock) { - switch (e) { - case QAbstractSocket::ConnectionRefusedError: - LOG(("TCP Error: socket connection refused - %1").arg(sock.errorString())); - break; - - case QAbstractSocket::RemoteHostClosedError: - TCP_LOG(("TCP Info: remote host closed socket connection - %1").arg(sock.errorString())); - break; - - case QAbstractSocket::HostNotFoundError: - LOG(("TCP Error: host not found - %1").arg(sock.errorString())); - break; - - case QAbstractSocket::SocketTimeoutError: - LOG(("TCP Error: socket timeout - %1").arg(sock.errorString())); - break; - - case QAbstractSocket::NetworkError: - LOG(("TCP Error: network - %1").arg(sock.errorString())); - break; - - case QAbstractSocket::ProxyAuthenticationRequiredError: - case QAbstractSocket::ProxyConnectionRefusedError: - case QAbstractSocket::ProxyConnectionClosedError: - case QAbstractSocket::ProxyConnectionTimeoutError: - case QAbstractSocket::ProxyNotFoundError: - case QAbstractSocket::ProxyProtocolError: - LOG(("TCP Error: proxy (%1) - %2").arg(e).arg(sock.errorString())); - break; - - default: - LOG(("TCP Error: other (%1) - %2").arg(e).arg(sock.errorString())); - break; - } - - TCP_LOG(("TCP Error %1, restarting! - %2").arg(e).arg(sock.errorString())); - } - - mtpBuffer _preparePQFake(const MTPint128 &nonce) { - MTPReq_pq req_pq(nonce); - mtpBuffer buffer; - uint32 requestSize = req_pq.innerLength() >> 2; - - buffer.resize(0); - buffer.reserve(8 + requestSize); - buffer.push_back(0); // tcp packet len - buffer.push_back(0); // tcp packet num - buffer.push_back(0); - buffer.push_back(0); - buffer.push_back(0); - buffer.push_back(unixtime()); - buffer.push_back(requestSize * 4); - req_pq.write(buffer); - buffer.push_back(0); // tcp crc32 hash - - return buffer; - } - - MTPResPQ _readPQFakeReply(const mtpBuffer &buffer) { - const mtpPrime *answer(buffer.constData()); - uint32 len = buffer.size(); - if (len < 5) { - LOG(("Fake PQ Error: bad request answer, len = %1").arg(len * sizeof(mtpPrime))); - DEBUG_LOG(("Fake PQ Error: answer bytes %1").arg(Logs::mb(answer, len * sizeof(mtpPrime)).str())); - throw Exception("bad pq reply"); - } - if (answer[0] != 0 || answer[1] != 0 || (((uint32)answer[2]) & 0x03) != 1/* || (unixtime() - answer[3] > 300) || (answer[3] - unixtime() > 60)*/) { // didnt sync time yet - LOG(("Fake PQ Error: bad request answer start (%1 %2 %3)").arg(answer[0]).arg(answer[1]).arg(answer[2])); - DEBUG_LOG(("Fake PQ Error: answer bytes %1").arg(Logs::mb(answer, len * sizeof(mtpPrime)).str())); - throw Exception("bad pq reply"); - } - uint32 answerLen = (uint32)answer[4]; - if (answerLen != (len - 5) * sizeof(mtpPrime)) { - LOG(("Fake PQ Error: bad request answer %1 <> %2").arg(answerLen).arg((len - 5) * sizeof(mtpPrime))); - DEBUG_LOG(("Fake PQ Error: answer bytes %1").arg(Logs::mb(answer, len * sizeof(mtpPrime)).str())); - throw Exception("bad pq reply"); - } - const mtpPrime *from(answer + 5), *end(from + len - 5); - MTPResPQ response; - response.read(from, end); - return response; - } + mtpBuffer data(response.size() >> 2); + memcpy(data.data(), response.constData(), response.size()); + return data; } -MTPabstractTcpConnection::MTPabstractTcpConnection() : -packetNum(0), packetRead(0), packetLeft(0), readingToShort(true), currentPos((char*)shortBuffer) { +bool _handleHttpError(QNetworkReply *reply) { // returnes "maybe bad key" + bool mayBeBadKey = false; + + QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute); + if (statusCode.isValid()) { + int status = statusCode.toInt(); + mayBeBadKey = (status == 410); + if (status == 429) { + LOG(("Protocol Error: 429 flood code returned!")); + } + } + + switch (reply->error()) { + case QNetworkReply::ConnectionRefusedError: LOG(("HTTP Error: connection refused - %1").arg(reply->errorString())); break; + case QNetworkReply::RemoteHostClosedError: LOG(("HTTP Error: remote host closed - %1").arg(reply->errorString())); break; + case QNetworkReply::HostNotFoundError: LOG(("HTTP Error: host not found - %2").arg(reply->error()).arg(reply->errorString())); break; + case QNetworkReply::TimeoutError: LOG(("HTTP Error: timeout - %2").arg(reply->error()).arg(reply->errorString())); break; + case QNetworkReply::OperationCanceledError: LOG(("HTTP Error: cancelled - %2").arg(reply->error()).arg(reply->errorString())); break; + case QNetworkReply::SslHandshakeFailedError: + case QNetworkReply::TemporaryNetworkFailureError: + case QNetworkReply::NetworkSessionFailedError: + case QNetworkReply::BackgroundRequestNotAllowedError: + case QNetworkReply::UnknownNetworkError: LOG(("HTTP Error: network error %1 - %2").arg(reply->error()).arg(reply->errorString())); break; + + // proxy errors (101-199): + case QNetworkReply::ProxyConnectionRefusedError: + case QNetworkReply::ProxyConnectionClosedError: + case QNetworkReply::ProxyNotFoundError: + case QNetworkReply::ProxyTimeoutError: + case QNetworkReply::ProxyAuthenticationRequiredError: + case QNetworkReply::UnknownProxyError:LOG(("HTTP Error: proxy error %1 - %2").arg(reply->error()).arg(reply->errorString())); break; + + // content errors (201-299): + case QNetworkReply::ContentAccessDenied: + case QNetworkReply::ContentOperationNotPermittedError: + case QNetworkReply::ContentNotFoundError: + case QNetworkReply::AuthenticationRequiredError: + case QNetworkReply::ContentReSendError: + case QNetworkReply::UnknownContentError: LOG(("HTTP Error: content error %1 - %2").arg(reply->error()).arg(reply->errorString())); break; + + // protocol errors + case QNetworkReply::ProtocolUnknownError: + case QNetworkReply::ProtocolInvalidOperationError: + case QNetworkReply::ProtocolFailure: LOG(("HTTP Error: protocol error %1 - %2").arg(reply->error()).arg(reply->errorString())); break; + }; + TCP_LOG(("HTTP Error %1, restarting! - %2").arg(reply->error()).arg(reply->errorString())); + + return mayBeBadKey; } -void MTPabstractTcpConnection::socketRead() { +uint32 _tcpPacketSize(const char *packet) { // must have at least 4 bytes readable + uint32 result = (packet[0] > 0) ? packet[0] : 0; + if (result == 0x7f) { + const uchar *bytes = reinterpret_cast(packet); + result = (((uint32(bytes[3]) << 8) | uint32(bytes[2])) << 8) | uint32(bytes[1]); + return (result << 2) + 4; + } + return (result << 2) + 1; +} + +mtpBuffer _handleTcpResponse(const char *packet, uint32 length) { + if (length < 5 || length > MTPPacketSizeMax) { + LOG(("TCP Error: bad packet size %1").arg(length)); + return mtpBuffer(1, -500); + } + int32 size = packet[0], len = length - 1; + if (size == 0x7f) { + const uchar *bytes = reinterpret_cast(packet); + size = (((uint32(bytes[3]) << 8) | uint32(bytes[2])) << 8) | uint32(bytes[1]); + len -= 3; + } + if (size * int32(sizeof(mtpPrime)) != len) { + LOG(("TCP Error: bad packet header")); + TCP_LOG(("TCP Error: bad packet header, packet: %1").arg(Logs::mb(packet, length).str())); + return mtpBuffer(1, -500); + } + const mtpPrime *packetdata = reinterpret_cast(packet + (length - len)); + TCP_LOG(("TCP Info: packet received, size = %1").arg(size * sizeof(mtpPrime))); + if (size == 1) { + if (*packetdata == -429) { + LOG(("Protocol Error: -429 flood code returned!")); + } else { + LOG(("TCP Error: error packet received, code = %1").arg(*packetdata)); + } + return mtpBuffer(1, *packetdata); + } + + mtpBuffer data(size); + memcpy(data.data(), packetdata, size * sizeof(mtpPrime)); + + return data; +} + +void _handleTcpError(QAbstractSocket::SocketError e, QTcpSocket &sock) { + switch (e) { + case QAbstractSocket::ConnectionRefusedError: + LOG(("TCP Error: socket connection refused - %1").arg(sock.errorString())); + break; + + case QAbstractSocket::RemoteHostClosedError: + TCP_LOG(("TCP Info: remote host closed socket connection - %1").arg(sock.errorString())); + break; + + case QAbstractSocket::HostNotFoundError: + LOG(("TCP Error: host not found - %1").arg(sock.errorString())); + break; + + case QAbstractSocket::SocketTimeoutError: + LOG(("TCP Error: socket timeout - %1").arg(sock.errorString())); + break; + + case QAbstractSocket::NetworkError: + LOG(("TCP Error: network - %1").arg(sock.errorString())); + break; + + case QAbstractSocket::ProxyAuthenticationRequiredError: + case QAbstractSocket::ProxyConnectionRefusedError: + case QAbstractSocket::ProxyConnectionClosedError: + case QAbstractSocket::ProxyConnectionTimeoutError: + case QAbstractSocket::ProxyNotFoundError: + case QAbstractSocket::ProxyProtocolError: + LOG(("TCP Error: proxy (%1) - %2").arg(e).arg(sock.errorString())); + break; + + default: + LOG(("TCP Error: other (%1) - %2").arg(e).arg(sock.errorString())); + break; + } + + TCP_LOG(("TCP Error %1, restarting! - %2").arg(e).arg(sock.errorString())); +} + +mtpBuffer _preparePQFake(const MTPint128 &nonce) { + MTPReq_pq req_pq(nonce); + mtpBuffer buffer; + uint32 requestSize = req_pq.innerLength() >> 2; + + buffer.resize(0); + buffer.reserve(8 + requestSize); + buffer.push_back(0); // tcp packet len + buffer.push_back(0); // tcp packet num + buffer.push_back(0); + buffer.push_back(0); + buffer.push_back(0); + buffer.push_back(unixtime()); + buffer.push_back(requestSize * 4); + req_pq.write(buffer); + buffer.push_back(0); // tcp crc32 hash + + return buffer; +} + +MTPResPQ _readPQFakeReply(const mtpBuffer &buffer) { + const mtpPrime *answer(buffer.constData()); + uint32 len = buffer.size(); + if (len < 5) { + LOG(("Fake PQ Error: bad request answer, len = %1").arg(len * sizeof(mtpPrime))); + DEBUG_LOG(("Fake PQ Error: answer bytes %1").arg(Logs::mb(answer, len * sizeof(mtpPrime)).str())); + throw Exception("bad pq reply"); + } + if (answer[0] != 0 || answer[1] != 0 || (((uint32)answer[2]) & 0x03) != 1/* || (unixtime() - answer[3] > 300) || (answer[3] - unixtime() > 60)*/) { // didnt sync time yet + LOG(("Fake PQ Error: bad request answer start (%1 %2 %3)").arg(answer[0]).arg(answer[1]).arg(answer[2])); + DEBUG_LOG(("Fake PQ Error: answer bytes %1").arg(Logs::mb(answer, len * sizeof(mtpPrime)).str())); + throw Exception("bad pq reply"); + } + uint32 answerLen = (uint32)answer[4]; + if (answerLen != (len - 5) * sizeof(mtpPrime)) { + LOG(("Fake PQ Error: bad request answer %1 <> %2").arg(answerLen).arg((len - 5) * sizeof(mtpPrime))); + DEBUG_LOG(("Fake PQ Error: answer bytes %1").arg(Logs::mb(answer, len * sizeof(mtpPrime)).str())); + throw Exception("bad pq reply"); + } + const mtpPrime *from(answer + 5), *end(from + len - 5); + MTPResPQ response; + response.read(from, end); + return response; +} + +} // namespace + +AbstractTcpConnection::AbstractTcpConnection() + : packetNum(0) + , packetRead(0) + , packetLeft(0) + , readingToShort(true) + , currentPos((char*)shortBuffer) { +} + +void AbstractTcpConnection::socketRead() { if (sock.state() != QAbstractSocket::ConnectedState) { LOG(("MTP error: socket not connected in socketRead(), state: %1").arg(sock.state())); emit error(); @@ -640,7 +646,7 @@ void MTPabstractTcpConnection::socketRead() { } while (sock.state() == QAbstractSocket::ConnectedState && sock.bytesAvailable()); } -MTPautoConnection::MTPautoConnection(QThread *thread) : MTPabstractTcpConnection() +AutoConnection::AutoConnection(QThread *thread) : AbstractTcpConnection() , status(WaitingBoth) , tcpNonce(MTP::nonce()) , httpNonce(MTP::nonce()) @@ -671,7 +677,7 @@ MTPautoConnection::MTPautoConnection(QThread *thread) : MTPabstractTcpConnection connect(&sock, SIGNAL(disconnected()), this, SLOT(onSocketDisconnected())); } -void MTPautoConnection::onHttpStart() { +void AutoConnection::onHttpStart() { if (status == HttpReady) { DEBUG_LOG(("Connection Info: HTTP/%1-transport chosen by timer").arg((_flagsHttp & MTPDdcOption::Flag::f_ipv6) ? "IPv6" : "IPv4")); status = UsingHttp; @@ -680,7 +686,7 @@ void MTPautoConnection::onHttpStart() { } } -void MTPautoConnection::onSocketConnected() { +void AutoConnection::onSocketConnected() { if (status == HttpReady || status == WaitingBoth || status == WaitingTcp) { mtpBuffer buffer(_preparePQFake(tcpNonce)); @@ -695,7 +701,7 @@ void MTPautoConnection::onSocketConnected() { } } -void MTPautoConnection::onTcpTimeoutTimer() { +void AutoConnection::onTcpTimeoutTimer() { if (status == HttpReady || status == WaitingBoth || status == WaitingTcp) { if (_tcpTimeout < MTPMaxReceiveDelay) _tcpTimeout *= 2; _tcpTimeout = -_tcpTimeout; @@ -709,7 +715,7 @@ void MTPautoConnection::onTcpTimeoutTimer() { } } -void MTPautoConnection::onSocketDisconnected() { +void AutoConnection::onSocketDisconnected() { if (_tcpTimeout < 0) { _tcpTimeout = -_tcpTimeout; if (status == HttpReady || status == WaitingBoth || status == WaitingTcp) { @@ -728,7 +734,7 @@ void MTPautoConnection::onSocketDisconnected() { } } -void MTPautoConnection::sendData(mtpBuffer &buffer) { +void AutoConnection::sendData(mtpBuffer &buffer) { if (status == FinishedWork) return; if (buffer.size() < 3) { @@ -750,7 +756,7 @@ uint32 FourCharsToUInt(char ch1, char ch2, char ch3, char ch4) { return *reinterpret_cast(ch); } -void MTPautoConnection::tcpSend(mtpBuffer &buffer) { +void AutoConnection::tcpSend(mtpBuffer &buffer) { if (!packetNum) { char nonce[64]; uint32 *first = reinterpret_cast(nonce), *second = first + 1; @@ -782,7 +788,7 @@ void MTPautoConnection::tcpSend(mtpBuffer &buffer) { } } -void MTPautoConnection::httpSend(mtpBuffer &buffer) { +void AutoConnection::httpSend(mtpBuffer &buffer) { int32 requestSize = (buffer.size() - 3) * sizeof(mtpPrime); QNetworkRequest request(address); @@ -793,7 +799,7 @@ void MTPautoConnection::httpSend(mtpBuffer &buffer) { requests.insert(manager.post(request, QByteArray((const char*)(&buffer[2]), requestSize))); } -void MTPautoConnection::disconnectFromServer() { +void AutoConnection::disconnectFromServer() { if (status == FinishedWork) return; status = FinishedWork; @@ -814,7 +820,7 @@ void MTPautoConnection::disconnectFromServer() { httpStartTimer.stop(); } -void MTPautoConnection::connectTcp(const QString &addr, int32 port, MTPDdcOption::Flags flags) { +void AutoConnection::connectTcp(const QString &addr, int32 port, MTPDdcOption::Flags flags) { _addrTcp = addr; _portTcp = port; _flagsTcp = flags; @@ -823,7 +829,7 @@ void MTPautoConnection::connectTcp(const QString &addr, int32 port, MTPDdcOption sock.connectToHost(QHostAddress(_addrTcp), _portTcp); } -void MTPautoConnection::connectHttp(const QString &addr, int32 port, MTPDdcOption::Flags flags) { +void AutoConnection::connectHttp(const QString &addr, int32 port, MTPDdcOption::Flags flags) { address = QUrl(((flags & MTPDdcOption::Flag::f_ipv6) ? qsl("http://[%1]:%2/api") : qsl("http://%1:%2/api")).arg(addr).arg(80));//not p - always 80 port for http transport TCP_LOG(("HTTP Info: address is %1").arg(address.toDisplayString())); connect(&manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(requestFinished(QNetworkReply*))); @@ -839,11 +845,11 @@ void MTPautoConnection::connectHttp(const QString &addr, int32 port, MTPDdcOptio httpSend(buffer); } -bool MTPautoConnection::isConnected() const { +bool AutoConnection::isConnected() const { return (status == UsingTcp) || (status == UsingHttp); } -void MTPautoConnection::requestFinished(QNetworkReply *reply) { +void AutoConnection::requestFinished(QNetworkReply *reply) { if (status == FinishedWork) return; reply->deleteLater(); @@ -904,7 +910,7 @@ void MTPautoConnection::requestFinished(QNetworkReply *reply) { } } -void MTPautoConnection::socketPacket(const char *packet, uint32 length) { +void AutoConnection::socketPacket(const char *packet, uint32 length) { if (status == FinishedWork) return; mtpBuffer data = _handleTcpResponse(packet, length); @@ -953,19 +959,19 @@ void MTPautoConnection::socketPacket(const char *packet, uint32 length) { } } -bool MTPautoConnection::usingHttpWait() { +bool AutoConnection::usingHttpWait() { return (status == UsingHttp); } -bool MTPautoConnection::needHttpWait() { +bool AutoConnection::needHttpWait() { return (status == UsingHttp) ? requests.isEmpty() : false; } -int32 MTPautoConnection::debugState() const { +int32 AutoConnection::debugState() const { return (status == UsingHttp) ? -1 : (UsingTcp ? sock.state() : -777); } -QString MTPautoConnection::transport() const { +QString AutoConnection::transport() const { if (status == UsingTcp) { return qsl("TCP"); } else if (status == UsingHttp) { @@ -975,7 +981,7 @@ QString MTPautoConnection::transport() const { } } -void MTPautoConnection::socketError(QAbstractSocket::SocketError e) { +void AutoConnection::socketError(QAbstractSocket::SocketError e) { if (status == FinishedWork) return; _handleTcpError(e, sock); @@ -992,8 +998,11 @@ void MTPautoConnection::socketError(QAbstractSocket::SocketError e) { } } -MTPtcpConnection::MTPtcpConnection(QThread *thread) : status(WaitingTcp), -tcpNonce(MTP::nonce()), _tcpTimeout(MTPMinReceiveDelay), _flags(0) { +TCPConnection::TCPConnection(QThread *thread) + : status(WaitingTcp) + , tcpNonce(MTP::nonce()) + , _tcpTimeout(MTPMinReceiveDelay) + , _flags(0) { moveToThread(thread); tcpTimeoutTimer.moveToThread(thread); @@ -1007,7 +1016,7 @@ tcpNonce(MTP::nonce()), _tcpTimeout(MTPMinReceiveDelay), _flags(0) { connect(&sock, SIGNAL(disconnected()), this, SLOT(onSocketDisconnected())); } -void MTPtcpConnection::onSocketConnected() { +void TCPConnection::onSocketConnected() { if (status == WaitingTcp) { mtpBuffer buffer(_preparePQFake(tcpNonce)); @@ -1020,7 +1029,7 @@ void MTPtcpConnection::onSocketConnected() { } } -void MTPtcpConnection::onTcpTimeoutTimer() { +void TCPConnection::onTcpTimeoutTimer() { if (status == WaitingTcp) { if (_tcpTimeout < MTPMaxReceiveDelay) _tcpTimeout *= 2; _tcpTimeout = -_tcpTimeout; @@ -1034,7 +1043,7 @@ void MTPtcpConnection::onTcpTimeoutTimer() { } } -void MTPtcpConnection::onSocketDisconnected() { +void TCPConnection::onSocketDisconnected() { if (_tcpTimeout < 0) { _tcpTimeout = -_tcpTimeout; if (status == WaitingTcp) { @@ -1047,7 +1056,7 @@ void MTPtcpConnection::onSocketDisconnected() { } } -void MTPtcpConnection::sendData(mtpBuffer &buffer) { +void TCPConnection::sendData(mtpBuffer &buffer) { if (status == FinishedWork) return; if (buffer.size() < 3) { @@ -1088,7 +1097,7 @@ void MTPtcpConnection::sendData(mtpBuffer &buffer) { } } -void MTPtcpConnection::disconnectFromServer() { +void TCPConnection::disconnectFromServer() { if (status == FinishedWork) return; status = FinishedWork; @@ -1096,7 +1105,7 @@ void MTPtcpConnection::disconnectFromServer() { sock.close(); } -void MTPtcpConnection::connectTcp(const QString &addr, int32 port, MTPDdcOption::Flags flags) { +void TCPConnection::connectTcp(const QString &addr, int32 port, MTPDdcOption::Flags flags) { _addr = addr; _port = port; _flags = flags; @@ -1105,7 +1114,7 @@ void MTPtcpConnection::connectTcp(const QString &addr, int32 port, MTPDdcOption: sock.connectToHost(QHostAddress(_addr), _port); } -void MTPtcpConnection::socketPacket(const char *packet, uint32 length) { +void TCPConnection::socketPacket(const char *packet, uint32 length) { if (status == FinishedWork) return; mtpBuffer data = _handleTcpResponse(packet, length); @@ -1132,32 +1141,35 @@ void MTPtcpConnection::socketPacket(const char *packet, uint32 length) { } } -bool MTPtcpConnection::isConnected() const { +bool TCPConnection::isConnected() const { return (status == UsingTcp); } -int32 MTPtcpConnection::debugState() const { +int32 TCPConnection::debugState() const { return sock.state(); } -QString MTPtcpConnection::transport() const { +QString TCPConnection::transport() const { return isConnected() ? qsl("TCP") : QString(); } -void MTPtcpConnection::socketError(QAbstractSocket::SocketError e) { +void TCPConnection::socketError(QAbstractSocket::SocketError e) { if (status == FinishedWork) return; _handleTcpError(e, sock); emit error(); } -MTPhttpConnection::MTPhttpConnection(QThread *thread) : status(WaitingHttp), httpNonce(MTP::nonce()), _flags(0) { +HTTPConnection::HTTPConnection(QThread *thread) + : status(WaitingHttp) + , httpNonce(MTP::nonce()) + , _flags(0) { moveToThread(thread); manager.moveToThread(thread); App::setProxySettings(manager); } -void MTPhttpConnection::sendData(mtpBuffer &buffer) { +void HTTPConnection::sendData(mtpBuffer &buffer) { if (status == FinishedWork) return; if (buffer.size() < 3) { @@ -1177,7 +1189,7 @@ void MTPhttpConnection::sendData(mtpBuffer &buffer) { requests.insert(manager.post(request, QByteArray((const char*)(&buffer[2]), requestSize))); } -void MTPhttpConnection::disconnectFromServer() { +void HTTPConnection::disconnectFromServer() { if (status == FinishedWork) return; status = FinishedWork; @@ -1193,7 +1205,7 @@ void MTPhttpConnection::disconnectFromServer() { address = QUrl(); } -void MTPhttpConnection::connectHttp(const QString &addr, int32 p, MTPDdcOption::Flags flags) { +void HTTPConnection::connectHttp(const QString &addr, int32 p, MTPDdcOption::Flags flags) { address = QUrl(((flags & MTPDdcOption::Flag::f_ipv6) ? qsl("http://[%1]:%2/api") : qsl("http://%1:%2/api")).arg(addr).arg(80));//not p - always 80 port for http transport TCP_LOG(("HTTP Info: address is %1").arg(address.toDisplayString())); connect(&manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(requestFinished(QNetworkReply*))); @@ -1207,11 +1219,11 @@ void MTPhttpConnection::connectHttp(const QString &addr, int32 p, MTPDdcOption:: sendData(buffer); } -bool MTPhttpConnection::isConnected() const { +bool HTTPConnection::isConnected() const { return (status == UsingHttp); } -void MTPhttpConnection::requestFinished(QNetworkReply *reply) { +void HTTPConnection::requestFinished(QNetworkReply *reply) { if (status == FinishedWork) return; reply->deleteLater(); @@ -1251,19 +1263,19 @@ void MTPhttpConnection::requestFinished(QNetworkReply *reply) { } } -bool MTPhttpConnection::usingHttpWait() { +bool HTTPConnection::usingHttpWait() { return true; } -bool MTPhttpConnection::needHttpWait() { +bool HTTPConnection::needHttpWait() { return requests.isEmpty(); } -int32 MTPhttpConnection::debugState() const { +int32 HTTPConnection::debugState() const { return -1; } -QString MTPhttpConnection::transport() const { +QString HTTPConnection::transport() const { if (status == UsingHttp) { return qsl("HTTP"); } else { @@ -1271,16 +1283,16 @@ QString MTPhttpConnection::transport() const { } } -void MTProtoConnectionPrivate::createConn(bool createIPv4, bool createIPv6) { +void ConnectionPrivate::createConn(bool createIPv4, bool createIPv6) { destroyConn(); if (createIPv4) { QWriteLocker lock(&stateConnMutex); if (cConnectionType() == dbictAuto) { - _conn4 = new MTPautoConnection(thread()); + _conn4 = new AutoConnection(thread()); } else if (cConnectionType() == dbictTcpProxy) { - _conn4 = new MTPtcpConnection(thread()); + _conn4 = new TCPConnection(thread()); } else { - _conn4 = new MTPhttpConnection(thread()); + _conn4 = new HTTPConnection(thread()); } connect(_conn4, SIGNAL(error(bool)), this, SLOT(onError4(bool))); connect(_conn4, SIGNAL(receivedSome()), this, SLOT(onReceivedSome())); @@ -1288,11 +1300,11 @@ void MTProtoConnectionPrivate::createConn(bool createIPv4, bool createIPv6) { if (createIPv6) { QWriteLocker lock(&stateConnMutex); if (cConnectionType() == dbictAuto) { - _conn6 = new MTPautoConnection(thread()); + _conn6 = new AutoConnection(thread()); } else if (cConnectionType() == dbictTcpProxy) { - _conn6 = new MTPtcpConnection(thread()); + _conn6 = new TCPConnection(thread()); } else { - _conn6 = new MTPhttpConnection(thread()); + _conn6 = new HTTPConnection(thread()); } connect(_conn6, SIGNAL(error(bool)), this, SLOT(onError6(bool))); connect(_conn6, SIGNAL(receivedSome()), this, SLOT(onReceivedSome())); @@ -1305,19 +1317,19 @@ void MTProtoConnectionPrivate::createConn(bool createIPv4, bool createIPv6) { oldConnectionTimer.start(MTPConnectionOldTimeout); } -void MTProtoConnectionPrivate::destroyConn(MTPabstractConnection **conn) { +void ConnectionPrivate::destroyConn(AbstractConnection **conn) { if (conn) { - MTPabstractConnection *toDisconnect = nullptr; + AbstractConnection *toDisconnect = nullptr; { QWriteLocker lock(&stateConnMutex); if (*conn) { toDisconnect = *conn; - disconnect(*conn, SIGNAL(connected()), 0, 0); - disconnect(*conn, SIGNAL(disconnected()), 0, 0); - disconnect(*conn, SIGNAL(error(bool)), 0, 0); - disconnect(*conn, SIGNAL(receivedData()), 0, 0); - disconnect(*conn, SIGNAL(receivedSome()), 0, 0); + disconnect(*conn, SIGNAL(connected()), nullptr, nullptr); + disconnect(*conn, SIGNAL(disconnected()), nullptr, nullptr); + disconnect(*conn, SIGNAL(error(bool)), nullptr, nullptr); + disconnect(*conn, SIGNAL(receivedData()), nullptr, nullptr); + disconnect(*conn, SIGNAL(receivedSome()), nullptr, nullptr); *conn = nullptr; } } @@ -1332,8 +1344,8 @@ void MTProtoConnectionPrivate::destroyConn(MTPabstractConnection **conn) { } } -MTProtoConnectionPrivate::MTProtoConnectionPrivate(QThread *thread, MTProtoConnection *owner, MTPSessionData *data, uint32 _dc) : QObject(0) -, _state(MTProtoConnection::Disconnected) +ConnectionPrivate::ConnectionPrivate(QThread *thread, Connection *owner, SessionData *data, uint32 _dc) : QObject(nullptr) +, _state(DisconnectedState) , _needSessionReset(false) , dc(_dc) , _owner(owner) @@ -1379,7 +1391,7 @@ MTProtoConnectionPrivate::MTProtoConnectionPrivate(QThread *thread, MTProtoConne connect(thread, SIGNAL(started()), this, SLOT(socketStart())); connect(thread, SIGNAL(finished()), this, SLOT(doFinish())); - connect(this, SIGNAL(finished(MTProtoConnection*)), _mtp_internal::globalSlotCarrier(), SLOT(connectionFinished(MTProtoConnection*)), Qt::QueuedConnection); + connect(this, SIGNAL(finished(MTProtoConnection*)), globalSlotCarrier(), SLOT(connectionFinished(MTProtoConnection*)), Qt::QueuedConnection); connect(&retryTimer, SIGNAL(timeout()), this, SLOT(retryByTimer())); connect(&_waitForConnectedTimer, SIGNAL(timeout()), this, SLOT(onWaitConnectedFailed())); @@ -1412,15 +1424,15 @@ MTProtoConnectionPrivate::MTProtoConnectionPrivate(QThread *thread, MTProtoConne connect(this, SIGNAL(resendAllAsync()), sessionData->owner(), SLOT(resendAll())); } -void MTProtoConnectionPrivate::onConfigLoaded() { +void ConnectionPrivate::onConfigLoaded() { socketStart(true); } -int32 MTProtoConnectionPrivate::getDC() const { +int32 ConnectionPrivate::getDC() const { return dc; } -int32 MTProtoConnectionPrivate::getState() const { +int32 ConnectionPrivate::getState() const { QReadLocker lock(&stateConnMutex); int32 result = _state; if (_state < 0) { @@ -1434,7 +1446,7 @@ int32 MTProtoConnectionPrivate::getState() const { return result; } -QString MTProtoConnectionPrivate::transport() const { +QString ConnectionPrivate::transport() const { QReadLocker lock(&stateConnMutex); if ((!_conn4 && !_conn6) || (_conn4 && _conn6) || (_state < 0)) { return QString(); @@ -1444,8 +1456,8 @@ QString MTProtoConnectionPrivate::transport() const { return result; } -bool MTProtoConnectionPrivate::setState(int32 state, int32 ifState) { - if (ifState != MTProtoConnection::UpdateAlways) { +bool ConnectionPrivate::setState(int32 state, int32 ifState) { + if (ifState != Connection::UpdateAlways) { QReadLocker lock(&stateConnMutex); if (_state != ifState) return false; } @@ -1461,7 +1473,7 @@ bool MTProtoConnectionPrivate::setState(int32 state, int32 ifState) { return true; } -void MTProtoConnectionPrivate::resetSession() { // recreate all msg_id and msg_seqno +void ConnectionPrivate::resetSession() { // recreate all msg_id and msg_seqno _needSessionReset = false; QWriteLocker locker1(sessionData->haveSentMutex()); @@ -1581,7 +1593,7 @@ void MTProtoConnectionPrivate::resetSession() { // recreate all msg_id and msg_s emit sessionResetDone(); } -mtpMsgId MTProtoConnectionPrivate::prepareToSend(mtpRequest &request, mtpMsgId currentLastId) { +mtpMsgId ConnectionPrivate::prepareToSend(mtpRequest &request, mtpMsgId currentLastId) { if (request->size() < 9) return 0; mtpMsgId msgId = *(mtpMsgId*)(request->constData() + 4); if (msgId) { // resending this request @@ -1598,7 +1610,7 @@ mtpMsgId MTProtoConnectionPrivate::prepareToSend(mtpRequest &request, mtpMsgId c return msgId; } -mtpMsgId MTProtoConnectionPrivate::replaceMsgId(mtpRequest &request, mtpMsgId newId) { +mtpMsgId ConnectionPrivate::replaceMsgId(mtpRequest &request, mtpMsgId newId) { if (request->size() < 9) return 0; mtpMsgId oldMsgId = *(mtpMsgId*)(request->constData() + 4); @@ -1661,7 +1673,7 @@ mtpMsgId MTProtoConnectionPrivate::replaceMsgId(mtpRequest &request, mtpMsgId ne return newId; } -mtpMsgId MTProtoConnectionPrivate::placeToContainer(mtpRequest &toSendRequest, mtpMsgId &bigMsgId, mtpMsgId *&haveSentArr, mtpRequest &req) { +mtpMsgId ConnectionPrivate::placeToContainer(mtpRequest &toSendRequest, mtpMsgId &bigMsgId, mtpMsgId *&haveSentArr, mtpRequest &req) { mtpMsgId msgId = prepareToSend(req, bigMsgId); if (msgId > bigMsgId) msgId = replaceMsgId(req, bigMsgId); if (msgId >= bigMsgId) bigMsgId = msgid(); @@ -1674,7 +1686,7 @@ mtpMsgId MTProtoConnectionPrivate::placeToContainer(mtpRequest &toSendRequest, m return msgId; } -void MTProtoConnectionPrivate::tryToSend() { +void ConnectionPrivate::tryToSend() { QReadLocker lockFinished(&sessionDataMutex); if (!sessionData || !_conn) { return; @@ -1682,15 +1694,15 @@ void MTProtoConnectionPrivate::tryToSend() { bool needsLayer = !sessionData->layerWasInited(); int32 state = getState(); - bool prependOnly = (state != MTProtoConnection::Connected); + bool prependOnly = (state != ConnectedState); mtpRequest pingRequest; - if (dc < _mtp_internal::dcShift) { // main session + if (dc == bareDcId(dc)) { // main session if (!prependOnly && !_pingIdToSend && !_pingId && _pingSendAt <= getms(true)) { _pingIdToSend = MTP::nonce(); } } if (_pingIdToSend) { - if (prependOnly || dc >= _mtp_internal::dcShift) { + if (prependOnly || dc != bareDcId(dc)) { MTPPing ping(MTPping(MTP_long(_pingIdToSend))); uint32 pingSize = ping.innerLength() >> 2; // copy from MTProtoSession::send pingRequest = mtpRequestData::prepare(pingSize); @@ -1708,7 +1720,7 @@ void MTProtoConnectionPrivate::tryToSend() { _pingSendAt = pingRequest->msDate + (MTPPingSendAfterAuto * 1000ULL); pingRequest->requestId = 0; // dont add to haveSent / wereAcked maps - if (dc < _mtp_internal::dcShift && !prependOnly) { // main session + if (dc == bareDcId(dc) && !prependOnly) { // main session _pingSender.start(MTPPingSendAfter * 1000); } @@ -1834,7 +1846,7 @@ void MTProtoConnectionPrivate::tryToSend() { mtpRequest wrappedRequest(mtpRequestData::prepare(toSendSize, toSendSize + 3)); // cons + msg_id wrappedRequest->resize(4); memcpy(wrappedRequest->data(), toSendRequest->constData(), 4 * sizeof(mtpPrime)); - _mtp_internal::wrapInvokeAfter(wrappedRequest, toSendRequest, haveSent); + wrapInvokeAfter(wrappedRequest, toSendRequest, haveSent); toSendRequest = wrappedRequest; } if (needsLayer) { @@ -1912,7 +1924,7 @@ void MTProtoConnectionPrivate::tryToSend() { req->msDate = mtpRequestData::isStateRequest(req) ? 0 : getms(true); int32 reqNeedsLayer = (needsLayer && req->needsLayer) ? toSendRequest->size() : 0; if (req->after) { - _mtp_internal::wrapInvokeAfter(toSendRequest, req, haveSent, reqNeedsLayer ? initSizeInInts : 0); + wrapInvokeAfter(toSendRequest, req, haveSent, reqNeedsLayer ? initSizeInInts : 0); if (reqNeedsLayer) { memcpy(toSendRequest->data() + reqNeedsLayer + 4, initSerialized.constData(), initSize); *(toSendRequest->data() + reqNeedsLayer + 3) += initSize; @@ -1959,7 +1971,7 @@ void MTProtoConnectionPrivate::tryToSend() { sendRequest(toSendRequest, needAnyResponse, lockFinished); } -void MTProtoConnectionPrivate::retryByTimer() { +void ConnectionPrivate::retryByTimer() { QReadLocker lockFinished(&sessionDataMutex); if (!sessionData) return; @@ -1982,18 +1994,18 @@ void MTProtoConnectionPrivate::retryByTimer() { socketStart(); } -void MTProtoConnectionPrivate::restartNow() { +void ConnectionPrivate::restartNow() { retryTimeout = 1; retryTimer.stop(); restart(); } -void MTProtoConnectionPrivate::socketStart(bool afterConfig) { +void ConnectionPrivate::socketStart(bool afterConfig) { if (_finished) { DEBUG_LOG(("MTP Error: socketStart() called for finished connection!")); return; } - bool isDldDc = (dc >= MTP::dldStart) && (dc < MTP::dldEnd); + bool isDldDc = isDldDcId(dc); if (isDldDc) { // using media_only addresses only if key for this dc is already created QReadLocker lockFinished(&sessionDataMutex); if (sessionData) { @@ -2003,7 +2015,7 @@ void MTProtoConnectionPrivate::socketStart(bool afterConfig) { } } - int32 baseDc = (dc % _mtp_internal::dcShift); + int32 bareDc = bareDcId(dc); static const int IPv4address = 0, IPv6address = 1; static const int TcpProtocol = 0, HttpProtocol = 1; @@ -2046,7 +2058,7 @@ void MTProtoConnectionPrivate::socketStart(bool afterConfig) { int32 mask = shifts[address][protocol][shift]; if (mask < 0) continue; - auto index = options.constFind(baseDc + _mtp_internal::dcShift * mask); + auto index = options.constFind(shiftDcId(bareDc, mask)); if (index != options.cend()) { ip[address][protocol] = index->ip; flags[address][protocol] = index->flags; @@ -2077,7 +2089,7 @@ void MTProtoConnectionPrivate::socketStart(bool afterConfig) { retryTimer.stop(); _waitForConnectedTimer.stop(); - setState(MTProtoConnection::Connecting); + setState(ConnectingState); _pingId = _pingMsgId = _pingIdToSend = _pingSendAt = 0; _pingSender.stop(); @@ -2099,7 +2111,7 @@ void MTProtoConnectionPrivate::socketStart(bool afterConfig) { } } -void MTProtoConnectionPrivate::restart(bool mayBeBadKey) { +void ConnectionPrivate::restart(bool mayBeBadKey) { QReadLocker lockFinished(&sessionDataMutex); if (!sessionData) return; @@ -2136,7 +2148,7 @@ void MTProtoConnectionPrivate::restart(bool mayBeBadKey) { setState(-retryTimeout); } -void MTProtoConnectionPrivate::onSentSome(uint64 size) { +void ConnectionPrivate::onSentSome(uint64 size) { if (!_waitForReceivedTimer.isActive()) { uint64 remain = _waitForReceived; if (!oldConnection) { @@ -2146,9 +2158,9 @@ void MTProtoConnectionPrivate::onSentSome(uint64 size) { DEBUG_LOG(("Checking connect for request with size %1 bytes, delay will be %2").arg(size).arg(remain)); } } - if (dc >= MTP::uplStart && dc < MTP::uplEnd) { + if (isUplDcId(dc)) { remain *= MTPUploadSessionsCount; - } else if (dc >= MTP::dldStart && dc < MTP::dldEnd) { + } else if (isDldDcId(dc)) { remain *= MTPDownloadSessionsCount; } _waitForReceivedTimer.start(remain); @@ -2156,7 +2168,7 @@ void MTProtoConnectionPrivate::onSentSome(uint64 size) { if (!firstSentAt) firstSentAt = getms(true); } -void MTProtoConnectionPrivate::onReceivedSome() { +void ConnectionPrivate::onReceivedSome() { if (oldConnection) { oldConnection = false; DEBUG_LOG(("This connection marked as not old!")); @@ -2172,13 +2184,13 @@ void MTProtoConnectionPrivate::onReceivedSome() { } } -void MTProtoConnectionPrivate::onOldConnection() { +void ConnectionPrivate::onOldConnection() { oldConnection = true; _waitForReceived = MTPMinReceiveDelay; DEBUG_LOG(("This connection marked as old! _waitForReceived now %1ms").arg(_waitForReceived)); } -void MTProtoConnectionPrivate::onPingSender() { +void ConnectionPrivate::onPingSender() { if (_pingId) { if (_pingSendAt + (MTPPingSendAfter - MTPPingSendAfterAuto - 1) * 1000ULL < getms(true)) { LOG(("Could not send ping for MTPPingSendAfter seconds, restarting..")); @@ -2191,7 +2203,7 @@ void MTProtoConnectionPrivate::onPingSender() { } } -void MTProtoConnectionPrivate::onPingSendForce() { +void ConnectionPrivate::onPingSendForce() { if (!_pingId) { _pingSendAt = 0; DEBUG_LOG(("Will send ping!")); @@ -2199,7 +2211,7 @@ void MTProtoConnectionPrivate::onPingSendForce() { } } -void MTProtoConnectionPrivate::onWaitReceivedFailed() { +void ConnectionPrivate::onWaitReceivedFailed() { if (cConnectionType() != dbictAuto && cConnectionType() != dbictTcpProxy) { return; } @@ -2216,7 +2228,7 @@ void MTProtoConnectionPrivate::onWaitReceivedFailed() { QTimer::singleShot(0, this, SLOT(socketStart())); } -void MTProtoConnectionPrivate::onWaitConnectedFailed() { +void ConnectionPrivate::onWaitConnectedFailed() { DEBUG_LOG(("MTP Info: can't connect in %1ms").arg(_waitForConnected)); if (_waitForConnected < MTPMaxConnectDelay) _waitForConnected *= 2; @@ -2227,7 +2239,7 @@ void MTProtoConnectionPrivate::onWaitConnectedFailed() { QTimer::singleShot(0, this, SLOT(socketStart())); } -void MTProtoConnectionPrivate::onWaitIPv4Failed() { +void ConnectionPrivate::onWaitIPv4Failed() { _conn = _conn6; destroyConn(&_conn4); @@ -2240,7 +2252,7 @@ void MTProtoConnectionPrivate::onWaitIPv4Failed() { } } -void MTProtoConnectionPrivate::doDisconnect() { +void ConnectionPrivate::doDisconnect() { destroyConn(); { @@ -2252,18 +2264,18 @@ void MTProtoConnectionPrivate::doDisconnect() { clearAuthKeyData(); - setState(MTProtoConnection::Disconnected); + setState(DisconnectedState); restarted = false; } -void MTProtoConnectionPrivate::doFinish() { +void ConnectionPrivate::doFinish() { doDisconnect(); _finished = true; emit finished(_owner); deleteLater(); } -void MTProtoConnectionPrivate::handleReceived() { +void ConnectionPrivate::handleReceived() { QReadLocker lockFinished(&sessionDataMutex); if (!sessionData) return; @@ -2364,12 +2376,12 @@ void MTProtoConnectionPrivate::handleReceived() { badTime = true; } - bool wasConnected = (getState() == MTProtoConnection::Connected); + bool wasConnected = (getState() == ConnectedState); if (serverSalt != mySalt) { if (!badTime) { DEBUG_LOG(("MTP Info: other salt received.. received: %1, my salt: %2, updating..").arg(serverSalt).arg(mySalt)); sessionData->setSalt(serverSalt); - if (setState(MTProtoConnection::Connected, MTProtoConnection::Connecting)) { // only connected + if (setState(ConnectedState, ConnectingState)) { // only connected if (restarted) { emit resendAllAsync(); restarted = false; @@ -2441,7 +2453,7 @@ void MTProtoConnectionPrivate::handleReceived() { } if (!wasConnected) { - if (getState() == MTProtoConnection::Connected) { + if (getState() == ConnectedState) { emit needToSendAsync(); } } @@ -2451,7 +2463,7 @@ void MTProtoConnectionPrivate::handleReceived() { } } -int32 MTProtoConnectionPrivate::handleOneReceived(const mtpPrime *from, const mtpPrime *end, uint64 msgId, int32 serverTime, uint64 serverSalt, bool badTime) { +int32 ConnectionPrivate::handleOneReceived(const mtpPrime *from, const mtpPrime *end, uint64 msgId, int32 serverTime, uint64 serverSalt, bool badTime) { mtpTypeId cons = *from; try { @@ -2603,7 +2615,7 @@ int32 MTProtoConnectionPrivate::handleOneReceived(const mtpPrime *from, const mt mtpRequestId requestId = wasSent(resendId); if (requestId) { LOG(("Message Error: bad message notification received, msgId %1, error_code %2, fatal: clearing callbacks").arg(data.vbad_msg_id.v).arg(errorCode)); - _mtp_internal::clearCallbacksDelayed(RPCCallbackClears(1, RPCCallbackClear(requestId, -errorCode))); + clearCallbacksDelayed(RPCCallbackClears(1, RPCCallbackClear(requestId, -errorCode))); } else { DEBUG_LOG(("Message Error: such message was not sent recently %1").arg(resendId)); } @@ -2628,7 +2640,7 @@ int32 MTProtoConnectionPrivate::handleOneReceived(const mtpPrime *from, const mt sessionData->setSalt(serverSalt); unixtimeSet(serverTime); - if (setState(MTProtoConnection::Connected, MTProtoConnection::Connecting)) { // maybe only connected + if (setState(ConnectedState, ConnectingState)) { // maybe only connected if (restarted) { emit resendAllAsync(); restarted = false; @@ -2979,7 +2991,7 @@ int32 MTProtoConnectionPrivate::handleOneReceived(const mtpPrime *from, const mt return 1; } -mtpBuffer MTProtoConnectionPrivate::ungzip(const mtpPrime *from, const mtpPrime *end) const { +mtpBuffer ConnectionPrivate::ungzip(const mtpPrime *from, const mtpPrime *end) const { MTPstring packed(from, end); // read packed string as serialized mtp string type uint32 packedLen = packed.c_string().v.size(), unpackedChunk = packedLen, unpackedLen = 0; @@ -3026,7 +3038,7 @@ mtpBuffer MTProtoConnectionPrivate::ungzip(const mtpPrime *from, const mtpPrime return result; } -bool MTProtoConnectionPrivate::requestsFixTimeSalt(const QVector &ids, int32 serverTime, uint64 serverSalt) { +bool ConnectionPrivate::requestsFixTimeSalt(const QVector &ids, int32 serverTime, uint64 serverSalt) { uint32 idsCount = ids.size(); for (uint32 i = 0; i < idsCount; ++i) { @@ -3039,7 +3051,7 @@ bool MTProtoConnectionPrivate::requestsFixTimeSalt(const QVector &ids, return false; } -void MTProtoConnectionPrivate::requestsAcked(const QVector &ids, bool byResponse) { +void ConnectionPrivate::requestsAcked(const QVector &ids, bool byResponse) { uint32 idsCount = ids.size(); DEBUG_LOG(("Message Info: requests acked, ids %1").arg(Logs::vector(ids))); @@ -3071,7 +3083,7 @@ void MTProtoConnectionPrivate::requestsAcked(const QVector &ids, bool b mtpRequestId reqId = req.value()->requestId; bool moveToAcked = byResponse; if (!moveToAcked) { // ignore ACK, if we need a response (if we have a handler) - moveToAcked = !_mtp_internal::hasCallbacks(reqId); + moveToAcked = !hasCallbacks(reqId); } if (moveToAcked) { wereAcked.insert(msgId, reqId); @@ -3089,7 +3101,7 @@ void MTProtoConnectionPrivate::requestsAcked(const QVector &ids, bool b mtpRequestId reqId = reqIt.value(); bool moveToAcked = byResponse; if (!moveToAcked) { // ignore ACK, if we need a response (if we have a handler) - moveToAcked = !_mtp_internal::hasCallbacks(reqId); + moveToAcked = !hasCallbacks(reqId); } if (moveToAcked) { QWriteLocker locker4(sessionData->toSendMutex()); @@ -3130,7 +3142,7 @@ void MTProtoConnectionPrivate::requestsAcked(const QVector &ids, bool b } if (clearedAcked.size()) { - _mtp_internal::clearCallbacksDelayed(clearedAcked); + clearCallbacksDelayed(clearedAcked); } if (toAckMore.size()) { @@ -3138,7 +3150,7 @@ void MTProtoConnectionPrivate::requestsAcked(const QVector &ids, bool b } } -void MTProtoConnectionPrivate::handleMsgsStates(const QVector &ids, const string &states, QVector &acked) { +void ConnectionPrivate::handleMsgsStates(const QVector &ids, const string &states, QVector &acked) { uint32 idsCount = ids.size(); if (!idsCount) { DEBUG_LOG(("Message Info: void ids vector in handleMsgsStates()")); @@ -3182,12 +3194,12 @@ void MTProtoConnectionPrivate::handleMsgsStates(const QVector &ids, con } } -void MTProtoConnectionPrivate::resend(quint64 msgId, quint64 msCanWait, bool forceContainer, bool sendMsgStateInfo) { +void ConnectionPrivate::resend(quint64 msgId, quint64 msCanWait, bool forceContainer, bool sendMsgStateInfo) { if (msgId == _pingMsgId) return; emit resendAsync(msgId, msCanWait, forceContainer, sendMsgStateInfo); } -void MTProtoConnectionPrivate::resendMany(QVector msgIds, quint64 msCanWait, bool forceContainer, bool sendMsgStateInfo) { +void ConnectionPrivate::resendMany(QVector msgIds, quint64 msCanWait, bool forceContainer, bool sendMsgStateInfo) { for (int32 i = 0, l = msgIds.size(); i < l; ++i) { if (msgIds.at(i) == _pingMsgId) { msgIds.remove(i); @@ -3197,7 +3209,7 @@ void MTProtoConnectionPrivate::resendMany(QVector msgIds, quint64 msCan emit resendManyAsync(msgIds, msCanWait, forceContainer, sendMsgStateInfo); } -void MTProtoConnectionPrivate::onConnected4() { +void ConnectionPrivate::onConnected4() { _waitForConnected = MTPMinConnectDelay; _waitForConnectedTimer.stop(); @@ -3223,7 +3235,7 @@ void MTProtoConnectionPrivate::onConnected4() { updateAuthKey(); } -void MTProtoConnectionPrivate::onConnected6() { +void ConnectionPrivate::onConnected6() { _waitForConnected = MTPMinConnectDelay; _waitForConnectedTimer.stop(); @@ -3243,7 +3255,7 @@ void MTProtoConnectionPrivate::onConnected6() { _waitForIPv4Timer.start(MTPIPv4ConnectionWaitTimeout); } -void MTProtoConnectionPrivate::onDisconnected4() { +void ConnectionPrivate::onDisconnected4() { if (_conn && _conn == _conn6) return; // disconnected the unused if (_conn || !_conn6) { @@ -3254,7 +3266,7 @@ void MTProtoConnectionPrivate::onDisconnected4() { } } -void MTProtoConnectionPrivate::onDisconnected6() { +void ConnectionPrivate::onDisconnected6() { if (_conn && _conn == _conn4) return; // disconnected the unused if (_conn || !_conn4) { @@ -3265,7 +3277,7 @@ void MTProtoConnectionPrivate::onDisconnected6() { } } -void MTProtoConnectionPrivate::updateAuthKey() { +void ConnectionPrivate::updateAuthKey() { QReadLocker lockFinished(&sessionDataMutex); if (!sessionData || !_conn) return; @@ -3302,8 +3314,8 @@ void MTProtoConnectionPrivate::updateAuthKey() { return authKeyCreated(); } - authKeyData = new MTProtoConnectionPrivate::AuthKeyCreateData(); - authKeyStrings = new MTProtoConnectionPrivate::AuthKeyCreateStrings(); + authKeyData = new ConnectionPrivate::AuthKeyCreateData(); + authKeyStrings = new ConnectionPrivate::AuthKeyCreateStrings(); authKeyData->req_num = 0; authKeyData->nonce = MTP::nonce(); @@ -3317,13 +3329,13 @@ void MTProtoConnectionPrivate::updateAuthKey() { sendRequestNotSecure(req_pq); } -void MTProtoConnectionPrivate::clearMessages() { +void ConnectionPrivate::clearMessages() { if (keyId && keyId != mtpAuthKey::RecreateKeyId && _conn) { _conn->received().clear(); } } -void MTProtoConnectionPrivate::pqAnswered() { +void ConnectionPrivate::pqAnswered() { disconnect(_conn, SIGNAL(receivedData()), this, SLOT(pqAnswered())); DEBUG_LOG(("AuthKey Info: receiving Req_pq answer..")); @@ -3421,7 +3433,7 @@ void MTProtoConnectionPrivate::pqAnswered() { sendRequestNotSecure(req_DH_params); } -void MTProtoConnectionPrivate::dhParamsAnswered() { +void ConnectionPrivate::dhParamsAnswered() { disconnect(_conn, SIGNAL(receivedData()), this, SLOT(dhParamsAnswered())); DEBUG_LOG(("AuthKey Info: receiving Req_DH_params answer..")); @@ -3542,7 +3554,7 @@ void MTProtoConnectionPrivate::dhParamsAnswered() { return restart(); } -void MTProtoConnectionPrivate::dhClientParamsSend() { +void ConnectionPrivate::dhClientParamsSend() { if (++authKeyData->retries > 5) { LOG(("AuthKey Error: could not create auth_key for %1 retries").arg(authKeyData->retries - 1)); return restart(); @@ -3603,7 +3615,7 @@ void MTProtoConnectionPrivate::dhClientParamsSend() { sendRequestNotSecure(req_client_DH_params); } -void MTProtoConnectionPrivate::dhClientParamsAnswered() { +void ConnectionPrivate::dhClientParamsAnswered() { QReadLocker lockFinished(&sessionDataMutex); if (!sessionData) return; @@ -3648,7 +3660,7 @@ void MTProtoConnectionPrivate::dhClientParamsAnswered() { mtpAuthKeyPtr authKey(new mtpAuthKey()); authKey->setKey(authKeyData->auth_key); - authKey->setDC(dc % _mtp_internal::dcShift); + authKey->setDC(bareDcId(dc)); DEBUG_LOG(("AuthKey Info: auth key gen succeed, id: %1, server salt: %2, auth key: %3").arg(authKey->keyId()).arg(serverSalt).arg(Logs::mb(authKeyData->auth_key, 256).str())); @@ -3723,13 +3735,13 @@ void MTProtoConnectionPrivate::dhClientParamsAnswered() { return restart(); } -void MTProtoConnectionPrivate::authKeyCreated() { +void ConnectionPrivate::authKeyCreated() { clearAuthKeyData(); connect(_conn, SIGNAL(receivedData()), this, SLOT(handleReceived())); if (sessionData->getSalt()) { // else receive salt in bad_server_salt first, then try to send all the requests - setState(MTProtoConnection::Connected); + setState(ConnectedState); if (restarted) { emit resendAllAsync(); restarted = false; @@ -3741,7 +3753,7 @@ void MTProtoConnectionPrivate::authKeyCreated() { emit needToSendAsync(); } -void MTProtoConnectionPrivate::clearAuthKeyData() { +void ConnectionPrivate::clearAuthKeyData() { if (authKeyData) { #ifdef Q_OS_WIN SecureZeroMemory(authKeyData, sizeof(AuthKeyCreateData)); @@ -3759,7 +3771,7 @@ void MTProtoConnectionPrivate::clearAuthKeyData() { } } -void MTProtoConnectionPrivate::onError4(bool mayBeBadKey) { +void ConnectionPrivate::onError4(bool mayBeBadKey) { if (_conn && _conn == _conn6) return; // error in the unused if (_conn || !_conn6) { @@ -3773,7 +3785,7 @@ void MTProtoConnectionPrivate::onError4(bool mayBeBadKey) { } } -void MTProtoConnectionPrivate::onError6(bool mayBeBadKey) { +void ConnectionPrivate::onError6(bool mayBeBadKey) { if (_conn && _conn == _conn4) return; // error in the unused if (_conn || !_conn4) { @@ -3787,11 +3799,11 @@ void MTProtoConnectionPrivate::onError6(bool mayBeBadKey) { } } -void MTProtoConnectionPrivate::onReadyData() { +void ConnectionPrivate::onReadyData() { } template -void MTProtoConnectionPrivate::sendRequestNotSecure(const TRequest &request) { +void ConnectionPrivate::sendRequestNotSecure(const TRequest &request) { try { mtpBuffer buffer; uint32 requestSize = request.innerLength() >> 2; @@ -3821,7 +3833,7 @@ void MTProtoConnectionPrivate::sendRequestNotSecure(const TRequest &request) { } template -bool MTProtoConnectionPrivate::readResponseNotSecure(TResponse &response) { +bool ConnectionPrivate::readResponseNotSecure(TResponse &response) { onReceivedSome(); try { @@ -3858,7 +3870,7 @@ bool MTProtoConnectionPrivate::readResponseNotSecure(TResponse &response) { return true; } -bool MTProtoConnectionPrivate::sendRequest(mtpRequest &request, bool needAnyResponse, QReadLocker &lockFinished) { +bool ConnectionPrivate::sendRequest(mtpRequest &request, bool needAnyResponse, QReadLocker &lockFinished) { uint32 fullSize = request->size(); if (fullSize < 9) return false; @@ -3915,7 +3927,7 @@ bool MTProtoConnectionPrivate::sendRequest(mtpRequest &request, bool needAnyResp return true; } -mtpRequestId MTProtoConnectionPrivate::wasSent(mtpMsgId msgId) const { +mtpRequestId ConnectionPrivate::wasSent(mtpMsgId msgId) const { if (msgId == _pingMsgId) return mtpRequestId(0xFFFFFFFF); { QReadLocker locker(sessionData->haveSentMutex()); @@ -3938,24 +3950,24 @@ mtpRequestId MTProtoConnectionPrivate::wasSent(mtpMsgId msgId) const { return 0; } -void MTProtoConnectionPrivate::lockKey() { +void ConnectionPrivate::lockKey() { unlockKey(); sessionData->keyMutex()->lockForWrite(); myKeyLock = true; } -void MTProtoConnectionPrivate::unlockKey() { +void ConnectionPrivate::unlockKey() { if (myKeyLock) { myKeyLock = false; sessionData->keyMutex()->unlock(); } } -MTProtoConnectionPrivate::~MTProtoConnectionPrivate() { +ConnectionPrivate::~ConnectionPrivate() { t_assert(_finished && _conn == nullptr && _conn4 == nullptr && _conn6 == nullptr); } -void MTProtoConnectionPrivate::stop() { +void ConnectionPrivate::stop() { QWriteLocker lockFinished(&sessionDataMutex); if (sessionData) { if (myKeyLock) { @@ -3966,3 +3978,6 @@ void MTProtoConnectionPrivate::stop() { sessionData = nullptr; } } + +} // namespace internal +} // namespace MTP diff --git a/Telegram/SourceFiles/mtproto/connection.h b/Telegram/SourceFiles/mtproto/connection.h index 7a556b83e..25cc61f28 100644 --- a/Telegram/SourceFiles/mtproto/connection.h +++ b/Telegram/SourceFiles/mtproto/connection.h @@ -23,50 +23,26 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "mtproto/core_types.h" #include "mtproto/auth_key.h" -inline bool mtpRequestData::isSentContainer(const mtpRequest &request) { // "request-like" wrap for msgIds vector - if (request->size() < 9) return false; - return (!request->msDate && !(*request)[6]); // msDate = 0, seqNo = 0 -} -inline bool mtpRequestData::isStateRequest(const mtpRequest &request) { - if (request->size() < 9) return false; - return (mtpTypeId((*request)[8]) == mtpc_msgs_state_req); -} -inline bool mtpRequestData::needAck(const mtpRequest &request) { - if (request->size() < 9) return false; - return mtpRequestData::needAckByType((*request)[8]); -} -inline bool mtpRequestData::needAckByType(mtpTypeId type) { - switch (type) { - case mtpc_msg_container: - case mtpc_msgs_ack: - case mtpc_http_wait: - case mtpc_bad_msg_notification: - case mtpc_msgs_all_info: - case mtpc_msgs_state_info: - case mtpc_msg_detailed_info: - case mtpc_msg_new_detailed_info: - return false; - } - return true; -} +namespace MTP { +namespace internal { -class MTProtoConnectionPrivate; -class MTPSessionData; +class ConnectionPrivate; +class SessionData; -class MTPThread : public QThread { +class Thread : public QThread { Q_OBJECT public: - MTPThread(); + Thread(); uint32 getThreadId() const; - ~MTPThread(); + ~Thread(); private: uint32 _threadId; }; -class MTProtoConnection { +class Connection { public: enum ConnectionType { @@ -74,19 +50,13 @@ public: HttpConnection }; - MTProtoConnection(); - int32 start(MTPSessionData *data, int32 dc = 0); // return dc + Connection(); + int32 start(SessionData *data, int32 dc = 0); // return dc void kill(); void waitTillFinish(); - ~MTProtoConnection(); + ~Connection(); - enum { - Disconnected = 0, - Connecting = 1, - Connected = 2, - - UpdateAlways = 666 - }; + static const int UpdateAlways = 666; int32 state() const; QString transport() const; @@ -94,18 +64,22 @@ public: private: QThread *thread; - MTProtoConnectionPrivate *data; + ConnectionPrivate *data; }; -class MTPabstractConnection : public QObject { +class AbstractConnection : public QObject { Q_OBJECT typedef QList BuffersQueue; public: - MTPabstractConnection() : _sentEncrypted(false) { + AbstractConnection() : _sentEncrypted(false) { + } + AbstractConnection(const AbstractConnection &other) = delete; + AbstractConnection &operator=(const AbstractConnection &other) = delete; + virtual ~AbstractConnection() = 0{ } void setSentEncrypted() { @@ -149,12 +123,14 @@ protected: }; -class MTPabstractTcpConnection : public MTPabstractConnection { +class AbstractTcpConnection : public AbstractConnection { Q_OBJECT public: - MTPabstractTcpConnection(); + AbstractTcpConnection(); + virtual ~AbstractTcpConnection() = 0 { + } public slots: @@ -174,12 +150,12 @@ protected: }; -class MTPautoConnection : public MTPabstractTcpConnection { +class AutoConnection : public AbstractTcpConnection { Q_OBJECT public: - MTPautoConnection(QThread *thread); + AutoConnection(QThread *thread); void sendData(mtpBuffer &buffer) override; void disconnectFromServer() override; @@ -239,12 +215,12 @@ private: }; -class MTPtcpConnection : public MTPabstractTcpConnection { +class TCPConnection : public AbstractTcpConnection { Q_OBJECT public: - MTPtcpConnection(QThread *thread); + TCPConnection(QThread *thread); void sendData(mtpBuffer &buffer) override; void disconnectFromServer() override; @@ -287,12 +263,12 @@ private: }; -class MTPhttpConnection : public MTPabstractConnection { +class HTTPConnection : public AbstractConnection { Q_OBJECT public: - MTPhttpConnection(QThread *thread); + HTTPConnection(QThread *thread); void sendData(mtpBuffer &buffer) override; void disconnectFromServer() override; @@ -330,13 +306,13 @@ private: }; -class MTProtoConnectionPrivate : public QObject { +class ConnectionPrivate : public QObject { Q_OBJECT public: - MTProtoConnectionPrivate(QThread *thread, MTProtoConnection *owner, MTPSessionData *data, uint32 dc); - ~MTProtoConnectionPrivate(); + ConnectionPrivate(QThread *thread, Connection *owner, SessionData *data, uint32 dc); + ~ConnectionPrivate(); void stop(); @@ -361,7 +337,7 @@ signals: void resendManyAsync(QVector msgIds, quint64 msCanWait, bool forceContainer, bool sendMsgStateInfo); void resendAllAsync(); - void finished(MTProtoConnection *connection); + void finished(Connection *connection); public slots: @@ -412,7 +388,7 @@ private: void doDisconnect(); void createConn(bool createIPv4, bool createIPv6); - void destroyConn(MTPabstractConnection **conn = 0); // 0 - destory all + void destroyConn(AbstractConnection **conn = 0); // 0 - destory all mtpMsgId placeToContainer(mtpRequest &toSendRequest, mtpMsgId &bigMsgId, mtpMsgId *&haveSentArr, mtpRequest &req); mtpMsgId prepareToSend(mtpRequest &request, mtpMsgId currentLastId); @@ -427,7 +403,7 @@ private: void clearMessages(); - bool setState(int32 state, int32 ifState = MTProtoConnection::UpdateAlways); + bool setState(int32 state, int32 ifState = Connection::UpdateAlways); mutable QReadWriteLock stateConnMutex; int32 _state; @@ -435,8 +411,8 @@ private: void resetSession(); uint32 dc; - MTProtoConnection *_owner; - MTPabstractConnection *_conn, *_conn4, *_conn6; + Connection *_owner; + AbstractConnection *_conn, *_conn4, *_conn6; SingleTimer retryTimer; // exp retry timer int retryTimeout; @@ -475,7 +451,8 @@ private: uint64 keyId; QReadWriteLock sessionDataMutex; - MTPSessionData *sessionData; + SessionData *sessionData; + bool myKeyLock; void lockKey(); void unlockKey(); @@ -523,3 +500,6 @@ private: void clearAuthKeyData(); }; + +} // namespace internal +} // namespace MTP diff --git a/Telegram/SourceFiles/mtproto/core_types.h b/Telegram/SourceFiles/mtproto/core_types.h index 040d59567..592f6ad85 100644 --- a/Telegram/SourceFiles/mtproto/core_types.h +++ b/Telegram/SourceFiles/mtproto/core_types.h @@ -22,35 +22,16 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "types.h" -#undef min -#undef max +namespace MTP { -//#define DEBUG_MTPPRIME +// type DcId represents actual data center id, while in most cases +// we use some shifted ids, like DcId() + X * DCShift +typedef int32 DcId; +typedef int32 ShiftedDcId; + +} -#ifdef DEBUG_MTPPRIME -class mtpPrime { // for debug visualization, not like int32 :( in default constructor -public: - explicit mtpPrime() : _v(0) { - } - mtpPrime(int32 v) : _v(v) { - } - mtpPrime &operator=(int32 v) { - _v = v; - return (*this); - } - operator int32&() { - return _v; - } - operator const int32 &() const { - return _v; - } -private: - int32 _v; -}; -#else typedef int32 mtpPrime; -#endif - typedef int32 mtpRequestId; typedef uint64 mtpMsgId; typedef uint64 mtpPingId; @@ -1072,3 +1053,30 @@ extern const MTPVector MTPnullEntities; extern const MTPMessageFwdHeader MTPnullFwdHeader; QString stickerSetTitle(const MTPDstickerSet &s); + +inline bool mtpRequestData::isSentContainer(const mtpRequest &request) { // "request-like" wrap for msgIds vector + if (request->size() < 9) return false; + return (!request->msDate && !(*request)[6]); // msDate = 0, seqNo = 0 +} +inline bool mtpRequestData::isStateRequest(const mtpRequest &request) { + if (request->size() < 9) return false; + return (mtpTypeId((*request)[8]) == mtpc_msgs_state_req); +} +inline bool mtpRequestData::needAck(const mtpRequest &request) { + if (request->size() < 9) return false; + return mtpRequestData::needAckByType((*request)[8]); +} +inline bool mtpRequestData::needAckByType(mtpTypeId type) { + switch (type) { + case mtpc_msg_container: + case mtpc_msgs_ack: + case mtpc_http_wait: + case mtpc_bad_msg_notification: + case mtpc_msgs_all_info: + case mtpc_msgs_state_info: + case mtpc_msg_detailed_info: + case mtpc_msg_new_detailed_info: + return false; + } + return true; +} diff --git a/Telegram/SourceFiles/mtproto/dcenter.cpp b/Telegram/SourceFiles/mtproto/dcenter.cpp index 470e0e228..577c37bd8 100644 --- a/Telegram/SourceFiles/mtproto/dcenter.cpp +++ b/Telegram/SourceFiles/mtproto/dcenter.cpp @@ -82,7 +82,7 @@ void mtpLogoutOtherDCs() { } for (int32 i = 0, cnt = dcs.size(); i != cnt; ++i) { if (dcs[i] != MTP::maindc()) { - logoutGuestMap.insert(MTP::lgt + dcs[i], MTP::send(MTPauth_LogOut(), rpcDone(&logoutDone), rpcFail(&logoutDone), MTP::lgt + dcs[i])); + logoutGuestMap.insert(MTP::lgtDcId(dcs[i]), MTP::send(MTPauth_LogOut(), rpcDone(&logoutDone), rpcFail(&logoutDone), MTP::lgtDcId(dcs[i]))); } } } @@ -193,7 +193,7 @@ void mtpUpdateDcOptions(const QVector &options) { } for (QVector::const_iterator i = options.cbegin(), e = options.cend(); i != e; ++i) { const MTPDdcOption &optData(i->c_dcOption()); - int32 id = optData.vid.v, idWithShift = id + (optData.vflags.v * _mtp_internal::dcShift); + int32 id = optData.vid.v, idWithShift = MTP::shiftDcId(id, optData.vflags.v); if (already.constFind(idWithShift) == already.cend()) { already.insert(idWithShift); auto a = opts.constFind(idWithShift); @@ -243,7 +243,7 @@ void MTProtoConfigLoader::done() { _enumRequest = 0; } if (_enumCurrent) { - MTP::killSession(MTP::cfg + _enumCurrent); + MTP::killSession(MTP::cfgDcId(_enumCurrent)); _enumCurrent = 0; } emit loaded(); @@ -257,14 +257,14 @@ void MTProtoConfigLoader::enumDC() { if (!_enumCurrent) { _enumCurrent = mainDC; } else { - MTP::killSession(MTP::cfg + _enumCurrent); + MTP::killSession(MTP::cfgDcId(_enumCurrent)); } OrderedSet dcs; { QReadLocker lock(mtpDcOptionsMutex()); const MTP::DcOptions &options(Global::DcOptions()); for (auto i = options.cbegin(), e = options.cend(); i != e; ++i) { - dcs.insert(i.key() % _mtp_internal::dcShift); + dcs.insert(MTP::bareDcId(i.key())); } } OrderedSet::const_iterator i = dcs.constFind(_enumCurrent); @@ -273,7 +273,7 @@ void MTProtoConfigLoader::enumDC() { } else { _enumCurrent = i.key(); } - _enumRequest = MTP::send(MTPhelp_GetConfig(), rpcDone(configLoaded), rpcFail(configFailed), MTP::cfg + _enumCurrent); + _enumRequest = MTP::send(MTPhelp_GetConfig(), rpcDone(configLoaded), rpcFail(configFailed), MTP::cfgDcId(_enumCurrent)); _enumDCTimer.start(MTPEnumDCTimeout); } diff --git a/Telegram/SourceFiles/mtproto/facade.cpp b/Telegram/SourceFiles/mtproto/facade.cpp index c63e6834b..bb98d37f0 100644 --- a/Telegram/SourceFiles/mtproto/facade.cpp +++ b/Telegram/SourceFiles/mtproto/facade.cpp @@ -24,10 +24,13 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "localstorage.h" +namespace MTP { + namespace { - typedef QMap Sessions; + + typedef QMap Sessions; Sessions sessions; - MTProtoSession *mainSession; + internal::Session *mainSession; typedef QMap RequestsByDC; // holds dcWithShift for request to this dc or -dc for request to main dc RequestsByDC requestsByDC; @@ -62,7 +65,7 @@ namespace { typedef QMap AuthWaiters; // holds request ids waiting for auth import to specific dc AuthWaiters authWaiters; - typedef OrderedSet MTPQuittingConnections; + typedef OrderedSet MTPQuittingConnections; MTPQuittingConnections quittingConnections; QMutex toClearLock; @@ -71,7 +74,7 @@ namespace { RPCResponseHandler globalHandler; MTPStateChangedHandler stateChangedHandler = 0; MTPSessionResetHandler sessionResetHandler = 0; - _mtp_internal::GlobalSlotCarrier *_globalSlotCarrier = 0; + internal::GlobalSlotCarrier *_globalSlotCarrier = 0; void importDone(const MTPauth_Authorization &result, mtpRequestId req) { QMutexLocker locker1(&requestByDCLock); @@ -79,11 +82,11 @@ namespace { RequestsByDC::iterator i = requestsByDC.find(req); if (i == requestsByDC.end()) { LOG(("MTP Error: auth import request not found in requestsByDC, requestId: %1").arg(req)); - RPCError error(rpcClientError("AUTH_IMPORT_FAIL", QString("did not find import request in requestsByDC, request %1").arg(req))); - if (globalHandler.onFail && MTP::authedId()) (*globalHandler.onFail)(req, error); // auth failed in main dc + RPCError error(internal::rpcClientError("AUTH_IMPORT_FAIL", QString("did not find import request in requestsByDC, request %1").arg(req))); + if (globalHandler.onFail && authedId()) (*globalHandler.onFail)(req, error); // auth failed in main dc return; } - int32 newdc = i.value() % _mtp_internal::dcShift; + DcId newdc = bareDcId(i.value()); DEBUG_LOG(("MTP Info: auth import to dc %1 succeeded").arg(newdc)); @@ -105,16 +108,15 @@ namespace { continue; } if (k.value() < 0) { - MTP::setdc(newdc); + setdc(newdc); k.value() = -newdc; } else { - int32 shift = k.value() - (k.value() % _mtp_internal::dcShift); - dcWithShift += shift; + dcWithShift += getDcIdShift(k.value()); k.value() = dcWithShift; } DEBUG_LOG(("MTP Info: resending request %1 to dc %2 after import auth").arg(requestId).arg(k.value())); } - if (MTProtoSession *session = _mtp_internal::getSession(dcWithShift)) { + if (internal::Session *session = internal::getSession(dcWithShift)) { session->sendPrepared(j.value()); } } @@ -125,7 +127,7 @@ namespace { bool importFail(const RPCError &error, mtpRequestId req) { if (mtpIsFlood(error)) return false; - if (globalHandler.onFail && MTP::authedId()) (*globalHandler.onFail)(req, error); // auth import failed + if (globalHandler.onFail && authedId()) (*globalHandler.onFail)(req, error); // auth import failed return true; } @@ -133,13 +135,13 @@ namespace { AuthExportRequests::const_iterator i = authExportRequests.constFind(req); if (i == authExportRequests.cend()) { LOG(("MTP Error: auth export request target dcWithShift not found, requestId: %1").arg(req)); - RPCError error(rpcClientError("AUTH_IMPORT_FAIL", QString("did not find target dcWithShift, request %1").arg(req))); - if (globalHandler.onFail && MTP::authedId()) (*globalHandler.onFail)(req, error); // auth failed in main dc + RPCError error(internal::rpcClientError("AUTH_IMPORT_FAIL", QString("did not find target dcWithShift, request %1").arg(req))); + if (globalHandler.onFail && authedId()) (*globalHandler.onFail)(req, error); // auth failed in main dc return; } const MTPDauth_exportedAuthorization &data(result.c_auth_exportedAuthorization()); - MTP::send(MTPauth_ImportAuthorization(data.vid, data.vbytes), rpcDone(importDone), rpcFail(importFail), i.value()); + send(MTPauth_ImportAuthorization(data.vid, data.vbytes), rpcDone(importDone), rpcFail(importFail), i.value()); authExportRequests.remove(req); } @@ -148,9 +150,9 @@ namespace { AuthExportRequests::const_iterator i = authExportRequests.constFind(req); if (i != authExportRequests.cend()) { - authWaiters[i.value() % _mtp_internal::dcShift].clear(); + authWaiters[bareDcId(i.value())].clear(); } - if (globalHandler.onFail && MTP::authedId()) (*globalHandler.onFail)(req, error); // auth failed in main dc + if (globalHandler.onFail && authedId()) (*globalHandler.onFail)(req, error); // auth failed in main dc return true; } @@ -179,11 +181,11 @@ namespace { DEBUG_LOG(("MTP Info: changing request %1 from dcWithShift%2 to dc%3").arg(requestId).arg(dcWithShift).arg(newdcWithShift)); if (dcWithShift < 0) { // newdc shift = 0 - if (false && MTP::authedId() && !authExportRequests.contains(requestId)) { // migrate not supported at this moment + if (false && authedId() && !authExportRequests.contains(requestId)) { // migrate not supported at this moment DEBUG_LOG(("MTP Info: importing auth to dc %1").arg(newdcWithShift)); DCAuthWaiters &waiters(authWaiters[newdcWithShift]); if (!waiters.size()) { - authExportRequests.insert(MTP::send(MTPauth_ExportAuthorization(MTP_int(newdcWithShift)), rpcDone(exportDone), rpcFail(exportFail)), newdcWithShift); + authExportRequests.insert(send(MTPauth_ExportAuthorization(MTP_int(newdcWithShift)), rpcDone(exportDone), rpcFail(exportFail)), newdcWithShift); } waiters.push_back(requestId); return true; @@ -191,8 +193,7 @@ namespace { MTP::setdc(newdcWithShift); } } else { - int32 shift = dcWithShift - (dcWithShift % _mtp_internal::dcShift); - newdcWithShift += shift; + newdcWithShift += MTP::getDcIdShift(dcWithShift); } mtpRequest req; @@ -205,8 +206,8 @@ namespace { } req = i.value(); } - if (MTProtoSession *session = _mtp_internal::getSession(newdcWithShift)) { - _mtp_internal::registerRequest(requestId, (dcWithShift < 0) ? -newdcWithShift : newdcWithShift); + if (internal::Session *session = internal::getSession(newdcWithShift)) { + internal::registerRequest(requestId, (dcWithShift < 0) ? -newdcWithShift : newdcWithShift); session->sendPrepared(req); } return true; @@ -247,8 +248,8 @@ namespace { LOG(("MTP Error: unauthorized request without dc info, requestId %1").arg(requestId)); } } - int32 newdc = abs(dcWithShift) % _mtp_internal::dcShift; - if (!newdc || newdc == mtpMainDC() || !MTP::authedId()) { + int32 newdc = bareDcId(qAbs(dcWithShift)); + if (!newdc || newdc == mtpMainDC() || !authedId()) { if (!badGuestDC && globalHandler.onFail) (*globalHandler.onFail)(requestId, error); // auth failed in main dc return false; } @@ -256,7 +257,7 @@ namespace { DEBUG_LOG(("MTP Info: importing auth to dcWithShift %1").arg(dcWithShift)); DCAuthWaiters &waiters(authWaiters[newdc]); if (!waiters.size()) { - authExportRequests.insert(MTP::send(MTPauth_ExportAuthorization(MTP_int(newdc)), rpcDone(exportDone), rpcFail(exportFail)), abs(dcWithShift)); + authExportRequests.insert(send(MTPauth_ExportAuthorization(MTP_int(newdc)), rpcDone(exportDone), rpcFail(exportFail)), abs(dcWithShift)); } waiters.push_back(requestId); if (badGuestDC) badGuestDCRequests.insert(requestId); @@ -284,7 +285,7 @@ namespace { } if (!dcWithShift) return false; - if (MTProtoSession *session = _mtp_internal::getSession(dcWithShift < 0 ? (-dcWithShift) : dcWithShift)) { + if (internal::Session *session = internal::getSession(qAbs(dcWithShift))) { req->needsLayer = true; session->sendPrepared(req); } @@ -322,12 +323,12 @@ namespace { if (!dcWithShift) return false; if (!req->after) { - if (MTProtoSession *session = _mtp_internal::getSession(dcWithShift < 0 ? (-dcWithShift) : dcWithShift)) { + if (internal::Session *session = internal::getSession(qAbs(dcWithShift))) { req->needsLayer = true; session->sendPrepared(req); } } else { - int32 newdc = abs(dcWithShift) % _mtp_internal::dcShift; + int32 newdc = bareDcId(qAbs(dcWithShift)); DCAuthWaiters &waiters(authWaiters[newdc]); if (waiters.indexOf(req->after->requestId) >= 0) { if (waiters.indexOf(requestId) < 0) { @@ -360,553 +361,547 @@ namespace { bool _paused = false; +} // namespace + +namespace internal { + +Session *getSession(ShiftedDcId shiftedDcId) { + if (!_started) return nullptr; + if (!shiftedDcId) return mainSession; + if (!bareDcId(shiftedDcId)) { + shiftedDcId += bareDcId(mainSession->getDcWithShift()); + } + + Sessions::const_iterator i = sessions.constFind(shiftedDcId); + if (i == sessions.cend()) { + i = sessions.insert(shiftedDcId, new Session(shiftedDcId)); + } + return i.value(); } -namespace _mtp_internal { - MTProtoSession *getSession(int32 dcWithShift) { - if (!_started) return 0; - if (!dcWithShift) return mainSession; - if (!(dcWithShift % _mtp_internal::dcShift)) { - dcWithShift += (mainSession->getDcWithShift() % _mtp_internal::dcShift); - } - - Sessions::const_iterator i = sessions.constFind(dcWithShift); - if (i == sessions.cend()) { - i = sessions.insert(dcWithShift, new MTProtoSession(dcWithShift)); - } - return i.value(); - } - - bool paused() { - return _paused; - } - - void registerRequest(mtpRequestId requestId, int32 dcWithShift) { - { - QMutexLocker locker(&requestByDCLock); - requestsByDC.insert(requestId, dcWithShift); - } - _mtp_internal::performDelayedClear(); // need to do it somewhere.. - } - - void unregisterRequest(mtpRequestId requestId) { - requestsDelays.remove(requestId); - - { - QWriteLocker locker(&requestMapLock); - requestMap.remove(requestId); - } +bool paused() { + return _paused; +} +void registerRequest(mtpRequestId requestId, int32 dcWithShift) { + { QMutexLocker locker(&requestByDCLock); - requestsByDC.remove(requestId); + requestsByDC.insert(requestId, dcWithShift); + } + internal::performDelayedClear(); // need to do it somewhere.. +} + +void unregisterRequest(mtpRequestId requestId) { + requestsDelays.remove(requestId); + + { + QWriteLocker locker(&requestMapLock); + requestMap.remove(requestId); } - mtpRequestId storeRequest(mtpRequest &request, const RPCResponseHandler &parser) { - mtpRequestId res = reqid(); - request->requestId = res; - if (parser.onDone || parser.onFail) { - QMutexLocker locker(&parserMapLock); - parserMap.insert(res, parser); - } - { - QWriteLocker locker(&requestMapLock); - requestMap.insert(res, request); - } - return res; - } + QMutexLocker locker(&requestByDCLock); + requestsByDC.remove(requestId); +} - mtpRequest getRequest(mtpRequestId reqId) { - static mtpRequest zero; - mtpRequest req; - { - QReadLocker locker(&requestMapLock); - RequestMap::const_iterator i = requestMap.constFind(reqId); - req = (i == requestMap.cend()) ? zero : i.value(); - } - return req; +mtpRequestId storeRequest(mtpRequest &request, const RPCResponseHandler &parser) { + mtpRequestId res = reqid(); + request->requestId = res; + if (parser.onDone || parser.onFail) { + QMutexLocker locker(&parserMapLock); + parserMap.insert(res, parser); } + { + QWriteLocker locker(&requestMapLock); + requestMap.insert(res, request); + } + return res; +} - void wrapInvokeAfter(mtpRequest &to, const mtpRequest &from, const mtpRequestMap &haveSent, int32 skipBeforeRequest) { - mtpMsgId afterId(*(mtpMsgId*)(from->after->data() + 4)); - mtpRequestMap::const_iterator i = afterId ? haveSent.constFind(afterId) : haveSent.cend(); - int32 size = to->size(), lenInInts = (from.innerLength() >> 2), headlen = 4, fulllen = headlen + lenInInts; - if (i == haveSent.constEnd()) { // no invoke after or such msg was not sent or was completed recently - to->resize(size + fulllen + skipBeforeRequest); - if (skipBeforeRequest) { - memcpy(to->data() + size, from->constData() + 4, headlen * sizeof(mtpPrime)); - memcpy(to->data() + size + headlen + skipBeforeRequest, from->constData() + 4 + headlen, lenInInts * sizeof(mtpPrime)); - } else { - memcpy(to->data() + size, from->constData() + 4, fulllen * sizeof(mtpPrime)); - } - } else { - to->resize(size + fulllen + skipBeforeRequest + 3); +mtpRequest getRequest(mtpRequestId reqId) { + static mtpRequest zero; + mtpRequest req; + { + QReadLocker locker(&requestMapLock); + RequestMap::const_iterator i = requestMap.constFind(reqId); + req = (i == requestMap.cend()) ? zero : i.value(); + } + return req; +} + +void wrapInvokeAfter(mtpRequest &to, const mtpRequest &from, const mtpRequestMap &haveSent, int32 skipBeforeRequest) { + mtpMsgId afterId(*(mtpMsgId*)(from->after->data() + 4)); + mtpRequestMap::const_iterator i = afterId ? haveSent.constFind(afterId) : haveSent.cend(); + int32 size = to->size(), lenInInts = (from.innerLength() >> 2), headlen = 4, fulllen = headlen + lenInInts; + if (i == haveSent.constEnd()) { // no invoke after or such msg was not sent or was completed recently + to->resize(size + fulllen + skipBeforeRequest); + if (skipBeforeRequest) { memcpy(to->data() + size, from->constData() + 4, headlen * sizeof(mtpPrime)); - (*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); - } - } - - void clearCallbacks(mtpRequestId requestId, int32 errorCode) { - RPCResponseHandler h; - bool found = false; - { - QMutexLocker locker(&parserMapLock); - ParserMap::iterator i = parserMap.find(requestId); - if (i != parserMap.end()) { - h = i.value(); - found = true; - - parserMap.erase(i); - } - } - if (errorCode && found) { - rpcErrorOccured(requestId, h, rpcClientError("CLEAR_CALLBACK", QString("did not handle request %1, error code %2").arg(requestId).arg(errorCode))); - } - } - - void clearCallbacksDelayed(const RPCCallbackClears &requestIds) { - uint32 idsCount = requestIds.size(); - if (!idsCount) return; - - if (cDebug()) { - QString idsStr = QString("%1").arg(requestIds[0].requestId); - for (uint32 i = 1; i < idsCount; ++i) { - idsStr += QString(", %1").arg(requestIds[i].requestId); - } - DEBUG_LOG(("RPC Info: clear callbacks delayed, msgIds: %1").arg(idsStr)); - } - - QMutexLocker lock(&toClearLock); - uint32 toClearNow = toClear.size(); - if (toClearNow) { - toClear.resize(toClearNow + idsCount); - memcpy(toClear.data() + toClearNow, requestIds.constData(), idsCount * sizeof(RPCCallbackClear)); + memcpy(to->data() + size + headlen + skipBeforeRequest, from->constData() + 4 + headlen, lenInInts * sizeof(mtpPrime)); } else { - toClear = requestIds; + 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); + } +} + +void clearCallbacks(mtpRequestId requestId, int32 errorCode) { + RPCResponseHandler h; + bool found = false; + { + QMutexLocker locker(&parserMapLock); + ParserMap::iterator i = parserMap.find(requestId); + if (i != parserMap.end()) { + h = i.value(); + found = true; + + parserMap.erase(i); } } + if (errorCode && found) { + rpcErrorOccured(requestId, h, rpcClientError("CLEAR_CALLBACK", QString("did not handle request %1, error code %2").arg(requestId).arg(errorCode))); + } +} - void performDelayedClear() { - QMutexLocker lock(&toClearLock); - if (!toClear.isEmpty()) { - for (RPCCallbackClears::iterator i = toClear.begin(), e = toClear.end(); i != e; ++i) { - if (cDebug()) { - QMutexLocker locker(&parserMapLock); - if (parserMap.find(i->requestId) != parserMap.end()) { - DEBUG_LOG(("RPC Info: clearing delayed callback %1, error code %2").arg(i->requestId).arg(i->errorCode)); - } - } - clearCallbacks(i->requestId, i->errorCode); - _mtp_internal::unregisterRequest(i->requestId); - } - toClear.clear(); +void clearCallbacksDelayed(const RPCCallbackClears &requestIds) { + uint32 idsCount = requestIds.size(); + if (!idsCount) return; + + if (cDebug()) { + QString idsStr = QString("%1").arg(requestIds[0].requestId); + for (uint32 i = 1; i < idsCount; ++i) { + idsStr += QString(", %1").arg(requestIds[i].requestId); } + DEBUG_LOG(("RPC Info: clear callbacks delayed, msgIds: %1").arg(idsStr)); } - void execCallback(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) { - RPCResponseHandler h; - { - QMutexLocker locker(&parserMapLock); - ParserMap::iterator i = parserMap.find(requestId); - if (i != parserMap.cend()) { - h = i.value(); - parserMap.erase(i); + QMutexLocker lock(&toClearLock); + uint32 toClearNow = toClear.size(); + if (toClearNow) { + toClear.resize(toClearNow + idsCount); + memcpy(toClear.data() + toClearNow, requestIds.constData(), idsCount * sizeof(RPCCallbackClear)); + } else { + toClear = requestIds; + } +} - DEBUG_LOG(("RPC Info: found parser for request %1, trying to parse response..").arg(requestId)); - } - } - if (h.onDone || h.onFail) { - try { - if (from >= end) throw mtpErrorInsufficient(); - - if (*from == mtpc_rpc_error) { - RPCError err(MTPRpcError(from, end)); - DEBUG_LOG(("RPC Info: error received, code %1, type %2, description: %3").arg(err.code()).arg(err.type()).arg(err.description())); - if (!rpcErrorOccured(requestId, h, err)) { - QMutexLocker locker(&parserMapLock); - parserMap.insert(requestId, h); - return; - } - } else { - if (h.onDone) { -// t_assert(App::app() != 0); - (*h.onDone)(requestId, from, end); - } +void performDelayedClear() { + QMutexLocker lock(&toClearLock); + if (!toClear.isEmpty()) { + for (RPCCallbackClears::iterator i = toClear.begin(), e = toClear.end(); i != e; ++i) { + if (cDebug()) { + QMutexLocker locker(&parserMapLock); + if (parserMap.find(i->requestId) != parserMap.end()) { + DEBUG_LOG(("RPC Info: clearing delayed callback %1, error code %2").arg(i->requestId).arg(i->errorCode)); } - } catch (Exception &e) { - if (!rpcErrorOccured(requestId, h, rpcClientError("RESPONSE_PARSE_FAILED", QString("exception text: ") + e.what()))) { + } + clearCallbacks(i->requestId, i->errorCode); + internal::unregisterRequest(i->requestId); + } + toClear.clear(); + } +} + +void execCallback(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) { + RPCResponseHandler h; + { + QMutexLocker locker(&parserMapLock); + ParserMap::iterator i = parserMap.find(requestId); + if (i != parserMap.cend()) { + h = i.value(); + parserMap.erase(i); + + DEBUG_LOG(("RPC Info: found parser for request %1, trying to parse response..").arg(requestId)); + } + } + if (h.onDone || h.onFail) { + try { + if (from >= end) throw mtpErrorInsufficient(); + + if (*from == mtpc_rpc_error) { + RPCError err(MTPRpcError(from, end)); + DEBUG_LOG(("RPC Info: error received, code %1, type %2, description: %3").arg(err.code()).arg(err.type()).arg(err.description())); + if (!rpcErrorOccured(requestId, h, err)) { QMutexLocker locker(&parserMapLock); parserMap.insert(requestId, h); return; } - } - } else { - DEBUG_LOG(("RPC Info: parser not found for %1").arg(requestId)); - } - unregisterRequest(requestId); - } - - bool hasCallbacks(mtpRequestId requestId) { - QMutexLocker locker(&parserMapLock); - ParserMap::iterator i = parserMap.find(requestId); - return (i != parserMap.cend()); - } - - void globalCallback(const mtpPrime *from, const mtpPrime *end) { - if (globalHandler.onDone) (*globalHandler.onDone)(0, from, end); // some updates were received - } - - void onStateChange(int32 dcWithShift, int32 state) { - if (stateChangedHandler) stateChangedHandler(dcWithShift, state); - } - - void onSessionReset(int32 dcWithShift) { - if (sessionResetHandler) sessionResetHandler(dcWithShift); - } - - bool rpcErrorOccured(mtpRequestId requestId, const RPCFailHandlerPtr &onFail, const RPCError &err) { // return true if need to clean request data - if (mtpIsFlood(err)) { - if (onFail && (*onFail)(requestId, err)) return true; - } - - if (onErrorDefault(requestId, err)) { - return false; - } - LOG(("RPC Error: request %1 got fail with code %2, error %3%4").arg(requestId).arg(err.code()).arg(err.type()).arg(err.description().isEmpty() ? QString() : QString(": %1").arg(err.description()))); - onFail && (*onFail)(requestId, err); - return true; - } - - GlobalSlotCarrier::GlobalSlotCarrier() { - connect(&_timer, SIGNAL(timeout()), this, SLOT(checkDelayed())); - } - - void GlobalSlotCarrier::checkDelayed() { - uint64 now = getms(true); - while (!delayedRequests.isEmpty() && now >= delayedRequests.front().second) { - mtpRequestId requestId = delayedRequests.front().first; - delayedRequests.pop_front(); - - int32 dcWithShift = 0; - { - QMutexLocker locker(&requestByDCLock); - RequestsByDC::const_iterator i = requestsByDC.constFind(requestId); - if (i != requestsByDC.cend()) { - dcWithShift = i.value(); - } else { - LOG(("MTP Error: could not find request dc for delayed resend, requestId %1").arg(requestId)); - continue; + } else { + if (h.onDone) { +// t_assert(App::app() != 0); + (*h.onDone)(requestId, from, end); } } - - mtpRequest req; - { - QReadLocker locker(&requestMapLock); - RequestMap::const_iterator j = requestMap.constFind(requestId); - if (j == requestMap.cend()) { - DEBUG_LOG(("MTP Error: could not find request %1").arg(requestId)); - continue; - } - req = j.value(); + } catch (Exception &e) { + if (!rpcErrorOccured(requestId, h, rpcClientError("RESPONSE_PARSE_FAILED", QString("exception text: ") + e.what()))) { + QMutexLocker locker(&parserMapLock); + parserMap.insert(requestId, h); + return; } - if (MTProtoSession *session = _mtp_internal::getSession(dcWithShift < 0 ? (-dcWithShift) : dcWithShift)) { - session->sendPrepared(req); + } + } else { + DEBUG_LOG(("RPC Info: parser not found for %1").arg(requestId)); + } + unregisterRequest(requestId); +} + +bool hasCallbacks(mtpRequestId requestId) { + QMutexLocker locker(&parserMapLock); + ParserMap::iterator i = parserMap.find(requestId); + return (i != parserMap.cend()); +} + +void globalCallback(const mtpPrime *from, const mtpPrime *end) { + if (globalHandler.onDone) (*globalHandler.onDone)(0, from, end); // some updates were received +} + +void onStateChange(int32 dcWithShift, int32 state) { + if (stateChangedHandler) stateChangedHandler(dcWithShift, state); +} + +void onSessionReset(int32 dcWithShift) { + if (sessionResetHandler) sessionResetHandler(dcWithShift); +} + +bool rpcErrorOccured(mtpRequestId requestId, const RPCFailHandlerPtr &onFail, const RPCError &err) { // return true if need to clean request data + if (mtpIsFlood(err)) { + if (onFail && (*onFail)(requestId, err)) return true; + } + + if (onErrorDefault(requestId, err)) { + return false; + } + LOG(("RPC Error: request %1 got fail with code %2, error %3%4").arg(requestId).arg(err.code()).arg(err.type()).arg(err.description().isEmpty() ? QString() : QString(": %1").arg(err.description()))); + onFail && (*onFail)(requestId, err); + return true; +} + +GlobalSlotCarrier::GlobalSlotCarrier() { + connect(&_timer, SIGNAL(timeout()), this, SLOT(checkDelayed())); +} + +void GlobalSlotCarrier::checkDelayed() { + uint64 now = getms(true); + while (!delayedRequests.isEmpty() && now >= delayedRequests.front().second) { + mtpRequestId requestId = delayedRequests.front().first; + delayedRequests.pop_front(); + + int32 dcWithShift = 0; + { + QMutexLocker locker(&requestByDCLock); + RequestsByDC::const_iterator i = requestsByDC.constFind(requestId); + if (i != requestsByDC.cend()) { + dcWithShift = i.value(); + } else { + LOG(("MTP Error: could not find request dc for delayed resend, requestId %1").arg(requestId)); + continue; } } - if (!delayedRequests.isEmpty()) { - _timer.start(delayedRequests.front().second - now); + mtpRequest req; + { + QReadLocker locker(&requestMapLock); + RequestMap::const_iterator j = requestMap.constFind(requestId); + if (j == requestMap.cend()) { + DEBUG_LOG(("MTP Error: could not find request %1").arg(requestId)); + continue; + } + req = j.value(); + } + if (Session *session = getSession(qAbs(dcWithShift))) { + session->sendPrepared(req); } } - void GlobalSlotCarrier::connectionFinished(MTProtoConnection *connection) { - MTPQuittingConnections::iterator i = quittingConnections.find(connection); - if (i != quittingConnections.cend()) { - quittingConnections.erase(i); - } + if (!delayedRequests.isEmpty()) { + _timer.start(delayedRequests.front().second - now); + } +} - connection->waitTillFinish(); - delete connection; +void GlobalSlotCarrier::connectionFinished(Connection *connection) { + MTPQuittingConnections::iterator i = quittingConnections.find(connection); + if (i != quittingConnections.cend()) { + quittingConnections.erase(i); } - GlobalSlotCarrier *globalSlotCarrier() { - return _globalSlotCarrier; + connection->waitTillFinish(); + delete connection; +} + +GlobalSlotCarrier *globalSlotCarrier() { + return _globalSlotCarrier; +} + +void queueQuittingConnection(Connection *connection) { + quittingConnections.insert(connection); +} + +} // namespace internal + +void start() { + if (started()) return; + + unixtimeInit(); + + MTProtoDCMap &dcs(mtpDCMap()); + + _globalSlotCarrier = new internal::GlobalSlotCarrier(); + + mainSession = new internal::Session(mtpMainDC()); + sessions.insert(mainSession->getDcWithShift(), mainSession); + + _started = true; + + if (mtpNeedConfig()) { + mtpConfigLoader()->load(); } +} - void queueQuittingConnection(MTProtoConnection *connection) { - quittingConnections.insert(connection); +bool started() { + return _started; +} + +void restart() { + if (!_started) return; + + for (auto i = sessions.cbegin(), e = sessions.cend(); i != e; ++i) { + i.value()->restart(); } +} -}; +void restart(int32 dcMask) { + if (!_started) return; -namespace MTP { - - const uint32 cfg = 1 * _mtp_internal::dcShift; // send(MTPhelp_GetConfig(), MTP::cfg + dc) - for dc enum - const uint32 lgt = 2 * _mtp_internal::dcShift; // send(MTPauth_LogOut(), MTP::lgt + dc) - for logout of guest dcs enum - const uint32 dldStart = dld(0), dldEnd = dld(MTPDownloadSessionsCount - 1) + _mtp_internal::dcShift; - const uint32 uplStart = upl(0), uplEnd = upl(MTPUploadSessionsCount - 1) + _mtp_internal::dcShift; - - void start() { - if (started()) return; - - unixtimeInit(); - - MTProtoDCMap &dcs(mtpDCMap()); - - _globalSlotCarrier = new _mtp_internal::GlobalSlotCarrier(); - - mainSession = new MTProtoSession(mtpMainDC()); - sessions.insert(mainSession->getDcWithShift(), mainSession); - - _started = true; - - if (mtpNeedConfig()) { - mtpConfigLoader()->load(); - } - } - - bool started() { - return _started; - } - - void restart() { - if (!_started) return; - - for (Sessions::const_iterator i = sessions.cbegin(), e = sessions.cend(); i != e; ++i) { + dcMask = bareDcId(dcMask); + for (Sessions::const_iterator i = sessions.cbegin(), e = sessions.cend(); i != e; ++i) { + if (bareDcId(i.value()->getDcWithShift()) == dcMask) { i.value()->restart(); } } +} - void restart(int32 dcMask) { - if (!_started) return; +void pause() { + if (!_started) return; + _paused = true; +} - dcMask %= _mtp_internal::dcShift; - for (Sessions::const_iterator i = sessions.cbegin(), e = sessions.cend(); i != e; ++i) { - if ((i.value()->getDcWithShift() % int(_mtp_internal::dcShift)) == dcMask) { - i.value()->restart(); +void unpause() { + if (!_started) return; + _paused = false; + for (Sessions::const_iterator i = sessions.cbegin(), e = sessions.cend(); i != e; ++i) { + i.value()->unpaused(); + } +} + +void configure(int32 dc, int32 user) { + if (_started) return; + mtpSetDC(dc); + mtpAuthed(user); +} + +void setdc(int32 dc, bool fromZeroOnly) { + if (!dc || !_started) return; + mtpSetDC(dc, fromZeroOnly); + int32 oldMainDc = mainSession->getDcWithShift(); + if (maindc() != oldMainDc) { + killSession(oldMainDc); + } + Local::writeMtpData(); +} + +int32 maindc() { + return mtpMainDC(); +} + +int32 dcstate(int32 dc) { + if (!_started) return 0; + + if (!dc) return mainSession->getState(); + if (!bareDcId(dc)) { + dc += bareDcId(mainSession->getDcWithShift()); + } + + Sessions::const_iterator i = sessions.constFind(dc); + if (i != sessions.cend()) return i.value()->getState(); + + return DisconnectedState; +} + +QString dctransport(int32 dc) { + if (!_started) return QString(); + + if (!dc) return mainSession->transport(); + if (!bareDcId(dc)) { + dc += bareDcId(mainSession->getDcWithShift()); + } + + Sessions::const_iterator i = sessions.constFind(dc); + if (i != sessions.cend()) return i.value()->transport(); + + return QString(); +} + +void ping() { + if (internal::Session *session = internal::getSession(0)) { + session->ping(); + } +} + +void cancel(mtpRequestId requestId) { + if (!_started) return; + + mtpMsgId msgId = 0; + requestsDelays.remove(requestId); + { + QWriteLocker locker(&requestMapLock); + RequestMap::iterator i = requestMap.find(requestId); + if (i != requestMap.end()) { + msgId = *(mtpMsgId*)(i.value()->constData() + 4); + requestMap.erase(i); + } + } + { + QMutexLocker locker(&requestByDCLock); + RequestsByDC::iterator i = requestsByDC.find(requestId); + if (i != requestsByDC.end()) { + if (internal::Session *session = internal::getSession(qAbs(i.value()))) { + session->cancel(requestId, msgId); } + requestsByDC.erase(i); } } + internal::clearCallbacks(requestId); +} - void pause() { - if (!_started) return; - _paused = true; - } +void killSession(int32 dc) { + Sessions::iterator i = sessions.find(dc); + if (i != sessions.cend()) { + bool wasMain = (i.value() == mainSession); - void unpause() { - if (!_started) return; - _paused = false; - for (Sessions::const_iterator i = sessions.cbegin(), e = sessions.cend(); i != e; ++i) { - i.value()->unpaused(); - } - } + i.value()->kill(); + i.value()->deleteLater(); + sessions.erase(i); - void configure(int32 dc, int32 user) { - if (_started) return; - mtpSetDC(dc); - mtpAuthed(user); - } - - void setdc(int32 dc, bool fromZeroOnly) { - if (!dc || !_started) return; - mtpSetDC(dc, fromZeroOnly); - int32 oldMainDc = mainSession->getDcWithShift(); - if (maindc() != oldMainDc) { - killSession(oldMainDc); - } - Local::writeMtpData(); - } - - int32 maindc() { - return mtpMainDC(); - } - - int32 dcstate(int32 dc) { - if (!_started) return 0; - - if (!dc) return mainSession->getState(); - if (!(dc % _mtp_internal::dcShift)) { - dc += (mainSession->getDcWithShift() % _mtp_internal::dcShift); - } - - Sessions::const_iterator i = sessions.constFind(dc); - if (i != sessions.cend()) return i.value()->getState(); - - return MTProtoConnection::Disconnected; - } - - QString dctransport(int32 dc) { - if (!_started) return QString(); - - if (!dc) return mainSession->transport(); - if (!(dc % _mtp_internal::dcShift)) { - dc += (mainSession->getDcWithShift() % _mtp_internal::dcShift); - } - - Sessions::const_iterator i = sessions.constFind(dc); - if (i != sessions.cend()) return i.value()->transport(); - - return QString(); - } - - void ping() { - if (MTProtoSession *session = _mtp_internal::getSession(0)) { - session->ping(); - } - } - - void cancel(mtpRequestId requestId) { - if (!_started) return; - - mtpMsgId msgId = 0; - requestsDelays.remove(requestId); - { - QWriteLocker locker(&requestMapLock); - RequestMap::iterator i = requestMap.find(requestId); - if (i != requestMap.end()) { - msgId = *(mtpMsgId*)(i.value()->constData() + 4); - requestMap.erase(i); + if (wasMain) { + mainSession = new internal::Session(mtpMainDC()); + int32 newdc = mainSession->getDcWithShift(); + i = sessions.find(newdc); + if (i != sessions.cend()) { + i.value()->kill(); + i.value()->deleteLater(); + sessions.erase(i); } + sessions.insert(newdc, mainSession); } - { - QMutexLocker locker(&requestByDCLock); - RequestsByDC::iterator i = requestsByDC.find(requestId); - if (i != requestsByDC.end()) { - if (MTProtoSession *session = _mtp_internal::getSession(abs(i.value()))) { - session->cancel(requestId, msgId); - } - requestsByDC.erase(i); + } +} + +void stopSession(int32 dc) { + Sessions::iterator i = sessions.find(dc); + if (i != sessions.end()) { + if (i.value() != mainSession) { // don't stop main session + i.value()->stop(); + } + } +} + +int32 state(mtpRequestId requestId) { + if (requestId > 0) { + QMutexLocker locker(&requestByDCLock); + RequestsByDC::iterator i = requestsByDC.find(requestId); + if (i != requestsByDC.end()) { + if (internal::Session *session = internal::getSession(qAbs(i.value()))) { + return session->requestState(requestId); } + return MTP::RequestConnecting; } - _mtp_internal::clearCallbacks(requestId); + return MTP::RequestSent; } - - void killSession(int32 dc) { - Sessions::iterator i = sessions.find(dc); - if (i != sessions.cend()) { - bool wasMain = (i.value() == mainSession); - - i.value()->kill(); - i.value()->deleteLater(); - sessions.erase(i); - - if (wasMain) { - mainSession = new MTProtoSession(mtpMainDC()); - int32 newdc = mainSession->getDcWithShift(); - i = sessions.find(newdc); - if (i != sessions.cend()) { - i.value()->kill(); - i.value()->deleteLater(); - sessions.erase(i); - } - sessions.insert(newdc, mainSession); - } - } + if (internal::Session *session = internal::getSession(-requestId)) { + return session->requestState(0); } + return MTP::RequestConnecting; +} - void stopSession(int32 dc) { - Sessions::iterator i = sessions.find(dc); - if (i != sessions.end()) { - if (i.value() != mainSession) { // don't stop main session - i.value()->stop(); - } - } +void finish() { + for (Sessions::iterator i = sessions.begin(), e = sessions.end(); i != e; ++i) { + i.value()->kill(); + delete i.value(); } + sessions.clear(); + mainSession = nullptr; - int32 state(mtpRequestId requestId) { - if (requestId > 0) { - QMutexLocker locker(&requestByDCLock); - RequestsByDC::iterator i = requestsByDC.find(requestId); - if (i != requestsByDC.end()) { - if (MTProtoSession *session = _mtp_internal::getSession(abs(i.value()))) { - return session->requestState(requestId); - } - return MTP::RequestConnecting; - } - return MTP::RequestSent; - } - if (MTProtoSession *session = _mtp_internal::getSession(-requestId)) { - return session->requestState(0); - } - return MTP::RequestConnecting; + for (MTPQuittingConnections::const_iterator i = quittingConnections.cbegin(), e = quittingConnections.cend(); i != e; ++i) { + i.key()->waitTillFinish(); + delete i.key(); } + quittingConnections.clear(); - void finish() { - for (Sessions::iterator i = sessions.begin(), e = sessions.end(); i != e; ++i) { - i.value()->kill(); - delete i.value(); - } - sessions.clear(); - mainSession = nullptr; + delete _globalSlotCarrier; + _globalSlotCarrier = nullptr; - for (MTPQuittingConnections::const_iterator i = quittingConnections.cbegin(), e = quittingConnections.cend(); i != e; ++i) { - i.key()->waitTillFinish(); - delete i.key(); - } - quittingConnections.clear(); + mtpDestroyConfigLoader(); - delete _globalSlotCarrier; - _globalSlotCarrier = nullptr; + _started = false; +} - mtpDestroyConfigLoader(); +void authed(int32 uid) { + mtpAuthed(uid); +} - _started = false; - } +int32 authedId() { + return mtpAuthed(); +} - void authed(int32 uid) { - mtpAuthed(uid); - } +void logoutKeys(RPCDoneHandlerPtr onDone, RPCFailHandlerPtr onFail) { + mtpRequestId req = MTP::send(MTPauth_LogOut(), onDone, onFail); + mtpLogoutOtherDCs(); +} - int32 authedId() { - return mtpAuthed(); - } +void setGlobalDoneHandler(RPCDoneHandlerPtr handler) { + globalHandler.onDone = handler; +} - void logoutKeys(RPCDoneHandlerPtr onDone, RPCFailHandlerPtr onFail) { - mtpRequestId req = MTP::send(MTPauth_LogOut(), onDone, onFail); - mtpLogoutOtherDCs(); - } +void setGlobalFailHandler(RPCFailHandlerPtr handler) { + globalHandler.onFail = handler; +} - void setGlobalDoneHandler(RPCDoneHandlerPtr handler) { - globalHandler.onDone = handler; - } +void setStateChangedHandler(MTPStateChangedHandler handler) { + stateChangedHandler = handler; +} - void setGlobalFailHandler(RPCFailHandlerPtr handler) { - globalHandler.onFail = handler; - } +void setSessionResetHandler(MTPSessionResetHandler handler) { + sessionResetHandler = handler; +} - void setStateChangedHandler(MTPStateChangedHandler handler) { - stateChangedHandler = handler; - } +void clearGlobalHandlers() { + setGlobalDoneHandler(RPCDoneHandlerPtr()); + setGlobalFailHandler(RPCFailHandlerPtr()); + setStateChangedHandler(0); + setSessionResetHandler(0); +} - void setSessionResetHandler(MTPSessionResetHandler handler) { - sessionResetHandler = handler; - } +void updateDcOptions(const QVector &options) { + mtpUpdateDcOptions(options); + Local::writeSettings(); +} - void clearGlobalHandlers() { - setGlobalDoneHandler(RPCDoneHandlerPtr()); - setGlobalFailHandler(RPCFailHandlerPtr()); - setStateChangedHandler(0); - setSessionResetHandler(0); - } +mtpKeysMap getKeys() { + return mtpGetKeys(); +} - void updateDcOptions(const QVector &options) { - mtpUpdateDcOptions(options); - Local::writeSettings(); - } +void setKey(int32 dc, mtpAuthKeyPtr key) { + return mtpSetKey(dc, key); +} - mtpKeysMap getKeys() { - return mtpGetKeys(); - } +QReadWriteLock *dcOptionsMutex() { + return mtpDcOptionsMutex(); +} - void setKey(int32 dc, mtpAuthKeyPtr key) { - return mtpSetKey(dc, key); - } - - QReadWriteLock *dcOptionsMutex() { - return mtpDcOptionsMutex(); - } - -}; +} // namespace MTP diff --git a/Telegram/SourceFiles/mtproto/facade.h b/Telegram/SourceFiles/mtproto/facade.h index 88d5863be..912fee118 100644 --- a/Telegram/SourceFiles/mtproto/facade.h +++ b/Telegram/SourceFiles/mtproto/facade.h @@ -20,177 +20,227 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org */ #pragma once +#include "mtproto/core_types.h" #include "mtproto/session.h" #include "mtproto/file_download.h" -namespace _mtp_internal { - MTProtoSession *getSession(int32 dc); // 0 - current set dc - - bool paused(); - - void registerRequest(mtpRequestId requestId, int32 dc); - void unregisterRequest(mtpRequestId requestId); - - static const uint32 dcShift = 10000; - - mtpRequestId storeRequest(mtpRequest &request, const RPCResponseHandler &parser); - mtpRequest getRequest(mtpRequestId req); - void wrapInvokeAfter(mtpRequest &to, const mtpRequest &from, const mtpRequestMap &haveSent, int32 skipBeforeRequest = 0); - void clearCallbacks(mtpRequestId requestId, int32 errorCode = RPCError::NoError); // 0 - do not toggle onError callback - void clearCallbacksDelayed(const RPCCallbackClears &requestIds); - void performDelayedClear(); - void execCallback(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end); - bool hasCallbacks(mtpRequestId requestId); - void globalCallback(const mtpPrime *from, const mtpPrime *end); - void onStateChange(int32 dcWithShift, int32 state); - void onSessionReset(int32 dcWithShift); - bool rpcErrorOccured(mtpRequestId requestId, const RPCFailHandlerPtr &onFail, const RPCError &err); // return true if need to clean request data - inline bool rpcErrorOccured(mtpRequestId requestId, const RPCResponseHandler &handler, const RPCError &err) { - return rpcErrorOccured(requestId, handler.onFail, err); - } - - // used for: - // - resending requests by timer which were postponed by flood delay - // - destroying MTProtoConnections whose thread has finished - class GlobalSlotCarrier : public QObject { - Q_OBJECT - - public: - - GlobalSlotCarrier(); - - public slots: - - void checkDelayed(); - void connectionFinished(MTProtoConnection *connection); - - private: - - SingleTimer _timer; - }; - - GlobalSlotCarrier *globalSlotCarrier(); - void queueQuittingConnection(MTProtoConnection *connection); -}; - namespace MTP { - extern const uint32 cfg; // send(MTPhelp_GetConfig(), MTP::cfg + dc) - for dc enum - extern const uint32 lgt; // send(MTPauth_LogOut(), MTP::lgt + dc) - for logout of guest dcs enum - inline uint32 dld(int32 index) { // send(req, callbacks, MTP::dld(i) + dc) - for download - t_assert(index >= 0 && index < MTPDownloadSessionsCount); - return (0x10 + index) * _mtp_internal::dcShift; - }; - inline uint32 upl(int32 index) { // send(req, callbacks, MTP::upl(i) + dc) - for upload - t_assert(index >= 0 && index < MTPUploadSessionsCount); - return (0x20 + index) * _mtp_internal::dcShift; - }; - extern const uint32 dldStart, dldEnd; // dc >= dldStart && dc < dldEnd => dc in dld - extern const uint32 uplStart, uplEnd; // dc >= uplStart && dc < uplEnd => dc in upl +namespace internal { - void start(); - bool started(); - void restart(); - void restart(int32 dcMask); +Session *getSession(ShiftedDcId shiftedDcId); // 0 - current set dc - void pause(); - void unpause(); +bool paused(); - void configure(int32 dc, int32 user); +void registerRequest(mtpRequestId requestId, int32 dc); +void unregisterRequest(mtpRequestId requestId); - void setdc(int32 dc, bool fromZeroOnly = false); - int32 maindc(); +mtpRequestId storeRequest(mtpRequest &request, const RPCResponseHandler &parser); +mtpRequest getRequest(mtpRequestId req); +void wrapInvokeAfter(mtpRequest &to, const mtpRequest &from, const mtpRequestMap &haveSent, int32 skipBeforeRequest = 0); +void clearCallbacks(mtpRequestId requestId, int32 errorCode = RPCError::NoError); // 0 - do not toggle onError callback +void clearCallbacksDelayed(const RPCCallbackClears &requestIds); +void performDelayedClear(); +void execCallback(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end); +bool hasCallbacks(mtpRequestId requestId); +void globalCallback(const mtpPrime *from, const mtpPrime *end); +void onStateChange(int32 dcWithShift, int32 state); +void onSessionReset(int32 dcWithShift); +bool rpcErrorOccured(mtpRequestId requestId, const RPCFailHandlerPtr &onFail, const RPCError &err); // return true if need to clean request data +inline bool rpcErrorOccured(mtpRequestId requestId, const RPCResponseHandler &handler, const RPCError &err) { + return rpcErrorOccured(requestId, handler.onFail, err); +} - int32 dcstate(int32 dc = 0); - QString dctransport(int32 dc = 0); +// used for: +// - resending requests by timer which were postponed by flood delay +// - destroying MTProtoConnections whose thread has finished +class GlobalSlotCarrier : public QObject { + Q_OBJECT - template - inline mtpRequestId send(const TRequest &request, RPCResponseHandler callbacks = RPCResponseHandler(), int32 dc = 0, uint64 msCanWait = 0, mtpRequestId after = 0) { - if (MTProtoSession *session = _mtp_internal::getSession(dc)) { - return session->send(request, callbacks, msCanWait, true, !dc, after); - } - return 0; - } - template - inline mtpRequestId send(const TRequest &request, RPCDoneHandlerPtr onDone, RPCFailHandlerPtr onFail = RPCFailHandlerPtr(), int32 dc = 0, uint64 msCanWait = 0, mtpRequestId after = 0) { - return send(request, RPCResponseHandler(onDone, onFail), dc, msCanWait, after); - } - inline void sendAnything(int32 dc = 0, uint64 msCanWait = 0) { - if (MTProtoSession *session = _mtp_internal::getSession(dc)) { - return session->sendAnything(msCanWait); - } - } - void ping(); - void cancel(mtpRequestId req); - void killSession(int32 dc); - void stopSession(int32 dc); +public: - enum { - RequestSent = 0, - RequestConnecting = 1, - RequestSending = 2 - }; - int32 state(mtpRequestId req); // < 0 means waiting for such count of ms + GlobalSlotCarrier(); - void finish(); +public slots: - void authed(int32 uid); - int32 authedId(); - void logoutKeys(RPCDoneHandlerPtr onDone, RPCFailHandlerPtr onFail); + void checkDelayed(); + void connectionFinished(Connection *connection); - void setGlobalDoneHandler(RPCDoneHandlerPtr handler); - void setGlobalFailHandler(RPCFailHandlerPtr handler); - void setStateChangedHandler(MTPStateChangedHandler handler); - void setSessionResetHandler(MTPSessionResetHandler handler); - void clearGlobalHandlers(); - - void updateDcOptions(const QVector &options); - - template - T nonce() { - T result; - memset_rand(&result, sizeof(T)); - return result; - } - - mtpKeysMap getKeys(); - void setKey(int32 dc, mtpAuthKeyPtr key); - - QReadWriteLock *dcOptionsMutex(); - - struct DcOption { - DcOption(int id, MTPDdcOption::Flags flags, const string &ip, int port) : id(id), flags(flags), ip(ip), port(port) { - } - - int id; - MTPDdcOption::Flags flags; - string ip; - int port; - }; - typedef QMap DcOptions; +private: + SingleTimer _timer; }; -template -mtpRequestId MTProtoSession::send(const TRequest &request, RPCResponseHandler callbacks, uint64 msCanWait, bool needsLayer, bool toMainDC, mtpRequestId after) { - mtpRequestId requestId = 0; - try { - uint32 requestSize = request.innerLength() >> 2; - mtpRequest reqSerialized(mtpRequestData::prepare(requestSize)); - request.write(*reqSerialized); +GlobalSlotCarrier *globalSlotCarrier(); +void queueQuittingConnection(Connection *connection); - DEBUG_LOG(("MTP Info: adding request to toSendMap, msCanWait %1").arg(msCanWait)); +} // namespace internal - reqSerialized->msDate = getms(true); // > 0 - can send without container - reqSerialized->needsLayer = needsLayer; - if (after) reqSerialized->after = _mtp_internal::getRequest(after); - requestId = _mtp_internal::storeRequest(reqSerialized, callbacks); - - sendPrepared(reqSerialized, msCanWait); - } catch (Exception &e) { - requestId = 0; - _mtp_internal::rpcErrorOccured(requestId, callbacks, rpcClientError("NO_REQUEST_ID", QString("send() failed to queue request, exception: %1").arg(e.what()))); - } - if (requestId) _mtp_internal::registerRequest(requestId, toMainDC ? -getDcWithShift() : getDcWithShift()); - return requestId; +constexpr ShiftedDcId DCShift = 10000; +constexpr DcId bareDcId(ShiftedDcId shiftedDcId) { + return (shiftedDcId % DCShift); } +constexpr ShiftedDcId shiftDcId(DcId dcId, int value) { + return dcId + DCShift * value; +} +constexpr int getDcIdShift(ShiftedDcId shiftedDcId) { + return (shiftedDcId - bareDcId(shiftedDcId)) / DCShift; +} + +// send(MTPhelp_GetConfig(), MTP::cfgDcId(dc)) - for dc enumeration +constexpr ShiftedDcId cfgDcId(DcId dcId) { + return shiftDcId(dcId, 0x01); +} + +// send(MTPauth_LogOut(), MTP::lgtDcId(dc)) - for logout of guest dcs enumeration +constexpr ShiftedDcId lgtDcId(DcId dcId) { + return shiftDcId(dcId, 0x02); +} + +namespace internal { + constexpr ShiftedDcId downloadDcId(DcId dcId, int index) { + static_assert(MTPDownloadSessionsCount < 0x10, "Too large MTPDownloadSessionsCount!"); + return shiftDcId(dcId, 0x10 + index); + }; +} + +// send(req, callbacks, MTP::dldDcId(dc, index)) - for download shifted dc id +inline ShiftedDcId dldDcId(DcId dcId, int index) { + t_assert(index >= 0 && index < MTPDownloadSessionsCount); + return internal::downloadDcId(dcId, index); +} +constexpr bool isDldDcId(ShiftedDcId shiftedDcId) { + return (shiftedDcId >= internal::downloadDcId(0, 0)) && (shiftedDcId < internal::downloadDcId(0, MTPDownloadSessionsCount - 1) + DCShift); +} + +namespace internal { + constexpr ShiftedDcId uploadDcId(DcId dcId, int index) { + static_assert(MTPUploadSessionsCount < 0x10, "Too large MTPUploadSessionsCount!"); + return shiftDcId(dcId, 0x20 + index); + }; +} + +// send(req, callbacks, MTP::uplDcId(index)) - for upload shifted dc id +// uploading always to the main dc so bareDcId == 0 +inline ShiftedDcId uplDcId(DcId dcId) { + return internal::uploadDcId(dcId, 0); +}; +constexpr bool isUplDcId(ShiftedDcId shiftedDcId) { + return (shiftedDcId >= internal::uploadDcId(0, 0)) && (shiftedDcId < internal::uploadDcId(0, MTPUploadSessionsCount - 1) + DCShift); +} + +void start(); +bool started(); +void restart(); +void restart(int32 dcMask); + +void pause(); +void unpause(); + +void configure(int32 dc, int32 user); + +void setdc(int32 dc, bool fromZeroOnly = false); +int32 maindc(); + +enum { + DisconnectedState = 0, + ConnectingState = 1, + ConnectedState = 2, +}; +int32 dcstate(int32 dc = 0); +QString dctransport(int32 dc = 0); + +template +inline mtpRequestId send(const TRequest &request, RPCResponseHandler callbacks = RPCResponseHandler(), int32 dc = 0, uint64 msCanWait = 0, mtpRequestId after = 0) { + if (internal::Session *session = internal::getSession(dc)) { + return session->send(request, callbacks, msCanWait, true, !dc, after); + } + return 0; +} +template +inline mtpRequestId send(const TRequest &request, RPCDoneHandlerPtr onDone, RPCFailHandlerPtr onFail = RPCFailHandlerPtr(), int32 dc = 0, uint64 msCanWait = 0, mtpRequestId after = 0) { + return send(request, RPCResponseHandler(onDone, onFail), dc, msCanWait, after); +} +inline void sendAnything(int32 dc = 0, uint64 msCanWait = 0) { + if (internal::Session *session = internal::getSession(dc)) { + return session->sendAnything(msCanWait); + } +} +void ping(); +void cancel(mtpRequestId req); +void killSession(int32 dc); +void stopSession(int32 dc); + +enum { + RequestSent = 0, + RequestConnecting = 1, + RequestSending = 2 +}; +int32 state(mtpRequestId req); // < 0 means waiting for such count of ms + +void finish(); + +void authed(int32 uid); +int32 authedId(); +void logoutKeys(RPCDoneHandlerPtr onDone, RPCFailHandlerPtr onFail); + +void setGlobalDoneHandler(RPCDoneHandlerPtr handler); +void setGlobalFailHandler(RPCFailHandlerPtr handler); +void setStateChangedHandler(MTPStateChangedHandler handler); +void setSessionResetHandler(MTPSessionResetHandler handler); +void clearGlobalHandlers(); + +void updateDcOptions(const QVector &options); + +template +T nonce() { + T result; + memset_rand(&result, sizeof(T)); + return result; +} + +mtpKeysMap getKeys(); +void setKey(int32 dc, mtpAuthKeyPtr key); + +QReadWriteLock *dcOptionsMutex(); + +struct DcOption { + DcOption(int id, MTPDdcOption::Flags flags, const string &ip, int port) : id(id), flags(flags), ip(ip), port(port) { + } + + int id; + MTPDdcOption::Flags flags; + string ip; + int port; +}; +typedef QMap DcOptions; + +namespace internal { + + template + mtpRequestId Session::send(const TRequest &request, RPCResponseHandler callbacks, uint64 msCanWait, bool needsLayer, bool toMainDC, mtpRequestId after) { + mtpRequestId requestId = 0; + try { + uint32 requestSize = request.innerLength() >> 2; + mtpRequest reqSerialized(mtpRequestData::prepare(requestSize)); + request.write(*reqSerialized); + + DEBUG_LOG(("MTP Info: adding request to toSendMap, msCanWait %1").arg(msCanWait)); + + reqSerialized->msDate = getms(true); // > 0 - can send without container + reqSerialized->needsLayer = needsLayer; + if (after) reqSerialized->after = MTP::internal::getRequest(after); + requestId = MTP::internal::storeRequest(reqSerialized, callbacks); + + sendPrepared(reqSerialized, msCanWait); + } catch (Exception &e) { + requestId = 0; + MTP::internal::rpcErrorOccured(requestId, callbacks, rpcClientError("NO_REQUEST_ID", QString("send() failed to queue request, exception: %1").arg(e.what()))); + } + if (requestId) MTP::internal::registerRequest(requestId, toMainDC ? -getDcWithShift() : getDcWithShift()); + return requestId; + } + +} // namespace internal + +} // namespace MTP diff --git a/Telegram/SourceFiles/mtproto/file_download.cpp b/Telegram/SourceFiles/mtproto/file_download.cpp index c40e20e98..aa8251de4 100644 --- a/Telegram/SourceFiles/mtproto/file_download.cpp +++ b/Telegram/SourceFiles/mtproto/file_download.cpp @@ -352,9 +352,9 @@ mtpFileLoader::mtpFileLoader(const StorageImageLocation *location, int32 size, L , _location(location) , _id(0) , _access(0) { - LoaderQueues::iterator i = queues.find(MTP::dld(0) + _dc); + LoaderQueues::iterator i = queues.find(MTP::dldDcId(_dc, 0)); if (i == queues.cend()) { - i = queues.insert(MTP::dld(0) + _dc, FileLoaderQueue(MaxFileQueries)); + i = queues.insert(MTP::dldDcId(_dc, 0), FileLoaderQueue(MaxFileQueries)); } _queue = &i.value(); } @@ -368,9 +368,9 @@ mtpFileLoader::mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, L , _location(0) , _id(id) , _access(access) { - LoaderQueues::iterator i = queues.find(MTP::dld(0) + _dc); + LoaderQueues::iterator i = queues.find(MTP::dldDcId(_dc, 0)); if (i == queues.cend()) { - i = queues.insert(MTP::dld(0) + _dc, FileLoaderQueue(MaxFileQueries)); + i = queues.insert(MTP::dldDcId(_dc, 0), FileLoaderQueue(MaxFileQueries)); } _queue = &i.value(); } @@ -432,7 +432,7 @@ bool mtpFileLoader::loadPart() { App::app()->killDownloadSessionsStop(_dc); - mtpRequestId reqId = MTP::send(MTPupload_GetFile(MTPupload_getFile(loc, MTP_int(offset), MTP_int(limit))), rpcDone(&mtpFileLoader::partLoaded, offset), rpcFail(&mtpFileLoader::partFailed), MTP::dld(dcIndex) + _dc, 50); + mtpRequestId reqId = MTP::send(MTPupload_GetFile(MTPupload_getFile(loc, MTP_int(offset), MTP_int(limit))), rpcDone(&mtpFileLoader::partLoaded, offset), rpcFail(&mtpFileLoader::partFailed), MTP::dldDcId(_dc, dcIndex), 50); ++_queue->queries; dr.v[dcIndex] += limit; diff --git a/Telegram/SourceFiles/mtproto/session.cpp b/Telegram/SourceFiles/mtproto/session.cpp index 8409549b0..9c4ad9c73 100644 --- a/Telegram/SourceFiles/mtproto/session.cpp +++ b/Telegram/SourceFiles/mtproto/session.cpp @@ -22,7 +22,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "mtproto/session.h" -void MTPSessionData::clear() { +namespace MTP { +namespace internal { + +void SessionData::clear() { RPCCallbackClears clearCallbacks; { QReadLocker locker1(haveSentMutex()), locker2(toResendMutex()), locker3(haveReceivedMutex()), locker4(wereAckedMutex()); @@ -63,11 +66,11 @@ void MTPSessionData::clear() { QWriteLocker locker(receivedIdsMutex()); receivedIds.clear(); } - _mtp_internal::clearCallbacksDelayed(clearCallbacks); + clearCallbacksDelayed(clearCallbacks); } -MTProtoSession::MTProtoSession(int32 dcenter) : QObject() +Session::Session(int32 dcenter) : QObject() , _connection(0) , _killed(false) , _needToReceive(false) @@ -95,7 +98,7 @@ MTProtoSession::MTProtoSession(int32 dcenter) : QObject() MTProtoDCMap &dcs(mtpDCMap()); - _connection = new MTProtoConnection(); + _connection = new Connection(); dcWithShift = _connection->start(&data, dcenter); if (!dcWithShift) { delete _connection; @@ -105,11 +108,11 @@ MTProtoSession::MTProtoSession(int32 dcenter) : QObject() } if (!dc) { dcenter = dcWithShift; - int32 dcId = dcWithShift % _mtp_internal::dcShift; + int32 dcId = bareDcId(dcWithShift); MTProtoDCMap::const_iterator dcIndex = dcs.constFind(dcId); if (dcIndex == dcs.cend()) { dc = MTProtoDCPtr(new MTProtoDC(dcId, mtpAuthKeyPtr())); - dcs.insert(dcWithShift % _mtp_internal::dcShift, dc); + dcs.insert(dcId, dc); } else { dc = dcIndex.value(); } @@ -124,7 +127,7 @@ MTProtoSession::MTProtoSession(int32 dcenter) : QObject() } } -void MTProtoSession::restart() { +void Session::restart() { if (_killed) { DEBUG_LOG(("Session Error: can't restart a killed session")); return; @@ -132,7 +135,7 @@ void MTProtoSession::restart() { emit needToRestart(); } -void MTProtoSession::stop() { +void Session::stop() { if (_killed) { DEBUG_LOG(("Session Error: can't kill a killed session")); return; @@ -144,20 +147,20 @@ void MTProtoSession::stop() { } } -void MTProtoSession::kill() { +void Session::kill() { stop(); _killed = true; DEBUG_LOG(("Session Info: marked session dcWithShift %1 as killed").arg(dcWithShift)); } -void MTProtoSession::unpaused() { +void Session::unpaused() { if (_needToReceive) { _needToReceive = false; QTimer::singleShot(0, this, SLOT(tryToReceive())); } } -void MTProtoSession::sendAnything(quint64 msCanWait) { +void Session::sendAnything(quint64 msCanWait) { if (_killed) { DEBUG_LOG(("Session Error: can't send anything in a killed session")); return; @@ -187,7 +190,7 @@ void MTProtoSession::sendAnything(quint64 msCanWait) { } } -void MTProtoSession::needToResumeAndSend() { +void Session::needToResumeAndSend() { if (_killed) { DEBUG_LOG(("Session Info: can't resume a killed session")); return; @@ -196,7 +199,7 @@ void MTProtoSession::needToResumeAndSend() { DEBUG_LOG(("Session Info: resuming session dcWithShift %1").arg(dcWithShift)); MTProtoDCMap &dcs(mtpDCMap()); - _connection = new MTProtoConnection(); + _connection = new Connection(); if (!_connection->start(&data, dcWithShift)) { delete _connection; _connection = 0; @@ -213,11 +216,11 @@ void MTProtoSession::needToResumeAndSend() { } } -void MTProtoSession::sendPong(quint64 msgId, quint64 pingId) { +void Session::sendPong(quint64 msgId, quint64 pingId) { send(MTP_pong(MTP_long(msgId), MTP_long(pingId))); } -void MTProtoSession::sendMsgsStateInfo(quint64 msgId, QByteArray data) { +void Session::sendMsgsStateInfo(quint64 msgId, QByteArray data) { MTPMsgsStateInfo req(MTP_msgs_state_info(MTP_long(msgId), MTPstring())); string &info(req._msgs_state_info().vinfo._string().v); info.resize(data.size()); @@ -227,7 +230,7 @@ void MTProtoSession::sendMsgsStateInfo(quint64 msgId, QByteArray data) { send(req); } -void MTProtoSession::checkRequestsByTimer() { +void Session::checkRequestsByTimer() { QVector resendingIds; QVector removingIds; // remove very old (10 minutes) containers and resend requests QVector stateRequestIds; @@ -288,19 +291,19 @@ void MTProtoSession::checkRequestsByTimer() { } } } - _mtp_internal::clearCallbacksDelayed(clearCallbacks); + clearCallbacksDelayed(clearCallbacks); } } -void MTProtoSession::onConnectionStateChange(qint32 newState) { - _mtp_internal::onStateChange(dcWithShift, newState); +void Session::onConnectionStateChange(qint32 newState) { + onStateChange(dcWithShift, newState); } -void MTProtoSession::onResetDone() { - _mtp_internal::onSessionReset(dcWithShift); +void Session::onResetDone() { + onSessionReset(dcWithShift); } -void MTProtoSession::cancel(mtpRequestId requestId, mtpMsgId msgId) { +void Session::cancel(mtpRequestId requestId, mtpMsgId msgId) { if (requestId) { QWriteLocker locker(data.toSendMutex()); data.toSendMap().remove(requestId); @@ -311,20 +314,20 @@ void MTProtoSession::cancel(mtpRequestId requestId, mtpMsgId msgId) { } } -void MTProtoSession::ping() { +void Session::ping() { _ping = true; sendAnything(0); } -int32 MTProtoSession::requestState(mtpRequestId requestId) const { +int32 Session::requestState(mtpRequestId requestId) const { int32 result = MTP::RequestSent; bool connected = false; if (_connection) { int32 s = _connection->state(); - if (s == MTProtoConnection::Connected) { + if (s == ConnectedState) { connected = true; - } else if (s == MTProtoConnection::Connecting || s == MTProtoConnection::Disconnected) { + } else if (s == ConnectingState || s == DisconnectedState) { if (result < 0 || result == MTP::RequestSent) { result = MTP::RequestConnecting; } @@ -349,14 +352,14 @@ int32 MTProtoSession::requestState(mtpRequestId requestId) const { } } -int32 MTProtoSession::getState() const { +int32 Session::getState() const { int32 result = -86400000; if (_connection) { int32 s = _connection->state(); - if (s == MTProtoConnection::Connected) { + if (s == ConnectedState) { return s; - } else if (s == MTProtoConnection::Connecting || s == MTProtoConnection::Disconnected) { + } else if (s == ConnectingState || s == DisconnectedState) { if (result < 0) { return s; } @@ -367,16 +370,16 @@ int32 MTProtoSession::getState() const { } } if (result == -86400000) { - result = MTProtoConnection::Disconnected; + result = DisconnectedState; } return result; } -QString MTProtoSession::transport() const { +QString Session::transport() const { return _connection ? _connection->transport() : QString(); } -mtpRequestId MTProtoSession::resend(quint64 msgId, quint64 msCanWait, bool forceContainer, bool sendMsgStateInfo) { +mtpRequestId Session::resend(quint64 msgId, quint64 msCanWait, bool forceContainer, bool sendMsgStateInfo) { mtpRequest request; { QWriteLocker locker(data.haveSentMutex()); @@ -416,13 +419,13 @@ mtpRequestId MTProtoSession::resend(quint64 msgId, quint64 msCanWait, bool force } } -void MTProtoSession::resendMany(QVector msgIds, quint64 msCanWait, bool forceContainer, bool sendMsgStateInfo) { +void Session::resendMany(QVector msgIds, quint64 msCanWait, bool forceContainer, bool sendMsgStateInfo) { for (int32 i = 0, l = msgIds.size(); i < l; ++i) { resend(msgIds.at(i), msCanWait, forceContainer, sendMsgStateInfo); } } -void MTProtoSession::resendAll() { +void Session::resendAll() { QVector toResend; { QReadLocker locker(data.haveSentMutex()); @@ -437,7 +440,7 @@ void MTProtoSession::resendAll() { } } -void MTProtoSession::sendPrepared(const mtpRequest &request, uint64 msCanWait, bool newRequest) { // returns true, if emit of needToSend() is needed +void Session::sendPrepared(const mtpRequest &request, uint64 msCanWait, bool newRequest) { // returns true, if emit of needToSend() is needed { QWriteLocker locker(data.toSendMutex()); data.toSendMap().insert(request->requestId, request); @@ -453,33 +456,33 @@ void MTProtoSession::sendPrepared(const mtpRequest &request, uint64 msCanWait, b sendAnything(msCanWait); } -QReadWriteLock *MTProtoSession::keyMutex() const { +QReadWriteLock *Session::keyMutex() const { return dc->keyMutex(); } -void MTProtoSession::authKeyCreatedForDC() { +void Session::authKeyCreatedForDC() { DEBUG_LOG(("AuthKey Info: MTProtoSession::authKeyCreatedForDC slot, emitting authKeyCreated(), dcWithShift %1").arg(dcWithShift)); data.setKey(dc->getKey()); emit authKeyCreated(); } -void MTProtoSession::notifyKeyCreated(const mtpAuthKeyPtr &key) { +void Session::notifyKeyCreated(const mtpAuthKeyPtr &key) { DEBUG_LOG(("AuthKey Info: MTProtoSession::keyCreated(), setting, dcWithShift %1").arg(dcWithShift)); dc->setKey(key); } -void MTProtoSession::layerWasInitedForDC(bool wasInited) { +void Session::layerWasInitedForDC(bool wasInited) { DEBUG_LOG(("MTP Info: MTProtoSession::layerWasInitedForDC slot, dcWithShift %1").arg(dcWithShift)); data.setLayerWasInited(wasInited); } -void MTProtoSession::notifyLayerInited(bool wasInited) { +void Session::notifyLayerInited(bool wasInited) { DEBUG_LOG(("MTP Info: emitting MTProtoDC::layerWasInited(%1), dcWithShift %2").arg(Logs::b(wasInited)).arg(dcWithShift)); dc->setConnectionInited(wasInited); emit dc->layerWasInited(wasInited); } -void MTProtoSession::destroyKey() { +void Session::destroyKey() { if (!dc) return; if (data.getKey()) { @@ -491,16 +494,16 @@ void MTProtoSession::destroyKey() { } } -int32 MTProtoSession::getDcWithShift() const { +int32 Session::getDcWithShift() const { return dcWithShift; } -void MTProtoSession::tryToReceive() { +void Session::tryToReceive() { if (_killed) { DEBUG_LOG(("Session Error: can't receive in a killed session")); return; } - if (_mtp_internal::paused()) { + if (paused()) { _needToReceive = true; return; } @@ -519,20 +522,23 @@ void MTProtoSession::tryToReceive() { responses.erase(i); } if (requestId <= 0) { - if (dcWithShift < int(_mtp_internal::dcShift)) { // call globalCallback only in main session - _mtp_internal::globalCallback(response.constData(), response.constData() + response.size()); + if (dcWithShift == bareDcId(dcWithShift)) { // call globalCallback only in main session + globalCallback(response.constData(), response.constData() + response.size()); } } else { - _mtp_internal::execCallback(requestId, response.constData(), response.constData() + response.size()); + execCallback(requestId, response.constData(), response.constData() + response.size()); } ++cnt; } } -MTProtoSession::~MTProtoSession() { +Session::~Session() { t_assert(_connection == 0); } MTPrpcError rpcClientError(const QString &type, const QString &description) { return MTP_rpc_error(MTP_int(0), MTP_string(("CLIENT_" + type + (description.length() ? (": " + description) : "")).toUtf8().constData())); } + +} // namespace internal +} // namespace MTP diff --git a/Telegram/SourceFiles/mtproto/session.h b/Telegram/SourceFiles/mtproto/session.h index e1fd43cbd..49285f606 100644 --- a/Telegram/SourceFiles/mtproto/session.h +++ b/Telegram/SourceFiles/mtproto/session.h @@ -24,15 +24,22 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "mtproto/dcenter.h" #include "mtproto/rpc_sender.h" -class MTProtoSession; +namespace MTP { +namespace internal { -class MTPSessionData { +class Session; + +class SessionData { public: - MTPSessionData(MTProtoSession *creator) - : _session(0), _salt(0) - , _messagesSent(0), _fakeRequestId(-2000000000) - , _owner(creator), _keyChecked(false), _layerInited(false) { + SessionData(Session *creator) + : _session(0) + , _salt(0) + , _messagesSent(0) + , _fakeRequestId(-2000000000) + , _owner(creator) + , _keyChecked(false) + , _layerInited(false) { } void setSession(uint64 session) { @@ -170,10 +177,10 @@ public: return _fakeRequestId; } - MTProtoSession *owner() { + Session *owner() { return _owner; } - const MTProtoSession *owner() const { + const Session *owner() const { return _owner; } @@ -192,7 +199,7 @@ private: uint32 _messagesSent; mtpRequestId _fakeRequestId; - MTProtoSession *_owner; + Session *_owner; mtpAuthKeyPtr _authKey; bool _keyChecked, _layerInited; @@ -217,12 +224,12 @@ private: }; -class MTProtoSession : public QObject { +class Session : public QObject { Q_OBJECT public: - MTProtoSession(int32 dcenter); + Session(int32 dcenter); void restart(); void stop(); @@ -231,7 +238,7 @@ public: void unpaused(); int32 getDcWithShift() const; - ~MTProtoSession(); + ~Session(); QReadWriteLock *keyMutex() const; void notifyKeyCreated(const mtpAuthKeyPtr &key); @@ -278,12 +285,12 @@ public slots: private: - MTProtoConnection *_connection; + Connection *_connection; bool _killed; bool _needToReceive; - MTPSessionData data; + SessionData data; int32 dcWithShift; MTProtoDCPtr dc; @@ -297,8 +304,11 @@ private: }; -inline QReadWriteLock *MTPSessionData::keyMutex() const { +inline QReadWriteLock *SessionData::keyMutex() const { return _owner->keyMutex(); } MTPrpcError rpcClientError(const QString &type, const QString &description = QString()); + +} // namespace internal +} // namespace MTP diff --git a/Telegram/SourceFiles/stdafx.h b/Telegram/SourceFiles/stdafx.h index 458defe4c..e88e760af 100644 --- a/Telegram/SourceFiles/stdafx.h +++ b/Telegram/SourceFiles/stdafx.h @@ -18,6 +18,9 @@ to link the code of portions of this program with the OpenSSL library. Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org */ + +#define NOMINMAX // no min() and max() macro declarations + #ifdef TDESKTOP_WINRT #include diff --git a/Telegram/SourceFiles/window.cpp b/Telegram/SourceFiles/window.cpp index ff088c269..8d7cbbad4 100644 --- a/Telegram/SourceFiles/window.cpp +++ b/Telegram/SourceFiles/window.cpp @@ -765,7 +765,7 @@ void Window::mtpStateChanged(int32 dc, int32 state) { void Window::updateTitleStatus() { int32 state = MTP::dcstate(); - if (state == MTProtoConnection::Connecting || state == MTProtoConnection::Disconnected || (state < 0 && state > -600)) { + if (state == MTP::ConnectingState || state == MTP::DisconnectedState || (state < 0 && state > -600)) { if (main || getms() > 5000 || _connecting) { showConnecting(lang(lng_connecting)); }