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 }