/// <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); }
/// <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 void MessageParseTest() { KadId id = KadId.GenerateRandom(); NodeMessage msg = new NodeMessage.Builder() .SetType(MessageType.Ping) .SetOriginator(id) .Build(); NodeMessage msgParsed = new NodeMessage.Builder(msg.ToBytes()).Build(); Assert.AreEqual(id.GetNumericValue(), new KadId(id.Value).GetNumericValue()); Assert.AreEqual(msg.Type, msgParsed.Type); Assert.AreEqual(msg.Seq, msgParsed.Seq); Assert.AreEqual(msg.OriginatorId.GetNumericValue(), msgParsed.OriginatorId.GetNumericValue()); }
/// <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>()); }
private void ListenIncoming(KadNode ownerNode) { IPEndPoint incomingIpEndPoint = new IPEndPoint(IPAddress.Any, EndPoint.Port); while (!_stopped) { try { byte[] rawMsg = _udpClient.Receive(ref incomingIpEndPoint); NodeMessage incomingMsg = new NodeMessage.Builder(rawMsg).Build(); //TODO: msg validation ulong msgIdx = GetMessageId(incomingIpEndPoint.Address, incomingMsg.Seq); //TODO: two spare bytes for port if (_messages.ContainsKey(msgIdx)) { NodeMessage rqMsg = null; if (_messages.TryRemove(msgIdx, out rqMsg)) { rqMsg.ProcessResponse(incomingMsg); } } else { if (incomingMsg.IsRequest) { ownerNode.ProcessRequest(incomingMsg, incomingIpEndPoint); _messages.AddOrUpdate(msgIdx, incomingMsg, (k, v) => v); } } } catch (SocketException se) { if (se.SocketErrorCode != SocketError.Interrupted) { throw se; } } incomingIpEndPoint = new IPEndPoint(IPAddress.Any, EndPoint.Port); } }
/// <summary> /// Processes request from other node. Used by NodeServer class /// </summary> /// <param name="msg">Request to process</param> /// <param name="origAddress">Request originator adress</param> public void ProcessRequest(NodeMessage msg, IPEndPoint origAddress) { switch (msg.Type) { case MessageType.Ping: { //TODO: handle cases when bucket is full, etc NodeMessage respMsg = new NodeMessage.Builder() .SetType(MessageType.Ping) .SetOriginator(Id) .SetSeq(msg.Seq) .SetIsRequest(false) .Build(); _server.SendMessage(origAddress, respMsg); break; } case MessageType.FindNode: { var closestNodes = BucketList.GetClosestNodes(new KadId(msg.Payload), 20); NodeMessage respMsg = new NodeMessage.Builder() .SetType(MessageType.FindNode) .SetSeq(msg.Seq) .SetOriginator(Id) .SetContacts(closestNodes) .Build(); _server.SendMessage(origAddress, respMsg); break; } case MessageType.FindValue: { KadId valueId = new KadId(msg.Payload); NodeMessage.Builder msgBuilder = new NodeMessage.Builder() .SetType(MessageType.FindValue) .SetSeq(msg.Seq) .SetOriginator(Id); if (Storage.Contains(valueId)) { msgBuilder.SetKadValueAsPayload(Storage.Get(valueId)); } else { var closestNodes = BucketList.GetClosestNodes(valueId, 20); msgBuilder.SetContacts(closestNodes) .SetType(MessageType.FindNode); } _server.SendMessage(origAddress, msgBuilder.Build()); break; } case MessageType.CanStoreValue: { NodeMessage respMsg = new NodeMessage.Builder() .SetType(MessageType.CanStoreValue) .SetSeq(msg.Seq) .SetOriginator(Id) .SetIsRequest(false) .SetFlagAsPayload(!Storage.IsFull()) .Build(); _server.SendMessage(origAddress, respMsg); break; } case MessageType.StoreValue: { NodeMessage.Builder msgBuilder = new NodeMessage.Builder() .SetSeq(msg.Seq) .SetOriginator(Id) .SetIsRequest(false) .SetType(MessageType.CanStoreValue); if (Storage.IsFull()) { msgBuilder.SetFlagAsPayload(false); } else { msgBuilder.SetFlagAsPayload(true); Storage.Put(msg.Value); } _server.SendMessage(origAddress, msgBuilder.Build()); break; } } UpdateLastSeen(msg); }