254 lines
10 KiB
HTML
254 lines
10 KiB
HTML
|
<?xml version="1.0" encoding="utf-8" ?>
|
||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||
|
<head>
|
||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||
|
<meta name="generator" content="Docutils 0.5: http://docutils.sourceforge.net/" />
|
||
|
<title>creating torrents</title>
|
||
|
<meta name="author" content="Arvid Norberg, arvid@rasterbar.com" />
|
||
|
<link rel="stylesheet" type="text/css" href="../../css/base.css" />
|
||
|
<link rel="stylesheet" type="text/css" href="../../css/rst.css" />
|
||
|
<link rel="stylesheet" href="style.css" type="text/css" />
|
||
|
<style type="text/css">
|
||
|
/* Hides from IE-mac \*/
|
||
|
* html pre { height: 1%; }
|
||
|
/* End hide from IE-mac */
|
||
|
</style>
|
||
|
</head>
|
||
|
<body>
|
||
|
<div class="document" id="creating-torrents">
|
||
|
<div id="container">
|
||
|
<div id="headerNav">
|
||
|
<ul>
|
||
|
<li class="first"><a href="/">Home</a></li>
|
||
|
<li><a href="../../products.html">Products</a></li>
|
||
|
<li><a href="../../contact.html">Contact</a></li>
|
||
|
</ul>
|
||
|
</div>
|
||
|
<div id="header">
|
||
|
<h1><span>Rasterbar Software</span></h1>
|
||
|
<h2><span>Software developement and consulting</span></h2>
|
||
|
</div>
|
||
|
<div id="main">
|
||
|
<h1 class="title">creating torrents</h1>
|
||
|
<table class="docinfo" frame="void" rules="none">
|
||
|
<col class="docinfo-name" />
|
||
|
<col class="docinfo-content" />
|
||
|
<tbody valign="top">
|
||
|
<tr><th class="docinfo-name">Author:</th>
|
||
|
<td>Arvid Norberg, <a class="last reference external" href="mailto:arvid@rasterbar.com">arvid@rasterbar.com</a></td></tr>
|
||
|
</tbody>
|
||
|
</table>
|
||
|
<div class="contents topic" id="table-of-contents">
|
||
|
<p class="topic-title first">Table of contents</p>
|
||
|
<ul class="simple">
|
||
|
<li><a class="reference internal" href="#overview" id="id2">overview</a></li>
|
||
|
<li><a class="reference internal" href="#high-level-example" id="id3">high level example</a></li>
|
||
|
<li><a class="reference internal" href="#add-files" id="id4">add_files</a></li>
|
||
|
<li><a class="reference internal" href="#set-piece-hashes" id="id5">set_piece_hashes()</a></li>
|
||
|
<li><a class="reference internal" href="#file-storage" id="id6">file_storage</a></li>
|
||
|
<li><a class="reference internal" href="#create-torrent" id="id7">create_torrent</a><ul>
|
||
|
<li><a class="reference internal" href="#id1" id="id8">create_torrent()</a></li>
|
||
|
<li><a class="reference internal" href="#generate" id="id9">generate()</a></li>
|
||
|
</ul>
|
||
|
</li>
|
||
|
</ul>
|
||
|
</div>
|
||
|
<div class="section" id="overview">
|
||
|
<h1>overview</h1>
|
||
|
<p>This section describes the functions and classes that are used
|
||
|
to create torrent files. It is a layered API with low level classes
|
||
|
and higher level convenience functions. A torrent is created in 4
|
||
|
steps:</p>
|
||
|
<ol class="arabic simple">
|
||
|
<li>first the files that will be part of the torrent are determined.</li>
|
||
|
<li>the torrent properties are set, such as tracker url, web seeds,
|
||
|
DHT nodes etc.</li>
|
||
|
<li>Read through all the files in the torrent, SHA-1 all the data
|
||
|
and set the piece hashes.</li>
|
||
|
<li>The torrent is bencoded into a file or buffer.</li>
|
||
|
</ol>
|
||
|
<p>If there are a lot of files and or deep directoy hierarchies to
|
||
|
traverse, step one can be time consuming.</p>
|
||
|
<p>Typically step 3 is by far the most time consuming step, since it
|
||
|
requires to read all the bytes from all the files in the torrent.</p>
|
||
|
<p>All of these classes and functions are declared by including
|
||
|
<tt class="docutils literal"><span class="pre">libtorrent/create_torrent.hpp</span></tt>.</p>
|
||
|
</div>
|
||
|
<div class="section" id="high-level-example">
|
||
|
<h1>high level example</h1>
|
||
|
<pre class="literal-block">
|
||
|
file_storage fs;
|
||
|
|
||
|
// recursively adds files in directories
|
||
|
add_files(fs, "./my_torrent");
|
||
|
|
||
|
create_torrent t(fs);
|
||
|
t.add_tracker("http://my.tracker.com/announce");
|
||
|
t.set_creator("libtorrent example");
|
||
|
|
||
|
// reads the files and calculates the hashes
|
||
|
set_piece_hashes(t, ".");
|
||
|
|
||
|
ofstream out("my_torrent.torrent", std::ios_base::binary);
|
||
|
bencode(std::ostream_iterator<char>(out), t.generate());
|
||
|
</pre>
|
||
|
</div>
|
||
|
<div class="section" id="add-files">
|
||
|
<h1>add_files</h1>
|
||
|
<blockquote>
|
||
|
<pre class="literal-block">
|
||
|
template <class Pred>
|
||
|
void add_files(file_storage& fs, boost::filesystem::path const& path, Pred p);
|
||
|
|
||
|
void add_files(file_storage& fs, boost::filesystem::path const& path);
|
||
|
</pre>
|
||
|
</blockquote>
|
||
|
<p>Adds the file specified by <tt class="docutils literal"><span class="pre">path</span></tt> to the <tt class="docutils literal"><span class="pre">file_storage</span></tt> object. In case <tt class="docutils literal"><span class="pre">path</span></tt>
|
||
|
refers to a diretory, files will be added recursively from the directory.</p>
|
||
|
<p>If specified, the predicate <tt class="docutils literal"><span class="pre">p</span></tt> is called once for every file and directory that
|
||
|
is encountered. files for which <tt class="docutils literal"><span class="pre">p</span></tt> returns true are added, and directories for
|
||
|
which <tt class="docutils literal"><span class="pre">p</span></tt> returns true are traversed. <tt class="docutils literal"><span class="pre">p</span></tt> must have the following signature:</p>
|
||
|
<pre class="literal-block">
|
||
|
bool Pred(boost::filesystem::path const& p);
|
||
|
</pre>
|
||
|
<p>The path that is passed in to the predicate is the full path of the file or
|
||
|
directory. If no predicate is specified, all files are added, and all directories
|
||
|
are traveresed.</p>
|
||
|
<p>The ".." directory is never traversed.</p>
|
||
|
</div>
|
||
|
<div class="section" id="set-piece-hashes">
|
||
|
<h1>set_piece_hashes()</h1>
|
||
|
<blockquote>
|
||
|
<pre class="literal-block">
|
||
|
template <class Fun>
|
||
|
void set_piece_hashes(create_torrent& t, boost::filesystem::path const& p, Fun f);
|
||
|
|
||
|
void set_piece_hashes(create_torrent& t, boost::filesystem::path const& p);
|
||
|
</pre>
|
||
|
</blockquote>
|
||
|
<p>This function will assume that the files added to the torrent file exists at path
|
||
|
<tt class="docutils literal"><span class="pre">p</span></tt>, read those files and hash the content and set the hashes in the <tt class="docutils literal"><span class="pre">create_torrent</span></tt>
|
||
|
object. The optional function <tt class="docutils literal"><span class="pre">f</span></tt> is called in between every hash that is set. <tt class="docutils literal"><span class="pre">f</span></tt>
|
||
|
must have the following signature:</p>
|
||
|
<pre class="literal-block">
|
||
|
void Fun(int);
|
||
|
</pre>
|
||
|
</div>
|
||
|
<div class="section" id="file-storage">
|
||
|
<h1>file_storage</h1>
|
||
|
<p>The <tt class="docutils literal"><span class="pre">file_storage</span></tt> class represents a file list and the piece
|
||
|
size. Everything necessary to interpret a regular bittorrent storage
|
||
|
file structure. Its synopsis:</p>
|
||
|
<pre class="literal-block">
|
||
|
class file_storage
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
bool is_valid() const;
|
||
|
|
||
|
void add_file(file_entry const& e);
|
||
|
void add_file(fs::path const& p, size_type size);
|
||
|
void rename_file(int index, std::string const& new_filename);
|
||
|
|
||
|
std::vector<file_slice> map_block(int piece, size_type offset
|
||
|
, int size) const;
|
||
|
peer_request map_file(int file, size_type offset, int size) const;
|
||
|
|
||
|
typedef std::vector<file_entry>::const_iterator iterator;
|
||
|
typedef std::vector<file_entry>::const_reverse_iterator reverse_iterator;
|
||
|
|
||
|
iterator begin() const;
|
||
|
iterator end() const;
|
||
|
reverse_iterator rbegin();
|
||
|
reverse_iterator rend() const;
|
||
|
int num_files() const;
|
||
|
|
||
|
file_entry const& at(int index) const;
|
||
|
|
||
|
size_type total_size() const;
|
||
|
void set_num_pieces(int n);
|
||
|
int num_pieces() const;
|
||
|
void set_piece_length(int l);
|
||
|
int piece_length() const;
|
||
|
int piece_size(int index) const;
|
||
|
|
||
|
void set_name(std::string const& n);
|
||
|
const std::string& name() const;
|
||
|
|
||
|
void swap(file_storage& ti);
|
||
|
}
|
||
|
</pre>
|
||
|
</div>
|
||
|
<div class="section" id="create-torrent">
|
||
|
<h1>create_torrent</h1>
|
||
|
<p>The <tt class="docutils literal"><span class="pre">create_torrent</span></tt> class has the following synopsis:</p>
|
||
|
<pre class="literal-block">
|
||
|
struct create_torrent
|
||
|
{
|
||
|
create_torrent(file_storage& fs, int piece_size);
|
||
|
create_torrent(file_storage& fs);
|
||
|
create_torrent(torrent_info const& ti);
|
||
|
|
||
|
entry generate() const;
|
||
|
|
||
|
file_storage const& files() const;
|
||
|
|
||
|
void set_comment(char const* str);
|
||
|
void set_creator(char const* str);
|
||
|
void set_hash(int index, sha1_hash const& h);
|
||
|
void add_url_seed(std::string const& url);
|
||
|
void add_node(std::pair<std::string, int> const& node);
|
||
|
void add_tracker(std::string const& url, int tier = 0);
|
||
|
|
||
|
int num_pieces() const;
|
||
|
int piece_length() const;
|
||
|
int piece_size(int i) const;
|
||
|
};
|
||
|
</pre>
|
||
|
<div class="section" id="id1">
|
||
|
<h2>create_torrent()</h2>
|
||
|
<blockquote>
|
||
|
<pre class="literal-block">
|
||
|
create_torrent(file_storage& fs, int piece_size);
|
||
|
create_torrent(file_storage& fs);
|
||
|
create_torrent(torrent_info const& ti);
|
||
|
</pre>
|
||
|
</blockquote>
|
||
|
<p>The contrstructor that does not take a piece_size will calculate
|
||
|
a piece size such that the torrent file is roughly 40 kB.</p>
|
||
|
<p>The overlad that takes a <tt class="docutils literal"><span class="pre">torrent_info</span></tt> object will make a verbatim
|
||
|
copy of its info dictionary (to preserve the info-hash). The copy of
|
||
|
the info dictionary will be used by <tt class="docutils literal"><span class="pre">generate()</span></tt>. This means
|
||
|
that none of the member functions of create_torrent that affects
|
||
|
the content of the info dictionary (such as <tt class="docutils literal"><span class="pre">set_hash()</span></tt>), will not
|
||
|
have any affect.</p>
|
||
|
</div>
|
||
|
<div class="section" id="generate">
|
||
|
<h2>generate()</h2>
|
||
|
<blockquote>
|
||
|
<pre class="literal-block">
|
||
|
entry generate() const;
|
||
|
</pre>
|
||
|
</blockquote>
|
||
|
<p>This function will generate the .torrent file as a bencode tree. In order to
|
||
|
generate the flat file, use the bencode() function.</p>
|
||
|
<p>It may be useful to add custom entries to the torrent file before bencoding it
|
||
|
and saving it to disk.</p>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div id="footer">
|
||
|
<span>Copyright © 2005 Rasterbar Software.</span>
|
||
|
</div>
|
||
|
</div>
|
||
|
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
|
||
|
</script>
|
||
|
<script type="text/javascript">
|
||
|
_uacct = "UA-1599045-1";
|
||
|
urchinTracker();
|
||
|
</script>
|
||
|
</div>
|
||
|
</body>
|
||
|
</html>
|