dns.go 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. package dns
  2. import (
  3. "net"
  4. "sync"
  5. "time"
  6. )
  7. type entry struct {
  8. domain string
  9. ip net.IP
  10. validUntil time.Time
  11. }
  12. func newEntry(domain string, ip net.IP) *entry {
  13. this := &entry{
  14. domain: domain,
  15. ip: ip,
  16. }
  17. this.Extend()
  18. return this
  19. }
  20. func (this *entry) IsValid() bool {
  21. return this.validUntil.After(time.Now())
  22. }
  23. func (this *entry) Extend() {
  24. this.validUntil = time.Now().Add(time.Hour)
  25. }
  26. type DnsCache struct {
  27. sync.RWMutex
  28. cache map[string]*entry
  29. }
  30. func NewCache() *DnsCache {
  31. cache := &DnsCache{
  32. cache: make(map[string]*entry),
  33. }
  34. go cache.cleanup()
  35. return cache
  36. }
  37. func (this *DnsCache) cleanup() {
  38. for range time.Tick(10 * time.Second) {
  39. entry2Remove := make([]*entry, 0, 128)
  40. this.RLock()
  41. for _, entry := range this.cache {
  42. if !entry.IsValid() {
  43. entry2Remove = append(entry2Remove, entry)
  44. }
  45. }
  46. this.RUnlock()
  47. for _, entry := range entry2Remove {
  48. if !entry.IsValid() {
  49. this.Lock()
  50. delete(this.cache, entry.domain)
  51. this.Unlock()
  52. }
  53. }
  54. }
  55. }
  56. func (this *DnsCache) Add(domain string, ip net.IP) {
  57. this.RLock()
  58. entry, found := this.cache[domain]
  59. this.RUnlock()
  60. if found {
  61. entry.ip = ip
  62. entry.Extend()
  63. } else {
  64. this.Lock()
  65. this.cache[domain] = newEntry(domain, ip)
  66. this.Unlock()
  67. }
  68. }
  69. func (this *DnsCache) Get(domain string) net.IP {
  70. this.RLock()
  71. entry, found := this.cache[domain]
  72. this.RUnlock()
  73. if found {
  74. return entry.ip
  75. }
  76. return nil
  77. }