// NewDHT creates a new DHT object with the given peer as the 'local' host func NewDHT(ctx context.Context, p peer.Peer, ps peer.Peerstore, dialer inet.Dialer, sender inet.Sender, dstore ds.Datastore) *IpfsDHT { dht := new(IpfsDHT) dht.dialer = dialer dht.sender = sender dht.datastore = dstore dht.self = p dht.peerstore = ps dht.ContextCloser = ctxc.NewContextCloser(ctx, nil) dht.providers = NewProviderManager(dht.Context(), p.ID()) dht.AddCloserChild(dht.providers) dht.routingTables = make([]*kb.RoutingTable, 3) dht.routingTables[0] = kb.NewRoutingTable(20, kb.ConvertPeerID(p.ID()), time.Millisecond*1000) dht.routingTables[1] = kb.NewRoutingTable(20, kb.ConvertPeerID(p.ID()), time.Millisecond*1000) dht.routingTables[2] = kb.NewRoutingTable(20, kb.ConvertPeerID(p.ID()), time.Hour) dht.birth = time.Now() dht.Validators = make(map[string]ValidatorFunc) dht.Validators["pk"] = ValidatePublicKeyRecord if doPinging { dht.Children().Add(1) go dht.PingRoutine(time.Second * 10) } return dht }
// Find specific Peer // FindPeer searches for a peer with given ID. func (dht *IpfsDHT) FindPeer(ctx context.Context, id peer.ID) (peer.Peer, error) { // Check if were already connected to them p, _ := dht.FindLocal(id) if p != nil { return p, nil } routeLevel := 0 closest := dht.routingTables[routeLevel].NearestPeers(kb.ConvertPeerID(id), AlphaValue) if closest == nil || len(closest) == 0 { return nil, kb.ErrLookupFailure } // Sanity... for _, p := range closest { if p.ID().Equal(id) { log.Error("Found target peer in list of closest peers...") return p, nil } } // setup the Query query := newQuery(u.Key(id), dht.dialer, func(ctx context.Context, p peer.Peer) (*dhtQueryResult, error) { pmes, err := dht.findPeerSingle(ctx, p, id, routeLevel) if err != nil { return nil, err } closer := pmes.GetCloserPeers() var clpeers []peer.Peer for _, pbp := range closer { np, err := dht.getPeer(peer.ID(pbp.GetId())) if err != nil { log.Warningf("Received invalid peer from query: %v", err) continue } ma, err := pbp.Address() if err != nil { log.Warning("Received peer with bad or missing address.") continue } np.AddAddress(ma) if pbp.GetId() == string(id) { return &dhtQueryResult{ peer: np, success: true, }, nil } clpeers = append(clpeers, np) } return &dhtQueryResult{closerPeers: clpeers}, nil }) // run it! result, err := query.Run(ctx, closest) if err != nil { return nil, err } log.Debugf("FindPeer %v %v", id, result.success) if result.peer == nil { return nil, routing.ErrNotFound } return result.peer, nil }