예제 #1
0
        public ClientEngine(EngineSettings settings, PeerListener listener, PieceWriter writer)
        {
            Check.Settings(settings);
            Check.Listener(listener);
            Check.Writer(writer);

            this.listener = listener;
            this.settings = settings;

            this.connectionManager = new ConnectionManager(this);
            RegisterDht(new NullDhtEngine());
            this.diskManager   = new DiskManager(this, writer);
            this.listenManager = new ListenManager(this);
            MainLoop.QueueTimeout(TimeSpan.FromMilliseconds(TickLength), delegate {
                if (IsRunning && !disposed)
                {
                    LogicTick();
                }
                return(!disposed);
            });
            this.torrents         = new List <TorrentManager>();
            this.torrentsReadonly = new ReadOnlyCollection <TorrentManager> (torrents);
            CreateRateLimiters();
            this.peerId = GeneratePeerId();

            localPeerListener      = new LocalPeerListener(this);
            localPeerManager       = new LocalPeerManager();
            LocalPeerSearchEnabled = SupportsLocalPeerDiscovery;
            listenManager.Register(listener);
            // This means we created the listener in the constructor
            if (listener.Endpoint.Port == 0)
            {
                listener.ChangeEndpoint(new IPEndPoint(IPAddress.Any, settings.ListenPort));
            }
        }
        async Task ChangePieceWriterAsync (IPieceWriter writer)
        {
            writer = writer ?? throw new ArgumentNullException (nameof (writer));

            await MainLoop;
            if (IsRunning)
                throw new InvalidOperationException ("You must stop all active downloads before changing the piece writer used to write data to disk.");
            await DiskManager.SetWriterAsync (writer);
        }
예제 #3
0
        public void Setup()
        {
            rig         = TestRig.CreateMultiFile();
            diskManager = rig.Engine.DiskManager;

            writer             = new ExceptionWriter();
            diskManager.Writer = writer;
            handle             = new ManualResetEvent(false);
            rig.Manager.Stop();
        }
예제 #4
0
        public void Setup()
        {
            writer = new PieceWriter();
            for (int i = 0; i < fileData.Files.Count; i++)
            {
                writer.Data.Add(fileData.Files[i], fileData.Data[i]);
            }

            diskManager = new DiskManager(new EngineSettings(), writer);
        }
        public ClientEngine (EngineSettings settings, Factories factories)
        {
            settings = settings ?? throw new ArgumentNullException (nameof (settings));
            Factories = factories ?? throw new ArgumentNullException (nameof (factories));

            // This is just a sanity check to make sure the ReusableTasks.dll assembly is
            // loadable.
            GC.KeepAlive (ReusableTasks.ReusableTask.CompletedTask);

            PeerId = GeneratePeerId ();
            Settings = settings ?? throw new ArgumentNullException (nameof (settings));
            CheckSettingsAreValid (Settings);

            allTorrents = new List<TorrentManager> ();
            dhtNodeLocker = new SemaphoreSlim (1, 1);
            publicTorrents = new List<TorrentManager> ();
            Torrents = new ReadOnlyCollection<TorrentManager> (publicTorrents);

            DiskManager = new DiskManager (Settings, Factories);

            ConnectionManager = new ConnectionManager (PeerId, Settings, Factories, DiskManager);
            listenManager = new ListenManager (this);
            PortForwarder = Factories.CreatePortForwarder ();

            MainLoop.QueueTimeout (TimeSpan.FromMilliseconds (TickLength), delegate {
                if (IsRunning && !Disposed)
                    LogicTick ();
                return !Disposed;
            });

            downloadLimiter = new RateLimiter ();
            downloadLimiters = new RateLimiterGroup {
                new DiskWriterLimiter(DiskManager),
                downloadLimiter,
            };

            uploadLimiter = new RateLimiter ();
            uploadLimiters = new RateLimiterGroup {
                uploadLimiter
            };

            PeerListener = (settings.ListenEndPoint == null ? null : Factories.CreatePeerConnectionListener (settings.ListenEndPoint)) ?? new NullPeerListener ();
            listenManager.SetListener (PeerListener);

            DhtListener = (settings.DhtEndPoint == null ? null : Factories.CreateDhtListener (settings.DhtEndPoint)) ?? new NullDhtListener ();
            DhtEngine = (settings.DhtEndPoint == null ? null : Factories.CreateDht ()) ?? new NullDhtEngine ();
            Dht = new DhtEngineWrapper (DhtEngine);
            DhtEngine.SetListenerAsync (DhtListener).GetAwaiter ().GetResult ();

            DhtEngine.StateChanged += DhtEngineStateChanged;
            DhtEngine.PeersFound += DhtEnginePeersFound;
            LocalPeerDiscovery = new NullLocalPeerDiscovery ();

            RegisterLocalPeerDiscovery (settings.AllowLocalPeerDiscovery ? Factories.CreateLocalPeerDiscovery () : null);
        }
