Пример #1
0
        /// <summary>
        /// Uninitializes the torrent engine.
        /// </summary>
        public static void Uninitialize()
        {
            if (!isInitialized)
            {
                return;
            }

            Log.LogInfo("[Engine] Shutting down TorrentEngine.");

            isInitialized = false;
            isStopping    = true;
            workQueueResetEvent.Set();

            TorrentRegistry.StopAllActiveTorrents();
            PeerListener.StopListening();
            LocalPeerListener.StopListening();
            LocalPeerDiscovery.Uninitialize();
            DiskManager.Uninitialize();

            if (engineThread != null)
            {
                engineThread.Join();
                engineThread = null;
            }
        }
Пример #2
0
        private static bool HandleBroadcast(string broadcastMessage, IPEndPoint endPoint)
        {
            HeaderCollection headers;

            if (!TryParseMessage(broadcastMessage, out headers))
            {
                return(false);
            }

            string hostText;

            if (!headers.TryGetString("Host", out hostText))
            {
                return(false);
            }

            string expectedHostText = (endPoint.AddressFamily == AddressFamily.InterNetwork ? multicastEndpointV4 : multicastEndpointV6);

            if (!string.Equals(hostText, expectedHostText))
            {
                return(false);
            }

            int    port;
            string portText;

            if (!headers.TryGetString("Port", out portText) || !int.TryParse(portText, out port) || port <= 0 || port > ushort.MaxValue)
            {
                return(false);
            }

            string[] infoHashesHex;
            if (!headers.TryGetStrings("Infohash", out infoHashesHex) || infoHashesHex.Length == 0)
            {
                return(false);
            }

            // Parse all info hashes
            InfoHash[] infoHashes;
            try
            {
                infoHashes = new InfoHash[infoHashesHex.Length];
                for (int i = 0; i < infoHashesHex.Length; i++)
                {
                    if (infoHashesHex[i].Length != 40)
                    {
                        return(false);
                    }

                    infoHashes[i] = new InfoHash(infoHashesHex[i]);
                }
            }
            catch
            {
                return(false);
            }

            // Check if we are the one who sent this
            string cookieText;

            if (headers.TryGetString("Cookie", out cookieText) && string.Equals(cookieText, cookie))
            {
                return(false);
            }

            Log.LogInfo("[LocalPeerDiscovery][{0}] Received a local broadcast for {1} torrents.", endPoint.Address, infoHashes.Length);

            var peerEndPoint = new IPEndPoint(endPoint.Address, port);

            for (int i = 0; i < infoHashes.Length; i++)
            {
                var infoHash = infoHashes[i];
                var torrent  = TorrentRegistry.FindTorrentByInfoHash(infoHash);
                if (torrent == null || torrent.IsPrivate)
                {
                    continue;
                }

                var peerInfo = new PeerInfo(peerEndPoint);
                torrent.AddPeer(peerInfo);
            }
            return(true);
        }
Пример #3
0
        private bool HandleHandshake(Packet packet)
        {
            if (packet.Length != 68)
            {
                Log.LogWarning("[Peer][{0}] Invalid handshake received with {1} bytes (should have been 68).", endPoint, packet.Length);
                return(false);
            }

            int protocolNameLength = packet.ReadByte();

            if (packet.RemainingBytes < (protocolNameLength + 40))
            {
                Log.LogWarning("[Peer][{0}] Invalid handshake received with {1} bytes (protocol name length: {2}).", endPoint, packet.Length, protocolNameLength);
                return(false);
            }

            string protocolName = packet.ReadString(protocolNameLength);

            if (!string.Equals(protocolName, ProtocolName))
            {
                Log.LogWarning("[Peer][{0}] Handshake protocol is not supported: {1}", endPoint, protocolName);
                return(false);
            }

            // Skip 8 bytes of flags
            packet.Skip(8);

            byte[] hashBytes = packet.ReadBytes(20);
            byte[] idBytes   = packet.ReadBytes(20);

            var infoHash = new InfoHash(hashBytes);
            var peerID   = new PeerID(idBytes);

            if (torrent != null && !torrent.InfoHash.Equals(infoHash))
            {
                Log.LogWarning("[Peer][{0}] Handshake with invalid info hash: {1}", endPoint, infoHash);
                return(false);
            }
            else if (torrent != null && peerID.Equals(torrent.PeerID))
            {
                peer.IsSelf = true;
                Log.LogDebug("[Peer][{0}] Handshake with ourself. Closing connection.", endPoint);
                return(false);
            }
            else if (torrent == null)
            {
                var foundTorrent = TorrentRegistry.FindTorrentByInfoHash(infoHash);
                if (foundTorrent == null)
                {
                    Log.LogWarning("[Peer][{0}] Handshake with unknown info hash: {1}", endPoint, infoHash);
                    return(false);
                }
                else if (foundTorrent.IsStoppedOrStopping)
                {
                    Log.LogWarning("[Peer][{0}] Handshake received for a torrent that is stopped or currently stopping: {1}", endPoint, infoHash);
                    return(false);
                }

                torrent = foundTorrent;
                if (peerID.Equals(torrent.PeerID))
                {
                    Log.LogDebug("[Peer][{0}] Handshake with ourself. Closing connection.", endPoint);
                    return(false);
                }

                peer = torrent.OnPeerHandshaked(peerID, this);
            }

            if (peer.ID.IsNone)
            {
                // If the peer had no ID prior, then we set it now and register the ID with the torrent
                peer.ID = peerID;
                torrent.RegisterPeerWithID(peerID, peer);
            }
            else if (!peerID.Equals(peer.ID))
            {
                Log.LogWarning("[Peer][{0}] Handshake with invalid peer ID: {1}   !==   {2}", endPoint, peerID, peer.ID);
                return(false);
            }

            this.infoHash       = infoHash;
            this.peerID         = peerID;
            isHandshakeReceived = true;

            Log.LogDebug("[Peer][{0}] A peer handshaked with us with info hash [{1}] and peer ID [{2}].", endPoint, infoHash, peerID);

            SendHandshake();
            SendBitField();
            OnHandshaked();
            return(true);
        }