mtproto_serialized_request.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  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. #include "mtproto/details/mtproto_serialized_request.h"
  8. #include "base/random.h"
  9. namespace MTP::details {
  10. namespace {
  11. uint32 CountPaddingPrimesCount(
  12. uint32 requestSize,
  13. bool forAuthKeyInner) {
  14. if (forAuthKeyInner) {
  15. return ((8 + requestSize) & 0x03)
  16. ? (4 - ((8 + requestSize) & 0x03))
  17. : 0;
  18. }
  19. auto result = ((8 + requestSize) & 0x03)
  20. ? (4 - ((8 + requestSize) & 0x03))
  21. : 0;
  22. // At least 12 bytes of random padding.
  23. if (result < 3) {
  24. result += 4;
  25. }
  26. // Some more random padding.
  27. return result + ((base::RandomValue<uchar>() & 0x0F) << 2);
  28. }
  29. } // namespace
  30. SerializedRequest::SerializedRequest(const RequestConstructHider::Tag &tag)
  31. : _data(std::make_shared<RequestData>(tag)) {
  32. }
  33. SerializedRequest SerializedRequest::Prepare(
  34. uint32 size,
  35. uint32 reserveSize) {
  36. Expects(size > 0);
  37. const auto finalSize = std::max(size, reserveSize);
  38. auto result = SerializedRequest(RequestConstructHider::Tag{});
  39. result->reserve(kMessageBodyPosition + finalSize);
  40. result->resize(kMessageBodyPosition);
  41. result->back() = (size << 2);
  42. result->lastSentTime = crl::now();
  43. return result;
  44. }
  45. RequestData *SerializedRequest::operator->() const {
  46. Expects(_data != nullptr);
  47. return _data.get();
  48. }
  49. RequestData &SerializedRequest::operator*() const {
  50. Expects(_data != nullptr);
  51. return *_data;
  52. }
  53. SerializedRequest::operator bool() const {
  54. return (_data != nullptr);
  55. }
  56. void SerializedRequest::setMsgId(mtpMsgId msgId) {
  57. Expects(_data != nullptr);
  58. Expects(_data->size() > kMessageBodyPosition);
  59. memcpy(_data->data() + kMessageIdPosition, &msgId, sizeof(mtpMsgId));
  60. }
  61. mtpMsgId SerializedRequest::getMsgId() const {
  62. Expects(_data != nullptr);
  63. Expects(_data->size() > kMessageBodyPosition);
  64. return *(mtpMsgId*)(_data->constData() + kMessageIdPosition);
  65. }
  66. void SerializedRequest::setSeqNo(uint32 seqNo) {
  67. Expects(_data != nullptr);
  68. Expects(_data->size() > kMessageBodyPosition);
  69. (*_data)[kSeqNoPosition] = mtpPrime(seqNo);
  70. }
  71. uint32 SerializedRequest::getSeqNo() const {
  72. Expects(_data != nullptr);
  73. Expects(_data->size() > kMessageBodyPosition);
  74. return uint32((*_data)[kSeqNoPosition]);
  75. }
  76. void SerializedRequest::addPadding(bool forAuthKeyInner) {
  77. Expects(_data != nullptr);
  78. Expects(_data->size() > kMessageBodyPosition);
  79. const auto requestSize = (tl::count_length(*this) >> 2);
  80. const auto padding = CountPaddingPrimesCount(
  81. requestSize,
  82. forAuthKeyInner);
  83. const auto fullSize = kMessageBodyPosition + requestSize + padding;
  84. if (uint32(_data->size()) != fullSize) {
  85. _data->resize(fullSize);
  86. if (padding > 0) {
  87. bytes::set_random(bytes::make_span(*_data).subspan(
  88. (fullSize - padding) * sizeof(mtpPrime)));
  89. }
  90. }
  91. }
  92. uint32 SerializedRequest::messageSize() const {
  93. Expects(_data != nullptr);
  94. Expects(_data->size() > kMessageBodyPosition);
  95. const auto ints = (tl::count_length(*this) >> 2);
  96. return kMessageIdInts + kSeqNoInts + kMessageLengthInts + ints;
  97. }
  98. bool SerializedRequest::needAck() const {
  99. Expects(_data != nullptr);
  100. Expects(_data->size() > kMessageBodyPosition);
  101. const auto type = mtpTypeId((*_data)[kMessageBodyPosition]);
  102. switch (type) {
  103. case mtpc_msg_container:
  104. case mtpc_msgs_ack:
  105. case mtpc_http_wait:
  106. case mtpc_bad_msg_notification:
  107. case mtpc_msgs_all_info:
  108. case mtpc_msgs_state_info:
  109. case mtpc_msg_detailed_info:
  110. case mtpc_msg_new_detailed_info:
  111. return false;
  112. }
  113. return true;
  114. }
  115. size_t SerializedRequest::sizeInBytes() const {
  116. Expects(!_data || _data->size() > kMessageBodyPosition);
  117. return _data ? (*_data)[kMessageLengthPosition] : 0;
  118. }
  119. const void *SerializedRequest::dataInBytes() const {
  120. Expects(!_data || _data->size() > kMessageBodyPosition);
  121. return _data ? (_data->constData() + kMessageBodyPosition) : nullptr;
  122. }
  123. } // namespace MTP