Example #1
0
        public void Remove()
        {
            var bucket = new KBucket <Contact>();

            Assert.AreEqual(0, bucket.Count);

            bucket.Add(new Contact("a"));
            bucket.Add(new Contact("b"));
            bucket.Add(new Contact("c"));
            Assert.AreEqual(3, bucket.Count);

            bucket.Remove(new Contact("b"));
            Assert.AreEqual(2, bucket.Count);

            Assert.IsTrue(bucket.Contains(new Contact("a")));
            Assert.IsFalse(bucket.Contains(new Contact("b")));
            Assert.IsTrue(bucket.Contains(new Contact("c")));
        }
Example #2
0
        public void Add()
        {
            var bucket = new KBucket <Contact>();
            var x      = new Contact("1");

            bucket.Add(x);
            Assert.AreEqual(1, bucket.Count);
            Assert.IsTrue(bucket.Contains(x));
        }
Example #3
0
        public void BucketTest()
        {
            var bucket = new KBucket(4, new System.Random(), Logger.None);
            var peer1  = new BoundPeer(
                new PrivateKey().PublicKey,
                new DnsEndPoint("0.0.0.0", 1234),
                0);
            var peer2 = new BoundPeer(
                new PrivateKey().PublicKey,
                new DnsEndPoint("0.0.0.0", 1234),
                0);
            var peer3 = new BoundPeer(
                new PrivateKey().PublicKey,
                new DnsEndPoint("0.0.0.0", 1234),
                0);
            var peer4 = new BoundPeer(
                new PrivateKey().PublicKey,
                new DnsEndPoint("0.0.0.0", 1234),
                0);
            var peer5 = new BoundPeer(
                new PrivateKey().PublicKey,
                new DnsEndPoint("0.0.0.0", 1234),
                0);

            Assert.Empty(bucket.Peers);
            Assert.True(bucket.IsEmpty());
            Assert.Null(bucket.AddPeer(peer1));
            Assert.True(bucket.Contains(peer1));
            Assert.False(bucket.Contains(peer2));
            Assert.False(bucket.IsEmpty());
            Assert.False(bucket.IsFull());
            Assert.Null(bucket.AddPeer(peer2));
            Assert.Null(bucket.AddPeer(peer3));
            Assert.Null(bucket.AddPeer(peer4));
            Assert.True(bucket.IsFull());
            Assert.Contains(
                bucket.GetRandomPeer(),
                new[] { peer1, peer2, peer3, peer4 });
            Assert.Equal(peer1, bucket.AddPeer(peer5));
            Assert.True(bucket.Contains(peer1));
            Assert.False(bucket.Contains(peer5));
            bucket.Clear();
            Assert.True(bucket.IsEmpty());
        }
Example #4
0
 protected void EvictContact(KBucket bucket, Contact toEvict)
 {
     evictionCount.TryRemove(toEvict.ID.Value, out _);
     Validate.IsTrue <BucketDoesNotContainContactToEvict>(bucket.Contains(toEvict.ID), "Bucket doesn't contain the contact to be evicted.");
     bucket.EvictContact(toEvict);
     ContactRemoved?.Invoke(this, new ContactEventArgs()
     {
         Contact = toEvict
     });
 }
