This repository contains two attempts at my final project for CS386 (Computer Networks) at Reed College.
This version lives in the v1-broken/ directory.
git submodule init; cd bencode; make).
My initial plan was to use C to write a program that would take a .torrent file, decode it, ask one of the specified trackers for a list of peers, and then download the file or files from them. I got it to the point where I was able to send a HTTP request to a tracker, but they all responded with errors along the lines of "torrent not valid". Turns out that the bencode library I was using (and another I tired), were unable to re-encode the info dictionary into bencode that would produce a valid checksum.
At this point I gave up on metainfo files and rewrote it to use the more modern magnet URI scheme. Unfortunately, all the magnet URIs I found preferred UDP trackers. I attempted to write a client for the UDP tracker protocol, but was unable to figure out how to pack together a valid packet.
Therefore, in order to actually get a list of peers, we need a hand-crafted magnet URI that uses HTTP trackers. At this point I was running rather short on time and chose to abandon this program in favour of a LibTorrent wrapper discussed below. The code in the old project is organised in the v1-broken/ directory as follows:
torrent_tstructure with information about the file we want to download, then spawning off a pair of threads to concurrently download and upload chunks to and from peers.
The bak/ directory also contains extract.(c,h) and tracker.(c,h), which, in the earlier iteration of the program, were responsible for decoding the metainfo file and requesting information from a HTTP tracker.
The existing program takes two flags, one to print a help message and
-h), and one to print debugging information (
-v). I strongly
recommend running it with the latter flag. For the sake of simplicity
I only chose to support downloading one torrent at a time, concurrency
can be achieved with an external tool like
The source and Makefile live in v2-working/.
Upon realising that I was on a trajectory to not complete this assignment in time, I investigated LibTorrent, a BitTorrent client implementation in a C++ library, and threw together a basic program.
I was initially resistant to using any kind of library because my primary goal was to learn how BitTorrent, and peer-to-peer protocols more generally, work. I believe I achieved this goal while trying to write the first version. Although I didn't gain any knowledge writing second version (other than how to use LibTorrent and a reminder of how much I dislike C++), I produced a program that could successfully download /ahem/ Linux ISOs from magnet links.
This program lives in a single C++ file and doesn't take any options
other than a magnet link. It does, however, contain a
boolean which you can set to
true if you want to see something more
interesting that the number of bytes downloaded. By default I also
have it set to exit when the torrent is fully downloaded, thought this
can be changed by commenting out the marked lines.