예제 #6
0
        public void Setup()
        {
            writer = new PieceWriter();
            for (int i = 0; i < fileData.Files.Count; i++)
            {
                writer.Data.Add(fileData.Files[i], fileData.Data[i]);
            }

            diskManager = new DiskManager(new EngineSettingsBuilder {
                DiskCacheBytes = 0
            }.ToSettings(), Factories.Default, writer);
        }
예제 #7
0
        public ClientEngine(EngineSettings settings)
        {
            settings = settings ?? throw new ArgumentNullException(nameof(settings));

            // This is just a sanity check to make sure the ReusableTasks.dll assembly is
            // loadable.
            GC.KeepAlive(ReusableTasks.ReusableTask.CompletedTask);

            PeerId   = GeneratePeerId();
            Settings = settings ?? throw new ArgumentNullException(nameof(settings));
            CheckSettingsAreValid(Settings);

            allTorrents    = new List <TorrentManager> ();
            publicTorrents = new List <TorrentManager> ();
            Torrents       = new ReadOnlyCollection <TorrentManager> (publicTorrents);

            DiskManager = new DiskManager(Settings);
            DiskManager.ChangePieceWriter(new DiskWriter(Settings.MaximumOpenFiles));

            ConnectionManager = new ConnectionManager(PeerId, Settings, DiskManager);
            listenManager     = new ListenManager(this);
            PortForwarder     = new MonoNatPortForwarder();

            MainLoop.QueueTimeout(TimeSpan.FromMilliseconds(TickLength), delegate {
                if (IsRunning && !Disposed)
                {
                    LogicTick();
                }
                return(!Disposed);
            });

            downloadLimiter  = new RateLimiter();
            downloadLimiters = new RateLimiterGroup {
                new DiskWriterLimiter(DiskManager),
                downloadLimiter,
            };

            uploadLimiter  = new RateLimiter();
            uploadLimiters = new RateLimiterGroup {
                uploadLimiter
            };

            Listener = PeerListenerFactory.CreateTcp(settings.ListenPort);
            listenManager.SetListener(Listener);

            DhtListener             = DhtListenerFactory.CreateUdp(settings.DhtPort);
            DhtEngine               = settings.DhtPort == -1 ? new NullDhtEngine() : DhtEngineFactory.Create(DhtListener);
            DhtEngine.StateChanged += DhtEngineStateChanged;
            DhtEngine.PeersFound   += DhtEnginePeersFound;

            RegisterLocalPeerDiscovery(settings.AllowLocalPeerDiscovery && settings.ListenPort > 0 ? LocalPeerDiscoveryFactory.Create(settings.ListenPort) : null);
        }
예제 #8
0
        public async Task MoveFile_SamePath()
        {
            using var tmp = TempDir.Create();
            var file = TorrentFileInfo.Create(Constants.BlockSize, ("file.txt", 123456, Path.Combine(tmp.Path, "orig.txt"))).Single();

            File.OpenWrite(file.FullPath).Close();

            using var writer  = new TestPieceWriter();
            using var manager = new DiskManager(new EngineSettings(), Factories.Default, writer);

            await manager.MoveFileAsync(file, file.FullPath);

            Assert.IsTrue(File.Exists(file.FullPath));
        }
