// // Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021 // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #pragma once #include "td/telegram/ChannelId.h" #include "td/telegram/ChatId.h" #include "td/telegram/DialogId.h" #include "td/telegram/InputGroupCallId.h" #include "td/telegram/PtsManager.h" #include "td/telegram/telegram_api.h" #include "td/telegram/UserId.h" #include "td/actor/actor.h" #include "td/actor/PromiseFuture.h" #include "td/actor/Timeout.h" #include "td/utils/common.h" #include "td/utils/logging.h" #include #include namespace td { extern int VERBOSITY_NAME(get_difference); class Td; class UpdatesManager : public Actor { public: UpdatesManager(Td *td, ActorShared<> parent); void on_get_updates(tl_object_ptr &&updates_ptr, Promise &&promise); void on_get_updates_state(tl_object_ptr &&state, const char *source); void on_get_difference(tl_object_ptr &&difference_ptr); static std::unordered_set get_sent_messages_random_ids(const telegram_api::Updates *updates_ptr); static vector *> get_new_messages( const telegram_api::Updates *updates_ptr); static vector get_update_new_group_call_ids(const telegram_api::Updates *updates_ptr); static vector get_update_notify_settings_dialog_ids(const telegram_api::Updates *updates_ptr); static vector get_chat_dialog_ids(const telegram_api::Updates *updates_ptr); static int32 get_update_edit_message_pts(const telegram_api::Updates *updates_ptr); void get_difference(const char *source); void schedule_get_difference(const char *source); void init_state(); void ping_server(); void on_server_pong(tl_object_ptr &&state); int32 get_pts() const { return pts_manager_.mem_pts(); } int32 get_qts() const { return qts_manager_.mem_pts(); } int32 get_date() const { return date_; } Promise<> set_pts(int32 pts, const char *source) TD_WARN_UNUSED_RESULT; static const double MAX_UNFILLED_GAP_TIME; static void fill_pts_gap(void *td); bool running_get_difference() const { return running_get_difference_; } private: static constexpr int32 FORCED_GET_DIFFERENCE_PTS_DIFF = 100000; friend class OnUpdate; class PendingUpdates { public: int32 seq_begin; int32 seq_end; int32 date; vector> updates; Promise promise; PendingUpdates(int32 seq_begin, int32 seq_end, int32 date, vector> &&updates, Promise &&promise) : seq_begin(seq_begin), seq_end(seq_end), date(date), updates(std::move(updates)), promise(std::move(promise)) { } }; class PendingQtsUpdate { public: tl_object_ptr update; vector> promises; }; Td *td_; ActorShared<> parent_; PtsManager pts_manager_; PtsManager qts_manager_; int32 date_ = 0; int32 seq_ = 0; string date_source_ = "nowhere"; int32 short_update_date_ = 0; std::multimap postponed_updates_; // updates received during getDifference std::multimap pending_seq_updates_; // updates with too big seq std::map pending_qts_updates_; // updates with too big qts Timeout seq_gap_timeout_; Timeout qts_gap_timeout_; int32 retry_time_ = 1; Timeout retry_timeout_; bool running_get_difference_ = false; int32 last_get_difference_pts_ = 0; int32 last_get_difference_qts_ = 0; int32 min_postponed_update_pts_ = 0; int32 min_postponed_update_qts_ = 0; void tear_down() override; Promise<> add_pts(int32 pts); void on_pts_ack(PtsManager::PtsId ack_token); void save_pts(int32 pts); Promise<> add_qts(int32 qts); void on_qts_ack(PtsManager::PtsId ack_token); void save_qts(int32 qts); void set_date(int32 date, bool from_update, string date_source); int32 get_short_update_date() const; void process_get_difference_updates(vector> &&new_messages, vector> &&new_encrypted_messages, vector> &&other_updates); void on_pending_update(tl_object_ptr update, int32 seq, Promise &&promise, const char *source); void add_pending_qts_update(tl_object_ptr &&update, int32 qts, Promise &&promise); void on_pending_updates(vector> &&updates, int32 seq_begin, int32 seq_end, int32 date, Promise &&promise, const char *source); void process_updates(vector> &&updates, bool force_apply, Promise &&promise); void process_seq_updates(int32 seq_end, int32 date, vector> &&updates, Promise &&promise); void process_qts_update(tl_object_ptr &&update_ptr, int32 qts, Promise &&promise); void process_pending_seq_updates(); void process_pending_qts_updates(); static void fill_seq_gap(void *td); static void fill_qts_gap(void *td); static void fill_get_difference_gap(void *td); static void fill_gap(void *td, const char *source); void set_seq_gap_timeout(double timeout); void set_qts_gap_timeout(double timeout); void run_get_difference(bool is_recursive, const char *source); void on_failed_get_difference(); void before_get_difference(bool is_initial); void after_get_difference(); static bool have_update_pts_changed(const vector> &updates); static int32 get_update_pts(const telegram_api::Update *update); static int32 get_update_qts(const telegram_api::Update *update); static const vector> *get_updates(const telegram_api::Updates *updates_ptr); bool is_acceptable_user(UserId user_id) const; bool is_acceptable_chat(ChatId chat_id) const; bool is_acceptable_channel(ChannelId channel_id) const; bool is_acceptable_peer(const tl_object_ptr &peer) const; bool is_acceptable_message_entities(const vector> &message_entities) const; bool is_acceptable_message_reply_header( const telegram_api::object_ptr &header) const; bool is_acceptable_message_forward_header( const telegram_api::object_ptr &header) const; bool is_acceptable_message(const telegram_api::Message *message_ptr) const; bool is_acceptable_update(const telegram_api::Update *update) const; void on_update(tl_object_ptr update, bool force_apply, Promise &&promise); void on_update(tl_object_ptr update, bool force_apply, Promise &&promise); void on_update(tl_object_ptr update, bool force_apply, Promise &&promise); void on_update(tl_object_ptr update, bool force_apply, Promise &&promise); void on_update(tl_object_ptr update, bool force_apply, Promise &&promise); void on_update(tl_object_ptr update, bool force_apply, Promise &&promise); void on_update(tl_object_ptr update, bool force_apply, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool force_apply, Promise &&promise); void on_update(tl_object_ptr update, bool force_apply, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool force_apply, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool force_apply, Promise &&promise); void on_update(tl_object_ptr update, bool force_apply, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool force_apply, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool force_apply, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); // unsupported updates void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); }; } // namespace td