Example #1
0
        internal static void PrepareOverlappedFakeContacts(Kademlia kademlia1, Kademlia kademlia2, int contacts)
        {
            for (int i = 0; i < contacts; i++)
            {
                var id = KademliaId.RandomId;
                var ni = new NodeInformation(new IPEndPoint(IPAddress.Loopback, 12345), id);

                RegisterFakeContact(kademlia1, ni);
            }
            for (int i = 0; i < contacts; i++)
            {
                var id = KademliaId.RandomId;
                var ni = new NodeInformation(new IPEndPoint(IPAddress.Loopback, 12345), id);

                RegisterFakeContact(kademlia2, ni);
            }
            for (int i = 0; i < contacts; i++)
            {
                var id = KademliaId.RandomId;
                var ni = new NodeInformation(new IPEndPoint(IPAddress.Loopback, 12345), id);

                RegisterFakeContact(kademlia1, ni);
                RegisterFakeContact(kademlia2, ni);
            }
        }
Example #2
0
        internal void RemoveFromKademliaWhenRequestTimeout()
        {
            var id = KademliaId.RandomId;
            var ni = new NodeInformation(new IPEndPoint(IPAddress.Loopback, 65432), id);
            var message = new UdpMessage();
            kademlia.HandleIncomingRequest(ni, message);
            var response = new UdpMessage();
            response.ResponseId = message.RequestId;
            response.SenderNodeId = id;

            message.ResponseCallback(response);
            Assert.AreEqual(1, kademlia.CurrentContactCount);

            // actual test

            bool noResponse = false;
            message = new UdpMessage();
            message.PingRequest = new PingRequest();
            message.ResponseCallback = udpMessage => Assert.Fail("The response callback should not be called in this test");
            message.NoResponseCallback = () => noResponse = true;

            node.SendUdpMessage(message, ni.EndPoint, id);

            for (int i = 0; i < Node.TimeoutTicks; i++)
                node.TimerElapsed();
            Assert.AreEqual(1, kademlia.CurrentContactCount);

            for (int i = 0; i < Node.TimeoutTicks; i++)
                node.TimerElapsed();
            Assert.IsTrue(noResponse, "The no-response callback should be called in this test");
            Assert.AreEqual(0, kademlia.CurrentContactCount);
        }
Example #3
0
        internal static void RegisterFakeContact(Kademlia kademlia, NodeInformation ni)
        {
            var message = new UdpMessage();
            kademlia.HandleIncomingRequest(ni, message);

            if (message.ResponseCallback == null)
                return;

            var response = new UdpMessage();
            response.ResponseId = message.RequestId;
            response.SenderNodeId = ni.NodeId;
            message.ResponseCallback(response);
        }
        internal void PrepareKademlia()
        {
            node = new Node(null);
            kademlia = node.Kademlia;

            node2 = new Node(12345, null);
            kademlia2 = node2.Kademlia;

            targetId = node2.Id;

            var ni = new NodeInformation(new IPEndPoint(IPAddress.Loopback, 12345), targetId);
            TestHelper.RegisterFakeContact(kademlia, ni);

            // set LastSeen to a time beyond the ping interval
            var contact = Mirror.ForObject(kademlia)["FirstContact"].Invoke();
            Mirror.ForObject(contact)["LastSeen"].Value = DateTime.Now - TimeSpan.FromHours(1.1);
        }
Example #5
0
        internal void KademliaContactsAfterNewContact()
        {
            for (int i = 0; i < 10; i++)
            {
                var id = KademliaId.RandomId;
                var ni = new NodeInformation(new IPEndPoint(i + 1, i + 1), id);
                var message = new UdpMessage();
                kademlia.HandleIncomingRequest(ni, message);

                Assert.AreEqual(i, kademlia.CurrentContactCount);
                Assert.IsNotNull(message.PingRequest);

                var response = new UdpMessage();
                response.ResponseId = message.RequestId;
                response.SenderNodeId = id;
                message.ResponseCallback(response);

                Assert.AreEqual(i + 1, kademlia.CurrentContactCount);
            }
        }
Example #6
0
        internal void CreateNodes()
        {
            KyruTimer.Reset();

            nodeA = new KyruApplication(12345).Node;
            nodeB = new KyruApplication(12346).Node;
            nodeC = new KyruApplication(12347).Node;

            nodeAInfo = new NodeInformation(new IPEndPoint(IPAddress.Loopback, 12345), nodeA.Id);
            nodeBInfo = new NodeInformation(new IPEndPoint(IPAddress.Loopback, 12346), nodeB.Id);
            nodeCInfo = new NodeInformation(new IPEndPoint(IPAddress.Loopback, 12347), nodeC.Id);

            nodeA.Start();
            nodeB.Start();
            nodeC.Start();

            nodeA.Kademlia.AddNode(nodeBInfo.EndPoint);
            nodeC.Kademlia.AddNode(nodeBInfo.EndPoint);

            KyruTimer.Start();

            Thread.Sleep(TestParameters.LocalhostCommunicationTimeout);
        }
