/// <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 <ContactNode> FindNode(ContactNode node, Id id) { Message.MnlMessage msg = new Message.MnlMessage.Builder() .SetType(MessageType.Query) .SetQueryType(QueryType.FindNode) .SetOriginatorId(Id) .Build(); msg.Payload.Add("target", id.Value); Message.MnlMessage response = _server.SendMessageSync(node, msg, _validateMsgs, TimeoutInMSec).Response; List <ContactNode> nodes = new List <ContactNode>(); if (response == null) { return(nodes); } UpdateLastSeen(node); if (response.Payload.ContainsKey("nodes")) { byte[] nodeString = (byte[])response.Payload["nodes"]; int offset = 0; while (offset < nodeString.Length) { nodes.Add(new ContactNode(nodeString, ref offset)); } } return(nodes); }
public void SendBadToken(IPEndPoint toEndPoint) { Message.MnlMessage badTokenMsg = new Message.MnlMessage.Builder() .SetType(MessageType.Error) .SetErrorCode(ErrorType.ProtocolError) .SetErrorMessage("Bad token") .Build(); SendMessage(toEndPoint, badTokenMsg); }
/// <summary> /// Pings other node /// </summary> /// <param name="node">Node to ping</param> /// <returns></returns> public MnlMessage Ping(IPEndPoint nodeEndPoint) { Message.MnlMessage msg = new Message.MnlMessage.Builder() .SetType(MessageType.Query) .SetQueryType(QueryType.Ping) .SetOriginatorId(Id) .Build(); //do not validate id if we don't know nothing about node except it's address return(_server.SendMessageSync(new ContactNode(Id, nodeEndPoint), msg, false, TimeoutInMSec).Response); }
/// <summary> /// Pings other node /// </summary> /// <param name="node">Node to ping</param> /// <returns></returns> public MnlMessage Ping(ContactNode node) { Message.MnlMessage msg = new Message.MnlMessage.Builder() .SetType(MessageType.Query) .SetQueryType(QueryType.Ping) .SetOriginatorId(Id) .Build(); UpdateLastSeen(node); return(_server.SendMessageSync(node, msg, _validateMsgs, TimeoutInMSec).Response); }
/// <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 bool GetPeers(ContactNode node, Id infohash, out IEnumerable <ContactNode> nodes, out object token) { Message.MnlMessage msg = new Message.MnlMessage.Builder() .SetType(MessageType.Query) .SetQueryType(QueryType.GetPeers) .SetOriginatorId(Id) .SetInfohash(infohash) .Build(); UpdateLastSeen(node); Message.MnlMessage response = _server.SendMessageSync(node, msg, _validateMsgs, TimeoutInMSec).Response; List <ContactNode> contacts = new List <ContactNode>(); nodes = contacts; token = null; if (response == null) { return(false); } if (response.Payload.ContainsKey("token")) { token = response.Payload["token"]; } if (response.Payload.ContainsKey("values")) { List <object> valuesStrings = (List <object>)response.Payload["values"]; foreach (object peerInfo in valuesStrings) { contacts.Add(ContactNode.FromPeerInfo(peerInfo as byte[])); } return(true); } else if (response.Payload.ContainsKey("nodes")) { byte[] nodeString = (byte[])response.Payload["nodes"]; int offset = 0; while (offset < nodeString.Length) { contacts.Add(new ContactNode(nodeString, ref offset)); } return(false); } return(false); }
/// <summary> /// Find contact's closest nodes to id /// </summary> /// <param name="node">Node to query</param> /// <param name="id">Id to compare</param> /// <returns></returns> public MnlMessage AnnouncePeer(ContactNode node, Id infohash, int port, object token, int?impliedPort) { Message.MnlMessage msg = new Message.MnlMessage.Builder() .SetType(MessageType.Query) .SetQueryType(QueryType.AnnouncePeer) .SetOriginatorId(Id) .SetInfohash(infohash) .Build(); msg.Payload.Add("port", port); msg.Payload.Add("implied_port", impliedPort ?? 0); msg.Payload.Add("token", token ?? new byte[0]); UpdateLastSeen(node); return(_server.SendMessageSync(node, msg, _validateMsgs, TimeoutInMSec).Response); }
private void ListenIncoming(Node ownerNode) { while (!_stopped) { try { IPEndPoint incomingIpEndPoint = new IPEndPoint(IPAddress.Any, EndPoint.Port); byte[] rawMsg = _udpClient.Receive(ref incomingIpEndPoint); if (!IsLegitMnlDhtMessage(rawMsg)) { continue; } Message.MnlMessage incomingMsg = null; try { incomingMsg = new Message.MnlMessage.Builder(rawMsg).Build(); } catch (Bittorrent.InvalidFieldException ife) { MnlMessage errMessage = new MnlMessage.Builder() .SetTranId(GenerateTranId()) .SetType(MessageType.Error) .SetErrorCode(ErrorType.ProtocolError) .SetErrorMessage(ife.Message) .Build(); Debug.WriteLine($"Sending incorrect field message {ife.Message}"); SendMessage(incomingIpEndPoint, errMessage); continue; } catch (MalformedPacketException mpe) { MnlMessage errMessage = new MnlMessage.Builder() .SetTranId(GenerateTranId()) .SetType(MessageType.Error) .SetErrorCode(ErrorType.ProtocolError) .SetErrorMessage(mpe.Message) .Build(); Debug.WriteLine($"Sending malformed packet message {mpe.Message}"); SendMessage(incomingIpEndPoint, errMessage); continue; } ulong msgIdx = GetMessageId(incomingIpEndPoint.Address, BitConverter.ToUInt16(Encoding.ASCII.GetBytes(incomingMsg.TranId.PadLeft(2, '\0')), 0)); if (_messages.ContainsKey(msgIdx)) { PendingMnlMessage rqMsg; if (_messages.TryRemove(msgIdx, out rqMsg)) { if (incomingMsg.Type == MessageType.Error) { Debug.WriteLine($"Recieved error {incomingMsg.ErrorMessage}"); switch (incomingMsg.ErrorCode) { case ErrorType.ProtocolError: case ErrorType.MethodUnknown: Debug.WriteLine($"!!!Error {incomingMsg.ErrorMessage}"); break; default: continue; } } if (rqMsg.ValidateId) { if (rqMsg.RecipientId != incomingMsg.OriginatorId) { Debug.WriteLine($"Node {incomingIpEndPoint} id mismatch!"); OnMaliciousMessage?.Invoke(incomingIpEndPoint, rqMsg.RecipientId, rqMsg.SentMessage); continue; } } rqMsg.SentMessage.SetResponse(incomingMsg); } } else { if (incomingMsg.Type == MessageType.Query) { ownerNode.ProcessQuery(incomingMsg, incomingIpEndPoint); } } } catch (SocketException se) { if (se.SocketErrorCode != SocketError.Interrupted) { throw; } } } }