diff --git a/src/client/WFDnsClient.cc b/src/client/WFDnsClient.cc index 151ac910..2e4ec3ed 100644 --- a/src/client/WFDnsClient.cc +++ b/src/client/WFDnsClient.cc @@ -100,7 +100,7 @@ struct DnsStatus size_t next_server; // next server to try size_t last_server; // last server to try size_t next_domain; // next search domain to try - int attempt_left; + int attempts_left; int try_origin_state; }; @@ -163,8 +163,8 @@ static void __callback_internal(WFDnsTask *task, const DnsParams& params, if (try_next_server) { if (s.last_server == s.next_server) - s.attempt_left--; - if (s.attempt_left <= 0) + s.attempts_left--; + if (s.attempts_left <= 0) return; s.next_server = (s.next_server + 1) % p->uris.size(); @@ -247,7 +247,7 @@ WFDnsTask *WFDnsClient::create_dns_task(const std::string& name, status.origin_name = name; status.next_domain = 0; - status.attempt_left = p->attempts; + status.attempts_left = p->attempts; status.try_origin_state = DNS_STATUS_TRY_ORIGIN_FIRST; if (!name.empty() && name.back() == '.') diff --git a/src/manager/DnsCache.h b/src/manager/DnsCache.h index fa719dae..0ccf081e 100644 --- a/src/manager/DnsCache.h +++ b/src/manager/DnsCache.h @@ -27,6 +27,7 @@ #include #include #include "LRUCache.h" +#include "DnsUtil.h" #define GET_TYPE_TTL 0 #define GET_TYPE_CONFIDENT 1 @@ -38,15 +39,6 @@ struct DnsCacheValue int64_t expire_time; }; -class ValueDeleter -{ -public: - void operator() (const DnsCacheValue& value) const - { - freeaddrinfo(value.addrinfo); - } -}; - // RAII: NO. Release handle by user // Thread safety: YES // MUST call release when handle no longer used @@ -56,6 +48,20 @@ public: using HostPort = std::pair; using DnsHandle = LRUHandle; + class ValueDeleter + { + public: + void operator() (const DnsCacheValue& value) const + { + struct addrinfo *ai = value.addrinfo; + + if (ai && (ai->ai_flags | AI_PASSIVE)) + freeaddrinfo(ai); + else + DnsUtil::freeaddrinfo(ai); + } + }; + public: // release handle by get/put void release(DnsHandle *handle) diff --git a/src/manager/WFGlobal.cc b/src/manager/WFGlobal.cc index ca3f7c19..5f727445 100644 --- a/src/manager/WFGlobal.cc +++ b/src/manager/WFGlobal.cc @@ -627,7 +627,8 @@ static inline const char *__try_options(const char *p, const char *q, return NULL; } -static void __set_options(const char *p, int& ndots, int& attempt, bool& rotate) +static void __set_options(const char *p, + int *ndots, int *attempts, bool *rotate) { const char *start; const char *opt; @@ -648,17 +649,17 @@ static void __set_options(const char *p, int& ndots, int& attempt, bool& rotate) break; if ((opt = __try_options(start, p, "ndots:")) != NULL) - ndots = atoi(opt); + *ndots = atoi(opt); else if ((opt = __try_options(start, p, "attempts:")) != NULL) - attempt = atoi(opt); + *attempts = atoi(opt); else if ((opt = __try_options(start, p, "rotate")) != NULL) - rotate = true; + *rotate = true; } } static int __parse_resolv_conf(const char *filename, std::string& url, std::string& search_list, - int& ndots, int& attempts, bool& rotate) + int *ndots, int *attempts, bool *rotate) { size_t bufsize = 0; void *line = NULL; @@ -713,8 +714,8 @@ private: std::string search; client = new WFDnsClient; - if (__parse_resolv_conf(path, url, search, ndots, attempts, - rotate) >= 0) + if (__parse_resolv_conf(path, url, search, &ndots, &attempts, + &rotate) >= 0) { if (client->init(url, search, ndots, attempts, rotate) >= 0) return; diff --git a/src/nameservice/WFDnsResolver.cc b/src/nameservice/WFDnsResolver.cc index 6ec137f9..bf9cb374 100644 --- a/src/nameservice/WFDnsResolver.cc +++ b/src/nameservice/WFDnsResolver.cc @@ -238,6 +238,16 @@ static int __readaddrinfo(const char *filename, return ret < 0 ? EAI_SYSTEM : EAI_NONAME; } +// Add AI_PASSIVE to point that this addrinfo is alloced by getaddrinfo +static void __add_passive_flags(struct addrinfo *ai) +{ + while (ai) + { + ai->ai_flags |= AI_PASSIVE; + ai = ai->ai_next; + } +} + static ThreadDnsTask *__create_thread_dns_task(const std::string& host, unsigned short port, thread_dns_callback_t callback) @@ -277,7 +287,7 @@ public: private: virtual void dispatch(); virtual SubTask *done(); - void dns_callback(ThreadDnsTask *dns_task); + void thread_dns_callback(ThreadDnsTask *dns_task); void dns_single_callback(WFDnsTask *dns_task); void dns_parallel_callback(const ParallelWork *pwork); void dns_callback_internal(DnsOutput *dns_task, @@ -373,6 +383,7 @@ void WFResolverTask::dispatch() dns_in.reset(host_, port_); DnsRoutine::run(&dns_in, &dns_out); + __add_passive_flags((struct addrinfo *)dns_out.get_addrinfo()); dns_callback_internal(&dns_out, (unsigned int)-1, (unsigned int)-1); insert_dns_ = false; } @@ -391,6 +402,7 @@ void WFResolverTask::dispatch() { DnsOutput out; DnsRoutine::create(&out, ret, ai); + __add_passive_flags((struct addrinfo *)out.get_addrinfo()); dns_callback_internal(&out, dns_ttl_default_, dns_ttl_min_); insert_dns_ = false; } @@ -398,7 +410,7 @@ void WFResolverTask::dispatch() if (insert_dns_ && !client) { - auto&& cb = std::bind(&WFResolverTask::dns_callback, + auto&& cb = std::bind(&WFResolverTask::thread_dns_callback, this, std::placeholders::_1); ThreadDnsTask *dns_task = __create_thread_dns_task(host_, port_, @@ -595,10 +607,14 @@ void WFResolverTask::dns_parallel_callback(const ParallelWork *pwork) delete this; } -void WFResolverTask::dns_callback(ThreadDnsTask *dns_task) +void WFResolverTask::thread_dns_callback(ThreadDnsTask *dns_task) { if (dns_task->get_state() == WFT_STATE_SUCCESS) - dns_callback_internal(dns_task->get_output(), dns_ttl_default_, dns_ttl_min_); + { + DnsOutput *out = dns_task->get_output(); + __add_passive_flags((struct addrinfo *)out->get_addrinfo()); + dns_callback_internal(out, dns_ttl_default_, dns_ttl_min_); + } else { this->state = dns_task->get_state(); diff --git a/src/protocol/DnsUtil.cc b/src/protocol/DnsUtil.cc index f34ac51b..7faf9c32 100644 --- a/src/protocol/DnsUtil.cc +++ b/src/protocol/DnsUtil.cc @@ -124,3 +124,16 @@ int DnsUtil::getaddrinfo(const protocol::DnsResponse *resp, return 0; } + +void DnsUtil::freeaddrinfo(struct addrinfo *ai) +{ + struct addrinfo *p; + + while (ai != NULL) + { + p = ai; + ai = ai->ai_next; + free(p->ai_canonname); + free(p); + } +} diff --git a/src/protocol/DnsUtil.h b/src/protocol/DnsUtil.h index 4fa696a4..08def0fb 100644 --- a/src/protocol/DnsUtil.h +++ b/src/protocol/DnsUtil.h @@ -32,6 +32,7 @@ public: static int getaddrinfo(const protocol::DnsResponse *resp, unsigned short port, struct addrinfo **res); + static void freeaddrinfo(struct addrinfo *ai); }; class DnsResultCursor