merged back encryption branch to trunk

This commit is contained in:
Arvid Norberg 2007-06-06 00:41:20 +00:00
parent 41cf912501
commit 273f8bd921
35 changed files with 2323 additions and 537 deletions

View File

@ -6,6 +6,7 @@ Massaroddel
Tianhao Qiu.
Contributions by:
Shyam
Magnus Jonsson
Daniel Wallin
Cory Nelson

View File

@ -1,3 +1,4 @@
* added encryption support
* added parole mode for peers whose data fails the hash check.
* optimized heap usage in piece-picker and web seed downloader.
* fixed bug in DHT where older write tokens weren't accepted.

15
Jamfile
View File

@ -28,6 +28,10 @@ feature dht-support : on off logging : composite propagated symmetric link-incom
feature.compose <dht-support>off : <define>TORRENT_DISABLE_DHT ;
feature.compose <dht-support>logging : <define>TORRENT_DHT_VERBOSE_LOGGING ;
feature pe-support : on off : composite propagated symmetric ;
feature.compose <pe-support>on : ;
feature.compose <pe-support>off : <define>TORRENT_DISABLE_ENCRYPTION ;
feature openssl : off on : composite propagated symmetric link-incompatible ;
feature.compose <openssl>on : <define>TORRENT_USE_OPENSSL ;
@ -37,6 +41,8 @@ feature.compose <resolve-countries>off : <define>TORRENT_DISABLE_RESOLVE_COUNTRI
feature character-set : ansi unicode : composite propagated link-incompatible ;
feature.compose <character-set>unicode : <define>_UNICODE <define>UNICODE ;
feature zlib : shipped system : composite ;
feature statistics : off on : composite propagated symmetric link-incompatible ;
feature.compose <statistics>on : <define>TORRENT_STATS ;
@ -136,7 +142,7 @@ project torrent
<include>./include
<include>./include/libtorrent
<include>./zlib
<zlib>shipped:<include>./zlib
<include>$(BOOST_ROOT)
<variant>release:<define>NDEBUG
<define>BOOST_ALL_NO_LIB
@ -179,13 +185,16 @@ project torrent
lib torrent
:
src/$(SOURCES).cpp
zlib/$(ZLIB_SOURCES).c
$(LIBS)
# pch
:
<dht-support>on:<source>src/$(KADEMLIA_SOURCES).cpp
<dht-support>logging:<source>src/$(KADEMLIA_SOURCES).cpp
<openssl>off:<source>src/sha1.cpp
<zlib>shipped:<source>zlib/$(ZLIB_SOURCES).c
<zlib>system:<library>z
<pe-support>on:<source>src/pe_crypto.cpp
<pe-support>on:<library>crypt
<openssl>on:<library>crypt
<openssl>off,<pe-support>off:<source>src/sha1.cpp
;

View File

@ -206,6 +206,24 @@ logging of the DHT protocol traffic.</li>
</ul>
</td>
</tr>
<tr><td><tt class="docutils literal"><span class="pre">zlib</span></tt></td>
<td><ul class="first last simple">
<li><tt class="docutils literal"><span class="pre">system</span></tt> - links against the zlib supplied
with your operating system.</li>
<li><tt class="docutils literal"><span class="pre">shipped</span></tt> - links against the zlib bundled
with the libtorrent package.</li>
</ul>
</td>
</tr>
<tr><td><tt class="docutils literal"><span class="pre">pe-support</span></tt></td>
<td><ul class="first last simple">
<li><tt class="docutils literal"><span class="pre">on</span></tt> - turns on support for encrypted
connections. requires openssl (libcrypto)</li>
<li><tt class="docutils literal"><span class="pre">off</span></tt> - turns off support for encrypted
connections. openssl is not linked in.</li>
</ul>
</td>
</tr>
<tr><td><tt class="docutils literal"><span class="pre">link</span></tt></td>
<td><ul class="first last simple">
<li><tt class="docutils literal"><span class="pre">static</span></tt> - builds libtorrent as a static
@ -273,7 +291,8 @@ boost.program-options symbols.</p>
sure all build variants will actually compile), you can invoke this command:</p>
<pre class="literal-block">
bjam debug release link=shared link=static logging=verbose logging=default \
logging=none dht-support=on dht-support=logging dht-support=off
logging=none dht-support=on dht-support=logging dht-support=off pe-support=on \
pe-support=off zlib=shipped zlib=system
</pre>
</div>
</div>

View File

@ -208,6 +208,16 @@ Build features:
| | logging of the DHT protocol traffic. |
| | * ``off`` - build without DHT support. |
+------------------------+----------------------------------------------------+
| ``zlib`` | * ``system`` - links against the zlib supplied |
| | with your operating system. |
| | * ``shipped`` - links against the zlib bundled |
| | with the libtorrent package. |
+------------------------+----------------------------------------------------+
| ``pe-support`` | * ``on`` - turns on support for encrypted |
| | connections. requires openssl (libcrypto) |
| | * ``off`` - turns off support for encrypted |
| | connections. openssl is not linked in. |
+------------------------+----------------------------------------------------+
| ``link`` | * ``static`` - builds libtorrent as a static |
| | library (.a / .lib) |
| | * ``shared`` - builds libtorrent as a shared |
@ -261,7 +271,9 @@ To build all possible variants of libtorrent (good for testing when making
sure all build variants will actually compile), you can invoke this command::
bjam debug release link=shared link=static logging=verbose logging=default \
logging=none dht-support=on dht-support=logging dht-support=off
logging=none dht-support=on dht-support=logging dht-support=off pe-support=on \
pe-support=off zlib=shipped zlib=system openssl=on openssl=off \
character-set=ansi character-set=unicode
building with autotools
-----------------------
@ -472,6 +484,12 @@ defines you can use to control the build.
| ``TORRENT_DHT_VERBOSE_LOGGING`` | This will enable verbose logging of the DHT |
| | protocol traffic. |
+---------------------------------+-------------------------------------------------+
| ``TORRENT_DISABLE_ENCRYPTION`` | This will disable any encryption support and |
| | the openssl dependency that comes with it. |
| | Encryption support is the peer connection |
| | encrypted supported by clients such as |
| | uTorrent, Azureus and KTorrent. |
+---------------------------------+-------------------------------------------------+
If you experience that libtorrent uses unreasonable amounts of cpu, it will

