Example #1
0
        public void TooManyContactsTest()
        {
            KBucket kbucket = new KBucket();

            // Add max # of contacts.
            Constants.K.ForEach(n => kbucket.AddContact(new Contact(null, new ID(n))));

            // Add one more.
            kbucket.AddContact(new Contact(null, new ID(21)));
        }
Example #2
0
        /// <summary>
        /// Add a contact if possible, based on the algorithm described
        /// in sections 2.2, 2.4 and 4.2
        /// </summary>
        public void AddContact(Contact contact)
        {
            Validate.IsFalse<OurNodeCannotBeAContactException>(ourID == contact.ID, "Cannot add ourselves as a contact!");
            contact.Touch();            // Update the LastSeen to now.

            lock (this)
            {
                KBucket kbucket = GetKBucket(contact.ID);

                if (kbucket.Contains(contact.ID))
                {
                    // Replace the existing contact, updating the network info and LastSeen timestamp.
                    kbucket.UpdateContactInfo(contact);
                }
                else if (kbucket.IsBucketFull)
                {
                    if (CanSplit(kbucket))
                    {
                        // Split the bucket and try again.
                        (KBucket k1, KBucket k2) = kbucket.Split();
                        int idx = GetKBucketIndex(contact.ID);
                        buckets[idx] = k1;
                        buckets.Insert(idx + 1, k2);
                        buckets[idx].Touch();
                        buckets[idx + 1].Touch();
                        AddContact(contact);
                    }
                    else
                    {
                        Contact lastSeenContact = kbucket.Contacts.OrderBy(c => c.LastSeen).First();
                        RpcError error = lastSeenContact.Protocol.Ping(ourContact);

                        if (error.HasError)
                        {
                            // Null continuation is used because unit tests may not initialize a DHT.
                            dht?.DelayEviction(lastSeenContact, contact);
                        }
                        else
                        {
                            // Still can't add the contact, so put it into the pending list.
                            dht?.AddToPending(contact);
                        }
                    }
                }
                else
                {
                    // Bucket isn't full, so just add the contact.
                    kbucket.AddContact(contact);
                    dht?.ContactAddedToBucket(kbucket, contact);
                }
            }
        }
Example #3
0
        /// <summary>
        /// Find a pending contact that goes into the bucket that now has room.
        /// </summary>
        protected void ReplaceWithPendingContact(KBucket bucket)
        {
            Contact contact;

            // Non-concurrent list needs locking while we query it.
            lock (pendingContacts)
            {
                contact = pendingContacts.Where(c => node.BucketList.GetKBucket(c.ID) == bucket).OrderBy(c => c.LastSeen).LastOrDefault();

                if (contact != null)
                {
                    pendingContacts.Remove(contact);
                    bucket.AddContact(contact);
                }
            }
        }