Beispiel #1
0
        /// <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);
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
 /// <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);
 }
Beispiel #4
0
        /// <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);
        }
Beispiel #5
0
        /// <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);
        }
Beispiel #6
0
        /// <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);
        }
Beispiel #7
0
        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;
                    }
                }
            }
        }