Minor GetHostByName improvements.
GitOrigin-RevId: ff61c5aa543067e855a6f4a7f25c579a8c17aa87
This commit is contained in:
parent
bc838db8ec
commit
12ffc22483
@ -6,16 +6,17 @@
|
|||||||
//
|
//
|
||||||
#include "td/net/GetHostByNameActor.h"
|
#include "td/net/GetHostByNameActor.h"
|
||||||
|
|
||||||
|
#include "td/net/Wget.h"
|
||||||
|
|
||||||
|
#include "td/utils/JsonBuilder.h"
|
||||||
#include "td/utils/logging.h"
|
#include "td/utils/logging.h"
|
||||||
#include "td/utils/Time.h"
|
#include "td/utils/Time.h"
|
||||||
#include "td/utils/JsonBuilder.h"
|
|
||||||
#include "td/net/Wget.h"
|
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
class GoogleDnsResolver : public Actor {
|
class GoogleDnsResolver : public Actor {
|
||||||
public:
|
public:
|
||||||
GoogleDnsResolver(std::string host, GetHostByNameActor::ResolveOptions options, td::Promise<td::IPAddress> promise)
|
GoogleDnsResolver(std::string host, GetHostByNameActor::ResolveOptions options, Promise<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)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,13 +45,14 @@ class GoogleDnsResolver : public Actor {
|
|||||||
return Status::Error("Failed to parse dns result: not an object");
|
return Status::Error("Failed to parse dns result: not an object");
|
||||||
}
|
}
|
||||||
TRY_RESULT(answer, get_json_object_field(json_value.get_object(), "Answer", JsonValue::Type::Array, false));
|
TRY_RESULT(answer, get_json_object_field(json_value.get_object(), "Answer", JsonValue::Type::Array, false));
|
||||||
if (answer.get_array().size() == 0) {
|
auto &array = answer.get_array();
|
||||||
|
if (array.size() == 0) {
|
||||||
return Status::Error("Failed to parse dns result: Answer is an empty array");
|
return Status::Error("Failed to parse dns result: Answer is an empty array");
|
||||||
}
|
}
|
||||||
if (answer.get_array()[0].type() != JsonValue::Type::Object) {
|
if (array[0].type() != JsonValue::Type::Object) {
|
||||||
return Status::Error("Failed to parse dns result: Answer[0] is not an object");
|
return Status::Error("Failed to parse dns result: Answer[0] is not an object");
|
||||||
}
|
}
|
||||||
auto &answer_0 = answer.get_array()[0].get_object();
|
auto &answer_0 = array[0].get_object();
|
||||||
TRY_RESULT(ip_str, get_json_object_string_field(answer_0, "data", false));
|
TRY_RESULT(ip_str, get_json_object_string_field(answer_0, "data", false));
|
||||||
IPAddress ip;
|
IPAddress ip;
|
||||||
TRY_STATUS(ip.init_host_port(ip_str, 0));
|
TRY_STATUS(ip.init_host_port(ip_str, 0));
|
||||||
@ -59,9 +61,10 @@ class GoogleDnsResolver : public Actor {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class NativeDnsResolver : public Actor {
|
class NativeDnsResolver : public Actor {
|
||||||
public:
|
public:
|
||||||
NativeDnsResolver(std::string host, GetHostByNameActor::ResolveOptions options, td::Promise<td::IPAddress> promise)
|
NativeDnsResolver(std::string host, GetHostByNameActor::ResolveOptions options, Promise<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)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,9 +75,9 @@ class NativeDnsResolver : public Actor {
|
|||||||
|
|
||||||
void start_up() override {
|
void start_up() override {
|
||||||
IPAddress ip;
|
IPAddress ip;
|
||||||
auto begin_time = td::Time::now();
|
auto begin_time = Time::now();
|
||||||
auto status = ip.init_host_port(host_, 0, options_.prefer_ipv6);
|
auto status = ip.init_host_port(host_, 0, options_.prefer_ipv6);
|
||||||
auto end_time = td::Time::now();
|
auto end_time = Time::now();
|
||||||
LOG(WARNING) << "Init host = " << host_ << " in " << end_time - begin_time << " seconds to " << ip;
|
LOG(WARNING) << "Init host = " << host_ << " in " << end_time - begin_time << " seconds to " << ip;
|
||||||
if (status.is_error()) {
|
if (status.is_error()) {
|
||||||
promise_.set_error(std::move(status));
|
promise_.set_error(std::move(status));
|
||||||
@ -84,9 +87,10 @@ class NativeDnsResolver : public Actor {
|
|||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class DnsResolver : public Actor {
|
class DnsResolver : public Actor {
|
||||||
public:
|
public:
|
||||||
DnsResolver(std::string host, GetHostByNameActor::ResolveOptions options, td::Promise<td::IPAddress> promise)
|
DnsResolver(std::string host, GetHostByNameActor::ResolveOptions options, Promise<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)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,6 +130,7 @@ class DnsResolver : public Actor {
|
|||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
GetHostByNameActor::Options::Options() = default;
|
GetHostByNameActor::Options::Options() = default;
|
||||||
|
|
||||||
ActorOwn<> GetHostByNameActor::resolve(std::string host, ResolveOptions options, Promise<IPAddress> promise) {
|
ActorOwn<> GetHostByNameActor::resolve(std::string host, ResolveOptions options, Promise<IPAddress> promise) {
|
||||||
switch (options.type) {
|
switch (options.type) {
|
||||||
case Native:
|
case Native:
|
||||||
@ -137,6 +142,9 @@ ActorOwn<> GetHostByNameActor::resolve(std::string host, ResolveOptions options,
|
|||||||
case 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)));
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
return ActorOwn<>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,7 +155,7 @@ void GetHostByNameActor::on_result(std::string host, bool prefer_ipv6, Result<IP
|
|||||||
auto &value = cache_[prefer_ipv6].emplace(host, Value{{}, 0}).first->second;
|
auto &value = cache_[prefer_ipv6].emplace(host, Value{{}, 0}).first->second;
|
||||||
|
|
||||||
auto promises = std::move(value.promises);
|
auto promises = std::move(value.promises);
|
||||||
auto end_time = td::Time::now();
|
auto end_time = Time::now();
|
||||||
if (res.is_ok()) {
|
if (res.is_ok()) {
|
||||||
value = Value{res.move_as_ok(), end_time + options_.ok_timeout};
|
value = Value{res.move_as_ok(), end_time + options_.ok_timeout};
|
||||||
} else {
|
} else {
|
||||||
@ -160,7 +168,7 @@ void GetHostByNameActor::on_result(std::string host, bool prefer_ipv6, Result<IP
|
|||||||
|
|
||||||
void GetHostByNameActor::run(string host, int port, bool prefer_ipv6, Promise<IPAddress> promise) {
|
void GetHostByNameActor::run(string host, int port, bool prefer_ipv6, Promise<IPAddress> promise) {
|
||||||
auto &value = cache_[prefer_ipv6].emplace(host, Value{{}, 0}).first->second;
|
auto &value = cache_[prefer_ipv6].emplace(host, Value{{}, 0}).first->second;
|
||||||
auto begin_time = td::Time::now();
|
auto begin_time = Time::now();
|
||||||
if (value.expire_at > begin_time) {
|
if (value.expire_at > begin_time) {
|
||||||
return promise.set_result(value.get_ip_port(port));
|
return promise.set_result(value.get_ip_port(port));
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
class GetHostByNameActor final : public td::Actor {
|
|
||||||
|
class GetHostByNameActor final : public Actor {
|
||||||
public:
|
public:
|
||||||
enum ResolveType { Native, Google, All };
|
enum ResolveType { Native, Google, All };
|
||||||
struct Options {
|
struct Options {
|
||||||
@ -26,27 +27,27 @@ class GetHostByNameActor final : public td::Actor {
|
|||||||
int32 error_timeout{ERROR_CACHE_TIME};
|
int32 error_timeout{ERROR_CACHE_TIME};
|
||||||
};
|
};
|
||||||
explicit GetHostByNameActor(Options options = {});
|
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, Promise<IPAddress> promise);
|
||||||
|
|
||||||
struct ResolveOptions {
|
struct ResolveOptions {
|
||||||
ResolveType type{Native};
|
ResolveType type{Native};
|
||||||
bool prefer_ipv6;
|
bool prefer_ipv6{false};
|
||||||
int scheduler_id{-1};
|
int scheduler_id{-1};
|
||||||
};
|
};
|
||||||
static TD_WARN_UNUSED_RESULT ActorOwn<> resolve(std::string host, ResolveOptions 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 {
|
||||||
Result<td::IPAddress> ip;
|
Result<IPAddress> ip;
|
||||||
double expire_at;
|
double expire_at;
|
||||||
|
|
||||||
ActorOwn<> query;
|
ActorOwn<> query;
|
||||||
std::vector<std::pair<int, Promise<IPAddress>>> promises;
|
std::vector<std::pair<int, Promise<IPAddress>>> promises;
|
||||||
|
|
||||||
Value(Result<td::IPAddress> ip, double expire_at) : ip(std::move(ip)), expire_at(expire_at) {
|
Value(Result<IPAddress> ip, double expire_at) : ip(std::move(ip)), expire_at(expire_at) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<td::IPAddress> get_ip_port(int port) {
|
Result<IPAddress> get_ip_port(int port) {
|
||||||
auto res = ip.clone();
|
auto res = ip.clone();
|
||||||
if (res.is_ok()) {
|
if (res.is_ok()) {
|
||||||
res.ok_ref().set_port(port);
|
res.ok_ref().set_port(port);
|
||||||
|
@ -16,9 +16,9 @@
|
|||||||
#include "td/mtproto/PingConnection.h"
|
#include "td/mtproto/PingConnection.h"
|
||||||
#include "td/mtproto/RawConnection.h"
|
#include "td/mtproto/RawConnection.h"
|
||||||
|
|
||||||
|
#include "td/net/GetHostByNameActor.h"
|
||||||
#include "td/net/Socks5.h"
|
#include "td/net/Socks5.h"
|
||||||
#include "td/net/TransparentProxy.h"
|
#include "td/net/TransparentProxy.h"
|
||||||
#include "td/net/GetHostByNameActor.h"
|
|
||||||
|
|
||||||
#include "td/telegram/ConfigManager.h"
|
#include "td/telegram/ConfigManager.h"
|
||||||
#include "td/telegram/net/DcId.h"
|
#include "td/telegram/net/DcId.h"
|
||||||
@ -74,10 +74,11 @@ TEST(Mtproto, GetHostByName) {
|
|||||||
cnt--;
|
cnt--;
|
||||||
sched.start();
|
sched.start();
|
||||||
while (sched.run_main(10)) {
|
while (sched.run_main(10)) {
|
||||||
// empty;
|
// empty
|
||||||
}
|
}
|
||||||
sched.finish();
|
sched.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Mtproto, GetHostByNameActor) {
|
TEST(Mtproto, GetHostByNameActor) {
|
||||||
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(WARNING));
|
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(WARNING));
|
||||||
ConcurrentScheduler sched;
|
ConcurrentScheduler sched;
|
||||||
@ -127,7 +128,7 @@ TEST(Mtproto, GetHostByNameActor) {
|
|||||||
cnt--;
|
cnt--;
|
||||||
sched.start();
|
sched.start();
|
||||||
while (sched.run_main(10)) {
|
while (sched.run_main(10)) {
|
||||||
// empty;
|
// empty
|
||||||
}
|
}
|
||||||
sched.finish();
|
sched.finish();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user