diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 79f7738a..f9df66ac 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -2083,7 +2083,7 @@ updateScopeNotificationSettings scope:NotificationSettingsScope notification_set //@chat_id Chat identifier @reply_markup_message_id Identifier of the message from which reply markup needs to be used; 0 if there is no default custom reply markup in the chat updateChatReplyMarkup chat_id:int53 reply_markup_message_id:int53 = Update; -//@description A draft has changed. Be aware that the update may come in the currently opened chat but with old content of the draft. If the user has changed the content of the draft, this update shouldn't be applied @chat_id Chat identifier @draft_message The new draft message; may be null @order New value of the chat order +//@description A chat draft has changed. Be aware that the update may come in the currently opened chat but with old content of the draft. If the user has changed the content of the draft, this update shouldn't be applied @chat_id Chat identifier @draft_message The new draft message; may be null @order New value of the chat order updateChatDraftMessage chat_id:int53 draft_message:draftMessage order:int64 = Update; //@description Some messages were deleted @chat_id Chat identifier @message_ids Identifiers of the deleted messages @@ -2094,6 +2094,9 @@ updateDeleteMessages chat_id:int53 message_ids:vector is_permanent:Bool f //@description User activity in the chat has changed @chat_id Chat identifier @user_id Identifier of a user performing an action @action The action description updateUserChatAction chat_id:int53 user_id:int32 action:ChatAction = Update; +//@description A promoted by enabled proxy chat has changed @chat_id Identifier of the promoted chat or 0 if none +updatePromotedChat chat_id:int53 = Update; + //@description The user went online or offline @user_id User identifier @status New status of the user updateUserStatus user_id:int32 status:UserStatus = Update; diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index 0ba96127..a08387eb 100644 Binary files a/td/generate/scheme/td_api.tlo and b/td/generate/scheme/td_api.tlo differ diff --git a/td/telegram/Global.cpp b/td/telegram/Global.cpp index e1739191..75b07f02 100644 --- a/td/telegram/Global.cpp +++ b/td/telegram/Global.cpp @@ -51,7 +51,7 @@ void Global::set_temp_auth_key_watchdog(ActorOwn actor) { temp_auth_key_watchdog_ = std::move(actor); } -const MtprotoHeader &Global::mtproto_header() const { +MtprotoHeader &Global::mtproto_header() { return *mtproto_header_; } void Global::set_mtproto_header(std::unique_ptr mtproto_header) { diff --git a/td/telegram/Global.h b/td/telegram/Global.h index c11f101c..34e54e2e 100644 --- a/td/telegram/Global.h +++ b/td/telegram/Global.h @@ -221,7 +221,7 @@ class Global : public ActorContext { ActorId temp_auth_key_watchdog() const; void set_temp_auth_key_watchdog(ActorOwn actor); - const MtprotoHeader &mtproto_header() const; + MtprotoHeader &mtproto_header(); void set_mtproto_header(std::unique_ptr mtproto_header); const TdParameters ¶meters() const { diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index d368625c..87ff04e0 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -4700,46 +4700,6 @@ MessagesManager::MessagesManager(Td *td, ActorShared<> parent) : td_(td), parent active_dialog_action_timeout_.set_callback_data(static_cast(this)); sequence_dispatcher_ = create_actor("multi sequence dispatcher"); - - if (G()->parameters().use_message_db) { - auto last_database_server_dialog_date_string = G()->td_db()->get_binlog_pmc()->get("last_server_dialog_date"); - if (!last_database_server_dialog_date_string.empty()) { - string order_str; - string dialog_id_str; - std::tie(order_str, dialog_id_str) = split(last_database_server_dialog_date_string); - - auto r_order = to_integer_safe(order_str); - auto r_dialog_id = to_integer_safe(dialog_id_str); - if (r_order.is_error() || r_dialog_id.is_error()) { - LOG(ERROR) << "Can't parse " << last_database_server_dialog_date_string; - } else { - last_database_server_dialog_date_ = DialogDate(r_order.ok(), DialogId(r_dialog_id.ok())); - } - } - LOG(INFO) << "Load last_database_server_dialog_date_ = " << last_database_server_dialog_date_; - - auto unread_message_count_string = G()->td_db()->get_binlog_pmc()->get("unread_message_count"); - if (!unread_message_count_string.empty()) { - string total_count; - string muted_count; - std::tie(total_count, muted_count) = split(unread_message_count_string); - - auto r_total_count = to_integer_safe(total_count); - auto r_muted_count = to_integer_safe(muted_count); - if (r_total_count.is_error() || r_muted_count.is_error()) { - LOG(ERROR) << "Can't parse " << unread_message_count_string; - } else { - unread_message_total_count_ = r_total_count.ok(); - unread_message_muted_count_ = r_muted_count.ok(); - is_unread_count_inited_ = true; - send_update_unread_message_count(DialogId(), true, "load unread_message_count"); - } - } - LOG(INFO) << "Load last_database_server_dialog_date_ = " << last_database_server_dialog_date_; - } else { - G()->td_db()->get_binlog_pmc()->erase("last_server_dialog_date"); - G()->td_db()->get_binlog_pmc()->erase("unread_message_count"); - } } MessagesManager::~MessagesManager() = default; @@ -9598,6 +9558,70 @@ void MessagesManager::tear_down() { void MessagesManager::start_up() { always_wait_for_mailbox(); + if (G()->parameters().use_message_db) { + auto last_database_server_dialog_date_string = G()->td_db()->get_binlog_pmc()->get("last_server_dialog_date"); + if (!last_database_server_dialog_date_string.empty()) { + string order_str; + string dialog_id_str; + std::tie(order_str, dialog_id_str) = split(last_database_server_dialog_date_string); + + auto r_order = to_integer_safe(order_str); + auto r_dialog_id = to_integer_safe(dialog_id_str); + if (r_order.is_error() || r_dialog_id.is_error()) { + LOG(ERROR) << "Can't parse " << last_database_server_dialog_date_string; + } else { + last_database_server_dialog_date_ = DialogDate(r_order.ok(), DialogId(r_dialog_id.ok())); + } + } + LOG(INFO) << "Load last_database_server_dialog_date_ = " << last_database_server_dialog_date_; + + auto unread_message_count_string = G()->td_db()->get_binlog_pmc()->get("unread_message_count"); + if (!unread_message_count_string.empty()) { + string total_count; + string muted_count; + std::tie(total_count, muted_count) = split(unread_message_count_string); + + auto r_total_count = to_integer_safe(total_count); + auto r_muted_count = to_integer_safe(muted_count); + if (r_total_count.is_error() || r_muted_count.is_error()) { + LOG(ERROR) << "Can't parse " << unread_message_count_string; + } else { + unread_message_total_count_ = r_total_count.ok(); + unread_message_muted_count_ = r_muted_count.ok(); + is_unread_count_inited_ = true; + send_update_unread_message_count(DialogId(), true, "load unread_message_count"); + } + } + LOG(INFO) << "Load last_database_server_dialog_date_ = " << last_database_server_dialog_date_; + + auto promoted_dialog_id_string = G()->td_db()->get_binlog_pmc()->get("promoted_dialog_id"); + if (!promoted_dialog_id_string.empty()) { + auto r_dialog_id = to_integer_safe(promoted_dialog_id_string); + if (r_dialog_id.is_error()) { + LOG(ERROR) << "Can't parse " << promoted_dialog_id_string; + } else { + promoted_dialog_id_ = DialogId(r_dialog_id.ok()); + if (!promoted_dialog_id_.is_valid()) { + LOG(ERROR) << "Have invalid chat ID " << promoted_dialog_id_string; + promoted_dialog_id_ = DialogId(); + } else { + Dialog *d = get_dialog_force(promoted_dialog_id_); + if (d == nullptr) { + LOG(ERROR) << "Can't load " << promoted_dialog_id_; + promoted_dialog_id_ = DialogId(); + } + } + } + } + if (promoted_dialog_id_.is_valid()) { + send_update_promoted_chat(); + } + } else { + G()->td_db()->get_binlog_pmc()->erase("last_server_dialog_date"); + G()->td_db()->get_binlog_pmc()->erase("unread_message_count"); + G()->td_db()->get_binlog_pmc()->erase("promoted_dialog_id"); + } + if (G()->parameters().use_message_db) { ttl_db_loop_start(G()->server_time()); } @@ -19120,6 +19144,13 @@ void MessagesManager::send_update_chat_unread_mention_count(const Dialog *d) { } } +void MessagesManager::send_update_promoted_chat() const { + if (!td_->auth_manager_->is_bot()) { + LOG(INFO) << "Update promoted chat to " << promoted_dialog_id_; + send_closure(G()->td(), &Td::send_update, make_tl_object(promoted_dialog_id_.get())); + } +} + void MessagesManager::on_send_message_get_quick_ack(int64 random_id) { auto it = being_sent_messages_.find(random_id); if (it == being_sent_messages_.end()) { @@ -25816,4 +25847,41 @@ void MessagesManager::get_payment_receipt(FullMessageId full_message_id, td::get_payment_receipt(message_id.get_server_message_id(), std::move(promise)); } +void MessagesManager::on_get_promoted_dialog_id(tl_object_ptr peer, + vector> users, + vector> chats) { + if (peer == nullptr) { + set_promoted_dialog_id(DialogId()); + return; + } + + td_->contacts_manager_->on_get_users(std::move(users)); + td_->contacts_manager_->on_get_chats(std::move(chats)); + + set_promoted_dialog_id(DialogId(peer)); +} + +void MessagesManager::set_promoted_dialog_id(DialogId dialog_id) { + if (promoted_dialog_id_ == dialog_id) { + return; + } + + promoted_dialog_id_ = dialog_id; + if (dialog_id.is_valid()) { + force_create_dialog(dialog_id, "set_promoted_dialog_id"); + /* + Dialog *d = get_dialog(dialog_id); + CHECK(d != nullptr); + update_dialog_pos(d, false, "set_promoted_dialog_id"); + */ + } + + if (G()->parameters().use_message_db) { + G()->td_db()->get_binlog_pmc()->set("promoted_dialog_id", to_string(promoted_dialog_id_.get())); + LOG(INFO) << "Save promoted " << promoted_dialog_id_; + } + + send_update_promoted_chat(); +} + } // namespace td diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index f2638aef..d9859039 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -1401,6 +1401,10 @@ class MessagesManager : public Actor { void on_get_dialog_query_finished(DialogId dialog_id, Status &&status); + void on_get_promoted_dialog_id(tl_object_ptr peer, + vector> users, + vector> chats); + void on_binlog_events(vector &&events); void get_payment_form(FullMessageId full_message_id, Promise> &&promise); @@ -2218,6 +2222,8 @@ class MessagesManager : public Actor { void send_update_chat_unread_mention_count(const Dialog *d); + void send_update_promoted_chat() const; + tl_object_ptr get_message_object(DialogId dialog_id, const Message *message) const; static tl_object_ptr get_messages_object(int32 total_count, @@ -2597,6 +2603,8 @@ class MessagesManager : public Actor { void on_upload_dialog_photo(FileId file_id, tl_object_ptr input_file); void on_upload_dialog_photo_error(FileId file_id, Status status); + void set_promoted_dialog_id(DialogId dialog_id); + static uint64 get_sequence_dispatcher_id(DialogId dialog_id, int32 message_content_type); Dialog *get_service_notifications_dialog(); @@ -2884,6 +2892,8 @@ class MessagesManager : public Actor { std::unordered_map set_typing_query_; + DialogId promoted_dialog_id_; + Td *td_; ActorShared<> parent_; }; diff --git a/td/telegram/StateManager.cpp b/td/telegram/StateManager.cpp index 11171d54..3b10788f 100644 --- a/td/telegram/StateManager.cpp +++ b/td/telegram/StateManager.cpp @@ -14,6 +14,7 @@ #include "td/utils/Time.h" namespace td { + void StateManager::inc_connect() { auto &cnt = get_link_token() == 1 ? connect_cnt_ : connect_proxy_cnt_; cnt++; @@ -48,6 +49,7 @@ void StateManager::on_synchronized(bool is_synchronized) { void StateManager::on_network(NetType new_network_type) { do_on_network(new_network_type, true /*inc_generation*/); } + void StateManager::do_on_network(NetType new_network_type, bool inc_generation) { bool new_network_flag = new_network_type != NetType::None; if (network_flag_ != new_network_flag) { @@ -176,4 +178,5 @@ void StateManager::loop() { has_timestamp_ = false; } } + } // namespace td diff --git a/td/telegram/StateManager.h b/td/telegram/StateManager.h index 9582db7c..fcba69a1 100644 --- a/td/telegram/StateManager.h +++ b/td/telegram/StateManager.h @@ -14,6 +14,7 @@ #include "td/utils/common.h" namespace td { + class StateManager final : public Actor { public: enum class State : int32 { WaitingForNetwork, ConnectingToProxy, Connecting, Updating, Ready, Empty }; @@ -131,4 +132,5 @@ class StateManager final : public Actor { return ConnectionToken(std::move(actor)); } }; + } // namespace td diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 63602472..c53db6c0 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -30,6 +30,7 @@ #include namespace td { + class AnimationsManager; class AudiosManager; class AuthManager; diff --git a/td/telegram/TdDb.cpp b/td/telegram/TdDb.cpp index 4bf474df..1c11a45e 100644 --- a/td/telegram/TdDb.cpp +++ b/td/telegram/TdDb.cpp @@ -304,6 +304,7 @@ Status TdDb::init_sqlite(int32 scheduler_id, const TdParameters ¶meters, DbK if (dialog_db_was_created) { binlog_pmc.erase("unread_message_count"); binlog_pmc.erase("last_server_dialog_date"); + binlog_pmc.erase("promoted_dialog_id"); } if (db_version == 0) { binlog_pmc.erase_by_prefix("top_dialogs"); diff --git a/td/telegram/net/ConnectionCreator.cpp b/td/telegram/net/ConnectionCreator.cpp index 492fb0e4..0aac4d91 100644 --- a/td/telegram/net/ConnectionCreator.cpp +++ b/td/telegram/net/ConnectionCreator.cpp @@ -6,9 +6,14 @@ // #include "td/telegram/net/ConnectionCreator.h" +#include "td/telegram/telegram_api.h" + #include "td/telegram/ConfigManager.h" #include "td/telegram/Global.h" #include "td/telegram/logevent/LogEvent.h" +#include "td/telegram/MessagesManager.h" +#include "td/telegram/net/MtprotoHeader.h" +#include "td/telegram/net/NetQueryDispatcher.h" #include "td/telegram/StateManager.h" #include "td/mtproto/IStreamTransport.h" @@ -216,15 +221,24 @@ void ConnectionCreator::set_proxy(Proxy proxy) { } void ConnectionCreator::set_proxy_impl(Proxy proxy, bool from_db) { + auto have_proxy = proxy.type() != Proxy::Type::None; if (proxy_ == proxy) { + if (!have_proxy) { + on_get_proxy_info(make_tl_object(0)); + } return; } proxy_ = std::move(proxy); - send_closure(G()->state_manager(), &StateManager::on_proxy, proxy_.type() != Proxy::Type::None); + G()->mtproto_header().set_proxy(proxy_); + send_closure(G()->state_manager(), &StateManager::on_proxy, have_proxy); if (!from_db) { - G()->td_db()->get_binlog_pmc()->set("proxy", log_event_store(proxy_).as_slice().str()); + if (have_proxy) { + G()->td_db()->get_binlog_pmc()->set("proxy", log_event_store(proxy_).as_slice().str()); + } else { + G()->td_db()->get_binlog_pmc()->erase("proxy"); + } for (auto &child : children_) { child.second.reset(); } @@ -233,6 +247,14 @@ void ConnectionCreator::set_proxy_impl(Proxy proxy, bool from_db) { resolve_proxy_query_token_ = 0; resolve_proxy_timestamp_ = Timestamp(); proxy_ip_address_ = IPAddress(); + + get_proxy_info_query_token_ = 0; + get_proxy_info_timestamp_ = Timestamp(); + if (!have_proxy || !from_db) { + on_get_proxy_info(make_tl_object(0)); + } else { + schedule_get_proxy_info(0); + } } void ConnectionCreator::get_proxy(Promise promise) { @@ -246,6 +268,7 @@ void ConnectionCreator::on_network(bool network_flag, uint32 network_generation) if (network_flag_) { resolve_proxy_query_token_ = 0; resolve_proxy_timestamp_ = Timestamp(); + get_proxy_info_timestamp_ = Timestamp(); for (auto &client : clients_) { client.second.backoff.clear(); client.second.flood_control.clear_events(); @@ -258,6 +281,7 @@ void ConnectionCreator::on_network(bool network_flag, uint32 network_generation) } } } + void ConnectionCreator::on_online(bool online_flag) { online_flag_ = online_flag; if (online_flag_) { @@ -597,19 +621,20 @@ void ConnectionCreator::on_dc_update(DcId dc_id, string ip_port, Promise<> promi void ConnectionCreator::start_up() { class StateCallback : public StateManager::Callback { public: - explicit StateCallback(ActorId session) : session_(std::move(session)) { + explicit StateCallback(ActorId connection_creator) + : connection_creator_(std::move(connection_creator)) { } bool on_network(NetType network_type, uint32 generation) override { - send_closure(session_, &ConnectionCreator::on_network, network_type != NetType::None, generation); - return session_.is_alive(); + send_closure(connection_creator_, &ConnectionCreator::on_network, network_type != NetType::None, generation); + return connection_creator_.is_alive(); } bool on_online(bool online_flag) override { - send_closure(session_, &ConnectionCreator::on_online, online_flag); - return session_.is_alive(); + send_closure(connection_creator_, &ConnectionCreator::on_online, online_flag); + return connection_creator_.is_alive(); } private: - ActorId session_; + ActorId connection_creator_; }; send_closure(G()->state_manager(), &StateManager::add_callback, make_unique(actor_id(this))); @@ -622,15 +647,15 @@ void ConnectionCreator::start_up() { on_dc_options(std::move(dc_options)); } + Proxy proxy; auto log_event_proxy = G()->td_db()->get_binlog_pmc()->get("proxy"); if (!log_event_proxy.empty()) { - Proxy proxy; log_event_parse(proxy, log_event_proxy).ensure(); - set_proxy_impl(std::move(proxy), true); } + set_proxy_impl(std::move(proxy), true); get_host_by_name_actor_ = - create_actor_on_scheduler("GetHostByNameActor", G()->get_gc_scheduler_id(), 29 * 60, 0); + create_actor_on_scheduler("GetHostByNameActor", G()->get_gc_scheduler_id(), 5 * 60 - 1, 0); ref_cnt_guard_ = create_reference(-1); @@ -703,38 +728,121 @@ void ConnectionCreator::loop() { if (!network_flag_) { return; } - if (proxy_.type() == Proxy::Type::None) { - return; + + Timestamp timeout; + if (proxy_.type() == Proxy::Type::Mtproto) { + if (get_proxy_info_timestamp_.is_in_past()) { + if (get_proxy_info_query_token_ == 0) { + get_proxy_info_query_token_ = next_token(); + auto query = G()->net_query_creator().create(create_storer(telegram_api::help_getProxyData())); + G()->net_query_dispatcher().dispatch_with_callback(std::move(query), + actor_shared(this, get_proxy_info_query_token_)); + } + } else { + CHECK(get_proxy_info_query_token_ == 0); + timeout.relax(get_proxy_info_timestamp_); + } } - if (resolve_proxy_query_token_ != 0) { - return; + + if (proxy_.type() != Proxy::Type::None) { + if (resolve_proxy_timestamp_.is_in_past()) { + if (resolve_proxy_query_token_ == 0) { + resolve_proxy_query_token_ = next_token(); + send_closure( + get_host_by_name_actor_, &GetHostByNameActor::run, proxy_.server().str(), proxy_.port(), + PromiseCreator::lambda([actor_id = create_reference(resolve_proxy_query_token_)](Result result) { + send_closure(std::move(actor_id), &ConnectionCreator::on_proxy_resolved, std::move(result), false); + })); + } + } else { + CHECK(resolve_proxy_query_token_ == 0); + timeout.relax(resolve_proxy_timestamp_); + } } - if (resolve_proxy_timestamp_ && !resolve_proxy_timestamp_.is_in_past()) { - set_timeout_at(resolve_proxy_timestamp_.at()); - return; + + if (timeout) { + set_timeout_at(timeout.at()); } - resolve_proxy_query_token_ = next_token(); - send_closure( - get_host_by_name_actor_, &GetHostByNameActor::run, proxy_.server().str(), proxy_.port(), - PromiseCreator::lambda([actor_id = create_reference(resolve_proxy_query_token_)](Result result) { - send_closure(std::move(actor_id), &ConnectionCreator::on_proxy_resolved, std::move(result), false); - })); } -void ConnectionCreator::on_proxy_resolved(Result r_ip_address, bool dummy) { +void ConnectionCreator::on_result(NetQueryPtr query) { + if (get_link_token() != get_proxy_info_query_token_) { + return; + } + SCOPE_EXIT { loop(); }; + + get_proxy_info_query_token_ = 0; + auto res = fetch_result(std::move(query)); + if (res.is_error()) { + if (G()->close_flag()) { + return; + } + LOG(ERROR) << "Receive error for getProxyData: " << res.error(); + return schedule_get_proxy_info(60); + } + on_get_proxy_info(res.move_as_ok()); +} + +void ConnectionCreator::on_get_proxy_info(telegram_api::object_ptr proxy_data_ptr) { + CHECK(proxy_data_ptr != nullptr); + LOG(INFO) << "Receive " << to_string(proxy_data_ptr); + int32 expires = 0; + switch (proxy_data_ptr->get_id()) { + case telegram_api::help_proxyDataEmpty::ID: { + auto proxy = telegram_api::move_object_as(proxy_data_ptr); + expires = proxy->expires_; + send_closure(G()->messages_manager(), &MessagesManager::on_get_promoted_dialog_id, nullptr, + vector>(), vector>()); + break; + } + case telegram_api::help_proxyDataPromo::ID: { + auto proxy = telegram_api::move_object_as(proxy_data_ptr); + expires = proxy->expires_; + send_closure(G()->messages_manager(), &MessagesManager::on_get_promoted_dialog_id, std::move(proxy->peer_), + std::move(proxy->users_), std::move(proxy->chats_)); + break; + } + default: + UNREACHABLE(); + } + if (expires != 0) { + expires -= G()->unix_time(); + } + schedule_get_proxy_info(expires); +} + +void ConnectionCreator::schedule_get_proxy_info(int32 expires) { + if (expires < 0) { + LOG(ERROR) << "Receive wrong expires: " << expires; + expires = 0; + } + if (expires != 0 && expires < 60) { + expires = 60; + } + if (expires > 86400) { + expires = 86400; + } + get_proxy_info_timestamp_ = Timestamp::in(expires); +} + +void ConnectionCreator::on_proxy_resolved(Result r_ip_address, bool dummy) { if (get_link_token() != resolve_proxy_query_token_) { return; } + + SCOPE_EXIT { + loop(); + }; + resolve_proxy_query_token_ = 0; if (r_ip_address.is_error()) { resolve_proxy_timestamp_ = Timestamp::in(1 * 60); return; } proxy_ip_address_ = r_ip_address.move_as_ok(); - proxy_ip_address_.set_port(proxy_.port()); resolve_proxy_timestamp_ = Timestamp::in(5 * 60); for (auto &client : clients_) { client_loop(client.second); diff --git a/td/telegram/net/ConnectionCreator.h b/td/telegram/net/ConnectionCreator.h index 403b8ea8..b5592b94 100644 --- a/td/telegram/net/ConnectionCreator.h +++ b/td/telegram/net/ConnectionCreator.h @@ -10,6 +10,7 @@ #include "td/telegram/net/DcOptions.h" #include "td/telegram/net/DcOptionsSet.h" +#include "td/telegram/net/NetQuery.h" #include "td/telegram/StateManager.h" #include "td/mtproto/IStreamTransport.h" @@ -148,7 +149,7 @@ inline bool operator!=(const Proxy &lhs, const Proxy &rhs) { return !(lhs == rhs); } -class ConnectionCreator : public Actor { +class ConnectionCreator : public NetQueryCallback { public: explicit ConnectionCreator(ActorShared<> parent); ConnectionCreator(ConnectionCreator &&other); @@ -180,6 +181,9 @@ class ConnectionCreator : public Actor { Timestamp resolve_proxy_timestamp_; uint64 resolve_proxy_query_token_{0}; + uint64 get_proxy_info_query_token_{0}; + Timestamp get_proxy_info_timestamp_; + struct ClientInfo { class Backoff { #if TD_ANDROID || TD_DARWIN_IOS || TD_DARWIN_WATCH_OS || TD_TIZEN @@ -233,10 +237,10 @@ class ConnectionCreator : public Actor { int ref_cnt_{0}; ActorShared create_reference(int64 token); bool close_flag_{false}; - int64 current_token_ = 0; + uint64 current_token_ = 0; std::map> children_; - int64 next_token() { + uint64 next_token() { return ++current_token_; } void set_proxy_impl(Proxy proxy, bool from_db); @@ -246,6 +250,8 @@ class ConnectionCreator : public Actor { void hangup() override; void loop() override; + void on_result(NetQueryPtr query) override; + void save_dc_options(); Result do_request_connection(DcId dc_id, bool allow_media_only); Result, bool>> do_request_raw_connection(DcId dc_id, @@ -270,6 +276,10 @@ class ConnectionCreator : public Actor { bool check_flag); void client_set_timeout_at(ClientInfo &client, double wakeup_at); + void on_get_proxy_info(telegram_api::object_ptr proxy_data_ptr); + + void schedule_get_proxy_info(int32 expires); + void on_proxy_resolved(Result ip_address, bool dummy); static DcOptions get_default_dc_options(bool is_test); diff --git a/td/telegram/net/MtprotoHeader.h b/td/telegram/net/MtprotoHeader.h index be546cd3..5c9ec603 100644 --- a/td/telegram/net/MtprotoHeader.h +++ b/td/telegram/net/MtprotoHeader.h @@ -24,8 +24,13 @@ class MtprotoHeader { Proxy proxy; }; - explicit MtprotoHeader(const Options &options) - : default_header_(gen_header(options, false)), anonymous_header_(gen_header(options, true)) { + explicit MtprotoHeader(const Options &options) : options_(options) { + gen_headers(); + } + + void set_proxy(Proxy proxy) { + options_.proxy = proxy; + default_header_ = gen_header(options_, false); } Slice get_default_header() const { @@ -36,9 +41,15 @@ class MtprotoHeader { } private: + Options options_; string default_header_; string anonymous_header_; + void gen_headers() { + default_header_ = gen_header(options_, false); + anonymous_header_ = gen_header(options_, true); + } + static string gen_header(const Options &options, bool is_anonymous); };