dns.go 1.5 KB

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