Пример #1
0
        private Tuple <KadContactNode, KadValue> LookupValue(KadId valueId, out SortedSet <KadContactNode> retSortList)
        {
            var closestNodes = Owner.BucketList.GetClosestNodes(valueId, MaxConcurrentThreads);
            SortedSet <KadContactNode> shortList = new SortedSet <KadContactNode>(closestNodes, new KadId.KadIdToBaseComparator(valueId));

            retSortList = shortList;
            if (shortList.Count == 0)
            {
                return(null);
            }

            SortedSet <KadId> queriedNodes   = new SortedSet <KadId>(new KadId.KadIdToIdComparator());
            KadId             closestId      = shortList.Min.Id;
            SemaphoreSlim     tasksSemaphore = new SemaphoreSlim(MaxConcurrentThreads);
            KadContactNode    returnedNode   = null;
            KadValue          value          = null;
            //Should do fine for small alpha
            List <Task> tasks = new List <Task>();

            while (queriedNodes.Count < ReplicationCount)
            {
                var shortListSnapshot = shortList.Where((n) => !queriedNodes.Contains(n.Id)).ToList();
                foreach (var node in shortListSnapshot)
                {
                    tasks.Add(Task.Run(() => {
                        var response = Owner.FindValue(node, valueId);
                        if (response != null)
                        {
                            if (response.Type == MessageType.FindNode)
                            {
                                foreach (var contact in response.Contacts)
                                {
                                    shortList.Add(contact);
                                }
                            }
                            else if (response.Type == MessageType.FindValue)
                            {
                                value        = new KadValue(valueId, DateTime.Now, response.Payload);
                                returnedNode = node;
                            }
                        }
                        tasksSemaphore.Release();
                    }));
                    queriedNodes.Add(node.Id);
                    tasksSemaphore.Wait();
                }

                Task.WaitAll(tasks.ToArray());
                tasks.Clear();

                if ((shortList.Min.Id ^ closestId) >= closestId)
                {
                    break;
                }

                closestId = shortList.Min.Id;
            }

            return(value != null ? new Tuple <KadContactNode, KadValue>(returnedNode, value) : null);
        }
Пример #2
0
        public void StoreValue()
        {
            KadNode ownerNode = new KadNode(new System.Net.IPEndPoint(IPAddress.Loopback, 55555));
            KadNode node1     = new KadNode(new System.Net.IPEndPoint(IPAddress.Loopback, 55556));
            KadNode node2     = new KadNode(new System.Net.IPEndPoint(IPAddress.Loopback, 55557));
            KadNode node3     = new KadNode(new System.Net.IPEndPoint(IPAddress.Loopback, 55558));
            KadNode node4     = new KadNode(new System.Net.IPEndPoint(IPAddress.Loopback, 55559));

            node1.BucketList.Put(new KadContactNode(node2.Id, node2.EndPoint));
            node1.BucketList.Put(new KadContactNode(node3.Id, node3.EndPoint));
            node1.BucketList.Put(new KadContactNode(node4.Id, node4.EndPoint));

            KadValue value = new KadValue(KadId.GenerateRandom(), DateTime.UtcNow, new byte[20]);

            KadHashTable hashTable = new KadHashTable(ownerNode, new KadContactNode(node1.Id, node1.EndPoint));

            hashTable.StoreValue(value);

            Assert.IsTrue(ownerNode.Storage.OwnerValues.Count() == 1);
            Assert.IsTrue(ownerNode.Storage.OwnerValues.First().Id.GetNumericValue() == value.Id.GetNumericValue());

            Assert.IsTrue(node1.Storage.Values.Count() == 1);
            Assert.IsTrue(node1.Storage.Values.First().Id.GetNumericValue() == value.Id.GetNumericValue());

            Assert.IsTrue(node2.Storage.Values.Count() == 1);
            Assert.IsTrue(node2.Storage.Values.First().Id.GetNumericValue() == value.Id.GetNumericValue());

            Assert.IsTrue(node3.Storage.Values.Count() == 1);
            Assert.IsTrue(node3.Storage.Values.First().Id.GetNumericValue() == value.Id.GetNumericValue());

            Assert.IsTrue(node4.Storage.Values.Count() == 1);
            Assert.IsTrue(node4.Storage.Values.First().Id.GetNumericValue() == value.Id.GetNumericValue());
        }
