GetHostByNameActor: Options and test

GitOrigin-RevId: afebe6e940b2048d3ef6f6368ff824443d55a909
This commit is contained in:
Arseny Smirnov 2019-01-24 17:07:11 +04:00
parent 320d660f1c
commit c07b26e45c
4 changed files with 102 additions and 35 deletions

View File

@ -1241,8 +1241,12 @@ void ConnectionCreator::start_up() {
on_proxy_changed(true); on_proxy_changed(true);
} }
get_host_by_name_actor_ = GetHostByNameActor::Options options;
create_actor_on_scheduler<GetHostByNameActor>("GetHostByNameActor", G()->get_gc_scheduler_id(), 5 * 60 - 1, 0); options.scheduler_id = G()->get_gc_scheduler_id();
options.type = GetHostByNameActor::ResolveType::All;
options.ok_timeout = 5 * 60 - 1;
options.error_timeout = 0;
get_host_by_name_actor_ = create_actor<GetHostByNameActor>("GetHostByNameActor", options);
ref_cnt_guard_ = create_reference(-1); ref_cnt_guard_ = create_reference(-1);

View File

@ -15,13 +15,13 @@ namespace td {
namespace detail { namespace detail {
class GoogleDnsResolver : public Actor { class GoogleDnsResolver : public Actor {
public: public:
GoogleDnsResolver(std::string host, GetHostByNameActor::Options options, td::Promise<td::IPAddress> promise) GoogleDnsResolver(std::string host, GetHostByNameActor::ResolveOptions options, td::Promise<td::IPAddress> promise)
: host_(std::move(host)), options_(std::move(options)), promise_(std::move(promise)) { : host_(std::move(host)), options_(std::move(options)), promise_(std::move(promise)) {
} }
private: private:
std::string host_; std::string host_;
GetHostByNameActor::Options options_; GetHostByNameActor::ResolveOptions options_;
Promise<IPAddress> promise_; Promise<IPAddress> promise_;
ActorOwn<Wget> wget_; ActorOwn<Wget> wget_;
@ -62,13 +62,13 @@ class GoogleDnsResolver : public Actor {
}; };
class NativeDnsResolver : public Actor { class NativeDnsResolver : public Actor {
public: public:
NativeDnsResolver(std::string host, GetHostByNameActor::Options options, td::Promise<td::IPAddress> promise) NativeDnsResolver(std::string host, GetHostByNameActor::ResolveOptions options, td::Promise<td::IPAddress> promise)
: host_(std::move(host)), options_(std::move(options)), promise_(std::move(promise)) { : host_(std::move(host)), options_(std::move(options)), promise_(std::move(promise)) {
} }
private: private:
std::string host_; std::string host_;
GetHostByNameActor::Options options_; GetHostByNameActor::ResolveOptions options_;
Promise<IPAddress> promise_; Promise<IPAddress> promise_;
void start_up() override { void start_up() override {
@ -87,18 +87,17 @@ class NativeDnsResolver : public Actor {
}; };
class DnsResolver : public Actor { class DnsResolver : public Actor {
public: public:
DnsResolver(std::string host, GetHostByNameActor::Options options, td::Promise<td::IPAddress> promise) DnsResolver(std::string host, GetHostByNameActor::ResolveOptions options, td::Promise<td::IPAddress> promise)
: host_(std::move(host)), options_(std::move(options)), promise_(std::move(promise)) { : host_(std::move(host)), options_(std::move(options)), promise_(std::move(promise)) {
} }
private: private:
std::string host_; std::string host_;
GetHostByNameActor::Options options_; GetHostByNameActor::ResolveOptions options_;
Promise<IPAddress> promise_; Promise<IPAddress> promise_;
ActorOwn<> query_; ActorOwn<> query_;
size_t pos_ = 0; size_t pos_ = 0;
GetHostByNameActor::Options::Type types[2] = {GetHostByNameActor::Options::Google, GetHostByNameActor::ResolveType types[2] = {GetHostByNameActor::Google, GetHostByNameActor::Native};
GetHostByNameActor::Options::Native};
void loop() override { void loop() override {
if (!query_.empty()) { if (!query_.empty()) {
@ -126,22 +125,22 @@ class DnsResolver : public Actor {
}; };
} // namespace detail } // namespace detail
ActorOwn<> GetHostByNameActor::resolve(std::string host, Options options, Promise<IPAddress> promise) { GetHostByNameActor::Options::Options() = default;
ActorOwn<> GetHostByNameActor::resolve(std::string host, ResolveOptions options, Promise<IPAddress> promise) {
switch (options.type) { switch (options.type) {
case Options::Native: case Native:
return ActorOwn<>(create_actor_on_scheduler<detail::NativeDnsResolver>( return ActorOwn<>(create_actor_on_scheduler<detail::NativeDnsResolver>(
"NativeDnsResolver", options.scheduler_id, std::move(host), options, std::move(promise))); "NativeDnsResolver", options.scheduler_id, std::move(host), options, std::move(promise)));
case Options::Google: case Google:
return ActorOwn<>(create_actor_on_scheduler<detail::GoogleDnsResolver>( return ActorOwn<>(create_actor_on_scheduler<detail::GoogleDnsResolver>(
"GoogleDnsResolver", options.scheduler_id, std::move(host), options, std::move(promise))); "GoogleDnsResolver", options.scheduler_id, std::move(host), options, std::move(promise)));
case Options::All: case All:
return ActorOwn<>(create_actor_on_scheduler<detail::DnsResolver>("DnsResolver", options.scheduler_id, return ActorOwn<>(create_actor_on_scheduler<detail::DnsResolver>("DnsResolver", options.scheduler_id,
std::move(host), options, std::move(promise))); std::move(host), options, std::move(promise)));
} }
} }
GetHostByNameActor::GetHostByNameActor(int32 ok_timeout, int32 error_timeout) GetHostByNameActor::GetHostByNameActor(Options options) : options_(options) {
: ok_timeout_(ok_timeout), error_timeout_(error_timeout) {
} }
void GetHostByNameActor::on_result(std::string host, bool prefer_ipv6, Result<IPAddress> res) { void GetHostByNameActor::on_result(std::string host, bool prefer_ipv6, Result<IPAddress> res) {
@ -150,9 +149,9 @@ void GetHostByNameActor::on_result(std::string host, bool prefer_ipv6, Result<IP
auto promises = std::move(value.promises); auto promises = std::move(value.promises);
auto end_time = td::Time::now(); auto end_time = td::Time::now();
if (res.is_ok()) { if (res.is_ok()) {
value = Value{res.move_as_ok(), end_time + ok_timeout_}; value = Value{res.move_as_ok(), end_time + options_.ok_timeout};
} else { } else {
value = Value{res.move_as_error(), end_time + error_timeout_}; value = Value{res.move_as_error(), end_time + options_.error_timeout};
} }
for (auto &promise : promises) { for (auto &promise : promises) {
promise.second.set_result(value.get_ip_port(promise.first)); promise.second.set_result(value.get_ip_port(promise.first));
@ -168,8 +167,9 @@ void GetHostByNameActor::run(string host, int port, bool prefer_ipv6, Promise<IP
value.promises.emplace_back(port, std::move(promise)); value.promises.emplace_back(port, std::move(promise));
if (value.query.empty()) { if (value.query.empty()) {
Options options; ResolveOptions options;
options.type = Options::Type::All; options.type = options_.type;
options.scheduler_id = options_.scheduler_id;
options.prefer_ipv6 = prefer_ipv6; options.prefer_ipv6 = prefer_ipv6;
value.query = value.query =
resolve(host, options, resolve(host, options,

View File

@ -17,15 +17,23 @@
namespace td { namespace td {
class GetHostByNameActor final : public td::Actor { class GetHostByNameActor final : public td::Actor {
public: public:
explicit GetHostByNameActor(int32 ok_timeout = CACHE_TIME, int32 error_timeout = ERROR_CACHE_TIME); enum ResolveType { Native, Google, All };
struct Options {
Options();
ResolveType type{Native};
int scheduler_id{-1};
int32 ok_timeout{CACHE_TIME};
int32 error_timeout{ERROR_CACHE_TIME};
};
explicit GetHostByNameActor(Options options = {});
void run(std::string host, int port, bool prefer_ipv6, td::Promise<td::IPAddress> promise); void run(std::string host, int port, bool prefer_ipv6, td::Promise<td::IPAddress> promise);
struct Options { struct ResolveOptions {
enum Type { Native, Google, All } type{Native}; ResolveType type{Native};
bool prefer_ipv6{false}; bool prefer_ipv6;
int scheduler_id{-1}; int scheduler_id{-1};
}; };
static TD_WARN_UNUSED_RESULT ActorOwn<> resolve(std::string host, Options options, Promise<IPAddress> promise); static TD_WARN_UNUSED_RESULT ActorOwn<> resolve(std::string host, ResolveOptions options, Promise<IPAddress> promise);
private: private:
struct Value { struct Value {
@ -50,8 +58,7 @@ class GetHostByNameActor final : public td::Actor {
static constexpr int32 CACHE_TIME = 60 * 29; // 29 minutes static constexpr int32 CACHE_TIME = 60 * 29; // 29 minutes
static constexpr int32 ERROR_CACHE_TIME = 60 * 5; // 5 minutes static constexpr int32 ERROR_CACHE_TIME = 60 * 5; // 5 minutes
int32 ok_timeout_; Options options_;
int32 error_timeout_;
void on_result(std::string host, bool prefer_ipv6, Result<IPAddress> res); void on_result(std::string host, bool prefer_ipv6, Result<IPAddress> res);
}; };

View File

@ -33,7 +33,7 @@ REGISTER_TESTS(mtproto);
using namespace td; using namespace td;
TEST(Mtproto, DnsOverHttps) { TEST(Mtproto, GetHostByName) {
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(WARNING)); SET_VERBOSITY_LEVEL(VERBOSITY_NAME(WARNING));
ConcurrentScheduler sched; ConcurrentScheduler sched;
int threads_n = 0; int threads_n = 0;
@ -43,7 +43,7 @@ TEST(Mtproto, DnsOverHttps) {
{ {
auto guard = sched.get_main_guard(); auto guard = sched.get_main_guard();
auto run = [&](GetHostByNameActor::Options options) { auto run = [&](GetHostByNameActor::ResolveOptions options) {
auto promise = PromiseCreator::lambda([&, num = cnt](Result<IPAddress> r_ip_address) { auto promise = PromiseCreator::lambda([&, num = cnt](Result<IPAddress> r_ip_address) {
if (r_ip_address.is_ok()) { if (r_ip_address.is_ok()) {
LOG(WARNING) << num << " " << r_ip_address.ok(); LOG(WARNING) << num << " " << r_ip_address.ok();
@ -58,12 +58,68 @@ TEST(Mtproto, DnsOverHttps) {
GetHostByNameActor::resolve("web.telegram.org", options, std::move(promise)).release(); GetHostByNameActor::resolve("web.telegram.org", options, std::move(promise)).release();
}; };
run(GetHostByNameActor::Options{GetHostByNameActor::Options::Native, true, -1}); for (auto type : {GetHostByNameActor::ResolveType::Native, GetHostByNameActor::ResolveType::Google,
run(GetHostByNameActor::Options{GetHostByNameActor::Options::Google, true, -1}); GetHostByNameActor::ResolveType::All}) {
run(GetHostByNameActor::Options{GetHostByNameActor::Options::All, true, -1}); for (auto prefer_ipv6 : {false, true}) {
run(GetHostByNameActor::Options{GetHostByNameActor::Options::Native, false, -1}); GetHostByNameActor::ResolveOptions options;
run(GetHostByNameActor::Options{GetHostByNameActor::Options::Google, false, -1}); options.type = type;
run(GetHostByNameActor::Options{GetHostByNameActor::Options::All, false, -1}); options.prefer_ipv6 = prefer_ipv6;
run(options);
}
}
}
cnt--;
sched.start();
while (sched.run_main(10)) {
// empty;
}
sched.finish();
}
TEST(Mtproto, GetHostByNameActor) {
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(WARNING));
ConcurrentScheduler sched;
int threads_n = 0;
sched.init(threads_n);
int cnt = 1;
{
auto guard = sched.get_main_guard();
auto run = [&](GetHostByNameActor::Options options) {
auto host = create_actor<GetHostByNameActor>("GetHostByNameActor", options);
auto host_id = host.get();
auto promise = PromiseCreator::lambda([&, num = cnt](Result<IPAddress> r_ip_address) {
if (r_ip_address.is_ok()) {
LOG(WARNING) << num << " " << r_ip_address.ok();
} else {
LOG(ERROR) << num << " " << r_ip_address.error();
}
if (--cnt == 0) {
Scheduler::instance()->finish();
}
});
cnt++;
send_closure(host_id, &GetHostByNameActor::run, "web.telegram.org", 443, false, std::move(promise));
promise = PromiseCreator::lambda([&, num = cnt, host = std::move(host)](Result<IPAddress> r_ip_address) {
if (r_ip_address.is_ok()) {
LOG(WARNING) << num << " " << r_ip_address.ok();
} else {
LOG(ERROR) << num << " " << r_ip_address.error();
}
if (--cnt == 0) {
Scheduler::instance()->finish();
}
});
cnt++;
send_closure(host_id, &GetHostByNameActor::run, "web.telegram.org", 443, false, std::move(promise));
};
for (auto type : {GetHostByNameActor::ResolveType::Native, GetHostByNameActor::ResolveType::Google,
GetHostByNameActor::ResolveType::All}) {
GetHostByNameActor::Options options;
options.type = type;
run(options);
}
} }
cnt--; cnt--;
sched.start(); sched.start();