2003-10-23 01:00:57 +02:00
|
|
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
|
|
|
|
|
|
|
|
<html>
|
|
|
|
<head>
|
|
|
|
<title>libtorrent</title>
|
|
|
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
|
|
|
<link href="style.css" type="text/css" rel="stylesheet">
|
|
|
|
</head>
|
|
|
|
|
|
|
|
<body>
|
|
|
|
|
|
|
|
<h1>libtorrent</h1>
|
2003-10-23 18:55:52 +02:00
|
|
|
|
|
|
|
<table style="margin-left:auto;margin-right:auto" cellpadding="10">
|
|
|
|
<tr>
|
|
|
|
<td>
|
|
|
|
<a href="http://www.sourceforge.net/projects/libtorrent">sourceforge page</a>
|
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
<a href="http://lists.sourceforge.net/lists/listinfo/libtorrent-discuss">mailing list</a>
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
</table>
|
|
|
|
|
|
|
|
|
2003-10-23 01:00:57 +02:00
|
|
|
<p>
|
|
|
|
libtorrent is a C++ library that aims to be a good alternative to all the
|
|
|
|
<a href="links.html">other bittorrent implementations</a> around. It is a
|
|
|
|
library and not a full featured client, although it comes with a working
|
|
|
|
example client.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
The main goals of libtorrent are:
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<ul>
|
|
|
|
<li>to be cpu efficient
|
|
|
|
<li>to be memory efficient
|
|
|
|
<li>to be very easy to use
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
libtorrent is not finished. It is an ongoing project (including this documentation).
|
|
|
|
The current state includes the following features:
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<ul>
|
|
|
|
<li>multitracker extension support
|
|
|
|
(as <a href="http://home.elp.rr.com/tur/multitracker-spec.txt">described by TheShadow</a>)
|
|
|
|
<li>serves multiple torrents on a single port and a single thread
|
|
|
|
<li>supports http proxies and proxy authentication
|
|
|
|
<li>gzipped tracker-responses
|
|
|
|
<li>piece picking on block-level (as opposed to piece-level) like in
|
|
|
|
<a href="http://azureus.sourceforge.net/">Azureus</a>
|
2003-11-02 22:06:50 +01:00
|
|
|
<li>queues torrents for file check, instead of checking all of them in parallel.
|
|
|
|
<li>uses separate threads for checking files and for main downloader, with a fool-proof
|
|
|
|
thread-safe library interface. (i.e. There's no way for the user to cause a deadlock).
|
2003-11-09 19:17:09 +01:00
|
|
|
<li>can limit the upload bandwidth usage
|
2003-11-02 22:06:50 +01:00
|
|
|
</ul>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
Functions that are yet to be implemented:
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<ul>
|
|
|
|
<li>optimistic unchoke
|
|
|
|
<li>Snubbing
|
|
|
|
<li>end game mode
|
|
|
|
<li>new allocation model
|
|
|
|
<li>fast resume
|
|
|
|
<li>file-level piece priority
|
2003-11-09 19:17:09 +01:00
|
|
|
<li>a good upload speed cap
|
2003-10-23 01:00:57 +02:00
|
|
|
</ul>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
libtorrent is portable at least among windows, macosx, and UNIX-systems. It uses boost.thread,
|
|
|
|
boost.filesystem and various other boost libraries and zlib.
|
|
|
|
</p>
|
|
|
|
|
2003-10-24 14:44:18 +02:00
|
|
|
<p>
|
|
|
|
libtorrent has been successfully compiled and tested on:
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<ul>
|
2003-10-26 04:18:17 +01:00
|
|
|
<li>Cygwin GCC 3.3.1
|
|
|
|
<li>Windows 2000 vc7.1
|
|
|
|
<li>Linux x86 (debian) GCC 3.0
|
2003-10-24 14:44:18 +02:00
|
|
|
</ul>
|
|
|
|
|
2003-10-23 01:00:57 +02:00
|
|
|
<h1>building</h1>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
To build libtorrent you need <a href="http://www.boost.org">boost</a> and bjam installed.
|
|
|
|
Then you can use <tt>bjam</tt> to build libtorrent.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
To make bjam work, you need to set the environment variable <tt>BOOST_ROOT</tt> to the
|
|
|
|
path where boost is installed (e.g. c:\boost_1_30_2 on windows). Then you can just run
|
|
|
|
<tt>bjam</tt> in the libtorrent directory.
|
|
|
|
</p>
|
|
|
|
|
2003-10-24 13:42:07 +02:00
|
|
|
<p>
|
|
|
|
The Jamfile doesn't work yet. On unix-systems you can use the makefile however. You
|
|
|
|
first have to build boost.thread and boost.filesystem. You do this by, in the directory
|
|
|
|
'boost-1.30.2/tools/build/jam_src' run the build script <tt>./build.sh</tt>. This should
|
|
|
|
produce at least one folder with the 'bin' prefix (and the rest of the name describes
|
|
|
|
your platform). Put the files in that folder somewhere in your path.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
You can then invoke <tt>bjam</tt> in the directories 'boost-1.30.2/libs/thread/build' and
|
|
|
|
'boost-1.30.2/libs/filesystem/build'. That will produce the needed libraries. Put these
|
|
|
|
libraries in the libtorrent root directory. You then have to modify the makefile to use
|
|
|
|
you prefered compiler and to have the correct path to your boost istallation.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
Then the makefile should be able to do the rest.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
When building (with boost 1.30.2) on linux and solaris however, I found that I had to make the following
|
|
|
|
modifications to the boost.date-time library. In the file:
|
2003-10-30 00:28:09 +01:00
|
|
|
'boost-1.30.2/boost/date_time/gregorian_calendar.hpp' line 59. Prepend 'boost/date_time/'
|
2003-10-24 13:42:07 +02:00
|
|
|
to the include path.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>And the second modification was in the file:
|
|
|
|
'boost-1.30.2/boost/date_time/microsec_time_clock.hpp' add the following include at the top
|
|
|
|
of the file:
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<code>#include "boost/cstdint.hpp"</code>
|
|
|
|
|
2003-10-23 01:00:57 +02:00
|
|
|
<p>
|
|
|
|
TODO: more detailed build instructions.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<h1>using</h1>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
The interface of libtorrent consists of a few classes. The main class is
|
|
|
|
the <tt>session</tt>, it contains the main loop that serves all torrents.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<h2>session</h2>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
The <tt>session</tt> class has the following synopsis:
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
class session: public boost::noncopyable
|
|
|
|
{
|
2003-10-26 18:35:23 +01:00
|
|
|
session(int listen_port, const std::string& fingerprint = std::string());
|
2003-10-23 01:00:57 +02:00
|
|
|
|
|
|
|
torrent_handle add_torrent(const torrent_info& t, const std::string& save_path);
|
2003-11-08 03:16:26 +01:00
|
|
|
void remove_torrent(const torrent_handle& h);
|
2003-10-23 01:00:57 +02:00
|
|
|
|
|
|
|
void set_http_settings(const http_settings& settings);
|
2003-11-09 19:17:09 +01:00
|
|
|
void set_upload_rate_limit(int bytes_per_second);
|
2003-10-23 01:00:57 +02:00
|
|
|
};
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
Once it's created, it will spawn the main thread that will do all the work.
|
|
|
|
The main thread will be idle as long it doesn't have any torrents to participate in.
|
|
|
|
You add torrents through the <tt>add_torrent()</tt>-function where you give an
|
|
|
|
object representing the information found in the torrent file and the path where you
|
|
|
|
want to save the files. The <tt>save_path</tt> will be prepended to the directory-
|
|
|
|
structure in the torrent-file.
|
|
|
|
</p>
|
|
|
|
|
2003-11-08 03:16:26 +01:00
|
|
|
<p>
|
|
|
|
<tt>remove_torrent()</tt> will close all peer connections associated with the torrent and tell
|
|
|
|
the tracker that we've stopped participating in the swarm.
|
|
|
|
</p>
|
|
|
|
|
2003-11-02 22:06:50 +01:00
|
|
|
<p>
|
|
|
|
If the torrent you are trying to add already exists in the session (is either queued
|
|
|
|
for checking, being checked or downloading) <tt>add_torrent()</tt> will throw
|
|
|
|
<tt>duplicate_torrent</tt> which derives from <tt>std::exception</tt>.
|
|
|
|
</p>
|
|
|
|
|
2003-10-26 18:35:23 +01:00
|
|
|
<p>
|
|
|
|
<tt>fingerprint</tt> is a short string that will be used in the peer_id to
|
2003-10-31 16:06:32 +01:00
|
|
|
identify the client. If the string is longer than 7 characters it will
|
|
|
|
be trimmed down to 7 characters. The default is an empty string.
|
2003-10-26 18:35:23 +01:00
|
|
|
</p>
|
|
|
|
|
2003-11-09 19:17:09 +01:00
|
|
|
<p>
|
|
|
|
<tt>set_upload_rate_limit()</tt> set the maximum number of bytes allowed to be
|
|
|
|
sent to peers per second. This bandwidth is distributed among all the peers. If
|
|
|
|
you don't want to limit upload rate, you can set this to -1 (the default).
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
The destructor of session will notify all trackers that our torrents has been shut down.
|
|
|
|
If some trackers are down, they will timout. All this before the destructor of session
|
|
|
|
returns. So, it's adviced that any kind of interface (such as windows) are closed before
|
|
|
|
destructing the sessoin object. Because it can take a few second for it to finish. The
|
|
|
|
timeout can be set with <tt>set_http_settings()</tt>.
|
|
|
|
</p>
|
|
|
|
|
2003-10-23 01:00:57 +02:00
|
|
|
<p>
|
|
|
|
How to parse a torrent file and create a <tt>torrent_info</tt> object is described below.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
The <a href="#torrent_handle"><tt>torrent_handle</tt></a> returned by <tt>add_torrent</tt>
|
|
|
|
can be used to retrieve information about the torrent's progress, its peers etc. It
|
|
|
|
is also used to abort a torrent.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
The constructor takes a listen port as argument, if the given port is busy it will
|
|
|
|
increase the port number by one and try again. If it still fails it will continue
|
|
|
|
increasing the port number until it succeeds or has failed 9 ports. <i>This will
|
|
|
|
change in the future to give more control of the listen-port.</i>
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<h2>parsing torrent files</h2>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
The torrent files are <a href="http://bitconjurer.org/BitTorrent/protocol.html">
|
|
|
|
bencoded</a>. There are two functions in libtorrent that can encode and decode
|
|
|
|
bencoded data. They are:
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<h3>
|
|
|
|
template<class InIt>
|
|
|
|
entry bdecode(InIt start, InIt end);<br>
|
|
|
|
|
|
|
|
template<class OutIt>
|
|
|
|
void bencode(OutIt out, const entry& e);
|
|
|
|
</h3>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
The <tt>entry</tt> class is the internal representation of the bencoded data
|
|
|
|
and it can be used to retreive information, an entry can also be build by
|
|
|
|
the program and given to <tt>bencode()</tt> to encode it into the <tt>OutIt</tt>
|
|
|
|
iterator.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
The <tt>OutIt</tt> and <tt>InIt</tt> are iterators
|
|
|
|
(<a href="http://www.sgi.com/tech/stl/InputIterator.html"><tt>InputIterator</tt></a>
|
|
|
|
and <a href="http://www.sgi.com/tech/stl/OutputIterator.html"><tt>OutputIterator</tt></a>
|
|
|
|
respectively). They are templates and are usually instantiated as
|
|
|
|
<a href="http://www.sgi.com/tech/stl/ostream_iterator.html">
|
|
|
|
<tt>std::ostream_iterator</tt></a>,
|
|
|
|
<a href="http://www.sgi.com/tech/stl/back_insert_iterator.html">
|
|
|
|
<tt>std::back_insert_iterator</tt></a> or
|
|
|
|
<a href="http://www.sgi.com/tech/stl/istream_iterator.html">
|
|
|
|
<tt>std::istream_iterator</tt></a>. These functions will assume that the iterator
|
|
|
|
refers to a character (<tt>char</tt>). So, if you want to encode entry <tt>e</tt>
|
|
|
|
into a buffer in memory, you can do it like this:
|
|
|
|
</p>
|
|
|
|
|
2003-10-30 00:28:09 +01:00
|
|
|
<code>std::vector<char> buffer;
|
2003-10-23 01:00:57 +02:00
|
|
|
bencode(std::back_insert_iterator<std::vector<char> >(buf), e);
|
|
|
|
</code>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
If you want to decode a torrent file from a buffer in memory, you can do it like this:
|
|
|
|
</p>
|
|
|
|
|
2003-10-30 00:28:09 +01:00
|
|
|
<code>std::vector<char> buffer;
|
2003-10-23 01:00:57 +02:00
|
|
|
|
|
|
|
// ...
|
|
|
|
|
|
|
|
entry e = bdecode(buf.begin(), buf.end());
|
|
|
|
</code>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
Or, if you have a raw char buffer:
|
|
|
|
</p>
|
|
|
|
|
2003-10-30 00:28:09 +01:00
|
|
|
<code>const char* buf;
|
2003-10-23 01:00:57 +02:00
|
|
|
|
|
|
|
// ...
|
|
|
|
|
|
|
|
entry e = bdecode(buf, buf + data_size);
|
|
|
|
</code>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
Now we just need to know how to retrieve information from the <tt>entry</tt>.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<h2>entry</h2>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
The <tt>entry</tt> class represents one node in a bencoded hierarchy. It works as a
|
|
|
|
variant type, it can be either a list, a dictionary (<tt>std::map</tt>), an integer
|
|
|
|
or a string. This is its synopsis:
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
class entry
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
typedef std::map<std::string, entry> dictionary_type;
|
|
|
|
typedef std::string string_type;
|
|
|
|
typedef std::vector<entry> list_type;
|
|
|
|
typedef <i>implementation-defined</i> integer_type;
|
|
|
|
|
|
|
|
enum data_type
|
|
|
|
{
|
|
|
|
int_t,
|
|
|
|
string_t,
|
|
|
|
list_t,
|
|
|
|
dictionary_t,
|
|
|
|
undefined_t
|
|
|
|
};
|
|
|
|
|
|
|
|
data_type type() const;
|
|
|
|
|
|
|
|
entry();
|
|
|
|
entry(data_type t);
|
|
|
|
entry(const entry& e);
|
|
|
|
|
|
|
|
void operator=(const entry& e);
|
|
|
|
|
|
|
|
integer_type& integer()
|
|
|
|
const integer_type& integer() const;
|
|
|
|
string_type& string();
|
|
|
|
const string_type& string() const;
|
|
|
|
list_type& list();
|
|
|
|
const list_type& list() const;
|
|
|
|
dictionary_type& dict();
|
|
|
|
const dictionary_type& dict() const;
|
|
|
|
|
2003-10-28 02:20:50 +01:00
|
|
|
void print(std::ostream& os, int indent = 0) const;
|
2003-10-23 01:00:57 +02:00
|
|
|
};
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
The <tt>integer()</tt>, <tt>string()</tt>, <tt>list()</tt> and <tt>dict()</tt> functions
|
|
|
|
are accessorts that return the respecive type. If the <tt>entry</tt> object isn't of the
|
|
|
|
type you request, the accessor will throw <tt>type_error</tt> (which derives from
|
|
|
|
<tt>std::runtime_error</tt>). You can ask an <tt>entry</tt> for its type through the
|
|
|
|
<tt>type()</tt> function.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
The <tt>print()</tt> function is there for debug purposes only.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
If you want to create an <tt>entry</tt> you give it the type you want it to have in its
|
|
|
|
constructor, and then use one of the non-const accessors to get a reference which you then
|
|
|
|
can assign the value you want it to have.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
The typical code to get info from a torrent file will then look like this:
|
|
|
|
</p>
|
|
|
|
|
2003-10-30 00:28:09 +01:00
|
|
|
<code>entry torrent_file;
|
2003-10-23 01:00:57 +02:00
|
|
|
|
|
|
|
// ...
|
|
|
|
|
|
|
|
const entry::dictionary_type& dict = torrent_file.dict();
|
|
|
|
entry::dictionary_type::const_iterator i;
|
|
|
|
i = dict.find("announce");
|
|
|
|
if (i != dict.end())
|
|
|
|
{
|
|
|
|
std::string tracker_url= i->second.string();
|
|
|
|
std::cout << tracker_url << "\n";
|
|
|
|
}
|
|
|
|
</code>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
To make it easier to extract information from a torren file, the class <tt>torrent_info</tt>
|
|
|
|
exists.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<h2>torrent_info</h2>
|
|
|
|
<p>
|
|
|
|
The <tt>torrent_info</tt> has the following synopsis:
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
class torrent_info
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
torrent_info(const entry& torrent_file)
|
|
|
|
|
|
|
|
typedef std::vector<file>::const_iterator file_iterator;
|
|
|
|
typedef std::vector<file>::const_reverse_iterator reverse_file_iterator;
|
|
|
|
|
|
|
|
file_iterator begin_files() const;
|
|
|
|
file_iterator end_files() const;
|
|
|
|
reverse_file_iterator rbegin_files() const;
|
|
|
|
reverse_file_iterator rend_files() const;
|
|
|
|
|
|
|
|
std::size_t num_files() const;
|
|
|
|
const file& file_at(int index) const;
|
|
|
|
|
|
|
|
const std::vector<announce_entry>& trackers() const;
|
|
|
|
|
|
|
|
int prioritize_tracker(int index);
|
|
|
|
|
|
|
|
entry::integer_type total_size() const;
|
|
|
|
entry::integer_type piece_length() const;
|
|
|
|
std::size_t num_pieces() const;
|
|
|
|
const sha1_hash& info_hash() const;
|
2003-10-30 00:28:09 +01:00
|
|
|
const std::stirng& name() const;
|
2003-10-23 01:00:57 +02:00
|
|
|
|
|
|
|
void print(std::ostream& os) const;
|
|
|
|
|
|
|
|
entry::integer_type piece_size(unsigned int index) const;
|
|
|
|
const sha1_hash& hash_for_piece(unsigned int index) const;
|
|
|
|
};
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
This class will need some explanation. First of all, to get a list of all files
|
|
|
|
in the torrent, you can use <tt>begin_files()</tt>, <tt>end_files()</tt>,
|
|
|
|
<tt>rbegin_files()</tt> and <tt>rend_files()</tt>. These will give you standard vector
|
|
|
|
iterators with the type <tt>file</tt>.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
struct file
|
|
|
|
{
|
|
|
|
std::string path;
|
|
|
|
std::string filename;
|
|
|
|
entry::integer_type size;
|
|
|
|
};
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
If you need index-access to files you can use the <tt>num_files()</tt> and <tt>file_at()
|
|
|
|
</tt> to access files using indices.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
The <tt>print()</tt> function is there for debug purposes only. It will print the info from
|
|
|
|
the torrent file to the given outstream.
|
|
|
|
</p>
|
|
|
|
|
2003-10-30 00:28:09 +01:00
|
|
|
<p>
|
|
|
|
<tt>name()</tt> returns the name of the torrent.
|
|
|
|
</p>
|
|
|
|
|
2003-10-23 01:00:57 +02:00
|
|
|
<p>
|
|
|
|
The <tt>trackers()</tt> function will return a sorted vector of <tt>announce_entry</tt>.
|
|
|
|
Each announce entry contains a string, which is the tracker url, and a tier index. The
|
|
|
|
tier index is the high-level priority. No matter which trackers that works or not, the
|
|
|
|
ones with lower tier will always be tried before the one with higher tier number.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
struct announce_entry
|
|
|
|
{
|
|
|
|
std::string url;
|
|
|
|
int tier;
|
|
|
|
};
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
The <tt>prioritize_tracker()</tt> is used internally to move a tracker to the front
|
|
|
|
of its tier group. i.e. It will never be moved pass a tracker with a different tier
|
|
|
|
number. For more information about how multiple trackers are dealt with, see the
|
|
|
|
<a href="http://home.elp.rr.com/tur/multitracker-spec.txt">specification</a>.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
<tt>total_size()</tt>, <tt>piece_length()</tt> and <tt>num_pieces()</tt> returns the total
|
|
|
|
number of bytes the torrent-file represents (all the files in it), the number of byte for
|
|
|
|
each piece and the total number of pieces, respectively. The difference between
|
|
|
|
<tt>piece_size()</tt> and <tt>piece_length()</tt> is that <tt>piece_size()</tt> takes
|
|
|
|
the piece index as argument and gives you the exact size of that piece. It will always
|
|
|
|
be the same as <tt>piece_length()</tt> except in the case of the last piece, which may
|
|
|
|
be smaller.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
<tt>hash_for_piece()</tt> takes a piece-index and returns the 20-bytes sha1-hash for that
|
|
|
|
piece and <tt>info_hash()</tt> returns the 20-bytes sha1-hash for the info-section of the
|
|
|
|
torrent file. For more information on the <tt>sha1_hash</tt>, see the <a href="#big_number">big_number</a> class.
|
|
|
|
</p>
|
|
|
|
|
2003-10-31 16:06:32 +01:00
|
|
|
<h2><a name="torrent_handle"></a>torrent_handle</h2>
|
2003-10-23 01:00:57 +02:00
|
|
|
|
|
|
|
<p>
|
|
|
|
You will usually have to store your <tt>torrent_handle</tt>s somewhere, since it's the
|
2003-10-31 16:06:32 +01:00
|
|
|
object through which you retrieve infromation about the torrent and aborts the torrent.
|
2003-10-23 01:00:57 +02:00
|
|
|
Its declaration looks like this:
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
struct torrent_handle
|
|
|
|
{
|
|
|
|
torrent_handle();
|
|
|
|
|
2003-10-31 05:02:51 +01:00
|
|
|
torrent_status status() const;
|
2003-11-02 22:06:50 +01:00
|
|
|
void get_download_queue(std::vector<partial_piece_info>& queue);
|
|
|
|
void get_peer_info(std::vector<peer_info>& v);
|
2003-10-23 01:00:57 +02:00
|
|
|
};
|
|
|
|
</pre>
|
|
|
|
|
2003-11-02 22:06:50 +01:00
|
|
|
<p>
|
|
|
|
The default constructor will initialize the handle to an invalid state. Which means you cannot
|
|
|
|
perform any operation on it, unless you first assign it a valid handle. If you try to perform
|
|
|
|
any operation they will simply return.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<h3>status()</h3>
|
|
|
|
|
2003-10-23 01:00:57 +02:00
|
|
|
<p>
|
2003-10-31 05:02:51 +01:00
|
|
|
<tt>status()</tt> will return a structure with information about the status of this
|
|
|
|
torrent. It contains the following fields:
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
struct torrent_status
|
|
|
|
{
|
|
|
|
enum state_t
|
|
|
|
{
|
|
|
|
invalid_handle,
|
|
|
|
queued_for_checking,
|
|
|
|
checking_files,
|
|
|
|
downloading,
|
|
|
|
seeding
|
|
|
|
};
|
|
|
|
|
|
|
|
state_t state;
|
|
|
|
float progress;
|
2003-11-05 00:27:06 +01:00
|
|
|
boost::posix_time::time_duration next_announce;
|
2003-10-31 05:02:51 +01:00
|
|
|
std::size_t total_download;
|
|
|
|
std::size_t total_upload;
|
|
|
|
};
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
<tt>progress</tt> is a value in the range [0, 1], that represents the progress of the
|
|
|
|
torrent's current task. It may be checking files or downloading. The torrent's
|
|
|
|
current task is in the <tt>state</tt> member, it will be one of the following:
|
2003-10-23 01:00:57 +02:00
|
|
|
</p>
|
|
|
|
|
|
|
|
<table>
|
2003-11-02 22:06:50 +01:00
|
|
|
<tr>
|
|
|
|
<td>
|
|
|
|
<tt>invalid_handle</tt>
|
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
This will be the state if you called status on an uninitialized handle (a
|
|
|
|
handle that was constructed with the default constructor).
|
|
|
|
</td>
|
|
|
|
</tr>
|
2003-10-23 01:00:57 +02:00
|
|
|
<tr>
|
|
|
|
<td>
|
2003-10-31 13:15:32 +01:00
|
|
|
<tt>queued_for_checking</tt>
|
2003-10-23 01:00:57 +02:00
|
|
|
</td>
|
|
|
|
<td>
|
2003-10-31 05:02:51 +01:00
|
|
|
The torrent is in the queue for being checked. But there currently is another
|
|
|
|
torrent that are being checked. This torrent will wait for its turn.
|
2003-10-23 01:00:57 +02:00
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td>
|
2003-10-31 05:02:51 +01:00
|
|
|
<tt>checking_files</tt>
|
2003-10-23 01:00:57 +02:00
|
|
|
</td>
|
|
|
|
<td>
|
2003-10-31 05:02:51 +01:00
|
|
|
The torrent has not started its download yet, and is currently checking existing
|
|
|
|
files.
|
2003-10-23 01:00:57 +02:00
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td>
|
|
|
|
<tt>downloading</tt>
|
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
The torrent is being downloaded. This is the state most torrents will be in most
|
|
|
|
of the time. The progress meter will tell how much of the files that has been
|
|
|
|
downloaded.
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td>
|
|
|
|
<tt>seeding</tt>
|
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
In this state the torrent has finished downloading and is a pure seeder.
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
</table>
|
|
|
|
|
2003-11-05 00:27:06 +01:00
|
|
|
<p>
|
|
|
|
<tt>next_announce</tt> is the time until the torrent will announce itself to the tracker.
|
|
|
|
</p>
|
|
|
|
|
2003-10-23 01:00:57 +02:00
|
|
|
<p>
|
2003-10-31 05:02:51 +01:00
|
|
|
<tt>total_download</tt> and <tt>total_upload</tt> is the number of bytes downloaded and
|
|
|
|
uploaded to all peers, accumulated.
|
2003-10-23 01:00:57 +02:00
|
|
|
</p>
|
|
|
|
|
2003-11-02 22:06:50 +01:00
|
|
|
<h3>get_download_queue()</h3>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
<tt>get_download_queue()</tt> takes a non-const reference to a vector which it will fill
|
|
|
|
information about pieces that are partially downloaded or not downloaded at all but partially
|
|
|
|
requested. The entry in the vector (<tt>partial_piece_info</tt>) looks like this:
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
struct partial_piece_info
|
|
|
|
{
|
|
|
|
enum { max_blocks_per_piece = <i>implementation-defined</i> };
|
|
|
|
int piece_index;
|
|
|
|
int blocks_in_piece;
|
|
|
|
std::bitset<max_blocks_per_piece> requested_blocks;
|
|
|
|
std::bitset<max_blocks_per_piece> finished_blocks;
|
|
|
|
peer_id peer[max_blocks_per_piece];
|
|
|
|
int num_downloads[max_blocks_per_piece];
|
|
|
|
};
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
<tt>piece_index</tt> is the index of the piece in question. <tt>blocks_in_piece</tt> is the
|
|
|
|
number of blocks in this particular piece. This number will be the same for most pieces, but
|
|
|
|
the last piece may have fewer blocks than the standard pieces.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
<tt>requested_blocks</tt> is a bitset with one bit per block in the piece. If a bit is set, it
|
|
|
|
means that that block has been requested, but not necessarily fully downloaded yet. To know
|
|
|
|
from whom the block has been requested, have a look in the <tt>peer</tt> array. The bit-index
|
|
|
|
in the <tt>requested_blocks</tt> and <tt>finished_blocks</tt> correspons to the array-index into
|
|
|
|
<tt>peers</tt> and <tt>num_downloads</tt>. The array of peers is contains the id of the
|
|
|
|
peer the piece was requested from. If a piece hasn't been requested (the bit in
|
|
|
|
<tt>requested_blocks</tt> is not set) the peer array entry will be undefined.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
The <tt>finished_blocks</tt> is a bitset where each bit says if the block is fully downloaded
|
|
|
|
or not. And the <tt>num_downloads</tt> array says how many times that block has been downloaded.
|
|
|
|
When a piece fails a hash verification, single blocks may be redownloaded to see if the hash teast
|
|
|
|
may pass then.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<h3>get_peer_info()</h3>
|
|
|
|
|
2003-10-23 01:00:57 +02:00
|
|
|
<p>
|
|
|
|
<tt>get_peer_info()</tt> takes a reference to a vector that will be cleared and filled
|
|
|
|
with one entry for each peer connected to this torrent. Each entry contains information about
|
|
|
|
that particular peer. It contains the following information:
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
struct peer_info
|
|
|
|
{
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
interesting = 0x1,
|
|
|
|
choked = 0x2,
|
|
|
|
remote_interested = 0x4,
|
|
|
|
remote_choked = 0x8
|
|
|
|
};
|
|
|
|
unsigned int flags;
|
|
|
|
address ip;
|
|
|
|
float up_speed;
|
|
|
|
float down_speed;
|
2003-10-30 00:28:09 +01:00
|
|
|
unsigned int total_download;
|
|
|
|
unsigned int total_upload;
|
2003-10-23 01:00:57 +02:00
|
|
|
peer_id id;
|
|
|
|
std::vector<bool> pieces;
|
2003-11-09 19:17:09 +01:00
|
|
|
int upload_limit;
|
2003-10-23 01:00:57 +02:00
|
|
|
};
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
The <tt>flags</tt> attribute tells you in which state the peer is. It is set to
|
|
|
|
any combination of the four enums above. Where <tt>interesting</tt> means that we
|
2003-10-31 13:15:32 +01:00
|
|
|
are interested in pieces from this peer. <tt>choked</tt> means that <u>we</u> have
|
2003-10-23 01:00:57 +02:00
|
|
|
choked this peer. <tt>remote_interested</tt> and <tt>remote_choked</tt> means the
|
|
|
|
same thing but that the peer is interested in pieces from us and the peer has choked
|
|
|
|
<u>us</u>.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
The <tt>ip</tt> field is the IP-address to this peer. Its type is a wrapper around the
|
|
|
|
actual address and the port number. See <a href"#address">address</a> class.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
<tt>up_speed</tt> and <tt>down_speed</tt> is the current upload and download speed
|
|
|
|
we have to and from this peer. These figures are updated aproximately once every second.
|
|
|
|
</p>
|
|
|
|
|
2003-10-30 00:28:09 +01:00
|
|
|
<p>
|
|
|
|
<tt>total_download</tt> and <tt>total_upload</tt> are the total number of bytes downloaded
|
|
|
|
from and uploaded to this peer. These numbers do not include the protocol chatter, but only
|
|
|
|
the payload data.
|
|
|
|
</p>
|
|
|
|
|
2003-10-23 01:00:57 +02:00
|
|
|
<p>
|
|
|
|
<tt>id</tt> is the peer's id as used in the bit torrent protocol. This id can be used to
|
|
|
|
extract 'fingerprints' from the peer. Sometimes it can tell you which client the peer
|
|
|
|
is using.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
<tt>pieces</tt> is a vector of booleans that has as many entries as there are pieces
|
|
|
|
in the torrent. Each boolean tells you if the peer has that piece (if it's set to true)
|
|
|
|
or if the peer miss that piece (set to false).
|
|
|
|
</p>
|
|
|
|
|
2003-11-09 19:17:09 +01:00
|
|
|
<p>
|
|
|
|
<tt>upload_limit</tt> is the number of bytes per second we are allowed to send to this
|
|
|
|
peer every second. It may be -1 if there's no limit.
|
|
|
|
</p>
|
|
|
|
|
2003-10-25 03:31:06 +02:00
|
|
|
<p>
|
|
|
|
TODO: address
|
|
|
|
</p>
|
|
|
|
|
2003-10-23 01:00:57 +02:00
|
|
|
<h2>http_settings</h2>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
You have some control over tracker requests through the <tt>http_settings</tt> object. You
|
|
|
|
create it and fill it with your settings and the use <tt>session::set_http_settings()</tt>
|
|
|
|
to apply them. You have control over proxy and authorization settings and also the user-agent
|
|
|
|
that will be sent to the tracker. The user-agent is a good way to identify your client.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
struct http_settings
|
|
|
|
{
|
|
|
|
http_settings();
|
|
|
|
std::string proxy_ip;
|
|
|
|
int proxy_port;
|
|
|
|
std::string proxy_login;
|
|
|
|
std::string proxy_password;
|
|
|
|
std::string user_agent;
|
2003-10-25 03:31:06 +02:00
|
|
|
int tracker_timeout;
|
|
|
|
int tracker_maximum_response_length;
|
2003-10-23 01:00:57 +02:00
|
|
|
};
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<p>
|
2003-10-25 03:31:06 +02:00
|
|
|
<tt>tracker_timeout</tt> is the number of seconds the tracker connection will
|
2003-11-09 19:17:09 +01:00
|
|
|
wait until it considers the tracker to have timed-out. Default value is 10
|
2003-10-25 03:31:06 +02:00
|
|
|
seconds.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
<tt>tracker_maximum_response_length</tt> is the maximum number of bytes in a
|
|
|
|
tracker response. If a response size passes this number it will be rejected
|
|
|
|
and the connection will be closed. On gzipped responses this size is measured
|
|
|
|
on the uncompressed data. So, if you get 20 bytes of gzip response that'll
|
|
|
|
expand to 2 megs, it will be interrupted before the entire response has been
|
|
|
|
uncompressed (given your limit is lower than 2 megs). Default limit is
|
|
|
|
1 megabyte.
|
|
|
|
</p>
|
|
|
|
|
2003-10-23 01:00:57 +02:00
|
|
|
<h2><a name="big_number"></a>big_number</h2>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
Both the <tt>peer_id</tt> and <tt>sha1_hash</tt> types are typedefs of the class
|
|
|
|
<tt>big_number</tt>. It represents 20 bytes of data. Its synopsis follows:
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
class big_number
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
bool operator==(const big_number& n) const;
|
|
|
|
bool operator!=(const big_number& n) const;
|
|
|
|
bool operator<(const big_number& n) const;
|
|
|
|
|
|
|
|
const unsigned char* begin() const;
|
|
|
|
const unsigned char* end() const;
|
|
|
|
|
|
|
|
unsigned char* begin();
|
|
|
|
unsigned char* end();
|
|
|
|
};
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
The iterators gives you access to individual bytes.
|
|
|
|
</p>
|
|
|
|
|
2003-10-30 00:28:09 +01:00
|
|
|
<h2>hasher</h2>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
This class creates sha1-hashes. Its declaration looks like this:
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
class hasher
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
hasher();
|
|
|
|
|
|
|
|
void update(const char* data, unsigned int len);
|
|
|
|
sha1_hash final();
|
|
|
|
void reset();
|
|
|
|
};
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
You use it by first instantiating it, then call <tt>update()</tt> to feed it
|
|
|
|
with data. i.e. you don't have to keep the entire buffer of which you want to
|
|
|
|
create the hash in memory. You can feed the hasher parts of it at a time. When
|
|
|
|
You have fed the hasher with all the data, you call <tt>final()</tt> and it
|
|
|
|
will return the sha1-hash of the data.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
If you want to reuse the hasher object once you have created a hash, you have to
|
|
|
|
call <tt>reset()</tt> to reinitialize it.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
The sha1-algorithm used was implemented by Steve Reid and released as public domain.
|
|
|
|
For more info, see <tt>src/sha1.c</tt>.
|
|
|
|
</p>
|
|
|
|
|
2003-11-02 22:06:50 +01:00
|
|
|
<h1>Feedback</h1>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
There's a <a href="http://lists.sourceforge.net/lists/listinfo/libtorrent-discuss">mailing list</a>.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
You can usually find me as hydri in <tt>#btports @ irc.freenode.net</tt>.
|
|
|
|
</p>
|
|
|
|
|
2003-10-23 01:00:57 +02:00
|
|
|
<h1>Credits</h1>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
Copyright © 2003 Arvid Norberg
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
<a href="http://sourceforge.net/">
|
|
|
|
<img style="border:0; width: 88px; height: 31px"
|
|
|
|
src="http://sourceforge.net/sflogo.php?group_id=79942"
|
|
|
|
alt="SourceForge" /></a>
|
|
|
|
|
|
|
|
<a href="http://validator.w3.org/check/referer">
|
|
|
|
<img style="border:0;width:88px;height:31px"
|
|
|
|
src="http://www.w3.org/Icons/valid-html401"
|
|
|
|
alt="Valid HTML 4.01!"></a>
|
|
|
|
|
|
|
|
<a href="http://jigsaw.w3.org/css-validator/">
|
|
|
|
<img style="border:0;width:88px;height:31px"
|
|
|
|
src="http://jigsaw.w3.org/css-validator/images/vcss"
|
|
|
|
alt="Valid CSS!"></a>
|
|
|
|
|
|
|
|
</p>
|
|
|
|
|
|
|
|
</body></html>
|
|
|
|
|