Add prefer_ipv6 parameter tp GetHostByNameActor.

GitOrigin-RevId: 727fc30d94657399f1e49efc208b6951a7677d2f
This commit is contained in:
levlam 2018-07-01 04:12:20 +03:00
parent 9e6ddb14a7
commit 9b0a138dd1
5 changed files with 28 additions and 20 deletions

View File

@ -455,7 +455,8 @@ void ConnectionCreator::ping_proxy(int32 proxy_id, Promise<double> promise) {
return promise.set_error(Status::Error(400, "Unknown proxy identifier")); return promise.set_error(Status::Error(400, "Unknown proxy identifier"));
} }
const Proxy &proxy = it->second; const Proxy &proxy = it->second;
send_closure(get_host_by_name_actor_, &GetHostByNameActor::run, proxy.server().str(), proxy.port(), bool prefer_ipv6 = G()->shared_config().get_option_boolean("prefer_ipv6");
send_closure(get_host_by_name_actor_, &GetHostByNameActor::run, proxy.server().str(), proxy.port(), prefer_ipv6,
PromiseCreator::lambda([actor_id = actor_id(this), promise = std::move(promise), PromiseCreator::lambda([actor_id = actor_id(this), promise = std::move(promise),
proxy_id](Result<IPAddress> result) mutable { proxy_id](Result<IPAddress> result) mutable {
if (result.is_error()) { if (result.is_error()) {
@ -1230,8 +1231,9 @@ void ConnectionCreator::loop() {
if (resolve_proxy_query_token_ == 0) { if (resolve_proxy_query_token_ == 0) {
resolve_proxy_query_token_ = next_token(); resolve_proxy_query_token_ = next_token();
const Proxy &proxy = proxies_[active_proxy_id_]; const Proxy &proxy = proxies_[active_proxy_id_];
bool prefer_ipv6 = G()->shared_config().get_option_boolean("prefer_ipv6");
send_closure( send_closure(
get_host_by_name_actor_, &GetHostByNameActor::run, proxy.server().str(), proxy.port(), get_host_by_name_actor_, &GetHostByNameActor::run, proxy.server().str(), proxy.port(), prefer_ipv6,
PromiseCreator::lambda([actor_id = create_reference(resolve_proxy_query_token_)](Result<IPAddress> result) { PromiseCreator::lambda([actor_id = create_reference(resolve_proxy_query_token_)](Result<IPAddress> result) {
send_closure(std::move(actor_id), &ConnectionCreator::on_proxy_resolved, std::move(result), false); send_closure(std::move(actor_id), &ConnectionCreator::on_proxy_resolved, std::move(result), false);
})); }));

View File

@ -15,13 +15,13 @@ GetHostByNameActor::GetHostByNameActor(int32 ok_timeout, int32 error_timeout)
: ok_timeout_(ok_timeout), error_timeout_(error_timeout) { : ok_timeout_(ok_timeout), error_timeout_(error_timeout) {
} }
void GetHostByNameActor::run(std::string host, int port, td::Promise<td::IPAddress> promise) { void GetHostByNameActor::run(std::string host, int port, bool prefer_ipv6, td::Promise<td::IPAddress> promise) {
auto r_ip = load_ip(std::move(host), port); auto r_ip = load_ip(std::move(host), port, prefer_ipv6);
promise.set_result(std::move(r_ip)); promise.set_result(std::move(r_ip));
} }
Result<td::IPAddress> GetHostByNameActor::load_ip(string host, int port) { Result<td::IPAddress> GetHostByNameActor::load_ip(string host, int port, bool prefer_ipv6) {
auto &value = cache_.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 = td::Time::now();
if (value.expire_at > begin_time) { if (value.expire_at > begin_time) {
auto ip = value.ip.clone(); auto ip = value.ip.clone();
@ -33,7 +33,7 @@ Result<td::IPAddress> GetHostByNameActor::load_ip(string host, int port) {
} }
td::IPAddress ip; td::IPAddress ip;
auto status = ip.init_host_port(host, port); auto status = ip.init_host_port(host, port, prefer_ipv6);
auto end_time = td::Time::now(); auto end_time = td::Time::now();
LOG(WARNING) << "Init host = " << host << ", port = " << port << " in " << end_time - begin_time << " seconds to " LOG(WARNING) << "Init host = " << host << ", port = " << port << " in " << end_time - begin_time << " seconds to "
<< ip; << ip;

View File

@ -17,7 +17,7 @@ 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); explicit GetHostByNameActor(int32 ok_timeout = CACHE_TIME, int32 error_timeout = ERROR_CACHE_TIME);
void run(std::string host, int port, td::Promise<td::IPAddress> promise); void run(std::string host, int port, bool prefer_ipv6, td::Promise<td::IPAddress> promise);
private: private:
struct Value { struct Value {
@ -27,12 +27,13 @@ class GetHostByNameActor final : public td::Actor {
Value(Result<td::IPAddress> ip, double expire_at) : ip(std::move(ip)), expire_at(expire_at) { Value(Result<td::IPAddress> ip, double expire_at) : ip(std::move(ip)), expire_at(expire_at) {
} }
}; };
std::unordered_map<string, Value> cache_; std::unordered_map<string, Value> cache_[2];
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_; int32 ok_timeout_;
int32 error_timeout_; int32 error_timeout_;
Result<td::IPAddress> load_ip(string host, int port) TD_WARN_UNUSED_RESULT;
Result<td::IPAddress> load_ip(string host, int port, bool prefer_ipv6) TD_WARN_UNUSED_RESULT;
}; };
} // namespace td } // namespace td

View File

@ -289,12 +289,12 @@ Status IPAddress::init_ipv4_port(CSlice ipv4, int port) {
return Status::OK(); return Status::OK();
} }
Status IPAddress::init_host_port(CSlice host, int port) { Status IPAddress::init_host_port(CSlice host, int port, bool prefer_ipv6) {
auto str_port = to_string(port); auto str_port = to_string(port);
return init_host_port(host, str_port); return init_host_port(host, str_port, prefer_ipv6);
} }
Status IPAddress::init_host_port(CSlice host, CSlice port) { Status IPAddress::init_host_port(CSlice host, CSlice port, bool prefer_ipv6) {
if (host.empty()) { if (host.empty()) {
return Status::Error("Host is empty"); return Status::Error("Host is empty");
} }
@ -327,14 +327,19 @@ Status IPAddress::init_host_port(CSlice host, CSlice port) {
addrinfo *best_info = nullptr; addrinfo *best_info = nullptr;
for (auto *ptr = info; ptr != nullptr; ptr = ptr->ai_next) { for (auto *ptr = info; ptr != nullptr; ptr = ptr->ai_next) {
if (ptr->ai_family == AF_INET) { if (ptr->ai_family == AF_INET && (!prefer_ipv6 || best_info == nullptr)) {
// just use first IPv4 address // just use first IPv4 address if there is no IPv6 and it isn't preferred
best_info = ptr; best_info = ptr;
if (!prefer_ipv6) {
break; break;
} }
if (ptr->ai_family == AF_INET6 && best_info == nullptr) { }
// or first IPv6 address if there is no IPv4 if (ptr->ai_family == AF_INET6 && (prefer_ipv6 || best_info == nullptr)) {
// or first IPv6 address if there is no IPv4 and it isn't preferred
best_info = ptr; best_info = ptr;
if (prefer_ipv6) {
break;
}
} }
} }
if (best_info == nullptr) { if (best_info == nullptr) {

View File

@ -46,8 +46,8 @@ class IPAddress {
Status init_ipv6_port(CSlice ipv6, int port) TD_WARN_UNUSED_RESULT; Status init_ipv6_port(CSlice ipv6, int port) TD_WARN_UNUSED_RESULT;
Status init_ipv6_as_ipv4_port(CSlice ipv4, int port) TD_WARN_UNUSED_RESULT; Status init_ipv6_as_ipv4_port(CSlice ipv4, int port) TD_WARN_UNUSED_RESULT;
Status init_ipv4_port(CSlice ipv4, int port) TD_WARN_UNUSED_RESULT; Status init_ipv4_port(CSlice ipv4, int port) TD_WARN_UNUSED_RESULT;
Status init_host_port(CSlice host, int port) TD_WARN_UNUSED_RESULT; Status init_host_port(CSlice host, int port, bool prefer_ipv6 = false) TD_WARN_UNUSED_RESULT;
Status init_host_port(CSlice host, CSlice port) TD_WARN_UNUSED_RESULT; Status init_host_port(CSlice host, CSlice port, bool prefer_ipv6 = false) TD_WARN_UNUSED_RESULT;
Status init_host_port(CSlice host_port) TD_WARN_UNUSED_RESULT; Status init_host_port(CSlice host_port) TD_WARN_UNUSED_RESULT;
Status init_socket_address(const SocketFd &socket_fd) TD_WARN_UNUSED_RESULT; Status init_socket_address(const SocketFd &socket_fd) TD_WARN_UNUSED_RESULT;
Status init_peer_address(const SocketFd &socket_fd) TD_WARN_UNUSED_RESULT; Status init_peer_address(const SocketFd &socket_fd) TD_WARN_UNUSED_RESULT;