mtproto_dcenter.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  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_dcenter.h"
  8. #include "mtproto/facade.h"
  9. #include "mtproto/mtproto_auth_key.h"
  10. #include "mtproto/mtproto_dc_options.h"
  11. #include "mtproto/mtp_instance.h"
  12. #include "mtproto/special_config_request.h"
  13. namespace MTP {
  14. namespace details {
  15. namespace {
  16. int IndexByType(TemporaryKeyType type) {
  17. switch (type) {
  18. case TemporaryKeyType::Regular: return 0;
  19. case TemporaryKeyType::MediaCluster: return 1;
  20. }
  21. Unexpected("Type value in IndexByType.");
  22. }
  23. int IndexByType(CreatingKeyType type) {
  24. switch (type) {
  25. case CreatingKeyType::Persistent:
  26. case CreatingKeyType::TemporaryRegular: return 0;
  27. case CreatingKeyType::TemporaryMediaCluster: return 1;
  28. }
  29. Unexpected("Creating type value in IndexByType.");
  30. }
  31. const char *NameOfType(CreatingKeyType type) {
  32. switch (type) {
  33. case CreatingKeyType::Persistent: return "persistent";
  34. case CreatingKeyType::TemporaryRegular: return "regular";
  35. case CreatingKeyType::TemporaryMediaCluster: return "media";
  36. }
  37. Unexpected("Type value in NameOfType.");
  38. }
  39. } // namespace
  40. TemporaryKeyType TemporaryKeyTypeByDcType(DcType type) {
  41. return (type == DcType::MediaCluster)
  42. ? TemporaryKeyType::MediaCluster
  43. : TemporaryKeyType::Regular;
  44. }
  45. Dcenter::Dcenter(DcId dcId, AuthKeyPtr &&key)
  46. : _id(dcId)
  47. , _persistentKey(std::move(key)) {
  48. }
  49. DcId Dcenter::id() const {
  50. return _id;
  51. }
  52. AuthKeyPtr Dcenter::getTemporaryKey(TemporaryKeyType type) const {
  53. QReadLocker lock(&_mutex);
  54. return _temporaryKeys[IndexByType(type)];
  55. }
  56. AuthKeyPtr Dcenter::getPersistentKey() const {
  57. QReadLocker lock(&_mutex);
  58. return _persistentKey;
  59. }
  60. bool Dcenter::destroyTemporaryKey(uint64 keyId) {
  61. QWriteLocker lock(&_mutex);
  62. for (auto &key : _temporaryKeys) {
  63. if (key && key->keyId() == keyId) {
  64. key = nullptr;
  65. _connectionInited = false;
  66. return true;
  67. }
  68. }
  69. return false;
  70. }
  71. bool Dcenter::destroyConfirmedForgottenKey(uint64 keyId) {
  72. QWriteLocker lock(&_mutex);
  73. if (!_persistentKey || _persistentKey->keyId() != keyId) {
  74. return false;
  75. }
  76. for (auto &key : _temporaryKeys) {
  77. key = nullptr;
  78. }
  79. _persistentKey = nullptr;
  80. _connectionInited = false;
  81. return true;
  82. }
  83. bool Dcenter::connectionInited() const {
  84. QReadLocker lock(&_mutex);
  85. return _connectionInited;
  86. }
  87. void Dcenter::setConnectionInited(bool connectionInited) {
  88. QWriteLocker lock(&_mutex);
  89. _connectionInited = connectionInited;
  90. }
  91. CreatingKeyType Dcenter::acquireKeyCreation(DcType type) {
  92. QReadLocker lock(&_mutex);
  93. const auto keyType = TemporaryKeyTypeByDcType(type);
  94. const auto index = IndexByType(keyType);
  95. auto &key = _temporaryKeys[index];
  96. if (key != nullptr) {
  97. return CreatingKeyType::None;
  98. }
  99. auto expected = false;
  100. const auto regular = IndexByType(TemporaryKeyType::Regular);
  101. if (keyType == TemporaryKeyType::MediaCluster && _temporaryKeys[regular]) {
  102. return !_creatingKeys[index].compare_exchange_strong(expected, true)
  103. ? CreatingKeyType::None
  104. : CreatingKeyType::TemporaryMediaCluster;
  105. }
  106. return !_creatingKeys[regular].compare_exchange_strong(expected, true)
  107. ? CreatingKeyType::None
  108. : (type != DcType::Cdn && !_persistentKey)
  109. ? CreatingKeyType::Persistent
  110. : CreatingKeyType::TemporaryRegular;
  111. }
  112. bool Dcenter::releaseKeyCreationOnDone(
  113. CreatingKeyType type,
  114. const AuthKeyPtr &temporaryKey,
  115. const AuthKeyPtr &persistentKeyUsedForBind) {
  116. Expects(_creatingKeys[IndexByType(type)]);
  117. Expects(_temporaryKeys[IndexByType(type)] == nullptr);
  118. Expects(temporaryKey != nullptr);
  119. QWriteLocker lock(&_mutex);
  120. if (type == CreatingKeyType::Persistent) {
  121. _persistentKey = persistentKeyUsedForBind;
  122. } else if (_persistentKey != persistentKeyUsedForBind) {
  123. return false;
  124. }
  125. _temporaryKeys[IndexByType(type)] = temporaryKey;
  126. _creatingKeys[IndexByType(type)] = false;
  127. _connectionInited = false;
  128. DEBUG_LOG(("AuthKey Info: Dcenter::releaseKeyCreationOnDone(%1, %2, %3)."
  129. ).arg(NameOfType(type)
  130. ).arg(temporaryKey ? temporaryKey->keyId() : 0
  131. ).arg(persistentKeyUsedForBind
  132. ? persistentKeyUsedForBind->keyId()
  133. : 0));
  134. return true;
  135. }
  136. void Dcenter::releaseKeyCreationOnFail(CreatingKeyType type) {
  137. Expects(_creatingKeys[IndexByType(type)]);
  138. Expects(_temporaryKeys[IndexByType(type)] == nullptr);
  139. _creatingKeys[IndexByType(type)] = false;
  140. }
  141. } // namespace details
  142. } // namespace MTP