New ConfigRecoverer scheme.

GitOrigin-RevId: 1101ddc56b0836387faf089ca52fe7376db9f88f
This commit is contained in:
levlam 2018-05-24 18:09:27 +03:00
parent ede1d58e0f
commit 0e48dd8a81
9 changed files with 105 additions and 83 deletions

View File

@ -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<ipPort> = 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<IpPort> = AccessPointRule;
help.configSimple#5a592a6c date:int expires:int rules:vector<AccessPointRule> = help.ConfigSimple;
---functions---
@ -1093,7 +1095,7 @@ help.saveAppLog#6f02f748 events:Vector<InputAppEvent> = 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;

Binary file not shown.

View File

@ -124,15 +124,11 @@ static ActorOwn<> get_simple_config_impl(Promise<SimpleConfig> promise, int32 sc
}
ActorOwn<> get_simple_config_azure(Promise<SimpleConfig> 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<SimpleConfig> 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<SimpleConfig> 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<SimpleConfig> 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<std::pair<string, string>>({{"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<SimpleConfig> r_simple_config, bool dummy) {
simple_config_query_.reset();
auto r_dc_options = [&]() -> Result<DcOptions> {
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<int>(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;

View File

@ -24,11 +24,9 @@ using SimpleConfig = tl_object_ptr<telegram_api::help_configSimple>;
Result<SimpleConfig> decode_config(Slice input);
ActorOwn<> get_simple_config_azure(Promise<SimpleConfig> promise, bool is_test = false, int32 scheduler_id = -1);
ActorOwn<> get_simple_config_azure(Promise<SimpleConfig> promise, bool is_test, int32 scheduler_id);
ActorOwn<> get_simple_config_google_app(Promise<SimpleConfig> promise, bool is_test = false, int32 scheduler_id = -1);
ActorOwn<> get_simple_config_google_dns(Promise<SimpleConfig> promise, bool is_test = false, int32 scheduler_id = -1);
ActorOwn<> get_simple_config_google_dns(Promise<SimpleConfig> promise, bool is_test, int32 scheduler_id);
using FullConfig = tl_object_ptr<telegram_api::config>;

View File

@ -4933,6 +4933,9 @@ void ContactsManager::on_get_user(tl_object_ptr<telegram_api::User> &&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) &&

View File

@ -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) {

View File

@ -671,6 +671,7 @@ void ConnectionCreator::request_raw_connection_by_ip(IPAddress ip_address,
Result<SocketFd> 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<SocketFd> ConnectionCreator::find_connection(const ConnectionCreator::Pro
int16 raw_dc_id = narrow_cast<int16>(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
}

View File

@ -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<const telegram_api::ipPort &>(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<const telegram_api::ipPortSecret &>(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 <class StorerT>
void store(StorerT &storer) const {
::td::store(dc_options, storer);

View File

@ -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<SimpleConfig> 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<SimpleConfig> 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<SimpleConfig> 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<SimpleConfig> 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();
}