| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- /*
- This file is part of Telegram Desktop,
- the official desktop application for the Telegram messaging service.
- For license and copyright information please follow this link:
- https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
- */
- #include "mtproto/connection_abstract.h"
- #include "mtproto/connection_tcp.h"
- #include "mtproto/connection_http.h"
- #include "mtproto/connection_resolving.h"
- #include "mtproto/session.h"
- #include "base/unixtime.h"
- #include "base/random.h"
- namespace MTP {
- namespace details {
- namespace {
- std::atomic<int> GlobalConnectionCounter/* = 0*/;
- } // namespace
- ConnectionPointer::ConnectionPointer() = default;
- ConnectionPointer::ConnectionPointer(std::nullptr_t) {
- }
- ConnectionPointer::ConnectionPointer(AbstractConnection *value)
- : _value(value) {
- }
- ConnectionPointer::ConnectionPointer(ConnectionPointer &&other)
- : _value(base::take(other._value)) {
- }
- ConnectionPointer &ConnectionPointer::operator=(ConnectionPointer &&other) {
- reset(base::take(other._value));
- return *this;
- }
- AbstractConnection *ConnectionPointer::get() const {
- return _value;
- }
- void ConnectionPointer::reset(AbstractConnection *value) {
- if (_value == value) {
- return;
- } else if (const auto old = base::take(_value)) {
- const auto disconnect = [&](auto signal) {
- old->disconnect(old, signal, nullptr, nullptr);
- };
- disconnect(&AbstractConnection::receivedData);
- disconnect(&AbstractConnection::receivedSome);
- disconnect(&AbstractConnection::error);
- disconnect(&AbstractConnection::connected);
- disconnect(&AbstractConnection::disconnected);
- old->disconnectFromServer();
- old->deleteLater();
- }
- _value = value;
- }
- ConnectionPointer::operator AbstractConnection*() const {
- return get();
- }
- AbstractConnection *ConnectionPointer::operator->() const {
- return get();
- }
- AbstractConnection &ConnectionPointer::operator*() const {
- return *get();
- }
- ConnectionPointer::operator bool() const {
- return get() != nullptr;
- }
- ConnectionPointer::~ConnectionPointer() {
- reset();
- }
- mtpBuffer AbstractConnection::prepareSecurePacket(
- uint64 keyId,
- MTPint128 msgKey,
- uint32 size) const {
- auto result = mtpBuffer();
- constexpr auto kTcpPrefixInts = 2;
- constexpr auto kAuthKeyIdPosition = kTcpPrefixInts;
- constexpr auto kAuthKeyIdInts = 2;
- constexpr auto kMessageKeyPosition = kAuthKeyIdPosition
- + kAuthKeyIdInts;
- constexpr auto kMessageKeyInts = 4;
- constexpr auto kPrefixInts = kTcpPrefixInts
- + kAuthKeyIdInts
- + kMessageKeyInts;
- constexpr auto kTcpPostfixInts = 4;
- result.reserve(kPrefixInts + size + kTcpPostfixInts);
- result.resize(kPrefixInts);
- *reinterpret_cast<uint64*>(&result[kAuthKeyIdPosition]) = keyId;
- *reinterpret_cast<MTPint128*>(&result[kMessageKeyPosition]) = msgKey;
- return result;
- }
- gsl::span<const mtpPrime> AbstractConnection::parseNotSecureResponse(
- const mtpBuffer &buffer) const {
- const auto answer = buffer.data();
- const auto len = buffer.size();
- if (len < 6) {
- LOG(("Not Secure Error: bad request answer, len = %1"
- ).arg(len * sizeof(mtpPrime)));
- DEBUG_LOG(("Not Secure Error: answer bytes %1"
- ).arg(Logs::mb(answer, len * sizeof(mtpPrime)).str()));
- return {};
- }
- if (answer[0] != 0
- || answer[1] != 0
- || (((uint32)answer[2]) & 0x03) != 1
- //|| (base::unixtime::now() - answer[3] > 300) // We didn't sync time yet.
- //|| (answer[3] - base::unixtime::now() > 60)
- || false) {
- LOG(("Not Secure Error: bad request answer start (%1 %2 %3)"
- ).arg(answer[0]
- ).arg(answer[1]
- ).arg(answer[2]));
- DEBUG_LOG(("Not Secure Error: answer bytes %1"
- ).arg(Logs::mb(answer, len * sizeof(mtpPrime)).str()));
- return {};
- }
- const auto answerLen = (uint32)answer[4];
- if (answerLen < 1 || answerLen > (len - 5) * sizeof(mtpPrime)) {
- LOG(("Not Secure Error: bad request answer 1 <= %1 <= %2"
- ).arg(answerLen
- ).arg((len - 5) * sizeof(mtpPrime)));
- DEBUG_LOG(("Not Secure Error: answer bytes %1"
- ).arg(Logs::mb(answer, len * sizeof(mtpPrime)).str()));
- return {};
- }
- return gsl::make_span(answer + 5, answerLen);
- }
- mtpBuffer AbstractConnection::preparePQFake(const MTPint128 &nonce) const {
- return prepareNotSecurePacket(
- MTPReq_pq(nonce),
- base::unixtime::mtproto_msg_id());
- }
- std::optional<MTPResPQ> AbstractConnection::readPQFakeReply(
- const mtpBuffer &buffer) const {
- const auto answer = parseNotSecureResponse(buffer);
- if (answer.empty()) {
- return std::nullopt;
- }
- auto from = answer.data();
- MTPResPQ response;
- return response.read(from, from + answer.size())
- ? std::make_optional(response)
- : std::nullopt;
- }
- AbstractConnection::AbstractConnection(
- QThread *thread,
- const ProxyData &proxy)
- : _proxy(proxy)
- , _debugId(QString::number(++GlobalConnectionCounter)) {
- moveToThread(thread);
- }
- ConnectionPointer AbstractConnection::Create(
- not_null<Instance*> instance,
- DcOptions::Variants::Protocol protocol,
- QThread *thread,
- const bytes::vector &secret,
- const ProxyData &proxy) {
- auto result = [&] {
- if (protocol == DcOptions::Variants::Tcp) {
- return ConnectionPointer::New<TcpConnection>(
- instance,
- thread,
- proxy);
- } else {
- return ConnectionPointer::New<HttpConnection>(thread, proxy);
- }
- }();
- if (proxy.tryCustomResolve()) {
- return ConnectionPointer::New<ResolvingConnection>(
- instance,
- thread,
- proxy,
- std::move(result));
- }
- return result;
- }
- QString AbstractConnection::ProtocolDcDebugId(int16 protocolDcId) {
- const auto postfix = (protocolDcId < 0) ? "_media" : "";
- protocolDcId = (protocolDcId < 0) ? (-protocolDcId) : protocolDcId;
- const auto prefix = (protocolDcId > kTestModeDcIdShift) ? "test_" : "";
- protocolDcId = (protocolDcId > kTestModeDcIdShift)
- ? (protocolDcId - kTestModeDcIdShift)
- : protocolDcId;
- return prefix + QString::number(protocolDcId) + postfix;
- }
- void AbstractConnection::logInfo(const QString &message) {
- DEBUG_LOG(("Connection %1 Info: ").arg(_debugId) + message);
- }
- void AbstractConnection::logError(const QString &message) {
- DEBUG_LOG(("Connection %1 Error: ").arg(_debugId) + message);
- }
- uint32 AbstractConnection::extendedNotSecurePadding() const {
- return uint32(base::RandomValue<uchar>() & 0x3F);
- }
- } // namespace details
- } // namespace MTP
|