예제 #9
0
        public async Task MoveFile_ConvertsToFullPath()
        {
            using var writer  = new TestPieceWriter();
            using var manager = new DiskManager(new EngineSettings(), Factories.Default, writer);

            var file = TorrentFileInfo.Create(Constants.BlockSize, 123456).Single();

            Assert.IsFalse(File.Exists(file.FullPath));

            await manager.MoveFileAsync(file, "NewPath");

            Assert.AreEqual(Path.GetFullPath("NewPath"), file.FullPath);
            Assert.IsFalse(File.Exists(file.FullPath));
        }
예제 #10
0
        public ClientEngine(EngineSettings settings, IPeerListener listener, IPieceWriter writer)
        {
            Check.Settings(settings);
            Check.Listener(listener);
            Check.Writer(writer);

            // This is just a sanity check to make sure the ReusableTasks.dll assembly is
            // loadable.
            GC.KeepAlive(ReusableTasks.ReusableTask.CompletedTask);

            PeerId   = GeneratePeerId();
            Listener = listener ?? throw new ArgumentNullException(nameof(listener));
            Settings = settings ?? throw new ArgumentNullException(nameof(settings));

            allTorrents    = new List <TorrentManager> ();
            publicTorrents = new List <TorrentManager> ();
            Torrents       = new ReadOnlyCollection <TorrentManager> (publicTorrents);

            DiskManager       = new DiskManager(Settings, writer);
            ConnectionManager = new ConnectionManager(PeerId, Settings, DiskManager);
            DhtEngine         = new NullDhtEngine();
            listenManager     = new ListenManager(this);
            PortForwarder     = new MonoNatPortForwarder();

            MainLoop.QueueTimeout(TimeSpan.FromMilliseconds(TickLength), delegate {
                if (IsRunning && !Disposed)
                {
                    LogicTick();
                }
                return(!Disposed);
            });

            downloadLimiter  = new RateLimiter();
            downloadLimiters = new RateLimiterGroup {
                new DiskWriterLimiter(DiskManager),
                downloadLimiter,
            };

            uploadLimiter  = new RateLimiter();
            uploadLimiters = new RateLimiterGroup {
                uploadLimiter
            };

            listenManager.Register(listener);

            if (SupportsLocalPeerDiscovery)
            {
                RegisterLocalPeerDiscovery(new LocalPeerDiscovery(Settings));
            }
        }
예제 #11
0
        public async Task MoveFile_TargetDirectoryDoesNotExist()
        {
            using var tmp = TempDir.Create();
            var file = TorrentFileInfo.Create(Constants.BlockSize, ("file.txt", 123456, Path.Combine(tmp.Path, "orig.txt"))).Single();

            File.OpenWrite(file.FullPath).Close();

            using var writer  = new TestPieceWriter();
            using var manager = new DiskManager(new EngineSettings(), Factories.Default, writer);

            var fullPath = Path.Combine(tmp.Path, "New", "Path", "file.txt");
            await manager.MoveFileAsync(file, fullPath);

            Assert.AreEqual(fullPath, file.FullPath);
        }
예제 #12
0
        public void Dispose()
        {
            if (Disposed)
            {
                return;
            }

            Disposed = true;
            MainLoop.QueueWait(() => {
                DhtEngine.Dispose();
                DiskManager.Dispose();
                listenManager.Dispose();
                LocalPeerDiscovery.Stop();
            });
        }
