Ejemplo n.º 1
0
        private async Task ProcessMsgData()
        {
            while (running)
            {
                if (!_recvMessageQueue.TryTake(out DhtData dhtData))
                {
                    await Task.Delay(1000);

                    continue;
                }
                try
                {
                    var dic = (Dictionary <string, object>)BEncoder.Decode(dhtData.Data);
                    var msg = new DhtMessage(dic);
                    switch (msg.MesageType)
                    {
                    case MessageType.Request:
                        var item = new Tuple <DhtMessage, IPEndPoint>(msg, dhtData.RemoteEndPoint);
                        _requestQueue.TryAdd(item);
                        break;

                    case MessageType.Response:
                        if (msg.MessageId.Length != 2)
                        {
                            continue;
                        }
                        var remotePoint  = dhtData.RemoteEndPoint;
                        var responseNode = new DhtNode()
                        {
                            NodeId = (byte[])msg.Data["id"], Host = remotePoint.Address, Port = (ushort)remotePoint.Port
                        };
                        var flag = await MessageMap.RequireRegisteredInfoAsync(msg, responseNode);

                        if (!flag)
                        {
                            continue;
                        }
                        _responseQueue.TryAdd(new Tuple <DhtMessage, DhtNode>(msg, responseNode), 10);
                        break;
                    }
                }
                catch (Exception ex)
                {
                    if (ex is DecodeException)
                    {
                        filterPeers.Add(dhtData.RemoteEndPoint.ToInt64());
                        continue;
                    }
                    _logger.Error($"ErrorData:{BitConverter.ToString(dhtData.Data)}", ex);
                    var response = new DhtMessage
                    {
                        MesageType = MessageType.Exception,
                        MessageId  = new byte[] { 0, 0 }
                    };
                    response.Errors.Add(202);
                    response.Errors.Add("Server Error:" + ex.Message);
                    _sendMessageQueue.TryAdd(new Tuple <DhtMessage, DhtNode>(response, new DhtNode(dhtData.RemoteEndPoint)));
                }
            }
        }
Ejemplo n.º 2
0
        public void AnnouncePeer(DhtNode node, byte[] infoHash, ushort port, string token)
        {
            var data = new Dictionary <string, object> {
                { "info_hash", infoHash }, { "port", port }, { "token", token }
            };

            SendMsg(CommandType.Announce_Peer, data, node);
        }
Ejemplo n.º 3
0
        public bool GetPeers(DhtNode node, byte[] infoHash)
        {
            var data = new Dictionary <string, object> {
                { "info_hash", infoHash }
            };

            return(SendMsg(CommandType.Get_Peers, data, node));
        }
Ejemplo n.º 4
0
        public bool FindNode(DhtNode node)
        {
            var data = new Dictionary <string, object> {
                { "target", GenerateRandomNodeId() }
            };

            return(SendMsg(CommandType.Find_Node, data, node));
        }
Ejemplo n.º 5
0
 public bool AddBootstrapNode(DhtNode node)
 {
     if (running)
     {
         return(false);
     }
     _bootstrapNodes.Add(node);
     return(true);
 }
Ejemplo n.º 6
0
        private bool SendMsg(CommandType command, IDictionary <string, object> data, DhtNode node)
        {
            var msg = new DhtMessage
            {
                CommandType = command,
                MesageType  = MessageType.Request,
                Data        = new SortedDictionary <string, object>(data)
            };

            msg.Data.Add("id", GetNeighborNodeId(node.NodeId));
            var dhtItem = new Tuple <DhtMessage, DhtNode>(msg, node);

            return(msg.CommandType == CommandType.Get_Peers ? _sendMessageQueue.TryAdd(dhtItem, EnqueueWaitTime) : _sendMessageQueue.TryAdd(dhtItem));
        }
Ejemplo n.º 7
0
        public DhtClient(DhtConfig config)
        {
            _endPoint = new IPEndPoint(IPAddress.Any, config.Port);
            _client   = new UdpClient(_endPoint)
            {
                Ttl = byte.MaxValue
            };
            switch (Environment.OSVersion.Platform)
            {
            case PlatformID.Win32NT:
            case PlatformID.Win32S:
            case PlatformID.Win32Windows:
            case PlatformID.WinCE:
                _client.Client.IOControl(-1744830452, new byte[] { Convert.ToByte(false) }, new byte[4]);
                break;
            }

            _node = new DhtNode()
            {
                Host = IPAddress.Any, Port = config.Port, NodeId = GenerateRandomNodeId()
            };
            _kTable = new RouteTable(config.KTableSize);

            _nodeQueue         = new BlockingCollection <DhtNode>(config.NodeQueueMaxSize);
            _recvMessageQueue  = new BlockingCollection <DhtData>(config.ReceiveQueueMaxSize);
            _requestQueue      = new BlockingCollection <Tuple <DhtMessage, IPEndPoint> >(config.RequestQueueMaxSize);
            _responseQueue     = new BlockingCollection <Tuple <DhtMessage, DhtNode> >(config.ResponseQueueMaxSize);
            _sendMessageQueue  = new BlockingCollection <Tuple <DhtMessage, DhtNode> >(config.SendQueueMaxSize);
            _replyMessageQueue = new BlockingCollection <Tuple <DhtMessage, DhtNode> >();

            _sendRateLimit            = new TokenBucketLimit(config.SendRateLimit * 1024, 1, TimeUnit.Second);
            _receveRateLimit          = new TokenBucketLimit(config.ReceiveRateLimit * 1024, 1, TimeUnit.Second);
            _processResponseThreadNum = config.ProcessResponseThreadNum;
            _processRequestThreadNum  = config.ProcessRequestThreadNum;
            _cancellationTokenSource  = new CancellationTokenSource();

            _tasks          = new List <Task>();
            _bootstrapNodes = new List <DhtNode>(DefaultBootstrapNodes);
            MessageMap      = IocContainer.GetService <AbstractMessageMap>();
        }
