public TorrentManager(string magnetUrl, string downloadLocation) { var settings = new EngineSettings { SavePath = downloadLocation, ListenPort = Port }; var torrentDefaults = new TorrentSettings(); var writer = new DiskWriter(); _dataAccessor = new MonotorrentDataAccessor(writer); _engine = new ClientEngine(settings, writer); if (!Directory.Exists(downloadLocation)) { Directory.CreateDirectory(downloadLocation); } var magnet = MagnetLink.Parse(magnetUrl); _manager = new MonoTorrent.Client.TorrentManager(magnet, downloadLocation, torrentDefaults, downloadLocation); _manager.PieceHashed += async(sender, eventArgs) => await _matroskaPlayer.OnPieceHashed(sender, eventArgs); _manager.TorrentStateChanged += delegate(object sender, TorrentStateChangedEventArgs args) { Console.WriteLine(args.NewState); }; _matroskaPlayer = new MatroskaPlayer(_manager, _dataAccessor); TorrentError += OnError; }
public void Add(string s) { if (!File.Exists(s)) { return; } foreach (TorrentManager mgr in items) { if (mgr.Torrent.TorrentPath == s) { Application.Info("Info", "The specified torrent is already loaded"); continue; } } Torrent torrent = Torrent.Load(s); FastResume resume = null; foreach (FastResume r in fastResume) { if (((BEncodedString)r.InfoHash).Equals((BEncodedString)torrent.InfoHash)) { resume = r; } } TorrentManager manager; if (resume == null) { manager = new TorrentManager(torrent, engine_settings.SavePath, (TorrentSettings)torrent_settings.Clone()); } else { manager = new MonoTorrent.Client.TorrentManager(torrent, engine_settings.SavePath, (TorrentSettings)torrent_settings.Clone(), resume); } manager.PeerConnected += new EventHandler <PeerConnectionEventArgs>(cm_PeerConnected); manager.PeerDisconnected += new EventHandler <PeerConnectionEventArgs>(cm_PeerDisconnected); engine.Register(manager); items.Add(manager); if (view != null) { view.ProviderChanged(); } manager.Start(); }
public MetadataMode(TorrentManager manager, string savePath) : base(manager) { this.savePath = savePath; }
internal PeerConnectionEventArgs(TorrentManager manager, PeerId id, Direction direction) : this(manager, id, direction, "") { }
public MatroskaPlayer(MonoTorrent.Client.TorrentManager manager, MonotorrentDataAccessor dataAccessor) { _manager = manager; _dataAccessor = dataAccessor; }
public AsyncConnectState(TorrentManager manager, IConnection connection, ValueStopwatch timer) { Manager = manager; Connection = connection; Timer = timer; }
internal async void ReceiveMessagesAsync(IConnection connection, IEncryption decryptor, RateLimiterGroup downloadLimiter, ConnectionMonitor monitor, TorrentManager torrentManager, PeerId id) { await MainLoop.SwitchToThreadpool(); ByteBufferPool.Releaser releaser = default; try { while (true) { if (id.AmRequestingPiecesCount == 0 && releaser.Buffer != null) { releaser.Dispose(); releaser = NetworkIO.BufferPool.Rent(1, out ByteBuffer _); } else if (id.AmRequestingPiecesCount > 0 && releaser.Buffer == null) { releaser.Dispose(); releaser = NetworkIO.BufferPool.Rent(Piece.BlockSize, out ByteBuffer _); } PeerMessage message = await PeerIO.ReceiveMessageAsync(connection, decryptor, downloadLimiter, monitor, torrentManager.Monitor, torrentManager, releaser.Buffer).ConfigureAwait(false); HandleReceivedMessage(id, torrentManager, message); } } catch { releaser.Dispose(); await ClientEngine.MainLoop; CleanupSocket(torrentManager, id); } }
internal bool Contains(TorrentManager manager) { return(Torrents.Contains(manager)); }
internal void Add(TorrentManager manager) { Torrents.AddLast(manager); }
async void ReceiveMessagesAsync(IConnection connection, IEncryption decryptor, RateLimiterGroup downloadLimiter, ConnectionMonitor monitor, TorrentManager torrentManager, PeerId id) { try { while (true) { var message = await PeerIO.ReceiveMessageAsync(connection, decryptor, downloadLimiter, monitor, torrentManager); if (id.Disposed) { if (message is PieceMessage msg) { ClientEngine.BufferManager.FreeBuffer(msg.Data); } } else { id.LastMessageReceived.Restart(); if (PeerMessageTransferred != null) { RaisePeerMessageTransferred(new PeerMessageEventArgs(id.TorrentManager, message, Direction.Incoming, id)); } message.Handle(id); } } } catch { CleanupSocket(id, "Could not receive a message"); } }
internal async void ConnectToPeer(TorrentManager manager, Peer peer) { // Connect to the peer. IConnection connection = ConnectionFactory.Create(peer.ConnectionUri); if (connection == null) { return; } var state = new AsyncConnectState(manager, connection, Stopwatch.StartNew()); PendingConnects.Add(state); manager.Peers.ConnectingToPeers.Add(peer); bool succeeded; try { await NetworkIO.ConnectAsync(connection); succeeded = true; } catch { succeeded = false; } PendingConnects.Remove(state); if (manager.Engine == null || !manager.Mode.CanAcceptConnections) { connection.Dispose(); return; } try { manager.Peers.ConnectingToPeers.Remove(peer); if (!succeeded) { Logger.Log(null, "ConnectionManager - Failed to connect{0}", peer); manager.RaiseConnectionAttemptFailed( new PeerConnectionFailedEventArgs(manager, peer, Direction.Outgoing, "EndCreateConnection")); peer.FailedConnectionAttempts++; connection.Dispose(); manager.Peers.BusyPeers.Add(peer); } else { PeerId id = new PeerId(peer, manager); id.Connection = connection; manager.Peers.ActivePeers.Add(peer); Logger.Log(id.Connection, "ConnectionManager - Connection opened"); ProcessFreshConnection(id); } } catch (Exception) { // FIXME: Do nothing now? } finally { // Try to connect to another peer TryConnect(); } }
internal PeerConnectedEventArgs(TorrentManager manager, PeerId id) : base(manager) { Peer = id; }
/// <summary> /// Creates a new choke/unchoke manager for a torrent manager /// </summeary> /// <param name="TorrentManager">The torrent manager this choke/unchoke manager belongs to</param> public ChokeUnchokeManager(TorrentManager TorrentManager, int MinimumTimeBetweenReviews, int PercentOfMaxRateToSkipReview) { owningTorrent = TorrentManager; minimumTimeBetweenReviews = MinimumTimeBetweenReviews; percentOfMaxRateToSkipReview = PercentOfMaxRateToSkipReview; }
protected Mode(TorrentManager manager) { CanAcceptConnections = true; this.manager = manager; manager.chokeUnchoker = new ChokeUnchokeManager(manager, manager.Settings.MinimumTimeBetweenReviews, manager.Settings.PercentOfMaxRateToSkipReview); }
public void Add (string s) { if (!File.Exists (s)) return; foreach (TorrentManager mgr in items){ if (mgr.Torrent.TorrentPath == s){ Application.Info ("Info", "The specified torrent is already loaded"); continue; } } Torrent torrent = Torrent.Load(s); FastResume resume = null; foreach (FastResume r in fastResume) { if (((BEncodedString)r.InfoHash).Equals((BEncodedString)torrent.InfoHash)) resume = r; } TorrentManager manager; if (resume == null) manager = new TorrentManager(torrent, engine_settings.SavePath, (TorrentSettings)torrent_settings.Clone()); else manager = new MonoTorrent.Client.TorrentManager(torrent, engine_settings.SavePath, (TorrentSettings)torrent_settings.Clone(), resume); manager.PeerConnected += new EventHandler<PeerConnectionEventArgs>(cm_PeerConnected); manager.PeerDisconnected += new EventHandler<PeerConnectionEventArgs>(cm_PeerDisconnected); engine.Register(manager); items.Add (manager); if (view != null) view.ProviderChanged (); manager.Start(); }
internal PieceManager(TorrentManager manager) { Manager = manager; PendingHashCheckPieces = new MutableBitField(1); Requester = manager.Engine.Factories.CreatePieceRequester(); }
bool TryConnect(TorrentManager manager) { int i; Peer peer; if (!manager.Mode.CanAcceptConnections) { return(false); } // If we have reached the max peers allowed for this torrent, don't connect to a new peer for this torrent if (manager.Peers.ConnectedPeers.Count >= manager.Settings.MaxConnections) { return(false); } // If the torrent isn't active, don't connect to a peer for it if (!manager.Mode.CanAcceptConnections) { return(false); } // If we are not seeding, we can connect to anyone. If we are seeding, we should only connect to a peer // if they are not a seeder. for (i = 0; i < manager.Peers.AvailablePeers.Count; i++) { if (manager.Mode.ShouldConnect(manager.Peers.AvailablePeers[i])) { break; } } // If this is true, there were no peers in the available list to connect to. if (i == manager.Peers.AvailablePeers.Count) { return(false); } // Remove the peer from the lists so we can start connecting to him peer = manager.Peers.AvailablePeers[i]; manager.Peers.AvailablePeers.RemoveAt(i); // Do not try to connect to ourselves if (peer.ConnectionUri.Port == manager.Engine.Listener.Endpoint.Port) { if (manager.Engine.Listener.Endpoint.Address.ToString() == peer.ConnectionUri.Host) { return(false); } if (manager.Engine.Listener.Endpoint.Address == IPAddress.Any) { foreach (var intf in NetworkInterface.GetAllNetworkInterfaces()) { if (intf.OperationalStatus == OperationalStatus.Up) { foreach (var ip in intf.GetIPProperties().UnicastAddresses) { if (ip.Address.ToString() == peer.ConnectionUri.Host) { return(false); } } } } } } if (ShouldBanPeer(peer)) { return(false); } // Connect to the peer ConnectToPeer(manager, peer); return(true); }
internal void Remove(TorrentManager manager) { Torrents.Remove(manager); }
public ErrorMode(TorrentManager manager) : base(manager) { CanAcceptConnections = false; CloseConnections(); }
internal async void ProcessNewOutgoingConnection(TorrentManager manager, PeerId id) { // If we have too many open connections, close the connection if (OpenConnections > MaxOpenConnections) { CleanupSocket(manager, id); return; } manager.Peers.ActivePeers.Add(id.Peer); manager.Peers.ConnectedPeers.Add(id); Interlocked.Increment(ref openConnections); try { // Create a handshake message to send to the peer var handshake = new HandshakeMessage(manager.InfoHash, LocalPeerId, VersionInfo.ProtocolStringV100); var preferredEncryption = EncryptionTypes.GetPreferredEncryption(id.Peer.AllowedEncryption, Settings.AllowedEncryption); EncryptorFactory.EncryptorResult result = await EncryptorFactory.CheckOutgoingConnectionAsync(id.Connection, preferredEncryption, manager.InfoHash, handshake); id.Decryptor = result.Decryptor; id.Encryptor = result.Encryptor; } catch { // If an exception is thrown it's because we tried to establish an encrypted connection and something went wrong if (id.Peer.AllowedEncryption.Contains(EncryptionType.PlainText)) { id.Peer.AllowedEncryption = EncryptionTypes.PlainText; } else { id.Peer.AllowedEncryption = EncryptionTypes.None; } manager.RaiseConnectionAttemptFailed(new ConnectionAttemptFailedEventArgs(id.Peer, ConnectionFailureReason.EncryptionNegiotiationFailed, manager)); CleanupSocket(manager, id); // CleanupSocket will contain the peer only if AllowedEncryption is not set to None. If // the peer was re-added, then we should try to reconnect to it immediately to try an // unencrypted connection. if (manager.Peers.AvailablePeers.Remove(id.Peer)) { ConnectToPeer(manager, id.Peer); } return; } try { // Receive their handshake HandshakeMessage handshake = await PeerIO.ReceiveHandshakeAsync(id.Connection, id.Decryptor); manager.Mode.HandleMessage(id, handshake); } catch { // If we choose plaintext and it resulted in the connection being closed, remove it from the list. id.Peer.AllowedEncryption = EncryptionTypes.Remove(id.Peer.AllowedEncryption, id.EncryptionType); manager.RaiseConnectionAttemptFailed(new ConnectionAttemptFailedEventArgs(id.Peer, ConnectionFailureReason.HandshakeFailed, manager)); CleanupSocket(manager, id); // CleanupSocket will contain the peer only if AllowedEncryption is not set to None. If // the peer was re-added, then we should try to reconnect to it immediately to try an // encrypted connection, assuming the previous connection was unencrypted and it failed. if (manager.Peers.AvailablePeers.Remove(id.Peer)) { ConnectToPeer(manager, id.Peer); } return; } try { if (id.BitField.Length != manager.Bitfield.Length) { throw new TorrentException($"The peer's bitfield was of length {id.BitField.Length} but the TorrentManager's bitfield was of length {manager.Bitfield.Length}."); } manager.HandlePeerConnected(id); id.MessageQueue.SetReady(); TryProcessQueue(manager, id); ReceiveMessagesAsync(id.Connection, id.Decryptor, manager.DownloadLimiters, id.Monitor, manager, id); id.WhenConnected.Restart(); id.LastBlockReceived.Restart(); } catch { manager.RaiseConnectionAttemptFailed(new ConnectionAttemptFailedEventArgs(id.Peer, ConnectionFailureReason.Unknown, manager)); CleanupSocket(manager, id); return; } }
public async Task Register(TorrentManager manager) => await Register(manager, true);
/// <summary> /// /// </summary> /// <param name="manager">The torrent which the peer is associated with.</param> /// <param name="id">The peer whose message queue you want to start processing</param> internal async void TryProcessQueue(TorrentManager manager, PeerId id) { if (!id.MessageQueue.BeginProcessing()) { return; } await MainLoop.SwitchToThreadpool(); ByteBufferPool.Releaser messageBuffer = default; ByteBufferPool.Releaser pieceBuffer = default; PeerMessage msg; try { while ((msg = id.MessageQueue.TryDequeue()) != null) { var msgLength = msg.ByteLength; if (msg is PieceMessage pm) { if (pieceBuffer.Buffer == null) { pieceBuffer = DiskManager.BufferPool.Rent(msgLength, out ByteBuffer _); } pm.DataReleaser = pieceBuffer; try { await DiskManager.ReadAsync(manager, pm.StartOffset + ((long)pm.PieceIndex * manager.Torrent.PieceLength), pm.Data, pm.RequestLength).ConfigureAwait(false); } catch (Exception ex) { await ClientEngine.MainLoop; manager.TrySetError(Reason.ReadFailure, ex); return; } System.Threading.Interlocked.Increment(ref id.piecesSent); } else { pieceBuffer.Dispose(); } if (messageBuffer.Buffer == null || messageBuffer.Buffer.Data.Length < msg.ByteLength) { messageBuffer.Dispose(); messageBuffer = NetworkIO.BufferPool.Rent(msgLength, out ByteBuffer _); } await PeerIO.SendMessageAsync(id.Connection, id.Encryptor, msg, manager.UploadLimiters, id.Monitor, manager.Monitor, messageBuffer.Buffer).ConfigureAwait(false); if (msg is PieceMessage) { System.Threading.Interlocked.Decrement(ref id.isRequestingPiecesCount); } id.LastMessageSent.Restart(); } } catch { await ClientEngine.MainLoop; CleanupSocket(manager, id); } finally { messageBuffer.Dispose(); pieceBuffer.Dispose(); } }
public void Add(TorrentManager manager, IPeerConnection connection) { ConnectionReceived?.Invoke(this, new PeerConnectionEventArgs(connection, manager.InfoHash)); }
public void Add(TorrentManager manager, IConnection connection) { MonoTorrent.Client.Peer p = new MonoTorrent.Client.Peer("", new Uri("tcp://12.123.123.1:2342"), EncryptionTypes.All); base.RaiseConnectionReceived(p, connection, manager); }
/// <summary> /// Creates a new inactive peer manager for a torrent manager /// </summary> /// <param name="TorrentManager">The torrent manager this choke/unchoke manager belongs to</param> /// <param name="TimeToWaitBeforeIdle">Number of seconds to protect a peer from being marked as inactive</param> public InactivePeerManager(TorrentManager TorrentManager) { owningTorrent = TorrentManager; }
public void Add(TorrentManager manager, IConnection connection) { var p = new Peer("", new Uri("ipv4://12.123.123.1:2342"), EncryptionTypes.All); ConnectionReceived?.Invoke(this, new NewConnectionEventArgs(p, connection, manager)); }
bool Read(TorrentManager manager, long offset, byte [] buffer, int count) { readMonitor.AddDelta(count); return(Writer.Read(manager.Torrent.Files, offset, buffer, 0, count, manager.Torrent.PieceLength, manager.Torrent.Size)); }
protected Unchoker(TorrentManager manager) { Manager = manager; }
void Write(TorrentManager manager, long offset, byte [] buffer, int count) { writeMonitor.AddDelta(count); Writer.Write(manager.Torrent.Files, offset, buffer, 0, count, manager.Torrent.PieceLength, manager.Torrent.Size); }
protected virtual void RaiseConnectionReceived(Peer peer, IConnection connection, TorrentManager manager) { if (ConnectionReceived != null) { Toolbox.RaiseAsyncEvent <NewConnectionEventArgs>(ConnectionReceived, this, new NewConnectionEventArgs(peer, connection, manager)); } }
public void PieceDataReceived(PeerId peer, PieceMessage message) { Piece piece; if (picker.ValidatePiece(peer, message.PieceIndex, message.StartOffset, message.RequestLength, out piece)) { PeerId id = peer; TorrentManager manager = id.TorrentManager; Block block = piece.Blocks [message.StartOffset / Piece.BlockSize]; long offset = (long)message.PieceIndex * id.TorrentManager.Torrent.PieceLength + message.StartOffset; id.LastBlockReceived = DateTime.Now; id.TorrentManager.PieceManager.RaiseBlockReceived(new BlockEventArgs(manager, block, piece, id)); id.TorrentManager.Engine.DiskManager.QueueWrite(manager, offset, message.Data, message.RequestLength, delegate { piece.Blocks[message.StartOffset / Piece.BlockSize].Written = true; ClientEngine.BufferManager.FreeBuffer(ref message.Data); // If we haven't written all the pieces to disk, there's no point in hash checking if (!piece.AllBlocksWritten) { return; } Logger.Info("Piece downloaded: {0}", piece.Index); // Hashcheck the piece as we now have all the blocks. id.Engine.DiskManager.BeginGetHash(id.TorrentManager, piece.Index, delegate(object o) { byte[] hash = (byte[])o; bool result = hash == null ? false : id.TorrentManager.Torrent.Pieces.IsValid(hash, piece.Index); id.TorrentManager.Bitfield[message.PieceIndex] = result; ClientEngine.MainLoop.Queue(delegate { id.TorrentManager.PieceManager.UnhashedPieces[piece.Index] = false; id.TorrentManager.HashedPiece(new PieceHashedEventArgs(id.TorrentManager, piece.Index, result)); List <PeerId> peers = new List <PeerId>(piece.Blocks.Length); for (int i = 0; i < piece.Blocks.Length; i++) { if (piece.Blocks[i].RequestedOff != null && !peers.Contains(piece.Blocks[i].RequestedOff)) { peers.Add(piece.Blocks[i].RequestedOff); } } for (int i = 0; i < peers.Count; i++) { if (peers[i].Connection != null) { peers[i].Peer.HashedPiece(result); if (peers [i].Peer.TotalHashFails == 5) { peers[i].ConnectionManager.CleanupSocket(id, "Too many hash fails"); } } } // If the piece was successfully hashed, enqueue a new "have" message to be sent out if (result) { id.TorrentManager.finishedPieces.Enqueue(piece.Index); } }); }); }); if (piece.AllBlocksReceived) { this.unhashedPieces[message.PieceIndex] = true; } } else { } }