func printPeer(p peer.Peer) (interface{}, error) { if p == nil { return nil, errors.New("Attempted to print nil peer!") } info := new(IdOutput) info.ID = p.ID().String() if p.PubKey() == nil { return nil, errors.New(`peer publickey not populated on offline runs, please run the daemon to use ipfs id!`) } pkb, err := p.PubKey().Bytes() if err != nil { return nil, err } info.PublicKey = base64.StdEncoding.EncodeToString(pkb) for _, a := range p.Addresses() { info.Addresses = append(info.Addresses, a.String()) } agent, protocol := p.GetVersions() info.AgentVersion = agent info.ProtocolVersion = protocol return info, nil }
func (r *dhtQueryRunner) addPeerToQuery(next peer.Peer, benchmark peer.Peer) { if next == nil { // wtf why are peers nil?!? log.Error("Query getting nil peers!!!\n") return } // if new peer further away than whom we got it from, bother (loops) if benchmark != nil && kb.Closer(benchmark.ID(), next.ID(), r.query.key) { return } // if already seen, no need. r.Lock() _, found := r.peersSeen[next.Key()] if found { r.Unlock() return } r.peersSeen[next.Key()] = next r.Unlock() log.Debugf("adding peer to query: %v\n", next) // do this after unlocking to prevent possible deadlocks. r.peersRemaining.Increment(1) select { case r.peersToQuery.EnqChan <- next: case <-r.ctx.Done(): } }
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 (ps *peerSet) AddIfSmallerThan(p peer.Peer, maxsize int) bool { var success bool ps.lk.Lock() if _, ok := ps.ps[string(p.ID())]; !ok && len(ps.ps) < maxsize { success = true ps.ps[string(p.ID())] = true } ps.lk.Unlock() return success }
func (pq *distancePQ) Enqueue(p peer.Peer) { pq.Lock() defer pq.Unlock() distance := ks.XORKeySpace.Key(p.ID()).Distance(pq.from) heap.Push(&pq.heap, &peerMetric{ peer: p, metric: distance, }) }
// CloseConnection removes a given peer from swarm + closes the connection func (s *Swarm) CloseConnection(p peer.Peer) error { c := s.GetConnection(p.ID()) if c == nil { return u.ErrNotFound } s.connsLock.Lock() delete(s.conns, u.Key(p.ID())) s.connsLock.Unlock() return c.Close() }
func peerToPBPeer(p peer.Peer) *Message_Peer { pbp := new(Message_Peer) addrs := p.Addresses() if len(addrs) == 0 || addrs[0] == nil { pbp.Addr = proto.String("") } else { addr := addrs[0].String() pbp.Addr = &addr } pid := string(p.ID()) pbp.Id = &pid return pbp }
// Dial connects to a peer. // // The idea is that the client of Swarm does not need to know what network // the connection will happen over. Swarm can use whichever it choses. // This allows us to use various transport protocols, do NAT traversal/relay, // etc. to achive connection. // // For now, Dial uses only TCP. This will be extended. func (s *Swarm) Dial(peer peer.Peer) (conn.Conn, error) { if peer.ID().Equal(s.local.ID()) { return nil, errors.New("Attempted connection to self!") } // check if we already have an open connection first c := s.GetConnection(peer.ID()) if c != nil { return c, nil } // check if we don't have the peer in Peerstore peer, err := s.peers.Add(peer) if err != nil { return nil, err } // open connection to peer d := &conn.Dialer{ LocalPeer: s.local, Peerstore: s.peers, } // try to connect to one of the peer's known addresses. // for simplicity, we do this sequentially. // A future commit will do this asynchronously. for _, addr := range peer.Addresses() { c, err = d.DialAddr(s.Context(), addr, peer) if err == nil { break } } if err != nil { return nil, err } c, err = s.connSetup(c) if err != nil { c.Close() return nil, err } // TODO replace the TODO ctx with a context passed in from caller log.Event(context.TODO(), "dial", peer) return c, nil }
// Update adds or moves the given peer to the front of its respective bucket // If a peer gets removed from a bucket, it is returned func (rt *RoutingTable) Update(p peer.Peer) peer.Peer { rt.tabLock.Lock() defer rt.tabLock.Unlock() peerID := ConvertPeerID(p.ID()) cpl := commonPrefixLen(peerID, rt.local) bucketID := cpl if bucketID >= len(rt.Buckets) { bucketID = len(rt.Buckets) - 1 } bucket := rt.Buckets[bucketID] e := bucket.find(p.ID()) if e == nil { // New peer, add to bucket if p.GetLatency() > rt.maxLatency { // Connection doesnt meet requirements, skip! return nil } bucket.pushFront(p) // Are we past the max bucket size? if bucket.len() > rt.bucketsize { // If this bucket is the rightmost bucket, and its full // we need to split it and create a new bucket if bucketID == len(rt.Buckets)-1 { return rt.nextBucket() } else { // If the bucket cant split kick out least active node return bucket.popBack() } } return nil } // If the peer is already in the table, move it to the front. // This signifies that it it "more active" and the less active nodes // Will as a result tend towards the back of the list bucket.moveToFront(e) return nil }
// 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 }
// TODO func (n *network) SendRequest( ctx context.Context, from peer.Peer, to peer.Peer, message bsmsg.BitSwapMessage) ( incoming bsmsg.BitSwapMessage, err error) { r, ok := n.clients[to.Key()] if !ok { return nil, errors.New("Cannot locate peer on network") } nextPeer, nextMsg := r.ReceiveMessage(context.TODO(), from, message) // TODO dedupe code if (nextPeer == nil && nextMsg != nil) || (nextMsg == nil && nextPeer != nil) { r.ReceiveError(errors.New("Malformed client request")) return nil, nil } // TODO dedupe code if nextPeer == nil && nextMsg == nil { return nil, nil } // TODO test when receiver doesn't immediately respond to the initiator of the request if !bytes.Equal(nextPeer.ID(), from.ID()) { go func() { nextReceiver, ok := n.clients[nextPeer.Key()] if !ok { // TODO log the error? } n.deliver(nextReceiver, nextPeer, nextMsg) }() return nil, nil } return nextMsg, nil }
// IsConnected returns whether a connection to given peer exists. func (n *IpfsNetwork) IsConnected(p peer.Peer) (bool, error) { return n.swarm.GetConnection(p.ID()) != nil, nil }
func (ps *peerSet) Contains(p peer.Peer) bool { ps.lk.RLock() _, ok := ps.ps[string(p.ID())] ps.lk.RUnlock() return ok }
func (ps *peerSet) Add(p peer.Peer) { ps.lk.Lock() ps.ps[string(p.ID())] = true ps.lk.Unlock() }