file_download_mtproto.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  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 "storage/file_download_mtproto.h"
  8. #include "data/data_document.h"
  9. #include "data/data_file_origin.h"
  10. #include "storage/cache/storage_cache_types.h"
  11. #include "main/main_session.h"
  12. #include "apiwrap.h"
  13. #include "mtproto/mtp_instance.h"
  14. #include "mtproto/mtproto_config.h"
  15. #include "mtproto/mtproto_auth_key.h"
  16. mtpFileLoader::mtpFileLoader(
  17. not_null<Main::Session*> session,
  18. const StorageFileLocation &location,
  19. Data::FileOrigin origin,
  20. LocationType type,
  21. const QString &to,
  22. int64 loadSize,
  23. int64 fullSize,
  24. LoadToCacheSetting toCache,
  25. LoadFromCloudSetting fromCloud,
  26. bool autoLoading,
  27. uint8 cacheTag)
  28. : FileLoader(
  29. session,
  30. to,
  31. loadSize,
  32. fullSize,
  33. type,
  34. toCache,
  35. fromCloud,
  36. autoLoading,
  37. cacheTag)
  38. , DownloadMtprotoTask(&session->downloader(), location, origin) {
  39. }
  40. mtpFileLoader::mtpFileLoader(
  41. not_null<Main::Session*> session,
  42. const WebFileLocation &location,
  43. int64 loadSize,
  44. int64 fullSize,
  45. LoadFromCloudSetting fromCloud,
  46. bool autoLoading,
  47. uint8 cacheTag)
  48. : FileLoader(
  49. session,
  50. QString(),
  51. loadSize,
  52. fullSize,
  53. UnknownFileLocation,
  54. LoadToCacheAsWell,
  55. fromCloud,
  56. autoLoading,
  57. cacheTag)
  58. , DownloadMtprotoTask(
  59. &session->downloader(),
  60. session->serverConfig().webFileDcId,
  61. { location }) {
  62. }
  63. mtpFileLoader::mtpFileLoader(
  64. not_null<Main::Session*> session,
  65. const GeoPointLocation &location,
  66. int64 loadSize,
  67. int64 fullSize,
  68. LoadFromCloudSetting fromCloud,
  69. bool autoLoading,
  70. uint8 cacheTag)
  71. : FileLoader(
  72. session,
  73. QString(),
  74. loadSize,
  75. fullSize,
  76. UnknownFileLocation,
  77. LoadToCacheAsWell,
  78. fromCloud,
  79. autoLoading,
  80. cacheTag)
  81. , DownloadMtprotoTask(
  82. &session->downloader(),
  83. session->serverConfig().webFileDcId,
  84. { location }) {
  85. }
  86. mtpFileLoader::mtpFileLoader(
  87. not_null<Main::Session*> session,
  88. const AudioAlbumThumbLocation &location,
  89. int64 loadSize,
  90. int64 fullSize,
  91. LoadFromCloudSetting fromCloud,
  92. bool autoLoading,
  93. uint8 cacheTag)
  94. : FileLoader(
  95. session,
  96. QString(),
  97. loadSize,
  98. fullSize,
  99. UnknownFileLocation,
  100. LoadToCacheAsWell,
  101. fromCloud,
  102. autoLoading,
  103. cacheTag)
  104. , DownloadMtprotoTask(
  105. &session->downloader(),
  106. session->serverConfig().webFileDcId,
  107. { location }) {
  108. }
  109. mtpFileLoader::~mtpFileLoader() {
  110. if (!_finished) {
  111. cancel();
  112. }
  113. }
  114. Data::FileOrigin mtpFileLoader::fileOrigin() const {
  115. return DownloadMtprotoTask::fileOrigin();
  116. }
  117. uint64 mtpFileLoader::objId() const {
  118. return DownloadMtprotoTask::objectId();
  119. }
  120. bool mtpFileLoader::readyToRequest() const {
  121. return !_finished
  122. && !_lastComplete
  123. && (_fullSize != 0 || !haveSentRequests())
  124. && (!_fullSize || _nextRequestOffset < _loadSize);
  125. }
  126. int64 mtpFileLoader::takeNextRequestOffset() {
  127. Expects(readyToRequest());
  128. const auto result = _nextRequestOffset;
  129. _nextRequestOffset += Storage::kDownloadPartSize;
  130. return result;
  131. }
  132. bool mtpFileLoader::feedPart(int64 offset, const QByteArray &bytes) {
  133. const auto buffer = bytes::make_span(bytes);
  134. if (!writeResultPart(offset, buffer)) {
  135. return false;
  136. }
  137. if (buffer.empty() || (buffer.size() % 1024)) { // bad next offset
  138. _lastComplete = true;
  139. }
  140. const auto finished = !haveSentRequests()
  141. && (_lastComplete || (_fullSize && _nextRequestOffset >= _loadSize));
  142. if (finished) {
  143. removeFromQueue();
  144. if (!finalizeResult()) {
  145. return false;
  146. }
  147. } else {
  148. notifyAboutProgress();
  149. }
  150. return true;
  151. }
  152. void mtpFileLoader::cancelOnFail() {
  153. cancel(FailureReason::OtherFailure);
  154. }
  155. bool mtpFileLoader::setWebFileSizeHook(int64 size) {
  156. if (!_fullSize || _fullSize == size) {
  157. _fullSize = _loadSize = size;
  158. return true;
  159. }
  160. LOG(("MTP Error: "
  161. "Bad size provided by bot for webDocument: %1, real: %2"
  162. ).arg(_fullSize
  163. ).arg(size));
  164. cancel(FailureReason::OtherFailure);
  165. return false;
  166. }
  167. void mtpFileLoader::startLoading() {
  168. addToQueue();
  169. }
  170. void mtpFileLoader::startLoadingWithPartial(const QByteArray &data) {
  171. Expects(data.startsWith("partial:"));
  172. constexpr auto kPrefix = 8;
  173. const auto parts = (data.size() - kPrefix) / Storage::kDownloadPartSize;
  174. const auto use = parts * int64(Storage::kDownloadPartSize);
  175. if (use > 0) {
  176. _nextRequestOffset = use;
  177. feedPart(0, QByteArray::fromRawData(data.data() + kPrefix, use));
  178. }
  179. startLoading();
  180. }
  181. void mtpFileLoader::cancelHook() {
  182. cancelAllRequests();
  183. }
  184. Storage::Cache::Key mtpFileLoader::cacheKey() const {
  185. return v::match(location().data, [&](const WebFileLocation &location) {
  186. return Data::WebDocumentCacheKey(location);
  187. }, [&](const GeoPointLocation &location) {
  188. return Data::GeoPointCacheKey(location);
  189. }, [&](const StorageFileLocation &location) {
  190. return location.cacheKey();
  191. }, [&](const AudioAlbumThumbLocation &location) {
  192. return Data::AudioAlbumThumbCacheKey(location);
  193. });
  194. }
  195. std::optional<MediaKey> mtpFileLoader::fileLocationKey() const {
  196. if (_locationType != UnknownFileLocation) {
  197. return mediaKey(_locationType, dcId(), objId());
  198. }
  199. return std::nullopt;
  200. }