public void RetrieveValues_NoValuesInStorage() { KadNode node1 = new KadNode(new System.Net.IPEndPoint(IPAddress.Loopback, 55555)); KadNode node2 = new KadNode(new System.Net.IPEndPoint(IPAddress.Loopback, 55556)); List <KadContactNode> nodes = new List <KadContactNode>(20); 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)); nodes.Add(contact); node2.BucketList.Put(contact); Thread.Sleep(500); } nodes = nodes.OrderBy((n) => n.Id.GetNumericValue()).ToList(); node1.BucketList.Put(new KadContactNode(node2.Id, node2.EndPoint)); var foundNodes = node1.FindValue(node2.Id, KadId.GenerateRandom()).Contacts; CollectionAssert.AreEqual(foundNodes.Select((n) => n.Id.GetNumericValue()).OrderBy((n) => n).ToList(), nodes.Select((n) => n.Id.GetNumericValue()).OrderBy((n) => n).ToList()); node1.Shutdown(); node2.Shutdown(); }
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); }
/// <summary> /// Pings other node /// </summary> /// <param name="node">Node to ping</param> /// <returns></returns> public NodeMessage Ping(KadContactNode node) { NodeMessage msg = new NodeMessage.Builder() .SetType(MessageType.Ping) .SetOriginator(node.Id) .Build(); msg.AddCallback(UpdateLastSeen); return(_server.SendMessageSync(node.EndPoint, msg, TimeoutInMSec).Response); }
public void Bucket_Contains() { Bucket bucket = new Bucket(1, 20); KadContactNode node = new kademlia_dht.Base.KadContactNode(kademlia_dht.Base.KadId.GenerateRandom(), new System.Net.IPEndPoint(IPAddress.Loopback, 20000)); bucket.Put(node); Assert.IsTrue(bucket.Contains(node.Id)); Assert.IsFalse(bucket.Contains(KadId.GenerateRandom())); }
/// <summary> /// Retrives value from other node /// </summary> /// <param name="node">Node to query</param> /// <param name="valId">Value id</param> /// <returns>Value if queried node has value, otherwise closest nodes to id</returns> public NodeMessage FindValue(KadContactNode node, KadId valId) { NodeMessage findValMsg = new NodeMessage.Builder() .SetType(MessageType.FindValue) .SetOriginator(Id) .SetIsRequest(true) .SetPayload(valId.Value) .Build(); findValMsg.AddCallback(UpdateLastSeen); return(_server.SendMessageSync(node.EndPoint, findValMsg, TimeoutInMSec).Response); }
/// <summary> /// Checks if other node can store value /// </summary> /// <param name="node">Node to check</param> /// <returns>True if node can store value</returns> public bool CanStoreValue(KadContactNode node) { NodeMessage canStoreValueMsg = new NodeMessage.Builder() .SetType(MessageType.CanStoreValue) .SetOriginator(Id) .SetIsRequest(true) .Build(); canStoreValueMsg.AddCallback(UpdateLastSeen); NodeMessage response = _server.SendMessageSync(node.EndPoint, canStoreValueMsg, TimeoutInMSec).Response; return(response != null && response.Payload[0] > 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); }
public bool TryReplaceLeastSeenContactFromBucket(KadContactNode newContact) { var bucket = Owner.BucketList.GetBucket(newContact.Id); var leastSeen = bucket.GetLeastSeen(); NodeMessage pongMsg = Owner.Ping(leastSeen); if (pongMsg == null) { bucket.Replace(leastSeen.Id, newContact); return(true); } return(false); }
public void BucketList_Put() { BucketList bucketList = new BucketList(KadId.GenerateRandom(), 20); byte[] kadId = new byte[20]; for (int i = 0; i < 20; i++) { kadId[19] = (byte)(i + 1); var contact = new kademlia_dht.Base.KadContactNode(new KadId(kadId), new System.Net.IPEndPoint(IPAddress.Loopback, 20000)); bucketList.Put(contact); Thread.Sleep(1000); } kadId[19] = 20; Assert.IsTrue(bucketList.Put(new KadContactNode(new KadId(kadId), new IPEndPoint(IPAddress.Loopback, 20000))) == BucketList.BucketPutResult.BucketIsFull); }
public void Bucket_GetLeastSeen_Reversed() { Bucket bucket = new Bucket(1, 20); KadContactNode leastSeen = null; 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)); leastSeen = contact; bucket.Put(contact); Thread.Sleep(1000); } Assert.IsTrue(bucket.IsFull()); Assert.IsFalse(leastSeen.Id.GetNumericValue() == bucket.GetLeastSeen().Id.GetNumericValue()); }
public void Bucket_PutAndRetrive() { Bucket bucket = new Bucket(1, 20); List <KadContactNode> nodes = new List <KadContactNode>(20); 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)); nodes.Add(contact); bucket.Put(contact); } for (int i = 0; i < nodes.Count; i++) { Debug.WriteLine(bucket.GetNode(nodes[i].Id)); } }
public KadHashTable(KadNode node, KadContactNode knownNode = null, KadHashTableConfiguration kadHashTableConfig = null) { Owner = node; if (knownNode != null) { Owner.BucketList.Put(knownNode); } if (kadHashTableConfig != null) { ReplicationCount = kadHashTableConfig.ReplicationCount ?? ReplicationCount; MaxConcurrentThreads = kadHashTableConfig.MaxConcurrentThreads ?? MaxConcurrentThreads; ReplicationInSecs = kadHashTableConfig.ReplicationInSecs ?? ReplicationInSecs; RepublicationInSecs = kadHashTableConfig.RepublicationInSecs ?? RepublicationInSecs; BucketsRefreshInSecs = kadHashTableConfig.BucketsRefreshInSecs ?? BucketsRefreshInSecs; } InitTable(); }
/// <summary> /// Find contact's closest nodes to id /// </summary> /// <param name="node">Node to query</param> /// <param name="id">Id to compare</param> /// <returns>Closest nodes to id</returns> public IEnumerable <KadContactNode> FindNode(KadContactNode node, KadId id) { NodeMessage msg = new NodeMessage.Builder() .SetType(MessageType.FindNode) .SetOriginator(Id) .SetIsRequest(true) .SetPayload(id.Value) .Build(); NodeMessage response = _server.SendMessageSync(node.EndPoint, msg, TimeoutInMSec).Response; msg.AddCallback(UpdateLastSeen); if (response != null) { return(new List <KadContactNode>(response.Contacts)); } return(new List <KadContactNode>()); }
public void KadNodeUnit_SaveLoadBuckets() { 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); } 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()); }
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()); }