[C#] Help with Monotorrent

Discussion in 'Mixed Languages' started by CODYQX4, Aug 27, 2012.

  1. CODYQX4

    CODYQX4 MDL Developer

    Sep 4, 2009
    4,801
    44,952
    150
    #1 CODYQX4, Aug 27, 2012
    Last edited by a moderator: Apr 20, 2017
    I'm trying to build a simple torrent downloader for use in Program Updating.

    I am using MonoTorrent, and am passing sample torrent links by hardcoding them. It downloads the torrent, but from there it just doesn't work.

    This is my code

    Code:
    using System;
    using System.IO;
    using MonoTorrent.Common;
    using MonoTorrent.Client;
    using System.Net;
    using System.Threading;
    using MonoTorrent.BEncoding;
    using MonoTorrent.Dht;
    using MonoTorrent.Dht.Listeners;
    
    namespace Updater
    {
        public class Stats
        {
            public string DownloadRate;
            public string UploadRate;
            public string DiskReadRate;
            public string DiskWriteRate;
            public string TotalDiskRead;
            public string TotalDiskWritten;
            public string OpenConnections;
            public string State;
            public string Name;
            public string Progress;
            public int NewPeers;
            public int ExistingPeers;
        }
        class TorrentClient
        {
            private readonly string _dhtNodeFile;
            private readonly string _fastResumeFile;
            private readonly string _torrentPath;
            private readonly ClientEngine _engine;        // The engine used for downloading
            private readonly TorrentManager _torrentMgr;    // The torrentManager will be stored that the engine gives us
            public readonly Stats TorrentStats;
    
            public TorrentClient(string dhtNodeFile, string fastResumeFile, string torrentPath, ClientEngine engine, TorrentManager manager)
            {
                _dhtNodeFile = dhtNodeFile;
                _fastResumeFile = fastResumeFile;
                _torrentPath = torrentPath;
                _engine = engine;
                _torrentMgr = manager;
                TorrentStats = new Stats();
            }
    
            public void StartEngine(int port)
            {
                // Create an instance of the engine.
                _engine.ChangeListenEndpoint(new IPEndPoint(IPAddress.Any, port));
                byte[] nodes = null;
                try
                {
                    nodes = File.ReadAllBytes(_dhtNodeFile);
                }
                catch
                {
                    Console.WriteLine("No existing dht nodes could be loaded");
                }
    
                DhtListener dhtListner = new DhtListener (new IPEndPoint (IPAddress.Any, port));
                DhtEngine dht = new DhtEngine (dhtListner);
                _engine.RegisterDht(dht);
                dhtListner.Start();
                _engine.DhtEngine.Start(nodes);
                
                // If the SavePath does not exist, we want to create it.
                if (!Directory.Exists(_engine.Settings.SavePath))
                    Directory.CreateDirectory(_engine.Settings.SavePath);
    
                // If the torrentsPath does not exist, we want to create it
                if (!Directory.Exists(_torrentPath))
                    Directory.CreateDirectory(_torrentPath);
    
                BEncodedDictionary fastResume;
                try
                {
                    fastResume = BEncodedValue.Decode<BEncodedDictionary>(File.ReadAllBytes(_fastResumeFile));
                }
                catch
                {
                    fastResume = new BEncodedDictionary();
                }
    
                // Load Torrent into the engine.
                // When any preprocessing has been completed, 
                // you register the TorrentManager with the engine.
                if (fastResume.ContainsKey(_torrentMgr.Torrent.InfoHash.ToHex ()))
                    _torrentMgr.LoadFastResume(new FastResume ((BEncodedDictionary)fastResume[_torrentMgr.Torrent.InfoHash.ToHex ()]));
                    _engine.Register(_torrentMgr);
    
                // Assign PeersFound Event
                _torrentMgr.PeersFound += ManagerPeersFound;
    
                ////// Hook into the events in the torrent manager and start the engine.
                ////// Every time a piece is hashed, this is fired.
                ////TorrentMgr.PieceHashed += delegate(object o, PieceHashedEventArgs e)
                ////{
                ////    lock (Listener)
                ////        Listener.WriteLine(string.Format("Piece Hashed: {0} - {1}", e.PieceIndex, e.HashPassed ? "Pass" : "Fail"));
                ////};
    
                ////// Every time the state changes (Stopped -> Seeding -> Downloading -> Hashing) this is fired
                ////TorrentMgr.TorrentStateChanged += delegate(object o, TorrentStateChangedEventArgs e)
                ////{
                ////    lock (Listener)
                ////        Listener.WriteLine("OldState: " + e.OldState.ToString() + " NewState: " + e.NewState.ToString());
                ////};
    
                ////// Every time the tracker's state changes, this is fired
                ////foreach (TrackerTier tier in TorrentMgr.TrackerManager)
                ////{
                ////    foreach (Tracker t in tier.GetTrackers())
                ////    {
                ////        t.AnnounceComplete += (sender, e) => Listener.WriteLine(string.Format("{0}: {1}", e.Successful, e.Tracker));
                ////    }
                ////}
    
                // Start the TorrentManager. The file will then hash (if required) and begin downloading/seeding
                _torrentMgr.Start();
    
                // While the Torrent is still running, save running stats.
                int i = 0;
                while (_torrentMgr.State != TorrentState.Stopped)
                {
                    if ((i++) % 10 == 0)
                    {
                        TorrentStats.DownloadRate = string.Format("{0:0.00} MB", _torrentMgr.Monitor.DataBytesDownloaded / (1024.0 * 1024.0));
                        TorrentStats.UploadRate = string.Format("{0:0.00} MB", _torrentMgr.Monitor.DataBytesUploaded / (1024.0 * 1024.0));
                        TorrentStats.DiskReadRate = string.Format("{0:0.00}kB/s", _engine.DiskManager.ReadRate / 1024.0);
                        TorrentStats.DiskWriteRate = string.Format("{0:0.00}kB/s", _engine.DiskManager.WriteRate / 1024.0);
                        TorrentStats.TotalDiskRead = string.Format("{0:0.00}kB", _engine.DiskManager.TotalRead / 1024.0);
                        TorrentStats.TotalDiskWritten = string.Format("{0:0.00}kB", _engine.DiskManager.TotalWritten / 1024.0);
                        TorrentStats.OpenConnections = string.Format("{0}", _engine.ConnectionManager.OpenConnections / 1024.0);
                        TorrentStats.State = string.Format("{0}", _torrentMgr.State);
                        TorrentStats.Name = string.Format("{0}", _torrentMgr.Torrent == null ? "MetaDataMode" : _torrentMgr.Torrent.Name);
                        TorrentStats.Progress = string.Format("{0:0.00}", _torrentMgr.Progress);
                    }
                    Thread.Sleep(500);
                }
            }
    
            void ManagerPeersFound(object sender, PeersAddedEventArgs e)
            {
                TorrentStats.ExistingPeers = e.ExistingPeers;
                TorrentStats.NewPeers = e.NewPeers;
            }
            
    public void Shutdown()
    {
                BEncodedDictionary fastResume = new BEncodedDictionary();
    
                _torrentMgr.Stop();
                while (_torrentMgr.State != TorrentState.Stopped)
                {
                    Thread.Sleep(250);
                }
    
                fastResume.Add(_torrentMgr.Torrent.InfoHash.ToHex(), _torrentMgr.SaveFastResume().Encode());
    
                #if !DISABLE_DHT
                File.WriteAllBytes(_dhtNodeFile, _engine.DhtEngine.SaveNodes());
                #endif
                File.WriteAllBytes(_fastResumeFile, fastResume.Encode());
                _engine.Dispose();
    
                Thread.Sleep(2000);
    }
    }
    }
    
    This is my Program Form
    Code:
    using System;
    using System.Globalization;
    using System.IO;
    using System.Windows.Forms;
    using MonoTorrent.Client;
    using MonoTorrent.Client.Encryption;
    using MonoTorrent.Common;
    
    namespace Updater
    {
        public partial class TorrentDownloader : Form
        {
            // Test Torrents
            //private const string Uri = "magnet:?xt=urn:btih:54aac947451cd15884d5d8101c8f6830add60536";
            private const string Uri2 = "http://h33t.com/download.php?id=5741e3c848053ae88dbe656a8d1c2cba3c5a3214&f=The+Newsroom+2012+S01E10+HDTV+XviD-AFG%5Bettv%5D.torrent";
    
            /// <summary>
            /// Assign to Label in a Thread-Safe Way
            /// </summary>
            /// <param name="label">Label to Set Text </param>
            /// <param name="text">Text to Assign</param>
            private void SetText(Label label, string text)
            {
                // InvokeRequired required compares the thread ID of the
                // calling thread to the thread ID of the creating thread.
                // If these threads are different, it returns true.
                if (label.InvokeRequired)
                {
                    SetTextDelegate d = SetText;
                    Invoke(d, new object[] { text });
                }
                else
                {
                    label.Text = text;
                }
            }
            #region Nested type: SetTextDelegate
            /// <summary>
            /// This delegate enables asynchronous calls for setting the text property on a TextBox control.
            /// </summary>
            /// <param name="label">Label to Set Text </param>
            /// <param name="text">Text to Assign to TextBox</param>
            private delegate void SetTextDelegate(Label label, string text);
            #endregion
    
            /// <summary>
            /// Assign to ProgressBar in a Thread-Safe Way
            /// </summary>
            /// <param name="progressBar">ProgressBar to Set Value</param>
            /// <param name="value">Value to Assign</param>
            private void SetValue(ProgressBar progressBar, int value)
            {
                // InvokeRequired required compares the thread ID of the
                // calling thread to the thread ID of the creating thread.
                // If these threads are different, it returns true.
                if (progressBar.InvokeRequired)
                {
                    SetValueDelegate d = SetValue;
                    Invoke(d, new object[] { progressBar, value });
                }
                else
                {
                    progressBar.Value = value;
                }
            }
            #region Nested type: SetValueDelegate
            /// <summary>
            /// This delegate enables asynchronous calls for setting the value property on a ProgressBar control.
            /// </summary>
            /// <param name="progressBar">ProgressBar to Set Value</param>
            /// <param name="value">Value to Assign</param>
            private delegate void SetValueDelegate(ProgressBar progressBar, int value);
            #endregion
    
            public TorrentDownloader()
            {
                InitializeComponent();
    
                workerDownloadTorrent.RunWorkerAsync();
            }
    
            private void WorkerDownloadTorrentDoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
            {
                // Start Torrent Client
                StartTorrentClient(12345);
            }
    
            private void StartTorrentClient(int port)
            {
                /* Generate the paths to the folder we will save .torrent files to and where we download files to */
                string basePath = Environment.CurrentDirectory;// This is the directory we are currently in
                string torrentPath = Path.Combine(basePath, "Torrents");    // This is the directory we will save .torrents to
                string downloadsPath = Path.Combine(basePath, "Downloads");// This is the directory we will save downloads to
                string fastResumeFile = Path.Combine(torrentPath, "fastresume.data");
                string dhtNodeFile = Path.Combine(basePath, "DhtNodes");
               
                // Create Torrent
                //MagnetLink magnet = new MagnetLink(uri);
                Torrent torrent = Torrent.Load(new Uri(Uri2), Path.Combine(torrentPath, "MyTorrent.torrent"));
    
                // Create Torrent Settings
                TorrentSettings torrentSettings = new TorrentSettings(4, 150);
    
                // Create Torrent Manager
                TorrentManager manager = new TorrentManager(torrent, downloadsPath, torrentSettings, basePath);
    
                // Create Torrent Engine Settings
                EngineSettings engineSettings = new EngineSettings(downloadsPath, port) { PreferEncryption = false, AllowedEncryption = EncryptionTypes.All };
    
                // Create Torrent Engine
                ClientEngine engine = new ClientEngine(engineSettings);
    
                // Create Torrent Client
                TorrentClient client = new TorrentClient(dhtNodeFile, fastResumeFile, torrentPath, engine, manager);
    
                // Start 
                client.StartEngine(port);
    
                // Show Stats
                while (manager.State != TorrentState.Stopped || Convert.ToInt16(client.TorrentStats.Progress) != 100)
                {
                    SetText(lblTorrentName, client.TorrentStats.Name);
                    SetText(lblTorrentState, client.TorrentStats.State);
                    SetText(lblDownloadSpeed, client.TorrentStats.DownloadRate);
                    SetText(lblUploadSpeed, client.TorrentStats.UploadRate);
                    SetText(lblDiskReadSpeed, client.TorrentStats.DiskReadRate);
                    SetText(lblDiskWriteSpeed, client.TorrentStats.DiskWriteRate);
                    SetText(lblDiskBytesRead, client.TorrentStats.TotalDiskRead);
                    SetText(lblDiskBytesWritten, client.TorrentStats.TotalDiskWritten);
                    SetText(lblOpenConnections, client.TorrentStats.OpenConnections);
                    SetText(lblExistingPeers, client.TorrentStats.ExistingPeers.ToString(CultureInfo.InvariantCulture));
                    SetText(lblNewPeers, client.TorrentStats.NewPeers.ToString(CultureInfo.InvariantCulture));
                    SetValue(downloadProgress, Convert.ToInt16(client.TorrentStats.Progress));
                }
    
                // Shutdown Torrent Client
                client.Shutdown();
            }
        }
    }
    
    It should download the torrent, refresh the form stats, and stop when done, then shutdown the torrent client but leave the form open. But it leaves so signs that it has downloaded anything.
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  2. Josh Cell

    Josh Cell MDL Developer

    Jan 8, 2011
    3,519
    7,100
    120
    The torrent method means a crappy update way to do it. If it has no seeders / leechers will occurs an error. If there are few trackers also.

    I haven't sure, but you can do your app update method using the MDL Forums. Your app tracks the version and download link on your thread and show it on a window.
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  3. CODYQX4

    CODYQX4 MDL Developer

    Sep 4, 2009
    4,801
    44,952
    150
    Just decided to scrap it.
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...