Example #7
0
 private bool Equals(NodeInformation other)
 {
     return Equals((KademliaId)NodeId, (KademliaId)other.NodeId) && IpAddress == other.IpAddress && Port == other.Port;
 }
Example #8
0
 internal KnownNode(NodeInformation node)
 {
     Node = node;
     LastSeen = DateTime.Now;
 }
Example #9
0
        /// <returns>Whether the contact needs to be pinged.</returns>
        private bool IsNewContact(NodeInformation contact)
        {
            if (node.Id == contact.NodeId)
                return false;

            var bucket = buckets[(node.Id - contact.NodeId).KademliaBucket()];
            if (bucket.Count >= k)
            {
                // the bucket is full
                return false;
            }
            return bucket.Find(n => n.Node == contact) == null;
        }
Example #10
0
        private void AddContact(NodeInformation contact)
        {
            if (node.Id == contact.NodeId)
                return;

            var bucketIndex = (node.Id - contact.NodeId).KademliaBucket();
            var bucket = buckets[bucketIndex];

            var existingContact = bucket.FirstOrDefault(n => n.Node == contact);
            if (existingContact == null)
            {
                if (bucket.Count >= k)
                {
                    // the bucket is full
                    return;
                }
                //this.Log("Adding contact {0} ({1})", contact.NodeId, contact.EndPoint);
                bucket.Add(new KnownNode(contact));

                if (CurrentContactCount == 1)
                {
                    // populate the contacts list
                    NodeLookup(node.Id, nodes =>
                                        {
                                            foreach (var n in nodes)
                                            {
                                                NodeLookup(n.NodeId, _ => { });
                                            }
                                        });
                }
            }
            else
            {
                existingContact.LastSeen = DateTime.Now;
            }
        }
Example #11
0
        /// <summary>
        /// Notifies Kademlia about incoming request messages, to maintain the contact list. If necessary, a ping request is added to the response message.
        /// </summary>
        /// <param name="sendingNode">The node that sent us a request.</param>
        /// <param name="outgoingMessage">The message object that will be sent.</param>
        internal void HandleIncomingRequest(NodeInformation sendingNode, UdpMessage outgoingMessage)
        {
            if (sendingNode.NodeId == node.Id)
                return;

            if (IsNewContact(sendingNode))
            {
                outgoingMessage.PingRequest = new PingRequest();
                outgoingMessage.ResponseCallback = message => AddContact(new NodeInformation(sendingNode.EndPoint, message.SenderNodeId));
            }
            else
            {
                AddContact(sendingNode);
            }
        }
Example #12
0
        /// <summary>Processes an incoming FindNode request.</summary>
        /// <param name="node">The sending node</param>
        /// <param name="request">The message received from the sending node</param>
        private void IncomingFindNode(NodeInformation node, UdpMessage request)
        {
            UdpMessage response = CreateUdpReply(request);
            Kademlia.HandleIncomingRequest(node, response);

            var contacts = Kademlia.NearestContactsTo(request.FindNodeRequest.NodeId, node.NodeId);
            response.FindNodeResponse = new FindNodeResponse();
            response.FindNodeResponse.Nodes = contacts.ToArray();

            SendUdpMessage(response, node);
        }
Example #13
0
        private void StoreTestObject()
        {
            // create the test object

            objectId = KademliaId.RandomId;
            var chunkId = KademliaId.RandomId;

            var user = new User();
            user.ObjectId = objectId;
            var userFile = new UserFile();
            userFile.ChunkList.Add(chunkId);
            user.Add(userFile);

            var ms = new MemoryStream();
            Serializer.Serialize(ms, user);
            bytes = ms.ToArray();

            // store it

            var ct = new CallbackTimeout<Error>();
            var ni = new NodeInformation(new IPEndPoint(IPAddress.Loopback, nodes[1].Port), nodes[1].Id);
            nodes[0].StoreObject(ni, objectId, bytes, ct.Done);
            if (!ct.Block(TestParameters.LocalhostCommunicationTimeout))
            {
                Assert.Fail("No response within timeout");
            }
            Assert.AreEqual(Error.Success, ct.Result);
        }
Example #14
0
        /// <summary>Processes an incoming FindValue request.</summary>
        /// <param name="node">The sending node</param>
        /// <param name="request">The message received from the sending node</param>
        private void IncomingFindValue(NodeInformation node, UdpMessage request)
        {
            UdpMessage response = CreateUdpReply(request);
            Kademlia.HandleIncomingRequest(node, response);

            response.FindValueResponse = new FindValueResponse();

            var metadata = MetadataStorage.Get(request.FindValueRequest.ObjectId);
            if (metadata == null)
            {
                var contacts = Kademlia.NearestContactsTo(request.FindValueRequest.ObjectId, request.SenderNodeId);
                response.FindValueResponse.Nodes = contacts.ToArray();
            }
            else
            {
                response.FindValueResponse.Data = metadata;
            }

            SendUdpMessage(response, node);
        }
