public static List<Contact> CloseContacts(this IBucketList _contactCache, ID target, ID excluded)
 {
     return _contactCache.CloseContacts(target)
             .Take(8 * ID.ID_LENGTH)
             .Where(x => x.GetID() != excluded)
             .ToList();
 }
예제 #2
0
        /// <summary>
        /// Make a new bucket list, for holding node contacts.
        /// </summary>
        /// <param name="ourID">The ID to center the list on.</param>
        public BucketList(Contact ourID, Func<Uri, IKadmeliaServer> serverFactory)
        {
            this.ourID = ourID.GetID();
            this.myself = ourID;
            buckets = new List<List<Contact>>(NUM_BUCKETS);
            accessTimes = new List<DateTime>();

            // Set up each bucket
            for (int i = 0; i < NUM_BUCKETS; i++)
            {
                buckets.Add(new List<Contact>(BUCKET_SIZE));
                accessTimes.Add(default(DateTime));
            }
            this.serverFactory = serverFactory;
        }
예제 #3
0
 /// <summary>
 /// Returns what bucket an ID maps to.
 /// PRECONDITION: ourID not passed.
 /// </summary>
 /// <param name="id"></param>
 /// <returns></returns>
 private int BucketFor(ID id)
 {
     return (OurId.DifferingBit(id));
 }
예제 #4
0
 public void Touch(ID key)
 {
     accessTimes[BucketFor(key)] = DateTime.Now;
 }
예제 #5
0
 public void Remove(ID toRemove)
 {
     int bucket = BucketFor(toRemove);
     for (int i = 0; i < buckets[bucket].Count; i++)
     {
         if (buckets[bucket][i].GetID() == toRemove)
         {
             buckets[bucket].RemoveAt(i);
             return;
         }
     }
 }
예제 #6
0
 public void Promote(ID toPromote)
 {
     Contact promotee = Get(toPromote);
     int bucket = BucketFor(toPromote);
     buckets[bucket].Remove(promotee); // Take out
     buckets[bucket].Add(promotee); // And put in at end
     accessTimes[bucket] = DateTime.Now;
 }
예제 #7
0
 public Contact Get(ID toGet)
 {
     int bucket = BucketFor(toGet);
     for (int i = 0; i < buckets[bucket].Count; i++)
     {
         if (buckets[bucket][i].GetID() == toGet)
         {
             return buckets[bucket][i];
         }
     }
     return null;
 }
예제 #8
0
 public bool Contains(ID toCheck)
 {
     return this.Get(toCheck) != null;
 }
예제 #9
0
 public IList<Contact> CloseContacts(ID target)
 {
     return AllContacts.OrderBy(x => x.GetID() ^ target)
                       .ToList();
 }
예제 #10
0
 public Contact Blocker(ID toAdd)
 {
     int bucket = BucketFor(toAdd);
     if (buckets[bucket].Count < BUCKET_SIZE)
     {
         return null;
     }
     else
     {
         return buckets[bucket][0];
     }
 }
예제 #11
0
        /// <summary>
        /// Determines the least significant bit at which the given ID differs from this one, from 0 through 8 * ID_LENGTH - 1.
        /// PRECONDITION: IDs do not match.
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public int DifferingBit(ID other)
        {
            ID differingBits = this ^ other;
            int differAt = 0;

            int i = 0;
            while (i < ID_LENGTH && differingBits.Data[i] == 0)
            {
                differAt += 8;
                i++;
            }

            // Subtract 1 for every zero bit from the right
            int j = 7;
            // 1 << j = pow(2, j)
            while (j >= 0 && (differingBits.Data[i] & (1 << j)) == 0)
            {
                j--;
                differAt++;
            }

            return differAt;
        }