Пример #3
0
        private void ReplicateValue(KadValue value)
        {
            var closestNodes = Owner.BucketList.GetClosestNodes(value.Id, ReplicationCount);

            foreach (var node in closestNodes)
            {
                Owner.StoreValue(node, value);
            }
        }
Пример #4
0
        public void StoreValue(KadValue value)
        {
            if (!Owner.Storage.Contains(value.Id))
            {
                Owner.Storage.PutOwnerVal(value);
            }

            ReplicateValue(value);
        }
Пример #5
0
        /// <summary>
        /// Store value in contact
        /// </summary>
        /// <param name="node">Contact node</param>
        /// <param name="value">Value to store</param>
        /// <returns>true, if node stored value</returns>
        public bool StoreValue(KadContactNode node, KadValue value)     //TODO: support chunking
        {
            NodeMessage storeValueMsg = new NodeMessage.Builder()
                                        .SetType(MessageType.StoreValue)
                                        .SetOriginator(Id)
                                        .SetIsRequest(true)
                                        .SetKadValueAsPayload(value)
                                        .Build();

            storeValueMsg.AddCallback(UpdateLastSeen);
            var response = _server.SendMessageSync(node.EndPoint, storeValueMsg, TimeoutInMSec).Response;

            return(response != null && response.Type == MessageType.CanStoreValue && response.Payload[0] > 0);
        }
Пример #6
0
        public void StoreValue()
        {
            KadNode node1 = new KadNode(new System.Net.IPEndPoint(IPAddress.Loopback, 55555));
            KadNode node2 = new KadNode(new System.Net.IPEndPoint(IPAddress.Loopback, 55556));

            KadValue val = new KadValue(KadId.GenerateRandom(), DateTime.Now, new byte[20]);

            node1.BucketList.Put(new KadContactNode(node2.Id, node2.EndPoint));
            Assert.IsTrue(node1.StoreValue(node2.Id, val));

            KadValue node2Val = node2.Storage.Get(val.Id);

            Assert.IsTrue(val.Id.GetNumericValue() == node2Val.Id.GetNumericValue());

            node1.Shutdown();
            node2.Shutdown();
        }
Пример #7
0
        public void StoreValue_CantStore()
        {
            KadNode node1 = new KadNode(new System.Net.IPEndPoint(IPAddress.Loopback, 55555));
            KadNode node2 = new KadNode(new System.Net.IPEndPoint(IPAddress.Loopback, 55556));

            for (int i = 0; i < 20; i++)
            {
                var value = new KadValue(kademlia_dht.Base.KadId.GenerateRandom(), DateTime.UtcNow, new byte[20]);
                node2.Storage.Put(value);
                Thread.Sleep(500);
            }

            KadValue val = new KadValue(KadId.GenerateRandom(), DateTime.UtcNow, new byte[20]);

            node1.BucketList.Put(new KadContactNode(node2.Id, node2.EndPoint));
            Assert.IsFalse(node1.StoreValue(node2.Id, val));

            node1.Shutdown();
            node2.Shutdown();
        }
Пример #8
0
        /// <summary>
        /// Checks whether value is expired
        /// Algorithm described in http://xlattice.sourceforge.net/components/protocol/kademlia/specs.html#expiration
        /// </summary>
        /// <param name="kadVal">Value to be checked</param>
        /// <returns>True if value expired</returns>
        public bool IsValueExpired(KadValue kadVal)
        {
            var valBucket = BucketList.GetBucket(kadVal.Id);
            int cA = 0, cB = 0;

            foreach (var bucket in BucketList.Buckets.Where((b) => b.Id < valBucket.Id))
            {
                cA += bucket.NodesCount;
            }

            foreach (var contact in valBucket.GetNodes())
            {
                if (contact.Id < kadVal.Id)
                {
                    cB++;
                }
            }

            int c = cA + cB;

            if (c == 0)
            {
                return(true);
            }

            int secondsBtw = (int)(DateTime.UtcNow - kadVal.Timestamp).TotalSeconds;

            if (c > Storage.Size())
            {
                if (secondsBtw >= ValueExpirationInSec)
                {
                    return(true);
                }
            }
            else if (secondsBtw >= ValueExpirationInSec * Math.Exp(Storage.Size() / c))
            {
                return(true);
            }

            return(false);
        }
