Fix usage of HttpDate in ConfigRecoverer.

GitOrigin-RevId: 17007d6b0afe58a0479d3d596bc4463548a26930
This commit is contained in:
levlam 2019-07-11 23:32:45 +03:00
parent d69251faba
commit db8539d9df
4 changed files with 41 additions and 32 deletions

View File

@ -58,30 +58,32 @@
namespace td { namespace td {
int VERBOSITY_NAME(config_recoverer) = VERBOSITY_NAME(INFO); int VERBOSITY_NAME(config_recoverer) = VERBOSITY_NAME(INFO);
Result<int64> HttpDate::to_unix_time(int32 year, int32 month, int32 day, int32 hour, int32 minute, int32 second) {
int64 res = 0; Result<int32> HttpDate::to_unix_time(int32 year, int32 month, int32 day, int32 hour, int32 minute, int32 second) {
if (year < 1970 || year > 2037) { if (year < 1970 || year > 2037) {
return td::Status::Error("invalid year"); return Status::Error("Invalid year");
} }
if (month < 1 || month > 12) { if (month < 1 || month > 12) {
return td::Status::Error("invalid month"); return Status::Error("Invalid month");
} }
if (day < 1 || day > days_in_month(year, month)) { if (day < 1 || day > days_in_month(year, month)) {
return td::Status::Error("invalid day"); return Status::Error("Invalid day");
} }
if (hour < 0 || hour > 24) { // is hour == 24 possible? if (hour < 0 || hour >= 24) {
return td::Status::Error("invalid hour"); return Status::Error("Invalid hour");
} }
if (minute < 0 || minute > 60) { if (minute < 0 || minute >= 60) {
return td::Status::Error("invalid minute"); return Status::Error("Invalid minute");
} }
if (second < 0 || second > 60) { if (second < 0 || second > 60) {
return td::Status::Error("invalid second"); return Status::Error("Invalid second");
} }
for (int y = 1970; y < year; y++) {
int32 res = 0;
for (int32 y = 1970; y < year; y++) {
res += (is_leap(y) + 365) * seconds_in_day(); res += (is_leap(y) + 365) * seconds_in_day();
} }
for (int m = 1; m < month; m++) { for (int32 m = 1; m < month; m++) {
res += days_in_month(year, m) * seconds_in_day(); res += days_in_month(year, m) * seconds_in_day();
} }
res += (day - 1) * seconds_in_day(); res += (day - 1) * seconds_in_day();
@ -91,11 +93,12 @@ Result<int64> HttpDate::to_unix_time(int32 year, int32 month, int32 day, int32 h
return res; return res;
} }
Result<int64> HttpDate::parse_http_date(std::string slice) { Result<int32> HttpDate::parse_http_date(std::string slice) {
td::Parser p(slice); Parser p(slice);
p.read_till(','); // ignore week day p.read_till(','); // ignore week day
p.skip(','); p.skip(',');
p.skip_whitespaces(); p.skip_whitespaces();
p.skip_nofail('0');
TRY_RESULT(day, to_integer_safe<int32>(p.read_word())); TRY_RESULT(day, to_integer_safe<int32>(p.read_word()));
auto month_name = p.read_word(); auto month_name = p.read_word();
to_lower_inplace(month_name); to_lower_inplace(month_name);
@ -115,7 +118,7 @@ Result<int64> HttpDate::parse_http_date(std::string slice) {
return Status::Error("timezone must be GMT"); return Status::Error("timezone must be GMT");
} }
Slice month_names[12] = {"jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"}; static Slice month_names[12] = {"jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"};
int month = 0; int month = 0;
@ -134,7 +137,7 @@ Result<int64> HttpDate::parse_http_date(std::string slice) {
} }
Result<SimpleConfig> decode_config(Slice input) { Result<SimpleConfig> decode_config(Slice input) {
static auto rsa = td::RSA::from_pem( static auto rsa = RSA::from_pem(
"-----BEGIN RSA PUBLIC KEY-----\n" "-----BEGIN RSA PUBLIC KEY-----\n"
"MIIBCgKCAQEAyr+18Rex2ohtVy8sroGP\n" "MIIBCgKCAQEAyr+18Rex2ohtVy8sroGP\n"
"BwXD3DOoKCSpjDqYoXgCqB7ioln4eDCFfOBUlfXUEvM/fnKCpF46VkAftlb4VuPD\n" "BwXD3DOoKCSpjDqYoXgCqB7ioln4eDCFfOBUlfXUEvM/fnKCpF46VkAftlb4VuPD\n"
@ -207,7 +210,7 @@ static ActorOwn<> get_simple_config_impl(Promise<SimpleConfigResult> promise, in
promise.set_result([&]() -> Result<SimpleConfigResult> { promise.set_result([&]() -> Result<SimpleConfigResult> {
TRY_RESULT(http_query, std::move(r_query)); TRY_RESULT(http_query, std::move(r_query));
SimpleConfigResult res; SimpleConfigResult res;
res.r_http_date = HttpDate::parse_http_date(http_query->get_arg("date").str()); res.r_http_date = HttpDate::parse_http_date(http_query->get_header("date").str());
res.r_config = decode_config(http_query->content_); res.r_config = decode_config(http_query->content_);
return res; return res;
}()); }());
@ -243,10 +246,9 @@ ActorOwn<> get_simple_config_google_dns(Promise<SimpleConfigResult> promise, con
PromiseCreator::lambda([promise = std::move(promise)](Result<unique_ptr<HttpQuery>> r_query) mutable { PromiseCreator::lambda([promise = std::move(promise)](Result<unique_ptr<HttpQuery>> r_query) mutable {
promise.set_result([&]() -> Result<SimpleConfigResult> { promise.set_result([&]() -> Result<SimpleConfigResult> {
TRY_RESULT(http_query, std::move(r_query)); TRY_RESULT(http_query, std::move(r_query));
LOG(ERROR) << *http_query;
SimpleConfigResult res; SimpleConfigResult res;
res.r_http_date = HttpDate::parse_http_date(http_query->get_arg("date").str()); res.r_http_date = HttpDate::parse_http_date(http_query->get_header("date").str());
res.r_config = [&]() -> Result<SimpleConfig> { res.r_config = [&]() -> Result<SimpleConfig> {
TRY_RESULT(json, json_decode(http_query->content_)); TRY_RESULT(json, json_decode(http_query->content_));
if (json.type() != JsonValue::Type::Object) { if (json.type() != JsonValue::Type::Object) {

View File

@ -30,7 +30,7 @@ class ConfigShared;
using SimpleConfig = tl_object_ptr<telegram_api::help_configSimple>; using SimpleConfig = tl_object_ptr<telegram_api::help_configSimple>;
struct SimpleConfigResult { struct SimpleConfigResult {
Result<SimpleConfig> r_config; Result<SimpleConfig> r_config;
Result<int64> r_http_date; Result<int32> r_http_date;
}; };
Result<SimpleConfig> decode_config(Slice input); Result<SimpleConfig> decode_config(Slice input);
@ -42,19 +42,20 @@ ActorOwn<> get_simple_config_google_dns(Promise<SimpleConfigResult> promise, con
bool is_test, int32 scheduler_id); bool is_test, int32 scheduler_id);
class HttpDate { class HttpDate {
public: static bool is_leap(int32 year) {
static bool is_leap(int year) {
return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0); return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
} }
static int32 days_in_month(int year, int month) { static int32 days_in_month(int32 year, int32 month) {
static int cnt[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; static int cnt[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
return cnt[month - 1] + (month == 2 && is_leap(year)); return cnt[month - 1] + (month == 2 && is_leap(year));
} }
static int64 seconds_in_day() { static int32 seconds_in_day() {
return 24 * 60 * 60; return 24 * 60 * 60;
} }
static Result<int64> to_unix_time(int32 year, int32 month, int32 day, int32 hour, int32 minute, int32 second);
static Result<int64> parse_http_date(std::string slice); public:
static Result<int32> to_unix_time(int32 year, int32 month, int32 day, int32 hour, int32 minute, int32 second);
static Result<int32> parse_http_date(std::string slice);
}; };
using FullConfig = tl_object_ptr<telegram_api::config>; using FullConfig = tl_object_ptr<telegram_api::config>;

View File

@ -753,7 +753,7 @@ void ConnectionCreator::request_raw_connection_by_ip(IPAddress ip_address, mtpro
}; };
auto token = next_token(); auto token = next_token();
auto callback = td::make_unique<Callback>(std::move(socket_fd_promise)); auto callback = td::make_unique<Callback>(std::move(socket_fd_promise));
LOG(INFO) << "Tls in ConfigRecoverer " << ip_address << " " << transport_type.secret.get_domain() << " " LOG(INFO) << "TLS in ConfigRecoverer " << ip_address << " " << transport_type.secret.get_domain() << " "
<< transport_type.secret.emulate_tls() << " " << transport_type.secret.get_proxy_secret().size() << transport_type.secret.emulate_tls() << " " << transport_type.secret.get_proxy_secret().size()
<< transport_type.secret.get_encoded_secret(); << transport_type.secret.get_encoded_secret();
children_[token] = {false, create_actor<mtproto::TlsInit>( children_[token] = {false, create_actor<mtproto::TlsInit>(
@ -987,7 +987,7 @@ void ConnectionCreator::client_loop(ClientInfo &client) {
bool was_connected_{false}; bool was_connected_{false};
unique_ptr<detail::StatsCallback> stats_callback_; unique_ptr<detail::StatsCallback> stats_callback_;
}; };
LOG(INFO) << "Start " << (proxy.use_socks5_proxy() ? "Socks5" : (proxy.use_http_tcp_proxy() ? "HTTP" : "Tls")) LOG(INFO) << "Start " << (proxy.use_socks5_proxy() ? "Socks5" : (proxy.use_http_tcp_proxy() ? "HTTP" : "TLS"))
<< ": " << extra.debug_str; << ": " << extra.debug_str;
auto token = next_token(); auto token = next_token();
auto callback = td::make_unique<Callback>(std::move(promise), std::move(stats_callback)); auto callback = td::make_unique<Callback>(std::move(promise), std::move(stats_callback));

View File

@ -144,11 +144,17 @@ TEST(Mtproto, config) {
auto guard = sched.get_main_guard(); auto guard = sched.get_main_guard();
auto run = [&](auto &func, bool is_test) { auto run = [&](auto &func, bool is_test) {
auto promise = PromiseCreator::lambda([&, num = cnt](Result<SimpleConfig> r_simple_config) { auto promise = PromiseCreator::lambda([&, num = cnt](Result<SimpleConfigResult> r_simple_config_result) {
if (r_simple_config.is_ok()) { if (r_simple_config_result.is_ok()) {
LOG(WARNING) << num << " " << to_string(r_simple_config.ok()); auto simple_config_result = r_simple_config_result.move_as_ok();
auto date = simple_config_result.r_http_date.is_ok()
? to_string(simple_config_result.r_http_date.ok())
: (PSTRING() << simple_config_result.r_http_date.error());
auto config = simple_config_result.r_config.is_ok() ? to_string(simple_config_result.r_config.ok())
: (PSTRING() << simple_config_result.r_config.error());
LOG(ERROR) << num << " " << date << " " << config;
} else { } else {
LOG(ERROR) << num << " " << r_simple_config.error(); LOG(ERROR) << num << " " << r_simple_config_result.error();
} }
if (--cnt == 0) { if (--cnt == 0) {
Scheduler::instance()->finish(); Scheduler::instance()->finish();