Index by title

0.90 Changelog

This document is a work in progress

  1. Resolved several issues/inconsistencies when creating torrents using the TorrentCreator.
  2. TorrentCreator now correctly includes MD5s for individual files.
  3. Added the ability to rename files when the torrent is being created
  4. Added the ability to selectively filter files when creating a torrent
  5. PieceLength is automatically set to the 'optimal' value if one is not explicitly set
  6. Added some fast paths when reading data from files to speed up common cases and slightly reduce memory usage
  7. Disable double buffering when reading/writing files
  8. Enhanced .torrent file parsing after I discovered an issue with BinaryReader.PeekChar (). Parsing from a FileStream is now more than 5x faster.
  9. Refactored how pieces are hashed and increased the speed in which files are hashed. The speed boost is roughly proportional to the number of files in a torrent and the piece size. The larger they are, the greater the perfomance boost.

API Reference

List of public class:

ClientEngine
TorrentManager


BanningFiltering IPs

Example 1

This example shows how to prevent a connection being made to the IPAddress '192.168.0.5'

 1 private void BanPeer (ClientEngine engine)
 2 {
 3     // Hook up a handler to the 'BanPeer' event. This is raised
 4     // every time a connection is received or an outgoing connection
 5     // is about to be created. If you wish to close/abort the connection
 6     // just set "BanPeer" to true.
 7     engine.ConnectionManager.BanPeer += delegate(object sender, AttemptConnectionEventArgs e) {
 8         if (e.Peer.ConnectionUri.Host == "192.168.0.5")
 9             e.BanPeer = true;
10     };
11 }

ClientEngine

Description:

client base class:

Events:

StatsUpdate (object sender, StatsUpdateEventArgs args)
CriticalException (object sender, CriticalExceptionEventArgs args)
TorrentRegistered (object sender, TorrentEventArgs args)
TorrentUnregistered (object sender, TorrentEventArgs args)

Properties:

ConnectionManager ConnectionManager
IDhtEngine DhtEngine
DiskManager DiskManager
PeerListener Listener
bool Disposed
PeerListener Listener
bool LocalPeerSearchEnabled
bool IsRunning
string PeerId
EngineSettings Settings

Constructors:

ClientEngine(EngineSettings settings)
ClientEngine(EngineSettings settings, PieceWriter writer)
ClientEngine(EngineSettings settings, PeerListener listener)
ClientEngine(EngineSettings settings, PeerListener listener, PieceWriter writer)

Methods:

void ChangeListenEndpoint(IPEndPoint endpoint)
bool Contains(InfoHash infoHash)
bool Contains(Torrent torrent)
bool Contains(TorrentManager manager)
void Dispose()
void Register(TorrentManager manager)
void Unregister(TorrentManager manager)
void RegisterDht(IDhtEngine engine)
void StartAll()
WaitHandle[] StopAll()
void PauseAll()
int TotalDownloadSpeed
int TotalUploadSpeed

Creating a custom PiecePicker

Example 1 Creating a picker to prioritise the first piece in a file

Example 1

 1 public class MyPicker : PiecePicker {
 2     public MyPicker (PiecePicker basePicker)
 3         : base (basePicker)
 4     {
 5 
 6     }
 7 
 8     public override MessageBundle PickPiece(PeerId id, BitField peerBitfield, List<PeerId> otherPeers, int count, int startIndex, int endIndex)
 9     {
10     // If we do not have the first piece and the other peer does have it
11         if (!HaveFirstPieceAlready && peerBitfield[0] == true) {
12             BitField bf = new BitField (peerBitfield.Length);
13             bf [0] = true;
14             MessageBundle msg = base.PickPiece (id, bf, otherPeers, count, startIndex, endIndex);
15             if (msg != null)
16                 return msg;
17         }
18         return base.PickPiece (id, peerBitfield, otherPeers, count, startIndex, endIndex);
19     }
20 }
21 
22 // This picker can then be added to the default picking pipeline by doing:
23 torrentManager.ChangePicker (new MyPicker (torrentManager.CreateDefaultPicker ()));