예제 #12
0
        /// <summary>
        /// Do an iterativeStore operation and publish the key/value pair on the network
        /// </summary>
        /// <param name="key"></param>
        /// <param name="val"></param>
        private IterativeFindResult IterativeStore(ID key, string val, DateTime originalInsertion, DateTime expires, int replicationFactor)
        {
            // Find the K closest nodes to the key
            var closest = IterativeFindNode(key);
            foreach (Contact c in closest.ClosestPeers.Take(replicationFactor))
            {
                var remotePeerUri = c.ToUri();
                var peer = serverFactory(remotePeerUri);
                peer.StoreValue(myself, key.Data, val, originalInsertion, expires);
            }

            return closest;
        }
예제 #13
0
 /// <summary>
 /// Do an iterativeFindNode operation.
 /// </summary>
 /// <param name="target"></param>
 /// <returns></returns>
 private IterativeFindResult IterativeFindNode(ID target)
 {
     return IterativeFind(target, false);
 }
예제 #14
0
        /// <summary>
        /// Perform a Kademlia iterativeFind* operation.
        /// If getValue is true, it sends out a list of strings if values are found, or null none are.
        /// </summary>
        /// <param name="target"></param>
        /// <param name="getValue">true for FindValue, false for FindNode</param>
        /// <param name="vals"></param>
        /// <returns></returns>
        private IterativeFindResult IterativeFind(ID target, bool getValue)
        {
            IterativeFindResult result = new IterativeFindResult();

            // Log the lookup
            if (target != routingTable.OurContact.GetID())
                routingTable.Touch(target);

            // Get the alpha closest nodes to the target
            var shortlist = new SortedList<ID, HaveAsked>();

            foreach (Contact c in routingTable.CloseContacts(20, target))
                shortlist.Add(c.GetID() ^ target, new HaveAsked() { Contact = c, Asked = false });

            // Until we run out of people to ask or we're done...
            bool peersLeftToAsk = true;
            while (peersLeftToAsk)
            {
                var closestPeerNotAsked = shortlist.Where(x => x.Value.Contact.GetID() != myself.GetID() && !x.Value.IsNotContactable)  //Don't ask myself, ignore not contactable nodes
                                                        .Take(3)    //only consider the first 3 closest nodes
                                                        .Where(x => x.Value.Asked == false) //That we haven't asked before
                                                        .FirstOrDefault(); //Get the first
                if (closestPeerNotAsked.Value == null)
                {
                    peersLeftToAsk = false;
                    continue;
                }

                result.NumberIterations += 1;

                closestPeerNotAsked.Value.Asked = true;
                var remotePeerUri = closestPeerNotAsked.Value.Contact.ToUri();
                var peer = serverFactory(remotePeerUri);

                SearchResult searchResult;
                if (getValue)
                    searchResult = peer.FindValue(myself, target.Data);
                else
                    searchResult = peer.FindNode(myself, target.Data);

                //peer is down, ignore
                if (searchResult == null)
                {
                    closestPeerNotAsked.Value.IsNotContactable = true;
                    continue;
                }

                if (searchResult.Values != null)
                {
                    result.Values = searchResult.Values;
                    result.TargetPeer = closestPeerNotAsked.Value.Contact;
                    return result;
                }

                if (searchResult.Contacts != null)
                {
                    // Add suggestions to shortlist and check for closest
                    foreach (Contact suggestion in searchResult.Contacts)
                    {
                        var distance = suggestion.GetID() ^ target;
                        if (!shortlist.ContainsKey(distance))
                            shortlist.Add(distance, new HaveAsked() { Contact = suggestion });

                        //Add this guy to our contact cache
                        routingTable.AddContact(suggestion);
                    }
                }
            }

            result.ClosestPeers = shortlist.Values.Where(x => !x.IsNotContactable).Select(x => x.Contact).Take(20).ToList();
            return result;
        }
 public static List<Contact> CloseContacts(this IBucketList _contactCache, int count, ID target)
 {
     return _contactCache.CloseContacts(target)
             .Take(count).ToList();
 }