server.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. package dns
  2. import (
  3. "net"
  4. "sync"
  5. "time"
  6. "github.com/v2ray/v2ray-core/app"
  7. "github.com/v2ray/v2ray-core/app/dispatcher"
  8. "github.com/v2ray/v2ray-core/common/log"
  9. "github.com/miekg/dns"
  10. )
  11. const (
  12. QueryTimeout = time.Second * 8
  13. )
  14. type DomainRecord struct {
  15. A *ARecord
  16. }
  17. type CacheServer struct {
  18. sync.RWMutex
  19. space app.Space
  20. hosts map[string]net.IP
  21. records map[string]*DomainRecord
  22. servers []NameServer
  23. }
  24. func NewCacheServer(space app.Space, config *Config) *CacheServer {
  25. server := &CacheServer{
  26. records: make(map[string]*DomainRecord),
  27. servers: make([]NameServer, len(config.NameServers)),
  28. hosts: config.Hosts,
  29. }
  30. space.InitializeApplication(func() error {
  31. if !space.HasApp(dispatcher.APP_ID) {
  32. log.Error("DNS: Dispatcher is not found in the space.")
  33. return app.ErrMissingApplication
  34. }
  35. dispatcher := space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher)
  36. for idx, ns := range config.NameServers {
  37. if ns.Address().Family().IsDomain() && ns.Address().Domain() == "localhost" {
  38. server.servers[idx] = &LocalNameServer{}
  39. } else {
  40. server.servers[idx] = NewUDPNameServer(ns, dispatcher)
  41. }
  42. }
  43. if len(config.NameServers) == 0 {
  44. server.servers = append(server.servers, &LocalNameServer{})
  45. }
  46. return nil
  47. })
  48. return server
  49. }
  50. func (this *CacheServer) Release() {
  51. }
  52. //@Private
  53. func (this *CacheServer) GetCached(domain string) []net.IP {
  54. this.RLock()
  55. defer this.RUnlock()
  56. if record, found := this.records[domain]; found && record.A.Expire.After(time.Now()) {
  57. return record.A.IPs
  58. }
  59. return nil
  60. }
  61. func (this *CacheServer) Get(domain string) []net.IP {
  62. if ip, found := this.hosts[domain]; found {
  63. return []net.IP{ip}
  64. }
  65. domain = dns.Fqdn(domain)
  66. ips := this.GetCached(domain)
  67. if ips != nil {
  68. return ips
  69. }
  70. for _, server := range this.servers {
  71. response := server.QueryA(domain)
  72. select {
  73. case a, open := <-response:
  74. if !open || a == nil {
  75. continue
  76. }
  77. this.Lock()
  78. this.records[domain] = &DomainRecord{
  79. A: a,
  80. }
  81. this.Unlock()
  82. log.Debug("DNS: Returning ", len(a.IPs), " IPs for domain ", domain)
  83. return a.IPs
  84. case <-time.After(QueryTimeout):
  85. }
  86. }
  87. log.Debug("DNS: Returning nil for domain ", domain)
  88. return nil
  89. }