1 <?xml version=
"1.0" encoding=
"utf-8" ?>
2 <!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3 <html xmlns=
"http://www.w3.org/1999/xhtml" xml:
lang=
"en" lang=
"en">
5 <meta http-equiv=
"Content-Type" content=
"text/html; charset=utf-8" />
6 <meta name=
"generator" content=
"Docutils 0.4: http://docutils.sourceforge.net/" />
8 <meta name=
"author" content=
"Arvid Norberg, arvid@rasterbar.com" />
9 <link rel=
"stylesheet" href=
"style.css" type=
"text/css" />
12 <div class=
"document">
13 <table class=
"docinfo" frame=
"void" rules=
"none">
14 <col class=
"docinfo-name" />
15 <col class=
"docinfo-content" />
17 <tr><th class=
"docinfo-name">Author:
</th>
18 <td>Arvid Norberg,
<a class=
"last reference" href=
"mailto:arvid@rasterbar.com">arvid
@rasterbar.com
</a></td></tr>
22 <h1><a id=
"libtorrent-plugins" name=
"libtorrent-plugins">libtorrent plugins
</a></h1>
23 <div class=
"contents topic" id=
"table-of-contents">
24 <p class=
"topic-title first"><a id=
"contents" name=
"contents">Contents
</a></p>
26 <li><a class=
"reference" href=
"#libtorrent-plugins" id=
"id1" name=
"id1">libtorrent plugins
</a><ul>
27 <li><a class=
"reference" href=
"#a-word-of-caution" id=
"id2" name=
"id2">a word of caution
</a></li>
30 <li><a class=
"reference" href=
"#plugin-interface" id=
"id3" name=
"id3">plugin interface
</a></li>
31 <li><a class=
"reference" href=
"#torrent-plugin" id=
"id4" name=
"id4">torrent_plugin
</a><ul>
32 <li><a class=
"reference" href=
"#new-connection" id=
"id5" name=
"id5">new_connection()
</a></li>
33 <li><a class=
"reference" href=
"#on-piece-pass-on-piece-fail" id=
"id6" name=
"id6">on_piece_pass() on_piece_fail()
</a></li>
34 <li><a class=
"reference" href=
"#tick" id=
"id7" name=
"id7">tick()
</a></li>
35 <li><a class=
"reference" href=
"#on-pause-on-resume" id=
"id8" name=
"id8">on_pause() on_resume()
</a></li>
36 <li><a class=
"reference" href=
"#on-files-checked" id=
"id9" name=
"id9">on_files_checked()
</a></li>
39 <li><a class=
"reference" href=
"#peer-plugin" id=
"id10" name=
"id10">peer_plugin
</a></li>
40 <li><a class=
"reference" href=
"#disk-buffer-holder" id=
"id11" name=
"id11">disk_buffer_holder
</a></li>
43 <p>libtorrent has a plugin interface for implementing extensions to the protocol.
44 These can be general extensions for transferring metadata or peer exchange
45 extensions, or it could be used to provide a way to customize the protocol
46 to fit a particular (closed) network.
</p>
47 <p>In short, the plugin interface makes it possible to:
</p>
49 <li>register extension messages (sent in the extension handshake), see
50 <a class=
"reference" href=
"extension_protocol.html">extensions
</a>.
</li>
51 <li>add data and parse data from the extension handshake.
</li>
52 <li>send extension messages and standard bittorrent messages.
</li>
53 <li>override or block the handling of standard bittorrent messages.
</li>
56 <h2><a id=
"a-word-of-caution" name=
"a-word-of-caution">a word of caution
</a></h2>
57 <p>Writing your own plugin is a very easy way to introduce serious bugs such as
58 dead locks and race conditions. Since a plugin has access to internal
59 structures it is also quite easy to sabotage libtorrent's operation.
</p>
60 <p>All the callbacks in this interface are called with the main libtorrent thread
61 mutex locked. And they are always called from the libtorrent main thread. In
62 case portions of your plugin are called from other threads, typically the main
63 thread, you cannot use any of the member functions on the internal structures
64 in libtorrent, since those require the mutex to be locked. Futhermore, you would
65 also need to have a mutex on your own shared data within the plugin, to make
66 sure it is not accessed at the same time from the libtorrent thread (through a
67 callback). See
<a class=
"reference" href=
"http://www.boost.org/doc/html/mutex.html">boost thread's mutex
</a>. If you need to send out a message from
68 another thread, use an internal queue, and do the actual sending in
<tt class=
"docutils literal"><span class=
"pre">tick()
</span></tt>.
</p>
72 <h1><a id=
"plugin-interface" name=
"plugin-interface">plugin interface
</a></h1>
73 <p>The plugin interface consists of two base classes that the plugin may
74 implement. These are called
<tt class=
"docutils literal"><span class=
"pre">torrent_plugin
</span></tt> and
<tt class=
"docutils literal"><span class=
"pre">peer_plugin
</span></tt>. They are
75 both found in the
<tt class=
"docutils literal"><span class=
"pre"><libtorrent/extensions.hpp
></span></tt> header.
</p>
76 <p>These plugins are instantiated for each torrent and possibly each peer,
78 <p>This is done by passing in a function or function object to
79 <tt class=
"docutils literal"><span class=
"pre">session::add_extension()
</span></tt> or
<tt class=
"docutils literal"><span class=
"pre">torrent_handle::add_extension()
</span></tt> (if the
80 torrent has already been started and you want to hook in the extension at
82 <p>The signature of the function is:
</p>
83 <pre class=
"literal-block">
84 boost::shared_ptr
<torrent_plugin
> (*)(torrent*, void*);
86 <p>The first argument is the internal torrent object, the second argument
87 is the userdata passed to
<tt class=
"docutils literal"><span class=
"pre">session::add_torrent()
</span></tt> or
88 <tt class=
"docutils literal"><span class=
"pre">torrent_handle::add_extension()
</span></tt>.
</p>
89 <p>The function should return a
<tt class=
"docutils literal"><span class=
"pre">boost::shared_ptr
<torrent_plugin
></span></tt> which
90 may or may not be
0. If it is a null pointer, the extension is simply ignored
91 for this torrent. If it is a valid pointer (to a class inheriting
92 <tt class=
"docutils literal"><span class=
"pre">torrent_plugin
</span></tt>), it will be associated with this torrent and callbacks
93 will be made on torrent events.
</p>
96 <h1><a id=
"torrent-plugin" name=
"torrent-plugin">torrent_plugin
</a></h1>
97 <p>The synopsis for
<tt class=
"docutils literal"><span class=
"pre">torrent_plugin
</span></tt> follows:
</p>
98 <pre class=
"literal-block">
101 virtual ~torrent_plugin();
102 virtual boost::shared_ptr
<peer_plugin
> new_connection(peer_connection*);
104 virtual void on_piece_pass(int index);
105 virtual void on_piece_failed(int index);
109 virtual bool on_pause();
110 virtual bool on_resume();
112 virtual void on_files_checked();
115 <p>This is the base class for a torrent_plugin. Your derived class is (if added
116 as an extension) instantiated for each torrent in the session. The callback
117 hook functions are defined as follows.
</p>
118 <div class=
"section">
119 <h2><a id=
"new-connection" name=
"new-connection">new_connection()
</a></h2>
120 <pre class=
"literal-block">
121 boost::shared_ptr
<peer_plugin
> new_connection(peer_connection*);
123 <p>This function is called each time a new peer is connected to the torrent. You
124 may choose to ignore this by just returning a default constructed
125 <tt class=
"docutils literal"><span class=
"pre">shared_ptr
</span></tt> (in which case you don't need to override this member
127 <p>If you need an extension to the peer connection (which most plugins do) you
128 are supposed to return an instance of your
<tt class=
"docutils literal"><span class=
"pre">peer_plugin
</span></tt> class. Which in
129 turn will have its hook functions called on event specific to that peer.
</p>
130 <p>The
<tt class=
"docutils literal"><span class=
"pre">peer_connection
</span></tt> will be valid as long as the
<tt class=
"docutils literal"><span class=
"pre">shared_ptr
</span></tt> is being
131 held by the torrent object. So, it is generally a good idea to not keep a
132 <tt class=
"docutils literal"><span class=
"pre">shared_ptr
</span></tt> to your own peer_plugin. If you want to keep references to it,
133 use
<tt class=
"docutils literal"><span class=
"pre">weak_ptr
</span></tt>.
</p>
134 <p>If this function throws an exception, the connection will be closed.
</p>
136 <div class=
"section">
137 <h2><a id=
"on-piece-pass-on-piece-fail" name=
"on-piece-pass-on-piece-fail">on_piece_pass() on_piece_fail()
</a></h2>
138 <pre class=
"literal-block">
139 void on_piece_pass(int index);
140 void on_piece_failed(int index);
142 <p>These hooks are called when a piece passes the hash check or fails the hash
143 check, respectively. The
<tt class=
"docutils literal"><span class=
"pre">index
</span></tt> is the piece index that was downloaded.
144 It is possible to access the list of peers that participated in sending the
145 piece through the
<tt class=
"docutils literal"><span class=
"pre">torrent
</span></tt> and the
<tt class=
"docutils literal"><span class=
"pre">piece_picker
</span></tt>.
</p>
147 <div class=
"section">
148 <h2><a id=
"tick" name=
"tick">tick()
</a></h2>
149 <pre class=
"literal-block">
152 <p>This hook is called approximately once per second. It is a way of making it
153 easy for plugins to do timed events, for sending messages or whatever.
</p>
155 <div class=
"section">
156 <h2><a id=
"on-pause-on-resume" name=
"on-pause-on-resume">on_pause() on_resume()
</a></h2>
157 <pre class=
"literal-block">
161 <p>These hooks are called when the torrent is paused and unpaused respectively.
162 The return value indicates if the event was handled. A return value of
163 <tt class=
"docutils literal"><span class=
"pre">true
</span></tt> indicates that it was handled, and no other plugin after this one
164 will have this hook function called, and the standard handler will also not be
165 invoked. So, returning true effectively overrides the standard behavior of
166 pause or unpause.
</p>
167 <p>Note that if you call
<tt class=
"docutils literal"><span class=
"pre">pause()
</span></tt> or
<tt class=
"docutils literal"><span class=
"pre">resume()
</span></tt> on the torrent from your
168 handler it will recurse back into your handler, so in order to invoke the
169 standard handler, you have to keep your own state on whether you want standard
170 behavior or overridden behavior.
</p>
172 <div class=
"section">
173 <h2><a id=
"on-files-checked" name=
"on-files-checked">on_files_checked()
</a></h2>
174 <pre class=
"literal-block">
175 void on_files_checked();
177 <p>This function is called when the initial files of the torrent have been
178 checked. If there are no files to check, this function is called immediately.
</p>
179 <p>i.e. This function is always called when the torrent is in a state where it
180 can start downloading.
</p>
183 <div class=
"section">
184 <h1><a id=
"peer-plugin" name=
"peer-plugin">peer_plugin
</a></h1>
185 <pre class=
"literal-block">
188 virtual ~peer_plugin();
190 virtual void add_handshake(entry
&);
191 virtual bool on_handshake(char const* reserved_bits);
192 virtual bool on_extension_handshake(lazy_entry const
& h);
194 virtual bool on_choke();
195 virtual bool on_unchoke();
196 virtual bool on_interested();
197 virtual bool on_not_interested();
198 virtual bool on_have(int index);
199 virtual bool on_bitfield(bitfield const
& bits);
200 virtual bool on_have_all();
201 virtual bool on_have_none();
202 virtual bool on_allowed_fast(int index);
203 virtual bool on_request(peer_request const
& req);
204 virtual bool on_piece(peer_request const
& piece, disk_buffer_holder
& buffer);
205 virtual bool on_cancel(peer_request const
& req);
206 virtual bool on_reject(peer_request const
& req);
207 virtual bool on_suggest(int index);
208 virtual bool on_extended(int length
209 , int msg, buffer::const_interval body);
210 virtual bool on_unknown_message(int length, int msg
211 , buffer::const_interval body);
212 virtual void on_piece_pass(int index);
213 virtual void on_piece_failed(int index);
217 virtual bool write_request(peer_request const
& r);
221 <div class=
"section">
222 <h1><a id=
"disk-buffer-holder" name=
"disk-buffer-holder">disk_buffer_holder
</a></h1>
223 <pre class=
"literal-block">
224 struct disk_buffer_holder
226 disk_buffer_holder(aux::session_impl
& s, char* b);
227 ~disk_buffer_holder();
232 <p>The disk buffer holder acts like a
<tt class=
"docutils literal"><span class=
"pre">scoped_ptr
</span></tt> that frees a disk buffer
233 when it's destructed, unless it's released.
<tt class=
"docutils literal"><span class=
"pre">release
</span></tt> returns the disk
234 buffer and transferres ownership and responsibility to free it to the caller.
</p>
235 <p>A disk buffer is freed by passing it to
<tt class=
"docutils literal"><span class=
"pre">session_impl::free_disk_buffer()
</span></tt>.
</p>
236 <p><tt class=
"docutils literal"><span class=
"pre">buffer()
</span></tt> returns the pointer without transferring responsibility. If
237 this buffer has been released,
<tt class=
"docutils literal"><span class=
"pre">buffer()
</span></tt> will return
0.
</p>