Creating Torrents

Example 1 shows how to create a simple torrent.
Example 2 shows how to create a torrent asynchronously so that it does not block the main thread in your application.
Example 3 shows how to abort the creation of a torrent after it has started
Example 4 shows how to create a torrent and load it without having to hash the data a second time

Example 1

 1 // 'path' is the location of the file/folder which is going to be converted
 2 // to a torrent. 'savePath' is where the .torrent file will be saved.
 3 void CreateTorrent(string path, string savePath) {
 4     // The class used for creating the torrent
 5     TorrentCreator c = new TorrentCreator();
 6 
 7     // Add one tier which contains two trackers
 8     RawTrackerTier tier = new RawTrackerTier ();
 9     tier.Add("http://localhost/announce");
10 
11     c.Announces.Add(tier);
12     c.Comment = "This is the comment";
13     c.CreatedBy = "Doug using " + VersionInfo.ClientVersion;
14     c.Publisher = "www.aaronsen.com";
15 
16     // Set the torrent as private so it will not use DHT or peer exchange
17     // Generally you will not want to set this.
18     c.Private = true;
19 
20     // Every time a piece has been hashed, this event will fire. It is an
21     // asynchronous event, so you have to handle threading yourself.
22     c.Hashed += delegate (object o, TorrentCreatorEventArgs e) {
23         Console.WriteLine("Current File is {0}% hashed", e.FileCompletion);
24         Console.WriteLine("Overall {0}% hashed", e.OverallCompletion);
25         Console.WriteLine("Total data to hash: {0}", e.OverallSize);
26     };
27 
28     // ITorrentFileSource can be implemented to provide the TorrentCreator
29     // with a list of files which will be added to the torrent metadata.
30     // The default implementation takes a path to a single file or a path
31     // to a directory. If the path is a directory, all files will be
32     // recursively added
33     ITorrentFileSource fileSource = new TorrentFileSource (path);
34 
35     // Create the torrent file and save it directly to the specified path
36     // Different overloads of 'Create' can be used to save the data to a Stream
37     // or just return it as a BEncodedDictionary (its native format) so it can be
38     // processed in memory
39     c.Create(fileSource, savePath);
40 }

Example 2

 1         // 'path' is the location of the file/folder which is going to be converted
 2         // to a torrent. 'savePath' is where the .torrent file will be saved.
 3         void CreateTorrent(string path, string savePath)
 4         {
 5             // The class used for creating the torrent
 6             TorrentCreator c = new TorrentCreator();
 7 
 8             // Fill in the path, trackers as in Example 1
 9             FillInStandardInformation(c);
10 
11             // Create the torrent asynchronously
12             c.BeginCreate(c, TorrentCreated);
13         }
14 
15         void TorrentCreated(IAsyncResult result)
16         {
17             TorrentCreator c = (TorrentCreator)result.AsyncState;
18 
19             // If any errors occured while creating the torrent, they
20             // will be rethrown here.
21             try
22             {   
23                 // Open the destination file and use the EndCreate overload which
24                 // writes the data directly to the Stream. 
25                 using (FileStream stream = File.OpenWrite(savePath))
26                     c.EndCreate(result, stream);
27             }
28             catch (Exception ex)
29             {
30                 Console.WriteLine("Error creating torrent: {0}", ex);
31             }
32         }

Example 3

 1         // 'path' is the location of the file/folder which is going to be converted
 2         // to a torrent. 'savePath' is where the .torrent file will be saved.
 3         void CreateTorrent(string path, string savePath)
 4         {
 5             // The class used for creating the torrent
 6             TorrentCreator c = new TorrentCreator();
 7 
 8             // Fill in the path, trackers as in Example 1
 9             FillInStandardInformation(c);
10 
11             // Create the torrent asynchronously and keep a reference to the
12             // IAsyncResult it returns
13             TorrentCreatorAsyncResult result = c.BeginCreate(c, TorrentCreated);
14 
15             // Abort creation of the torrent (can be called at any stage). Note, you
16             // can only abort the creation if the torrent is created asynchronously
17             result.Abort();
18         }