예제 #13
0
        public async Task MoveFiles_Overwrite_SameDir()
        {
            using var tmp = TempDir.Create();

            var file = TorrentFileInfo.Create(Constants.BlockSize, (Path.Combine("sub_dir", "orig.txt"), 123456, Path.Combine(tmp.Path, "sub_dir", "orig.txt"))).Single();

            Directory.CreateDirectory(Path.GetDirectoryName(file.FullPath));
            File.OpenWrite(file.FullPath).Close();

            using var writer  = new TestPieceWriter();
            using var manager = new DiskManager(new EngineSettings(), Factories.Default, writer);

            await manager.MoveFilesAsync(new[] { file }, tmp.Path, true);

            Assert.AreEqual(Path.Combine(tmp.Path, file.Path), file.FullPath);
            Assert.IsTrue(File.Exists(file.FullPath));
        }
        public void Dispose ()
        {
            if (Disposed)
                return;

            Disposed = true;
            MainLoop.QueueWait (() => {
                PeerListener.Stop ();
                listenManager.SetListener (new NullPeerListener ());

                DhtListener.Stop ();
                DhtEngine.Dispose ();

                DiskManager.Dispose ();
                LocalPeerDiscovery.Stop ();
            });
        }
예제 #15
0
        public void Setup()
        {
            var files = new [] {
                new TorrentFileInfo(new TorrentFile("First", Piece.BlockSize / 2)),
                new TorrentFileInfo(new TorrentFile("Second", Piece.BlockSize)),
                new TorrentFileInfo(new TorrentFile("Third", Piece.BlockSize + Piece.BlockSize / 2)),
                new TorrentFileInfo(new TorrentFile("Fourth", Piece.BlockSize * 2 + Piece.BlockSize / 2)),
            };

            buffer = new byte[Piece.BlockSize];
            data   = new TestTorrentData {
                Files       = files,
                Size        = files.Sum(f => f.Length),
                PieceLength = Piece.BlockSize * 2
            };

            writer      = new ExceptionWriter();
            diskManager = new DiskManager(new EngineSettings(), writer);
        }
예제 #16
0
        public ClientEngine(EngineSettings settings, IPeerListener listener, IPieceWriter writer)
        {
            Check.Settings(settings);
            Check.Listener(listener);
            Check.Writer(writer);

            PeerId   = GeneratePeerId();
            Listener = listener ?? throw new ArgumentNullException(nameof(listener));
            Settings = settings ?? throw new ArgumentNullException(nameof(settings));

            torrents = new List <TorrentManager>();
            Torrents = new ReadOnlyCollection <TorrentManager> (torrents);

            DiskManager       = new DiskManager(Settings, writer);
            ConnectionManager = new ConnectionManager(PeerId, Settings, DiskManager);
            DhtEngine         = new NullDhtEngine();
            listenManager     = new ListenManager(this);
            MainLoop.QueueTimeout(TimeSpan.FromMilliseconds(TickLength), delegate {
                if (IsRunning && !Disposed)
                {
                    LogicTick();
                }
                return(!Disposed);
            });

            downloadLimiter  = new RateLimiter();
            downloadLimiters = new RateLimiterGroup {
                new DiskWriterLimiter(DiskManager),
                downloadLimiter,
            };

            uploadLimiter  = new RateLimiter();
            uploadLimiters = new RateLimiterGroup {
                uploadLimiter
            };

            listenManager.Register(listener);

            if (SupportsLocalPeerDiscovery)
            {
                RegisterLocalPeerDiscovery(new LocalPeerDiscovery(Settings));
            }
        }
        public void Setup()
        {
            var pieceLength = Piece.BlockSize * 2;
            var files       = TorrentFileInfo.Create(pieceLength,
                                                     Piece.BlockSize / 2,
                                                     Piece.BlockSize,
                                                     Piece.BlockSize + Piece.BlockSize / 2,
                                                     Piece.BlockSize * 2 + Piece.BlockSize / 2
                                                     );

            buffer = new byte[Piece.BlockSize];
            data   = new TestTorrentData {
                Files       = files,
                Size        = files.Sum(f => f.Length),
                PieceLength = pieceLength
            };

            writer      = new ExceptionWriter();
            diskManager = new DiskManager(new EngineSettings(), writer);
        }
        public void Setup()
        {
            var pieceLength = Constants.BlockSize * 2;
            var files       = TorrentFileInfo.Create(pieceLength,
                                                     Constants.BlockSize / 2,
                                                     Constants.BlockSize,
                                                     Constants.BlockSize + Constants.BlockSize / 2,
                                                     Constants.BlockSize * 2 + Constants.BlockSize / 2
                                                     );

            buffer = new byte[Constants.BlockSize];
            data   = new TestTorrentData {
                Files       = files,
                Size        = files.Sum(f => f.Length),
                PieceLength = pieceLength
            };

            writer      = new ExceptionWriter();
            diskManager = new DiskManager(new EngineSettings(), Factories.Default, writer);
        }
