github.com/btcsuite/btcd@v0.24.0/connmgr/seed.go (about)

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