func TestNetAddress(t *testing.T) { tcp, err := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/1234") if err != nil { t.Error(err) return } udp, err := ma.NewMultiaddr("/ip4/127.0.0.1/udp/2345") if err != nil { t.Error(err) return } mh, err := mh.FromHexString("11140beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33") if err != nil { t.Error(err) return } p := Peer{ID: ID(mh)} p.AddAddress(tcp) p.AddAddress(udp) tcp2 := p.NetAddress("tcp") if tcp2 != tcp { t.Error("NetAddress lookup failed", tcp, tcp2) } udp2 := p.NetAddress("udp") if udp2 != udp { t.Error("NetAddress lookup failed", udp, udp2) } }
func TestValueGetSet(t *testing.T) { u.Debug = false addrA, err := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/1235") if err != nil { t.Fatal(err) } addrB, err := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/5679") if err != nil { t.Fatal(err) } peerA := makePeer(addrA) peerB := makePeer(addrB) neta := swarm.NewSwarm(peerA) err = neta.Listen() if err != nil { t.Fatal(err) } dhtA := NewDHT(peerA, neta, ds.NewMapDatastore()) netb := swarm.NewSwarm(peerB) err = netb.Listen() if err != nil { t.Fatal(err) } dhtB := NewDHT(peerB, netb, ds.NewMapDatastore()) dhtA.Start() dhtB.Start() errsa := dhtA.network.GetErrChan() errsb := dhtB.network.GetErrChan() go func() { select { case err := <-errsa: t.Fatal(err) case err := <-errsb: t.Fatal(err) } }() _, err = dhtA.Connect(addrB) if err != nil { t.Fatal(err) } dhtA.PutValue("hello", []byte("world")) val, err := dhtA.GetValue("hello", time.Second*2) if err != nil { t.Fatal(err) } if string(val) != "world" { t.Fatalf("Expected 'world' got '%s'", string(val)) } }
// TODO: Im not certain on this implementation, we get a list of peers/providers // from someone what do we do with it? Connect to each of them? randomly pick // one to get the value from? Or just connect to one at a time until we get a // successful connection and request the value from it? func (dht *IpfsDHT) getFromPeerList(key u.Key, timeout time.Duration, peerlist []*PBDHTMessage_PBPeer, level int) ([]byte, error) { for _, pinfo := range peerlist { p, _ := dht.Find(peer.ID(pinfo.GetId())) if p == nil { maddr, err := ma.NewMultiaddr(pinfo.GetAddr()) if err != nil { u.PErr("getValue error: %s\n", err) continue } p, err = dht.network.GetConnection(peer.ID(pinfo.GetId()), maddr) if err != nil { u.PErr("getValue error: %s\n", err) continue } } pmes, err := dht.getValueSingle(p, key, timeout, level) if err != nil { u.DErr("getFromPeers error: %s\n", err) continue } dht.providers.AddProvider(key, p) // Make sure it was a successful get if pmes.GetSuccess() && pmes.Value != nil { return pmes.GetValue(), nil } } return nil, u.ErrNotFound }
// Handle getting ID from this peer and adding it into the map func (s *Swarm) handleNewConn(nconn net.Conn) { p := new(peer.Peer) conn := &Conn{ Peer: p, Addr: nil, Conn: nconn, } newConnChans(conn) sin, sout, err := ident.Handshake(s.local, p, conn.Incoming.MsgChan, conn.Outgoing.MsgChan) if err != nil { u.PErr("%v\n", err.Error()) conn.Close() return } // Get address to contact remote peer from addr := <-sin maddr, err := ma.NewMultiaddr(string(addr)) if err != nil { u.PErr("Got invalid address from peer.") s.Error(err) return } p.AddAddress(maddr) conn.secIn = sin conn.secOut = sout err = s.StartConn(conn) if err != nil { s.Error(err) } }
func (dht *IpfsDHT) peerFromInfo(pbp *PBDHTMessage_PBPeer) (*peer.Peer, error) { maddr, err := ma.NewMultiaddr(pbp.GetAddr()) if err != nil { return nil, err } return dht.network.GetConnection(peer.ID(pbp.GetId()), maddr) }
func TestPing(t *testing.T) { u.Debug = true addrA, err := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/2222") if err != nil { t.Fatal(err) } addrB, err := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/5678") if err != nil { t.Fatal(err) } peerA := makePeer(addrA) peerB := makePeer(addrB) neta := swarm.NewSwarm(peerA) err = neta.Listen() if err != nil { t.Fatal(err) } dhtA := NewDHT(peerA, neta, ds.NewMapDatastore()) netb := swarm.NewSwarm(peerB) err = netb.Listen() if err != nil { t.Fatal(err) } dhtB := NewDHT(peerB, netb, ds.NewMapDatastore()) dhtA.Start() dhtB.Start() _, err = dhtA.Connect(addrB) if err != nil { t.Fatal(err) } //Test that we can ping the node err = dhtA.Ping(peerB, time.Second*2) if err != nil { t.Fatal(err) } dhtA.Halt() dhtB.Halt() }
// FindProviders searches for peers who can provide the value for given key. func (dht *IpfsDHT) FindProviders(key u.Key, timeout time.Duration) ([]*peer.Peer, error) { ll := startNewRPC("FindProviders") defer func() { ll.EndLog() ll.Print() }() u.DOut("Find providers for: '%s'\n", key) p := dht.routingTables[0].NearestPeer(kb.ConvertKey(key)) if p == nil { return nil, kb.ErrLookupFailure } for level := 0; level < len(dht.routingTables); { pmes, err := dht.findProvidersSingle(p, key, level, timeout) if err != nil { return nil, err } if pmes.GetSuccess() { u.DOut("Got providers back from findProviders call!\n") provs := dht.addPeerList(key, pmes.GetPeers()) ll.Success = true return provs, nil } u.DOut("Didnt get providers, just closer peers.\n") closer := pmes.GetPeers() if len(closer) == 0 { level++ continue } if peer.ID(closer[0].GetId()).Equal(dht.self.ID) { u.DOut("Got myself back as a closer peer.") return nil, u.ErrNotFound } maddr, err := ma.NewMultiaddr(closer[0].GetAddr()) if err != nil { // ??? Move up route level??? panic("not yet implemented") } np, err := dht.network.GetConnection(peer.ID(closer[0].GetId()), maddr) if err != nil { u.PErr("[%s] Failed to connect to: %s\n", dht.self.ID.Pretty(), closer[0].GetAddr()) level++ continue } p = np } return nil, u.ErrNotFound }
func setupPeer(id string, addr string) (*peer.Peer, error) { tcp, err := ma.NewMultiaddr(addr) if err != nil { return nil, err } mh, err := mh.FromHexString(id) if err != nil { return nil, err } p := &peer.Peer{ID: peer.ID(mh)} p.AddAddress(tcp) return p, nil }
func initConnections(cfg *config.Config, peers *peer.Map, route *dht.IpfsDHT) { for _, sp := range cfg.Peers { maddr, err := ma.NewMultiaddr(sp.Address) if err != nil { u.PErr("error: %v\n", err) continue } p, err := route.Connect(maddr) if err != nil { u.PErr("Bootstrapping error: %v\n", err) } (*peers)[p.Key()] = p } }
// FindPeer searches for a peer with given ID. func (dht *IpfsDHT) FindPeer(id peer.ID, timeout time.Duration) (*peer.Peer, error) { // Check if were already connected to them p, _ := dht.Find(id) if p != nil { return p, nil } routeLevel := 0 p = dht.routingTables[routeLevel].NearestPeer(kb.ConvertPeerID(id)) if p == nil { return nil, kb.ErrLookupFailure } if p.ID.Equal(id) { return p, nil } for routeLevel < len(dht.routingTables) { pmes, err := dht.findPeerSingle(p, id, timeout, routeLevel) plist := pmes.GetPeers() if plist == nil || len(plist) == 0 { routeLevel++ continue } found := plist[0] addr, err := ma.NewMultiaddr(found.GetAddr()) if err != nil { return nil, err } nxtPeer, err := dht.network.GetConnection(peer.ID(found.GetId()), addr) if err != nil { return nil, err } if pmes.GetSuccess() { if !id.Equal(nxtPeer.ID) { return nil, errors.New("got back invalid peer from 'successful' response") } return nxtPeer, nil } p = nxtPeer } return nil, u.ErrNotFound }
func setupDHTS(n int, t *testing.T) ([]*ma.Multiaddr, []*peer.Peer, []*IpfsDHT) { var addrs []*ma.Multiaddr for i := 0; i < 4; i++ { a, err := ma.NewMultiaddr(fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", 5000+i)) if err != nil { t.Fatal(err) } addrs = append(addrs, a) } var peers []*peer.Peer for i := 0; i < 4; i++ { p := new(peer.Peer) p.AddAddress(addrs[i]) sk, pk, err := ci.GenerateKeyPair(ci.RSA, 512) if err != nil { panic(err) } p.PubKey = pk p.PrivKey = sk id, err := identify.IDFromPubKey(pk) if err != nil { panic(err) } p.ID = id peers = append(peers, p) } var dhts []*IpfsDHT for i := 0; i < 4; i++ { net := swarm.NewSwarm(peers[i]) err := net.Listen() if err != nil { t.Fatal(err) } d := NewDHT(peers[i], net, ds.NewMapDatastore()) dhts = append(dhts, d) d.Start() } return addrs, peers, dhts }
func (dht *IpfsDHT) getValueOrPeers(p *peer.Peer, key u.Key, timeout time.Duration, level int) ([]byte, []*peer.Peer, error) { pmes, err := dht.getValueSingle(p, key, timeout, level) if err != nil { return nil, nil, err } if pmes.GetSuccess() { if pmes.Value == nil { // We were given provider[s] val, err := dht.getFromPeerList(key, timeout, pmes.GetPeers(), level) if err != nil { return nil, nil, err } return val, nil, nil } // Success! We were given the value return pmes.GetValue(), nil, nil } // We were given a closer node var peers []*peer.Peer for _, pb := range pmes.GetPeers() { if peer.ID(pb.GetId()).Equal(dht.self.ID) { continue } addr, err := ma.NewMultiaddr(pb.GetAddr()) if err != nil { u.PErr("%v\n", err.Error()) continue } np, err := dht.network.GetConnection(peer.ID(pb.GetId()), addr) if err != nil { u.PErr("%v\n", err.Error()) continue } peers = append(peers, np) } return nil, peers, nil }
//TODO: this function could also be done asynchronously func (dht *IpfsDHT) addPeerListAsync(k u.Key, peers []*PBDHTMessage_PBPeer, ps *peerSet, count int, out chan *peer.Peer) { for _, pbp := range peers { if peer.ID(pbp.GetId()).Equal(dht.self.ID) { continue } maddr, err := ma.NewMultiaddr(pbp.GetAddr()) if err != nil { u.PErr("%v\n", err) continue } p, err := dht.network.GetConnection(peer.ID(pbp.GetId()), maddr) if err != nil { u.PErr("%v\n", err) continue } dht.providers.AddProvider(k, p) if ps.AddIfSmallerThan(p, count) { out <- p } else if ps.Size() >= count { return } } }
func initIdentity(cfg *config.Config) (*peer.Peer, error) { if cfg.Identity == nil { return nil, errors.New("Identity was not set in config (was ipfs init run?)") } if len(cfg.Identity.PeerID) == 0 { return nil, errors.New("No peer ID in config! (was ipfs init run?)") } // address is optional var addresses []*ma.Multiaddr if len(cfg.Identity.Address) > 0 { maddr, err := ma.NewMultiaddr(cfg.Identity.Address) if err != nil { return nil, err } addresses = []*ma.Multiaddr{maddr} } skb, err := base64.StdEncoding.DecodeString(cfg.Identity.PrivKey) if err != nil { return nil, err } sk, err := ci.UnmarshalPrivateKey(skb) if err != nil { return nil, err } return &peer.Peer{ ID: peer.ID(b58.Decode(cfg.Identity.PeerID)), Addresses: addresses, PrivKey: sk, PubKey: sk.GetPublic(), }, nil }