예제 #19
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 ProcessQueue(TorrentManager manager, PeerId id)
        {
            while (id.QueueLength > 0)
            {
                var msg = id.Dequeue();
                var pm  = msg as PieceMessage;

                try {
                    if (pm != null)
                    {
                        pm.Data = ClientEngine.BufferManager.GetBuffer(pm.ByteLength);
                        try {
                            await DiskManager.ReadAsync(manager.Torrent, pm.StartOffset + ((long)pm.PieceIndex * manager.Torrent.PieceLength), pm.Data, pm.RequestLength);
                        } catch (Exception ex) {
                            manager.TrySetError(Reason.ReadFailure, ex);
                            return;
                        }
                        id.PiecesSent++;
                    }

                    await PeerIO.SendMessageAsync(id.Connection, id.Encryptor, msg, manager.UploadLimiters, id.Monitor, manager.Monitor);

                    if (msg is PieceMessage)
                    {
                        id.IsRequestingPiecesCount--;
                    }

                    id.LastMessageSent.Restart();
                } catch {
                    CleanupSocket(manager, id);
                    break;
                } finally {
                    if (pm?.Data != null)
                    {
                        ClientEngine.BufferManager.FreeBuffer(pm.Data);
                    }
                }
            }

            id.ProcessingQueue = false;
        }
예제 #20
0
        void LogicTick()
        {
            tickCount++;

            if (tickCount % 2 == 0)
            {
                downloadLimiter.UpdateChunks(Settings.MaximumDownloadSpeed, TotalDownloadSpeed);
                uploadLimiter.UpdateChunks(Settings.MaximumUploadSpeed, TotalUploadSpeed);
            }

            ConnectionManager.CancelPendingConnects();
            ConnectionManager.TryConnect();
            DiskManager.Tick();

            for (int i = 0; i < allTorrents.Count; i++)
            {
                allTorrents[i].Mode.Tick(tickCount);
            }

            RaiseStatsUpdate(new StatsUpdateEventArgs());
        }
예제 #21
0
        public void Setup()
        {
            var random = new Random();
            var files  = new [] {
                new TorrentFile("First", Piece.BlockSize / 2),
                new TorrentFile("Second", Piece.BlockSize),
                new TorrentFile("Third", Piece.BlockSize + Piece.BlockSize / 2),
                new TorrentFile("Fourth", Piece.BlockSize * 6 + Piece.BlockSize / 2),
            };

            var fileBytes = files
                            .Select(f => { var b = new byte [f.Length]; random.NextBytes(b); return(b); })
                            .ToArray();


            int pieceLength = Piece.BlockSize * 3;
            // Turn all the files into one byte array. Group the byte array into bittorrent pieces. Hash that piece.
            var hashes = fileBytes
                         .SelectMany(t => t)
                         .Partition(pieceLength)
                         .Select(t => SHA1.Create().ComputeHash(t))
                         .ToArray();

            fileData = new TestTorrentData {
                Data        = fileBytes,
                Files       = files,
                Hashes      = hashes,
                Size        = files.Sum(f => f.Length),
                PieceLength = pieceLength
            };

            writer = new PieceWriter();
            for (int i = 0; i < files.Length; i++)
            {
                writer.Data.Add(files[i], fileBytes[i]);
            }

            settings    = new EngineSettings();
            diskManager = new DiskManager(settings, writer);
        }