Example 4

 1 public static void CreateAndLoadTorrent (ClientEngine engine)
 2 {
 3     // Instantiate a torrent creator
 4     TorrentCreator creator = new TorrentCreator ();
 5 
 6     // Create a TorrentFileSource which is used to populate the .torrent
 7     ITorrentFileSource files = new TorrentFileSource ("somefile.dat");
 8 
 9     // Create the Torrent metadata blob
10     BEncodedDictionary torrentDict = creator.Create (files);
11 
12     // Instantiate a torrent
13     Torrent torrent = Torrent.Load (torrentDict);
14 
15     // Create a fake fast resume data with all the pieces set to true so we
16     // don't have to hash the torrent when adding it directly to the engine.
17     BitField bitfield = new BitField (torrent.Pieces.Count).Not ();
18     FastResume fastResumeData = new FastResume(torrent.InfoHash, bitfield);
19 
20     // Create a TorrentManager so the torrent can be downloaded and load
21     // the FastResume data so we don't have to hash it again.
22     TorrentManager manager = new TorrentManager (torrent, "SavePath", new TorrentSettings ());
23     manager.LoadFastResume (fastResumeData);
24 
25     // Register it with the engine and start the download
26     engine.Register (manager);
27     engine.StartAll ();
28 }

Enable DHT

 1 
 2         public void StartDht (ClientEngine engine, int port)
 3         {
 4             // Send/receive DHT messages on the specified port
 5             IPEndPoint listenAddress = new IPEndPoint (IPAddress.Any, port);
 6 
 7             // Create a listener which will process incoming/outgoing dht messages
 8             DhtListener listener = new UdpListener (listenAddress);
 9 
10             // Create the dht engine
11             DhtEngine dht = new DhtEngine (listener);
12 
13             // Connect the Dht engine to the MonoTorrent engine
14             engine.RegisterDht (dht);
15 
16             // Start listening for dht messages and activate the DHT engine
17             listener.Start ();
18 
19             // If there are existing DHT nodes stored on disk, load them
20             // into the DHT engine so we can try and avoid a (very slow)
21             // full bootstrap
22             byte[] nodes = null;
23             if (File.Exists (path))
24                 nodes = File.ReadAllBytes (nodes);
25             dht.Start (nodes);
26         }
27 
28         public void StopDht (DhtEngine dht, DhtListener listener)
29         {
30             // Stop the listener and dht engine. This does not
31             // clear internal data so the DHT can be started again
32             // later without needing a full bootstrap.
33             listener.Stop ();
34             dht.Stop ();
35 
36             // Save all known dht nodes to disk so they can be restored
37             // later. This is *highly* recommended as it makes startup
38             // much much faster.
39             File.WriteAllBytes (path, dht.SaveNodes ());
40         }


Get Source

git clone http://github.com/mono/bitsharp.git

This command allow you to get all source and all history. If you want to deelop create an account on github and make a fork.

Latest Stable Release

git checkout bitsharp-0.90

This should be used if you want something that works and do not require specific features/fixes which are only available in SVN. This is the recommended starting point for using MonoTorrent.

Latest Unstable

git checkout master

If you require features or fixes which only exist in SVN, want to develop new extensions/features or just want to help test the latest iteration of MonoTorrent, you should use the code from here. Bear in mind that occasionally SVN head can become unstable so if you run into issues either try the latest stable release, or just check out a slightly older revision of the code.

Git tutorial

If you want to send patch, you will have to work git. So here are good Tutorials:
http://help.github.com/
http://linux.yyz.us/git-howto.html
http://groups.google.com/group/pinta/web/git-tutorial?hl=en


Get statistics

Global

ClientEngine.TotalDownloadSpeed
ClientEngine.TotalUploadSpeed

