github.com/turingchain2020/turingchain@v1.1.21/system/p2p/dht/discovery.go (about)

     1  package dht
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"time"
     8  
     9  	"github.com/turingchain2020/turingchain/system/p2p/dht/extension"
    10  	p2pty "github.com/turingchain2020/turingchain/system/p2p/dht/types"
    11  	"github.com/turingchain2020/turingchain/types"
    12  	"github.com/libp2p/go-libp2p-core/host"
    13  	"github.com/libp2p/go-libp2p-core/peer"
    14  	"github.com/libp2p/go-libp2p-core/protocol"
    15  	discovery "github.com/libp2p/go-libp2p-discovery"
    16  	dht "github.com/libp2p/go-libp2p-kad-dht"
    17  	opts "github.com/libp2p/go-libp2p-kad-dht/opts"
    18  	kbt "github.com/libp2p/go-libp2p-kbucket"
    19  )
    20  
    21  const (
    22  	// Deprecated 老版本的协议,仅做兼容,TODO 后面升级后移除
    23  	classicDhtProtoID = "/ipfs/kad/%s/1.0.0/%d"
    24  	dhtProtoID        = "/%s-%d/kad/1.0.0" //title-channel/kad/1.0.0
    25  )
    26  
    27  // Discovery dht discovery
    28  type Discovery struct {
    29  	ctx              context.Context
    30  	kademliaDHT      *dht.IpfsDHT
    31  	RoutingDiscovery *discovery.RoutingDiscovery
    32  	mdnsService      *extension.MDNS
    33  	subCfg           *p2pty.P2PSubConfig
    34  	bootstraps       []peer.AddrInfo
    35  	host             host.Host
    36  }
    37  
    38  // InitDhtDiscovery init dht discovery
    39  func InitDhtDiscovery(ctx context.Context, host host.Host, peersInfo []peer.AddrInfo, chainCfg *types.TuringchainConfig, subCfg *p2pty.P2PSubConfig) *Discovery {
    40  
    41  	// Make the DHT,不同的ID进入不同的网络。
    42  	//如果不修改DHTProto 则有可能会连入IPFS网络,dhtproto=/ipfs/kad/1.0.0
    43  	d := new(Discovery)
    44  	opt := opts.Protocols(protocol.ID(fmt.Sprintf(dhtProtoID, chainCfg.GetTitle(), subCfg.Channel)),
    45  		protocol.ID(fmt.Sprintf(classicDhtProtoID, chainCfg.GetTitle(), subCfg.Channel)))
    46  	kademliaDHT, err := dht.New(ctx, host, opt, opts.BucketSize(dht.KValue*2))
    47  	if err != nil {
    48  		panic(err)
    49  	}
    50  	d.kademliaDHT = kademliaDHT
    51  	d.ctx = ctx
    52  	d.bootstraps = peersInfo
    53  	d.subCfg = subCfg
    54  	d.host = host
    55  	return d
    56  
    57  }
    58  
    59  //Start  the dht
    60  func (d *Discovery) Start() {
    61  	//连接内置种子,以及addrbook存储的节点
    62  	initInnerPeers(d.host, d.bootstraps, d.subCfg)
    63  	// Bootstrap the DHT. In the default configuration, this spawns a Background
    64  	// thread that will refresh the peer table every five minutes.
    65  	if err := d.kademliaDHT.Bootstrap(d.ctx); err != nil {
    66  		log.Error("Bootstrap", "err", err.Error())
    67  	}
    68  	d.RoutingDiscovery = discovery.NewRoutingDiscovery(d.kademliaDHT)
    69  }
    70  
    71  //Close close the dht
    72  func (d *Discovery) Close() error {
    73  	if d.kademliaDHT != nil {
    74  		return d.kademliaDHT.Close()
    75  	}
    76  	d.CloseFindLANPeers()
    77  	return nil
    78  }
    79  
    80  // FindLANPeers 查找局域网内的其他节点
    81  func (d *Discovery) FindLANPeers(host host.Host, serviceTag string) (<-chan peer.AddrInfo, error) {
    82  	mdns, err := extension.NewMDNS(d.ctx, host, serviceTag)
    83  	if err != nil {
    84  		return nil, err
    85  	}
    86  	d.mdnsService = mdns
    87  	return d.mdnsService.PeerChan(), nil
    88  }
    89  
    90  // CloseFindLANPeers close peers
    91  func (d *Discovery) CloseFindLANPeers() {
    92  	if d.mdnsService != nil {
    93  		d.mdnsService.Service.Close()
    94  	}
    95  }
    96  
    97  // FindSpecialPeer 根据指定的peerID ,查找指定的peer,
    98  func (d *Discovery) FindSpecialPeer(pid peer.ID) (*peer.AddrInfo, error) {
    99  	if d.kademliaDHT == nil {
   100  		return nil, errors.New("empty ptr")
   101  	}
   102  	ctx := context.Background()
   103  	pctx, cancel := context.WithTimeout(ctx, 30*time.Second)
   104  	defer cancel()
   105  
   106  	peerInfo, err := d.kademliaDHT.FindPeer(pctx, pid)
   107  	if err != nil {
   108  		return nil, err
   109  	}
   110  	return &peerInfo, nil
   111  }
   112  
   113  // FindLocalPeer 根据pid 查找当前DHT内部的peer信息
   114  func (d *Discovery) FindLocalPeer(pid peer.ID) peer.AddrInfo {
   115  	if d.kademliaDHT == nil {
   116  		return peer.AddrInfo{}
   117  	}
   118  	return d.kademliaDHT.FindLocal(pid)
   119  }
   120  
   121  // FindLocalPeers find local peers
   122  func (d *Discovery) FindLocalPeers(pids []peer.ID) []peer.AddrInfo {
   123  	var addrinfos []peer.AddrInfo
   124  	for _, pid := range pids {
   125  		addrinfos = append(addrinfos, d.FindLocalPeer(pid))
   126  	}
   127  	return addrinfos
   128  }
   129  
   130  // FindPeersConnectedToPeer 获取连接指定的peerId的peers信息,查找连接PID=A的所有节点
   131  func (d *Discovery) FindPeersConnectedToPeer(pid peer.ID) (<-chan *peer.AddrInfo, error) {
   132  	if d.kademliaDHT == nil {
   133  		return nil, errors.New("empty ptr")
   134  
   135  	}
   136  	pctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
   137  	defer cancel()
   138  	return d.kademliaDHT.FindPeersConnectedToPeer(pctx, pid)
   139  }
   140  
   141  // FindNearestPeers find nearest peers
   142  func (d *Discovery) FindNearestPeers(pid peer.ID, count int) []peer.ID {
   143  	if d.kademliaDHT == nil {
   144  		return nil
   145  	}
   146  
   147  	return d.kademliaDHT.RoutingTable().NearestPeers(kbt.ConvertPeerID(pid), count)
   148  }
   149  
   150  // RoutingTable get routing table
   151  func (d *Discovery) RoutingTable() *kbt.RoutingTable {
   152  	return d.kademliaDHT.RoutingTable()
   153  }
   154  
   155  // ListPeers routingTable 路由表的节点信息
   156  func (d *Discovery) ListPeers() []peer.ID {
   157  	if d.kademliaDHT == nil {
   158  		return nil
   159  	}
   160  	return d.kademliaDHT.RoutingTable().ListPeers()
   161  }
   162  
   163  // Update update peer
   164  func (d *Discovery) Update(pid peer.ID) error {
   165  	_, err := d.kademliaDHT.RoutingTable().Update(pid)
   166  	return err
   167  }
   168  
   169  // Remove remove peer
   170  func (d *Discovery) Remove(pid peer.ID) {
   171  	if d.kademliaDHT == nil {
   172  		return
   173  	}
   174  	d.kademliaDHT.RoutingTable().Remove(pid)
   175  
   176  }