예제 #22
0
        async Task UpdateSettingsAsync(EngineSettings oldSettings, EngineSettings newSettings)
        {
            await DiskManager.UpdateSettingsAsync(newSettings);

            if (newSettings.DiskCacheBytes != oldSettings.DiskCacheBytes)
            {
                await Task.WhenAll(Torrents.Select(t => DiskManager.FlushAsync(t)));
            }

            ConnectionManager.Settings = newSettings;

            if (oldSettings.AllowPortForwarding != newSettings.AllowPortForwarding)
            {
                if (newSettings.AllowPortForwarding)
                {
                    await PortForwarder.StartAsync(CancellationToken.None);
                }
                else
                {
                    await PortForwarder.StopAsync(removeExistingMappings : true, CancellationToken.None);
                }
            }

            if (oldSettings.DhtPort != newSettings.DhtPort)
            {
                if (DhtListener.EndPoint != null)
                {
                    await PortForwarder.UnregisterMappingAsync(new Mapping (Protocol.Udp, DhtListener.EndPoint.Port), CancellationToken.None);
                }
                else if (oldSettings.DhtPort > 0)
                {
                    await PortForwarder.UnregisterMappingAsync(new Mapping (Protocol.Udp, oldSettings.DhtPort), CancellationToken.None);
                }

                DhtListener = DhtListenerFactory.CreateUdp(newSettings.DhtPort);

                if (oldSettings.DhtPort == -1)
                {
                    await RegisterDht(DhtEngineFactory.Create(DhtListener));
                }
                else if (newSettings.DhtPort == -1)
                {
                    await RegisterDht(new NullDhtEngine());
                }

                DhtEngine.SetListener(DhtListener);

                if (IsRunning)
                {
                    DhtListener.Start();
                    if (Listener is ISocketListener newDhtListener)
                    {
                        await PortForwarder.RegisterMappingAsync(new Mapping (Protocol.Udp, newDhtListener.EndPoint.Port));
                    }
                    else
                    {
                        await PortForwarder.RegisterMappingAsync(new Mapping (Protocol.Udp, newSettings.DhtPort));
                    }
                }
            }

            if (oldSettings.ListenPort != newSettings.ListenPort)
            {
                if (Listener is ISocketListener oldListener)
                {
                    await PortForwarder.UnregisterMappingAsync(new Mapping (Protocol.Tcp, oldListener.EndPoint.Port), CancellationToken.None);
                }
                else if (oldSettings.ListenPort > 0)
                {
                    await PortForwarder.UnregisterMappingAsync(new Mapping (Protocol.Tcp, oldSettings.ListenPort), CancellationToken.None);
                }

                Listener.Stop();
                Listener = PeerListenerFactory.CreateTcp(newSettings.ListenPort);
                listenManager.SetListener(Listener);

                if (IsRunning)
                {
                    Listener.Start();
                    // The settings could say to listen at port 0, which means 'choose one dynamically'
                    if (Listener is ISocketListener peerListener)
                    {
                        await PortForwarder.RegisterMappingAsync(new Mapping (Protocol.Tcp, peerListener.EndPoint.Port));
                    }
                    else
                    {
                        await PortForwarder.RegisterMappingAsync(new Mapping (Protocol.Tcp, newSettings.ListenPort));
                    }
                }
            }

            // This depends on the Listener binding to it's local port.
            var localPort = newSettings.ListenPort;

            if (Listener is ISocketListener newListener)
            {
                localPort = newListener.EndPoint.Port;
            }

            if ((oldSettings.AllowLocalPeerDiscovery != newSettings.AllowLocalPeerDiscovery) ||
                (oldSettings.ListenPort != newSettings.ListenPort))
            {
                RegisterLocalPeerDiscovery(newSettings.AllowLocalPeerDiscovery && localPort > 0 ? new LocalPeerDiscovery(localPort) : null);
            }
        }
