/* */ #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(); i != _addrEntries.end(); ++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(); i != _addrEntries.end(); ++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(); i != _addrEntries.end(); ++i) { if((*i)._good) { return (*i)._addr; } } return A2STR::NIL; } 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; } 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_