func (dht *IpfsDHT) handleAddProvider(p peer.Peer, pmes *pb.Message) (*pb.Message, error) { key := u.Key(pmes.GetKey()) log.Debugf("%s adding %s as a provider for '%s'\n", dht.self, p, peer.ID(key)) // add provider should use the address given in the message for _, pb := range pmes.GetProviderPeers() { pid := peer.ID(pb.GetId()) if pid.Equal(p.ID()) { addr, err := pb.Address() if err != nil { log.Errorf("provider %s error with address %s", p, *pb.Addr) continue } log.Infof("received provider %s %s for %s", p, addr, key) p.AddAddress(addr) dht.providers.AddProvider(key, p) } else { log.Errorf("handleAddProvider received provider %s from %s", pid, p) } } return pmes, nil // send back same msg as confirmation. }
func TestClientFindProviders(t *testing.T) { peer := peer.WithIDString("42") rs := VirtualRoutingServer() client := rs.Client(peer) k := u.Key("hello") err := client.Provide(context.Background(), k) if err != nil { t.Fatal(err) } max := 100 providersFromHashTable := rs.Providers(k) isInHT := false for _, p := range providersFromHashTable { if bytes.Equal(p.ID(), peer.ID()) { isInHT = true } } if !isInHT { t.Fatal("Despite client providing key, peer wasn't in hash table as a provider") } providersFromClient := client.FindProvidersAsync(context.Background(), u.Key("hello"), max) isInClient := false for p := range providersFromClient { if bytes.Equal(p.ID(), peer.ID()) { isInClient = true } } if !isInClient { t.Fatal("Despite client providing key, client didn't receive peer when finding providers") } }
func (dht *IpfsDHT) handleFindPeer(p peer.Peer, pmes *pb.Message) (*pb.Message, error) { resp := pb.NewMessage(pmes.GetType(), "", pmes.GetClusterLevel()) var closest []peer.Peer // if looking for self... special case where we send it on CloserPeers. if peer.ID(pmes.GetKey()).Equal(dht.self.ID()) { closest = []peer.Peer{dht.self} } else { closest = dht.betterPeersToQuery(pmes, CloserPeerCount) } if closest == nil { log.Errorf("handleFindPeer: could not find anything.") return resp, nil } var withAddresses []peer.Peer for _, p := range closest { if len(p.Addresses()) > 0 { withAddresses = append(withAddresses, p) } } for _, p := range withAddresses { log.Debugf("handleFindPeer: sending back '%s'", p) } resp.CloserPeers = pb.PeersToPBPeers(withAddresses) return resp, nil }
func newPeer(t *testing.T, id string) peer.Peer { mh, err := mh.FromHexString(id) if err != nil { t.Error(err) return nil } return peer.WithID(peer.ID(mh)) }
func TestProviderManager(t *testing.T) { ctx := context.Background() mid := peer.ID("testing") p := NewProviderManager(ctx, mid) a := u.Key("test") p.AddProvider(a, peer.WithIDString("testingprovider")) resp := p.GetProviders(a) if len(resp) != 1 { t.Fatal("Could not retrieve provider.") } p.Close() }
// Bootstrap builds up list of peers by requesting random peer IDs func (dht *IpfsDHT) Bootstrap(ctx context.Context) { id := make([]byte, 16) rand.Read(id) p, err := dht.FindPeer(ctx, peer.ID(id)) if err != nil { log.Error("Bootstrap peer error: %s", err) } err = dht.dialer.DialPeer(ctx, p) if err != nil { log.Errorf("Bootstrap peer error: %s", err) } }
func TestSetAndGet(t *testing.T) { pid := peer.ID([]byte("the peer id")) p := peer.WithID(pid) k := u.Key("42") rs := VirtualRoutingServer() err := rs.Announce(p, k) if err != nil { t.Fatal(err) } providers := rs.Providers(k) if len(providers) != 1 { t.Fatal("should be one") } for _, elem := range providers { if bytes.Equal(elem.ID(), pid) { return } } t.Fatal("ID should have matched") }
// peerFromInfo returns a peer using info in the protobuf peer struct // to lookup or create a peer func (dht *IpfsDHT) peerFromInfo(pbp *pb.Message_Peer) (peer.Peer, error) { id := peer.ID(pbp.GetId()) // bail out if it's ourselves //TODO(jbenet) not sure this should be an error _here_ if id.Equal(dht.self.ID()) { return nil, errors.New("found self") } p, err := dht.getPeer(id) if err != nil { return nil, err } maddr, err := pbp.Address() if err != nil { return nil, err } p.AddAddress(maddr) return p, nil }
func (dht *IpfsDHT) verifyRecord(r *pb.Record) error { // First, validate the signature p, err := dht.peerstore.Get(peer.ID(r.GetAuthor())) if err != nil { return err } k := u.Key(r.GetKey()) blob := bytes.Join([][]byte{[]byte(k), r.GetValue(), []byte(r.GetAuthor())}, []byte{}) ok, err := p.PubKey().Verify(blob, r.GetSignature()) if err != nil { log.Error("Signature verify failed.") return err } if !ok { return ErrBadRecord } // Now, check validity func parts := strings.Split(r.GetKey(), "/") if len(parts) < 3 { log.Errorf("Record had bad key: %s", u.Key(r.GetKey())) return ErrBadRecord } fnc, ok := dht.Validators[parts[1]] if !ok { log.Errorf("Unrecognized key prefix: %s", parts[1]) return ErrInvalidRecordType } return fnc(u.Key(r.GetKey()), r.GetValue()) }
func initIdentity(cfg *config.Identity, peers peer.Peerstore, online bool) (peer.Peer, error) { if cfg.PeerID == "" { return nil, debugerror.New("Identity was not set in config (was ipfs init run?)") } if len(cfg.PeerID) == 0 { return nil, debugerror.New("No peer ID in config! (was ipfs init run?)") } // get peer from peerstore (so it is constructed there) id := peer.ID(b58.Decode(cfg.PeerID)) self, err := peers.Get(id) if err != nil { return nil, err } self.SetType(peer.Local) self, err = peers.Add(self) if err != nil { return nil, err } self.SetVersions(handshake.ClientVersion, handshake.IpfsVersion.String()) // when not online, don't need to parse private keys (yet) if online { skb, err := base64.StdEncoding.DecodeString(cfg.PrivKey) if err != nil { return nil, err } if err := self.LoadAndVerifyKeyPair(skb); err != nil { return nil, err } } return self, nil }
// Looks for race conditions in table operations. For a more 'certain' // test, increase the loop counter from 1000 to a much higher number // and set GOMAXPROCS above 1 func TestTableMultithreaded(t *testing.T) { local := peer.ID("localPeer") tab := NewRoutingTable(20, ConvertPeerID(local), time.Hour) var peers []peer.Peer for i := 0; i < 500; i++ { peers = append(peers, tu.RandPeer()) } done := make(chan struct{}) go func() { for i := 0; i < 1000; i++ { n := rand.Intn(len(peers)) tab.Update(peers[n]) } done <- struct{}{} }() go func() { for i := 0; i < 1000; i++ { n := rand.Intn(len(peers)) tab.Update(peers[n]) } done <- struct{}{} }() go func() { for i := 0; i < 1000; i++ { n := rand.Intn(len(peers)) tab.Find(peers[n].ID()) } done <- struct{}{} }() <-done <-done <-done }
func newPeerTime(t time.Time) peer.Peer { s := fmt.Sprintf("hmmm time: %v", t) h := u.Hash([]byte(s)) return peer.WithID(peer.ID(h)) }
Arguments: []cmds.Argument{ cmds.StringArg("peerid", false, false, "peer.ID of node to look up"), }, Run: func(req cmds.Request) (interface{}, error) { node, err := req.Context().GetNode() if err != nil { return nil, err } if len(req.Arguments()) == 0 { return printPeer(node.Identity) } pid := req.Arguments()[0] id := peer.ID(b58.Decode(pid)) if len(id) == 0 { return nil, cmds.ClientError("Invalid peer id") } ctx, _ := context.WithTimeout(context.TODO(), time.Second*5) if node.Routing == nil { return nil, errors.New(offlineIdErrorMessage) } p, err := node.Routing.FindPeer(ctx, id) if err == kb.ErrLookupFailure { return nil, errors.New(offlineIdErrorMessage) } if err != nil { return nil, err
// 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 }
func RandPeer() peer.Peer { id := make([]byte, 16) crand.Read(id) mhid := u.Hash(id) return peer.WithID(peer.ID(mhid)) }