diff --git a/td/generate/scheme/telegram_api.tl b/td/generate/scheme/telegram_api.tl index 6b7b70523..e1efa9ce5 100644 --- a/td/generate/scheme/telegram_api.tl +++ b/td/generate/scheme/telegram_api.tl @@ -14,8 +14,10 @@ vector#1cb5c415 {t:Type} # [ t ] = Vector t; error#c4b9f9bb code:int text:string = Error; -ipPort ipv4:int port:int = IpPort; -help.configSimple#d997c3c5 date:int expires:int dc_id:int ip_port_list:Vector = help.ConfigSimple; +ipPort#d433ad73 ipv4:int port:int = IpPort; +ipPortSecret#37982646 ipv4:int port:int secret:bytes = IpPort; +accessPointRule#4679b65f phone_prefix_rules:string dc_id:int ips:vector = AccessPointRule; +help.configSimple#5a592a6c date:int expires:int rules:vector = help.ConfigSimple; ---functions--- @@ -1093,7 +1095,7 @@ help.saveAppLog#6f02f748 events:Vector = Bool; help.getInviteText#4d392343 = help.InviteText; help.getSupport#9cdf08cd = help.Support; help.getAppChangelog#9010ef6f prev_app_version:string = Updates; -help.getTermsOfService#350170f3 = help.TermsOfService; +help.getTermsOfService#fa796a44 country_iso2:string lang_code:string = help.TermsOfService; help.setBotUpdatesStatus#ec22cfcd pending_updates_count:int message:string = Bool; help.getCdnConfig#52029342 = CdnConfig; help.getRecentMeUrls#3dc0f114 referer:string = help.RecentMeUrls; diff --git a/td/generate/scheme/telegram_api.tlo b/td/generate/scheme/telegram_api.tlo index c64e8df26..5d0f09b4d 100644 Binary files a/td/generate/scheme/telegram_api.tlo and b/td/generate/scheme/telegram_api.tlo differ diff --git a/td/telegram/ConfigManager.cpp b/td/telegram/ConfigManager.cpp index 2c61a3e69..5b3f3c883 100644 --- a/td/telegram/ConfigManager.cpp +++ b/td/telegram/ConfigManager.cpp @@ -124,15 +124,11 @@ static ActorOwn<> get_simple_config_impl(Promise promise, int32 sc } ActorOwn<> get_simple_config_azure(Promise promise, bool is_test, int32 scheduler_id) { - string url = PSTRING() << "https://software-download.microsoft.com/" << (is_test ? "test" : "prod") << "/config.txt"; + string url = PSTRING() << "https://software-download.microsoft.com/" << (is_test ? "test" : "prod") + << "v2/config.txt"; return get_simple_config_impl(std::move(promise), scheduler_id, std::move(url), "tcdnb.azureedge.net"); } -ActorOwn<> get_simple_config_google_app(Promise promise, bool is_test, int32 scheduler_id) { - string url = PSTRING() << "https://www.google.com/" << (is_test ? "test/" : ""); - return get_simple_config_impl(std::move(promise), scheduler_id, std::move(url), "dns-telegram.appspot.com"); -} - ActorOwn<> get_simple_config_google_dns(Promise promise, bool is_test, int32 scheduler_id) { VLOG(config_recoverer) << "Request simple config from Google DNS"; #if TD_EMSCRIPTEN // FIXME @@ -171,7 +167,7 @@ ActorOwn<> get_simple_config_google_dns(Promise promise, bool is_t return decode_config(data); }()); }), - PSTRING() << "https://google.com/resolve?name=" << (is_test ? "t" : "") << "ap.stel.com&type=16", + PSTRING() << "https://www.google.com/resolve?name=" << (is_test ? "t" : "") << "apv2.stel.com&type=16", std::vector>({{"Host", "dns.google.com"}}), 10 /*timeout*/, 3 /*ttl*/, SslFd::VerifyPeer::Off)); #endif @@ -370,25 +366,54 @@ class ConfigRecoverer : public Actor { loop(); } + static bool check_phone_number_rules(Slice phone_number, Slice rules) { + bool found = false; + for (auto prefix : full_split(rules, ',')) { + if (prefix.empty()) { + found = true; + } else if (prefix[0] == '+' && begins_with(phone_number, prefix.substr(1))) { + found = true; + } else if (prefix[0] == '-' && begins_with(phone_number, prefix.substr(1))) { + return false; + } else { + LOG(ERROR) << "Invalid prefix rule " << prefix; + } + } + return found; + } + void on_simple_config(Result r_simple_config, bool dummy) { simple_config_query_.reset(); - auto r_dc_options = [&]() -> Result { - if (r_simple_config.is_error()) { - return r_simple_config.move_as_error(); - } - return DcOptions(*r_simple_config.ok()); - }(); dc_options_i_ = 0; - if (r_dc_options.is_ok()) { - simple_config_ = r_dc_options.move_as_ok(); - VLOG(config_recoverer) << "Got SimpleConfig " << simple_config_; + if (r_simple_config.is_ok()) { + auto config = r_simple_config.move_as_ok(); + LOG(ERROR) << to_string(config); + if (config->expires_ >= G()->unix_time()) { + string phone_number = G()->shared_config().get_option_string("my_phone_number"); + simple_config_.dc_options.clear(); + + for (auto &rule : config->rules_) { + if (check_phone_number_rules(phone_number, rule->phone_prefix_rules_) && DcId::is_valid(rule->dc_id_)) { + DcId dc_id = DcId::internal(rule->dc_id_); + for (auto &ip_port : rule->ips_) { + DcOption option(dc_id, *ip_port); + if (option.is_valid()) { + simple_config_.dc_options.push_back(std::move(option)); + } + } + } + } + VLOG(config_recoverer) << "Got SimpleConfig " << simple_config_; + LOG(ERROR) << "Got SimpleConfig " << simple_config_; + } + simple_config_expire_at_ = get_config_expire_time(); simple_config_at_ = Time::now_cached(); for (size_t i = 1; i < simple_config_.dc_options.size(); i++) { std::swap(simple_config_.dc_options[i], simple_config_.dc_options[Random::fast(0, static_cast(i))]); } } else { - VLOG(config_recoverer) << "Get SimpleConfig error " << r_dc_options.error(); + VLOG(config_recoverer) << "Get SimpleConfig error " << r_simple_config.error(); simple_config_ = DcOptions(); simple_config_expire_at_ = get_failed_config_expire_time(); } @@ -515,10 +540,9 @@ class ConfigRecoverer : public Actor { }); auto get_simple_config = [&]() { switch (simple_config_turn_ % 3) { - case 0: - return get_simple_config_azure; case 1: - return get_simple_config_google_app; + return get_simple_config_azure; + case 0: case 2: default: return get_simple_config_google_dns; diff --git a/td/telegram/ConfigManager.h b/td/telegram/ConfigManager.h index 72fc4847d..a76fc15f3 100644 --- a/td/telegram/ConfigManager.h +++ b/td/telegram/ConfigManager.h @@ -24,11 +24,9 @@ using SimpleConfig = tl_object_ptr; Result decode_config(Slice input); -ActorOwn<> get_simple_config_azure(Promise promise, bool is_test = false, int32 scheduler_id = -1); +ActorOwn<> get_simple_config_azure(Promise promise, bool is_test, int32 scheduler_id); -ActorOwn<> get_simple_config_google_app(Promise promise, bool is_test = false, int32 scheduler_id = -1); - -ActorOwn<> get_simple_config_google_dns(Promise promise, bool is_test = false, int32 scheduler_id = -1); +ActorOwn<> get_simple_config_google_dns(Promise promise, bool is_test, int32 scheduler_id); using FullConfig = tl_object_ptr; diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index f58b6f094..6212ca1ad 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -4933,6 +4933,9 @@ void ContactsManager::on_get_user(tl_object_ptr &&user_ptr, if (flags & USER_FLAG_IS_ME) { set_my_id(user_id); td_->auth_manager_->set_is_bot(is_bot); + if (!is_bot) { + G()->shared_config().set_option_string("my_phone_number", user->phone_); + } } else { /* if (!(flags & USER_FLAG_HAS_ACCESS_HASH) && !(flags & USER_FLAG_IS_DELETED) && diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 9405e22b5..27f2c5a42 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -4204,7 +4204,7 @@ bool Td::is_internal_config_option(Slice name) { return name == "call_ring_timeout_ms" || name == "call_receive_timeout_ms" || name == "channels_read_media_period" || name == "edit_time_limit" || name == "revoke_pm_inbox" || name == "revoke_time_limit" || name == "revoke_pm_time_limit" || name == "rating_e_decay" || name == "saved_animations_limit" || - name == "recent_stickers_limit" || name == "expect_blocking" || name == "auth"; + name == "recent_stickers_limit" || name == "expect_blocking" || name == "my_phone_number" || name == "auth"; } void Td::on_config_option_updated(const string &name) { diff --git a/td/telegram/net/ConnectionCreator.cpp b/td/telegram/net/ConnectionCreator.cpp index 7ffb10c58..6975665be 100644 --- a/td/telegram/net/ConnectionCreator.cpp +++ b/td/telegram/net/ConnectionCreator.cpp @@ -671,6 +671,7 @@ void ConnectionCreator::request_raw_connection_by_ip(IPAddress ip_address, Result ConnectionCreator::find_connection(const ConnectionCreator::ProxyInfo &proxy, DcId dc_id, bool allow_media_only, FindConnectionExtra &extra) { + extra.debug_str = PSTRING() << "Failed to find valid IP for " << dc_id; TRY_RESULT(info, dc_options_set_.find_connection(dc_id, allow_media_only, proxy.use_proxy())); extra.stat = info.stat; int32 int_dc_id = dc_id.get_raw_id(); @@ -680,10 +681,11 @@ Result ConnectionCreator::find_connection(const ConnectionCreator::Pro int16 raw_dc_id = narrow_cast(info.option->is_media_only() ? -int_dc_id : int_dc_id); if (proxy.use_mtproto_proxy()) { + extra.debug_str = PSTRING() << "Mtproto " << proxy.ip_address() << " to DC" << raw_dc_id; + TRY_RESULT(secret, hex_decode(proxy.proxy().secret())); extra.transport_type = {mtproto::TransportType::ObfuscatedTcp, raw_dc_id, std::move(secret)}; - extra.debug_str = PSTRING() << "Mtproto " << proxy.ip_address() << " to DC" << raw_dc_id; LOG(INFO) << "Create: " << extra.debug_str; return SocketFd::open(proxy.ip_address()); } @@ -787,7 +789,7 @@ void ConnectionCreator::client_loop(ClientInfo &client) { auto r_socket_fd = find_connection(proxy, client.dc_id, client.allow_media_only, extra); check_mode |= extra.check_mode; if (r_socket_fd.is_error()) { - LOG(WARNING) << r_socket_fd.error(); + LOG(WARNING) << extra.debug_str << ": " << r_socket_fd.error(); if (extra.stat) { extra.stat->on_error(); // TODO: different kind of error } diff --git a/td/telegram/net/DcOptions.h b/td/telegram/net/DcOptions.h index 5c54eca6d..07cf67c80 100644 --- a/td/telegram/net/DcOptions.h +++ b/td/telegram/net/DcOptions.h @@ -81,9 +81,28 @@ class DcOption { init_ip_address(ip, port); } - DcOption(DcId new_dc_id, const telegram_api::ipPort &ip_port) { + DcOption(DcId new_dc_id, const telegram_api::IpPort &ip_port_ref) { + switch (ip_port_ref.get_id()) { + case telegram_api::ipPort::ID: { + auto &ip_port = static_cast(ip_port_ref); + init_ip_address(IPAddress::ipv4_to_str(ip_port.ipv4_), ip_port.port_); + break; + } + case telegram_api::ipPortSecret::ID: { + auto &ip_port = static_cast(ip_port_ref); + if (ip_port.secret_.size() != 16u) { + return; + } + flags_ |= Flags::HasSecret; + secret_ = ip_port.secret_.as_slice().str(); + init_ip_address(IPAddress::ipv4_to_str(ip_port.ipv4_), ip_port.port_); + break; + } + default: + UNREACHABLE(); + } + flags_ |= Flags::ObfuscatedTcpOnly; dc_id_ = new_dc_id; - init_ip_address(IPAddress::ipv4_to_str(ip_port.ipv4_), ip_port.port_); } DcId get_dc_id() const { @@ -204,15 +223,7 @@ class DcOptions { } } } - explicit DcOptions(const telegram_api::help_configSimple &config_simple) { - auto dc_id = DcId::is_valid(config_simple.dc_id_) ? DcId::internal(config_simple.dc_id_) : DcId(); - for (auto &ip_port : config_simple.ip_port_list_) { - DcOption option(dc_id, *ip_port); - if (option.is_valid()) { - dc_options.push_back(std::move(option)); - } - } - } + template void store(StorerT &storer) const { ::td::store(dc_options, storer); diff --git a/test/mtproto.cpp b/test/mtproto.cpp index 4798c16e9..cad5c8102 100644 --- a/test/mtproto.cpp +++ b/test/mtproto.cpp @@ -31,67 +31,49 @@ REGISTER_TESTS(mtproto); using namespace td; using namespace mtproto; -#if !TD_WINDOWS && !TD_EMSCRIPTEN // TODO TEST(Mtproto, config) { ConcurrentScheduler sched; int threads_n = 0; sched.init(threads_n); - int cnt = 3; + int cnt = 1; { auto guard = sched.get_current_guard(); - get_simple_config_azure(PromiseCreator::lambda([&](Result r_simple_config) { - if (r_simple_config.is_ok()) { - LOG(ERROR) << to_string(r_simple_config.ok()); - } else { - LOG(ERROR) << r_simple_config.error(); - } - if (--cnt == 0) { - Scheduler::instance()->finish(); - } - })) - .release(); - get_simple_config_google_app(PromiseCreator::lambda([&](Result r_simple_config) { - if (r_simple_config.is_ok()) { - LOG(ERROR) << to_string(r_simple_config.ok()); - } else { - LOG(ERROR) << r_simple_config.error(); - } - if (--cnt == 0) { - Scheduler::instance()->finish(); - } - })) - .release(); + auto run = [&](auto &func, bool is_test) { + cnt++; + auto promise = PromiseCreator::lambda([&](Result r_simple_config) { + if (r_simple_config.is_ok()) { + LOG(ERROR) << to_string(r_simple_config.ok()); + } else { + LOG(ERROR) << r_simple_config.error(); + } + if (--cnt == 0) { + Scheduler::instance()->finish(); + } + }); + func(std::move(promise), is_test, -1).release(); + }; - get_simple_config_google_dns(PromiseCreator::lambda([&](Result r_simple_config) { - if (r_simple_config.is_ok()) { - LOG(ERROR) << to_string(r_simple_config.ok()); - } else { - LOG(ERROR) << r_simple_config.error(); - } - if (--cnt == 0) { - Scheduler::instance()->finish(); - } - })) - .release(); + run(get_simple_config_azure, false); + run(get_simple_config_google_dns, false); + run(get_simple_config_azure, true); + run(get_simple_config_google_dns, true); } + cnt--; sched.start(); while (sched.run_main(10)) { // empty; } sched.finish(); } -#endif TEST(Mtproto, encrypted_config) { string data = - " LQ2 \b\n\tru6xVXpHHckW4eQWK0X3uThupVOor5sXT8t298IjDksYeUseQTOIrnUqiQj7o" - "+ZgPfhnfe+lfcQA+naax9akgllimjlJtL5riTf3O7iqZSnJ614qmCucxqqVTbXk/" - "hY2KaJTtsMqk7cShJjM3aQ4DD40h2InTaG7uyVO2q7K0GMUTeY3AM0Rt1lUjKHLD" - "g4RwjTzZaG8TwfgL/mZ7jsvgTTTATPWKUo7SmxQ9Hsj+07NMGqr6JKZS6aiU1Knz" - "VGCZ3OJEyRYocktN4HjaLpkguilaHWlVM2UNFUd5a+ajfLIiiKlH0FRC3XZ12CND" - "Y+NBjv0I57N2O4fBfswTlA== "; + " hO//tt \b\n\tiwPVovorKtIYtQ8y2ik7CqfJiJ4pJOCLRa4fBmNPixuRPXnBFF/3mTAAZoSyHq4SNylGHz0Cv1/" + "FnWWdEV+BPJeOTk+ARHcNkuJBt0CqnfcVCoDOpKqGyq0U31s2MOpQvHgAG+Tlpg02syuH0E4dCGRw5CbJPARiynteb9y5fT5x/" + "kmdp6BMR5tWQSQF0liH16zLh8BDSIdiMsikdcwnAvBwdNhRqQBqGx9MTh62MDmlebjtczE9Gz0z5cscUO2yhzGdphgIy6SP+" + "bwaqLWYF0XdPGjKLMUEJW+rou6fbL1t/EUXPtU0XmQAnO0Fh86h+AqDMOe30N4qKrPQ== "; auto config = decode_config(data).move_as_ok(); }