예제 #1
0
        internal void TestFindNode([Column(0, 1, 20, 100)] int contacts, [EnumData(typeof(TestHelper.PrepareType))] TestHelper.PrepareType prepareType)
        {
            switch (prepareType)
            {
                case TestHelper.PrepareType.Local:
                    TestHelper.PrepareFakeContacts(kademlia, contacts);
                    break;

                case TestHelper.PrepareType.Remote:
                    TestHelper.PrepareFakeContacts(kademlia2, contacts);
                    break;

                case TestHelper.PrepareType.Both:
                    TestHelper.PrepareFakeContacts(kademlia, kademlia2, contacts);
                    break;

                case TestHelper.PrepareType.Overlapped:
                    TestHelper.PrepareOverlappedFakeContacts(kademlia, kademlia2, contacts);
                    break;
            }

            var ct = new CallbackTimeout<UdpMessage>();
            var message = new UdpMessage();
            message.FindNodeRequest = new FindNodeRequest {NodeId = KademliaId.RandomId};
            message.ResponseCallback = ct.Done;

            node.SendUdpMessage(message, targetEndPoint, targetId);
            if (!ct.Block(TestParameters.LocalhostCommunicationTimeout))
            {
                Assert.Fail("No response within timeout");
            }

            // assumed success (too time-consuming to check)
        }
예제 #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);
        }
예제 #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);
        }
예제 #4
0
        public void TimerElapsed()
        {
            this.Log("Republishing metadata");

            lock (storage)
            {
                // remove expired metadata
                var deadline = DateTime.Now.UnixTimestamp() - 86400;

                var empty = new List<KademliaId>();

                foreach (var metadata in storage)
                {
                    metadata.Value.RemoveAll(m => deadline > m.Timestamp);

                    if (metadata.Value.Count == 0)
                        empty.Add(metadata.Key);
                }

                foreach (var id in empty)
                {
                    storage.Remove(id);
                }

                foreach (var metadata in storage)
                {
                    node.Kademlia.NodeLookup(metadata.Key, foundNodes =>
                                                           {
                                                               var storeRequest = new StoreRequest();
                                                               storeRequest.ObjectId = metadata.Key;
                                                               storeRequest.Data = metadata.Value.ToArray();

                                                               foreach (var foundNode in foundNodes)
                                                               {
                                                                   var message = new UdpMessage();
                                                                   message.StoreRequest = storeRequest;
                                                                   node.SendUdpMessage(message, foundNode.EndPoint, foundNode.NodeId);
                                                               }
                                                           });
                }
            }
        }
예제 #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);
            }
        }
예제 #6
0
 /// <summary>
 /// Adds a node to the kademlia contacts.
 /// </summary>
 internal void AddNode(IPEndPoint ep)
 {
     var ping = new UdpMessage();
     ping.PingRequest = new PingRequest();
     ping.ResponseCallback = response => AddVerifiedNode(ep, response.SenderNodeId);
     node.SendUdpMessage(ping, ep, null);
 }
예제 #7
0
        private void VerifyOwnership(KademliaId objectId, KyruObjectMetadata newItem)
        {
            var message = new UdpMessage();
            message.KeepObjectRequest = new KeepObjectRequest();
            message.KeepObjectRequest.ObjectId = objectId;
            message.ResponseCallback = delegate(UdpMessage udpMessage)
                                       {
                                           if (!udpMessage.KeepObjectResponse.HasObject) return;

                                           lock (storage)
                                           {
                                               if (!storage.ContainsKey(objectId))
                                                   storage[objectId] = new List<KyruObjectMetadata>();

                                               newItem.Timestamp = DateTime.Now.UnixTimestamp();
                                               storage[objectId].Add(newItem);
                                           }
                                       };
            node.SendUdpMessage(message, new IPEndPoint(newItem.IpAddress, newItem.Port), newItem.NodeId);
        }
예제 #8
0
파일: Node.cs 프로젝트: zr40/kyru-dotnet
 /// <summary>Creates a template reply UdpMessage with the ResponseId set based on the request message. Also notifies Kademlia about the request message.</summary>
 /// <param name="request">The incoming request message.</param>
 /// <returns>The created template reply message.</returns>
 private static UdpMessage CreateUdpReply(UdpMessage request)
 {
     return new UdpMessage {ResponseId = request.RequestId};
 }
예제 #9
0
파일: Node.cs 프로젝트: zr40/kyru-dotnet
 /// <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);
 }
예제 #10
0
파일: Node.cs 프로젝트: zr40/kyru-dotnet
        private void SendUdp(UdpMessage message, IPEndPoint target)
        {
            var s = new MemoryStream();
            s.WriteByte(ProtocolVersion);
            Serializer.Serialize(s, message);

            //this.Log("Sending {4} with length {0} with request ID {1:X16} to {2} (response ID {3:X16})", s.Length, message.RequestId, target, message.ResponseId, message.Inspect());
            udp.Send(s.GetBuffer(), (int) s.Length, target);
        }
예제 #11
0
파일: Node.cs 프로젝트: zr40/kyru-dotnet
        /// <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);
        }
예제 #12
0
파일: Node.cs 프로젝트: zr40/kyru-dotnet
 /// <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);
 }
예제 #13
0
파일: Node.cs 프로젝트: zr40/kyru-dotnet
        /// <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);
        }
예제 #14
0
파일: Node.cs 프로젝트: zr40/kyru-dotnet
        /// <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);
        }
예제 #15
0
파일: Node.cs 프로젝트: zr40/kyru-dotnet
        /// <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);
        }
예제 #16
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);
            }
        }
예제 #17
0
 private void CheckAlive(KnownNode contact, List<KnownNode> bucket)
 {
     var ping = new UdpMessage();
     ping.PingRequest = new PingRequest();
     ping.ResponseCallback = response => contact.LastSeen = DateTime.Now;
     ping.NoResponseCallback = () => bucket.Remove(contact);
     node.SendUdpMessage(ping, contact.Node.EndPoint, null);
 }
예제 #18
0
파일: Node.cs 프로젝트: zr40/kyru-dotnet
        /// <summary>Sends an UDP message to a given node.</summary>
        /// <param name="message">The message to be sent.</param>
        /// <param name="target">The address of the target node.</param>
        /// <param name="targetNodeId">The target node ID.</param>
        internal void SendUdpMessage(UdpMessage message, IPEndPoint target, KademliaId targetNodeId)
        {
            message.RequestId = Random.UInt64();
            message.SenderNodeId = Id;

            var requestIdentifier = new RequestIdentifier {EndPoint = target, RequestId = message.RequestId};
            var requestInformation = new RequestInformation {OutgoingMessage = message, SecondAttempt = false, NodeId = targetNodeId};

            if (message.IsRequest)
            {
                lock (outstandingRequests)
                {
                    outstandingRequests.Add(requestIdentifier, requestInformation);
                }
            }

            SendUdp(message, target);
        }