View File

@ -19,11 +19,11 @@
<td>Arvid Norberg, <a class="last reference" href="mailto:arvid&#64;rasterbar.com">arvid&#64;rasterbar.com</a></td></tr>
</tbody>
</table>
<div class="section" id="mainline-dht-extensions">
<h1>Mainline DHT extensions</h1>
<div class="section">
<h1><a id="mainline-dht-extensions" 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>client identification</h2>
<div class="section">
<h2><a id="client-identification" name="client-identification">client identification</a></h2>
<p>In each DHT packet, an extra key is inserted named &quot;v&quot;. 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
@ -51,8 +51,8 @@ as a binary number describing the client version.</p>
</tbody>
</table>
</div>
<div class="section" id="ipv6-support">
<h2>IPv6 support</h2>
<div class="section">
<h2><a id="ipv6-support" name="ipv6-support">IPv6 support</a></h2>
<p>The DHT messages that don't support IPv6 are the <tt class="docutils literal"><span class="pre">nodes</span></tt> replies.
They encode all the contacts as 6 bytes packed together in sequence in a
string. The problem is that IPv6 endpoints cannot be encoded as 6 bytes, but

View File

@ -20,16 +20,16 @@
</tbody>
</table>
<div class="contents topic" id="table-of-contents">
<p class="topic-title first">Table of contents</p>
<p class="topic-title first"><a name="table-of-contents">Table of contents</a></p>
<ul class="simple">
<li><a class="reference" href="#introduction" id="id4">introduction</a></li>
<li><a class="reference" href="#features" id="id5">features</a></li>
<li><a class="reference" href="#portability" id="id6">portability</a></li>
<li><a class="reference" href="#license" id="id7">license</a></li>
<li><a class="reference" href="#introduction" id="id6" name="id6">introduction</a></li>
<li><a class="reference" href="#features" id="id7" name="id7">features</a></li>
<li><a class="reference" href="#portability" id="id8" name="id8">portability</a></li>
<li><a class="reference" href="#license" id="id9" name="id9">license</a></li>
</ul>
</div>
<div class="section" id="introduction">
<h1>introduction</h1>
<div class="section">
<h1><a id="introduction" name="introduction">introduction</a></h1>
<p>libtorrent is a C++ library that aims to be a good alternative to all the
other bittorrent implementations around. It is a
library and not a full featured client, although it comes with a working
@ -41,8 +41,8 @@ example client.</p>
<li>to be very easy to use</li>
</ul>
</div>
<div class="section" id="features">
<h1>features</h1>
<div class="section">
<h1><a id="features" name="features">features</a></h1>
<p>libtorrent is still being developed, however it is stable. It is an ongoing
project (including this documentation). The current state includes the
following features:</p>
@ -67,7 +67,7 @@ as well as all local peers in a separate fast-resume file.</li>
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
download speed is high enough from that particular peer.</li>
<li>supports the <a class="reference" href="udp_tracker_protocol.html">udp-tracker protocol</a> by Olaf van der Spek.</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>supports http proxies and basic proxy authentication</li>
<li>gzipped tracker-responses</li>
@ -76,7 +76,7 @@ unchoked peers</li>
<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
to the other party.</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 an <a class="reference" href="udp_tracker_protocol.html">extension protocol</a>. See <a class="reference" href="manual.html#extensions">extensions</a>.</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>possibility to limit the number of connections.</li>
<li>delays have messages if there's no other outgoing traffic to the peer, and
@ -91,8 +91,8 @@ want to download.</li>
being connected</li>
</ul>
</div>
<div class="section" id="portability">
<h1>portability</h1>
<div class="section">
<h1><a id="portability" name="portability">portability</a></h1>
<p>libtorrent is portable at least among Windows, MacOS X and other UNIX-systems.
It uses Boost.Thread, Boost.Filesystem, Boost.Date_time and various other
boost libraries as well as <a class="reference" href="http://www.zlib.org">zlib</a> (shipped) and <a class="reference" href="http://asio.sf.net">asio</a> (shipped). At least version
@ -114,8 +114,8 @@ epoll on linux and kqueue on MacOS X and BSD.</p>
<li>msvc6</li>
</ul>
</div>
<div class="section" id="license">
<h1>license</h1>
<div class="section">
<h1><a id="license" name="license">license</a></h1>
<p>libtorrent is released under the <a class="reference" href="http://www.opensource.org/licenses/bsd-license.php">BSD-license</a>.</p>
<p>This means that you can use the library in your project without having to
release its source code. The only requirement is that you give credit

File diff suppressed because it is too large Load Diff

View File

