dns.go 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  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. config CacheConfig
  30. }
  31. func NewCache(config CacheConfig) *DnsCache {
  32. cache := &DnsCache{
  33. cache: make(map[string]*entry),
  34. }
  35. go cache.cleanup()
  36. return cache
  37. }
  38. func (this *DnsCache) cleanup() {
  39. for range time.Tick(60 * time.Second) {
  40. entry2Remove := make([]*entry, 0, 128)
  41. this.RLock()
  42. for _, entry := range this.cache {
  43. if !entry.IsValid() {
  44. entry2Remove = append(entry2Remove, entry)
  45. }
  46. }
  47. this.RUnlock()
  48. for _, entry := range entry2Remove {
  49. if !entry.IsValid() {
  50. this.Lock()
  51. delete(this.cache, entry.domain)
  52. this.Unlock()
  53. }
  54. }
  55. }
  56. }
  57. func (this *DnsCache) Add(domain string, ip net.IP) {
  58. this.RLock()
  59. entry, found := this.cache[domain]
  60. this.RUnlock()
  61. if found {
  62. entry.ip = ip
  63. entry.Extend()
  64. } else {
  65. this.Lock()
  66. this.cache[domain] = newEntry(domain, ip)
  67. this.Unlock()
  68. }
  69. }
  70. func (this *DnsCache) Get(domain string) net.IP {
  71. this.RLock()
  72. entry, found := this.cache[domain]
  73. this.RUnlock()
  74. if found {
  75. return entry.ip
  76. }
  77. return nil
  78. }