public void Stop()
        {
            try
            {
                if (timer != null)
                {
                    timer.Stop();
                    timer.Dispose();
                    timer = null;
                }
                if (_tcpRelay != null)
                {
                    _tcpRelay.Stop();
                    _tcpRelay = null;
                }
                if (_udpRelay != null)
                {
                    _udpRelay.Stop();
                    _udpRelay = null;
                }
                if (KCPTunnelController.IsRunning)
                {
                    KCPTunnelController.Stop();
                }

                TrafficStatistics.Save(_trafficStatistics);
            }
            catch (Exception e)
            {
                Logging.LogUsefulException(e);
            }
        }
        public MainController()
        {
            ConfigController = new ConfigurationController(this);
            ConfigController.ConfigChanged += OnConfigChanged;

            KCPTunnelController = new KCPTunnelController(this);

            _trafficStatistics = TrafficStatistics.Load();
        }
        private void btnShowAppStatistics_Click(object sender, RoutedEventArgs e)
        {
            progressBarAppStatistics.Visibility = Visibility.Visible;
            BackgroundWorker          statsWorker = new BackgroundWorker();
            Dictionary <string, long> stats       = new Dictionary <string, long>();

            statsWorker.DoWork += new DoWorkEventHandler((o, args) =>
            {
                PacketSerializer serializer  = new PacketSerializer("packets.bin");
                TrafficStatistics statistics = new TrafficStatistics(serializer.DeserializeAllPackets());
                stats = statistics.GetApplicationStatistics();
            });

            statsWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler((o, args) =>
            {
                btnShowAppStatistics.Visibility
                    = Visibility.Collapsed;
                chartApplications.DataContext       = stats;
                progressBarAppStatistics.Visibility = Visibility.Collapsed;
                chartApplications.Visibility        = Visibility.Visible;
            });

            statsWorker.RunWorkerAsync();
        }
        private void btnShowStatistics_Click(object sender, RoutedEventArgs e)
        {
            this.progressBarStatistics.Visibility = System.Windows.Visibility.Visible;
            BackgroundWorker getStatsWorker = new BackgroundWorker();

            int timeRange = this.comboTimeRange.SelectedIndex;

            Dictionary <byte, decimal> downloadedStats = new Dictionary <byte, decimal>();
            Dictionary <byte, decimal> uploadedStats   = new Dictionary <byte, decimal>();

            ObservableCollection <KeyValuePair <byte, decimal> > downloaded = new ObservableCollection <KeyValuePair <byte, decimal> >();
            Series downSeries = new LineSeries
            {
                Title = "Downloaded",
                DependentValuePath   = "Value",
                IndependentValuePath = "Key",
                ItemsSource          = downloaded,
                DataPointStyle       = (Style)FindResource("downLine")
            };

            ObservableCollection <KeyValuePair <byte, decimal> > uploaded = new ObservableCollection <KeyValuePair <byte, decimal> >();
            Series upSeries = new LineSeries
            {
                Title = "Uploaded",
                DependentValuePath   = "Value",
                IndependentValuePath = "Key",
                ItemsSource          = uploaded,
                DataPointStyle       = (Style)FindResource("upLine")
            };

            if (this.chartTraffic.Series.Count == 0)
            {
                this.chartTraffic.Series.Add(downSeries);
                this.chartTraffic.Series.Add(upSeries);
            }

            getStatsWorker.DoWork += new DoWorkEventHandler((o, args) =>
            {
                PacketSerializer serializer  = new PacketSerializer("packets.bin");
                List <Packet> allPackets     = serializer.DeserializeAllPackets();
                TrafficStatistics statistics = new TrafficStatistics(allPackets);

                switch (timeRange)
                {
                case 0:
                    downloadedStats = statistics.GetDownloadedLastHour();
                    uploadedStats   = statistics.GetUploadedLastHour();
                    this.lblTimeValue.Dispatcher.BeginInvoke(new Action(() =>
                    {
                        this.lblTimeValue.Content = "Minutes";
                    }));
                    break;

                case 1:
                    downloadedStats = statistics.GetDownloadedLastDay();
                    uploadedStats   = statistics.GetUploadedLastDay();
                    this.lblTimeValue.Dispatcher.BeginInvoke(new Action(() =>
                    {
                        this.lblTimeValue.Content = "Hours";
                    }));
                    break;

                case 3:
                    downloadedStats = statistics.GetDownloadedLastWeek();
                    uploadedStats   = statistics.GetUploadedLastWeek();
                    this.lblTimeValue.Dispatcher.BeginInvoke(new Action(() =>
                    {
                        this.lblTimeValue.Content = "Days";
                    }));
                    break;

                case 4:
                    downloadedStats = statistics.GetDownloadedLastMonth();
                    uploadedStats   = statistics.GetUploadedLastMonth();
                    this.lblTimeValue.Dispatcher.BeginInvoke(new Action(() =>
                    {
                        this.lblTimeValue.Content = "Days";
                    }));
                    break;
                }

                Dispatcher.BeginInvoke(new Action(() =>
                {
                    foreach (var key in downloadedStats.Keys)
                    {
                        downloaded.Add(new KeyValuePair <byte, decimal>(key, downloadedStats[key] / 1000000));
                    }

                    foreach (var key in uploadedStats.Keys)
                    {
                        uploaded.Add(new KeyValuePair <byte, decimal>(key, uploadedStats[key] / 1000000));
                    }
                }));

                allPackets.Clear();
                statistics.Dispose();
            });

            getStatsWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler((o, args) =>
            {
                this.progressBarStatistics.Visibility = System.Windows.Visibility.Collapsed;
                this.chartTraffic.Visibility          = System.Windows.Visibility.Visible;
            });

            getStatsWorker.RunWorkerAsync();
        }