2008-11-19 19:32:36 +01:00
<?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);
2008-12-02 09:41:02 +01:00
template < class Pred>
void add_files(file_storage& fs, boost::filesystem::wpath const& path, Pred p);
2008-11-19 19:32:36 +01:00
void add_files(file_storage& fs, boost::filesystem::path const& path);
2008-12-02 09:41:02 +01:00
void add_files(file_storage& fs, boost::filesystem::wpath const& path);
2008-11-19 19:32:36 +01:00
< / 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 >
2008-12-02 09:41:02 +01:00
< p > and for the wpath version:< / p >
< pre class = "literal-block" >
bool Pred(boost::filesystem::wpath const& p);
< / pre >
2008-11-19 19:32:36 +01:00
< 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);
2008-12-02 09:41:02 +01:00
template < class Fun>
void set_piece_hashes(create_torrent& t, boost::filesystem::wpath const& p, Fun f);
2008-11-19 19:32:36 +01:00
void set_piece_hashes(create_torrent& t, boost::filesystem::path const& p);
2008-12-02 09:41:02 +01:00
void set_piece_hashes(create_torrent& t, boost::filesystem::wpath const& p);
2008-11-19 19:32:36 +01:00
< / 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);
2008-12-02 09:41:02 +01:00
void add_file(fs::wpath const& p, size_type size);
2008-11-19 19:32:36 +01:00
void rename_file(int index, std::string const& new_filename);
2008-12-02 09:41:02 +01:00
void rename_file(int index, std::wstring const& new_filename);
2008-11-19 19:32:36 +01:00
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);
2008-12-02 09:41:02 +01:00
void set_name(std::wstring const& n);
2008-11-19 19:32:36 +01:00
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 >