/* */ #ifndef _D_DNS_CACHE_H_ #define _D_DNS_CACHE_H_ #include "common.h" #include #include #include #include "A2STR.h" namespace aria2 { class DNSCache { private: struct CacheEntry { std::string _hostname; std::string _addr; uint16_t _port; bool _good; CacheEntry (const std::string& hostname, const std::string& addr, uint16_t port): _hostname(hostname), _addr(addr), _port(port), _good(true) {} void markBad() { _good = false; } bool operator<(const CacheEntry& e) const { int r = _hostname.compare(e._hostname); if(r != 0) { return r < 0; } if(_port != e._port) { return _port < e._port; } return _addr < e._addr; } bool operator==(const CacheEntry& e) const { return _hostname == e._hostname && _addr == e._addr && _port == e._port; } }; std::deque _entries; std::deque::iterator findEntry (const std::string& hostname, const std::string& ipaddr, uint16_t port) { CacheEntry target(hostname, ipaddr, port); std::deque::iterator i = std::lower_bound(_entries.begin(), _entries.end(), target); if(i != _entries.end() && (*i) == target) { return i; } else { return _entries.end(); } } public: const std::string& find(const std::string& hostname, uint16_t port) const { CacheEntry target(hostname, A2STR::NIL, port); std::deque::const_iterator i = std::lower_bound(_entries.begin(), _entries.end(), target); for(; i != _entries.end() && (*i)._hostname == hostname && (*i)._port == port; ++i) { if((*i)._good) { return (*i)._addr; } } return A2STR::NIL; } void put (const std::string& hostname, const std::string& ipaddr, uint16_t port) { CacheEntry target(hostname, ipaddr, port); std::deque::iterator i = std::lower_bound(_entries.begin(), _entries.end(), target); if(i == _entries.end() || !((*i) == target)) { _entries.insert(i, target); } } void markBad (const std::string& hostname, const std::string& ipaddr, uint16_t port) { std::deque::iterator i = findEntry(hostname, ipaddr, port); if(i != _entries.end()) { (*i).markBad(); } } void remove(const std::string& hostname, uint16_t port) { CacheEntry target(hostname, A2STR::NIL, port); std::deque::iterator i = std::lower_bound(_entries.begin(), _entries.end(), target); for(; i != _entries.end() && (*i)._hostname == hostname && (*i)._port == port;) { i = _entries.erase(i); } } }; } // namespace aria2 #endif // _D_DNS_CACHE_H_