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); }
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()); }
private void ReplicateValue(KadValue value) { var closestNodes = Owner.BucketList.GetClosestNodes(value.Id, ReplicationCount); foreach (var node in closestNodes) { Owner.StoreValue(node, value); } }
public void StoreValue(KadValue value) { if (!Owner.Storage.Contains(value.Id)) { Owner.Storage.PutOwnerVal(value); } ReplicateValue(value); }
/// <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); }
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(); }
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(); }
/// <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); }
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(); }
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(); }
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(); }
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()); }
/// <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)); }