/// <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; } }
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); }
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); }