connection_abstract.h 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #pragma once
  8. #include "mtproto/mtproto_dc_options.h"
  9. #include "mtproto/mtproto_proxy_data.h"
  10. #include "base/bytes.h"
  11. #include <QtCore/QObject>
  12. #include <QtCore/QThread>
  13. #include <deque>
  14. namespace MTP {
  15. class Instance;
  16. namespace details {
  17. struct ConnectionOptions;
  18. class AbstractConnection;
  19. inline constexpr auto kTestModeDcIdShift = 10000;
  20. class ConnectionPointer {
  21. public:
  22. ConnectionPointer();
  23. ConnectionPointer(std::nullptr_t);
  24. ConnectionPointer(ConnectionPointer &&other);
  25. ConnectionPointer &operator=(ConnectionPointer &&other);
  26. template <typename ConnectionType, typename ...Args>
  27. static ConnectionPointer New(Args &&...args) {
  28. return ConnectionPointer(new ConnectionType(
  29. std::forward<Args>(args)...
  30. ));
  31. }
  32. AbstractConnection *get() const;
  33. void reset(AbstractConnection *value = nullptr);
  34. operator AbstractConnection*() const;
  35. AbstractConnection *operator->() const;
  36. AbstractConnection &operator*() const;
  37. explicit operator bool() const;
  38. ~ConnectionPointer();
  39. private:
  40. explicit ConnectionPointer(AbstractConnection *value);
  41. AbstractConnection *_value = nullptr;
  42. };
  43. class AbstractConnection : public QObject {
  44. Q_OBJECT
  45. public:
  46. AbstractConnection(QThread *thread, const ProxyData &proxy);
  47. AbstractConnection(const AbstractConnection &other) = delete;
  48. AbstractConnection &operator=(const AbstractConnection &other) = delete;
  49. virtual ~AbstractConnection() = default;
  50. // virtual constructor
  51. [[nodiscard]] static ConnectionPointer Create(
  52. not_null<Instance*> instance,
  53. DcOptions::Variants::Protocol protocol,
  54. QThread *thread,
  55. const bytes::vector &secret,
  56. const ProxyData &proxy);
  57. [[nodiscard]] virtual ConnectionPointer clone(const ProxyData &proxy) = 0;
  58. [[nodiscard]] virtual crl::time pingTime() const = 0;
  59. [[nodiscard]] virtual crl::time fullConnectTimeout() const = 0;
  60. virtual void sendData(mtpBuffer &&buffer) = 0;
  61. virtual void disconnectFromServer() = 0;
  62. virtual void connectToServer(
  63. const QString &ip,
  64. int port,
  65. const bytes::vector &protocolSecret,
  66. int16 protocolDcId,
  67. bool protocolForFiles) = 0;
  68. virtual void timedOut() {
  69. }
  70. [[nodiscard]] virtual bool isConnected() const = 0;
  71. [[nodiscard]] virtual bool usingHttpWait() {
  72. return false;
  73. }
  74. [[nodiscard]] virtual bool needHttpWait() {
  75. return false;
  76. }
  77. [[nodiscard]] virtual int32 debugState() const = 0;
  78. [[nodiscard]] virtual QString transport() const = 0;
  79. [[nodiscard]] virtual QString tag() const = 0;
  80. void setSentEncryptedWithKeyId(uint64 keyId) {
  81. _sentEncryptedWithKeyId = keyId;
  82. }
  83. [[nodiscard]] uint64 sentEncryptedWithKeyId() const {
  84. return _sentEncryptedWithKeyId;
  85. }
  86. using BuffersQueue = std::deque<mtpBuffer>;
  87. [[nodiscard]] BuffersQueue &received() {
  88. return _receivedQueue;
  89. }
  90. template <typename Request>
  91. [[nodiscard]] mtpBuffer prepareNotSecurePacket(
  92. const Request &request,
  93. mtpMsgId newId) const;
  94. [[nodiscard]] mtpBuffer prepareSecurePacket(
  95. uint64 keyId,
  96. MTPint128 msgKey,
  97. uint32 size) const;
  98. [[nodiscard]] gsl::span<const mtpPrime> parseNotSecureResponse(
  99. const mtpBuffer &buffer) const;
  100. [[nodiscard]] static QString ProtocolDcDebugId(int16 protocolDcId);
  101. [[nodiscard]] QString debugId() const {
  102. return _debugId;
  103. }
  104. void logInfo(const QString &message);
  105. void logError(const QString &message);
  106. // Used to emit error(...) with no real code from the server.
  107. static constexpr auto kErrorCodeOther = -499;
  108. Q_SIGNALS:
  109. void receivedData();
  110. void receivedSome(); // to stop restart timer
  111. void error(qint32 errorCodebool);
  112. void connected();
  113. void disconnected();
  114. void syncTimeRequest();
  115. protected:
  116. BuffersQueue _receivedQueue; // list of received packets, not processed yet
  117. int _pingTime = 0;
  118. ProxyData _proxy;
  119. QString _debugId;
  120. // first we always send fake MTPReq_pq to see if connection works at all
  121. // we send them simultaneously through TCP/HTTP/IPv4/IPv6 to choose the working one
  122. [[nodiscard]] mtpBuffer preparePQFake(const MTPint128 &nonce) const;
  123. [[nodiscard]] std::optional<MTPResPQ> readPQFakeReply(
  124. const mtpBuffer &buffer) const;
  125. private:
  126. [[nodiscard]] uint32 extendedNotSecurePadding() const;
  127. uint64 _sentEncryptedWithKeyId = 0;
  128. };
  129. template <typename Request>
  130. mtpBuffer AbstractConnection::prepareNotSecurePacket(
  131. const Request &request,
  132. mtpMsgId newId) const {
  133. const auto intsSize = tl::count_length(request) >> 2;
  134. const auto intsPadding = extendedNotSecurePadding();
  135. auto result = mtpBuffer();
  136. constexpr auto kTcpPrefixInts = 2;
  137. constexpr auto kAuthKeyIdInts = 2;
  138. constexpr auto kMessageIdInts = 2;
  139. constexpr auto kMessageLengthInts = 1;
  140. constexpr auto kPrefixInts = kTcpPrefixInts
  141. + kAuthKeyIdInts
  142. + kMessageIdInts
  143. + kMessageLengthInts;
  144. constexpr auto kTcpPostfixInts = 4;
  145. result.reserve(kPrefixInts + intsSize + intsPadding + kTcpPostfixInts);
  146. result.resize(kPrefixInts);
  147. const auto messageId = &result[kTcpPrefixInts + kAuthKeyIdInts];
  148. *reinterpret_cast<mtpMsgId*>(messageId) = newId;
  149. request.write(result);
  150. const auto messageLength = messageId + kMessageIdInts;
  151. *messageLength = (result.size() - kPrefixInts + intsPadding) << 2;
  152. if (intsPadding > 0) {
  153. const auto skipPrimes = result.size();
  154. result.resize(skipPrimes + intsPadding);
  155. const auto skipBytes = skipPrimes * sizeof(mtpPrime);
  156. bytes::set_random(bytes::make_span(result).subspan(skipBytes));
  157. }
  158. return result;
  159. }
  160. #define CONNECTION_LOG_INFO(x) if (Logs::DebugEnabled()) { logInfo(x); }
  161. #define CONNECTION_LOG_ERROR(x) if (Logs::DebugEnabled()) { logError(x); }
  162. } // namespace details
  163. } // namespace MTP