Note: generate this file with
makeinfo --html --no-split doc/guile-torrent.texi.
Table of Contents
This document describes guile-torrent version 0.1, a guile implementation of the bittorrent protocol.
|• Encoding and decoding data:|
|• Managing .torrent files:|
|• Connecting to Trackers:|
|• Sending and Receiving Messages:|
|• Reading and Writing Downloaded Files:|
1 Encoding and decoding data
Some parts of the bittorrent protocol use the bencoding for data
representation. This encoding is implemented in the
module. This module consists of a record type and two public procedures:
- Data Type: dictionnary
This data type represents a dictionnary. A dictionnary is a datastructure that associates values to keys. This field contains only one element,
alist, a association list.
- Scheme Procedure: bencode data
This procedure takes data and returns a
bytevectorcorresponding to the bencoded data. The data can be a
- Scheme Procedure: bdecode port
This procedure takes port and reads data from it. After it reaches
#eof, this procedure returns the data corresponding to what it read in the bencoding. The result can be a
integerdepending on the data that has been read.
2 Managing .torrent files
One of the ways to get torrent informations is by loading a .torrent file. The file contains many useful information, including announce URLs to wich the bittorrent client can ask for more peers regularly, the hash of each piece, their size and the list of files contained in the torrent.
From this, we can derive the infohash which is a
sha-1 hash of a
part of that file and corresponds to the identifier of the torrent.
Although there are multiple methods to get peers for a torrent, they all require
the infohash of the torrent before you can start asking for peers. The infohash
itself can come either from the .torrent file as seen in this section
magnet:// URL. The content of this URL is actually the hexadecimal
representation of the infohash.
(torrent metainfo) module is responsible for parsing .torrent
files. This module contains the following definitions:
- Data Type: metainfo
This data type represents the necessary information contained in the .torrent file.
The info section of the .torrent file.
A string containing the address of the main announce URL for this torrent.
A bytevector representing the infohash of this file.
- Data Type: torrent-info
This data type represents the necessary infomation contained in the
infosection of the .torrent file.
A number representing the number of bytes of each piece
A bytevector representing the concatenation of each piece’s
sha-1hash. This information is useful to independently check each piece’s integrity.
A boolean indicating whether this torrent is private i.e. whether the client must only use the trackers present in the file or if it can use other means such as the peer exchange protocol.
A boolean indicating whether this torrent contains a single file.
A string containing the name of the torrent. In single-file mode, this corresponds to the filename. In multiple-file mode, this corresponds to the name of the folder containing the files.
In single-file mode, a number representing the size of the file in bytes. In multiple-files mode,
In single-file mode,
#f. In multiple-files mode, a list of
torrent-info-fileobjects representing the content of the torrent.
- Data Type: torrent-info-file
This data type represents the necessary information to describe a file from a torrent.
A number representing the size of the file in bytes.
A list of strings representing the path to the file from the top-level directory of the torrent.
This module also defines the following procedure:
- Scheme Procedure: parse-torrent-file file
This procedure parses a .torrent file whose name is contained in file and returns a
metainfoobject containing the necessary information in that file.
3 Connecting to Trackers
(torrent tracker) module contains definitions and procedures that
deal with connecting to a tracker and getting information.
- Data Type: tracker
A string representing the host name of the tracker.
A string representing the path to the annouce page. e.g.
A string representing the protocol used to connect to the tracker. e.g.
A number representing the port of the tracker, or
#fto use the standard port for the protocol.
The infohash of the torrent we are interested in, represented by a bytevector.
The current state of this session:
'startindicates that we still haven’t connected to the tracker during this session;
'completeindicates that we have completed the download but haven’t told the tracker yet;
'stopindicates that we are about to stop, but we haven’t told the server yet;
'runningindicates that we are operating normally.
The number of bytes that we have uploaded during this session.
The number of bytes that we have downloaded during this session.
The number of bytes left that we need to download.
The tracker id or
#fif the tracker didn’t send us its tracker id.
- Data Type: tracker-response
When an error occured, a string containing the reason of the failure. Otherwise
#f. If this field is set, no other field can be considered valid.
When a warning is issued by the tracker, a string containing the content of the warning. Otherwise
A number representing the interval in seconds at which the tracker would want us to ask for more peers.
A number representing the minimum interval in seconds the tracker wants us to respect between two requests.
A string containing the tracker id. If no tracker id is given by the tracker,
#f. Otherwise, this value should be saved for future requests in the
idfield of the
The number of peers the tracker knows of that have finished downloading the torrent.
The number of peers the tracker knows of that have not yet finished downloading the torrent.
A list of peers, each represented by an association list containing two fields:
"port". The value of these fields are integers.
- Scheme Procedure: uri-port uri
Returns the port part of the uri as a number or
#fif it is not specified in the uri.
- Scheme Procedure: url-encode bv
This procedure takes a bytevector and returns the url-encoded value equivalent to the content of the bytevector. This works by using the
%xxencoding for each character that cannot appear in a url.
- Scheme Procedure: ask-more-peers tracker peerid port
This procedure will ask tracker for more peers. peerid and port must contain respectively the peer id and port of our client. This makes a request to the tracker and returns a
tracker-responseobject in case of success or a simple string containing the body of the response in case of error.
- Scheme Procedure: get-new-tracker uri infohash left
This method can be used to initialize all the fields of a new
trackerobject. It returns this new
- Scheme Procedure: tracker-fiber tracker peerid port infohash ending-channel peers-channel
This procedures runs a fiber that connects to the given tracker. peerid and port are our peer ID and port on which we are listening for connections. ending-channel is a channel on which the fiber listens from the
'stopmessage. peers-channel is a channel on which the fiber will put messages about newly found peers. Messages from this fiber are always of this form:
`(("type" 'new-peers) ("new-peers" <tracker-response-peers>)).
4 Sending and Receiving Messages
(torrent protocol) module is responsible for handling protocol
messages and connecting to peers.
- Data Type: peer
This data type represents a peer in the bittorrent protocol. A peer is another client running the bittorrent protocol that either has the file we are interested in or is interested in the file. This record type has the following fields:
A 20-bytes bytevector holding the peer-id of the remote peer.
The socket through which to communicate with the peer.
A bitfield representing the availability of pieces from that peer.
A boolean indicating whether the remote peer choked us. When we are choked, we shouldn’t request blocks to that peer.
A boolean indicating whether the remote peer is interested by what we have. If we wante to send it data, we should unchok it first.
A boolean indicating whether we are choking the remote peer. While we are choking it, it shouldn’t ask
A boolean indicating whether we told the remote peer we were interested. The remote peer will not likely unchoke us unless it is aware we are interested.
- Scheme Procedure: update-peer peer [#:options id sock bitfield choking interested am-choking am-interested channel]
This procedure returns an updated record for peer with the same content for fields of peer, but updating values of the corresponding optional arguments that were given.
Scheme Procedure: get-new-peer host port [#:options (id
This procedure connects to a peer specified by host and port and returns a new peer object. The
idfield is filled with the value of the optional argument id.
- Scheme Procedure: send-handshake sock infohash self-id
This procedure sends a handshake message to sock, a peer socket. The handshake must be the first message sent to the peer. It specifies the infohash and our self-id (peer id).
- Scheme Procedure: receive-handshake sock infohash
This procedure waits for the handshake on sock and compares its content with the infohash we are interested in. If the handshake is valid, returns the remote
peer-idobject associated to the connection, i.e. the peer id of the remote peer. Otherwise, returns
- Scheme Procedure: receive-message sock
This procedure waits for a message on sock and decodes it. If it is an invalid message, returns
#for throws an exception. Otherwise it returns a symbol or an association list corresponding to the message that was received.
The bittorrent protocol specifies these messages:
(("type" 'have) ("piece" piece-num))
(("type" 'bitfield) ("bitfield" bitfield))
(("type" 'request) ("index" index) ("start" start) ("len" len))
(("type" 'piece) ("index" index) ("start" start) ("block" block))
(("type" 'cancel) ("index" index) ("start" start) ("len" len))
(("type" 'port) ("port" port))
- Scheme Procedure: send-keep-alive sock
This procedure sends a keep-alive message. These messages must be sent from time to time because peers will close the connection after typically 2 minutes of inactivity.
- Sceme Procedure: send-choke sock
This procedure sends a message to choke the remote peer on sock. It should not ask us for pieces anymore.
- Scheme Procedure: send-unchoke sock
This procedure send a message to unchoke the remote peer on sock. It can now request pieces from us.
- Scheme Procedure: send-have sock piece
Notify the remote peer on sock we have completed download of piece, the zero-based index of the piece. It doesn’t need to be a piece downloaded from that peer.
- Scheme Procedure: send-bitfield sock bitfield
Send a bitfield to the remote peer on sock to tell it what pieces we already have or not. This is not required if we don’t have any piece yet. This procedure should only be used once after the handshake and before sending any other message.
- Scheme Procedure: send-request sock index start len
Ask the remote peer on sock for a part of a piece of size len, starting at offset start in the index piece. A typical value for len is 16384.
- Scheme Procedure: send-piece sock index start block
Send a block of data to the remote peer on sock. This block corresponds to the index piece at offset start. This should be used after a peer asked us for a piece.
- Scheme Procedure: send-cancel sock index start len
Ask the remote peer on sock to cancel sending the piece to us. The other arguments are the same as for the
- Scheme Procedure: send-port sock listen-port
Send the listen-port we are listening on for the DHT protocol.
- Scheme Procedure: has? bitfield piece
If bitfield is a representation of the bitfield of some peer, returns whether that peer has piece number piece.
- Scheme Procedure: has bitfield piece
Update bitfield such that it now has the bit corresponding to piece number piece set.
Additionnaly, this module defines higher-level functions and data types:
- Data Type: potential-peer
This data type represents coordinates to a peer we aren’t currently connected to. This is typically used to record peer lists received from trackers or other protocols.
The host of the peer.
The port the peer listens on.
Determines whether we learned about that peer a short or a long time ago.
- Scheme Procedure: merge-potential-peers old-peers new-peers
Returns a new list of potential peers that adds peers from new-peers to old-peers, either by adding peers that are not yet in old-peers or updating the freshness of already known peers.
- Scheme Procedure: peer-fiber parent-channel peer peerid infohash bitfield
Runs a fiber that connects to a peer, listens for commands and reports peer status. This fiber runs indefinitely until it receives a
'quitsignal on its private channel.
parent-channel is the channel to which the fiber should report changes to the current peer. These messages are are either
`(("type" peer) ("peer" peer))to report either a new connection or an update to the peer fields, or
`(("type" peer-closed) ("peer" peer))to signal the peer is disconnected and should not be taken into account anymore. This last message is given only when the fiber stops unexpectedly after it advertised a new peer. If an error occured before the connection could be advertised to the parent-channel, no message is sent to the channel.
peer is a
potential-peerwhose host and port fields are used to connect to the peer it represents. peerid is the peer ID of this client. infohash is the infohash of the torrent that should be recovered from that peer and bitfield is the bitfield representation of the pieces we have and don’t have yet.
5 Reading and Writing Downloaded Files
(torrent files) module is responsible for handling downloaded files.
It contains procedures to read, write and check pieces to one or more files.
- Scehem Procedure: check-piece piece-data sha1
Returns whether piece-data contains the data whose hash is sha1.
- Scheme Procedure: create-empty-file filename size
Creates filename and fill it with size null bytes.
- Scheme Procedure: get-block file position size
Read size bytes in filename from position position (in bytes from the beginning of the file).
- Scheme Procedure: get-representation piece-size pieces filename
Returns a list of booleans representing the state of the file: #t for a complete block,
#ffor a missing block.
- Scheme Procedure: get-representation-multiple piece-size pieces files
Returns a list of booleans representing the state of the files: #t for a complete block,
#ffor a missing block.