Example #5
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 #6
0
        void AddValidNode(NodeInfo nodeInfo)
        {
            if (!nodeInfo.IsPublicEndPoint)
            {
                return;
            }

            if (nodeInfo.NodeId == LocalId)
            {
                return;
            }

            if (!_bucket.Contains(nodeInfo.NodeId))
            {
                Log.Trace($"Adding new node {nodeInfo.PublicEndPoint}.", this);
            }

            var evictNode = _bucket.AddOrUpdate(nodeInfo);

            if (evictNode != null)
            {
                lock (_lock)
                {
                    if (_evictionsCount > 8)
                    {
                        return;
                    }
                    _evictionsCount++;
                }
                TaskRunner.Run(async() =>
                {
                    var client = new NodeClient(evictNode.PublicEndPoint);
                    var ni     = await client.DownloadNodeInfo();
                    if (ni.ResultType == DownloadResultTypes.Ok)
                    {
                        _bucket.AddOrUpdate(evictNode);
                    }
                    else
                    {
                        _bucket.Remove(evictNode.NodeId);
                        _bucket.AddOrUpdate(nodeInfo);
                    }

                    lock (_lock)
                    {
                        _evictionsCount--;
                    }
                });
            }
        }
        public void BucketTest()
        {
            var bucket = new KBucket(4, new System.Random(), Logger.None);
            var peer1  = new BoundPeer(
                new PrivateKey().PublicKey,
                new DnsEndPoint("0.0.0.0", 1234),
                AppProtocolVer);
            var peer2 = new BoundPeer(
                new PrivateKey().PublicKey,
                new DnsEndPoint("0.0.0.0", 1234),
                AppProtocolVer);
            var peer3 = new BoundPeer(
                new PrivateKey().PublicKey,
                new DnsEndPoint("0.0.0.0", 1234),
                AppProtocolVer);
            var peer4 = new BoundPeer(
                new PrivateKey().PublicKey,
                new DnsEndPoint("0.0.0.0", 1234),
                AppProtocolVer);
            var peer5 = new BoundPeer(
                new PrivateKey().PublicKey,
                new DnsEndPoint("0.0.0.0", 1234),
                AppProtocolVer);

            Assert.Empty(bucket.Peers);
            Assert.True(bucket.IsEmpty());
            bucket.AddPeer(peer1);
            Assert.True(bucket.Contains(peer1));
            Assert.False(bucket.Contains(peer2));
            Assert.False(bucket.IsEmpty());
            Assert.False(bucket.IsFull());
            // This sleep statement is used to distinguish updated time of followings.
            Thread.Sleep(100);
            bucket.AddPeer(peer2);
            Thread.Sleep(100);
            Assert.Contains(
                bucket.GetRandomPeer(null),
                new[] { peer1, peer2 }
                );
            Assert.Contains(
                bucket.GetRandomPeer(peer1.Address),
                new[] { peer2 }
                );
            bucket.AddPeer(peer3);
            Thread.Sleep(100);
            bucket.AddPeer(peer4);
            Assert.True(bucket.IsFull());
            Assert.Equal(
                bucket.Peers.ToHashSet(),
                new HashSet <BoundPeer> {
                peer1, peer2, peer3, peer4
            }
                );
            Assert.Contains(
                bucket.GetRandomPeer(null),
                new[] { peer1, peer2, peer3, peer4 }
                );
            Thread.Sleep(100);
            bucket.AddPeer(peer5);
            Assert.Equal(
                bucket.Peers.ToHashSet(),
                new HashSet <BoundPeer> {
                peer1, peer2, peer3, peer4
            }
                );
            Assert.False(bucket.Contains(peer5));
            Assert.Equal(peer4, bucket.Head.Peer);
            Assert.Equal(peer1, bucket.Tail.Peer);
            Thread.Sleep(100);
            bucket.AddPeer(peer1);
            Assert.Equal(peer1, bucket.Head.Peer);
            Assert.Equal(peer2, bucket.Tail.Peer);

            Assert.False(bucket.RemovePeer(peer5));
            Assert.True(bucket.RemovePeer(peer1));
            Assert.DoesNotContain(peer1, bucket.Peers);
            Assert.Equal(3, bucket.Peers.Count());

            bucket.Clear();
            Assert.True(bucket.IsEmpty());
        }
Example #8
0
 protected void EvictContact(KBucket bucket, Contact toEvict)
 {
     evictionCount.TryRemove(toEvict.ID.Value, out _);
     Validate.IsTrue <BucketDoesNotContainContactToEvict>(bucket.Contains(toEvict.ID), "Bucket doesn't contain the contact to be evicted.");
     bucket.EvictContact(toEvict);
 }
