/* */ #ifndef _D_DNS_CACHE_H_ #define _D_DNS_CACHE_H_ #include "common.h" #include #include #include #include #include "A2STR.h" namespace aria2 { class DNSCache { private: struct AddrEntry { std::string addr_; bool good_; AddrEntry(const std::string& addr):addr_(addr), good_(true) {} }; struct CacheEntry { std::string hostname_; uint16_t port_; std::vector addrEntries_; CacheEntry (const std::string& hostname, uint16_t port): hostname_(hostname), port_(port) {} void add(const std::string& addr) { addrEntries_.push_back(AddrEntry(addr)); } std::vector::iterator find(const std::string& addr) { for(std::vector::iterator i = addrEntries_.begin(), eoi = addrEntries_.end(); i != eoi; ++i) { if((*i).addr_ == addr) { return i; } } return addrEntries_.end(); } std::vector::const_iterator find(const std::string& addr) const { for(std::vector::const_iterator i = addrEntries_.begin(), eoi = addrEntries_.end(); i != eoi; ++i) { if((*i).addr_ == addr) { return i; } } return addrEntries_.end(); } bool contains(const std::string& addr) const { return find(addr) != addrEntries_.end(); } const std::string& getGoodAddr() const { for(std::vector::const_iterator i = addrEntries_.begin(), eoi = addrEntries_.end(); i != eoi; ++i) { if((*i).good_) { return (*i).addr_; } } return A2STR::NIL; } template void getAllGoodAddrs(OutputIterator out) const { for(std::vector::const_iterator i = addrEntries_.begin(), eoi = addrEntries_.end(); i != eoi; ++i) { if((*i).good_) { *out++ = (*i).addr_; } } } void markBad(const std::string& addr) { std::vector::iterator i = find(addr); if(i != addrEntries_.end()) { (*i).good_ = false; } } bool operator<(const CacheEntry& e) const { int r = hostname_.compare(e.hostname_); if(r != 0) { return r < 0; } return port_ < e.port_; } bool operator==(const CacheEntry& e) const { return hostname_ == e.hostname_ && port_ == e.port_; } }; std::deque entries_; public: const std::string& find(const std::string& hostname, uint16_t port) const { CacheEntry target(hostname, port); std::deque::const_iterator i = std::lower_bound(entries_.begin(), entries_.end(), target); if(i != entries_.end() && (*i) == target) { return (*i).getGoodAddr(); } return A2STR::NIL; } template void findAll (OutputIterator out, const std::string& hostname, uint16_t port) const { CacheEntry target(hostname, port); std::deque::const_iterator i = std::lower_bound(entries_.begin(), entries_.end(), target); if(i != entries_.end() && (*i) == target) { (*i).getAllGoodAddrs(out); } } void put (const std::string& hostname, const std::string& ipaddr, uint16_t port) { CacheEntry target(hostname, port); std::deque::iterator i = std::lower_bound(entries_.begin(), entries_.end(), target); if(i == entries_.end() || !((*i) == target)) { target.add(ipaddr); entries_.insert(i, target); } else { if(!(*i).contains(ipaddr)) { (*i).add(ipaddr); } } } void markBad (const std::string& hostname, const std::string& ipaddr, uint16_t port) { CacheEntry target(hostname, port); std::deque::iterator i = std::lower_bound(entries_.begin(), entries_.end(), target); if(i != entries_.end() && (*i) == target) { (*i).markBad(ipaddr); } } void remove(const std::string& hostname, uint16_t port) { CacheEntry target(hostname, port); std::deque::iterator i = std::lower_bound(entries_.begin(), entries_.end(), target); if(i != entries_.end() && (*i) == target) { entries_.erase(i); } } }; } // namespace aria2 #endif // _D_DNS_CACHE_H_