completed IPv6 support in ip_filter and updated test_ip_filter and documentation. Documented recently added extensions to DHT.
This commit is contained in:
parent
a42189af62
commit
fe0d570f05
|
@ -1,3 +1,6 @@
|
||||||
|
* added an extension to the DHT network protocol to support the
|
||||||
|
exchange of nodes with IPv6 addresses.
|
||||||
|
* modified the ip_filter api slightly to support IPv6
|
||||||
* modified the api slightly to make sequenced download threshold
|
* modified the api slightly to make sequenced download threshold
|
||||||
a per torrent-setting.
|
a per torrent-setting.
|
||||||
* changed the address type to support IPv6
|
* changed the address type to support IPv6
|
||||||
|
|
|
@ -242,6 +242,14 @@ logging=none dht-support=on dht-support=logging dht-support=off
|
||||||
<h2><a name="building-with-autotools">building with autotools</a></h2>
|
<h2><a name="building-with-autotools">building with autotools</a></h2>
|
||||||
<p>First of all, you need to install <tt class="docutils literal"><span class="pre">automake</span></tt> and <tt class="docutils literal"><span class="pre">autoconf</span></tt>. Many
|
<p>First of all, you need to install <tt class="docutils literal"><span class="pre">automake</span></tt> and <tt class="docutils literal"><span class="pre">autoconf</span></tt>. Many
|
||||||
unix/linux systems comes with these preinstalled.</p>
|
unix/linux systems comes with these preinstalled.</p>
|
||||||
|
<p>The prerequisites for building libtorrent is boost.thread, boost.date_time
|
||||||
|
and boost.filesystem. Those are the <em>compiled</em> boost libraries needed. The
|
||||||
|
headers-only libraries needed include (but is not necessarily limited to)
|
||||||
|
boost.bind, boost.ref, boost.multi_index, boost.optional, boost.lexical_cast,
|
||||||
|
boost.integer, boost.iterator, boost.tuple, boost.array, boost.function,
|
||||||
|
boost.smart_ptr, boost.preprocessor, boost.static_assert.</p>
|
||||||
|
<p>If you want to build the <tt class="docutils literal"><span class="pre">client_test</span></tt> example, you'll also need boost.regex
|
||||||
|
and boost.program_options.</p>
|
||||||
<div class="section" id="step-1-generating-the-build-system">
|
<div class="section" id="step-1-generating-the-build-system">
|
||||||
<h3><a name="step-1-generating-the-build-system">Step 1: Generating the build system</a></h3>
|
<h3><a name="step-1-generating-the-build-system">Step 1: Generating the build system</a></h3>
|
||||||
<p>No build system is present if libtorrent is checked out from CVS - it
|
<p>No build system is present if libtorrent is checked out from CVS - it
|
||||||
|
|
|
@ -232,6 +232,16 @@ building with autotools
|
||||||
First of all, you need to install ``automake`` and ``autoconf``. Many
|
First of all, you need to install ``automake`` and ``autoconf``. Many
|
||||||
unix/linux systems comes with these preinstalled.
|
unix/linux systems comes with these preinstalled.
|
||||||
|
|
||||||
|
The prerequisites for building libtorrent is boost.thread, boost.date_time
|
||||||
|
and boost.filesystem. Those are the *compiled* boost libraries needed. The
|
||||||
|
headers-only libraries needed include (but is not necessarily limited to)
|
||||||
|
boost.bind, boost.ref, boost.multi_index, boost.optional, boost.lexical_cast,
|
||||||
|
boost.integer, boost.iterator, boost.tuple, boost.array, boost.function,
|
||||||
|
boost.smart_ptr, boost.preprocessor, boost.static_assert.
|
||||||
|
|
||||||
|
If you want to build the ``client_test`` example, you'll also need boost.regex
|
||||||
|
and boost.program_options.
|
||||||
|
|
||||||
Step 1: Generating the build system
|
Step 1: Generating the build system
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
<?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.3.9: http://docutils.sourceforge.net/" />
|
||||||
|
<title></title>
|
||||||
|
<meta name="author" content="Arvid Norberg, arvid@rasterbar.com" />
|
||||||
|
<link rel="stylesheet" href="style.css" type="text/css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="document">
|
||||||
|
<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" href="mailto:arvid@rasterbar.com">arvid@rasterbar.com</a></td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div class="section" id="mainline-dht-extensions">
|
||||||
|
<h1><a name="mainline-dht-extensions">Mainline DHT extensions</a></h1>
|
||||||
|
<p>libtorrent implements a few extensions to the Mainline DHT protocol.</p>
|
||||||
|
<div class="section" id="client-identification">
|
||||||
|
<h2><a name="client-identification">client identification</a></h2>
|
||||||
|
<p>In each DHT packet, an extra key is inserted named "v". This is a string
|
||||||
|
describing the client and version used. This can help alot when debugging
|
||||||
|
and finding errors in client implementations. The string is encoded as four
|
||||||
|
characters, two characters describing the client and two characters interpreted
|
||||||
|
as a binary number describing the client version.</p>
|
||||||
|
<p>Currently known clients:</p>
|
||||||
|
<table border="1" class="docutils">
|
||||||
|
<colgroup>
|
||||||
|
<col width="65%" />
|
||||||
|
<col width="35%" />
|
||||||
|
</colgroup>
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr><td>uTorrent</td>
|
||||||
|
<td><tt class="docutils literal"><span class="pre">UT</span></tt></td>
|
||||||
|
</tr>
|
||||||
|
<tr><td>libtorrent</td>
|
||||||
|
<td><tt class="docutils literal"><span class="pre">LT</span></tt></td>
|
||||||
|
</tr>
|
||||||
|
<tr><td>MooPolice</td>
|
||||||
|
<td><tt class="docutils literal"><span class="pre">MP</span></tt></td>
|
||||||
|
</tr>
|
||||||
|
<tr><td>GetRight</td>
|
||||||
|
<td><tt class="docutils literal"><span class="pre">GR</span></tt></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="ipv6-support">
|
||||||
|
<h2><a name="ipv6-support">IPv6 support</a></h2>
|
||||||
|
<p>The only DHT messages that don't support IPv6 is the <tt class="docutils literal"><span class="pre">nodes</span></tt> reply. It
|
||||||
|
encodes all the contacts as 6 bytes sequences packed together in sequence in
|
||||||
|
string. The problem is that IPv6 endpoints cannot be encoded as 6 bytes, but
|
||||||
|
needs 18 bytes. The extension libtorrent applies is to add another key, called
|
||||||
|
<tt class="docutils literal"><span class="pre">nodes2</span></tt> which is encoded as a list of strings. Each string represents one
|
||||||
|
contact and is encoded as 20 bytes node-id and then a variable length encoded
|
||||||
|
IP address (6 bytes in IPv4 case and 18 bytes in IPv6 case).</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -30,10 +30,11 @@ IPv6 support
|
||||||
------------
|
------------
|
||||||
|
|
||||||
The only DHT messages that don't support IPv6 is the ``nodes`` reply. It
|
The only DHT messages that don't support IPv6 is the ``nodes`` reply. It
|
||||||
encodes all the contacts as 6 bytes sequences packet together in sequence in
|
encodes all the contacts as 6 bytes sequences packed together in sequence in
|
||||||
string. The problem is that IPv6 endpoints cannot be encoded as 6 bytes, but
|
string. The problem is that IPv6 endpoints cannot be encoded as 6 bytes, but
|
||||||
18 bytes. The extension libtorrent applies is to add another key, called
|
needs 18 bytes. The extension libtorrent applies is to add another key, called
|
||||||
``nodes2`` which is encoded as a list of strings. Each string represents one
|
``nodes2`` which is encoded as a list of strings. Each string represents one
|
||||||
contact and is encoded as 20 bytes node-id and then a variable length encoded
|
contact and is encoded as 20 bytes node-id and then a variable length encoded
|
||||||
IP address (6 bytes in IPv4 case and 18 bytes in IPv6 case).
|
IP address (6 bytes in IPv4 case and 18 bytes in IPv6 case).
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,8 @@
|
||||||
<h1><a name="examples">examples</a></h1>
|
<h1><a name="examples">examples</a></h1>
|
||||||
<p>Except for the example programs in this manual, there's also a bigger example
|
<p>Except for the example programs in this manual, there's also a bigger example
|
||||||
of a (little bit) more complete client, <tt class="docutils literal"><span class="pre">client_test</span></tt>. There are separate
|
of a (little bit) more complete client, <tt class="docutils literal"><span class="pre">client_test</span></tt>. There are separate
|
||||||
instructions for how to use it <a class="reference" href="client_test.html">here</a> if you'd like to try it.</p>
|
instructions for how to use it <a class="reference" href="client_test.html">here</a> if you'd like to try it. Note that building
|
||||||
|
<tt class="docutils literal"><span class="pre">client_test</span></tt> also requires boost.regex and boost.program_options library.</p>
|
||||||
<div class="section" id="dump-torrent">
|
<div class="section" id="dump-torrent">
|
||||||
<h2><a name="dump-torrent">dump_torrent</a></h2>
|
<h2><a name="dump-torrent">dump_torrent</a></h2>
|
||||||
<p>This is an example of a program that will take a torrent-file as a parameter and
|
<p>This is an example of a program that will take a torrent-file as a parameter and
|
||||||
|
|
|
@ -13,7 +13,8 @@ examples
|
||||||
|
|
||||||
Except for the example programs in this manual, there's also a bigger example
|
Except for the example programs in this manual, there's also a bigger example
|
||||||
of a (little bit) more complete client, ``client_test``. There are separate
|
of a (little bit) more complete client, ``client_test``. There are separate
|
||||||
instructions for how to use it here__ if you'd like to try it.
|
instructions for how to use it here__ if you'd like to try it. Note that building
|
||||||
|
``client_test`` also requires boost.regex and boost.program_options library.
|
||||||
|
|
||||||
__ client_test.html
|
__ client_test.html
|
||||||
|
|
||||||
|
|
|
@ -47,44 +47,47 @@ example client.</p>
|
||||||
project (including this documentation). The current state includes the
|
project (including this documentation). The current state includes the
|
||||||
following features:</p>
|
following features:</p>
|
||||||
<ul class="simple">
|
<ul class="simple">
|
||||||
<li>Trackerless torrents (using a kademlia DHT)</li>
|
<li>trackerless torrents (using the Mainline kademlia DHT protocol) with
|
||||||
|
some <a class="reference" href="dht_extensions.html">DHT extensions</a>.</li>
|
||||||
|
<li>support for IPv6</li>
|
||||||
|
<li>piece-wise, unordered, incremental file allocation</li>
|
||||||
|
<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). (see <a class="reference" href="manual.html#threads">threads</a>)</li>
|
||||||
|
<li>adjusts the length of the request queue depending on download rate.</li>
|
||||||
<li>multitracker extension support (as <a class="reference" href="http://home.elp.rr.com/tur/multitracker-spec.txt">specified by John Hoffman</a>)</li>
|
<li>multitracker extension support (as <a class="reference" href="http://home.elp.rr.com/tur/multitracker-spec.txt">specified by John Hoffman</a>)</li>
|
||||||
|
<li>supports files > 2 gigabytes.</li>
|
||||||
<li>serves multiple torrents on a single port and in a single thread</li>
|
<li>serves multiple torrents on a single port and in a single thread</li>
|
||||||
<li>gzipped tracker-responses</li>
|
<li>fast resume support, a way to get rid of the costly piece check at the
|
||||||
|
start of a resumed torrent. Saves the storage state, piece_picker state
|
||||||
|
as well as all local peers in a separate fast-resume file.</li>
|
||||||
<li><a class="reference" href="manual.html#http-seeding">HTTP seeding</a>, as <a class="reference" href="http://www.getright.com/seedtorrent.html">specified by Michael Burford of GetRight</a>.</li>
|
<li><a class="reference" href="manual.html#http-seeding">HTTP seeding</a>, as <a class="reference" href="http://www.getright.com/seedtorrent.html">specified by Michael Burford of GetRight</a>.</li>
|
||||||
<li>piece picking on block-level (as opposed to piece-level).
|
<li>piece picking on block-level (as opposed to piece-level).
|
||||||
This means it can download parts of the same piece from different peers.
|
This means it can download parts of the same piece from different peers.
|
||||||
It will also prefer to download whole pieces from single peers if the
|
It will also prefer to download whole pieces from single peers if the
|
||||||
download speed is high enough from that particular peer.</li>
|
download speed is high enough from that particular peer.</li>
|
||||||
|
<li>supports the <a class="reference" href="extension_protocol.html">udp-tracker protocol</a> by Olaf van der Spek.</li>
|
||||||
<li>queues torrents for file check, instead of checking all of them in parallel.</li>
|
<li>queues torrents for file check, instead of checking all of them in parallel.</li>
|
||||||
<li>supports http proxies and proxy authentication</li>
|
<li>supports http proxies and basic proxy authentication</li>
|
||||||
<li>uses separate threads for checking files and for main downloader, with a
|
<li>gzipped tracker-responses</li>
|
||||||
fool-proof thread-safe library interface. (i.e. There's no way for the
|
|
||||||
user to cause a deadlock). (see <a class="reference" href="manual.html#threads">threads</a>)</li>
|
|
||||||
<li>can limit the upload and download bandwidth usage and the maximum number of
|
<li>can limit the upload and download bandwidth usage and the maximum number of
|
||||||
unchoked peers</li>
|
unchoked peers</li>
|
||||||
<li>piece-wise, unordered, incremental file allocation</li>
|
|
||||||
<li>implements fair trade. User settable trade-ratio, must at least be 1:1,
|
<li>implements fair trade. User settable trade-ratio, must at least be 1:1,
|
||||||
but one can choose to trade 1 for 2 or any other ratio that isn't unfair
|
but one can choose to trade 1 for 2 or any other ratio that isn't unfair
|
||||||
to the other party.</li>
|
to the other party.</li>
|
||||||
<li>fast resume support, a way to get rid of the costly piece check at the
|
<li>supports an <a class="reference" href="udp_tracker_protocol.html">extension protocol</a>. See <a class="reference" href="manual.html#extensions">extensions</a>.</li>
|
||||||
start of a resumed torrent. Saves the storage state, piece_picker state
|
|
||||||
as well as all local peers in a separate fast-resume file.</li>
|
|
||||||
<li>supports an <a class="reference" href="extension_protocol.html">extension protocol</a>. See <a class="reference" href="manual.html#extensions">extensions</a>.</li>
|
|
||||||
<li>supports files > 2 gigabytes.</li>
|
|
||||||
<li>supports the <tt class="docutils literal"><span class="pre">no_peer_id=1</span></tt> extension that will ease the load off trackers.</li>
|
<li>supports the <tt class="docutils literal"><span class="pre">no_peer_id=1</span></tt> extension that will ease the load off trackers.</li>
|
||||||
<li>supports the <a class="reference" href="udp_tracker_protocol.html">udp-tracker protocol</a> by Olaf van der Spek.</li>
|
|
||||||
<li>possibility to limit the number of connections.</li>
|
<li>possibility to limit the number of connections.</li>
|
||||||
<li>delays have messages if there's no other outgoing traffic to the peer, and
|
<li>delays have messages if there's no other outgoing traffic to the peer, and
|
||||||
doesn't send have messages to peers that already has the piece. This saves
|
doesn't send have messages to peers that already has the piece. This saves
|
||||||
bandwidth.</li>
|
bandwidth.</li>
|
||||||
<li>does not have any requirements on the piece order in a torrent that it
|
<li>does not have any requirements on the piece order in a torrent that it
|
||||||
resumes. This means it can resume a torrent downloaded by any client.</li>
|
resumes. This means it can resume a torrent downloaded by any client.</li>
|
||||||
<li>adjusts the length of the request queue depending on download rate.</li>
|
|
||||||
<li>supports the <tt class="docutils literal"><span class="pre">compact=1</span></tt> tracker parameter.</li>
|
<li>supports the <tt class="docutils literal"><span class="pre">compact=1</span></tt> tracker parameter.</li>
|
||||||
<li>selective downloading. The ability to select which parts of a torrent you
|
<li>selective downloading. The ability to select which parts of a torrent you
|
||||||
want to download.</li>
|
want to download.</li>
|
||||||
<li>ip filter</li>
|
<li>ip filter to disallow ip addresses and ip ranges from connecting and
|
||||||
|
being connected</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="portability">
|
<div class="section" id="portability">
|
||||||
|
|
|
@ -29,45 +29,49 @@ libtorrent is still being developed, however it is stable. It is an ongoing
|
||||||
project (including this documentation). The current state includes the
|
project (including this documentation). The current state includes the
|
||||||
following features:
|
following features:
|
||||||
|
|
||||||
* Trackerless torrents (using a kademlia DHT)
|
* trackerless torrents (using the Mainline kademlia DHT protocol) with
|
||||||
|
some `DHT extensions`_.
|
||||||
|
* support for IPv6
|
||||||
|
* piece-wise, unordered, incremental file allocation
|
||||||
|
* 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). (see threads_)
|
||||||
|
* adjusts the length of the request queue depending on download rate.
|
||||||
* multitracker extension support (as `specified by John Hoffman`__)
|
* multitracker extension support (as `specified by John Hoffman`__)
|
||||||
|
* supports files > 2 gigabytes.
|
||||||
* serves multiple torrents on a single port and in a single thread
|
* serves multiple torrents on a single port and in a single thread
|
||||||
* gzipped tracker-responses
|
* fast resume support, a way to get rid of the costly piece check at the
|
||||||
|
start of a resumed torrent. Saves the storage state, piece_picker state
|
||||||
|
as well as all local peers in a separate fast-resume file.
|
||||||
* `HTTP seeding`_, as `specified by Michael Burford of GetRight`__.
|
* `HTTP seeding`_, as `specified by Michael Burford of GetRight`__.
|
||||||
* piece picking on block-level (as opposed to piece-level).
|
* piece picking on block-level (as opposed to piece-level).
|
||||||
This means it can download parts of the same piece from different peers.
|
This means it can download parts of the same piece from different peers.
|
||||||
It will also prefer to download whole pieces from single peers if the
|
It will also prefer to download whole pieces from single peers if the
|
||||||
download speed is high enough from that particular peer.
|
download speed is high enough from that particular peer.
|
||||||
|
* supports the `udp-tracker protocol`__ by Olaf van der Spek.
|
||||||
* queues torrents for file check, instead of checking all of them in parallel.
|
* queues torrents for file check, instead of checking all of them in parallel.
|
||||||
* supports http proxies and proxy authentication
|
* supports http proxies and basic proxy authentication
|
||||||
* uses separate threads for checking files and for main downloader, with a
|
* gzipped tracker-responses
|
||||||
fool-proof thread-safe library interface. (i.e. There's no way for the
|
|
||||||
user to cause a deadlock). (see threads_)
|
|
||||||
* can limit the upload and download bandwidth usage and the maximum number of
|
* can limit the upload and download bandwidth usage and the maximum number of
|
||||||
unchoked peers
|
unchoked peers
|
||||||
* piece-wise, unordered, incremental file allocation
|
|
||||||
* implements fair trade. User settable trade-ratio, must at least be 1:1,
|
* implements fair trade. User settable trade-ratio, must at least be 1:1,
|
||||||
but one can choose to trade 1 for 2 or any other ratio that isn't unfair
|
but one can choose to trade 1 for 2 or any other ratio that isn't unfair
|
||||||
to the other party.
|
to the other party.
|
||||||
* fast resume support, a way to get rid of the costly piece check at the
|
|
||||||
start of a resumed torrent. Saves the storage state, piece_picker state
|
|
||||||
as well as all local peers in a separate fast-resume file.
|
|
||||||
* supports an `extension protocol`__. See extensions_.
|
* supports an `extension protocol`__. See extensions_.
|
||||||
* supports files > 2 gigabytes.
|
|
||||||
* supports the ``no_peer_id=1`` extension that will ease the load off trackers.
|
* supports the ``no_peer_id=1`` extension that will ease the load off trackers.
|
||||||
* supports the `udp-tracker protocol`__ by Olaf van der Spek.
|
|
||||||
* possibility to limit the number of connections.
|
* possibility to limit the number of connections.
|
||||||
* delays have messages if there's no other outgoing traffic to the peer, and
|
* delays have messages if there's no other outgoing traffic to the peer, and
|
||||||
doesn't send have messages to peers that already has the piece. This saves
|
doesn't send have messages to peers that already has the piece. This saves
|
||||||
bandwidth.
|
bandwidth.
|
||||||
* does not have any requirements on the piece order in a torrent that it
|
* does not have any requirements on the piece order in a torrent that it
|
||||||
resumes. This means it can resume a torrent downloaded by any client.
|
resumes. This means it can resume a torrent downloaded by any client.
|
||||||
* adjusts the length of the request queue depending on download rate.
|
|
||||||
* supports the ``compact=1`` tracker parameter.
|
* supports the ``compact=1`` tracker parameter.
|
||||||
* selective downloading. The ability to select which parts of a torrent you
|
* selective downloading. The ability to select which parts of a torrent you
|
||||||
want to download.
|
want to download.
|
||||||
* ip filter
|
* ip filter to disallow ip addresses and ip ranges from connecting and
|
||||||
|
being connected
|
||||||
|
|
||||||
|
.. _`DHT extensions`: dht_extensions.html
|
||||||
__ http://home.elp.rr.com/tur/multitracker-spec.txt
|
__ http://home.elp.rr.com/tur/multitracker-spec.txt
|
||||||
__ http://www.getright.com/seedtorrent.html
|
__ http://www.getright.com/seedtorrent.html
|
||||||
__ extension_protocol.html
|
__ extension_protocol.html
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
<body>
|
<body>
|
||||||
<div class="document">
|
<div class="document">
|
||||||
<div id="librarySidebar"><ul class="simple">
|
<div id="librarySidebar"><ul class="simple">
|
||||||
|
<li><a class="reference" href="http://sourceforge.net/project/showfiles.php?group_id=79942">download</a></li>
|
||||||
<li><a class="reference" href="features.html">features</a></li>
|
<li><a class="reference" href="features.html">features</a></li>
|
||||||
<li><a class="reference" href="building.html">building libtorrent</a></li>
|
<li><a class="reference" href="building.html">building libtorrent</a></li>
|
||||||
<li><a class="reference" href="examples.html">examples</a></li>
|
<li><a class="reference" href="examples.html">examples</a></li>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
<div id="librarySidebar">
|
<div id="librarySidebar">
|
||||||
|
|
||||||
|
* download_
|
||||||
* features_
|
* features_
|
||||||
* `building libtorrent`_
|
* `building libtorrent`_
|
||||||
* examples_
|
* examples_
|
||||||
|
@ -22,6 +22,7 @@
|
||||||
libtorrent
|
libtorrent
|
||||||
==========
|
==========
|
||||||
|
|
||||||
|
.. _download: http://sourceforge.net/project/showfiles.php?group_id=79942
|
||||||
.. _features: features.html
|
.. _features: features.html
|
||||||
.. _`building libtorrent`: building.html
|
.. _`building libtorrent`: building.html
|
||||||
.. _examples: examples.html
|
.. _examples: examples.html
|
||||||
|
|
|
@ -1939,28 +1939,32 @@ the number of outstanding requests to use with url-seeds. Default is 5.</p>
|
||||||
<h1><a name="ip-filter">ip_filter</a></h1>
|
<h1><a name="ip-filter">ip_filter</a></h1>
|
||||||
<p>The <tt class="docutils literal"><span class="pre">ip_filter</span></tt> class is a set of rules that uniquely categorizes all
|
<p>The <tt class="docutils literal"><span class="pre">ip_filter</span></tt> class is a set of rules that uniquely categorizes all
|
||||||
ip addresses as allowed or disallowed. The default constructor creates
|
ip addresses as allowed or disallowed. The default constructor creates
|
||||||
a single rule that allows all addresses (0.0.0.0 - 255.255.255.255).
|
a single rule that allows all addresses (0.0.0.0 - 255.255.255.255 for
|
||||||
The <tt class="docutils literal"><span class="pre">address</span></tt> type here is <tt class="docutils literal"><span class="pre">asio::ip::address_v4</span></tt>. It can also be
|
the IPv4 range, and the equivalent range covering all addresses for the
|
||||||
accessed as <tt class="docutils literal"><span class="pre">libtorrent::address</span></tt>.</p>
|
IPv6 range).</p>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<pre class="literal-block">
|
<pre class="literal-block">
|
||||||
|
template <class Addr>
|
||||||
|
struct ip_range
|
||||||
|
{
|
||||||
|
Addr first;
|
||||||
|
Addr last;
|
||||||
|
int flags;
|
||||||
|
};
|
||||||
|
|
||||||
class ip_filter
|
class ip_filter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum access_flags { blocked = 1 };
|
enum access_flags { blocked = 1 };
|
||||||
|
|
||||||
ip_filter();
|
ip_filter();
|
||||||
void add_rule(address_v4 first, address_v4 last, int flags);
|
void add_rule(address first, address last, int flags);
|
||||||
int access(address_v4 const& addr) const;
|
int access(address const& addr) const;
|
||||||
|
|
||||||
struct ip_range
|
typedef boost::tuple<std::vector<ip_range<address_v4> >
|
||||||
{
|
, std::vector<ip_range<address_v6> > > filter_tuple_t;
|
||||||
address_v4 first;
|
|
||||||
address_v4 last;
|
|
||||||
int flags;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<ip_range> export_filter() const;
|
filter_tuple_t export_filter() const;
|
||||||
};
|
};
|
||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
@ -1979,13 +1983,15 @@ ip_filter()
|
||||||
<h2><a name="add-rule">add_rule()</a></h2>
|
<h2><a name="add-rule">add_rule()</a></h2>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<pre class="literal-block">
|
<pre class="literal-block">
|
||||||
void add_rule(address_v4 first, address_v4 last, int flags);
|
void add_rule(address first, address last, int flags);
|
||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
<p>Adds a rule to the filter. <tt class="docutils literal"><span class="pre">first</span></tt> and <tt class="docutils literal"><span class="pre">last</span></tt> defines a range of
|
<p>Adds a rule to the filter. <tt class="docutils literal"><span class="pre">first</span></tt> and <tt class="docutils literal"><span class="pre">last</span></tt> defines a range of
|
||||||
ip addresses that will be marked with the given flags. The <tt class="docutils literal"><span class="pre">flags</span></tt>
|
ip addresses that will be marked with the given flags. The <tt class="docutils literal"><span class="pre">flags</span></tt>
|
||||||
can currently be 0, which means allowed, or <tt class="docutils literal"><span class="pre">ip_filter::blocked</span></tt>, which
|
can currently be 0, which means allowed, or <tt class="docutils literal"><span class="pre">ip_filter::blocked</span></tt>, which
|
||||||
means disallowed.</p>
|
means disallowed.</p>
|
||||||
|
<p>precondition:
|
||||||
|
<tt class="docutils literal"><span class="pre">first.is_v4()</span> <span class="pre">==</span> <span class="pre">last.is_v4()</span> <span class="pre">&&</span> <span class="pre">first.is_v6()</span> <span class="pre">==</span> <span class="pre">last.is_v6()</span></tt></p>
|
||||||
<p>postcondition:
|
<p>postcondition:
|
||||||
<tt class="docutils literal"><span class="pre">access(x)</span> <span class="pre">==</span> <span class="pre">flags</span></tt> for every <tt class="docutils literal"><span class="pre">x</span></tt> in the range [<tt class="docutils literal"><span class="pre">first</span></tt>, <tt class="docutils literal"><span class="pre">last</span></tt>]</p>
|
<tt class="docutils literal"><span class="pre">access(x)</span> <span class="pre">==</span> <span class="pre">flags</span></tt> for every <tt class="docutils literal"><span class="pre">x</span></tt> in the range [<tt class="docutils literal"><span class="pre">first</span></tt>, <tt class="docutils literal"><span class="pre">last</span></tt>]</p>
|
||||||
<p>This means that in a case of overlapping ranges, the last one applied takes
|
<p>This means that in a case of overlapping ranges, the last one applied takes
|
||||||
|
@ -1995,7 +2001,7 @@ precedence.</p>
|
||||||
<h2><a name="access">access()</a></h2>
|
<h2><a name="access">access()</a></h2>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<pre class="literal-block">
|
<pre class="literal-block">
|
||||||
int access(address_v4 const& addr) const;
|
int access(address const& addr) const;
|
||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
<p>Returns the access permissions for the given address (<tt class="docutils literal"><span class="pre">addr</span></tt>). The permission
|
<p>Returns the access permissions for the given address (<tt class="docutils literal"><span class="pre">addr</span></tt>). The permission
|
||||||
|
@ -2007,13 +2013,16 @@ the current filter.</p>
|
||||||
<h2><a name="export-filter">export_filter()</a></h2>
|
<h2><a name="export-filter">export_filter()</a></h2>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<pre class="literal-block">
|
<pre class="literal-block">
|
||||||
std::vector<ip_range> export_filter() const;
|
boost::tuple<std::vector<ip_range<address_v4> >
|
||||||
|
, std::vector<ip_range<address_v6> > > export_filter() const;
|
||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
<p>This function will return the current state of the filter in the minimum number of
|
<p>This function will return the current state of the filter in the minimum number of
|
||||||
ranges possible. They are sorted from ranges in low addresses to high addresses. Each
|
ranges possible. They are sorted from ranges in low addresses to high addresses. Each
|
||||||
entry in the returned vector is a range with the access control specified in its
|
entry in the returned vector is a range with the access control specified in its
|
||||||
<tt class="docutils literal"><span class="pre">flags</span></tt> field.</p>
|
<tt class="docutils literal"><span class="pre">flags</span></tt> field.</p>
|
||||||
|
<p>The return value is a tuple containing two range-lists. One for IPv4 addresses
|
||||||
|
and one for IPv6 addresses.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="big-number">
|
<div class="section" id="big-number">
|
||||||
|
|
|
@ -1935,29 +1935,33 @@ ip_filter
|
||||||
|
|
||||||
The ``ip_filter`` class is a set of rules that uniquely categorizes all
|
The ``ip_filter`` class is a set of rules that uniquely categorizes all
|
||||||
ip addresses as allowed or disallowed. The default constructor creates
|
ip addresses as allowed or disallowed. The default constructor creates
|
||||||
a single rule that allows all addresses (0.0.0.0 - 255.255.255.255).
|
a single rule that allows all addresses (0.0.0.0 - 255.255.255.255 for
|
||||||
The ``address`` type here is ``asio::ip::address_v4``. It can also be
|
the IPv4 range, and the equivalent range covering all addresses for the
|
||||||
accessed as ``libtorrent::address``.
|
IPv6 range).
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
|
template <class Addr>
|
||||||
|
struct ip_range
|
||||||
|
{
|
||||||
|
Addr first;
|
||||||
|
Addr last;
|
||||||
|
int flags;
|
||||||
|
};
|
||||||
|
|
||||||
class ip_filter
|
class ip_filter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum access_flags { blocked = 1 };
|
enum access_flags { blocked = 1 };
|
||||||
|
|
||||||
ip_filter();
|
ip_filter();
|
||||||
void add_rule(address_v4 first, address_v4 last, int flags);
|
void add_rule(address first, address last, int flags);
|
||||||
int access(address_v4 const& addr) const;
|
int access(address const& addr) const;
|
||||||
|
|
||||||
struct ip_range
|
typedef boost::tuple<std::vector<ip_range<address_v4> >
|
||||||
{
|
, std::vector<ip_range<address_v6> > > filter_tuple_t;
|
||||||
address_v4 first;
|
|
||||||
address_v4 last;
|
|
||||||
int flags;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<ip_range> export_filter() const;
|
filter_tuple_t export_filter() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1979,13 +1983,16 @@ add_rule()
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
void add_rule(address_v4 first, address_v4 last, int flags);
|
void add_rule(address first, address last, int flags);
|
||||||
|
|
||||||
Adds a rule to the filter. ``first`` and ``last`` defines a range of
|
Adds a rule to the filter. ``first`` and ``last`` defines a range of
|
||||||
ip addresses that will be marked with the given flags. The ``flags``
|
ip addresses that will be marked with the given flags. The ``flags``
|
||||||
can currently be 0, which means allowed, or ``ip_filter::blocked``, which
|
can currently be 0, which means allowed, or ``ip_filter::blocked``, which
|
||||||
means disallowed.
|
means disallowed.
|
||||||
|
|
||||||
|
precondition:
|
||||||
|
``first.is_v4() == last.is_v4() && first.is_v6() == last.is_v6()``
|
||||||
|
|
||||||
postcondition:
|
postcondition:
|
||||||
``access(x) == flags`` for every ``x`` in the range [``first``, ``last``]
|
``access(x) == flags`` for every ``x`` in the range [``first``, ``last``]
|
||||||
|
|
||||||
|
@ -1998,7 +2005,7 @@ access()
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
int access(address_v4 const& addr) const;
|
int access(address const& addr) const;
|
||||||
|
|
||||||
Returns the access permissions for the given address (``addr``). The permission
|
Returns the access permissions for the given address (``addr``). The permission
|
||||||
can currently be 0 or ``ip_filter::blocked``. The complexity of this operation
|
can currently be 0 or ``ip_filter::blocked``. The complexity of this operation
|
||||||
|
@ -2011,13 +2018,17 @@ export_filter()
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
std::vector<ip_range> export_filter() const;
|
boost::tuple<std::vector<ip_range<address_v4> >
|
||||||
|
, std::vector<ip_range<address_v6> > > export_filter() const;
|
||||||
|
|
||||||
This function will return the current state of the filter in the minimum number of
|
This function will return the current state of the filter in the minimum number of
|
||||||
ranges possible. They are sorted from ranges in low addresses to high addresses. Each
|
ranges possible. They are sorted from ranges in low addresses to high addresses. Each
|
||||||
entry in the returned vector is a range with the access control specified in its
|
entry in the returned vector is a range with the access control specified in its
|
||||||
``flags`` field.
|
``flags`` field.
|
||||||
|
|
||||||
|
The return value is a tuple containing two range-lists. One for IPv4 addresses
|
||||||
|
and one for IPv6 addresses.
|
||||||
|
|
||||||
|
|
||||||
big_number
|
big_number
|
||||||
==========
|
==========
|
||||||
|
|
|
@ -33,6 +33,19 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#ifndef TORRENT_IP_FILTER_HPP
|
#ifndef TORRENT_IP_FILTER_HPP
|
||||||
#define TORRENT_IP_FILTER_HPP
|
#define TORRENT_IP_FILTER_HPP
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push, 1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/limits.hpp>
|
||||||
|
#include <boost/utility.hpp>
|
||||||
|
#include <boost/tuple/tuple.hpp>
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "libtorrent/config.hpp"
|
#include "libtorrent/config.hpp"
|
||||||
#include "libtorrent/socket.hpp"
|
#include "libtorrent/socket.hpp"
|
||||||
#include <set>
|
#include <set>
|
||||||
|
@ -47,6 +60,189 @@ inline bool operator<=(address const& lhs
|
||||||
return lhs < rhs || lhs == rhs;
|
return lhs < rhs || lhs == rhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class Addr>
|
||||||
|
struct ip_range
|
||||||
|
{
|
||||||
|
Addr first;
|
||||||
|
Addr last;
|
||||||
|
int flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
// this is the generic implementation of
|
||||||
|
// a filter for a specific address type.
|
||||||
|
// it works with IPv4 and IPv6
|
||||||
|
template<class Addr>
|
||||||
|
class filter_impl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
filter_impl()
|
||||||
|
{
|
||||||
|
typename Addr::bytes_type zero;
|
||||||
|
std::fill(zero.begin(), zero.end(), 0);
|
||||||
|
// make the entire ip-range non-blocked
|
||||||
|
m_access_list.insert(range(Addr(zero), 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_rule(Addr first, Addr last, int flags)
|
||||||
|
{
|
||||||
|
using boost::next;
|
||||||
|
using boost::prior;
|
||||||
|
|
||||||
|
assert(!m_access_list.empty());
|
||||||
|
assert(first < last || first == last);
|
||||||
|
|
||||||
|
typename range_t::iterator i = m_access_list.upper_bound(first);
|
||||||
|
typename range_t::iterator j = m_access_list.upper_bound(last);
|
||||||
|
|
||||||
|
if (i != m_access_list.begin()) --i;
|
||||||
|
|
||||||
|
assert(j != m_access_list.begin());
|
||||||
|
assert(j != i);
|
||||||
|
|
||||||
|
int first_access = i->access;
|
||||||
|
int last_access = prior(j)->access;
|
||||||
|
|
||||||
|
if (i->start != first && first_access != flags)
|
||||||
|
{
|
||||||
|
i = m_access_list.insert(i, range(first, flags));
|
||||||
|
}
|
||||||
|
else if (i != m_access_list.begin() && prior(i)->access == flags)
|
||||||
|
{
|
||||||
|
--i;
|
||||||
|
first_access = i->access;
|
||||||
|
}
|
||||||
|
assert(!m_access_list.empty());
|
||||||
|
assert(i != m_access_list.end());
|
||||||
|
|
||||||
|
if (i != j) m_access_list.erase(next(i), j);
|
||||||
|
if (i->start == first)
|
||||||
|
{
|
||||||
|
// we can do this const-cast because we know that the new
|
||||||
|
// start address will keep the set correctly ordered
|
||||||
|
const_cast<Addr&>(i->start) = first;
|
||||||
|
const_cast<int&>(i->access) = flags;
|
||||||
|
}
|
||||||
|
else if (first_access != flags)
|
||||||
|
{
|
||||||
|
m_access_list.insert(i, range(first, flags));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((j != m_access_list.end()
|
||||||
|
&& minus_one(j->start) != last)
|
||||||
|
|| (j == m_access_list.end()
|
||||||
|
&& last != max_addr()))
|
||||||
|
{
|
||||||
|
assert(j == m_access_list.end() || last < minus_one(j->start));
|
||||||
|
if (last_access != flags)
|
||||||
|
j = m_access_list.insert(j, range(plus_one(last), last_access));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j != m_access_list.end() && j->access == flags) m_access_list.erase(j);
|
||||||
|
assert(!m_access_list.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
int access(Addr const& addr) const
|
||||||
|
{
|
||||||
|
assert(!m_access_list.empty());
|
||||||
|
typename range_t::const_iterator i = m_access_list.upper_bound(addr);
|
||||||
|
if (i != m_access_list.begin()) --i;
|
||||||
|
assert(i != m_access_list.end());
|
||||||
|
assert(i->start <= addr && (boost::next(i) == m_access_list.end()
|
||||||
|
|| addr < boost::next(i)->start));
|
||||||
|
return i->access;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<ip_range<Addr> > export_filter() const
|
||||||
|
{
|
||||||
|
std::vector<ip_range<Addr> > ret;
|
||||||
|
ret.reserve(m_access_list.size());
|
||||||
|
|
||||||
|
for (typename range_t::const_iterator i = m_access_list.begin()
|
||||||
|
, end(m_access_list.end()); i != end;)
|
||||||
|
{
|
||||||
|
ip_range<Addr> r;
|
||||||
|
r.first = i->start;
|
||||||
|
r.flags = i->access;
|
||||||
|
|
||||||
|
++i;
|
||||||
|
if (i == end)
|
||||||
|
r.last = max_addr();
|
||||||
|
else
|
||||||
|
r.last = minus_one(i->start);
|
||||||
|
|
||||||
|
ret.push_back(r);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
Addr plus_one(Addr const& a) const
|
||||||
|
{
|
||||||
|
typename Addr::bytes_type tmp(a.to_bytes());
|
||||||
|
typedef typename Addr::bytes_type::reverse_iterator iter;
|
||||||
|
for (iter i = tmp.rbegin()
|
||||||
|
, end(tmp.rend()); i != end; ++i)
|
||||||
|
{
|
||||||
|
if (*i < std::numeric_limits<typename iter::value_type>::max())
|
||||||
|
{
|
||||||
|
*i += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*i = 0;
|
||||||
|
}
|
||||||
|
return Addr(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
Addr minus_one(Addr const& a) const
|
||||||
|
{
|
||||||
|
typename Addr::bytes_type tmp(a.to_bytes());
|
||||||
|
typedef typename Addr::bytes_type::reverse_iterator iter;
|
||||||
|
for (iter i = tmp.rbegin()
|
||||||
|
, end(tmp.rend()); i != end; ++i)
|
||||||
|
{
|
||||||
|
if (*i > 0)
|
||||||
|
{
|
||||||
|
*i -= 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*i = std::numeric_limits<typename iter::value_type>::max();
|
||||||
|
}
|
||||||
|
return Addr(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
Addr max_addr() const
|
||||||
|
{
|
||||||
|
typename Addr::bytes_type tmp;
|
||||||
|
std::fill(tmp.begin(), tmp.end()
|
||||||
|
, std::numeric_limits<typename Addr::bytes_type::value_type>::max());
|
||||||
|
return Addr(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct range
|
||||||
|
{
|
||||||
|
range(Addr addr, int access = 0): start(addr), access(access) {}
|
||||||
|
bool operator<(range const& r) const
|
||||||
|
{ return start < r.start; }
|
||||||
|
bool operator<(Addr const& a) const
|
||||||
|
{ return start < a; }
|
||||||
|
Addr start;
|
||||||
|
// the end of the range is implicit
|
||||||
|
// and given by the next entry in the set
|
||||||
|
int access;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::set<range> range_t;
|
||||||
|
range_t m_access_list;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
class TORRENT_EXPORT ip_filter
|
class TORRENT_EXPORT ip_filter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -55,38 +251,23 @@ public:
|
||||||
{
|
{
|
||||||
blocked = 1
|
blocked = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
ip_filter();
|
|
||||||
void add_rule(address_v4 first, address_v4 last, int flags);
|
|
||||||
int access(address_v4 const& addr) const;
|
|
||||||
|
|
||||||
struct ip_range
|
// both addresses MUST be of the same type (i.e. both must
|
||||||
{
|
// be either IPv4 or both must be IPv6)
|
||||||
address_v4 first;
|
void add_rule(address first, address last, int flags);
|
||||||
address_v4 last;
|
int access(address const& addr) const;
|
||||||
int flags;
|
|
||||||
};
|
typedef boost::tuple<std::vector<ip_range<address_v4> >
|
||||||
|
, std::vector<ip_range<address_v6> > > filter_tuple_t;
|
||||||
std::vector<ip_range> export_filter() const;
|
|
||||||
|
filter_tuple_t export_filter() const;
|
||||||
|
|
||||||
// void print() const;
|
// void print() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct range
|
|
||||||
{
|
|
||||||
range(address_v4 addr, int access = 0): start(addr), access(access) {}
|
|
||||||
bool operator<(range const& r) const
|
|
||||||
{ return start < r.start; }
|
|
||||||
bool operator<(address const& a) const
|
|
||||||
{ return start < a; }
|
|
||||||
address_v4 start;
|
|
||||||
// the end of the range is implicit
|
|
||||||
// and given by the next entry in the set
|
|
||||||
int access;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::set<range> range_t;
|
detail::filter_impl<address_v4> m_filter4;
|
||||||
range_t m_access_list;
|
detail::filter_impl<address_v6> m_filter6;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,103 +37,37 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
namespace libtorrent
|
namespace libtorrent
|
||||||
{
|
{
|
||||||
|
void ip_filter::add_rule(address first, address last, int flags)
|
||||||
ip_filter::ip_filter()
|
|
||||||
{
|
{
|
||||||
// make the entire ip-range non-blocked
|
if (first.is_v4())
|
||||||
m_access_list.insert(range(address_v4(0UL), 0));
|
{
|
||||||
|
assert(last.is_v4());
|
||||||
|
m_filter4.add_rule(first.to_v4(), last.to_v4(), flags);
|
||||||
|
}
|
||||||
|
else if (first.is_v6())
|
||||||
|
{
|
||||||
|
assert(last.is_v6());
|
||||||
|
m_filter6.add_rule(first.to_v6(), last.to_v6(), flags);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
assert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ip_filter::add_rule(address_v4 first, address_v4 last, int flags)
|
int ip_filter::access(address const& addr) const
|
||||||
{
|
{
|
||||||
using boost::next;
|
if (addr.is_v4())
|
||||||
using boost::prior;
|
return m_filter4.access(addr.to_v4());
|
||||||
|
else if (addr.is_v6())
|
||||||
assert(!m_access_list.empty());
|
return m_filter6.access(addr.to_v6());
|
||||||
assert(first <= last);
|
else
|
||||||
range_t::iterator i = m_access_list.upper_bound(first);
|
assert(false);
|
||||||
range_t::iterator j = m_access_list.upper_bound(last);
|
|
||||||
|
|
||||||
if (i != m_access_list.begin()) --i;
|
|
||||||
|
|
||||||
assert(j != m_access_list.begin());
|
|
||||||
assert(j != i);
|
|
||||||
|
|
||||||
int first_access = i->access;
|
|
||||||
int last_access = prior(j)->access;
|
|
||||||
|
|
||||||
if (i->start != first && first_access != flags)
|
|
||||||
{
|
|
||||||
i = m_access_list.insert(i, range(first, flags));
|
|
||||||
}
|
|
||||||
else if (i != m_access_list.begin() && prior(i)->access == flags)
|
|
||||||
{
|
|
||||||
--i;
|
|
||||||
first_access = i->access;
|
|
||||||
}
|
|
||||||
assert(!m_access_list.empty());
|
|
||||||
assert(i != m_access_list.end());
|
|
||||||
|
|
||||||
if (i != j)
|
|
||||||
m_access_list.erase(next(i), j);
|
|
||||||
if (i->start == first)
|
|
||||||
{
|
|
||||||
// we can do this const-cast because we know that the new
|
|
||||||
// start address will keep the set correctly ordered
|
|
||||||
const_cast<address_v4&>(i->start) = first;
|
|
||||||
const_cast<int&>(i->access) = flags;
|
|
||||||
}
|
|
||||||
else if (first_access != flags)
|
|
||||||
{
|
|
||||||
m_access_list.insert(i, range(first, flags));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((j != m_access_list.end() && j->start.to_ulong() - 1 != last.to_ulong())
|
|
||||||
|| (j == m_access_list.end() && last.to_ulong() != 0xffffffff))
|
|
||||||
{
|
|
||||||
assert(j == m_access_list.end() || last.to_ulong() < j->start.to_ulong() - 1);
|
|
||||||
if (last_access != flags)
|
|
||||||
j = m_access_list.insert(j, range(address_v4(last.to_ulong() + 1), last_access));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (j != m_access_list.end() && j->access == flags) m_access_list.erase(j);
|
|
||||||
assert(!m_access_list.empty());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ip_filter::access(address_v4 const& addr) const
|
ip_filter::filter_tuple_t ip_filter::export_filter() const
|
||||||
{
|
{
|
||||||
assert(!m_access_list.empty());
|
return boost::make_tuple(m_filter4.export_filter()
|
||||||
range_t::const_iterator i = m_access_list.upper_bound(addr);
|
, m_filter6.export_filter());
|
||||||
if (i != m_access_list.begin()) --i;
|
|
||||||
assert(i != m_access_list.end());
|
|
||||||
assert(i->start <= addr && (boost::next(i) == m_access_list.end()
|
|
||||||
|| addr < boost::next(i)->start));
|
|
||||||
return i->access;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::vector<ip_filter::ip_range> ip_filter::export_filter() const
|
|
||||||
{
|
|
||||||
std::vector<ip_range> ret;
|
|
||||||
ret.reserve(m_access_list.size());
|
|
||||||
|
|
||||||
for (range_t::const_iterator i = m_access_list.begin()
|
|
||||||
, end(m_access_list.end()); i != end;)
|
|
||||||
{
|
|
||||||
ip_range r;
|
|
||||||
r.first = i->start;
|
|
||||||
r.flags = i->access;
|
|
||||||
|
|
||||||
++i;
|
|
||||||
if (i == end)
|
|
||||||
r.last = address_v4(0xffffffff);
|
|
||||||
else
|
|
||||||
r.last = address_v4(i->start.to_ulong() - 1);
|
|
||||||
|
|
||||||
ret.push_back(r);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
void ip_filter::print() const
|
void ip_filter::print() const
|
||||||
|
|
|
@ -3,24 +3,35 @@
|
||||||
|
|
||||||
#include "test.hpp"
|
#include "test.hpp"
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Currently this test only tests that the filter can handle
|
||||||
|
IPv4 addresses. Maybe it should be extended to IPv6 as well,
|
||||||
|
but the actual code is just a template, so it is probably
|
||||||
|
pretty safe to assume that as long as it works for IPv4 it
|
||||||
|
also works for IPv6.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
using namespace libtorrent;
|
using namespace libtorrent;
|
||||||
|
|
||||||
bool compare(ip_filter::ip_range const& lhs
|
template <class Addr>
|
||||||
, ip_filter::ip_range const& rhs)
|
bool compare(ip_range<Addr> const& lhs
|
||||||
|
, ip_range<Addr> const& rhs)
|
||||||
{
|
{
|
||||||
return lhs.first == rhs.first
|
return lhs.first == rhs.first
|
||||||
&& lhs.last == rhs.last
|
&& lhs.last == rhs.last
|
||||||
&& lhs.flags == rhs.flags;
|
&& lhs.flags == rhs.flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_rules_invariant(std::vector<ip_filter::ip_range> const& r, ip_filter const& f)
|
void test_rules_invariant(std::vector<ip_range<address_v4> > const& r, ip_filter const& f)
|
||||||
{
|
{
|
||||||
typedef std::vector<ip_filter::ip_range>::const_iterator iterator;
|
typedef std::vector<ip_range<address_v4> >::const_iterator iterator;
|
||||||
TEST_CHECK(!r.empty());
|
TEST_CHECK(!r.empty());
|
||||||
if (r.empty()) return;
|
if (r.empty()) return;
|
||||||
|
|
||||||
TEST_CHECK(r.front().first == address_v4::from_string("0.0.0.0"));
|
TEST_CHECK(r.front().first == address::from_string("0.0.0.0"));
|
||||||
TEST_CHECK(r.back().last == address_v4::from_string("255.255.255.255"));
|
TEST_CHECK(r.back().last == address::from_string("255.255.255.255"));
|
||||||
|
|
||||||
iterator i = r.begin();
|
iterator i = r.begin();
|
||||||
iterator j = boost::next(i);
|
iterator j = boost::next(i);
|
||||||
|
@ -36,10 +47,11 @@ void test_rules_invariant(std::vector<ip_filter::ip_range> const& r, ip_filter c
|
||||||
int test_main()
|
int test_main()
|
||||||
{
|
{
|
||||||
using namespace libtorrent;
|
using namespace libtorrent;
|
||||||
std::vector<ip_filter::ip_range> range;
|
|
||||||
|
std::vector<ip_range<address_v4> > range;
|
||||||
|
|
||||||
// **** test joining of ranges at the end ****
|
// **** test joining of ranges at the end ****
|
||||||
ip_filter::ip_range expected1[] =
|
ip_range<address_v4> expected1[] =
|
||||||
{
|
{
|
||||||
{address_v4::from_string("0.0.0.0"), address_v4::from_string("0.255.255.255"), 0}
|
{address_v4::from_string("0.0.0.0"), address_v4::from_string("0.255.255.255"), 0}
|
||||||
, {address_v4::from_string("1.0.0.0"), address_v4::from_string("3.0.0.0"), ip_filter::blocked}
|
, {address_v4::from_string("1.0.0.0"), address_v4::from_string("3.0.0.0"), ip_filter::blocked}
|
||||||
|
@ -48,28 +60,30 @@ int test_main()
|
||||||
|
|
||||||
{
|
{
|
||||||
ip_filter f;
|
ip_filter f;
|
||||||
f.add_rule(address_v4::from_string("1.0.0.0"), address_v4::from_string("2.0.0.0"), ip_filter::blocked);
|
f.add_rule(address::from_string("1.0.0.0"), address::from_string("2.0.0.0"), ip_filter::blocked);
|
||||||
f.add_rule(address_v4::from_string("2.0.0.1"), address_v4::from_string("3.0.0.0"), ip_filter::blocked);
|
f.add_rule(address::from_string("2.0.0.1"), address::from_string("3.0.0.0"), ip_filter::blocked);
|
||||||
|
|
||||||
range = f.export_filter();
|
range = boost::get<0>(f.export_filter());
|
||||||
test_rules_invariant(range, f);
|
test_rules_invariant(range, f);
|
||||||
|
|
||||||
TEST_CHECK(range.size() == 3);
|
TEST_CHECK(range.size() == 3);
|
||||||
TEST_CHECK(std::equal(range.begin(), range.end(), expected1, &compare));
|
TEST_CHECK(std::equal(range.begin(), range.end(), expected1, &compare<address_v4>));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// **** test joining of ranges at the start ****
|
// **** test joining of ranges at the start ****
|
||||||
|
|
||||||
{
|
{
|
||||||
ip_filter f;
|
ip_filter f;
|
||||||
f.add_rule(address_v4::from_string("2.0.0.1"), address_v4::from_string("3.0.0.0"), ip_filter::blocked);
|
f.add_rule(address::from_string("2.0.0.1"), address::from_string("3.0.0.0"), ip_filter::blocked);
|
||||||
f.add_rule(address_v4::from_string("1.0.0.0"), address_v4::from_string("2.0.0.0"), ip_filter::blocked);
|
f.add_rule(address::from_string("1.0.0.0"), address::from_string("2.0.0.0"), ip_filter::blocked);
|
||||||
|
|
||||||
range = f.export_filter();
|
range = boost::get<0>(f.export_filter());
|
||||||
test_rules_invariant(range, f);
|
test_rules_invariant(range, f);
|
||||||
|
|
||||||
TEST_CHECK(range.size() == 3);
|
TEST_CHECK(range.size() == 3);
|
||||||
TEST_CHECK(std::equal(range.begin(), range.end(), expected1, &compare));
|
TEST_CHECK(std::equal(range.begin(), range.end(), expected1, &compare<address_v4>));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -77,14 +91,15 @@ int test_main()
|
||||||
|
|
||||||
{
|
{
|
||||||
ip_filter f;
|
ip_filter f;
|
||||||
f.add_rule(address_v4::from_string("2.0.0.1"), address_v4::from_string("3.0.0.0"), ip_filter::blocked);
|
f.add_rule(address::from_string("2.0.0.1"), address::from_string("3.0.0.0"), ip_filter::blocked);
|
||||||
f.add_rule(address_v4::from_string("1.0.0.0"), address_v4::from_string("2.4.0.0"), ip_filter::blocked);
|
f.add_rule(address::from_string("1.0.0.0"), address::from_string("2.4.0.0"), ip_filter::blocked);
|
||||||
|
|
||||||
range = f.export_filter();
|
range = boost::get<0>(f.export_filter());
|
||||||
test_rules_invariant(range, f);
|
test_rules_invariant(range, f);
|
||||||
|
|
||||||
TEST_CHECK(range.size() == 3);
|
TEST_CHECK(range.size() == 3);
|
||||||
TEST_CHECK(std::equal(range.begin(), range.end(), expected1, &compare));
|
TEST_CHECK(std::equal(range.begin(), range.end(), expected1, &compare<address_v4>));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -92,14 +107,15 @@ int test_main()
|
||||||
|
|
||||||
{
|
{
|
||||||
ip_filter f;
|
ip_filter f;
|
||||||
f.add_rule(address_v4::from_string("1.0.0.0"), address_v4::from_string("2.4.0.0"), ip_filter::blocked);
|
f.add_rule(address::from_string("1.0.0.0"), address::from_string("2.4.0.0"), ip_filter::blocked);
|
||||||
f.add_rule(address_v4::from_string("2.0.0.1"), address_v4::from_string("3.0.0.0"), ip_filter::blocked);
|
f.add_rule(address::from_string("2.0.0.1"), address::from_string("3.0.0.0"), ip_filter::blocked);
|
||||||
|
|
||||||
range = f.export_filter();
|
range = boost::get<0>(f.export_filter());
|
||||||
test_rules_invariant(range, f);
|
test_rules_invariant(range, f);
|
||||||
|
|
||||||
TEST_CHECK(range.size() == 3);
|
TEST_CHECK(range.size() == 3);
|
||||||
TEST_CHECK(std::equal(range.begin(), range.end(), expected1, &compare));
|
TEST_CHECK(std::equal(range.begin(), range.end(), expected1, &compare<address_v4>));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -107,50 +123,52 @@ int test_main()
|
||||||
|
|
||||||
{
|
{
|
||||||
ip_filter f;
|
ip_filter f;
|
||||||
f.add_rule(address_v4::from_string("1.0.0.0"), address_v4::from_string("2.0.0.0"), ip_filter::blocked);
|
f.add_rule(address::from_string("1.0.0.0"), address::from_string("2.0.0.0"), ip_filter::blocked);
|
||||||
f.add_rule(address_v4::from_string("3.0.0.0"), address_v4::from_string("4.0.0.0"), ip_filter::blocked);
|
f.add_rule(address::from_string("3.0.0.0"), address::from_string("4.0.0.0"), ip_filter::blocked);
|
||||||
f.add_rule(address_v4::from_string("5.0.0.0"), address_v4::from_string("6.0.0.0"), ip_filter::blocked);
|
f.add_rule(address::from_string("5.0.0.0"), address::from_string("6.0.0.0"), ip_filter::blocked);
|
||||||
f.add_rule(address_v4::from_string("7.0.0.0"), address_v4::from_string("8.0.0.0"), ip_filter::blocked);
|
f.add_rule(address::from_string("7.0.0.0"), address::from_string("8.0.0.0"), ip_filter::blocked);
|
||||||
|
|
||||||
f.add_rule(address_v4::from_string("1.0.1.0"), address_v4::from_string("9.0.0.0"), ip_filter::blocked);
|
f.add_rule(address::from_string("1.0.1.0"), address::from_string("9.0.0.0"), ip_filter::blocked);
|
||||||
|
|
||||||
range = f.export_filter();
|
range = boost::get<0>(f.export_filter());
|
||||||
test_rules_invariant(range, f);
|
test_rules_invariant(range, f);
|
||||||
|
|
||||||
TEST_CHECK(range.size() == 3);
|
TEST_CHECK(range.size() == 3);
|
||||||
ip_filter::ip_range expected[] =
|
ip_range<address_v4> expected[] =
|
||||||
{
|
{
|
||||||
{address_v4::from_string("0.0.0.0"), address_v4::from_string("0.255.255.255"), 0}
|
{address_v4::from_string("0.0.0.0"), address_v4::from_string("0.255.255.255"), 0}
|
||||||
, {address_v4::from_string("1.0.0.0"), address_v4::from_string("9.0.0.0"), ip_filter::blocked}
|
, {address_v4::from_string("1.0.0.0"), address_v4::from_string("9.0.0.0"), ip_filter::blocked}
|
||||||
, {address_v4::from_string("9.0.0.1"), address_v4::from_string("255.255.255.255"), 0}
|
, {address_v4::from_string("9.0.0.1"), address_v4::from_string("255.255.255.255"), 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_CHECK(std::equal(range.begin(), range.end(), expected, &compare));
|
TEST_CHECK(std::equal(range.begin(), range.end(), expected, &compare<address_v4>));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// **** test joining of multiple overlapping ranges 2 ****
|
// **** test joining of multiple overlapping ranges 2 ****
|
||||||
|
|
||||||
{
|
{
|
||||||
ip_filter f;
|
ip_filter f;
|
||||||
f.add_rule(address_v4::from_string("1.0.0.0"), address_v4::from_string("2.0.0.0"), ip_filter::blocked);
|
f.add_rule(address::from_string("1.0.0.0"), address::from_string("2.0.0.0"), ip_filter::blocked);
|
||||||
f.add_rule(address_v4::from_string("3.0.0.0"), address_v4::from_string("4.0.0.0"), ip_filter::blocked);
|
f.add_rule(address::from_string("3.0.0.0"), address::from_string("4.0.0.0"), ip_filter::blocked);
|
||||||
f.add_rule(address_v4::from_string("5.0.0.0"), address_v4::from_string("6.0.0.0"), ip_filter::blocked);
|
f.add_rule(address::from_string("5.0.0.0"), address::from_string("6.0.0.0"), ip_filter::blocked);
|
||||||
f.add_rule(address_v4::from_string("7.0.0.0"), address_v4::from_string("8.0.0.0"), ip_filter::blocked);
|
f.add_rule(address::from_string("7.0.0.0"), address::from_string("8.0.0.0"), ip_filter::blocked);
|
||||||
|
|
||||||
f.add_rule(address_v4::from_string("0.0.1.0"), address_v4::from_string("7.0.4.0"), ip_filter::blocked);
|
f.add_rule(address::from_string("0.0.1.0"), address::from_string("7.0.4.0"), ip_filter::blocked);
|
||||||
|
|
||||||
range = f.export_filter();
|
range = boost::get<0>(f.export_filter());
|
||||||
test_rules_invariant(range, f);
|
test_rules_invariant(range, f);
|
||||||
|
|
||||||
TEST_CHECK(range.size() == 3);
|
TEST_CHECK(range.size() == 3);
|
||||||
ip_filter::ip_range expected[] =
|
ip_range<address_v4> expected[] =
|
||||||
{
|
{
|
||||||
{address_v4::from_string("0.0.0.0"), address_v4::from_string("0.0.0.255"), 0}
|
{address_v4::from_string("0.0.0.0"), address_v4::from_string("0.0.0.255"), 0}
|
||||||
, {address_v4::from_string("0.0.1.0"), address_v4::from_string("8.0.0.0"), ip_filter::blocked}
|
, {address_v4::from_string("0.0.1.0"), address_v4::from_string("8.0.0.0"), ip_filter::blocked}
|
||||||
, {address_v4::from_string("8.0.0.1"), address_v4::from_string("255.255.255.255"), 0}
|
, {address_v4::from_string("8.0.0.1"), address_v4::from_string("255.255.255.255"), 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_CHECK(std::equal(range.begin(), range.end(), expected, &compare));
|
TEST_CHECK(std::equal(range.begin(), range.end(), expected, &compare<address_v4>));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue