resolver.go 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. package vnet
  2. import (
  3. "errors"
  4. "fmt"
  5. "net"
  6. "sync"
  7. "github.com/pion/logging"
  8. )
  9. var (
  10. errHostnameEmpty = errors.New("host name must not be empty")
  11. errFailedtoParseIPAddr = errors.New("failed to parse IP address")
  12. )
  13. type resolverConfig struct {
  14. LoggerFactory logging.LoggerFactory
  15. }
  16. type resolver struct {
  17. parent *resolver // read-only
  18. hosts map[string]net.IP // requires mutex
  19. mutex sync.RWMutex // thread-safe
  20. log logging.LeveledLogger // read-only
  21. }
  22. func newResolver(config *resolverConfig) *resolver {
  23. r := &resolver{
  24. hosts: map[string]net.IP{},
  25. log: config.LoggerFactory.NewLogger("vnet"),
  26. }
  27. if err := r.addHost("localhost", "127.0.0.1"); err != nil {
  28. r.log.Warn("failed to add localhost to resolver")
  29. }
  30. return r
  31. }
  32. func (r *resolver) setParent(parent *resolver) {
  33. r.mutex.Lock()
  34. defer r.mutex.Unlock()
  35. r.parent = parent
  36. }
  37. func (r *resolver) addHost(name string, ipAddr string) error {
  38. r.mutex.Lock()
  39. defer r.mutex.Unlock()
  40. if len(name) == 0 {
  41. return errHostnameEmpty
  42. }
  43. ip := net.ParseIP(ipAddr)
  44. if ip == nil {
  45. return fmt.Errorf("%w \"%s\"", errFailedtoParseIPAddr, ipAddr)
  46. }
  47. r.hosts[name] = ip
  48. return nil
  49. }
  50. func (r *resolver) lookUp(hostName string) (net.IP, error) {
  51. ip := func() net.IP {
  52. r.mutex.RLock()
  53. defer r.mutex.RUnlock()
  54. if ip2, ok := r.hosts[hostName]; ok {
  55. return ip2
  56. }
  57. return nil
  58. }()
  59. if ip != nil {
  60. return ip, nil
  61. }
  62. // mutex must be unlocked before calling into parent resolver
  63. if r.parent != nil {
  64. return r.parent.lookUp(hostName)
  65. }
  66. return nil, &net.DNSError{
  67. Err: "host not found",
  68. Name: hostName,
  69. Server: "vnet resolver",
  70. IsTimeout: false,
  71. IsTemporary: false,
  72. }
  73. }