/// <summary>
        /// 处理 PeerExitNetwork 消息。
        /// </summary>
        /// <param name="args">处理时所需要的信息。</param>
        private void HandlePeerExitNetwork(HandleMessageArgs args)
        {
            Logger.Log("收到消息: 用户退出。");
            ushort   bitTorrentClientPort;
            InfoHash infoHash;

            Logger.Log("解码用户及 infohash 数据。");
            MessageFactory.GetPeerMessageContent(args.Message, out infoHash, out bitTorrentClientPort);
            Logger.Log("Infohash: " + infoHash.ToHexString() + Environment.NewLine + "用户端口: " + bitTorrentClientPort.ToString());
            List <Peer> peerList;

            if (TrackerServer.Seeds.TryGetValue(infoHash, out peerList))
            {
                Logger.Log("在本机发现该种子。移出列表。");
                KEndPoint ep = args.Message.Header.SourceEndPoint;
                ep.SetPort(bitTorrentClientPort);
                Peer peer = Peer.Create(ep);
                lock (peerList)
                {
                    peerList.Remove(peer);
                    EventHelper.RaiseEvent(ConnectionListChanged, this, EventArgs.Empty);
                }
            }

            Logger.Log("转发消息。");
            // 转发
            BroadcastMessage(args.Message);
        }
        /// <summary>
        /// 处理 GotPeer 消息。
        /// </summary>
        /// <param name="args">处理时所需要的信息。</param>
        private void HandleGotPeer(HandleMessageArgs args)
        {
            Logger.Log("收到消息: 在其他客户端上找到种子。");
            ushort   bitTorrentClientPort;
            InfoHash infoHash;

            Logger.Log("解码用户及 infohash 数据。");
            MessageFactory.GetPeerMessageContent(args.Message, out infoHash, out bitTorrentClientPort);
            Logger.Log("Infohash: " + infoHash.ToHexString() + Environment.NewLine + "用户端口: " + bitTorrentClientPort.ToString());
            List <Peer> peerList;

            if (!TrackerServer.Seeds.TryGetValue(infoHash, out peerList))
            {
                // 这是本客户端发出的信息,那么本客户端就要接收并处理
                peerList = new List <Peer>(8);
                lock (TrackerServer.Seeds)
                {
                    TrackerServer.Seeds.Add(infoHash, peerList);
                }
            }
            {
                Logger.Log("处理GOTPEER。添加对方地址。");
                KEndPoint ep = args.Message.Header.SourceEndPoint;
                ep.SetPort(bitTorrentClientPort);
                Peer peer = Peer.Create(ep);
                if (!peerList.Contains(peer))
                {
                    lock (peerList)
                    {
                        peerList.Add(peer);
                    }
                }
            }
        }
        /// <summary>
        /// 处理 PeerEnterNetwork 消息。
        /// </summary>
        /// <param name="args">处理时所需要的信息。</param>
        private void HandlePeerEnterNetwork(HandleMessageArgs args)
        {
            Logger.Log("收到消息: 用户加入。");
            ushort   bitTorrentClientPort;
            InfoHash infoHash;

            Logger.Log("解码用户及 infohash 数据。");
            MessageFactory.GetPeerMessageContent(args.Message, out infoHash, out bitTorrentClientPort);
            Logger.Log("Infohash: " + infoHash.ToHexString() + Environment.NewLine + "用户端口: " + bitTorrentClientPort.ToString());
            List <Peer> peerList;

            if (TrackerServer.Seeds.TryGetValue(infoHash, out peerList))
            {
                Logger.Log("在本机发现该种子。加入列表。");
                KEndPoint remoteClientEP = args.Message.Header.SourceEndPoint;
                KEndPoint remoteBTEP     = remoteClientEP;
                remoteBTEP.SetPort(bitTorrentClientPort);
                Peer peer = Peer.Create(remoteBTEP);
                if (!peerList.Contains(peer))
                {
                    lock (peerList)
                    {
                        peerList.Add(peer);
                    }
                }

                // 同时报告信息源,我这里有种子
                Logger.Log("报告消息源在这里找到种子。");
                // 此时 ep 的 Port 已经被修改,所以不能直接向 ep 所表示的端点发送,之前写错了……
                // 所以后面索性改了名称,remoteClientEP 和 remoteBTEP
                SendMessage(remoteClientEP, MessageFactory.GotPeer(LocalKEndPoint, infoHash, (ushort)TrackerServer.Myself.EndPoint.GetPortNumber()));
            }

            Logger.Log("转发消息。");
            // 转发
            BroadcastMessage(args.Message);
        }
