regenerate html
This commit is contained in:
parent
488f7697c6
commit
b656076323
|
@ -56,20 +56,20 @@
|
|||
<p class="topic-title first">Table of contents</p>
|
||||
<ul class="simple">
|
||||
<li><a class="reference internal" href="#terminology" id="id3">terminology</a></li>
|
||||
<li><a class="reference internal" href="#messages" id="id4">messages</a></li>
|
||||
<li><a class="reference internal" href="#immutable-items" id="id5">immutable items</a><ul>
|
||||
<li><a class="reference internal" href="#put-message" id="id6">put message</a></li>
|
||||
<li><a class="reference internal" href="#get-message" id="id7">get message</a></li>
|
||||
<li><a class="reference internal" href="#messages" id="id4">messages</a><ul>
|
||||
<li><a class="reference internal" href="#put-message" id="id5">put message</a></li>
|
||||
<li><a class="reference internal" href="#get-message" id="id6">get message</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#mutable-items" id="id8">mutable items</a><ul>
|
||||
<li><a class="reference internal" href="#id1" id="id9">put message</a></li>
|
||||
<li><a class="reference internal" href="#id2" id="id10">get message</a></li>
|
||||
<li><a class="reference internal" href="#mutable-items" id="id7">mutable items</a><ul>
|
||||
<li><a class="reference internal" href="#id1" id="id8">put message</a></li>
|
||||
<li><a class="reference internal" href="#id2" id="id9">get message</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#signature-verification" id="id11">signature verification</a></li>
|
||||
<li><a class="reference internal" href="#expiration" id="id12">expiration</a></li>
|
||||
<li><a class="reference internal" href="#test-vectors" id="id13">test vectors</a></li>
|
||||
<li><a class="reference internal" href="#signature-verification" id="id10">signature verification</a></li>
|
||||
<li><a class="reference internal" href="#expiration" id="id11">expiration</a></li>
|
||||
<li><a class="reference internal" href="#test-vector" id="id12">test vector</a></li>
|
||||
<li><a class="reference internal" href="#resources" id="id13">resources</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>This is a proposal for an extension to the BitTorrent DHT to allow
|
||||
|
@ -88,41 +88,45 @@ alive.</p>
|
|||
</div>
|
||||
<div class="section" id="messages">
|
||||
<h1>messages</h1>
|
||||
<p>The proposed new messages <tt class="docutils literal">get</tt> and <tt class="docutils literal">put</tt> are similar to the existing <tt class="docutils literal">get_peers</tt>
|
||||
and <tt class="docutils literal">announce_peer</tt>.</p>
|
||||
<p>Responses to <tt class="docutils literal">get</tt> should always include <tt class="docutils literal">nodes</tt> and <tt class="docutils literal">nodes6</tt>. Those fields
|
||||
have the same semantics as in its <tt class="docutils literal">get_peers</tt> response. It should also include a write token,
|
||||
<tt class="docutils literal">token</tt>, with the same semantics as int <tt class="docutils literal">get_peers</tt>. The write token MAY be tied
|
||||
specifically to the key which <tt class="docutils literal">get</tt> requested. i.e. the <tt class="docutils literal">token</tt> can only be used
|
||||
to store values under that one key.</p>
|
||||
<p>The <tt class="docutils literal">id</tt> field in these messages has the same semantics as the standard DHT messages,
|
||||
i.e. the node ID of the node sending the message, to maintain the structure of the DHT
|
||||
network.</p>
|
||||
<p>The <tt class="docutils literal">token</tt> field also has the same semantics as the standard DHT message <tt class="docutils literal">get_peers</tt>
|
||||
and <tt class="docutils literal">announce_peer</tt>, when requesting an item and to write an item respectively.</p>
|
||||
<p>The <tt class="docutils literal">k</tt> field is the 32 byte curve25519 public key, which the signature
|
||||
can be authenticated with. When looking up a mutable item, the <tt class="docutils literal">target</tt> field
|
||||
MUST be the SHA-1 hash of this key.</p>
|
||||
<p>The distinction between storing mutable and immutable items is the inclusion
|
||||
of a public key, a sequence number and signature (<tt class="docutils literal">k</tt>, <tt class="docutils literal">seq</tt> and <tt class="docutils literal">sig</tt>).</p>
|
||||
<p><tt class="docutils literal">get</tt> requests for mutable items and immutable items cannot be distinguished from
|
||||
eachother. An implementation can either store mutable and immutable items in the same
|
||||
hash table internally, or in separate ones and potentially do two lookups for <tt class="docutils literal">get</tt>
|
||||
requests.</p>
|
||||
<p>The <tt class="docutils literal">v</tt> field is the <em>value</em> to be stored. It is allowed to be any bencoded type (list,
|
||||
dict, string or integer). When it's being hashed (for verifying its signature or to calculate
|
||||
its key), its flattened, bencoded, form is used. It is important to use the exact
|
||||
bencoded representation as it appeared in the message. decoding and then re-encoding
|
||||
bencoded structures is not necessarily an identity operation.</p>
|
||||
<p>Storing nodes SHOULD reject <tt class="docutils literal">put</tt> requests where the bencoded form of <tt class="docutils literal">v</tt> is longer
|
||||
than 1000 bytes.</p>
|
||||
</div>
|
||||
<div class="section" id="immutable-items">
|
||||
<h1>immutable items</h1>
|
||||
<p>Immutable items are stored under their SHA-1 hash, and since they cannot be modified,
|
||||
there is no need to authenticate the origin of them. This makes immutable items simple.</p>
|
||||
<p>A node making a lookup SHOULD verify the data it receives from the network, to verify
|
||||
that its hash matches the target that was looked up.</p>
|
||||
<p>The proposed new messages <tt class="docutils literal">get</tt> and <tt class="docutils literal">put</tt> are similar to the existing
|
||||
<tt class="docutils literal">get_peers</tt> and <tt class="docutils literal">announce_peer</tt>.</p>
|
||||
<p>Responses to <tt class="docutils literal">get</tt> should always include <tt class="docutils literal">nodes</tt> and <tt class="docutils literal">nodes6</tt>. Those
|
||||
fields have the same semantics as in its <tt class="docutils literal">get_peers</tt> response. It should also
|
||||
include a write token, <tt class="docutils literal">token</tt>, with the same semantics as int <tt class="docutils literal">get_peers</tt>.
|
||||
The write token MAY be tied specifically to the key which <tt class="docutils literal">get</tt> requested.
|
||||
i.e. the <tt class="docutils literal">token</tt> can only be used to store values under that one key. It may
|
||||
also be tied to the node ID and IP address of the requesting node.</p>
|
||||
<p>The <tt class="docutils literal">id</tt> field in these messages has the same semantics as the standard DHT
|
||||
messages, i.e. the node ID of the node sending the message, to maintain the
|
||||
structure of the DHT network.</p>
|
||||
<p>The <tt class="docutils literal">token</tt> field also has the same semantics as the standard DHT message
|
||||
<tt class="docutils literal">get_peers</tt> and <tt class="docutils literal">announce_peer</tt>, when requesting an item and to write an
|
||||
item respectively.</p>
|
||||
<p>The <tt class="docutils literal">k</tt> field is the 32 byte curve25519 public key, which the signature can be
|
||||
authenticated with. When looking up a mutable item, the <tt class="docutils literal">target</tt> field MUST be
|
||||
the SHA-1 hash of this key concatenated with the <tt class="docutils literal">salt</tt>, if present.</p>
|
||||
<p>The distinction between storing mutable and immutable items is the inclusion of
|
||||
a public key, a sequence number, signature and an optional salt (<tt class="docutils literal">k</tt>, <tt class="docutils literal">seq</tt>,
|
||||
<tt class="docutils literal">sig</tt> and <tt class="docutils literal">salt</tt>).</p>
|
||||
<p><tt class="docutils literal">get</tt> requests for mutable items and immutable items cannot be distinguished
|
||||
from eachother. An implementation can either store mutable and immutable items
|
||||
in the same hash table internally, or in separate ones and potentially do two
|
||||
lookups for <tt class="docutils literal">get</tt> requests.</p>
|
||||
<p>The <tt class="docutils literal">v</tt> field is the <em>value</em> to be stored. It is allowed to be any bencoded
|
||||
type (list, dict, string or integer). When it's being hashed (for verifying its
|
||||
signature or to calculate its key), its flattened, bencoded, form is used. It is
|
||||
important to use the verbatim bencoded representation as it appeared in the
|
||||
message. decoding and then re-encoding bencoded structures is not necessarily an
|
||||
identity operation.</p>
|
||||
<p>Storing nodes MAY reject <tt class="docutils literal">put</tt> requests where the bencoded form of <tt class="docutils literal">v</tt> is
|
||||
longer than 1000 bytes. In other words, it's not safe to assume storing more
|
||||
than 1000 bytes will succeed.</p>
|
||||
<p>immutable items ---------------</p>
|
||||
<p>Immutable items are stored under their SHA-1 hash, and since they cannot be
|
||||
modified, there is no need to authenticate the origin of them. This makes
|
||||
immutable items simple.</p>
|
||||
<p>A node making a lookup SHOULD verify the data it receives from the network, to
|
||||
verify that its hash matches the target that was looked up.</p>
|
||||
<div class="section" id="put-message">
|
||||
<h2>put message</h2>
|
||||
<p>Request:</p>
|
||||
|
@ -182,17 +186,32 @@ that its hash matches the target that was looked up.</p>
|
|||
<div class="section" id="mutable-items">
|
||||
<h1>mutable items</h1>
|
||||
<p>Mutable items can be updated, without changing their DHT keys. To authenticate
|
||||
that only the original publisher can update an item, it is signed by a private key
|
||||
generated by the original publisher. The target ID mutable items are stored under
|
||||
is the SHA-1 hash of the public key (as it appears in the <tt class="docutils literal">put</tt> message).</p>
|
||||
that only the original publisher can update an item, it is signed by a private
|
||||
key generated by the original publisher. The target ID mutable items are stored
|
||||
under is the SHA-1 hash of the public key (as it appears in the <tt class="docutils literal">put</tt>
|
||||
message).</p>
|
||||
<p>In order to avoid a malicious node to overwrite the list head with an old
|
||||
version, the sequence number <tt class="docutils literal">seq</tt> must be monotonically increasing for each update,
|
||||
and a node hosting the list node MUST not downgrade a list head from a higher sequence
|
||||
number to a lower one, only upgrade. The sequence number SHOULD not exceed <tt class="docutils literal">MAX_INT64</tt>,
|
||||
(i.e. <tt class="docutils literal">0x7fffffffffffffff</tt>. A client MAY reject any message with a sequence number
|
||||
exceeding this. A client MAY also reject any message with a negative sequence number.</p>
|
||||
<p>The signature is a 64 byte curve25519 signature of the bencoded sequence
|
||||
number concatenated with the <tt class="docutils literal">v</tt> key. e.g. something like this:: <tt class="docutils literal">3:seqi4e1:v12:Hello world!</tt>.</p>
|
||||
version, the sequence number <tt class="docutils literal">seq</tt> must be monotonically increasing for each
|
||||
update, and a node hosting the list node MUST not downgrade a list head from a
|
||||
higher sequence number to a lower one, only upgrade. The sequence number SHOULD
|
||||
not exceed <tt class="docutils literal">MAX_INT64</tt>, (i.e. <tt class="docutils literal">0x7fffffffffffffff</tt>. A client MAY reject any
|
||||
message with a sequence number exceeding this. A client MAY also reject any
|
||||
message with a negative sequence number.</p>
|
||||
<p>The signature is a 64 byte curve25519 signature of the bencoded sequence number
|
||||
concatenated with the <tt class="docutils literal">v</tt> key. e.g. something like this:</p>
|
||||
<pre class="literal-block">
|
||||
3:seqi4e1:v12:Hello world!
|
||||
</pre>
|
||||
<p>If the <tt class="docutils literal">salt</tt> key is present and non-empty, the salt string must be included
|
||||
in what's signed. Note that if <tt class="docutils literal">salt</tt> is specified and an empty string, it is
|
||||
as if it was not specified and nothing in addition to the sequence number and
|
||||
the data is signed.</p>
|
||||
<p>When a salt is included in what is signed, the key <tt class="docutils literal">salt</tt> with the value of
|
||||
the key is prepended in its bencoded form. For example, if <tt class="docutils literal">salt</tt> is "foobar",
|
||||
the buffer to be signed is:</p>
|
||||
<pre class="literal-block">
|
||||
4:salt6:foobar3:seqi4e1:v12:Hello world!
|
||||
</pre>
|
||||
<div class="section" id="id1">
|
||||
<h2>put message</h2>
|
||||
<p>Request:</p>
|
||||
|
@ -203,6 +222,7 @@ number concatenated with the <tt class="docutils literal">v</tt> key. e.g. somet
|
|||
"cas": <em><optional 20 byte hash (string)></em>,
|
||||
"id": <em><20 byte id of sending node (string)></em>,
|
||||
"k": <em><curve25519 public key (32 bytes string)></em>,
|
||||
"salt": <em><optional salt to be appended to "k" when hashing (string)></em>
|
||||
"seq": <em><monotonically increasing sequence number (integer)></em>,
|
||||
"sig": <em><curve25519 signature (64 bytes string)></em>,
|
||||
"token": <em><write-token (string)></em>,
|
||||
|
@ -215,22 +235,36 @@ number concatenated with the <tt class="docutils literal">v</tt> key. e.g. somet
|
|||
</pre>
|
||||
<p>Storing nodes receiving a <tt class="docutils literal">put</tt> request where <tt class="docutils literal">seq</tt> is lower than or equal
|
||||
to what's already stored on the node, MUST reject the request. If the sequence
|
||||
number is equal, and the value is also the same, the node SHOULD reset its timeout
|
||||
counter.</p>
|
||||
number is equal, and the value is also the same, the node SHOULD reset its
|
||||
timeout counter.</p>
|
||||
<p>If the sequence number in the <tt class="docutils literal">put</tt> message is lower than the sequence number
|
||||
associated with the currently stored value, the storing node MAY return an error
|
||||
message with code 302 (see error codes below).</p>
|
||||
<p>Note that this request does not contain a target hash. The target hash under
|
||||
which this blob is stored is implied by the <tt class="docutils literal">k</tt> argument. The key is
|
||||
the SHA-1 hash of the key (<tt class="docutils literal">k</tt>).</p>
|
||||
which this blob is stored is implied by the <tt class="docutils literal">k</tt> argument. The key is the SHA-1
|
||||
hash of the key (<tt class="docutils literal">k</tt>).</p>
|
||||
<p>In order to support a single key being used to store separate items in the DHT,
|
||||
an optional <tt class="docutils literal">salt</tt> can be specified in the <tt class="docutils literal">put</tt> request of mutable items.
|
||||
If the salt entry is not present, it can be assumed to be an empty string, and
|
||||
its semantics should be identical as specifying a salt key with an empty string.
|
||||
The salt can be any binary string (but probably most conveniently a hash of
|
||||
something). This string is appended to the key, as specified in the <tt class="docutils literal">k</tt> field,
|
||||
when calculating the key to store the blob under (i.e. the key <tt class="docutils literal">get</tt> requests
|
||||
specify to retrieve this data).</p>
|
||||
<p>This lets a single entity, with a single key, publish any number of unrelated
|
||||
items, with a single key that readers can verify. This is useful if the
|
||||
publisher doesn't know ahead of time how many different items are to be
|
||||
published. It can distribute a single public key for users to authenticate the
|
||||
published blobs.</p>
|
||||
<p>The <tt class="docutils literal">cas</tt> field is optional. If present it is interpreted as the sha-1 hash of
|
||||
the sequence number and <tt class="docutils literal">v</tt> field that is expected to be replaced. The buffer
|
||||
to hash is the same as the one signed when storing. <tt class="docutils literal">cas</tt> is short for <em>compare
|
||||
and swap</em>, it has similar semantics as CAS CPU instructions. If specified as part
|
||||
of the put command, and the current value stored under the public key differs from
|
||||
the expected value, the store fails. The <tt class="docutils literal">cas</tt> field only applies to mutable puts.
|
||||
If there is no current value, the <tt class="docutils literal">cas</tt> field SHOULD be ignored, not preventing
|
||||
the put based on it.</p>
|
||||
the sequence number, <tt class="docutils literal">v</tt> field and possibly the <tt class="docutils literal">salt</tt> field, that is
|
||||
expected to be replaced. The buffer to hash is the same as the one signed when
|
||||
storing. <tt class="docutils literal">cas</tt> is short for <em>compare and swap</em>, it has similar semantics as
|
||||
CAS CPU instructions. If specified as part of the put command, and the current
|
||||
value stored under the public key differs from the expected value, the store
|
||||
fails. The <tt class="docutils literal">cas</tt> field only applies to mutable puts. If there is no current
|
||||
value, the <tt class="docutils literal">cas</tt> field SHOULD be ignored. A put operation should not be
|
||||
prevented based on the <tt class="docutils literal">cas</tt> field if no value is currently present.</p>
|
||||
<p>Response:</p>
|
||||
<pre class="literal-block">
|
||||
{
|
||||
|
@ -239,11 +273,13 @@ the put based on it.</p>
|
|||
"y": "r",
|
||||
}
|
||||
</pre>
|
||||
<p>If the store fails for any reason an error message is returned instead of the message
|
||||
template above, i.e. one where "y" is "e" and "e" is a tuple of [error-code, message]).
|
||||
Failures include where the <tt class="docutils literal">cas</tt> hash mismatches and the sequence number is outdated.</p>
|
||||
<p>If no <tt class="docutils literal">cas</tt> field is included in the <tt class="docutils literal">put</tt> message, the value of the current <tt class="docutils literal">v</tt>
|
||||
field should be disregarded when determining whether or not to save the item.</p>
|
||||
<p>If the store fails for any reason an error message is returned instead of the
|
||||
message template above, i.e. one where "y" is "e" and "e" is a tuple of
|
||||
[error-code, message]). Failures include where the <tt class="docutils literal">cas</tt> hash mismatches and
|
||||
the sequence number is outdated.</p>
|
||||
<p>If no <tt class="docutils literal">cas</tt> field is included in the <tt class="docutils literal">put</tt> message, the value of the current
|
||||
<tt class="docutils literal">v</tt> field should be disregarded when determining whether or not to save the
|
||||
item. (However, the signature, sequence number obviously still should).</p>
|
||||
<p>The error message (as specified by <a class="reference external" href="http://www.bittorrent.org/beps/bep_0005.html">BEP5</a>) looks like this:</p>
|
||||
<pre class="literal-block">
|
||||
{
|
||||
|
@ -283,8 +319,9 @@ current.</td>
|
|||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>An implementation MUST emit 301 errors if the cas-hash mismatches. This is
|
||||
a critical feature in synchronization of multiple agents sharing an immutable item.</p>
|
||||
<p>An implementation MUST emit 301 errors if the cas-hash mismatches. This is a
|
||||
critical feature in synchronization of multiple agents sharing an immutable
|
||||
item.</p>
|
||||
</div>
|
||||
<div class="section" id="id2">
|
||||
<h2>get message</h2>
|
||||
|
@ -294,7 +331,7 @@ a critical feature in synchronization of multiple agents sharing an immutable it
|
|||
"a":
|
||||
{
|
||||
"id": <em><20 byte id of sending node (string)></em>,
|
||||
"target:" <em><20 byte SHA-1 hash of public key (string)></em>
|
||||
"target:" <em><20 byte SHA-1 hash of public key and salt (string)></em>
|
||||
},
|
||||
"t": <em><transaction-id (string)></em>,
|
||||
"y": "q",
|
||||
|
@ -310,6 +347,7 @@ a critical feature in synchronization of multiple agents sharing an immutable it
|
|||
"k": <em><curve25519 public key (32 bytes string)></em>,
|
||||
"nodes": <em><IPv4 nodes close to 'target'></em>,
|
||||
"nodes6": <em><IPv6 nodes close to 'target'></em>,
|
||||
"salt": <em><optional salt to be appended to "k" when hashing (string)></em>
|
||||
"seq": <em><monotonically increasing sequence number (integer)></em>,
|
||||
"sig": <em><curve25519 signature (64 bytes string)></em>,
|
||||
"token": <em><write-token (string)></em>,
|
||||
|
@ -323,33 +361,65 @@ a critical feature in synchronization of multiple agents sharing an immutable it
|
|||
</div>
|
||||
<div class="section" id="signature-verification">
|
||||
<h1>signature verification</h1>
|
||||
<p>The signature, private and public keys are in the format as produced by this derivative <a class="reference external" href="https://github.com/nightcracker/ed25519">ed25519 library</a>.</p>
|
||||
<p>In order to make it maximally difficult to attack the bencoding parser, signing and verification of the
|
||||
value and sequence number should be done as follows:</p>
|
||||
<p>In order to make it maximally difficult to attack the bencoding parser, signing
|
||||
and verification of the value and sequence number should be done as follows:</p>
|
||||
<ol class="arabic simple">
|
||||
<li>encode value and sequence number separately</li>
|
||||
<li>concatenate <em>"3:seqi"</em> <tt class="docutils literal">seq</tt> <em>"e1:v"</em> <tt class="docutils literal">len</tt> <em>":"</em> and the encoded value.
|
||||
sequence number 1 of value "Hello World!" would be converted to: "3:seqi1e1:v12:Hello World!"
|
||||
In this way it is not possible to convince a node that part of the length is actually part of the
|
||||
sequence number even if the parser contains certain bugs. Furthermore it is not possible to have a
|
||||
verification failure if a bencoding serializer alters the order of entries in the dictionary.</li>
|
||||
<li>concatenate ("4:salt" <em>length-of-salt</em> ":" <em>salt</em>) "3:seqi" <em>seq</em>
|
||||
"e1:v" <em>len</em> ":" and the encoded value.
|
||||
sequence number 1 of value "Hello World!" would be converted to:
|
||||
"3:seqi1e1:v12:Hello World!". In this way it is not possible to convince a
|
||||
node that part of the length is actually part of the sequence number even if
|
||||
the parser contains certain bugs. Furthermore it is not possible to have a
|
||||
verification failure if a bencoding serializer alters the order of entries in
|
||||
the dictionary. The salt is in parenthesis because it is optional. It is only
|
||||
prepended if a non-empty salt is specified in the <tt class="docutils literal">put</tt> request.</li>
|
||||
<li>sign or verify the concatenated string</li>
|
||||
</ol>
|
||||
<p>On the storage node, the signature MUST be verified before accepting the store command. The data
|
||||
MUST be stored under the SHA-1 hash of the public key (as it appears in the bencoded dict).</p>
|
||||
<p>On the requesting nodes, the key they get back from a <tt class="docutils literal">get</tt> request MUST be verified to hash
|
||||
to the target ID the lookup was made for, as well as verifying the signature. If any of these fail,
|
||||
the response SHOULD be considered invalid.</p>
|
||||
<p>On the storage node, the signature MUST be verified before accepting the store
|
||||
command. The data MUST be stored under the SHA-1 hash of the public key (as it
|
||||
appears in the bencoded dict).</p>
|
||||
<p>On the requesting nodes, the key they get back from a <tt class="docutils literal">get</tt> request MUST be
|
||||
verified to hash to the target ID the lookup was made for, as well as verifying
|
||||
the signature. If any of these fail, the response SHOULD be considered invalid.</p>
|
||||
</div>
|
||||
<div class="section" id="expiration">
|
||||
<h1>expiration</h1>
|
||||
<p>Without re-announcement, these items MAY expire in 2 hours. In order
|
||||
to keep items alive, they SHOULD be re-announced once an hour.</p>
|
||||
<p>Any node that's interested in keeping a blob in the DHT alive may announce it. It would simply
|
||||
repeat the signature for a mutable put without having the private key.</p>
|
||||
<p>Any node that's interested in keeping a blob in the DHT alive may announce it.
|
||||
It would simply repeat the signature for a mutable put without having the
|
||||
private key.</p>
|
||||
</div>
|
||||
<div class="section" id="test-vectors">
|
||||
<h1>test vectors</h1>
|
||||
<div class="section" id="test-vector">
|
||||
<h1>test vector</h1>
|
||||
<p>The buffer being signed:</p>
|
||||
<pre class="literal-block">
|
||||
3:seqi1e1:v12:Hello World!
|
||||
</pre>
|
||||
<p>public key:</p>
|
||||
<pre class="literal-block">
|
||||
77ff84905a91936367c01360803104f92432fcd904a43511876df5cdf3e7e548
|
||||
</pre>
|
||||
<p>private key:</p>
|
||||
<pre class="literal-block">
|
||||
e06d3183d14159228433ed599221b80bd0a5ce8352e4bdf0262f76786ef1c74d
|
||||
b7e7a9fea2c0eb269d61e3b38e450a22e754941ac78479d6c54e1faf6037881d
|
||||
</pre>
|
||||
<p>signature:</p>
|
||||
<pre class="literal-block">
|
||||
305ac8aeb6c9c151fa120f120ea2cfb923564e11552d06a5d856091e5e853cff
|
||||
1260d3f39e4999684aa92eb73ffd136e6f4f3ecbfda0ce53a1608ecd7ae21f01
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section" id="resources">
|
||||
<h1>resources</h1>
|
||||
<p>Libraries that implement curve25519 DSA:</p>
|
||||
<ul class="simple">
|
||||
<li><a class="reference external" href="http://nacl.cr.yp.to/">NaCl</a></li>
|
||||
<li><a class="reference external" href="https://github.com/jedisct1/libsodium">libsodium</a></li>
|
||||
<li><a class="reference external" href="https://github.com/nightcracker/ed25519">nightcracker's ed25519</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div id="footer">
|
||||
|
|
|
@ -55,17 +55,17 @@
|
|||
<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="id54">overview</a></li>
|
||||
<li><a class="reference internal" href="#things-to-keep-in-mind" id="id55">things to keep in mind</a></li>
|
||||
<li><a class="reference internal" href="#network-primitives" id="id56">network primitives</a></li>
|
||||
<li><a class="reference internal" href="#exceptions" id="id57">exceptions</a></li>
|
||||
<li><a class="reference internal" href="#magnet-links" id="id58">magnet links</a></li>
|
||||
<li><a class="reference internal" href="#queuing" id="id59">queuing</a></li>
|
||||
<li><a class="reference internal" href="#fast-resume" id="id60">fast resume</a></li>
|
||||
<li><a class="reference internal" href="#storage-allocation" id="id61">storage allocation</a></li>
|
||||
<li><a class="reference internal" href="#extensions" id="id62">extensions</a></li>
|
||||
<li><a class="reference internal" href="#piece-picker" id="id63">piece picker</a></li>
|
||||
<li><a class="reference internal" href="#ssl-torrents" id="id64">SSL torrents</a></li>
|
||||
<li><a class="reference internal" href="#overview" id="id52">overview</a></li>
|
||||
<li><a class="reference internal" href="#things-to-keep-in-mind" id="id53">things to keep in mind</a></li>
|
||||
<li><a class="reference internal" href="#network-primitives" id="id54">network primitives</a></li>
|
||||
<li><a class="reference internal" href="#exceptions" id="id55">exceptions</a></li>
|
||||
<li><a class="reference internal" href="#magnet-links" id="id56">magnet links</a></li>
|
||||
<li><a class="reference internal" href="#queuing" id="id57">queuing</a></li>
|
||||
<li><a class="reference internal" href="#fast-resume" id="id58">fast resume</a></li>
|
||||
<li><a class="reference internal" href="#storage-allocation" id="id59">storage allocation</a></li>
|
||||
<li><a class="reference internal" href="#extensions" id="id60">extensions</a></li>
|
||||
<li><a class="reference internal" href="#piece-picker" id="id61">piece picker</a></li>
|
||||
<li><a class="reference internal" href="#ssl-torrents" id="id62">SSL torrents</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="overview">
|
||||
|
@ -80,9 +80,11 @@ the <tt class="docutils literal">session</tt>, it contains the main loop that se
|
|||
</li>
|
||||
<li><p class="first">start extensions (see <a class="reference external" href="reference-Core.html#add_extension()">add_extension()</a>).</p>
|
||||
</li>
|
||||
<li><p class="first">start DHT, LSD, UPnP, NAT-PMP etc (see <a class="reference external" href="reference-Session.html#start_dht()">start_dht()</a>, <a class="reference external" href="reference-Session.html#start_lsd()">start_lsd()</a>, <a class="reference external" href="reference-Session.html#start_upnp()">start_upnp()</a> and <a class="reference external" href="reference-Session.html#start_natpmp()">start_natpmp()</a>).</p>
|
||||
<li><p class="first">start DHT, LSD, UPnP, NAT-PMP etc (see <a class="reference external" href="reference-Session.html#start_dht()">start_dht()</a>, <a class="reference external" href="reference-Session.html#start_lsd()">start_lsd()</a>, <a class="reference external" href="reference-Session.html#start_upnp()">start_upnp()</a>
|
||||
and <a class="reference external" href="reference-Session.html#start_natpmp()">start_natpmp()</a>).</p>
|
||||
</li>
|
||||
<li><p class="first">parse .torrent-files and add them to the <a class="reference external" href="reference-Session.html#session">session</a> (see <a class="reference external" href="reference-Core.html#torrent_info">torrent_info</a>, <a class="reference external" href="reference-Session.html#async_add_torrent()">async_add_torrent()</a> and <a class="reference external" href="reference-Session.html#add_torrent()">add_torrent()</a>)</p>
|
||||
<li><p class="first">parse .torrent-files and add them to the <a class="reference external" href="reference-Session.html#session">session</a> (see <a class="reference external" href="reference-Core.html#torrent_info">torrent_info</a>,
|
||||
<a class="reference external" href="reference-Session.html#async_add_torrent()">async_add_torrent()</a> and <a class="reference external" href="reference-Session.html#add_torrent()">add_torrent()</a>)</p>
|
||||
</li>
|
||||
<li><p class="first">main loop (see <a class="reference external" href="reference-Session.html#session">session</a>)</p>
|
||||
<blockquote>
|
||||
|
@ -219,42 +221,45 @@ download, without any .torrent file.</p>
|
|||
<p>libtorrent supports <em>queuing</em>. Which means it makes sure that a limited number of
|
||||
torrents are being downloaded at any given time, and once a torrent is completely
|
||||
downloaded, the next in line is started.</p>
|
||||
<p>Torrents that are <em>auto managed</em> are subject to the queuing and the active torrents
|
||||
limits. To make a torrent auto managed, set <tt class="docutils literal">auto_managed</tt> to true when adding the
|
||||
torrent (see <a class="reference external" href="reference-Session.html#async_add_torrent()">async_add_torrent()</a> and <a class="reference external" href="reference-Session.html#add_torrent()">add_torrent()</a>).</p>
|
||||
<p>Torrents that are <em>auto managed</em> are subject to the queuing and the active
|
||||
torrents limits. To make a torrent auto managed, set <tt class="docutils literal">auto_managed</tt> to true
|
||||
when adding the torrent (see <a class="reference external" href="reference-Session.html#async_add_torrent()">async_add_torrent()</a> and <a class="reference external" href="reference-Session.html#add_torrent()">add_torrent()</a>).</p>
|
||||
<p>The limits of the number of downloading and seeding torrents are controlled via
|
||||
<tt class="docutils literal">active_downloads</tt>, <tt class="docutils literal">active_seeds</tt> and <tt class="docutils literal">active_limit</tt> in <a class="reference external" href="reference-Settings.html#session_settings">session_settings</a>.
|
||||
These limits takes non auto managed torrents into account as well. If there are
|
||||
more non-auto managed torrents being downloaded than the <tt class="docutils literal">active_downloads</tt>
|
||||
setting, any auto managed torrents will be queued until torrents are removed so
|
||||
that the number drops below the limit.</p>
|
||||
<tt class="docutils literal">active_downloads</tt>, <tt class="docutils literal">active_seeds</tt> and <tt class="docutils literal">active_limit</tt> in
|
||||
<a class="reference external" href="reference-Settings.html#session_settings">session_settings</a>. These limits takes non auto managed torrents into account as
|
||||
well. If there are more non-auto managed torrents being downloaded than the
|
||||
<tt class="docutils literal">active_downloads</tt> setting, any auto managed torrents will be queued until
|
||||
torrents are removed so that the number drops below the limit.</p>
|
||||
<p>The default values are 8 active downloads and 5 active seeds.</p>
|
||||
<p>At a regular interval, torrents are checked if there needs to be any re-ordering of
|
||||
which torrents are active and which are queued. This interval can be controlled via
|
||||
<tt class="docutils literal">auto_manage_interval</tt> in <a class="reference external" href="reference-Settings.html#session_settings">session_settings</a>. It defaults to every 30 seconds.</p>
|
||||
<p>For queuing to work, resume data needs to be saved and restored for all torrents.
|
||||
See <a class="reference external" href="reference-Core.html#save_resume_data()">save_resume_data()</a>.</p>
|
||||
<p>At a regular interval, torrents are checked if there needs to be any
|
||||
re-ordering of which torrents are active and which are queued. This interval
|
||||
can be controlled via <tt class="docutils literal">auto_manage_interval</tt> in <a class="reference external" href="reference-Settings.html#session_settings">session_settings</a>. It defaults
|
||||
to every 30 seconds.</p>
|
||||
<p>For queuing to work, resume data needs to be saved and restored for all
|
||||
torrents. See <a class="reference external" href="reference-Core.html#save_resume_data()">save_resume_data()</a>.</p>
|
||||
<div class="section" id="downloading">
|
||||
<h2>downloading</h2>
|
||||
<p>Torrents that are currently being downloaded or incomplete (with bytes still to download)
|
||||
are queued. The torrents in the front of the queue are started to be actively downloaded
|
||||
and the rest are ordered with regards to their queue position. Any newly added torrent
|
||||
is placed at the end of the queue. Once a torrent is removed or turns into a seed, its
|
||||
queue position is -1 and all torrents that used to be after it in the queue, decreases their
|
||||
position in order to fill the gap.</p>
|
||||
<p>Torrents that are currently being downloaded or incomplete (with bytes still to
|
||||
download) are queued. The torrents in the front of the queue are started to be
|
||||
actively downloaded and the rest are ordered with regards to their queue
|
||||
position. Any newly added torrent is placed at the end of the queue. Once a
|
||||
torrent is removed or turns into a seed, its queue position is -1 and all
|
||||
torrents that used to be after it in the queue, decreases their position in
|
||||
order to fill the gap.</p>
|
||||
<p>The queue positions are always in a sequence without any gaps.</p>
|
||||
<p>Lower queue position means closer to the front of the queue, and will be started sooner than
|
||||
torrents with higher queue positions.</p>
|
||||
<p>Lower queue position means closer to the front of the queue, and will be
|
||||
started sooner than torrents with higher queue positions.</p>
|
||||
<p>To query a torrent for its position in the queue, or change its position, see:
|
||||
<a class="reference external" href="reference-Core.html#queue_position()">queue_position()</a>, <a class="reference external" href="reference-Core.html#queue_position_up()">queue_position_up()</a>, <a class="reference external" href="reference-Core.html#queue_position_down()">queue_position_down()</a>, <a class="reference external" href="reference-Core.html#queue_position_top()">queue_position_top()</a> and <a class="reference external" href="reference-Core.html#queue_position_bottom()">queue_position_bottom()</a>.</p>
|
||||
<a class="reference external" href="reference-Core.html#queue_position()">queue_position()</a>, <a class="reference external" href="reference-Core.html#queue_position_up()">queue_position_up()</a>, <a class="reference external" href="reference-Core.html#queue_position_down()">queue_position_down()</a>,
|
||||
<a class="reference external" href="reference-Core.html#queue_position_top()">queue_position_top()</a> and <a class="reference external" href="reference-Core.html#queue_position_bottom()">queue_position_bottom()</a>.</p>
|
||||
</div>
|
||||
<div class="section" id="seeding">
|
||||
<h2>seeding</h2>
|
||||
<p>Auto managed seeding torrents are rotated, so that all of them are allocated a fair
|
||||
amount of seeding. Torrents with fewer completed <em>seed cycles</em> are prioritized for
|
||||
seeding. A seed cycle is completed when a torrent meets either the share ratio limit
|
||||
(uploaded bytes / downloaded bytes), the share time ratio (time seeding / time
|
||||
downloaing) or seed time limit (time seeded).</p>
|
||||
<p>Auto managed seeding torrents are rotated, so that all of them are allocated a
|
||||
fair amount of seeding. Torrents with fewer completed <em>seed cycles</em> are
|
||||
prioritized for seeding. A seed cycle is completed when a torrent meets either
|
||||
the share ratio limit (uploaded bytes / downloaded bytes), the share time ratio
|
||||
(time seeding / time downloaing) or seed time limit (time seeded).</p>
|
||||
<p>The relevant settings to control these limits are <tt class="docutils literal">share_ratio_limit</tt>,
|
||||
<tt class="docutils literal">seed_time_ratio_limit</tt> and <tt class="docutils literal">seed_time_limit</tt> in <a class="reference external" href="reference-Settings.html#session_settings">session_settings</a>.</p>
|
||||
</div>
|
||||
|
@ -269,10 +274,11 @@ will not check the piece hashes then, and rely on the information given in the
|
|||
fast-resume data. The fast-resume data also contains information about which
|
||||
blocks, in the unfinished pieces, were downloaded, so it will not have to
|
||||
start from scratch on the partially downloaded pieces.</p>
|
||||
<p>To use the fast-resume data you simply give it to <a class="reference external" href="reference-Session.html#async_add_torrent()">async_add_torrent()</a> and <a class="reference external" href="reference-Session.html#add_torrent()">add_torrent()</a>, and it
|
||||
will skip the time consuming checks. It may have to do the checking anyway, if
|
||||
the fast-resume data is corrupt or doesn't fit the storage for that torrent,
|
||||
then it will not trust the fast-resume data and just do the checking.</p>
|
||||
<p>To use the fast-resume data you simply give it to <a class="reference external" href="reference-Session.html#async_add_torrent()">async_add_torrent()</a> and
|
||||
<a class="reference external" href="reference-Session.html#add_torrent()">add_torrent()</a>, and it will skip the time consuming checks. It may have to do
|
||||
the checking anyway, if the fast-resume data is corrupt or doesn't fit the
|
||||
storage for that torrent, then it will not trust the fast-resume data and just
|
||||
do the checking.</p>
|
||||
<div class="section" id="file-format">
|
||||
<h2>file format</h2>
|
||||
<p>The file format is a bencoded dictionary containing the following fields:</p>
|
||||
|
@ -479,30 +485,28 @@ last resume data checkpoint.</td>
|
|||
<h1>storage allocation</h1>
|
||||
<p>There are two modes in which storage (files on disk) are allocated in libtorrent.</p>
|
||||
<ol class="arabic simple">
|
||||
<li>The traditional <em>full allocation</em> mode, where the entire files are filled up with
|
||||
zeros before anything is downloaded. libtorrent will look for sparse files support
|
||||
in the filesystem that is used for storage, and use sparse files or file system
|
||||
zero fill support if present. This means that on NTFS, full allocation mode will
|
||||
only allocate storage for the downloaded pieces.</li>
|
||||
<li>The <em>sparse allocation</em>, sparse files are used, and pieces are downloaded directly
|
||||
to where they belong. This is the recommended (and default) mode.</li>
|
||||
<li>The traditional <em>full allocation</em> mode, where the entire files are filled up
|
||||
with zeros before anything is downloaded. Files are allocated on demand, the
|
||||
first time anything is written to them. The main benefit of this mode is that
|
||||
it avoids creating heavily fragmented files.</li>
|
||||
<li>The <em>sparse allocation</em>, sparse files are used, and pieces are downloaded
|
||||
directly to where they belong. This is the recommended (and default) mode.</li>
|
||||
</ol>
|
||||
<p>In previous versions of libtorrent, a 3rd mode was supported, <em>compact allocation</em>.
|
||||
Support for this is deprecated and will be removed in future versions of libtorrent.
|
||||
It's still described in here for completeness.</p>
|
||||
<p>In previous versions of libtorrent, a 3rd mode was supported, <em>compact
|
||||
allocation</em>. Support for this is deprecated and will be removed in future
|
||||
versions of libtorrent. It's still described in here for completeness.</p>
|
||||
<p>The allocation mode is selected when a torrent is started. It is passed as an
|
||||
argument to <a class="reference external" href="reference-Session.html#add_torrent()">session::add_torrent()</a> or <a class="reference external" href="reference-Session.html#async_add_torrent()">session::async_add_torrent()</a>.</p>
|
||||
<p>The decision to use full allocation or compact allocation typically depends on whether
|
||||
any files have priority 0 and if the filesystem supports sparse files.</p>
|
||||
<p>The decision to use full allocation or compact allocation typically depends on
|
||||
whether any files have priority 0 and if the filesystem supports sparse files.</p>
|
||||
<div class="section" id="sparse-allocation">
|
||||
<h2>sparse allocation</h2>
|
||||
<p>On filesystems that supports sparse files, this allocation mode will only use
|
||||
as much space as has been downloaded.</p>
|
||||
<p>The main drawback of this mode is that it may create heavily fragmented files.</p>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li>It does not require an allocation pass on startup.</li>
|
||||
<li>It supports skipping files (setting prioirty to 0 to not download).</li>
|
||||
<li>Fast resume data will remain valid even when file time stamps are out of date.</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
</div>
|
||||
|
@ -510,31 +514,25 @@ as much space as has been downloaded.</p>
|
|||
<h2>full allocation</h2>
|
||||
<p>When a torrent is started in full allocation mode, the disk-io thread
|
||||
will make sure that the entire storage is allocated, and fill any gaps with zeros.
|
||||
This will be skipped if the filesystem supports sparse files or automatic zero filling.
|
||||
It will of course still check for existing pieces and fast resume data. The main
|
||||
drawbacks of this mode are:</p>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li>It may take longer to start the torrent, since it will need to fill the files
|
||||
with zeros on some systems. This delay is linearly dependent on the size of
|
||||
the download.</li>
|
||||
<li>The download may occupy unnecessary disk space between download sessions. In case
|
||||
sparse files are not supported.</li>
|
||||
<li>Disk caches usually perform extremely poorly with random access to large files
|
||||
and may slow down a download considerably.</li>
|
||||
with zeroes. This delay is linear to the size of the download.</li>
|
||||
<li>The download may occupy unnecessary disk space between download sessions.</li>
|
||||
<li>Disk caches usually perform poorly with random access to large files
|
||||
and may slow down the download some.</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<p>The benefits of this mode are:</p>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li>Downloaded pieces are written directly to their final place in the files and the
|
||||
total number of disk operations will be fewer and may also play nicer to
|
||||
<li>Downloaded pieces are written directly to their final place in the files and
|
||||
the total number of disk operations will be fewer and may also play nicer to
|
||||
filesystems' file allocation, and reduce fragmentation.</li>
|
||||
<li>No risk of a download failing because of a full disk during download. Unless
|
||||
sparse files are being used.</li>
|
||||
<li>The fast resume data will be more likely to be usable, regardless of crashes or
|
||||
out of date data, since pieces won't move around.</li>
|
||||
<li>Can be used with prioritizing files to 0.</li>
|
||||
<li>No risk of a download failing because of a full disk during download, once
|
||||
all files have been created.</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
</div>
|
||||
|
@ -545,10 +543,11 @@ out of date data, since pieces won't move around.</li>
|
|||
<p class="last">Note that support for compact allocation is deprecated in libttorrent, and will
|
||||
be removed in future versions.</p>
|
||||
</div>
|
||||
<p>The compact allocation will only allocate as much storage as it needs to keep the
|
||||
pieces downloaded so far. This means that pieces will be moved around to be placed
|
||||
at their final position in the files while downloading (to make sure the completed
|
||||
download has all its pieces in the correct place). So, the main drawbacks are:</p>
|
||||
<p>The compact allocation will only allocate as much storage as it needs to keep
|
||||
the pieces downloaded so far. This means that pieces will be moved around to be
|
||||
placed at their final position in the files while downloading (to make sure the
|
||||
completed download has all its pieces in the correct place). So, the main
|
||||
drawbacks are:</p>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li>More disk operations while downloading since pieces are moved around.</li>
|
||||
|
@ -561,13 +560,13 @@ download has all its pieces in the correct place). So, the main drawbacks are:</
|
|||
<ul class="simple">
|
||||
<li>No startup delay, since the files don't need allocating.</li>
|
||||
<li>The download will not use unnecessary disk space.</li>
|
||||
<li>Disk caches perform much better than in full allocation and raises the download
|
||||
speed limit imposed by the disk.</li>
|
||||
<li>Disk caches perform much better than in full allocation and raises the
|
||||
download speed limit imposed by the disk.</li>
|
||||
<li>Works well on filesystems that don't support sparse files.</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<p>The algorithm that is used when allocating pieces and slots isn't very complicated.
|
||||
For the interested, a description follows.</p>
|
||||
<p>The algorithm that is used when allocating pieces and slots isn't very
|
||||
complicated. For the interested, a description follows.</p>
|
||||
<p>storing a piece:</p>
|
||||
<ol class="arabic simple">
|
||||
<li>let <strong>A</strong> be a newly downloaded piece, with index <strong>n</strong>.</li>
|
||||
|
@ -594,10 +593,10 @@ contain any piece), return that slot index.</li>
|
|||
</div>
|
||||
<div class="section" id="extensions">
|
||||
<h1>extensions</h1>
|
||||
<p>These extensions all operates within the <a class="reference external" href="extension_protocol.html">extension protocol</a>. The
|
||||
name of the extension is the name used in the extension-list packets,
|
||||
and the payload is the data in the extended message (not counting the
|
||||
length-prefix, message-id nor extension-id).</p>
|
||||
<p>These extensions all operates within the <a class="reference external" href="extension_protocol.html">extension protocol</a>. The name of the
|
||||
extension is the name used in the extension-list packets, and the payload is
|
||||
the data in the extended message (not counting the length-prefix, message-id
|
||||
nor extension-id).</p>
|
||||
<p>Note that since this protocol relies on one of the reserved bits in the
|
||||
handshake, it may be incompatible with future versions of the mainline
|
||||
bittorrent client.</p>
|
||||
|
@ -605,16 +604,16 @@ bittorrent client.</p>
|
|||
<div class="section" id="metadata-from-peers">
|
||||
<h2>metadata from peers</h2>
|
||||
<p>Extension name: "LT_metadata"</p>
|
||||
<p>This extension is deprecated in favor of the more widely supported <tt class="docutils literal">ut_metadata</tt>
|
||||
extension, see <a class="reference external" href="http://bittorrent.org/beps/bep_0009.html">BEP 9</a>.
|
||||
The point with this extension is that you don't have to distribute the
|
||||
metadata (.torrent-file) separately. The metadata can be distributed
|
||||
through the bittorrent swarm. The only thing you need to download such
|
||||
a torrent is the tracker url and the info-hash of the torrent.</p>
|
||||
<p>It works by assuming that the initial seeder has the metadata and that
|
||||
the metadata will propagate through the network as more peers join.</p>
|
||||
<p>There are three kinds of messages in the metadata extension. These packets
|
||||
are put as payload to the extension message. The three packets are:</p>
|
||||
<p>This extension is deprecated in favor of the more widely supported
|
||||
<tt class="docutils literal">ut_metadata</tt> extension, see <a class="reference external" href="http://bittorrent.org/beps/bep_0009.html">BEP 9</a>. The point with this extension is that
|
||||
you don't have to distribute the metadata (.torrent-file) separately. The
|
||||
metadata can be distributed through the bittorrent swarm. The only thing you
|
||||
need to download such a torrent is the tracker url and the info-hash of the
|
||||
torrent.</p>
|
||||
<p>It works by assuming that the initial seeder has the metadata and that the
|
||||
metadata will propagate through the network as more peers join.</p>
|
||||
<p>There are three kinds of messages in the metadata extension. These packets are
|
||||
put as payload to the extension message. The three packets are:</p>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li>request metadata</li>
|
||||
|
@ -726,12 +725,13 @@ doesn't have any metadata.</td>
|
|||
<div class="section" id="dont-have">
|
||||
<h2>dont_have</h2>
|
||||
<p>Extension name: "lt_dont_have"</p>
|
||||
<p>The <tt class="docutils literal">dont_have</tt> extension message is used to tell peers that the client no longer
|
||||
has a specific piece. The extension message should be advertised in the <tt class="docutils literal">m</tt> dictionary
|
||||
as <tt class="docutils literal">lt_dont_have</tt>. The message format mimics the regular <tt class="docutils literal">HAVE</tt> bittorrent message.</p>
|
||||
<p>Just like all extension messages, the first 2 bytes in the mssage itself are 20 (the
|
||||
bittorrent extension message) and the message ID assigned to this extension in the <tt class="docutils literal">m</tt>
|
||||
dictionary in the handshake.</p>
|
||||
<p>The <tt class="docutils literal">dont_have</tt> extension message is used to tell peers that the client no
|
||||
longer has a specific piece. The extension message should be advertised in the
|
||||
<tt class="docutils literal">m</tt> dictionary as <tt class="docutils literal">lt_dont_have</tt>. The message format mimics the regular
|
||||
<tt class="docutils literal">HAVE</tt> bittorrent message.</p>
|
||||
<p>Just like all extension messages, the first 2 bytes in the mssage itself are 20
|
||||
(the bittorrent extension message) and the message ID assigned to this
|
||||
extension in the <tt class="docutils literal">m</tt> dictionary in the handshake.</p>
|
||||
<table border="1" class="docutils">
|
||||
<colgroup>
|
||||
<col width="17%" />
|
||||
|
@ -752,24 +752,24 @@ has.</td>
|
|||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>The length of this message (including the extension message prefix) is
|
||||
6 bytes, i.e. one byte longer than the normal <tt class="docutils literal">HAVE</tt> message, because
|
||||
of the extension message wrapping.</p>
|
||||
<p>The length of this message (including the extension message prefix) is 6 bytes,
|
||||
i.e. one byte longer than the normal <tt class="docutils literal">HAVE</tt> message, because of the extension
|
||||
message wrapping.</p>
|
||||
</div>
|
||||
<div class="section" id="http-seeding">
|
||||
<h2>HTTP seeding</h2>
|
||||
<p>There are two kinds of HTTP seeding. One with that assumes a smart
|
||||
(and polite) client and one that assumes a smart server. These
|
||||
are specified in <a class="reference external" href="http://bittorrent.org/beps/bep_0019.html">BEP 19</a> and <a class="reference external" href="http://bittorrent.org/beps/bep_0017.html">BEP 17</a> respectively.</p>
|
||||
<p>libtorrent supports both. In the libtorrent source code and API,
|
||||
BEP 19 urls are typically referred to as <em>url seeds</em> and BEP 17
|
||||
urls are typically referred to as <em>HTTP seeds</em>.</p>
|
||||
<p>The libtorrent implementation of <a class="reference external" href="http://bittorrent.org/beps/bep_0019.html">BEP 19</a> assumes that, if the URL ends with a slash
|
||||
('/'), the filename should be appended to it in order to request pieces from
|
||||
that file. The way this works is that if the torrent is a single-file torrent,
|
||||
only that filename is appended. If the torrent is a multi-file torrent, the
|
||||
torrent's name '/' the file name is appended. This is the same directory
|
||||
structure that libtorrent will download torrents into.</p>
|
||||
<p>There are two kinds of HTTP seeding. One with that assumes a smart (and polite)
|
||||
client and one that assumes a smart server. These are specified in <a class="reference external" href="http://bittorrent.org/beps/bep_0019.html">BEP 19</a>
|
||||
and <a class="reference external" href="http://bittorrent.org/beps/bep_0017.html">BEP 17</a> respectively.</p>
|
||||
<p>libtorrent supports both. In the libtorrent source code and API, BEP 19 urls
|
||||
are typically referred to as <em>url seeds</em> and BEP 17 urls are typically referred
|
||||
to as <em>HTTP seeds</em>.</p>
|
||||
<p>The libtorrent implementation of <a class="reference external" href="http://bittorrent.org/beps/bep_0019.html">BEP 19</a> assumes that, if the URL ends with a
|
||||
slash ('/'), the filename should be appended to it in order to request pieces
|
||||
from that file. The way this works is that if the torrent is a single-file
|
||||
torrent, only that filename is appended. If the torrent is a multi-file
|
||||
torrent, the torrent's name '/' the file name is appended. This is the same
|
||||
directory structure that libtorrent will download torrents into.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="piece-picker">
|
||||
|
@ -788,64 +788,60 @@ structure that libtorrent will download torrents into.</p>
|
|||
</ul>
|
||||
<div class="section" id="internal-representation">
|
||||
<h2>internal representation</h2>
|
||||
<p>It is optimized by, at all times, keeping a list of pieces ordered
|
||||
by rarity, randomly shuffled within each rarity class. This list
|
||||
is organized as a single vector of contigous memory in RAM, for
|
||||
optimal memory locality and to eliminate heap allocations and frees
|
||||
when updating rarity of pieces.</p>
|
||||
<p>Expensive events, like a peer joining or leaving, are evaluated
|
||||
lazily, since it's cheaper to rebuild the whole list rather than
|
||||
updating every single piece in it. This means as long as no blocks
|
||||
are picked, peers joining and leaving is no more costly than a single
|
||||
peer joining or leaving. Of course the special cases of peers that have
|
||||
all or no pieces are optimized to not require rebuilding the list.</p>
|
||||
<p>It is optimized by, at all times, keeping a list of pieces ordered by rarity,
|
||||
randomly shuffled within each rarity class. This list is organized as a single
|
||||
vector of contigous memory in RAM, for optimal memory locality and to eliminate
|
||||
heap allocations and frees when updating rarity of pieces.</p>
|
||||
<p>Expensive events, like a peer joining or leaving, are evaluated lazily, since
|
||||
it's cheaper to rebuild the whole list rather than updating every single piece
|
||||
in it. This means as long as no blocks are picked, peers joining and leaving is
|
||||
no more costly than a single peer joining or leaving. Of course the special
|
||||
cases of peers that have all or no pieces are optimized to not require
|
||||
rebuilding the list.</p>
|
||||
</div>
|
||||
<div class="section" id="picker-strategy">
|
||||
<h2>picker strategy</h2>
|
||||
<p>The normal mode of the picker is of course <em>rarest first</em>, meaning
|
||||
pieces that few peers have are preferred to be downloaded over pieces
|
||||
that more peers have. This is a fundamental algorithm that is the
|
||||
basis of the performance of bittorrent. However, the user may set the
|
||||
piece picker into sequential download mode. This mode simply picks
|
||||
pieces sequentially, always preferring lower piece indices.</p>
|
||||
<p>When a torrent starts out, picking the rarest pieces means increased
|
||||
risk that pieces won't be completed early (since there are only a few
|
||||
peers they can be downloaded from), leading to a delay of having any
|
||||
piece to offer to other peers. This lack of pieces to trade, delays
|
||||
the client from getting started into the normal tit-for-tat mode of
|
||||
bittorrent, and will result in a long ramp-up time. The heuristic to
|
||||
mitigate this problem is to, for the first few pieces, pick random pieces
|
||||
rather than rare pieces. The threshold for when to leave this initial
|
||||
picker mode is determined by <a class="reference external" href="reference-Settings.html#initial_picker_threshold">session_settings::initial_picker_threshold</a>.</p>
|
||||
<p>The normal mode of the picker is of course <em>rarest first</em>, meaning pieces that
|
||||
few peers have are preferred to be downloaded over pieces that more peers have.
|
||||
This is a fundamental algorithm that is the basis of the performance of
|
||||
bittorrent. However, the user may set the piece picker into sequential download
|
||||
mode. This mode simply picks pieces sequentially, always preferring lower piece
|
||||
indices.</p>
|
||||
<p>When a torrent starts out, picking the rarest pieces means increased risk that
|
||||
pieces won't be completed early (since there are only a few peers they can be
|
||||
downloaded from), leading to a delay of having any piece to offer to other
|
||||
peers. This lack of pieces to trade, delays the client from getting started
|
||||
into the normal tit-for-tat mode of bittorrent, and will result in a long
|
||||
ramp-up time. The heuristic to mitigate this problem is to, for the first few
|
||||
pieces, pick random pieces rather than rare pieces. The threshold for when to
|
||||
leave this initial picker mode is determined by
|
||||
session_settings::initial_picker_threshold.</p>
|
||||
</div>
|
||||
<div class="section" id="reverse-order">
|
||||
<h2>reverse order</h2>
|
||||
<p>An orthogonal setting is <em>reverse order</em>, which is used for <em>snubbed</em>
|
||||
peers. Snubbed peers are peers that appear very slow, and might have timed
|
||||
out a piece request. The idea behind this is to make all snubbed peers
|
||||
more likely to be able to do download blocks from the same piece,
|
||||
concentrating slow peers on as few pieces as possible. The reverse order
|
||||
means that the most common pieces are picked, instead of the rarest pieces
|
||||
(or in the case of sequential download, the last pieces, intead of the first).</p>
|
||||
</div>
|
||||
<div class="section" id="parole-mode">
|
||||
<h2>parole mode</h2>
|
||||
<p>Peers that have participated in a piece that failed the hash check, may be
|
||||
put in <em>parole mode</em>. This means we prefer downloading a full piece from this
|
||||
peer, in order to distinguish which peer is sending corrupt data. Whether to
|
||||
do this is or not is controlled by <a class="reference external" href="reference-Settings.html#use_parole_mode">session_settings::use_parole_mode</a>.</p>
|
||||
<p>An orthogonal setting is <em>reverse order</em>, which is used for <em>snubbed</em> peers.
|
||||
Snubbed peers are peers that appear very slow, and might have timed out a piece
|
||||
request. The idea behind this is to make all snubbed peers more likely to be
|
||||
able to do download blocks from the same piece, concentrating slow peers on as
|
||||
few pieces as possible. The reverse order means that the most common pieces are
|
||||
picked, instead of the rarest pieces (or in the case of sequential download,
|
||||
the last pieces, intead of the first).</p>
|
||||
<p>parole mode -----------</p>
|
||||
<p>Peers that have participated in a piece that failed the hash check, may be put
|
||||
in <em>parole mode</em>. This means we prefer downloading a full piece from this
|
||||
peer, in order to distinguish which peer is sending corrupt data. Whether to do
|
||||
this is or not is controlled by <a class="reference external" href="reference-Settings.html#use_parole_mode">session_settings::use_parole_mode</a>.</p>
|
||||
<p>In parole mode, the piece picker prefers picking one whole piece at a time for
|
||||
a given peer, avoiding picking any blocks from a piece any other peer has
|
||||
contributed to (since that would defeat the purpose of parole mode).</p>
|
||||
</div>
|
||||
<div class="section" id="prioritize-partial-pieces">
|
||||
<h2>prioritize partial pieces</h2>
|
||||
<p>This setting determines if partially downloaded or requested pieces should always
|
||||
be preferred over other pieces. The benefit of doing this is that the number of
|
||||
partial pieces is minimized (and hence the turn-around time for downloading a block
|
||||
until it can be uploaded to others is minimized). It also puts less stress on the
|
||||
disk cache, since fewer partial pieces need to be kept in the cache. Whether or
|
||||
not to enable this is controlled by <a class="reference external" href="reference-Settings.html#prioritize_partial_pieces">session_settings::prioritize_partial_pieces</a>.</p>
|
||||
<p>prioritize partial pieces -------------------------</p>
|
||||
<p>This setting determines if partially downloaded or requested pieces should
|
||||
always be preferred over other pieces. The benefit of doing this is that the
|
||||
number of partial pieces is minimized (and hence the turn-around time for
|
||||
downloading a block until it can be uploaded to others is minimized). It also
|
||||
puts less stress on the disk cache, since fewer partial pieces need to be kept
|
||||
in the cache. Whether or not to enable this is controlled by
|
||||
session_settings::prioritize_partial_pieces.</p>
|
||||
<p>The main benefit of not prioritizing partial pieces is that the rarest first
|
||||
algorithm gets to have more influence on which pieces are picked. The picker is
|
||||
more likely to truly pick the rarest piece, and hence improving the performance
|
||||
|
@ -854,18 +850,15 @@ of the swarm.</p>
|
|||
in the piece picker exceeds the number of peers we're connected to times 1.5.
|
||||
This is in order to keep the waste of partial pieces to a minimum, but still
|
||||
prefer rarest pieces.</p>
|
||||
</div>
|
||||
<div class="section" id="prefer-whole-pieces">
|
||||
<h2>prefer whole pieces</h2>
|
||||
<p>prefer whole pieces -------------------</p>
|
||||
<p>The <em>prefer whole pieces</em> setting makes the piece picker prefer picking entire
|
||||
pieces at a time. This is used by web connections (both http seeding
|
||||
standards), in order to be able to coalesce the small bittorrent requests
|
||||
to larger HTTP requests. This significantly improves performance when
|
||||
downloading over HTTP.</p>
|
||||
<p>It is also used by peers that are downloading faster than a certain
|
||||
threshold. The main advantage is that these peers will better utilize the
|
||||
other peer's disk cache, by requesting all blocks in a single piece, from
|
||||
the same peer.</p>
|
||||
standards), in order to be able to coalesce the small bittorrent requests to
|
||||
larger HTTP requests. This significantly improves performance when downloading
|
||||
over HTTP.</p>
|
||||
<p>It is also used by peers that are downloading faster than a certain threshold.
|
||||
The main advantage is that these peers will better utilize the other peer's
|
||||
disk cache, by requesting all blocks in a single piece, from the same peer.</p>
|
||||
<p>This threshold is controlled by <a class="reference external" href="reference-Settings.html#whole_pieces_threshold">session_settings::whole_pieces_threshold</a>.</p>
|
||||
<p><em>TODO: piece affinity by speed category</em>
|
||||
<em>TODO: piece priorities</em></p>
|
||||
|
@ -874,8 +867,8 @@ the same peer.</p>
|
|||
<div class="section" id="ssl-torrents">
|
||||
<h1>SSL torrents</h1>
|
||||
<p>Torrents may have an SSL root (CA) certificate embedded in them. Such torrents
|
||||
are called <em>SSL torrents</em>. An SSL torrent talks to all bittorrent peers over SSL.
|
||||
The protocols are layered like this:</p>
|
||||
are called <em>SSL torrents</em>. An SSL torrent talks to all bittorrent peers over
|
||||
SSL. The protocols are layered like this:</p>
|
||||
<pre class="literal-block">
|
||||
+-----------------------+
|
||||
| BitTorrent protocol |
|
||||
|
@ -887,58 +880,66 @@ The protocols are layered like this:</p>
|
|||
| | UDP |
|
||||
+-----------+-----------+
|
||||
</pre>
|
||||
<p>During the SSL handshake, both peers need to authenticate by providing a certificate
|
||||
that is signed by the CA certificate found in the .torrent file. These peer
|
||||
certificates are expected to be privided to peers through some other means than
|
||||
bittorrent. Typically by a peer generating a certificate request which is sent to
|
||||
the publisher of the torrent, and the publisher returning a signed certificate.</p>
|
||||
<p>In libtorrent, <a class="reference external" href="reference-Core.html#set_ssl_certificate()">set_ssl_certificate()</a> in <a class="reference external" href="reference-Core.html#torrent_handle">torrent_handle</a> is used to tell libtorrent where
|
||||
to find the peer certificate and the private key for it. When an SSL torrent is loaded,
|
||||
the <a class="reference external" href="reference-Alerts.html#torrent_need_cert_alert">torrent_need_cert_alert</a> is posted to remind the user to provide a certificate.</p>
|
||||
<p>A peer connecting to an SSL torrent MUST provide the <em>SNI</em> TLS extension (server name
|
||||
indication). The server name is the hex encoded info-hash of the torrent to connect to.
|
||||
This is required for the client accepting the connection to know which certificate to
|
||||
present.</p>
|
||||
<p>SSL connections are accepted on a separate socket from normal bittorrent connections. To
|
||||
pick which port the SSL socket should bind to, set <a class="reference external" href="reference-Settings.html#ssl_listen">session_settings::ssl_listen</a> to a
|
||||
different port. It defaults to port 4433. This setting is only taken into account when the
|
||||
normal listen socket is opened (i.e. just changing this setting won't necessarily close
|
||||
and re-open the SSL socket). To not listen on an SSL socket at all, set <tt class="docutils literal">ssl_listen</tt> to 0.</p>
|
||||
<p>This feature is only available if libtorrent is build with openssl support (<tt class="docutils literal">TORRENT_USE_OPENSSL</tt>)
|
||||
and requires at least openSSL version 1.0, since it needs SNI support.</p>
|
||||
<p>Peer certificates must have at least one <em>SubjectAltName</em> field of type dNSName. At least
|
||||
one of the fields must <em>exactly</em> match the name of the torrent. This is a byte-by-byte comparison,
|
||||
the UTF-8 encoding must be identical (i.e. there's no unicode normalization going on). This is
|
||||
the recommended way of verifying certificates for HTTPS servers according to <a class="reference external" href="http://www.ietf.org/rfc/rfc2818.txt">RFC 2818</a>. Note
|
||||
the difference that for torrents only <em>dNSName</em> fields are taken into account (not IP address fields).
|
||||
The most specific (i.e. last) <em>Common Name</em> field is also taken into account if no <em>SubjectAltName</em>
|
||||
did not match.</p>
|
||||
<p>If any of these fields contain a single asterisk ("*"), the certificate is considered covering
|
||||
any torrent, allowing it to be reused for any torrent.</p>
|
||||
<p>The purpose of matching the torrent name with the fields in the peer certificate is to allow
|
||||
a publisher to have a single root certificate for all torrents it distributes, and issue
|
||||
separate peer certificates for each torrent. A peer receiving a certificate will not necessarily
|
||||
be able to access all torrents published by this root certificate (only if it has a "star cert").</p>
|
||||
<p>During the SSL handshake, both peers need to authenticate by providing a
|
||||
certificate that is signed by the CA certificate found in the .torrent file.
|
||||
These peer certificates are expected to be privided to peers through some other
|
||||
means than bittorrent. Typically by a peer generating a certificate request
|
||||
which is sent to the publisher of the torrent, and the publisher returning a
|
||||
signed certificate.</p>
|
||||
<p>In libtorrent, <a class="reference external" href="reference-Core.html#set_ssl_certificate()">set_ssl_certificate()</a> in <a class="reference external" href="reference-Core.html#torrent_handle">torrent_handle</a> is used to tell
|
||||
libtorrent where to find the peer certificate and the private key for it. When
|
||||
an SSL torrent is loaded, the <a class="reference external" href="reference-Alerts.html#torrent_need_cert_alert">torrent_need_cert_alert</a> is posted to remind the
|
||||
user to provide a certificate.</p>
|
||||
<p>A peer connecting to an SSL torrent MUST provide the <em>SNI</em> TLS extension
|
||||
(server name indication). The server name is the hex encoded info-hash of the
|
||||
torrent to connect to. This is required for the client accepting the connection
|
||||
to know which certificate to present.</p>
|
||||
<p>SSL connections are accepted on a separate socket from normal bittorrent
|
||||
connections. To pick which port the SSL socket should bind to, set
|
||||
<a class="reference external" href="reference-Settings.html#ssl_listen">session_settings::ssl_listen</a> to a different port. It defaults to port 4433.
|
||||
This setting is only taken into account when the normal listen socket is opened
|
||||
(i.e. just changing this setting won't necessarily close and re-open the SSL
|
||||
socket). To not listen on an SSL socket at all, set <tt class="docutils literal">ssl_listen</tt> to 0.</p>
|
||||
<p>This feature is only available if libtorrent is build with openssl support
|
||||
(<tt class="docutils literal">TORRENT_USE_OPENSSL</tt>) and requires at least openSSL version 1.0, since it
|
||||
needs SNI support.</p>
|
||||
<p>Peer certificates must have at least one <em>SubjectAltName</em> field of type
|
||||
dNSName. At least one of the fields must <em>exactly</em> match the name of the
|
||||
torrent. This is a byte-by-byte comparison, the UTF-8 encoding must be
|
||||
identical (i.e. there's no unicode normalization going on). This is the
|
||||
recommended way of verifying certificates for HTTPS servers according to <a class="reference external" href="http://www.ietf.org/rfc/rfc2818.txt">RFC
|
||||
2818</a>. Note the difference that for torrents only <em>dNSName</em> fields are taken
|
||||
into account (not IP address fields). The most specific (i.e. last) <em>Common
|
||||
Name</em> field is also taken into account if no <em>SubjectAltName</em> did not match.</p>
|
||||
<p>If any of these fields contain a single asterisk ("*"), the certificate is
|
||||
considered covering any torrent, allowing it to be reused for any torrent.</p>
|
||||
<p>The purpose of matching the torrent name with the fields in the peer
|
||||
certificate is to allow a publisher to have a single root certificate for all
|
||||
torrents it distributes, and issue separate peer certificates for each torrent.
|
||||
A peer receiving a certificate will not necessarily be able to access all
|
||||
torrents published by this root certificate (only if it has a "star cert").</p>
|
||||
<div class="section" id="testing">
|
||||
<h2>testing</h2>
|
||||
<p>To test incoming SSL connections to an SSL torrent, one can use the following <em>openssl</em> command:</p>
|
||||
<p>To test incoming SSL connections to an SSL torrent, one can use the following
|
||||
<em>openssl</em> command:</p>
|
||||
<pre class="literal-block">
|
||||
openssl s_client -cert <peer-certificate>.pem -key <peer-private-key>.pem -CAfile \
|
||||
<torrent-cert>.pem -debug -connect 127.0.0.1:4433 -tls1 -servername <info-hash>
|
||||
</pre>
|
||||
<p>To create a root certificate, the Distinguished Name (<em>DN</em>) is not taken into account
|
||||
by bittorrent peers. You still need to specify something, but from libtorrent's point of
|
||||
view, it doesn't matter what it is. libtorrent only makes sure the peer certificates are
|
||||
signed by the correct root certificate.</p>
|
||||
<p>One way to create the certificates is to use the <tt class="docutils literal">CA.sh</tt> script that comes with openssl,
|
||||
like thisi (don't forget to enter a common Name for the certificate):</p>
|
||||
<p>To create a root certificate, the Distinguished Name (<em>DN</em>) is not taken into
|
||||
account by bittorrent peers. You still need to specify something, but from
|
||||
libtorrent's point of view, it doesn't matter what it is. libtorrent only makes
|
||||
sure the peer certificates are signed by the correct root certificate.</p>
|
||||
<p>One way to create the certificates is to use the <tt class="docutils literal">CA.sh</tt> script that comes
|
||||
with openssl, like thisi (don't forget to enter a common Name for the
|
||||
certificate):</p>
|
||||
<pre class="literal-block">
|
||||
CA.sh -newca
|
||||
CA.sh -newreq
|
||||
CA.sh -sign
|
||||
</pre>
|
||||
<p>The torrent certificate is located in <tt class="docutils literal">./demoCA/private/demoCA/cacert.pem</tt>, this is
|
||||
the pem file to include in the .torrent file.</p>
|
||||
<p>The torrent certificate is located in <tt class="docutils literal">./demoCA/private/demoCA/cacert.pem</tt>,
|
||||
this is the pem file to include in the .torrent file.</p>
|
||||
<p>The peer's certificate is located in <tt class="docutils literal">./newcert.pem</tt> and the certificate's
|
||||
private key in <tt class="docutils literal">./newkey.pem</tt>.</p>
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue