/// <inheritdoc /> public async Task <Peer> FindPeerAsync(MultiHash id, CancellationToken cancel = default) { // Can always find self. if (SwarmService.LocalPeer.Id == id) { return(SwarmService.LocalPeer); } // Maybe the swarm knows about it. var found = SwarmService.KnownPeers.FirstOrDefault(p => p.Id == id); if (found != null && found.Addresses.Any()) { return(found); } // Ask our peers for information on the requested peer. var dQuery = new DistributedQuery <Peer> { QueryType = MessageType.FindNode, QueryKey = id, Dht = this, AnswersNeeded = 1 }; await dQuery.RunAsync(cancel).ConfigureAwait(false); // If not found, return the closest peer. return(!dQuery.Answers.Any() ? RoutingTable.NearestPeers(id).FirstOrDefault() : dQuery.Answers.First()); }
/// <inheritdoc /> public async Task <IEnumerable <Peer> > FindProvidersAsync(Cid id, int limit = 20, Action <Peer> action = null, CancellationToken cancel = default) { var dQuery = new DistributedQuery <Peer> { QueryType = MessageType.GetProviders, QueryKey = id.Hash, Dht = this, AnswersNeeded = limit, }; if (action != null) { dQuery.AnswerObtained += (s, e) => action.Invoke(e); } // Add any providers that we already know about. var providers = ContentRouter .Get(id) .Select(pid => pid == SwarmService.LocalPeer.Id ? SwarmService.LocalPeer : SwarmService.RegisterPeer(new Peer { Id = pid })); foreach (var provider in providers) { dQuery.AddAnswer(provider); } // Ask our peers for more providers. if (limit > dQuery.Answers.Count()) { await dQuery.RunAsync(cancel).ConfigureAwait(false); } return(dQuery.Answers.Take(limit)); }