예제 #1
0
        // ======= ======= ======= ======= =======

        /// <summary>
        /// Someone is pinging us.  Register the contact and respond.
        /// </summary>
        public Contact Ping(Contact sender)
        {
            Validate.IsFalse <SendingQueryToSelfException>(sender.ID == ourContact.ID, "Sender should not be ourself!");
            SendKeyValuesIfNewContact(sender);
            bucketList.AddContact(sender);

            return(ourContact);
        }
        protected IBucketList SetupSplitFailure(IBucketList bucketList = null)
        {
            // force host node ID to < 2^159 so the node ID is not in the 2^159 ... 2^160 range
            byte[] bhostID = new byte[20];
            bhostID[19] = 0x7F;
            ID hostID = new ID(bhostID);

            Contact dummyContact = new Contact(new VirtualProtocol(), hostID);

            ((VirtualProtocol)dummyContact.Protocol).Node = new Node(dummyContact, new VirtualStorage());
            bucketList = bucketList ?? new BucketList(hostID, dummyContact);

            // Also add a contact in this 0 - 2^159 range, arbitrarily something not our host ID.
            // This ensures that only one bucket split will occur after 20 nodes with ID >= 2^159 are added,
            // otherwise, buckets will in the 2^159 ... 2^160 space.
            dummyContact = new Contact(new VirtualProtocol(), ID.One);
            ((VirtualProtocol)dummyContact.Protocol).Node = new Node(dummyContact, new VirtualStorage());
            bucketList.AddContact(new Contact(dummyContact.Protocol, ID.One));

            Assert.IsTrue(bucketList.Buckets.Count == 1, "Bucket split should not have occurred.");
            Assert.IsTrue(bucketList.Buckets[0].Contacts.Count == 1, "Expected 1 contact in bucket 0.");

            // make sure contact ID's all have the same 5 bit prefix and are in the 2^159 ... 2^160 - 1 space
            byte[] bcontactID = new byte[20];
            bcontactID[19] = 0x80;
            // 1000 xxxx prefix, xxxx starts at 1000 (8)
            // this ensures that all the contacts in a bucket match only the prefix as only the first 5 bits are shared.
            // |----| shared range
            // 1000 1000 ...
            // 1000 1100 ...
            // 1000 1110 ...
            byte shifter = 0x08;
            int  pos     = 19;

            Constants.K.ForEach(() =>
            {
                bcontactID[pos] |= shifter;
                ID contactID     = new ID(bcontactID);
                dummyContact     = new Contact(new VirtualProtocol(), ID.One);
                ((VirtualProtocol)dummyContact.Protocol).Node = new Node(dummyContact, new VirtualStorage());
                bucketList.AddContact(new Contact(dummyContact.Protocol, contactID));
                shifter >>= 1;

                if (shifter == 0)
                {
                    shifter = 0x80;
                    --pos;
                }
            });

            return(bucketList);
        }