@ -92,8 +92,8 @@ The ``session`` class has the following synopsis::
torrent_handle find_torrent(sha_hash const& ih);
std::vector<torrent_handle> get_torrents() const;
void set_settings(
session_settings const& settings);
void set_settings(session_settings const& settings);
void set_pe_settings(pe_settings const& settings);
void set_upload_rate_limit(int bytes_per_second);
int upload_rate_limit() const;
@ -250,9 +250,9 @@ about the torrent's progress, its peers etc. It is also used to abort a torrent.
The second overload that takes a tracker url and an info-hash instead of metadata
(``torrent_info``) can be used with torrents where (at least some) peers support
the metadata extension. For the overload to be available, libtorrent must be built
with extensions enabled (``TORRENT_ENABLE_EXTENSIONS`` defined). It also takes an
optional ``name`` argument. This may be 0 in case no name should be assigned to the
torrent. In case it's not 0, the name is used for the torrent as long as it doesn't
with extensions enabled (``TORRENT_DISABLE_EXTENSIONS`` must not be defined). It also
takes an optional ``name`` argument. This may be 0 in case no name should be assigned
to the torrent. In case it's not 0, the name is used for the torrent as long as it doesn't
have metadata. See ``torrent_handle::name``.
remove_torrent() find_torrent() get_torrents()
@ -515,6 +515,19 @@ e.g.
.. _`libtorrent plugins`: libtorrent_plugins.html
set_settings() set_pe_settings()
--------------------------------
::
void set_settings(session_settings const& settings);
void set_pe_settings(pe_settings const& settings);
Sets the session settings and the packet encryption settings respectively.
See session_settings_ and pe_settings_ for more information on available
options.
set_peer_proxy() set_web_seed_proxy() set_tracker_proxy() set_dht_proxy()
-------------------------------------------------------------------------
@ -556,6 +569,7 @@ These functions returns references to their respective current settings.
The ``dht_proxy`` is not available when DHT is disabled.
start_dht() stop_dht() set_dht_settings() dht_state()
-----------------------------------------------------
@ -2310,6 +2324,66 @@ Default is 10 minutes
all trackers in its tracker list has failed. Either by an explicit error
message or a time out.
pe_settings
===========
The ``pe_settings`` structure is used to control the settings related
to peer protocol encryption::
struct pe_settings
{
pe_settings();
enum enc_policy
{
forced,
enabled,
disabled
};
enum enc_level
{
plaintext,
rc4,
both
};
enc_policy out_enc_policy;
enc_policy in_enc_policy;
enc_level allowed_enc_level;
bool prefer_rc4;
};
``in_enc_policy`` and ``out_enc_policy`` control the settings for incoming
and outgoing connections respectively. The settings for these are:
* ``forced`` - Only encrypted connections are allowed. Incoming connections
that are not encrypted are closed and if the encrypted outgoing connection
fails, a non-encrypted retry will not be made.
* ``enabled`` - encrypted connections are enabled, but non-encrypted
connections are allowed. An incoming non-encrypted connection will
be accepted, and if an outgoing encrypted connection fails, a non-
encrypted connection will be tried.
* ``disabled`` - only non-encrypted connections are allowed.
``allowed_enc_level`` determines the encryption level of the
connections. This setting will adjust which encryption scheme is
offered to the other peer, as well as which encryption scheme is
selected by the client. The settings are:
* ``plaintext`` - only the handshake is encrypted, the bulk of the traffic
remains unchanged.
* ``rc4`` - the entire stream is encrypted with RC4
* ``both`` - both RC4 and plaintext connections are allowed.
``prefer_rc4`` can be set to true if you want to prefer the RC4 encrypted stream.
proxy_settings
==============

View File

