seed.go raw

   1  package connmgr
   2  
   3  import (
   4  	"fmt"
   5  	"github.com/p9c/p9/pkg/chaincfg"
   6  	mrand "math/rand"
   7  	"net"
   8  	"strconv"
   9  	"time"
  10  	
  11  	"github.com/p9c/p9/pkg/wire"
  12  )
  13  
  14  const (
  15  	// These constants are used by the DNS seed code to pick a random last seen time.
  16  	secondsIn3Days int32 = 24 * 60 * 60 * 3
  17  	secondsIn4Days int32 = 24 * 60 * 60 * 4
  18  )
  19  
  20  // OnSeed is the signature of the callback function which is invoked when DNS seeding is succesful
  21  type OnSeed func(addrs []*wire.NetAddress)
  22  
  23  // LookupFunc is the signature of the DNS lookup function.
  24  type LookupFunc func(string) ([]net.IP, error)
  25  
  26  // SeedFromDNS uses DNS seeding to populate the address manager with peers.
  27  func SeedFromDNS(
  28  	chainParams *chaincfg.Params, reqServices wire.ServiceFlag,
  29  	lookupFn LookupFunc, seedFn OnSeed,
  30  ) {
  31  	for _, dnsseed := range chainParams.DNSSeeds {
  32  		var host string
  33  		if !dnsseed.HasFiltering || reqServices == wire.SFNodeNetwork {
  34  			host = dnsseed.Host
  35  		} else {
  36  			host = fmt.Sprintf("x%x.%s", uint64(reqServices), dnsseed.Host)
  37  		}
  38  		go func(host string) {
  39  			randSource := mrand.New(mrand.NewSource(time.Now().UnixNano()))
  40  			seedpeers, e := lookupFn(host)
  41  			if e != nil {
  42  				E.F("DNS routeable failed on seed %s: %v", host, e)
  43  				return
  44  			}
  45  			numPeers := len(seedpeers)
  46  			D.F("%d addresses found from DNS seed %s", numPeers, host)
  47  			if numPeers == 0 {
  48  				return
  49  			}
  50  			addresses := make([]*wire.NetAddress, len(seedpeers))
  51  			// if this errors then we have *real* problems
  52  			intPort, _ := strconv.Atoi(chainParams.DefaultPort)
  53  			for i, peer := range seedpeers {
  54  				addresses[i] = wire.NewNetAddressTimestamp(
  55  					// bitcoind seeds with addresses from a time randomly
  56  					// selected between 3 and 7 days ago.
  57  					time.Now().Add(
  58  						-1*time.Second*time.Duration(
  59  							secondsIn3Days+
  60  								randSource.Int31n(secondsIn4Days),
  61  						),
  62  					),
  63  					0, peer, uint16(intPort),
  64  				)
  65  			}
  66  			seedFn(addresses)
  67  		}(host)
  68  	}
  69  }
  70