sender.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  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 "base/variant.h"
  9. #include "mtproto/mtproto_response.h"
  10. #include "mtproto/mtp_instance.h"
  11. #include "mtproto/facade.h"
  12. namespace MTP {
  13. class Sender {
  14. class RequestBuilder {
  15. public:
  16. RequestBuilder(const RequestBuilder &other) = delete;
  17. RequestBuilder &operator=(const RequestBuilder &other) = delete;
  18. RequestBuilder &operator=(RequestBuilder &&other) = delete;
  19. protected:
  20. enum class FailSkipPolicy {
  21. Simple,
  22. HandleFlood,
  23. HandleAll,
  24. };
  25. using FailPlainHandler = Fn<void()>;
  26. using FailErrorHandler = Fn<void(const Error&)>;
  27. using FailRequestIdHandler = Fn<void(const Error&, mtpRequestId)>;
  28. using FailFullHandler = Fn<void(const Error&, const Response&)>;
  29. template <typename ...Args>
  30. static constexpr bool IsCallable
  31. = rpl::details::is_callable_plain_v<Args...>;
  32. template <typename Result, typename Handler>
  33. [[nodiscard]] DoneHandler MakeDoneHandler(
  34. not_null<Sender*> sender,
  35. Handler &&handler) {
  36. return [sender, handler = std::forward<Handler>(handler)](
  37. const Response &response) mutable {
  38. auto onstack = std::move(handler);
  39. sender->senderRequestHandled(response.requestId);
  40. auto result = Result();
  41. auto from = response.reply.constData();
  42. if (!result.read(from, from + response.reply.size())) {
  43. return false;
  44. } else if (!onstack) {
  45. return true;
  46. } else if constexpr (IsCallable<
  47. Handler,
  48. const Result&,
  49. const Response&>) {
  50. onstack(result, response);
  51. } else if constexpr (IsCallable<
  52. Handler,
  53. const Result&,
  54. mtpRequestId>) {
  55. onstack(result, response.requestId);
  56. } else if constexpr (IsCallable<
  57. Handler,
  58. const Result&>) {
  59. onstack(result);
  60. } else if constexpr (IsCallable<Handler>) {
  61. onstack();
  62. } else {
  63. static_assert(false_t(Handler{}), "Bad done handler.");
  64. }
  65. return true;
  66. };
  67. }
  68. template <typename Handler>
  69. [[nodiscard]] FailHandler MakeFailHandler(
  70. not_null<Sender*> sender,
  71. Handler &&handler,
  72. FailSkipPolicy skipPolicy) {
  73. return [
  74. sender,
  75. handler = std::forward<Handler>(handler),
  76. skipPolicy
  77. ](const Error &error, const Response &response) {
  78. if (skipPolicy == FailSkipPolicy::Simple) {
  79. if (IsDefaultHandledError(error)) {
  80. return false;
  81. }
  82. } else if (skipPolicy == FailSkipPolicy::HandleFlood) {
  83. if (IsDefaultHandledError(error) && !IsFloodError(error)) {
  84. return false;
  85. }
  86. }
  87. auto onstack = handler;
  88. sender->senderRequestHandled(response.requestId);
  89. if (!onstack) {
  90. return true;
  91. } else if constexpr (IsCallable<
  92. Handler,
  93. const Error&,
  94. const Response&>) {
  95. onstack(error, response);
  96. } else if constexpr (IsCallable<
  97. Handler,
  98. const Error&,
  99. mtpRequestId>) {
  100. onstack(error, response.requestId);
  101. } else if constexpr (IsCallable<
  102. Handler,
  103. const Error&>) {
  104. onstack(error);
  105. } else if constexpr (IsCallable<Handler>) {
  106. onstack();
  107. } else {
  108. static_assert(false_t(Handler{}), "Bad fail handler.");
  109. }
  110. return true;
  111. };
  112. }
  113. explicit RequestBuilder(not_null<Sender*> sender) noexcept
  114. : _sender(sender) {
  115. }
  116. RequestBuilder(RequestBuilder &&other) = default;
  117. void setToDC(ShiftedDcId dcId) noexcept {
  118. _dcId = dcId;
  119. }
  120. void setOverrideRequestId(mtpRequestId id) noexcept {
  121. _overrideRequestId = id;
  122. }
  123. void setCanWait(crl::time ms) noexcept {
  124. _canWait = ms;
  125. }
  126. void setDoneHandler(DoneHandler &&handler) noexcept {
  127. _done = std::move(handler);
  128. }
  129. template <typename Handler>
  130. void setFailHandler(Handler &&handler) noexcept {
  131. _fail = std::forward<Handler>(handler);
  132. }
  133. void setFailSkipPolicy(FailSkipPolicy policy) noexcept {
  134. _failSkipPolicy = policy;
  135. }
  136. void setAfter(mtpRequestId requestId) noexcept {
  137. _afterRequestId = requestId;
  138. }
  139. [[nodiscard]] ShiftedDcId takeDcId() const noexcept {
  140. return _dcId;
  141. }
  142. [[nodiscard]] crl::time takeCanWait() const noexcept {
  143. return _canWait;
  144. }
  145. [[nodiscard]] DoneHandler takeOnDone() noexcept {
  146. return std::move(_done);
  147. }
  148. [[nodiscard]] FailHandler takeOnFail() {
  149. return v::match(_fail, [&](auto &value) {
  150. return MakeFailHandler(
  151. _sender,
  152. std::move(value),
  153. _failSkipPolicy);
  154. });
  155. }
  156. [[nodiscard]] mtpRequestId takeAfter() const noexcept {
  157. return _afterRequestId;
  158. }
  159. [[nodiscard]] mtpRequestId takeOverrideRequestId() const noexcept {
  160. return _overrideRequestId;
  161. }
  162. [[nodiscard]] not_null<Sender*> sender() const noexcept {
  163. return _sender;
  164. }
  165. void registerRequest(mtpRequestId requestId) {
  166. _sender->senderRequestRegister(requestId);
  167. }
  168. private:
  169. not_null<Sender*> _sender;
  170. ShiftedDcId _dcId = 0;
  171. crl::time _canWait = 0;
  172. DoneHandler _done;
  173. std::variant<
  174. FailPlainHandler,
  175. FailErrorHandler,
  176. FailRequestIdHandler,
  177. FailFullHandler> _fail;
  178. FailSkipPolicy _failSkipPolicy = FailSkipPolicy::Simple;
  179. mtpRequestId _afterRequestId = 0;
  180. mtpRequestId _overrideRequestId = 0;
  181. };
  182. public:
  183. explicit Sender(not_null<Instance*> instance) noexcept
  184. : _instance(instance) {
  185. }
  186. [[nodiscard]] Instance &instance() const {
  187. return *_instance;
  188. }
  189. template <typename Request>
  190. class SpecificRequestBuilder : public RequestBuilder {
  191. private:
  192. friend class Sender;
  193. SpecificRequestBuilder(not_null<Sender*> sender, Request &&request) noexcept
  194. : RequestBuilder(sender)
  195. , _request(std::move(request)) {
  196. }
  197. public:
  198. SpecificRequestBuilder(SpecificRequestBuilder &&other) = default;
  199. [[nodiscard]] SpecificRequestBuilder &toDC(ShiftedDcId dcId) noexcept {
  200. setToDC(dcId);
  201. return *this;
  202. }
  203. [[nodiscard]] SpecificRequestBuilder &afterDelay(crl::time ms) noexcept {
  204. setCanWait(ms);
  205. return *this;
  206. }
  207. [[nodiscard]] SpecificRequestBuilder &overrideId(mtpRequestId id) noexcept {
  208. setOverrideRequestId(id);
  209. return *this;
  210. }
  211. using Result = typename Request::ResponseType;
  212. [[nodiscard]] SpecificRequestBuilder &done(
  213. FnMut<void(
  214. const Result &result,
  215. mtpRequestId requestId)> callback) {
  216. setDoneHandler(
  217. MakeDoneHandler<Result>(sender(), std::move(callback)));
  218. return *this;
  219. }
  220. [[nodiscard]] SpecificRequestBuilder &done(
  221. FnMut<void(
  222. const Result &result,
  223. const Response &response)> callback) {
  224. setDoneHandler(
  225. MakeDoneHandler<Result>(sender(), std::move(callback)));
  226. return *this;
  227. }
  228. [[nodiscard]] SpecificRequestBuilder &done(
  229. FnMut<void()> callback) {
  230. setDoneHandler(
  231. MakeDoneHandler<Result>(sender(), std::move(callback)));
  232. return *this;
  233. }
  234. [[nodiscard]] SpecificRequestBuilder &done(
  235. FnMut<void(
  236. const typename Request::ResponseType &result)> callback) {
  237. setDoneHandler(
  238. MakeDoneHandler<Result>(sender(), std::move(callback)));
  239. return *this;
  240. }
  241. [[nodiscard]] SpecificRequestBuilder &fail(
  242. Fn<void(
  243. const Error &error,
  244. mtpRequestId requestId)> callback) noexcept {
  245. setFailHandler(std::move(callback));
  246. return *this;
  247. }
  248. [[nodiscard]] SpecificRequestBuilder &fail(
  249. Fn<void(
  250. const Error &error,
  251. const Response &response)> callback) noexcept {
  252. setFailHandler(std::move(callback));
  253. return *this;
  254. }
  255. [[nodiscard]] SpecificRequestBuilder &fail(
  256. Fn<void()> callback) noexcept {
  257. setFailHandler(std::move(callback));
  258. return *this;
  259. }
  260. [[nodiscard]] SpecificRequestBuilder &fail(
  261. Fn<void(const Error &error)> callback) noexcept {
  262. setFailHandler(std::move(callback));
  263. return *this;
  264. }
  265. [[nodiscard]] SpecificRequestBuilder &handleFloodErrors() noexcept {
  266. setFailSkipPolicy(FailSkipPolicy::HandleFlood);
  267. return *this;
  268. }
  269. [[nodiscard]] SpecificRequestBuilder &handleAllErrors() noexcept {
  270. setFailSkipPolicy(FailSkipPolicy::HandleAll);
  271. return *this;
  272. }
  273. [[nodiscard]] SpecificRequestBuilder &afterRequest(mtpRequestId requestId) noexcept {
  274. setAfter(requestId);
  275. return *this;
  276. }
  277. mtpRequestId send() {
  278. const auto id = sender()->_instance->send(
  279. _request,
  280. takeOnDone(),
  281. takeOnFail(),
  282. takeDcId(),
  283. takeCanWait(),
  284. takeAfter(),
  285. takeOverrideRequestId());
  286. registerRequest(id);
  287. return id;
  288. }
  289. private:
  290. Request _request;
  291. };
  292. class SentRequestWrap {
  293. private:
  294. friend class Sender;
  295. SentRequestWrap(not_null<Sender*> sender, mtpRequestId requestId) : _sender(sender), _requestId(requestId) {
  296. }
  297. public:
  298. void cancel() {
  299. if (_requestId) {
  300. _sender->senderRequestCancel(_requestId);
  301. }
  302. }
  303. private:
  304. not_null<Sender*> _sender;
  305. mtpRequestId _requestId = 0;
  306. };
  307. template <
  308. typename Request,
  309. typename = std::enable_if_t<!std::is_reference_v<Request>>,
  310. typename = typename Request::Unboxed>
  311. [[nodiscard]] SpecificRequestBuilder<Request> request(Request &&request) noexcept;
  312. [[nodiscard]] SentRequestWrap request(mtpRequestId requestId) noexcept;
  313. [[nodiscard]] auto requestCanceller() noexcept {
  314. return [this](mtpRequestId requestId) {
  315. request(requestId).cancel();
  316. };
  317. }
  318. void requestSendDelayed() {
  319. _instance->sendAnything();
  320. }
  321. void requestCancellingDiscard() {
  322. for (auto &request : base::take(_requests)) {
  323. request.handled();
  324. }
  325. }
  326. [[nodiscard]] mtpRequestId allocateRequestId() noexcept {
  327. return details::GetNextRequestId();
  328. }
  329. [[nodiscard]] bool pending(mtpRequestId requestId) noexcept {
  330. return _requests.contains(requestId);
  331. }
  332. private:
  333. class RequestWrap {
  334. public:
  335. RequestWrap(
  336. not_null<Instance*> instance,
  337. mtpRequestId requestId) noexcept
  338. : _instance(instance)
  339. , _id(requestId) {
  340. }
  341. RequestWrap(const RequestWrap &other) = delete;
  342. RequestWrap &operator=(const RequestWrap &other) = delete;
  343. RequestWrap(RequestWrap &&other)
  344. : _instance(other._instance)
  345. , _id(base::take(other._id)) {
  346. }
  347. RequestWrap &operator=(RequestWrap &&other) {
  348. Expects(_instance == other._instance);
  349. if (_id != other._id) {
  350. cancelRequest();
  351. _id = base::take(other._id);
  352. }
  353. return *this;
  354. }
  355. mtpRequestId id() const noexcept {
  356. return _id;
  357. }
  358. void handled() const noexcept {
  359. _id = 0;
  360. }
  361. ~RequestWrap() {
  362. cancelRequest();
  363. }
  364. private:
  365. void cancelRequest() {
  366. if (_id) {
  367. _instance->cancel(_id);
  368. }
  369. }
  370. const not_null<Instance*> _instance;
  371. mutable mtpRequestId _id = 0;
  372. };
  373. struct RequestWrapComparator {
  374. using is_transparent = std::true_type;
  375. struct helper {
  376. mtpRequestId requestId = 0;
  377. helper() = default;
  378. helper(const helper &other) = default;
  379. helper(mtpRequestId requestId) noexcept : requestId(requestId) {
  380. }
  381. helper(const RequestWrap &request) noexcept : requestId(request.id()) {
  382. }
  383. bool operator<(helper other) const {
  384. return requestId < other.requestId;
  385. }
  386. };
  387. bool operator()(const helper &&lhs, const helper &&rhs) const {
  388. return lhs < rhs;
  389. }
  390. };
  391. template <typename Request>
  392. friend class SpecificRequestBuilder;
  393. friend class RequestBuilder;
  394. friend class RequestWrap;
  395. friend class SentRequestWrap;
  396. void senderRequestRegister(mtpRequestId requestId) {
  397. _requests.emplace(_instance, requestId);
  398. }
  399. void senderRequestHandled(mtpRequestId requestId) {
  400. auto it = _requests.find(requestId);
  401. if (it != _requests.cend()) {
  402. it->handled();
  403. _requests.erase(it);
  404. }
  405. }
  406. void senderRequestCancel(mtpRequestId requestId) {
  407. auto it = _requests.find(requestId);
  408. if (it != _requests.cend()) {
  409. _requests.erase(it);
  410. }
  411. }
  412. const not_null<Instance*> _instance;
  413. base::flat_set<RequestWrap, RequestWrapComparator> _requests;
  414. };
  415. template <typename Request, typename, typename>
  416. Sender::SpecificRequestBuilder<Request> Sender::request(Request &&request) noexcept {
  417. return SpecificRequestBuilder<Request>(this, std::move(request));
  418. }
  419. inline Sender::SentRequestWrap Sender::request(mtpRequestId requestId) noexcept {
  420. return SentRequestWrap(this, requestId);
  421. }
  422. } // namespace MTP