Example #15
0
 internal void StoreObject(NodeInformation targetNode, KademliaId objectId, byte[] bytes, Action<Error> done)
 {
     new Thread(new StoreObjectClient(app, targetNode, objectId, bytes, done).ThreadStart).Start();
 }
Example #16
0
 /// <summary>Sends an UDP message to a given node.</summary>
 /// <param name="message">The message to be sent.</param>
 /// <param name="targetNode">The target node.</param>
 private void SendUdpMessage(UdpMessage message, NodeInformation targetNode)
 {
     SendUdpMessage(message, targetNode.EndPoint, targetNode.NodeId);
 }
Example #17
0
        private void OnUdpReceive(IAsyncResult ar)
        {
            if (!running)
            {
                return;
            }
            var endPoint = new IPEndPoint(IPAddress.Any, 0);
            var data = udp.EndReceive(ar, ref endPoint);
            UdpListen();

            var ms = new MemoryStream(data);
            var protocolVersion = ms.ReadByte();
            if (protocolVersion != ProtocolVersion)
            {
                this.Warn("Ignoring message from {0} with unknown protocol version {1}", endPoint, protocolVersion);
                return;
            }

            var incomingMessage = Serializer.Deserialize<UdpMessage>(ms);

            if (!incomingMessage.Validate(endPoint))
                return;

            var ni = new NodeInformation(endPoint, incomingMessage.SenderNodeId);

            if (incomingMessage.ResponseId != 0)
            {
                var identifier = new RequestIdentifier {EndPoint = ni.EndPoint, RequestId = incomingMessage.ResponseId};

                lock (outstandingRequests)
                {
                    if (!outstandingRequests.ContainsKey(identifier))
                    {
                        this.Warn("{2} from {0} has unknown response ID {1:X16}", endPoint, incomingMessage.ResponseId, incomingMessage.Inspect());
                    }
                    else
                    {
                        var request = outstandingRequests[identifier];

                        if (request.NodeId != null && request.NodeId != incomingMessage.SenderNodeId)
                        {
                            this.Warn("In {0}, node ID from {1} does not match (expected {2}, received {3})", incomingMessage.Inspect(), endPoint, request.NodeId, (KademliaId) incomingMessage.SenderNodeId);
                        }
                        else
                        {
                            outstandingRequests.Remove(identifier);

                            // the callback will deal with handling the actual response
                            request.OutgoingMessage.ResponseCallback(incomingMessage);
                        }
                    }
                }
            }

            if (incomingMessage.PingRequest != null)
            {
                IncomingPing(ni, incomingMessage);
            }
            else if (incomingMessage.FindNodeRequest != null)
            {
                IncomingFindNode(ni, incomingMessage);
            }
            else if (incomingMessage.FindValueRequest != null)
            {
                IncomingFindValue(ni, incomingMessage);
            }
            else if (incomingMessage.StoreRequest != null)
            {
                IncomingStore(ni, incomingMessage);
            }
            else if (incomingMessage.KeepObjectRequest != null)
            {
                IncomingKeepObject(ni, incomingMessage);
            }
        }
Example #18
0
        /// <summary>Processes an incoming Store request.</summary>
        /// <param name="node">The sending node</param>
        /// <param name="request">The message received from the sending node</param>
        private void IncomingStore(NodeInformation node, UdpMessage request)
        {
            UdpMessage response = CreateUdpReply(request);
            Kademlia.HandleIncomingRequest(node, response);

            MetadataStorage.Store(request.StoreRequest.ObjectId, request.StoreRequest.Data);

            response.StoreResponse = new StoreResponse();
            SendUdpMessage(response, node);
        }
Example #19
0
 /// <summary>Processes an incoming Ping request.</summary>
 /// <param name="node">The sending node</param>
 /// <param name="request">The message received from the sending node</param>
 private void IncomingPing(NodeInformation node, UdpMessage request)
 {
     UdpMessage response = CreateUdpReply(request);
     Kademlia.HandleIncomingRequest(node, response);
     SendUdpMessage(response, node);
 }
Example #20
0
        /// <summary>Processes an incoming KeepObject request.</summary>
        /// <param name="node">The sending node</param>
        /// <param name="request">The message received from the sending node</param>
        private void IncomingKeepObject(NodeInformation node, UdpMessage request)
        {
            UdpMessage response = CreateUdpReply(request);
            Kademlia.HandleIncomingRequest(node, response);

            response.KeepObjectResponse = new KeepObjectResponse();
            response.KeepObjectResponse.HasObject = app.LocalObjectStorage.KeepObject(request.KeepObjectRequest.ObjectId);

            SendUdpMessage(response, node);
        }