Пример #9
0
        public void IsValueExpired_Exp()
        {
            KadId ownerNodeId = KadId.GenerateRandom();

            for (int i = 2; i < ownerNodeId.Value.Length; i++)
            {
                ownerNodeId.Value[i] = 255;
            }
            ownerNodeId.Value[0] = 0;
            ownerNodeId.Value[1] = 0;
            KadNode node1 = new KadNode(new System.Net.IPEndPoint(IPAddress.Loopback, 55555), ownerNodeId);

            byte[] baseId = new byte[20];

            for (int i = 1; i < 21; i++)  //fill up random bucket
            {
                baseId[19] = (byte)i;
                KadContactNode contact = new KadContactNode(new KadId(baseId), new IPEndPoint(IPAddress.Loopback, 20000));
                node1.BucketList.Put(contact);
            }

            //baseId[0] = 255;
            //baseId[1] = 255;
            //baseId[19] = 0;
            //for(int i = 1; i < 20; i++) {
            //    baseId[3] = (byte)i;
            //    ContactNode contact = new ContactNode(new KadId(baseId), new IPEndPoint(IPAddress.Loopback, 20000));
            //    node1.BucketList.Put(contact);
            //}

            KadValue nonExpiredVal = new KadValue(node1.BucketList.Buckets.Aggregate((o, n) => o.Id < n.Id ? n : o).GetNodes()
                                                  .Aggregate((o, n) => o.Id > n.Id ? n : o).Id, DateTime.UtcNow.AddSeconds(-(node1.ValueExpirationInSec + 1)), new byte[20]);

            Assert.IsFalse(node1.IsValueExpired(nonExpiredVal));

            KadValue expiredVal = new KadValue(nonExpiredVal.Id, DateTime.UtcNow.AddSeconds(-(((node1.ValueExpirationInSec + 1) * Math.Exp(20 / 19)))), new byte[20]);

            Assert.IsTrue(node1.IsValueExpired(expiredVal));

            node1.Shutdown();
        }
Пример #10
0
        public void IsValueExpired_GoodAmountOfCloseContacts()
        {
            KadId ownerNodeId = KadId.GenerateRandom();

            for (int i = 2; i < ownerNodeId.Value.Length; i++)
            {
                ownerNodeId.Value[i] = 255;
            }
            ownerNodeId.Value[0] = 0;
            ownerNodeId.Value[1] = 0;
            KadNode node1 = new KadNode(new System.Net.IPEndPoint(IPAddress.Loopback, 55555), ownerNodeId);


            byte[] baseId = new byte[20];
            baseId[0] = 255;
            for (int i = 0; i < 20; i++)  //fill up random bucket
            {
                baseId[19] = (byte)i;
                KadContactNode contact = new KadContactNode(new KadId(baseId), new IPEndPoint(IPAddress.Loopback, 20000));
                node1.BucketList.Put(contact);
            }

            baseId[1] = 255;
            for (int i = 0; i < 20; i++)
            {
                baseId[19] = (byte)i;
                KadContactNode contact = new KadContactNode(new KadId(baseId), new IPEndPoint(IPAddress.Loopback, 20000));
                node1.BucketList.Put(contact);
            }

            KadValue value = new KadValue(node1.BucketList.Buckets.Aggregate((o, n) => o.Id < n.Id ? n : o).GetNodes().Aggregate((o, n) => o.Id > n.Id ? n : o).Id, DateTime.UtcNow, new byte[20]);

            Assert.IsFalse(node1.IsValueExpired(value));

            KadValue expiredVal = new KadValue(value.Id, value.Timestamp.AddSeconds(-(node1.ValueExpirationInSec + 1)), new byte[20]);

            Assert.IsTrue(node1.IsValueExpired(expiredVal));

            node1.Shutdown();
        }
Пример #11
0
        public void RetrieveValues()
        {
            KadNode node1 = new KadNode(new System.Net.IPEndPoint(IPAddress.Loopback, 55555));
            KadNode node2 = new KadNode(new System.Net.IPEndPoint(IPAddress.Loopback, 55556));

            List <KadValue> values = new List <KadValue>(20);

            for (int i = 0; i < 20; i++)
            {
                var value = new KadValue(kademlia_dht.Base.KadId.GenerateRandom(), DateTime.UtcNow, new byte[20]);
                values.Add(value);
                node2.Storage.Put(value);
                Thread.Sleep(500);
            }

            values = values.OrderBy((v) => v.Id.GetNumericValue()).ToList();
            node1.BucketList.Put(new KadContactNode(node2.Id, node2.EndPoint));
            var foundVal = node1.FindValue(node2.Id, values.First().Id);

            Assert.AreEqual(values.First().Id.GetNumericValue(), foundVal.Value.Id.GetNumericValue());

            node1.Shutdown();
            node2.Shutdown();
        }