예제 #23
0
        internal ConnectionManager(BEncodedString localPeerId, EngineSettings settings, DiskManager diskManager)
        {
            DiskManager = diskManager ?? throw new ArgumentNullException(nameof(diskManager));
            LocalPeerId = localPeerId ?? throw new ArgumentNullException(nameof(localPeerId));
            Settings    = settings ?? throw new ArgumentNullException(nameof(settings));

            PendingConnects = new List <AsyncConnectState>();
            Torrents        = new LinkedList <TorrentManager>();
        }
예제 #24
0
        public ClientEngine(EngineSettings settings, PeerListener listener, PieceWriter writer)
        {
            Check.Settings(settings);
            Check.Listener(listener);
            Check.Writer(writer);

            this.listener = listener;
            this.settings = settings;

            this.connectionManager = new ConnectionManager(this);
            this.dhtListener = new UdpListener(new IPEndPoint(IPAddress.Any, settings.ListenPort));
            this.dhtEngine = new DhtEngine(dhtListener);
            this.diskManager = new DiskManager(this, writer);
            this.listenManager = new ListenManager(this);
            MainLoop.QueueTimeout(TimeSpan.FromMilliseconds(TickLength), delegate {
                if (IsRunning && !disposed)
                    LogicTick();
                return !disposed;
            });
            this.torrents = new MonoTorrentCollection<TorrentManager>();
            this.downloadLimiter = new RateLimiter();
            this.uploadLimiter = new RateLimiter();
            this.peerId = GeneratePeerId();

            listenManager.Register(listener);

            dhtEngine.StateChanged += delegate {
                if (dhtEngine.State != State.Ready)
                    return;
                MainLoop.Queue(delegate {
                    foreach (TorrentManager manager in torrents)
                    {
                        if (!manager.CanUseDht)
                            continue;

                        dhtEngine.Announce(manager.Torrent.infoHash, Listener.Endpoint.Port);
                        dhtEngine.GetPeers(manager.Torrent.infoHash);
                    }
                });
            };
            // This means we created the listener in the constructor
            if (listener.Endpoint.Port == 0)
                listener.ChangeEndpoint(new IPEndPoint(IPAddress.Any, settings.ListenPort));

            listener.Start();
        }
예제 #25
0
 public DiskWriterLimiter(DiskManager manager)
 {
     this.manager = manager;
 }
예제 #26
0
 public void FixtureSetup()
 {
     rig         = TestRig.CreateMultiFile();
     diskManager = rig.Engine.DiskManager;
 }
예제 #27
0
 public void FixtureSetup()
 {
     rig = TestRig.CreateMultiFile();
     diskManager = rig.Engine.DiskManager;
 }
예제 #28
0
        public ClientEngine(EngineSettings settings, PeerListener listener, PieceWriter writer)
        {
            Check.Settings(settings);
            Check.Listener(listener);
            Check.Writer(writer);

            this.listener = listener;
            this.settings = settings;

            this.connectionManager = new ConnectionManager(this);
            RegisterDht (new NullDhtEngine());
            this.diskManager = new DiskManager(this, writer);
            this.listenManager = new ListenManager(this);
            MainLoop.QueueTimeout(TimeSpan.FromMilliseconds(TickLength), delegate {
                if (IsRunning && !disposed)
                    LogicTick();
                return !disposed;
            });
            this.torrents = new MonoTorrentCollection<TorrentManager>();
            CreateRateLimiters();
            this.peerId = GeneratePeerId();

            localPeerListener = new LocalPeerListener(this);
            localPeerManager = new LocalPeerManager();
            LocalPeerSearchEnabled = SupportsLocalPeerDiscovery;
            listenManager.Register(listener);
            // This means we created the listener in the constructor
            if (listener.Endpoint.Port == 0)
                listener.ChangeEndpoint(new IPEndPoint(IPAddress.Any, settings.ListenPort));
        }
