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);
        }
Example #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.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());
            }
        }