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;
        }
示例#2
0
        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();
        }
示例#3
0
 public MetadataMode(TorrentManager manager, string savePath)
     : base(manager)
 {
     this.savePath = savePath;
 }
示例#4
0
 internal PeerConnectionEventArgs(TorrentManager manager, PeerId id, Direction direction)
     : this(manager, id, direction, "")
 {
 }
 public MatroskaPlayer(MonoTorrent.Client.TorrentManager manager, MonotorrentDataAccessor dataAccessor)
 {
     _manager      = manager;
     _dataAccessor = dataAccessor;
 }
示例#6
0
 public AsyncConnectState(TorrentManager manager, IConnection connection, ValueStopwatch timer)
 {
     Manager    = manager;
     Connection = connection;
     Timer      = timer;
 }
示例#7
0
        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);
            }
        }
示例#8
0
 internal bool Contains(TorrentManager manager)
 {
     return(Torrents.Contains(manager));
 }
示例#9
0
 internal void Add(TorrentManager manager)
 {
     Torrents.AddLast(manager);
 }
示例#10
0
        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");
            }
        }
示例#11
0
        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;
 }
示例#13
0
 /// <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;
 }
示例#14
0
 protected Mode(TorrentManager manager)
 {
     CanAcceptConnections  = true;
     this.manager          = manager;
     manager.chokeUnchoker = new ChokeUnchokeManager(manager, manager.Settings.MinimumTimeBetweenReviews, manager.Settings.PercentOfMaxRateToSkipReview);
 }
示例#15
0
		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();
		}
示例#16
0
 internal PieceManager(TorrentManager manager)
 {
     Manager = manager;
     PendingHashCheckPieces = new MutableBitField(1);
     Requester = manager.Engine.Factories.CreatePieceRequester();
 }
示例#17
0
        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);
        }
示例#18
0
 internal void Remove(TorrentManager manager)
 {
     Torrents.Remove(manager);
 }
示例#19
0
 public ErrorMode(TorrentManager manager)
     : base(manager)
 {
     CanAcceptConnections = false;
     CloseConnections();
 }
示例#20
0
        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;
            }
        }
示例#21
0
 public async Task Register(TorrentManager manager)
 => await Register(manager, true);
示例#22
0
        /// <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();
            }
        }
示例#23
0
 public void Add(TorrentManager manager, IPeerConnection connection)
 {
     ConnectionReceived?.Invoke(this, new PeerConnectionEventArgs(connection, manager.InfoHash));
 }
示例#24
0
 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;
 }
示例#26
0
        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));
        }
示例#27
0
 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));
 }
示例#28
0
 protected Unchoker(TorrentManager manager)
 {
     Manager = manager;
 }
示例#29
0
 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);
 }
示例#30
0
 protected virtual void RaiseConnectionReceived(Peer peer, IConnection connection, TorrentManager manager)
 {
     if (ConnectionReceived != null)
     {
         Toolbox.RaiseAsyncEvent <NewConnectionEventArgs>(ConnectionReceived, this, new NewConnectionEventArgs(peer, connection, manager));
     }
 }
示例#31
0
        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
            {
            }
        }