Beispiel #4
0
        /// <summary>
        /// 解码连接到接入点时收到的字节数组,并应用这些信息。
        /// </summary>
        /// <param name="data">收到的数据。</param>
        ///// <param name="sendPeerEnter">解码过程中是否应该广播 PeerEnterNetwork 消息。</param>
        /// <exception cref="System.FormatException">解码失败时发生。</exception>
        /// <remarks>
        /// 需要发送 PeerEnterNetwork 消息的情况会发生于:A开启客户端和μT,B开启客户端和μT,A(用户列表非空)再尝试连接B,此时如果B并没有保存全网的用户列表,那么A就要广播 PeerEnterNetwork。
        /// </remarks>
        private void DecodeTargetInformation(byte[] data)
        {
            // 如果对方发过来的是空,那么就肯定不会有数据啦
            if (data.Length > 0)
            {
                BEncodedDictionary dictionary = BEncodedDictionary.Decode(data) as BEncodedDictionary;
                if (dictionary == null)
                {
                    throw new FormatException("无法解码。");
                }
                BEncodedList       connList  = dictionary["connections"] as BEncodedList;
                BEncodedDictionary peersDict = dictionary["peers"] as BEncodedDictionary;

                // 规范 v1.2
                // 先确认自己,同时 if ... 是兼容老版的通信
                if (dictionary.ContainsKey("your endpoint"))
                {
                    BEncodedDictionary yourEndPoint = dictionary["your endpoint"] as BEncodedDictionary;
                    var ip   = new IPAddress((yourEndPoint["ip"] as BEncodedString).TextBytes);
                    var port = BitConverter.ToUInt16((yourEndPoint["port"] as BEncodedString).TextBytes, 0);
                    // 分别设置 KClient、TrackerServer 和 BT 客户端的自己
                    SetLocalEndPoint(new IPEndPoint(ip, port));
                    TrackerServer.SetLocalEndPoint(new IPEndPoint(ip, TrackerServer.LocalEndPoint.Port));
                    TrackerServer.SetMyself(new IPEndPoint(ip, TrackerServer.Myself.EndPoint.GetPortNumber()));

                    this.FreeToGo          = true;
                    TrackerServer.FreeToGo = true;
                }

                // ...
                lock (ConnectionList)
                {
                    foreach (var item in connList)
                    {
                        var       d   = item as BEncodedDictionary;
                        KEndPoint kep = KEndPoint.Empty;
                        kep.SetAddress((d["ip"] as BEncodedString).TextBytes);
                        kep.SetPort((int)BitConverter.ToUInt16((d["port"] as BEncodedString).TextBytes, 0));
                        try
                        {
                            AddToConnectionList(kep);
                        }
                        catch (Exception)
                        {
                        }
                    }
                }

                // 如果已经有用户登记了,那么应该广播
                if (TrackerServer.Seeds.Count > 0)
                {
                    lock (TrackerServer.Seeds)
                    {
                        foreach (var kv in TrackerServer.Seeds)
                        {
                            // 广播消息
                            BroadcastMyselfAddAsPeer(kv.Key);
                        }
                    }
                }
                lock (TrackerServer.Seeds)
                {
                    foreach (var kv in peersDict)
                    {
                        InfoHash    infoHash = InfoHash.FromByteArray(kv.Key.TextBytes);
                        List <Peer> peers    = new List <Peer>((kv.Value as BEncodedList).Count);
                        foreach (var item in (kv.Value as BEncodedList))
                        {
                            var       d   = item as BEncodedDictionary;
                            KEndPoint kep = KEndPoint.Empty;
                            kep.SetAddress((d["ip"] as BEncodedString).TextBytes);
                            kep.SetPort((int)BitConverter.ToUInt16((d["port"] as BEncodedString).TextBytes, 0));
                            Peer peer = Peer.Create(kep);
                            peers.Add(peer);
                        }
                        try
                        {
                            TrackerServer.Seeds.Add(infoHash, peers);
                        }
                        catch (Exception)
                        {
                        }
                    }
                }
            }
            else
            {
                Logger.Log("待解码的数据为空,这意味着对方客户端目前持有的连接列表和用户列表为空。");
            }
        }