diff --git a/docs/extension_protocol.html b/docs/extension_protocol.html index ba601d423..5b6161ad1 100644 --- a/docs/extension_protocol.html +++ b/docs/extension_protocol.html @@ -98,17 +98,21 @@ This is the defined item in the dictionary:

m -Dictionary of supported extension messages which maps -names of extensions to identification numbers of each -extension. The only requirement on the identification -numbers is that no extensions share the same. Setting +

Dictionary of supported extension messages which maps +names of extensions to an extended message ID for each +extension message. The only requirement on these IDs +is that no extension message share the same one. Setting an extension number to zero means that the extension is not supported/disabled. The client should ignore any -extension names it doesn't recognize. +extension names it doesn't recognize.

+

The extension message IDs are the IDs used to send the +extension messages to the peer sending this handshake. +i.e. The IDs are local to this particular peer.

+ -

Here are two other items that an implementation may choose to support:

+

Here are some other items that an implementation may choose to support:

@@ -167,7 +171,7 @@ imaginable.

- + @@ -214,8 +218,12 @@ extensions.

rationale

The reason why the extension messages' IDs would be defined in the handshake -is to avoid having a global registry somewhere, where ID's are assigned -global identifiers. Now the extensions have unique names.

+is to avoid having a global registry of message IDs. Instead the names of the +extension messages requires unique names, which is much easier to do without +a global registry. The convention is to use a two letter prefix on the +extension message names, the prefix would identify the client first +implementing the extension message. e.g. LT_metadata is implemented by +libtorrent, and hence it has the LT prefix.

If the client supporting the extensions can decide which numbers the messages it receives will have, it means they are constants within that client. i.e. they can be used in switch statements. It's easy for the other end to diff --git a/docs/extension_protocol.rst b/docs/extension_protocol.rst index c82541ca2..3a081f68b 100644 --- a/docs/extension_protocol.rst +++ b/docs/extension_protocol.rst @@ -59,16 +59,20 @@ This is the defined item in the dictionary: | name | description | +=======+===========================================================+ | m | Dictionary of supported extension messages which maps | -| | names of extensions to identification numbers of each | -| | extension. The only requirement on the identification | -| | numbers is that no extensions share the same. Setting | +| | names of extensions to an extended message ID for each | +| | extension message. The only requirement on these IDs | +| | is that no extension message share the same one. Setting | | | an extension number to zero means that the extension is | | | not supported/disabled. The client should ignore any | | | extension names it doesn't recognize. | +| | | +| | The extension message IDs are the IDs used to send the | +| | extension messages to the peer sending this handshake. | +| | i.e. The IDs are local to this particular peer. | +-------+-----------------------------------------------------------+ -Here are two other items that an implementation may choose to support: +Here are some other items that an implementation may choose to support: +-------+-----------------------------------------------------------+ | name | description | @@ -102,7 +106,7 @@ An example of what the payload of a handshake message could look like: | | +======================+===+ | | | | ``LT_metadata`` | 1 | | | | +----------------------+---+ | -| | | ``µT_PEX`` | 2 | | +| | | ``ut_pex`` | 2 | | | | +----------------------+---+ | | | | +-------------------+----------------------------------+ @@ -150,8 +154,12 @@ rationale --------- The reason why the extension messages' IDs would be defined in the handshake -is to avoid having a global registry somewhere, where ID's are assigned -global identifiers. Now the extensions have unique names. +is to avoid having a global registry of message IDs. Instead the names of the +extension messages requires unique names, which is much easier to do without +a global registry. The convention is to use a two letter prefix on the +extension message names, the prefix would identify the client first +implementing the extension message. e.g. ``LT_metadata`` is implemented by +libtorrent, and hence it has the ``LT`` prefix. If the client supporting the extensions can decide which numbers the messages it receives will have, it means they are constants within that client. i.e. @@ -177,3 +185,4 @@ identifiers is 1) The mainline DHT uses single byte identifiers. 2) Saves bandwidth. The only advantage of longer messages is that it makes the protocol more readable for a human, but the BT protocol wasn't designed to be a human readable protocol, so why bother. + diff --git a/docs/index.html b/docs/index.html index 861bd268f..0ece73625 100755 --- a/docs/index.html +++ b/docs/index.html @@ -25,6 +25,7 @@

