1 // 2 // Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021 3 // 4 // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 // 7 #pragma once 8 9 #include "td/telegram/net/NetQuery.h" 10 11 #include "td/actor/actor.h" 12 13 #include "td/utils/common.h" 14 #include "td/utils/Random.h" 15 16 #include <limits> 17 #include <unordered_map> 18 19 namespace td { 20 21 class SequenceDispatcher final : public NetQueryCallback { 22 public: 23 class Parent : public Actor { 24 public: 25 virtual void ready_to_close() = 0; 26 virtual void on_result() = 0; 27 }; 28 SequenceDispatcher() = default; SequenceDispatcher(ActorShared<Parent> parent)29 explicit SequenceDispatcher(ActorShared<Parent> parent) : parent_(std::move(parent)) { 30 } 31 void send_with_callback(NetQueryPtr query, ActorShared<NetQueryCallback> callback); 32 void on_result(NetQueryPtr query) final; 33 void close_silent(); 34 35 private: 36 enum class State : int32 { Start, Wait, Finish, Dummy }; 37 struct Data { 38 State state_; 39 NetQueryRef net_query_ref_; 40 NetQueryPtr query_; 41 ActorShared<NetQueryCallback> callback_; 42 uint64 generation_; 43 double total_timeout_; 44 double last_timeout_; 45 }; 46 47 ActorShared<Parent> parent_; 48 size_t id_offset_ = 1; 49 std::vector<Data> data_; 50 size_t finish_i_ = 0; // skip state_ == State::Finish 51 size_t next_i_ = 0; 52 size_t last_sent_i_ = std::numeric_limits<size_t>::max(); 53 uint64 generation_ = 1; 54 uint32 session_rand_ = Random::secure_int32(); 55 56 static constexpr int32 MAX_SIMULTANEOUS_WAIT = 10; 57 uint32 wait_cnt_ = 0; 58 59 void check_timeout(Data &data); 60 61 void try_resend_query(Data &data, NetQueryPtr query); 62 Data &data_from_token(); 63 void on_resend_ok(NetQueryPtr query); 64 void on_resend_error(); 65 void do_resend(Data &data); 66 void do_finish(Data &data); 67 68 void loop() final; 69 void try_shrink(); 70 71 void timeout_expired() final; 72 void hangup() final; 73 void tear_down() final; 74 }; 75 76 class MultiSequenceDispatcher final : public SequenceDispatcher::Parent { 77 public: 78 void send_with_callback(NetQueryPtr query, ActorShared<NetQueryCallback> callback, uint64 sequence_id); 79 80 private: 81 struct Data { 82 int32 cnt_; 83 ActorOwn<SequenceDispatcher> dispatcher_; 84 }; 85 std::unordered_map<uint64, Data> dispatchers_; 86 void on_result() final; 87 void ready_to_close() final; 88 }; 89 90 } // namespace td 91