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))); } } }
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); }
public bool GetPeers(DhtNode node, byte[] infoHash) { var data = new Dictionary <string, object> { { "info_hash", infoHash } }; return(SendMsg(CommandType.Get_Peers, data, node)); }
public bool FindNode(DhtNode node) { var data = new Dictionary <string, object> { { "target", GenerateRandomNodeId() } }; return(SendMsg(CommandType.Find_Node, data, node)); }
public bool AddBootstrapNode(DhtNode node) { if (running) { return(false); } _bootstrapNodes.Add(node); return(true); }
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)); }
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>(); }
public bool Ping(DhtNode node) { return(SendMsg(CommandType.Ping, null, node)); }
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); } } }
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))); }