Extensions

LT_metadata 1
µT_PEX
ut_pex 2
+++ + + + +
Author:Arvid Norberg, arvid@rasterbar.com
+
+

libtorrent plugins

+
+

Contents

+ +
+

libtorrent has a plugin interface for implementing extensions to the protocol. +These can be general extensions for transferring metadata or peer exchange +extensions, or it could be used to provide a way to customize the protocol +to fit a particular (closed) network.

+

In short, the plugin interface makes it possible to:

+ +
+

a word of caution

+

Writing your own plugin is a very easy way to introduce serious bugs such as +dead locks and race conditions. Since a plugin has access to internal +structures it is also quite easy to sabotage libtorrent's operation.

+

All the callbacks in this interface are called with the main libtorrent thread +mutex locked. And they are always called from the libtorrent main thread. In +case portions of your plugin are called from other threads, typically the main +thread, you cannot use any of the member functions on the internal structures +in libtorrent, since those require the mutex to be locked. Futhermore, you would +also need to have a mutex on your own shared data within the plugin, to make +sure it is not accessed at the same time from the libtorrent thread (through a +callback). See boost thread's mutex. If you need to send out a message from +another thread, use an internal queue, and do the actual sending in tick().

+
+
+
+

plugin interface

+

The plugin interface consists of two base classes that the plugin may +implement. These are called torrent_plugin and peer_plugin. They are +both found in the <libtorrent/extensions.hpp> header.

+

These plugins are instantiated for each torrent and possibly each peer, +respectively.

+
+
+

torrent_plugin

+

The synopsis for torrent_plugin follows:

+
+struct torrent_plugin
+{
+        virtual ~torrent_plugin();
+        virtual boost::shared_ptr<peer_plugin> new_connection(peer_connection*);
+
+        virtual void on_piece_pass(int index);
+        virtual void on_piece_failed(int index);
+
+        virtual void tick();
+
+        virtual bool on_pause();
+        virtual bool on_resume();
+};
+
+

This is the base class for a torrent_plugin. Your derived class is (if added +as an extension) instantiated for each torrent in the session. The callback +hook functions are defined as follows.

+
+

new_connection()

+
+boost::shared_ptr<peer_plugin> new_connection(peer_connection*);
+
+