Ejemplo n.º 8
0
 public bool Ping(DhtNode node)
 {
     return(SendMsg(CommandType.Ping, null, node));
 }
Ejemplo n.º 9
0
        private async Task ProcessResponseAsync(DhtMessage msg, DhtNode responseNode)
        {
            _kTable.AddOrUpdateNode(responseNode);
            object         nodeInfo;
            ISet <DhtNode> nodes = null;

            switch (msg.CommandType)
            {
            case CommandType.Find_Node:
                if (_kTable.IsFull || !msg.Data.TryGetValue("nodes", out nodeInfo))
                {
                    return;
                }
                nodes = DhtNode.ParseNode((byte[])nodeInfo);
                break;

            case CommandType.Get_Peers:
                var hashByte = msg.Get <byte[]>("info_hash");
                var infoHash = new InfoHash(hashByte);
                if (msg.Data.TryGetValue("values", out nodeInfo))
                {
                    IList <object> peerInfo;
                    if (nodeInfo is byte[] bytes)
                    {
                        peerInfo = new object[] { bytes };
                    }
                    else
                    {
                        peerInfo = (IList <object>)nodeInfo;
                    }
                    var peers = new HashSet <IPEndPoint>(peerInfo.Count);
                    foreach (var t in peerInfo)
                    {
                        var peer  = (byte[])t;
                        var point = DhtNode.ParsePeer(peer, 0);
                        if (point.Address.IsPublic())
                        {
                            peers.Add(point);
                        }
                    }
                    if (peers.Count > 0)
                    {
                        infoHash.Peers = peers;
                        if (OnFindPeer != null)
                        {
                            await OnFindPeer(infoHash);
                        }
                        return;
                    }
                }
                if (msg.Data.TryGetValue("nodes", out nodeInfo))
                {
                    if (!(nodeInfo is byte[]))
                    {
                        return;
                    }
                    nodes = DhtNode.ParseNode((byte[])nodeInfo);
                    foreach (var node in nodes)
                    {
                        _kTable.AddNode(node);
                        GetPeers(node, infoHash.Bytes);
                    }
                }
                break;
            }
            if (nodes != null)
            {
                foreach (var node in nodes)
                {
                    _nodeQueue.TryAdd(node);
                    _kTable.AddNode(node);
                }
            }
        }
Ejemplo n.º 10
0
        private async Task ProcessRequestAsync(DhtMessage msg, IPEndPoint remotePoint)
        {
            var response = new DhtMessage
            {
                MessageId  = msg.MessageId,
                MesageType = MessageType.Response
            };
            var requestNode = new DhtNode()
            {
                NodeId = (byte[])msg.Data["id"], Host = remotePoint.Address, Port = (ushort)remotePoint.Port
            };

            _kTable.AddOrUpdateNode(requestNode);
            response.Data.Add("id", GetNeighborNodeId(requestNode.NodeId));
            switch (msg.CommandType)
            {
            case CommandType.Find_Node:
                var targetNodeId = (byte[])msg.Data["target"];
                response.Data.Add("nodes", _kTable.FindNodes(targetNodeId).SelectMany(n => n.CompactNode()).ToArray());
                break;

            case CommandType.Get_Peers:
            case CommandType.Announce_Peer:
                var infoHash = new InfoHash((byte[])msg.Data["info_hash"]);
                if (OnReceiveInfoHash != null)
                {
                    await OnReceiveInfoHash(infoHash);
                }
                if (msg.CommandType == CommandType.Get_Peers)
                {
                    var nodes = _kTable.FindNodes(infoHash.Bytes);
                    response.Data.Add("nodes", nodes.SelectMany(n => n.CompactNode()).ToArray());
                    response.Data.Add("token", infoHash.Value.Substring(0, 2));
                    if (!infoHash.IsDown)
                    {
                        foreach (var node in nodes)
                        {
                            GetPeers(node, infoHash.Bytes);
                        }
                    }
                }
                else if (!infoHash.IsDown)
                {
                    if (!msg.Data.Keys.Contains("implied_port") || 0.Equals(msg.Data["implied_port"]))    //implied_port !=0 则端口使用port
                    {
                        remotePoint.Port = Convert.ToInt32(msg.Data["port"]);
                    }
                    infoHash.Peers = new HashSet <IPEndPoint>(1)
                    {
                        remotePoint
                    };
                    if (OnAnnouncePeer != null)
                    {
                        await OnAnnouncePeer(infoHash);
                    }
                }
                break;

            case CommandType.Ping:
                break;

            default:
                return;
            }
            _replyMessageQueue.TryAdd(new Tuple <DhtMessage, DhtNode>(response, new DhtNode(remotePoint)));
        }