Torrent

To get statistics of a torrrent you use the ConnectionMonitor object.
It is available with torrentManager.Monitor
Here is list of what you can get:

Peer

To have global information about peers:
TorrentManager.Peers.Seeds
TorrentManager.Peers.Leechs
TorrentManager.Peers.Available

You can get detail about each peer in TorrentManager.GetPeers() or from a peerId get in an event.
To get statistics of this particular peer you use the ConnectionMonitor object (same than torrent).
It is available with PeerId.Monitor

And you have few things directely in the peerId object :

Hosting a tracker

Example 1 Shows how to create a basic public tracker which tracks every torrent which it sees in an announce request
Example 2 Shows how to create a private tracker which only tracks torrents explicitly registered with it

Example 1

 1         public void StartTracker ()
 2         {
 3             Tracker tracker = new Tracker();
 4 
 5             // When unregistered torrents are allowed, if a client requests peers for
 6             // a torrent which is not currently monitored by the tracker, that torrent
 7             // will be added automatically. This is useful for creating a 'public' tracker.
 8             // Normally, if this is false, announce requests for torrents not already
 9             // registered with the engine are sent an error message.
10             tracker.AllowUnregisteredTorrents = true;
11 
12             // Set the interval between announce requests to 1 hour and min interval to 10 mins
13             tracker.AnnounceInterval = TimeSpan.FromHours(1);
14             tracker.MinAnnounceInterval = TimeSpan.FromMinutes(10);
15 
16             // Create a listener which will respond to scrape/announce requests
17             // You can pass a prefix like: http://153.462.23.1/announce which will
18             // create a listener on port 80 (the default HTTP port) which will handle
19             // all announce requests.
20             HttpListener listener = new HttpListener("http://myserver.com/announce");
21             tracker.RegisterListener(listener);
22             listener.Start();
23         }

Example 2

 1          // torrentDirectory is a folder containing .torrent files
 2         // which should be loaded into the engine
 3         public void StartTracker(string torrentDirectory)
 4         {
 5             // Create the tracker and register a listener as in Example 1
 6             Tracker tracker = new Tracker();
 7             HttpListener listener = new HttpListener("http://myserver.com/announce");
 8             tracker.RegisterListener(listener);
 9             listener.Start();
10 
11             // If an announce request is received for a torrent which is not registered with the
12             //the tracker an error will be returned.
13             tracker.AllowUnregisteredTorrents = false;
14 
15             // Load all torrents into the engine. Only announce requests for these torrents
16             // (or torrents added in the future) will be processed.
17             foreach (string file in Directory.GetFiles(torrentDirectory))
18             {
19                 Torrent torrent = Torrent.Load(file);
20 
21                 // InfoHashTrackable is a basic subclass of ITrackable. It only stores
22                 // the infohash and name of the torrent. If you need to store additional
23                 // data for each torrent you're tracking, just subclass ITrackable or
24                 // InfoHashTrackable and add the extra data there.
25                 InfoHashTrackable trackable = new InfoHashTrackable(torrent);
26                 tracker.Add(trackable);
27             }
28         }

Documentation

You can read documentation here.
This is a wiki, so you can edit documentation too!

Here are some interesting links to start with:

Else you can ask a question on our forum http://monotorrent.21.forumer.com


Managing Torrents

Example 1 shows how to add a torrent to the engine and start the download
Example 2 shows how to hash check a torrent and show a progress indicator
Example 3 shows how to stop a torrent and remove it from the engine