This function is called each time a new peer is connected to the torrent. You +may choose to ignore this by just returning a default constructed +shared_ptr (in which case you don't need to override this member +function).

+

If you need an extension to the peer connection (which most plugins do) you +are supposed to return an instance of your peer_plugin class. Which in +turn will have its hook functions called on event specific to that peer.

+

The peer_connection will be valid as long as the shared_ptr is being +held by the torrent object. So, it is generally a good idea to not keep a +shared_ptr to your own peer_plugin. If you want to keep references to it, +use weak_ptr.

+

If this function throws an exception, the connection will be closed.

+
+
+

on_piece_pass() on_piece_fail()

+
+void on_piece_pass(int index);
+void on_piece_failed(int index);
+
+

These hooks are called when a piece passes the hash check or fails the hash +check, respectively. The index is the piece index that was downloaded. +It is possible to access the list of peers that participated in sending the +piece through the torrent and the piece_picker.

+
+
+

tick()

+
+void tick();
+
+

This hook is called approximately once per second. It is a way of making it +easy for plugins to do timed events, for sending messages or whatever.

+
+
+

on_pause() on_resume()

+
+bool on_pause();
+bool on_resume();
+
+

These hooks are called when the torrent is paused and unpaused respectively. +The return value indicates if the event was handled. A return value of +true indicates that it was handled, and no other plugin after this one +will have this hook function called, and the standard handler will also not be +invoked. So, returning true effectively overrides the standard behavior of +pause or unpause.

+

Note that if you call pause() or resume() on the torrent from your +handler it will recurse back into your handler, so in order to invoke the +standard handler, you have to keep your own state on whether you want standard +behavior or overridden behavior.

+
+
+
+

peer_plugin

+
+struct peer_plugin
+{
+        virtual ~peer_plugin();
+
+        virtual void add_handshake(entry&);
+        virtual bool on_handshake();
+        virtual bool on_extension_handshake(entry const& h);
+
+        virtual bool on_choke();
+        virtual bool on_unchoke();
+        virtual bool on_interested();
+        virtual bool on_not_interested();
+        virtual bool on_have(int index);
+        virtual bool on_bitfield(std::vector<bool> const& bitfield);
+        virtual bool on_request(peer_request const& req);
+        virtual bool on_piece(peer_request const& piece, char const* data);
+        virtual bool on_cancel(peer_request const& req);
+        virtual bool on_extended(int length
+                , int msg, buffer::const_interval body);
+        virtual bool on_unknown_message(int length, int msg
+                , buffer::const_interval body);
+        virtual void on_piece_pass(int index);
+        virtual void on_piece_failed(int index);
+
+        virtual void tick();
+
+        virtual bool write_request(peer_request const& r);
+};
+
+
+ + + diff --git a/docs/libtorrent_plugins.rst b/docs/libtorrent_plugins.rst new file mode 100644 index 000000000..d6dc8360d --- /dev/null +++ b/docs/libtorrent_plugins.rst @@ -0,0 +1,179 @@ +:Author: Arvid Norberg, arvid@rasterbar.com + +libtorrent plugins +================== + +.. contents:: + +libtorrent has a plugin interface for implementing extensions to the protocol. +These can be general extensions for transferring metadata or peer exchange +extensions, or it could be used to provide a way to customize the protocol +to fit a particular (closed) network. + +In short, the plugin interface makes it possible to: + +* register extension messages (sent in the extension handshake), see + extensions_. +* add data and parse data from the extension handshake. +* send extension messages and standard bittorrent messages. +* override or block the handling of standard bittorrent messages. + +.. _extensions: extension_protocol.html + +a word of caution +----------------- + +Writing your own plugin is a very easy way to introduce serious bugs such as +dead locks and race conditions. Since a plugin has access to internal +structures it is also quite easy to sabotage libtorrent's operation. + +All the callbacks in this interface are called with the main libtorrent thread +mutex locked. And they are always called from the libtorrent main thread. In +case portions of your plugin are called from other threads, typically the main +thread, you cannot use any of the member functions on the internal structures +in libtorrent, since those require the mutex to be locked. Futhermore, you would +also need to have a mutex on your own shared data within the plugin, to make +sure it is not accessed at the same time from the libtorrent thread (through a +callback). See `boost thread's mutex`_. If you need to send out a message from +another thread, use an internal queue, and do the actual sending in ``tick()``. + +.. _`boost thread's mutex`: http://www.boost.org/doc/html/mutex.html + + +plugin interface +================ + +The plugin interface consists of two base classes that the plugin may +implement. These are called ``torrent_plugin`` and ``peer_plugin``. They are +both found in the ```` header. + +These plugins are instantiated for each torrent and possibly each peer, +respectively. + + +torrent_plugin +============== + +The synopsis for ``torrent_plugin`` follows:: + + struct torrent_plugin + { + virtual ~torrent_plugin(); + virtual boost::shared_ptr new_connection(peer_connection*); + + virtual void on_piece_pass(int index); + virtual void on_piece_failed(int index); + + virtual void tick(); + + virtual bool on_pause(); + virtual bool on_resume(); + }; + +This is the base class for a torrent_plugin. Your derived class is (if added +as an extension) instantiated for each torrent in the session. The callback +hook functions are defined as follows. + + +new_connection() +---------------- + +:: + + boost::shared_ptr new_connection(peer_connection*); + +This function is called each time a new peer is connected to the torrent. You +may choose to ignore this by just returning a default constructed +``shared_ptr`` (in which case you don't need to override this member +function). + +If you need an extension to the peer connection (which most plugins do) you +are supposed to return an instance of your ``peer_plugin`` class. Which in +turn will have its hook functions called on event specific to that peer. + +The ``peer_connection`` will be valid as long as the ``shared_ptr`` is being +held by the torrent object. So, it is generally a good idea to not keep a +``shared_ptr`` to your own peer_plugin. If you want to keep references to it, +use ``weak_ptr``. + +If this function throws an exception, the connection will be closed. + +on_piece_pass() on_piece_fail() +------------------------------- + +:: + + void on_piece_pass(int index); + void on_piece_failed(int index); + +These hooks are called when a piece passes the hash check or fails the hash +check, respectively. The ``index`` is the piece index that was downloaded. +It is possible to access the list of peers that participated in sending the +piece through the ``torrent`` and the ``piece_picker``. + +tick() +------ + +:: + + void tick(); + +This hook is called approximately once per second. It is a way of making it +easy for plugins to do timed events, for sending messages or whatever. + + +on_pause() on_resume() +---------------------- + +:: + + bool on_pause(); + bool on_resume(); + +These hooks are called when the torrent is paused and unpaused respectively. +The return value indicates if the event was handled. A return value of +``true`` indicates that it was handled, and no other plugin after this one +will have this hook function called, and the standard handler will also not be +invoked. So, returning true effectively overrides the standard behavior of +pause or unpause. + +Note that if you call ``pause()`` or ``resume()`` on the torrent from your +handler it will recurse back into your handler, so in order to invoke the +standard handler, you have to keep your own state on whether you want standard +behavior or overridden behavior. + + +peer_plugin +=========== + +:: + + struct peer_plugin + { + virtual ~peer_plugin(); + + virtual void add_handshake(entry&); + virtual bool on_handshake(); + virtual bool on_extension_handshake(entry const& h); + + virtual bool on_choke(); + virtual bool on_unchoke(); + virtual bool on_interested(); + virtual bool on_not_interested(); + virtual bool on_have(int index); + virtual bool on_bitfield(std::vector const& bitfield); + virtual bool on_request(peer_request const& req); + virtual bool on_piece(peer_request const& piece, char const* data); + virtual bool on_cancel(peer_request const& req); + virtual bool on_extended(int length + , int msg, buffer::const_interval body); + virtual bool on_unknown_message(int length, int msg + , buffer::const_interval body); + virtual void on_piece_pass(int index); + virtual void on_piece_failed(int index); + + virtual void tick(); + + virtual bool write_request(peer_request const& r); + }; + diff --git a/docs/manual.html b/docs/manual.html index a138a36bf..cf33306da 100755 --- a/docs/manual.html +++ b/docs/manual.html @@ -18,7 +18,7 @@ Author: Arvid Norberg, arvid@rasterbar.com Version: -0.11 +0.12
diff --git a/docs/manual.rst b/docs/manual.rst index dfc2a98de..79427bb30 100755 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -3,7 +3,7 @@ libtorrent API Documentation ============================ :Author: Arvid Norberg, arvid@rasterbar.com -:Version: 0.11 +:Version: 0.12 .. contents:: Table of contents :depth: 2 diff --git a/docs/style.css b/docs/style.css index 8bdadf496..9204e2fe8 100755 --- a/docs/style.css +++ b/docs/style.css @@ -244,7 +244,6 @@ div.contents { padding: 0 0 0 0.8em; list-style: none; text-align: left; -/* line-height: 1.5em;*/ } #table-of-contents a.reference {