Skip to content

Kevinpgalligan/cl-bittorrent

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

31 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

cl-bittorrent

This is a BitTorrent client written in Common Lisp.

(bittorrent:download-torrent "/path/to/file.torrent" "/download/dir/")

Setup

Clone the repo in your quicklisp local-projects/ directory, or add a symbolic link pointing to wherever you cloned it.

Then:

(ql:quickload 'bittorrent)

Testing

Unit tests:

(ql:quickload 'bittorrent-test)
(in-package bittorrent-test)
(run! 'bittorrent) ; runs all fiveam tests

Integration tests in the scripts/ folder:

  • handshake-test.lisp is used to test the handshake / message-sending between two peer threads. Run in Emacs with slime-eval-buffer.
  • tracker.lisp is used to construct and save a dummy tracker response. Set *peer* if you want a peer listed in the response, run (save-tracker-response) to save the response at the appropriate path.
  • tracker.py runs a dummy tracker server that returns the response generated by tracker.lisp.
  • run-client runs a fresh instance of the client with no existing data, accepts as arguments the path to the torrent file and the path to the download directory. Run from the command-line.

To test 1 client with no peers: (1) start the dummy tracker, (2) run a client from the REPL using download-torrent.

To test 2 clients talking to each other:

  1. Save tracker response to /tmp/ with scripts/tracker.lisp: just load the file and run (save-tracker-response).
  2. Start the dummy tracker (python3 scripts/tracker.py).
  3. Run a client from the command-line (with ./scripts/run-client --torrent data/test.torrent --dir /tmp/).
  4. Add that client's info (port and ID, from the logs) to the tracker: (set-peer! PORT-NUMBER "ID"), then (save-tracker-response) again. Note that the client's ID is URL-encoded and you will want to decode it using (quri:url-decode "STRING-HERE" :encoding :latin1).
  5. Run a client from the REPL using download-torrent, this time include a bit vector as an extra argument indicating which pieces it has downloaded (in the test I'm doing, one client has all the data and the other has none). Example invocation: (download-torrent "/path/to/cl-bittorrent/data/test.torrent" "/path/to/cl-bittorrent/data/" :start-piecemap (make-array 3 :element-type 'bit :initial-element 1) :debug-p t :log-level :debug :log-path "/tmp/c2-log.txt").

Missing features / wishlist

  • Pausing and resuming of downloads.
  • Ability to pick which files to download.
  • Downloading multiple torrents at a time.
  • More generally, consideration of how it could be used as a library / embedded in other applications. As it stands, there are no configuration options or hooks.
  • Resilience to errors: dropped connections, failed file writes, unresponsive tracker, etc.
  • Smarter selection of pieces for download (e.g. rarest first).
  • More faithful implementation of the choking algorithm from the spec (see design.md). Generally, more consideration of how choking/interest are handled (e.g. if a peer becomes interested, do we immediately unchoke it or do we always wait until the 10-second period has elapsed?).
  • UDP communication with trackers -- currently uses the old HTTP protocol, which most trackers don't accept anymore.
  • Let the tracker know when we've finished / are shutting down.
  • Handle case where client is in tracker's list of peers, i.e. don't try communicating with self.
  • Better tracking of upload/download rate for peers. Right now, peers could be sending us vast amounts of junk data, and we would consider them "good uploaders" & keep them unchoked. There's also no feedback from the worker threads to say that data was successfully sent to a peer.
  • A lot of data is being passed around as plists, which fail silently if there's a missing field or the wrong name is used to access a field. I don't like how fragile that is. Need to either replace the getfs with something that fails fast, or replace the plists with objects.
  • Peer thread should close socket on exit.

References

About

A BitTorrent client.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published