Example 1

 1     class MainClass
 2     {
 3         ClientEngine engine;
 4         string savePath;
 5 
 6         // savePath is the directory where downloads will be stored
 7         public MainClass(string savePath)
 8         {
 9             // Create a basic ClientEngine without changing any settings
10             this.engine = new ClientEngine(new EngineSettings());
11             this.savePath = savePath;
12         }
13 
14         public void DownloadTorrent(string path)
15         {
16             // Open the .torrent file
17             Torrent torrent = Torrent.Load(path);
18 
19             // Create the manager which will download the torrent to savePath
20             // using the default settings.
21             TorrentManager manager = new TorrentManager(torrent, savePath, new TorrentSettings());
22 
23             // Register the manager with the engine
24             engine.Register(manager);
25 
26             // Begin the download. It is not necessary to call HashCheck on the manager
27             // before starting the download. If a hash check has not been performed, the
28             // manager will enter the Hashing state and perform a hash check before it
29             // begins downloading.
30 
31             // If the torrent is fully downloaded already, calling 'Start' will place
32             // the manager in the Seeding state.
33             manager.Start();
34         }
35     }

Example 2

 1         public void HashTorrent(TorrentManager manager)
 2         {
 3             // Note: The manager must be in the 'Stopped' state in order to perform
 4             // a hash check. Also, to make the sample easier the event handler
 5             // is not unregistered. In your application be careful you don't
 6             // accidentally attach a new event handler every time the torrent is hashed
 7             manager.PieceHashed += delegate (object o, PieceHashedEventArgs e) {
 8                 int pieceIndex = e.PieceIndex;
 9                 int totalPieces = e.TorrentManager.Torrent.Pieces.Count;
10                 double progress = (double) pieceIndex / totalPieces * 100.0;
11                 if (e.HashPassed)
12                     Console.WriteLine("Piece {0} of {1} is complete", pieceIndex, totalPieces);
13                 else
14                     Console.WriteLine("Piece {0} of {1} is corrupt or incomplete ", pieceIndex, totalPieces);
15 
16                 // This shows how complete the hashing is.
17                 Console.WriteLine("Total progress is: {0}%", progress);
18 
19                 // This shows the percentage completion of the download. This value
20                 // is updated as the torrent is hashed or new pieces are downloaded
21                 Console.WriteLine("{0}% of the torrent is complete");
22             };
23 
24             // If 'true' is passed, the torrent will automatically go to the 'Downloading' or 'Seeding'
25             // state once the hash check is finished. Otherwise it will return to the 'Stopped' state.
26             manager.HashCheck(false);
27         }

Example 3

 1         public void StopTorrent(TorrentManager manager)
 2         {
 3             // When stopping a torrent, certain cleanup tasks need to be perfomed
 4             // such as flushing unwritten data to disk and informing the tracker
 5             // the client is no longer downloading/seeding the torrent. To allow for
 6             // this, when Stop is called the manager enters a 'Stopping' state. Once
 7             // all the tasks are completed the manager will enter the 'Stopped' state.
 8 
 9             // Hook into the TorrentStateChanged event so we can tell when the torrent
10             // finishes cleanup
11             manager.TorrentStateChanged += delegate (object o, TorrentStateChangedEventArgs e) {
12                 if (e.NewState == TorrentState.Stopping)
13                 {
14                     Console.WriteLine("Torrent {0} has begun stopping", e.TorrentManager.Torrent.Name);
15                 }
16                 else if (e.NewState == TorrentState.Stopped)
17                 {
18                     // It is now safe to unregister the torrent from the engine and dispose of it (if required)
19                     engine.Unregister(manager);
20                     manager.Dispose();
21 
22                     Console.WriteLine("Torrent {0} has stopped", e.TorrentManager.Torrent.Name);
23                 }
24             };
25 
26             // Begin the process to stop the torrent
27             manager.Stop ();
28         }

Save/Load Fast Resume