예제 #3
0
파일: Node.cs 프로젝트: mitacha/Kademlia-1
        // ======= ======= ======= ======= =======

        /// <summary>
        /// Someone is pinging us.  Register the contact and respond.
        /// </summary>
        public Contact Ping(Contact sender)
        {
            Validate.IsFalse <SendingQueryToSelfException>(sender.ID == ourContact.ID, "Sender should not be ourself!");
            // Not in spec...ping the sender to verify sender.
            RpcError err = sender.Protocol.PingBack(ourContact);

            if (!err.HasError)
            {
                SendKeyValuesIfNewContact(sender);
                bucketList.AddContact(sender);
            }

            return(ourContact);
        }
        public void ForceFailedAddTest()
        {
            Contact dummyContact = new Contact(new VirtualProtocol(), ID.Zero);

            ((VirtualProtocol)dummyContact.Protocol).Node = new Node(dummyContact, new VirtualStorage());

            IBucketList bucketList = SetupSplitFailure();

            Assert.IsTrue(bucketList.Buckets.Count == 2, "Bucket split should have occurred.");
            Assert.IsTrue(bucketList.Buckets[0].Contacts.Count == 1, "Expected 1 contact in bucket 0.");
            Assert.IsTrue(bucketList.Buckets[1].Contacts.Count == 20, "Expected 20 contacts in bucket 1.");

            // This next contact should not split the bucket as depth == 5 and therefore adding the contact will fail.
            // Any unique ID >= 2^159 will do.
            byte[] id = new byte[20];
            id[19] = 0x80;
            Contact newContact = new Contact(dummyContact.Protocol, new ID(id));

            bucketList.AddContact(newContact);

            Assert.IsTrue(bucketList.Buckets.Count == 2, "Bucket split should not have occurred.");
            Assert.IsTrue(bucketList.Buckets[0].Contacts.Count == 1, "Expected 1 contact in bucket 0.");
            Assert.IsTrue(bucketList.Buckets[1].Contacts.Count == 20, "Expected 20 contacts in bucket 1.");

            // Verify CanSplit -> Evict did not happen.
            Assert.IsFalse(bucketList.Buckets[1].Contacts.Contains(newContact), "Expected new contact NOT to replace an older contact.");
        }
        public void NonRespondingContactDelayedEvictionTest()
        {
            // Create a DHT so we have an eviction handler.
            Dht dht = new Dht(ID.Zero, new VirtualProtocol(), () => null, new Router());
            //Contact dummyContact = new Contact(new VirtualProtocol(), ID.Zero);
            //((VirtualProtocol)dummyContact.Protocol).Node = new Node(dummyContact, new VirtualStorage());

            IBucketList bucketList = SetupSplitFailure(dht.Node.BucketList);

            Assert.IsTrue(bucketList.Buckets.Count == 2, "Bucket split should have occurred.");
            Assert.IsTrue(bucketList.Buckets[0].Contacts.Count == 1, "Expected 1 contact in bucket 0.");
            Assert.IsTrue(bucketList.Buckets[1].Contacts.Count == 20, "Expected 20 contacts in bucket 1.");

            // The bucket is now full.  Pick the first contact, as it is last seen (they are added in chronological order.)
            Contact nonRespondingContact = bucketList.Buckets[1].Contacts[0];

            // Since the protocols are shared, we need to assign a unique protocol for this node for testing.
            VirtualProtocol vpUnresponding = new VirtualProtocol(((VirtualProtocol)nonRespondingContact.Protocol).Node, false);

            nonRespondingContact.Protocol = vpUnresponding;

            // Setup the next new contact (it can respond.)
            Contact nextNewContact = new Contact(dht.Contact.Protocol, ID.Zero.SetBit(159));

            bucketList.AddContact(nextNewContact);

            Assert.IsTrue(bucketList.Buckets[1].Contacts.Count == 20, "Expected 20 contacts in bucket 1.");

            // Verify CanSplit -> Evict happened.

            Assert.IsTrue(dht.PendingContacts.Count == 1, "Expected one pending contact.");
            Assert.IsTrue(dht.PendingContacts.Contains(nextNewContact), "Expected pending contact to be the 21st contact.");
            Assert.IsTrue(dht.EvictionCount.Count == 1, "Expected one contact to be pending eviction.");
        }
        public void NonRespondingContactEvictedTest()
        {
            // Create a DHT so we have an eviction handler.
            Dht dht = new Dht(ID.Zero, new VirtualProtocol(), () => null, new Router());
            //Contact dummyContact = new Contact(new VirtualProtocol(), ID.Zero);
            //((VirtualProtocol)dummyContact.Protocol).Node = new Node(dummyContact, new VirtualStorage());

            IBucketList bucketList = SetupSplitFailure(dht.Node.BucketList);

            Assert.IsTrue(bucketList.Buckets.Count == 2, "Bucket split should have occurred.");
            Assert.IsTrue(bucketList.Buckets[0].Contacts.Count == 1, "Expected 1 contact in bucket 0.");
            Assert.IsTrue(bucketList.Buckets[1].Contacts.Count == 20, "Expected 20 contacts in bucket 1.");

            // The bucket is now full.  Pick the first contact, as it is last seen (they are added in chronological order.)
            Contact nonRespondingContact = bucketList.Buckets[1].Contacts[0];

            // Since the protocols are shared, we need to assign a unique protocol for this node for testing.
            VirtualProtocol vpUnresponding = new VirtualProtocol(((VirtualProtocol)nonRespondingContact.Protocol).Node, false);

            nonRespondingContact.Protocol = vpUnresponding;

            // Setup the next new contact (it can respond.)
            Contact nextNewContact = new Contact(dht.Contact.Protocol, ID.Zero.SetBit(159));

            // Hit the non-responding contact EVICTION_LIMIT times, which will trigger the eviction algorithm.
            Constants.EVICTION_LIMIT.ForEach(() => bucketList.AddContact(nextNewContact));

            Assert.IsTrue(bucketList.Buckets[1].Contacts.Count == 20, "Expected 20 contacts in bucket 1.");

            // Verify CanSplit -> Pending eviction happened.

            Assert.IsTrue(dht.PendingContacts.Count == 0, "Pending contact list should now be empty.");
            Assert.IsFalse(bucketList.Buckets.SelectMany(b => b.Contacts).Contains(nonRespondingContact), "Expected bucket to NOT contain non-responding contact.");
            Assert.IsTrue(bucketList.Buckets.SelectMany(b => b.Contacts).Contains(nextNewContact), "Expected bucket to contain new contact.");
            Assert.IsTrue(dht.EvictionCount.Count == 0, "Expected no contacts to be pending eviction.");
        }