예제 #1
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);
        }
예제 #2
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);
            }
        }