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"));
}
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),
proxy_id](Result<IPAddress> result) mutable {
if (result.is_error()) {
@ -1230,8 +1231,9 @@ void ConnectionCreator::loop() {
if (resolve_proxy_query_token_ == 0) {
resolve_proxy_query_token_ = next_token();
const Proxy &proxy = proxies_[active_proxy_id_];
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(),
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) {
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) {
}
void GetHostByNameActor::run(std::string host, int port, td::Promise<td::IPAddress> promise) {
auto r_ip = load_ip(std::move(host), port);
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, prefer_ipv6);
promise.set_result(std::move(r_ip));
}
Result<td::IPAddress> GetHostByNameActor::load_ip(string host, int port) {
auto &value = cache_.emplace(host, Value{{}, 0}).first->second;
Result<td::IPAddress> GetHostByNameActor::load_ip(string host, int port, bool prefer_ipv6) {
auto &value = cache_[prefer_ipv6].emplace(host, Value{{}, 0}).first->second;
auto begin_time = td::Time::now();
if (value.expire_at > begin_time) {
auto ip = value.ip.clone();
@ -33,7 +33,7 @@ Result<td::IPAddress> GetHostByNameActor::load_ip(string host, int port) {
}
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();
LOG(WARNING) << "Init host = " << host << ", port = " << port << " in " << end_time - begin_time << " seconds to "
<< ip;

View File

@ -17,7 +17,7 @@ namespace td {
class GetHostByNameActor final : public td::Actor {
public:
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:
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) {
}
};
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 ERROR_CACHE_TIME = 60 * 5; // 5 minutes
int32 ok_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

View File

@ -289,12 +289,12 @@ Status IPAddress::init_ipv4_port(CSlice ipv4, int port) {
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);
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()) {
return Status::Error("Host is empty");
}
@ -327,14 +327,19 @@ Status IPAddress::init_host_port(CSlice host, CSlice port) {
addrinfo *best_info = nullptr;
for (auto *ptr = info; ptr != nullptr; ptr = ptr->ai_next) {
if (ptr->ai_family == AF_INET) {
// just use first IPv4 address
if (ptr->ai_family == AF_INET && (!prefer_ipv6 || best_info == nullptr)) {
// just use first IPv4 address if there is no IPv6 and it isn't preferred
best_info = ptr;
break;
if (!prefer_ipv6) {
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;
if (prefer_ipv6) {
break;
}
}
}
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_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_host_port(CSlice host, int port) TD_WARN_UNUSED_RESULT;
Status init_host_port(CSlice host, CSlice 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, bool prefer_ipv6 = false) 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_peer_address(const SocketFd &socket_fd) TD_WARN_UNUSED_RESULT;