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) }
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); }
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); }
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); } }); } } }
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); } }
/// <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); }
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); }
/// <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}; }
/// <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); }
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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); } }
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); }
/// <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); }