Пример #12
0
        public void KadNodeUnit_SaveLoadBucketsAndValues()
        {
            KadNode     kadNode = new KadNode(new System.Net.IPEndPoint(IPAddress.Loopback, 55555));
            KadNodeUnit unit    = new KadNodeUnit(kadNode);

            for (int i = 0; i < 20; i++)
            {
                var contact = new kademlia_dht.Base.KadContactNode(kademlia_dht.Base.KadId.GenerateRandom(), new System.Net.IPEndPoint(IPAddress.Loopback, 20000));
                unit.Node.BucketList.Put(contact);
                Thread.Sleep(1000);
            }

            byte[] value = new byte[20];
            for (int i = 0; i < 20; i++)
            {
                value[0] = (byte)(i + 1);
                var valId = new KadId(value);
                value[19] = (byte)i;
                var kadValue = new KadValue(valId, DateTime.UtcNow, value);

                if (i % 3 == 0)
                {
                    byte[] ownId = new byte[20];
                    ownId[3] = (byte)i;
                    unit.Node.Storage.PutOwnerVal(new KadValue(new KadId(ownId), DateTime.UtcNow, value));
                }
                else
                {
                    unit.Node.Storage.Put(kadValue);
                }

                Thread.Sleep(1000);
            }

            string savePath = "nodewithbuckets.xml";

            unit.SaveToFile(savePath);
            unit.Stop();

            KadNodeUnit unit2 = new KadNodeUnit(savePath);

            Assert.IsTrue(unit2.Node.Id.GetNumericValue() == unit.Node.Id.GetNumericValue());
            Assert.IsTrue(unit2.Node.EndPoint.Address.ToString() == unit.Node.EndPoint.Address.ToString());
            Assert.IsTrue(unit2.Node.EndPoint.Port == unit.Node.EndPoint.Port);
            CollectionAssert.AreEqual(unit2.Node.BucketList
                                      .Buckets.Select((b) => b.Id).ToList(), unit.Node.BucketList.Buckets.Select((b) => b.Id).ToList());

            CollectionAssert.AreEqual(unit2.Node.BucketList
                                      .Buckets
                                      .SelectMany((b) => b.GetNodes())
                                      .Select((n) => n.Id.GetNumericValue())
                                      .OrderBy((id) => id)
                                      .ToList(),
                                      unit.Node.BucketList
                                      .Buckets
                                      .SelectMany((b) => b.GetNodes())
                                      .Select((n) => n.Id.GetNumericValue())
                                      .OrderBy((id) => id)
                                      .ToList());
            CollectionAssert.AreEqual(unit2.Node.Storage.Values
                                      .Select((v) => v.Id.GetNumericValue())
                                      .OrderBy((id) => id)
                                      .ToList(),
                                      unit.Node.Storage.Values
                                      .Select((v) => v.Id.GetNumericValue())
                                      .OrderBy((id) => id)
                                      .ToList());

            CollectionAssert.AreEqual(unit2.Node.Storage.OwnerValues
                                      .Select((v) => v.Id.GetNumericValue())
                                      .OrderBy((id) => id)
                                      .ToList(),
                                      unit.Node.Storage.OwnerValues
                                      .Select((v) => v.Id.GetNumericValue())
                                      .OrderBy((id) => id)
                                      .ToList());

            CollectionAssert.AreEqual(unit2.Node.Storage.OwnerValues
                                      .Select((v) => v.Timestamp)
                                      .OrderBy((t) => t)
                                      .ToList(),
                                      unit.Node.Storage.OwnerValues
                                      .Select((v) => v.Timestamp)
                                      .OrderBy((t) => t)
                                      .ToList());
        }
Пример #13
0
        /// <summary>
        /// Store value in contact
        /// </summary>
        /// <param name="node">Contact node</param>
        /// <param name="value">Value to store</param>
        /// <returns>true, if node stored value</returns>
        public bool StoreValue(KadId id, KadValue value)
        {
            var bucket = BucketList.GetBucket(id);

            return(StoreValue(bucket.GetNode(id), value));
        }