server.go 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  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/miekg/dns"
  9. )
  10. const (
  11. QueryTimeout = time.Second * 2
  12. )
  13. type DomainRecord struct {
  14. A *ARecord
  15. }
  16. type CacheServer struct {
  17. sync.RWMutex
  18. records map[string]*DomainRecord
  19. servers []NameServer
  20. }
  21. func NewCacheServer(space app.Space, config *Config) *CacheServer {
  22. server := &CacheServer{
  23. records: make(map[string]*DomainRecord),
  24. servers: make([]NameServer, len(config.NameServers)),
  25. }
  26. dispatcher := space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher)
  27. for idx, ns := range config.NameServers {
  28. if ns.Address().IsDomain() && ns.Address().Domain() == "localhost" {
  29. server.servers[idx] = &LocalNameServer{}
  30. } else {
  31. server.servers[idx] = NewUDPNameServer(ns, dispatcher)
  32. }
  33. }
  34. return server
  35. }
  36. //@Private
  37. func (this *CacheServer) GetCached(domain string) []net.IP {
  38. this.RLock()
  39. defer this.RUnlock()
  40. if record, found := this.records[domain]; found && record.A.Expire.After(time.Now()) {
  41. return record.A.IPs
  42. }
  43. return nil
  44. }
  45. func (this *CacheServer) Get(context app.Context, domain string) []net.IP {
  46. domain = dns.Fqdn(domain)
  47. ips := this.GetCached(domain)
  48. if ips != nil {
  49. return ips
  50. }
  51. for _, server := range this.servers {
  52. response := server.QueryA(domain)
  53. select {
  54. case a := <-response:
  55. this.Lock()
  56. this.records[domain] = &DomainRecord{
  57. A: a,
  58. }
  59. this.Unlock()
  60. return a.IPs
  61. case <-time.Tick(QueryTimeout):
  62. }
  63. }
  64. return nil
  65. }