예제 #29
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();
            }
        }
예제 #30
0
 public DistributedDiskManager(DiskManager diskManager,
     FileInfoTable<TorrentManager> tmTable)
 {
     _diskManager = diskManager;
     _torrentManagerTable = tmTable;
 }
예제 #31
0
 public DiskWriterLimiter(DiskManager manager)
 {
     this.manager = manager;
 }
예제 #32
0
        async Task UpdateSettingsAsync(EngineSettings oldSettings, EngineSettings newSettings)
        {
            await DiskManager.UpdateSettingsAsync(newSettings);

            if (newSettings.DiskCacheBytes != oldSettings.DiskCacheBytes)
            {
                await Task.WhenAll(Torrents.Select(t => DiskManager.FlushAsync(t)));
            }

            ConnectionManager.Settings = newSettings;

            if (oldSettings.UsePartialFiles != newSettings.UsePartialFiles)
            {
                foreach (var manager in Torrents)
                {
                    await manager.UpdateUsePartialFiles(newSettings.UsePartialFiles);
                }
            }
            if (oldSettings.AllowPortForwarding != newSettings.AllowPortForwarding)
            {
                if (newSettings.AllowPortForwarding)
                {
                    await PortForwarder.StartAsync(CancellationToken.None);
                }
                else
                {
                    await PortForwarder.StopAsync(removeExistingMappings : true, CancellationToken.None);
                }
            }

            if (oldSettings.DhtEndPoint != newSettings.DhtEndPoint)
            {
                if (DhtListener.LocalEndPoint != null)
                {
                    await PortForwarder.UnregisterMappingAsync(new Mapping (Protocol.Udp, DhtListener.LocalEndPoint.Port), CancellationToken.None);
                }
                DhtListener.Stop();

                if (newSettings.DhtEndPoint == null)
                {
                    DhtListener = new NullDhtListener();
                    await RegisterDht(new NullDhtEngine());
                }
                else
                {
                    DhtListener = Factories.CreateDhtListener(Settings.DhtEndPoint) ?? new NullDhtListener();
                    if (IsRunning)
                    {
                        DhtListener.Start();
                    }

                    if (oldSettings.DhtEndPoint == null)
                    {
                        var dht = Factories.CreateDht();
                        await dht.SetListenerAsync(DhtListener);
                        await RegisterDht(dht);
                    }
                    else
                    {
                        await DhtEngine.SetListenerAsync(DhtListener);
                    }
                }

                if (DhtListener.LocalEndPoint != null)
                {
                    await PortForwarder.RegisterMappingAsync(new Mapping (Protocol.Udp, DhtListener.LocalEndPoint.Port));
                }
            }

            if (!Equals(oldSettings.ListenEndPoint, newSettings.ListenEndPoint))
            {
                if (PeerListener.LocalEndPoint != null)
                {
                    await PortForwarder.UnregisterMappingAsync(new Mapping (Protocol.Tcp, PeerListener.LocalEndPoint.Port), CancellationToken.None);
                }

                PeerListener.Stop();
                PeerListener = (newSettings.ListenEndPoint == null ? null : Factories.CreatePeerConnectionListener(newSettings.ListenEndPoint)) ?? new NullPeerListener();
                listenManager.SetListener(PeerListener);

                if (IsRunning)
                {
                    PeerListener.Start();
                    // The settings could say to listen at port 0, which means 'choose one dynamically'
                    if (PeerListener.LocalEndPoint != null)
                    {
                        await PortForwarder.RegisterMappingAsync(new Mapping (Protocol.Tcp, PeerListener.LocalEndPoint.Port));
                    }
                }
            }

            if (oldSettings.AllowLocalPeerDiscovery != newSettings.AllowLocalPeerDiscovery)
            {
                RegisterLocalPeerDiscovery(!newSettings.AllowLocalPeerDiscovery ? null : Factories.CreateLocalPeerDiscovery());
            }
        }