예제 #1
0
        /// <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);
                    }
                }
            }
        }
예제 #2
0
        /// <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);
        }
예제 #3
0
        public async Task Handle(WebSocket webSocket)
        {
            if (MaxPeers <= Peer.Count)
            {
                await webSocket.CloseAsync(WebSocketCloseStatus.EndpointUnavailable, "Too many peers", CancellationToken.None);

                return;
            }

            using (Peer peer = Peer.Create(webSocket))
            {
                try
                {
                    ArraySegment <byte> buffer = new ArraySegment <byte>(new byte[4 * 1024]);
                    while (webSocket.State == WebSocketState.Open)
                    {
                        List <byte>            receivedBytes = new List <byte>();
                        WebSocketReceiveResult result        = await webSocket.ReceiveAsync(buffer, CancellationToken.None);

                        while (!result.EndOfMessage)
                        {
                            receivedBytes.AddRange(buffer.Take(result.Count));
                            result = await webSocket.ReceiveAsync(buffer, CancellationToken.None);
                        }

                        receivedBytes.AddRange(buffer.Take(result.Count));

                        string message = receivedBytes.ToArray().GetString();
                        await ParseMessage(peer, message);
                    }
                }
                finally
                {
                    if (!string.IsNullOrWhiteSpace(peer.lobby) && _lobbies.TryGetValue(peer.lobby, out Lobby lobby) &&
                        await lobby.Leave(peer))
                    {
                        _ = _lobbies.TryRemove(peer.lobby, out _);
                        Console.WriteLine("Deleted lobby {0}, {1} still open.", peer.lobby, _lobbies.Count);
                        peer.lobby = null;
                    }

                    peer.shouldCloseConnection = false;
                }
            }
        }
예제 #4
0
        /// <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);
        }
예제 #5
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("待解码的数据为空,这意味着对方客户端目前持有的连接列表和用户列表为空。");
            }
        }
예제 #6
0
 public static bool AddPeer(TcpClient tcpc)
 {
     lock (addpeers_operation)
     {
         try
         {
             return(tcpc.Ip() != "" && !IpAddr.EqualsMine(tcpc.Ip()) && !HasPeer(tcpc.Ip()) && !HasMaximumConnections() && AddPeer(Peer.Create(Core, tcpc)));
         }
         catch
         {
             Log.NewLine($"Failed to connect to {tcpc.Ip()}.");
             return(false);
         }
     }
 }
예제 #7
0
 public static bool AddPeer(string ip)
 {
     lock (addpeers_operation)
     {
         try
         {
             return(ip != "" && !IpAddr.EqualsMine(ip) && !HasPeer(ip) && !HasMaximumConnections() && AddPeer(Peer.Create(Core, ip)));
         }
         catch
         {
             Log.NewLine($"Failed to connect to {ip}.");
             return(false);
         }
     }
 }
 /// <summary>
 /// 设定程序认为的 BitTorrent 客户端眼中的“自己”是什么。
 /// </summary>
 /// <param name="endPoint">本地的 BitTorrent 客户端使用的端点,包括本地局域网地址(不是本地环回地址)及其监听端口。</param>
 public void SetMyself(IPEndPoint endPoint, string peerID = null)
 {
     _myself = Peer.Create(KEndPoint.FromEndPoint(endPoint), peerID);
 }