Example #9
0
        public void BucketTest()
        {
            var bucket = new KBucket(4, new System.Random(), Logger.None);
            var peer1  = new BoundPeer(
                new PrivateKey().PublicKey,
                new DnsEndPoint("0.0.0.0", 1234));
            var peer2 = new BoundPeer(
                new PrivateKey().PublicKey,
                new DnsEndPoint("0.0.0.0", 1234));
            var peer3 = new BoundPeer(
                new PrivateKey().PublicKey,
                new DnsEndPoint("0.0.0.0", 1234));
            var peer4 = new BoundPeer(
                new PrivateKey().PublicKey,
                new DnsEndPoint("0.0.0.0", 1234));
            var peer5 = new BoundPeer(
                new PrivateKey().PublicKey,
                new DnsEndPoint("0.0.0.0", 1234));

            // Checks for an empty bucket.
            Assert.True(bucket.IsEmpty);
            Assert.False(bucket.IsFull);
            Assert.Empty(bucket.Peers);
            Assert.Empty(bucket.PeerStates);
            Assert.Null(bucket.GetRandomPeer());
            Assert.Null(bucket.Head);
            Assert.Null(bucket.Tail);

            // Checks for a partially filled bucket.
            bucket.AddPeer(peer1, DateTimeOffset.UtcNow);
            Assert.False(bucket.IsEmpty);
            Assert.False(bucket.IsFull);
            Assert.True(bucket.Contains(peer1));
            Assert.False(bucket.Contains(peer2));
            Assert.NotNull(bucket.GetRandomPeer());
            Assert.Null(bucket.GetRandomPeer(peer1.Address));
            Assert.NotNull(bucket.GetRandomPeer(peer2.Address));
            Assert.Equal(peer1, bucket.Head.Peer);
            Assert.Equal(peer1, bucket.Tail.Peer);

            // Sleep statement is used to distinguish updated times.
            Thread.Sleep(100);
            bucket.AddPeer(peer2, DateTimeOffset.UtcNow);
            Assert.Contains(
                bucket.GetRandomPeer(),
                new[] { peer1, peer2 }
                );
            Assert.Contains(
                bucket.GetRandomPeer(peer1.Address),
                new[] { peer2 }
                );

            // Checks for a full bucket.
            Thread.Sleep(100);
            bucket.AddPeer(peer3, DateTimeOffset.UtcNow);
            Thread.Sleep(100);
            bucket.AddPeer(peer4, DateTimeOffset.UtcNow);
            Assert.True(bucket.IsFull);
            Assert.Equal(
                bucket.Peers.ToHashSet(),
                new HashSet <BoundPeer> {
                peer1, peer2, peer3, peer4
            }
                );
            Assert.Contains(
                bucket.GetRandomPeer(),
                new[] { peer1, peer2, peer3, peer4 }
                );
            Thread.Sleep(100);
            bucket.AddPeer(peer5, DateTimeOffset.UtcNow);
            Assert.Equal(
                bucket.Peers.ToHashSet(),
                new HashSet <BoundPeer> {
                peer1, peer2, peer3, peer4
            }
                );
            Assert.False(bucket.Contains(peer5));
            Assert.Equal(peer4, bucket.Head.Peer);
            Assert.Equal(peer1, bucket.Tail.Peer);

            // Check order has changed.
            Thread.Sleep(100);
            bucket.AddPeer(peer1, DateTimeOffset.UtcNow);
            Assert.Equal(peer1, bucket.Head.Peer);
            Assert.Equal(peer2, bucket.Tail.Peer);

            Assert.False(bucket.RemovePeer(peer5));
            Assert.True(bucket.RemovePeer(peer1));
            Assert.DoesNotContain(peer1, bucket.Peers);
            Assert.Equal(3, bucket.Peers.Count());

            // Clear the bucket.
            bucket.Clear();
            Assert.True(bucket.IsEmpty);
            Assert.Empty(bucket.Peers);
            Assert.Null(bucket.Head);
            Assert.Null(bucket.Tail);
            Assert.Null(bucket.GetRandomPeer());
        }
Example #10
0
 /// <summary>
 ///   Determines in the peer exists in the routing table.
 /// </summary>
 public bool Contains(Peer peer)
 {
     return(_peers.Contains(new RoutingPeer(peer)));
 }