Skip to content

aspriddell/csdl

Repository files navigation

csdl

Providing libtorrent through a C++ library for use in .NET on Windows, Linux, macOS and Android.

Usage

Latest Nuget

Add csdl to the project via NuGet and create a single TorrentClient instance. This will usually be static (or singleton if using a dependency container), and a TorrentClientConfig can be passed in the constructor to configure the client.

// create a new TorrentClient instance, optionally passing in the configuration
var options = new TorrentClientConfig
{
    ForceEncryption = true,
    MaxConnections = 500
};

using var client = new TorrentClient(options);

// bonus: there is also an event handler that can be subscribed to if more information is wanted.
client.AlertRaised += (sender, args) =>
{
    // args can be checked against all classes in the csdl.Alerts namespace for more properties.
    Console.WriteLine(args.Message);
};

.torrent files can be parsed either by passing in a file path or a byte array containing the file contents to the TorrentInfo class, and the instance will be populated accordingly. Some metadata can be accessed from the TorrentInfo instance, such as the name of the torrent and a list of files contained within it.

var filePath = "path/to/torrent/file.torrent";
var torrentInfo = new TorrentInfo(filePath);

// get the name and list of files
Console.WriteLine($"Name: {torrentInfo.Name}");
Console.WriteLine("Files:");

foreach (var file in torrentInfo.Files)
{
    Console.WriteLine($"- {file.Path} ({file.Size} bytes)");
}

After parsing a torrent file, it can be "attached" to the client to start downloading the files. Note this method will not start a download, but will prepare the client to download the files when Start is called. This method also has an overload allowing a custom save path to be specified. If not, the default save path will be used (client.DefaultDownloadPath).

// this will be saved to DefaultDownloadPath.
var torrentManager = client.AttachTorrent(torrentInfo);

// the metadata can still be accessed but files have additional properties including their final destination and their download priority, which can be changed.
torrentManager.Files[0].Priority = TorrentFilePriority.DoNotDownload;

// after setting priorities, the download can begin (or resume if the torrent was previously started)
torrentManager.Start();

// if we want a progress update, we can request one
var progress = torrentManager.GetCurrentStatus();

if (progress.State == TorrentState.Finished)
{
    torrentManager.Stop();

    // when we want to "dispose" the manager, we can detach it from the client
    client.DetachTorrent(torrentManager);
}

If we want to wait for the download to complete, a timer and a TaskCompletionSource can be used to await the completion of the download.

void PerformDownload(TorrentClient client, TorrentInfo info, string savePath = null)
{
    var torrentTransfer = new TaskCompletionSource();
    var torrentManager = client.AttachTorrent(info, savePath);
    
    torrentManager.Start();
    
    using (new Timer(PerformProgressCheck, null, TimeSpan.Zero, TimeSpan.FromSeconds(1)))
    {
        await torrentTransfer.Task;
    }

    // at this point, the torrentManager has either finished downloading or seeding, and the poll has been stopped.

    client.DetachTorrent(torrentManager);
    return;

    // this function polls the progress (makes a call to libtorrent) every second to check if the torrent has finished downloading
    void PerformProgressCheck(object state)
    {
        if (torrentManager.GetCurrentStatus().State is TorrentState.Seeding or TorrentState.Finished)
        {
            torrentTransfer.SetResult();
        }
    }
}

Supported Systems

The native libraries, csdl.Native, are currently built for Windows, macOS and Linux for both x64 and arm64 architectures.

Android support is also provided by an optional package, csdl.Native.android which can be installed alongside csdl to extend platform compatibility to Android 5.0+ devices with x86_64, armeabi-v7a and arm64-v8a ABIs.