OSDN Git Service

Merge pull request #201 from Bytom/v0.1
[bytom/vapor.git] / p2p / discover / dht / dns_seeds.go
diff --git a/p2p/discover/dht/dns_seeds.go b/p2p/discover/dht/dns_seeds.go
new file mode 100644 (file)
index 0000000..d50584f
--- /dev/null
@@ -0,0 +1,66 @@
+package dht
+
+import (
+       "net"
+       "time"
+
+       log "github.com/sirupsen/logrus"
+
+       "github.com/vapor/consensus"
+       "github.com/vapor/errors"
+)
+
+var (
+       errInvalidIP     = errors.New("invalid ip address")
+       errDNSTimeout    = errors.New("get dns seed timeout")
+       errDNSSeedsEmpty = errors.New("dns seeds is empty")
+
+       dnsTimeout = 5 * time.Second
+)
+
+// QueryDNSSeeds Query the DNS seeds.
+func QueryDNSSeeds(lookupHost func(host string) (addrs []string, err error)) ([]string, error) {
+       if len(consensus.ActiveNetParams.DNSSeeds) == 0 {
+               return nil, errDNSSeedsEmpty
+       }
+
+       resultCh := make(chan *[]string, 1)
+       for _, dnsSeed := range consensus.ActiveNetParams.DNSSeeds {
+               go queryDNSSeeds(lookupHost, resultCh, dnsSeed, consensus.ActiveNetParams.DefaultPort)
+       }
+
+       select {
+       case result := <-resultCh:
+               return *result, nil
+       case <-time.After(dnsTimeout):
+               return nil, errDNSTimeout
+       }
+}
+
+func queryDNSSeeds(lookupHost func(host string) (addrs []string, err error), resultCh chan *[]string, dnsSeed, port string) {
+       var seeds []string
+
+       //TODO add proxy
+       addrs, err := lookupHost(dnsSeed)
+       if err != nil {
+               log.WithFields(log.Fields{"module": logModule, "err": err, "dnsSeed": dnsSeed}).Error("fail on look up host")
+               return
+       }
+
+       for _, addr := range addrs {
+               if ip := net.ParseIP(addr); ip == nil {
+                       log.WithFields(log.Fields{"module": logModule, "err": errInvalidIP, "dnsSeed": dnsSeed}).Error("fail on parse IP")
+                       return
+               }
+
+               seeds = append(seeds, net.JoinHostPort(addr, port))
+       }
+       if len(seeds) == 0 {
+               return
+       }
+       //if channel is full, drop it
+       select {
+       case resultCh <- &seeds:
+       default:
+       }
+}