This is used so that a full hash check does not have to be performed the first time a torrent is started. Normally all the data for a torrent would be passed through a SHA1 hasher so that data integrity can be verified. With fast resume you can skip this step.

 1         public void SaveFastResume (List <TorrentManager> managers)
 2         {
 3             // Store the fast resume for each torrent in a list,
 4             // then serialise the list to the disk.
 5             BEncodedList list = new BEncodedList ();
 6             foreach (TorrentManager manager in managers) {
 7 
 8                 // Get the fast resume data for the torrent
 9                 FastResume data = manager.SaveFastResume ();
10 
11                 // Encode the FastResume data to a BEncodedDictionary.
12                 BEncodedDictionary fastResume = data.Encode ();
13 
14                 // Add the FastResume dictionary to the main dictionary using
15                 // the torrents infohash as the key
16                 list.Add (data);
17             }
18 
19             // Write all the fast resume data to disk
20             File.WriteAllBytes (fastResumePath, list.Encode ());
21         }
22 
23         public void LoadFastResume (List <TorrentManager> managers)
24         {
25             // Read the main dictionary from disk and iterate through
26             // all the fast resume items
27             BEncodedList list = (BEncodedList) BEncodedValue.Decode (File.ReadAllBytes (fastResumePath));
28             foreach (BEncodedDictionary fastResume in list) {
29 
30                 // Decode the FastResume data from the BEncodedDictionary
31                 FastResume data = new FastResume (fastResume);
32 
33                 // Find the torrentmanager that the fastresume belongs to
34                 // and then load it
35                 foreach (TorrentManager manager in managers)
36                     if (manager.InfoHash == data.Infohash)
37                         manager.LoadFastResume (data);
38             }
39         }

Selective/Prioritised Downloading

Example 1 Shows how to prevent certain files from being downloaded and also prioritise other files

Example 1

 1         public void SelectiveDownload (TorrentManager manager)
 2         {
 3             Torrent torrent = manager.Torrent;
 4 
 5             // Don't download any files in the 'Docs' subfolder
 6             foreach (TorrentFile file in torrent.Files) {
 7                 if (file.Path.StartsWith ("Docs"))
 8                     file.Priority = Priority.DoNotDownload;
 9             }
10 
11             // Prioritise everything in the 'Data' subfolder
12             foreach (TorrentFile file in torrent.Files) {
13                 if (file.Path.StartsWith ("Data"))
14                     file.Priority = Priority.High;
15             }
16 
17             // Get all '.txt' files first
18             foreach (TorrentFile file in torrent.Files) {
19                 if (file.Path.EndsWith (".txt"))
20                     file.Priority = Priority.Immediate;
21             }
22         }


TorrentManager

Events:

PeerConnected(object sender, PeerConnectionEventArgs  args)
PeerDisconnected(object sender, PeerConnectionEventArgs args)
PeersFound(object sender, PeersAddedEventArgs args)
PieceHashed(object sender, PieceHashedEventArgs args)
TorrentStateChanged(object sender, TorrentStateChangedEventArgs args)

Properties:

BitField Bitfield
bool CanUseDht
bool Complete
ClientEngine Engine
Error Error
int PeerReviewRoundsComplete
bool HashChecked
bool HasMetadata
ConnectionMonitor Monitor
int OpenConnections
PeerManager Peers
PieceManager PieceManager
double Progress
string SavePath
TorrentSettings Settings
TorrentState State
DateTime StartTime
TrackerManager TrackerManager
Torrent Torrent
int UploadingTo
bool IsInitialSeeding
InfoHash InfoHash

Constructor:

TorrentManager(Torrent torrent, string savePath, TorrentSettings settings)
TorrentManager(Torrent torrent, string savePath, TorrentSettings settings, string baseDirectory)
TorrentManager(InfoHash infoHash, string savePath, TorrentSettings settings, string torrentSave, List&lt;MonoTorrentCollection&lt;string&gt;> announces)

Methods

void ChangePicker(PiecePicker picker)
List &lt;Piece&gt; GetActiveRequests()
List &lt;PeerId&gt; GetPeers()
void HashCheck(bool autoStart)
void MoveFiles(string newPath, bool overWriteExisting)
void Pause()
void Start()
WaitHandle Stop()
void LoadFastResume(FastResume data)
FastResume SaveFastResume()
void Dispose()
string ToString( )
bool Equals(object obj)
bool Equals(TorrentManager other)
int GetHashCode()