@ -297,7 +297,11 @@ void print_peer_info(std::ostream& out, std::vector<libtorrent::peer_info> const
<< ((i->flags & peer_info::local_connection)?'l':'r')
<< ((i->flags & peer_info::seed)?'s':'.')
<< ((i->flags & peer_info::on_parole)?'p':'.')
<< " "
#ifndef TORRENT_DISABLE_ENCRYPTION
<< ((i->flags & peer_info::rc4_encrypted)?'E':
(i->flags & peer_info::plaintext_encrypted)?'e':'.')
#endif
<< " "
<< ((i->source & peer_info::tracker)?"T":"_")
<< ((i->source & peer_info::pex)?"P":"_")
<< ((i->source & peer_info::dht)?"D":"_")

View File

@ -27,6 +27,7 @@ libtorrent/peer.hpp \
libtorrent/peer_connection.hpp \
libtorrent/bt_peer_connection.hpp \
libtorrent/web_peer_connection.hpp \
libtorrent/pe_crypto.hpp \
libtorrent/natpmp.hpp \
libtorrent/pch.hpp \
libtorrent/peer_id.hpp \

View File

@ -217,6 +217,11 @@ namespace libtorrent
entry dht_state() const;
#endif
#ifndef TORRENT_DISABLE_ENCRYPTION
void set_pe_settings(pe_settings const& settings);
pe_settings const& get_pe_settings() const { return m_pe_settings; }
#endif
// called when a port mapping is successful, or a router returns
// a failure to map a port
void on_port_mapping(int tcp_port, int udp_port, std::string const& errmsg);
@ -429,6 +434,11 @@ namespace libtorrent
// but for the udp port used by the DHT.
int m_external_udp_port;
#endif
#ifndef TORRENT_DISABLE_ENCRYPTION
pe_settings m_pe_settings;
#endif
boost::shared_ptr<natpmp> m_natpmp;
boost::shared_ptr<upnp> m_upnp;
boost::shared_ptr<lsd> m_lsd;

View File

@ -1,6 +1,7 @@
/*
Copyright (c) 2003, Arvid Norberg
Copyright (c) 2003 - 2006, Arvid Norberg
Copyright (c) 2007, Arvid Norberg, Un Shyam
All rights reserved.
Redistribution and use in source and binary forms, with or without
@ -68,6 +69,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/peer_request.hpp"
#include "libtorrent/piece_block_progress.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/pe_crypto.hpp"
namespace libtorrent
{
@ -102,6 +104,11 @@ namespace libtorrent
, policy::peer* peerinfo);
~bt_peer_connection();
#ifndef TORRENT_DISABLE_ENCRYPTION
bool supports_encryption() const
{ return m_encrypted; }
#endif
enum message_type
{
@ -213,19 +220,76 @@ namespace libtorrent
// will be invalid.
boost::optional<piece_block_progress> downloading_piece_progress() const;
#ifndef TORRENT_DISABLE_ENCRYPTION
// if (is_local()), we are 'a' otherwise 'b'
//
// 1. a -> b dhkey, pad
// 2. b -> a dhkey, pad
// 3. a -> b sync, payload
// 4. b -> a sync, payload
// 5. a -> b payload
void write_pe1_2_dhkey();
void write_pe3_sync();
void write_pe4_sync(int crypto_select);
void write_pe_vc_cryptofield(buffer::interval& write_buf,
int crypto_field, int pad_size);
// stream key (info hash of attached torrent)
// secret is the DH shared secret
// initializes m_RC4_handler
void init_pe_RC4_handler(char const* secret, sha1_hash const& stream_key);
// these functions encrypt the send buffer if m_rc4_encrypted
// is true, otherwise it passes the call to the
// peer_connection functions of the same names
void send_buffer(char* begin, char* end);
buffer::interval allocate_send_buffer(int size);
void setup_send();
// Returns offset at which bytestream (src, src + src_size)
// matches bytestream(target, target + target_size).
// If no sync found, return -1
int get_syncoffset(char const* src, int src_size,
char const* target, int target_size) const;
#endif
enum state
{
read_protocol_length = 0,
read_protocol_string,
#ifndef TORRENT_DISABLE_ENCRYPTION
read_pe_dhkey = 0,
read_pe_syncvc,
read_pe_synchash,
read_pe_skey_vc,
read_pe_cryptofield,
read_pe_pad,
read_pe_ia,
init_bt_handshake,
read_protocol_identifier,
#else
read_protocol_identifier = 0,
#endif
read_info_hash,
read_peer_id,
// handshake complete
read_packet_size,
read_packet
};
#ifndef TORRENT_DISABLE_ENCRYPTION
enum
{
handshake_len = 68,
dh_key_len = 96
};
#endif
std::string m_client_version;
// state of on_receive
state m_state;
// the timeout in seconds
@ -262,6 +326,44 @@ namespace libtorrent
#endif
bool m_supports_dht_port;
#ifndef TORRENT_DISABLE_ENCRYPTION
// this is set to true after the encryption method has been
// succesfully negotiated (either plaintext or rc4), to signal
// automatic encryption/decryption.
bool m_encrypted;
// true if rc4, false if plaintext
bool m_rc4_encrypted;
// used to disconnect peer if sync points are not found within
// the maximum number of bytes
int m_sync_bytes_read;
// hold information about latest allocated send buffer
// need to check for non zero (begin, end) for operations with this
buffer::interval m_enc_send_buffer;
// initialized during write_pe1_2_dhkey, and destroyed on
// creation of m_RC4_handler. Cannot reinitialize once
// initialized.
boost::scoped_ptr<DH_key_exchange> m_DH_key_exchange;
// if RC4 is negotiated, this is used for
// encryption/decryption during the entire session. Destroyed
// if plaintext is selected
boost::scoped_ptr<RC4_handler> m_RC4_handler;
// (outgoing only) synchronize verification constant with
// remote peer, this will hold RC4_decrypt(vc). Destroyed
// after the sync step.
boost::scoped_array<char> m_sync_vc;
// (incoming only) synchronize hash with remote peer, holds
// the sync hash (hash("req1",secret)). Destroyed after the
// sync step.
boost::scoped_ptr<sha1_hash> m_sync_hash;
#endif // #ifndef TORRENT_DISABLE_ENCRYPTION
#ifndef NDEBUG
// this is set to true when the client's
// bitfield is sent to this peer
@ -269,6 +371,7 @@ namespace libtorrent
bool m_in_constructor;
#endif
};
}

View File

@ -74,6 +74,12 @@ public:
return begin[index];
}
bool operator==(const const_interval& p_interval)
{
return (begin == p_interval.begin
&& end == p_interval.end);
}
int left() const { assert(end >= begin); return end - begin; }
char const* begin;

View File

@ -0,0 +1,125 @@
/*
Copyright (c) 2007, Un Shyam
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TORRENT_DISABLE_ENCRYPTION
#ifndef TORRENT_PE_CRYPTO_HPP_INCLUDED
#define TORRENT_PE_CRYPTO_HPP_INCLUDED
#include <cassert>
#include <openssl/dh.h>
#include <openssl/engine.h>
#include <openssl/rc4.h>
#include "peer_id.hpp" // For sha1_hash
namespace libtorrent
{
class DH_key_exchange
{
public:
DH_key_exchange ();
~DH_key_exchange ();
// Get local public key, always 96 bytes
char const* get_local_key (void) const;
// read remote_pubkey, generate and store shared secret in
// m_dh_secret
void compute_secret (const char* remote_pubkey);
const char* get_secret (void) const;
private:
int get_local_key_size () const
{
assert (m_DH);
return BN_num_bytes (m_DH->pub_key);
}
DH* m_DH;
static const unsigned char m_dh_prime[96];
static const unsigned char m_dh_generator[1];
char m_dh_local_key[96];
char m_dh_secret[96];
};
class RC4_handler // Non copyable
{
public:
// Input longkeys must be 20 bytes
RC4_handler (const sha1_hash& rc4_local_longkey,
const sha1_hash& rc4_remote_longkey)
{
RC4_set_key (&m_local_key, 20,
reinterpret_cast<unsigned char const*>(rc4_local_longkey.begin()));
RC4_set_key (&m_remote_key, 20,
reinterpret_cast<unsigned char const*>(rc4_remote_longkey.begin()));
// Discard first 1024 bytes
char buf[1024];
encrypt (buf, 1024);
decrypt (buf, 1024);
};
~RC4_handler () {};
void encrypt (char* pos, int len)
{
assert (len >= 0);
assert (pos);
RC4 (&m_local_key, len, reinterpret_cast<unsigned char const*>(pos),
reinterpret_cast<unsigned char*>(pos));
}
void decrypt (char* pos, int len)
{
assert (len >= 0);
assert (pos);
RC4 (&m_remote_key, len, reinterpret_cast<unsigned char const*>(pos),
reinterpret_cast<unsigned char*>(pos));
}
private:
RC4_KEY m_local_key; // Key to encrypt outgoing data
RC4_KEY m_remote_key; // Key to decrypt incoming data
};
} // namespace libtorrent
#endif // TORRENT_PE_CRYPTO_HPP_INCLUDED
#endif // TORRENT_DISABLE_ENCRYPTION

View File

@ -395,6 +395,14 @@ namespace libtorrent
- m_write_pos;
}
#ifndef TORRENT_DISABLE_ENCRYPTION
buffer::interval wr_recv_buffer()
{
return buffer::interval(&m_recv_buffer[0]
, &m_recv_buffer[0] + m_recv_pos);
}
#endif
buffer::const_interval receive_buffer() const
{
return buffer::const_interval(&m_recv_buffer[0]
@ -408,7 +416,6 @@ namespace libtorrent
bool packet_finished() const
{
assert(m_recv_pos <= m_packet_size);
return m_packet_size <= m_recv_pos;
}

View File

@ -117,6 +117,13 @@ namespace libtorrent
return *this;
}
big_number& operator ^= (big_number const& n)
{
for (int i = 0; i< number_size; ++i)
m_number[i] ^= n.m_number[i];
return *this;
}
unsigned char& operator[](int i)
{ assert(i >= 0 && i < number_size); return m_number[i]; }

View File

@ -57,6 +57,10 @@ namespace libtorrent
queued = 0x100,
on_parole = 0x200,
seed = 0x400
#ifndef TORRENT_DISABLE_ENCRYPTION
, rc4_encrypted = 0x800,
plaintext_encrypted = 0x1000
#endif
};
unsigned int flags;

View File

@ -135,6 +135,17 @@ namespace libtorrent
tcp::endpoint ip;
connection_type type;
#ifndef TORRENT_DISABLE_ENCRYPTION
// Hints encryption support of peer. Only effective for
// and when the outgoing encryption policy allows both
// encrypted and non encrypted connections
// (pe_settings::out_enc_policy == enabled). The initial
// state of this flag determines the initial connection
// attempt type (true = encrypted, false = standard).
// This will be toggled everytime either an encrypted or
// non-encrypted handshake fails.
bool pe_support;
#endif
// the number of failed connection attempts this peer has
int failcount;

View File

@ -178,6 +178,11 @@ namespace libtorrent
void add_dht_router(std::pair<std::string, int> const& node);
#endif
#ifndef TORRENT_DISABLE_ENCRYPTION
void set_pe_settings(pe_settings const& settings);
pe_settings const& get_pe_settings() const;
#endif
#ifndef TORRENT_DISABLE_EXTENSIONS
void add_extension(boost::function<boost::shared_ptr<torrent_plugin>(torrent*)> ext);
#endif

View File

@ -269,6 +269,42 @@ namespace libtorrent
};
#endif
#ifndef TORRENT_DISABLE_ENCRYPTION
struct pe_settings
{
pe_settings()
: out_enc_policy(enabled)
, in_enc_policy(enabled)
, allowed_enc_level(both)
, prefer_rc4(false)
{}
enum enc_policy
{
forced, // disallow non encrypted connections
enabled, // allow encrypted and non encrypted connections
disabled // disallow encrypted connections
};
enum enc_level
{
plaintext, // use only plaintext encryption
rc4, // use only rc4 encryption
both // allow both
};
enc_policy out_enc_policy;
enc_policy in_enc_policy;
enc_level allowed_enc_level;
// if the allowed encryption level is both, setting this to
// true will prefer rc4 if both methods are offered, plaintext
// otherwise
bool prefer_rc4;
};
#endif
}
#endif

View File

@ -16,7 +16,7 @@ libtorrent_la_SOURCES = allocate_resources.cpp \
bandwidth_manager.cpp entry.cpp escape_string.cpp \
peer_connection.cpp bt_peer_connection.cpp web_peer_connection.cpp \
natpmp.cpp piece_picker.cpp policy.cpp session.cpp session_impl.cpp sha1.cpp \
stat.cpp storage.cpp torrent.cpp torrent_handle.cpp \
stat.cpp storage.cpp torrent.cpp torrent_handle.cpp pe_crypto.cpp \
torrent_info.cpp tracker_manager.cpp http_connection.cpp \
http_tracker_connection.cpp udp_tracker_connection.cpp \
alert.cpp identify_client.cpp ip_filter.cpp file.cpp metadata_transfer.cpp \
@ -59,6 +59,7 @@ $(top_srcdir)/include/libtorrent/peer.hpp \
$(top_srcdir)/include/libtorrent/peer_connection.hpp \
$(top_srcdir)/include/libtorrent/bt_peer_connection.hpp \
$(top_srcdir)/include/libtorrent/web_peer_connection.hpp \
$(top_srcdir)/include/libtorrent/pe_crypto.hpp \
$(top_srcdir)/include/libtorrent/natpmp.hpp \
$(top_srcdir)/include/libtorrent/pch.hpp \
$(top_srcdir)/include/libtorrent/peer_id.hpp \

File diff suppressed because it is too large Load Diff

View File

@ -412,6 +412,10 @@ namespace libtorrent
m_send_buffer += '&';
}
#ifndef TORRENT_DISABLE_ENCRYPTION
m_send_buffer += "supportcrypto=1&";
#endif
// extension that tells the tracker that
// we don't need any peer_id's in the response
if (!url_has_argument(request, "no_peer_id"))

122
src/pe_crypto.cpp Normal file
View File

@ -0,0 +1,122 @@
/*
Copyright (c) 2007, Un Shyam
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TORRENT_DISABLE_ENCRYPTION
#include <cassert>
#include <algorithm>
#include <openssl/dh.h>
#include <openssl/engine.h>
#include "libtorrent/pe_crypto.hpp"
namespace libtorrent {
// Set the prime P and the generator, generate local public key
DH_key_exchange::DH_key_exchange ()
{
m_DH = DH_new ();
m_DH->p = BN_bin2bn (m_dh_prime, sizeof(m_dh_prime), NULL);
m_DH->g = BN_bin2bn (m_dh_generator, sizeof(m_dh_generator), NULL);
assert (sizeof(m_dh_prime) == DH_size(m_DH));
DH_generate_key (m_DH); // TODO Check != 0
assert (m_DH->pub_key);
// DH can generate key sizes that are smaller than the size of
// P with exponentially decreasing probability, in which case
// the msb's of m_dh_local_key need to be zeroed
// appropriately.
int key_size = get_local_key_size();
int len_dh = sizeof(m_dh_prime); // must equal DH_size(m_DH)
if (key_size != len_dh)
{
assert(key_size > 0 && key_size < len_dh);
int pad_zero_size = len_dh - key_size;
std::fill(m_dh_local_key, m_dh_local_key + pad_zero_size, 0);
BN_bn2bin(m_DH->pub_key, (unsigned char*)m_dh_local_key + pad_zero_size);
}
else
BN_bn2bin(m_DH->pub_key, (unsigned char*)m_dh_local_key); // TODO Check return value
}
DH_key_exchange::~DH_key_exchange ()
{
assert (m_DH);
DH_free (m_DH);
}
char const* DH_key_exchange::get_local_key () const
{
return m_dh_local_key;
}
// compute shared secret given remote public key
void DH_key_exchange::compute_secret (char const* remote_pubkey)
{
assert (remote_pubkey);
BIGNUM* bn_remote_pubkey = BN_bin2bn ((unsigned char*)remote_pubkey, 96, NULL);
int ret =
DH_compute_key ( (unsigned char*)m_dh_secret, bn_remote_pubkey, m_DH); // TODO Check for errors
BN_free (bn_remote_pubkey);
}
char const* DH_key_exchange::get_secret () const
{
return m_dh_secret;
}
const unsigned char DH_key_exchange::m_dh_prime[96] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
0xA6, 0x3A, 0x36, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x05, 0x63
};
const unsigned char DH_key_exchange::m_dh_generator[1] = { 2 };
} // namespace libtorrent
#endif // #ifndef TORRENT_DISABLE_ENCRYPTION

View File

@ -336,6 +336,9 @@ namespace libtorrent
void peer_connection::announce_piece(int index)
{
// dont announce during handshake
if (in_handshake()) return;
// optimization, don't send have messages
// to peers that already have the piece
if (!m_ses.settings().send_redundant_have
@ -1769,8 +1772,9 @@ namespace libtorrent
assert(int(m_recv_buffer.size()) >= size);
assert(int(m_recv_buffer.size()) >= m_recv_pos);
assert(m_recv_pos >= size);
std::memmove(&m_recv_buffer[0], &m_recv_buffer[0] + size, m_recv_pos - size);
if (size > 0)
std::memmove(&m_recv_buffer[0], &m_recv_buffer[0] + size, m_recv_pos - size);
m_recv_pos -= size;
@ -1869,6 +1873,8 @@ namespace libtorrent
}
}
m_statistics.second_tick(tick_interval);
// If the client sends more data
// we send it data faster, otherwise, slower.
// It will also depend on how much data the
@ -2071,7 +2077,7 @@ namespace libtorrent
}
return;
}
if (!can_write()) return;
assert(!m_writing);
@ -2145,7 +2151,6 @@ namespace libtorrent
assert(m_recv_pos >= 0);
assert(m_packet_size > 0);
assert(max_receive > 0);
assert(can_read());
#ifdef TORRENT_VERBOSE_LOGGING
@ -2169,7 +2174,7 @@ namespace libtorrent
if (int(m_recv_buffer.size()) < m_packet_size)
m_recv_buffer.resize(m_packet_size);
}
void peer_connection::send_buffer(char const* begin, char const* end)
{
std::vector<char>& buf = m_send_buffer[m_current_send_buffer];
@ -2213,10 +2218,11 @@ namespace libtorrent
assert(m_reading);
m_reading = false;
if (error)
{
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << "**ERROR**: " << error.message() << "\n";
(*m_logger) << "**ERROR**: " << error.message() << "[in peer_connection::on_receive_data]\n";
#endif
on_receive(error, bytes_transferred);
throw std::runtime_error(error.message());
@ -2300,7 +2306,7 @@ namespace libtorrent
// all exceptions should derive from std::exception
assert(false);
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
m_ses.connection_failed(m_socket, remote(), "connection failed for unkown reason");
m_ses.connection_failed(m_socket, remote(), "connection failed for unknown reason");
}
bool peer_connection::can_write() const
@ -2428,10 +2434,11 @@ namespace libtorrent
m_write_pos += bytes_transferred;
if (error)
{
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << "**ERROR**: " << error.message() << "\n";
(*m_logger) << "**ERROR**: " << error.message() << " [in peer_connection::on_send_data]\n";
#endif
throw std::runtime_error(error.message());
}
@ -2480,7 +2487,7 @@ namespace libtorrent
// all exceptions should derive from std::exception
assert(false);
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
m_ses.connection_failed(m_socket, remote(), "connection failed for unkown reason");
m_ses.connection_failed(m_socket, remote(), "connection failed for unknown reason");
}
@ -2633,9 +2640,19 @@ namespace libtorrent
time_duration d;
d = time_now() - m_last_sent;
if (total_seconds(d) < m_timeout / 2) return;
if (m_connecting) return;
if (in_handshake()) return;
// if the last send has not completed yet, do not send a keep
// alive
if (m_writing) return;
#ifdef TORRENT_VERBOSE_LOGGING
using namespace boost::posix_time;
(*m_logger) << time_now_string() << " ==> KEEPALIVE\n";
#endif
write_keepalive();
}

View File

@ -1021,7 +1021,10 @@ namespace libtorrent
// the iterator is invalid
// because of the push_back()
i = boost::prior(m_peers.end());
if (flags & 0x02) p.seed = true;
#ifndef TORRENT_DISABLE_ENCRYPTION
if (flags & 0x01) p.pe_support = true;
#endif
if (flags & 0x02) i->seed = true;
// try to send a DHT ping to this peer
// as well, to figure out if it supports
@ -1408,6 +1411,9 @@ namespace libtorrent
policy::peer::peer(const tcp::endpoint& ip_, peer::connection_type t, int src)
: ip(ip_)
, type(t)
#ifndef TORRENT_DISABLE_ENCRYPTION
, pe_support(true)
#endif
, failcount(0)
, hashfails(0)
, seed(false)

View File

@ -252,6 +252,18 @@ namespace libtorrent
#endif
#ifndef TORRENT_DISABLE_ENCRYPTION
void session::set_pe_settings(pe_settings const& settings)
{
m_impl->set_pe_settings(settings);
}
pe_settings const& session::get_pe_settings() const
{
return m_impl->get_pe_settings();
}
#endif
bool session::is_listening() const
{
return m_impl->is_listening();

View File

@ -1755,6 +1755,14 @@ namespace libtorrent { namespace detail
#endif
#ifndef TORRENT_DISABLE_ENCRYPTION
void session_impl::set_pe_settings(pe_settings const& settings)
{
mutex_t::scoped_lock l(m_mutex);
m_pe_settings = settings;
}
#endif
void session_impl::set_download_rate_limit(int bytes_per_second)
{
assert(bytes_per_second > 0 || bytes_per_second == -1);

View File

@ -117,14 +117,21 @@ namespace libtorrent { namespace
if (di == dropped.end())
{
// don't write too big of a package
if (num_added >= max_peer_entries) continue;
if (num_added >= max_peer_entries) break;
// only send proper bittorrent peers
bt_peer_connection* p = dynamic_cast<bt_peer_connection*>(i->second);
if (!p) continue;
// i->first was added since the last time
detail::write_endpoint(i->first, pla_out);
// no supported flags to set yet
// 0x01 - peer supports encryption
// 0x02 - peer is a seed
int flags = i->second->is_seed() ? 2 : 0;
int flags = p->is_seed() ? 2 : 0;
#ifndef TORRENT_DISABLE_ENCRYPTION
flags |= p->supports_encryption() ? 1 : 0;
#endif
detail::write_uint8(flags, plf_out);
++num_added;
}
@ -280,14 +287,21 @@ namespace libtorrent { namespace
if (!send_peer(*i->second)) continue;
// don't write too big of a package
if (num_added >= max_peer_entries) continue;
if (num_added >= max_peer_entries) break;
// only send proper bittorrent peers
bt_peer_connection* p = dynamic_cast<bt_peer_connection*>(i->second);
if (!p) continue;
// i->first was added since the last time
detail::write_endpoint(i->first, pla_out);
// no supported flags to set yet
// 0x01 - peer supports encryption
// 0x02 - peer is a seed
int flags = i->second->is_seed() ? 2 : 0;
int flags = p->is_seed() ? 2 : 0;
#ifndef TORRENT_DISABLE_ENCRYPTION
flags |= p->supports_encryption() ? 1 : 0;
#endif
detail::write_uint8(flags, plf_out);
++num_added;
}

View File

@ -15,6 +15,7 @@ test-suite libtorrent :
[ run test_storage.cpp ]
[ run test_piece_picker.cpp ]
# [ run test_entry.cpp ]
[ run test_pe_crypto.cpp ]
[ run test_bencoding.cpp ]
[ run test_primitives.cpp ]
[ run test_ip_filter.cpp ]

View File

@ -1,4 +1,4 @@
noinst_PROGRAMS = test_hasher test_bencoding test_ip_filter test_piece_picker test_storage test_metadata_extension test_buffer test_allocate_resources
noinst_PROGRAMS = test_hasher test_bencoding test_ip_filter test_piece_picker test_storage test_metadata_extension test_buffer test_allocate_resources test_pe_crypto
EXTRA_DIST = Jamfile
test_hasher_SOURCES = main.cpp test_hasher.cpp
@ -25,6 +25,9 @@ test_allocate_resources_LDADD = $(top_builddir)/src/libtorrent.la
test_metadata_extension_SOURCES = main.cpp setup_transfer.cpp test_metadata_extension.cpp
test_metadata_extension_LDADD = $(top_builddir)/src/libtorrent.la
test_pe_crypto_SOURCES = main.cpp test_pe_crypto.cpp
test_pe_crypto_LDADD = $(top_builddir)/src/libtorrent.la $(top_builddir)/test/setup_transfer.o
noinst_HEADERS = test.hpp setup_transfer.hpp
AM_CXXFLAGS=-ftemplate-depth-50 -I$(top_srcdir)/include -I$(top_srcdir)/include/libtorrent @DEBUGFLAGS@ @PTHREAD_CFLAGS@

View File

@ -22,7 +22,7 @@ void sleep(int msec)
using namespace libtorrent;
boost::tuple<torrent_handle, torrent_handle> setup_transfer(
session& ses1, session& ses2, bool clear_files)
session& ses1, session& ses2, bool clear_files, bool use_metadata_transfer)
{
using namespace boost::filesystem;
@ -59,8 +59,12 @@ boost::tuple<torrent_handle, torrent_handle> setup_transfer(
// file pool will complain if two torrents are trying to
// use the same files
torrent_handle tor1 = ses1.add_torrent(t, "./tmp1");
torrent_handle tor2 = ses2.add_torrent(tracker_url
torrent_handle tor2;
if (use_metadata_transfer)
tor2 = ses2.add_torrent(tracker_url
, t.info_hash(), 0, "./tmp2");
else
tor2 = ses2.add_torrent(t, "./tmp2");
sleep(100);

View File

@ -8,7 +8,7 @@
void sleep(int msec);
boost::tuple<libtorrent::torrent_handle, libtorrent::torrent_handle>
setup_transfer(libtorrent::session& ses1, libtorrent::session& ses2
, bool clear_files);
, bool clear_files, bool use_metadata_transfer = true);
#endif

194
test/test_pe_crypto.cpp Normal file
View File

@ -0,0 +1,194 @@
/*
Copyright (c) 2007, Un Shyam
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include <algorithm>
#include <iostream>
#include "libtorrent/hasher.hpp"
#include "libtorrent/pe_crypto.hpp"
#include "libtorrent/session.hpp"
#include "setup_transfer.hpp"
#include "test.hpp"
void display_pe_policy(libtorrent::pe_settings::enc_policy policy)
{
using namespace libtorrent;
using std::cerr;
if (policy == pe_settings::disabled) cerr << "disabled ";
else if (policy == pe_settings::enabled) cerr << "enabled ";
else if (policy == pe_settings::forced) cerr << "forced ";
}
void display_pe_settings(libtorrent::pe_settings s)
{
using namespace libtorrent;
using std::cerr;
cerr << "out_enc_policy - ";
display_pe_policy(s.out_enc_policy);
cerr << "\tin_enc_policy - ";
display_pe_policy(s.in_enc_policy);
cerr << "\nenc_level - ";
if (s.allowed_enc_level == pe_settings::plaintext) cerr << "plaintext ";
else if (s.allowed_enc_level == pe_settings::rc4) cerr << "rc4 ";
else if (s.allowed_enc_level == pe_settings::both) cerr << "both ";
cerr << "\t\tprefer_rc4 - ";
(s.prefer_rc4) ? cerr << "true" : cerr << "false";
cerr << "\n\n";
}
void test_transfer(libtorrent::pe_settings::enc_policy policy,
libtorrent::pe_settings::enc_level level = libtorrent::pe_settings::both,
bool pref_rc4 = false)
{
using namespace libtorrent;
using std::cerr;
session ses1(fingerprint("LT", 0, 1, 0, 0), std::make_pair(48000, 49000));
session ses2(fingerprint("LT", 0, 1, 0, 0), std::make_pair(49000, 50000));
pe_settings s;
s.out_enc_policy = libtorrent::pe_settings::enabled;
s.in_enc_policy = libtorrent::pe_settings::enabled;
s.allowed_enc_level = pe_settings::both;
ses2.set_pe_settings(s);
s.out_enc_policy = policy;
s.in_enc_policy = policy;
s.allowed_enc_level = level;
s.prefer_rc4 = pref_rc4;
ses1.set_pe_settings(s);
// s = ses1.get_pe_settings();
// cerr << " Session1 \n";
// display_pe_settings(s);
// s = ses2.get_pe_settings();
// cerr << " Session2 \n";
// display_pe_settings(s);
torrent_handle tor1;
torrent_handle tor2;
boost::tie(tor1, tor2) = setup_transfer(ses1, ses2, true, false);
std::cerr << "waiting for transfer to complete\n";
for (int i = 0; i < 50; ++i)
{
tor2.status();
std::auto_ptr<alert> a;
a = ses1.pop_alert();
if (a.get())
std::cerr << "ses1: " << a->msg() << "\n";
a = ses2.pop_alert();
if (a.get())
std::cerr << "ses2: " << a->msg() << "\n";
if (tor2.is_seed()) break;
sleep(100);
}
TEST_CHECK(tor2.is_seed());
if (tor2.is_seed()) std::cerr << "done\n";
}
int test_main()
{
using namespace libtorrent;
int repcount = 64;
for (int rep = 0; rep < repcount; ++rep)
{
DH_key_exchange DH1, DH2;
DH1.compute_secret(DH2.get_local_key());
DH2.compute_secret(DH1.get_local_key());
TEST_CHECK(std::equal(DH1.get_secret(), DH1.get_secret() + 96, DH2.get_secret()));
}
DH_key_exchange DH1, DH2;
DH1.compute_secret(DH2.get_local_key());
DH2.compute_secret(DH1.get_local_key());
TEST_CHECK(std::equal(DH1.get_secret(), DH1.get_secret() + 96, DH2.get_secret()));
sha1_hash test1_key = hasher("test1_key",8).final();
sha1_hash test2_key = hasher("test2_key",8).final();
RC4_handler RC41 (test2_key, test1_key);
RC4_handler RC42 (test1_key, test2_key);
for (int rep = 0; rep < repcount; ++rep)
{
std::size_t buf_len = rand() % (512 * 1024);
char* buf = new char[buf_len];
char* zero_buf = new char[buf_len];
std::fill(buf, buf + buf_len, 0);
std::fill(zero_buf, zero_buf + buf_len, 0);
RC41.encrypt(buf, buf_len);
RC42.decrypt(buf, buf_len);
TEST_CHECK(std::equal(buf, buf + buf_len, zero_buf));
RC42.encrypt(buf, buf_len);
RC41.decrypt(buf, buf_len);
TEST_CHECK(std::equal(buf, buf + buf_len, zero_buf));
delete[] buf;
delete[] zero_buf;
}
test_transfer(pe_settings::disabled);
test_transfer(pe_settings::forced, pe_settings::plaintext);
test_transfer(pe_settings::forced, pe_settings::rc4);
test_transfer(pe_settings::forced, pe_settings::both, false);
test_transfer(pe_settings::forced, pe_settings::both, true);
test_transfer(pe_settings::enabled, pe_settings::plaintext);
test_transfer(pe_settings::enabled, pe_settings::rc4);
test_transfer(pe_settings::enabled, pe_settings::both, false);
test_transfer(pe_settings::enabled, pe_settings::both, true);
return 0;
}