*** empty log message ***
This commit is contained in:
27
Jamfile
27
Jamfile
@@ -14,9 +14,8 @@ lib winsock : : <name>wsock32.lib ;
|
|||||||
project torrent
|
project torrent
|
||||||
: requirements
|
: requirements
|
||||||
|
|
||||||
: usage-requirements
|
|
||||||
|
|
||||||
<include>./include
|
<include>./include
|
||||||
|
<include>./zlib
|
||||||
<include>$(BOOST_ROOT)
|
<include>$(BOOST_ROOT)
|
||||||
<variant>release:<define>NDEBUG
|
<variant>release:<define>NDEBUG
|
||||||
<define>BOOST_ALL_NO_LIB
|
<define>BOOST_ALL_NO_LIB
|
||||||
@@ -38,6 +37,13 @@ project torrent
|
|||||||
|
|
||||||
<toolset>darwin:<cxxflags>-Wno-unused-variable
|
<toolset>darwin:<cxxflags>-Wno-unused-variable
|
||||||
|
|
||||||
|
: usage-requirements
|
||||||
|
|
||||||
|
<include>./include
|
||||||
|
<include>$(BOOST_ROOT)
|
||||||
|
<variant>release:<define>NDEBUG
|
||||||
|
<define>BOOST_ALL_NO_LIB
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
@@ -65,6 +71,21 @@ SOURCES =
|
|||||||
sha1.c
|
sha1.c
|
||||||
;
|
;
|
||||||
|
|
||||||
|
ZLIB_SOURCES =
|
||||||
|
adler32.c
|
||||||
|
compress.c
|
||||||
|
crc32.c
|
||||||
|
deflate.c
|
||||||
|
gzio.c
|
||||||
|
infback.c
|
||||||
|
inffast.c
|
||||||
|
inflate.c
|
||||||
|
inftrees.c
|
||||||
|
trees.c
|
||||||
|
uncompr.c
|
||||||
|
zutil.c
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
# some windows specific settings
|
# some windows specific settings
|
||||||
|
|
||||||
@@ -81,8 +102,8 @@ SOURCES =
|
|||||||
|
|
||||||
lib torrent
|
lib torrent
|
||||||
:
|
:
|
||||||
zlib//zlib
|
|
||||||
src/$(SOURCES)
|
src/$(SOURCES)
|
||||||
|
zlib/$(ZLIB_SOURCES)
|
||||||
$(LIBS)
|
$(LIBS)
|
||||||
/boost/thread//boost_thread
|
/boost/thread//boost_thread
|
||||||
/boost/filesystem//boost_filesystem/<link>static
|
/boost/filesystem//boost_filesystem/<link>static
|
||||||
|
@@ -100,18 +100,18 @@ The current state includes the following features:</p>
|
|||||||
<li>queues torrents for file check, instead of checking all of them in parallel.</li>
|
<li>queues torrents for file check, instead of checking all of them in parallel.</li>
|
||||||
<li>uses separate threads for checking files and for main downloader, with a fool-proof
|
<li>uses separate threads for checking files and for main downloader, with a fool-proof
|
||||||
thread-safe library interface. (i.e. There's no way for the user to cause a deadlock).</li>
|
thread-safe library interface. (i.e. There's no way for the user to cause a deadlock).</li>
|
||||||
<li>can limit the upload bandwidth usage and the maximum number of unchoked peers</li>
|
<li>can limit the upload and download bandwidth usage and the maximum number of unchoked peers</li>
|
||||||
<li>piece-wise file allocation</li>
|
<li>piece-wise, unordered, file allocation</li>
|
||||||
<li>implements fair trade. User settable trade-ratio, must at least be 1:1,
|
<li>implements fair trade. User settable trade-ratio, must at least be 1:1,
|
||||||
but one can choose to trade 1 for 2 or any other ratio that isn't unfair to the other
|
but one can choose to trade 1 for 2 or any other ratio that isn't unfair to the other
|
||||||
party.</li>
|
party. (i.e. real tit for tat)</li>
|
||||||
<li>fast resume support, a way to get rid of the costly piece check at the start
|
<li>fast resume support, a way to get rid of the costly piece check at the start
|
||||||
of a resumed torrent. Saves the storage state, piece_picker state as well as all local
|
of a resumed torrent. Saves the storage state, piece_picker state as well as all local
|
||||||
peers in a separate fast-resume file.</li>
|
peers in a separate fast-resume file.</li>
|
||||||
<li>supports the extension protocol <a class="reference" href="http://nolar.com/azureus/extended.htm">described by Nolar</a>. See <a class="reference" href="#extensions">extensions</a>.</li>
|
<li>supports the extension protocol <a class="reference" href="http://nolar.com/azureus/extended.htm">described by Nolar</a>. See <a class="reference" href="#extensions">extensions</a>.</li>
|
||||||
<li>supports files > 2 gigabytes (currently only on windows).</li>
|
<li>supports files > 2 gigabytes (currently only on windows).</li>
|
||||||
<li>supports the <tt class="literal"><span class="pre">no_peer_id=1</span></tt> extension that will ease the load off trackers.</li>
|
<li>supports the <tt class="literal"><span class="pre">no_peer_id=1</span></tt> extension that will ease the load off trackers.</li>
|
||||||
<li>supports the <a class="reference" href="udp_tracker_protocol.html">udp-tracker protocol</a>.</li>
|
<li>supports the <a class="reference" href="udp_tracker_protocol.html">udp-tracker protocol</a> by Olaf van der Spek.</li>
|
||||||
<li>possibility to limit the number of connections.</li>
|
<li>possibility to limit the number of connections.</li>
|
||||||
<li>delays have messages if there's no other outgoing traffic to the peer, and doesn't
|
<li>delays have messages if there's no other outgoing traffic to the peer, and doesn't
|
||||||
send have messages to peers that already has the piece. This saves bandwidth.</li>
|
send have messages to peers that already has the piece. This saves bandwidth.</li>
|
||||||
@@ -178,7 +178,7 @@ not support files larger than 2 Gigabytes.</p>
|
|||||||
<div class="section" id="cygwin-and-msvc">
|
<div class="section" id="cygwin-and-msvc">
|
||||||
<h2><a name="cygwin-and-msvc">cygwin and msvc</a></h2>
|
<h2><a name="cygwin-and-msvc">cygwin and msvc</a></h2>
|
||||||
<p>Note that if you're building on windows using the <tt class="literal"><span class="pre">msvc</span></tt> toolset, you cannot run it
|
<p>Note that if you're building on windows using the <tt class="literal"><span class="pre">msvc</span></tt> toolset, you cannot run it
|
||||||
from a cygwin terminal, you'll have to run it from a cmd terminal. The same goes for
|
from a cygwin terminal, you'll have to run it from a <tt class="literal"><span class="pre">cmd</span></tt> terminal. The same goes for
|
||||||
cygwin, if you're building with gcc (mingw) you'll have to run it from a cygwin terminal.
|
cygwin, if you're building with gcc (mingw) you'll have to run it from a cygwin terminal.
|
||||||
Also, make sure the paths are correct in the different environments. In cygwin, the paths
|
Also, make sure the paths are correct in the different environments. In cygwin, the paths
|
||||||
(<tt class="literal"><span class="pre">BOOST_BUILD_PATH</span></tt> and <tt class="literal"><span class="pre">BOOST_ROOT</span></tt>) should be in the typical unix-format (e.g.
|
(<tt class="literal"><span class="pre">BOOST_BUILD_PATH</span></tt> and <tt class="literal"><span class="pre">BOOST_ROOT</span></tt>) should be in the typical unix-format (e.g.
|
||||||
@@ -281,6 +281,7 @@ class session: public boost::noncopyable
|
|||||||
|
|
||||||
void set_http_settings(const http_settings& settings);
|
void set_http_settings(const http_settings& settings);
|
||||||
void set_upload_rate_limit(int bytes_per_second);
|
void set_upload_rate_limit(int bytes_per_second);
|
||||||
|
void set_download_rate_limit(int bytes_per_second);
|
||||||
|
|
||||||
bool is_listening() const;
|
bool is_listening() const;
|
||||||
unsigned short listen_port() const;
|
unsigned short listen_port() const;
|
||||||
@@ -298,7 +299,7 @@ class session: public boost::noncopyable
|
|||||||
The main thread will be idle as long it doesn't have any torrents to participate in.
|
The main thread will be idle as long it doesn't have any torrents to participate in.
|
||||||
You add torrents through the <tt class="literal"><span class="pre">add_torrent()</span></tt>-function where you give an
|
You add torrents through the <tt class="literal"><span class="pre">add_torrent()</span></tt>-function where you give an
|
||||||
object representing the information found in the torrent file and the path where you
|
object representing the information found in the torrent file and the path where you
|
||||||
want to save the files. The <tt class="literal"><span class="pre">save_path</span></tt> will be prepended to the directory-
|
want to save the files. The <tt class="literal"><span class="pre">save_path</span></tt> will be prepended to the directory
|
||||||
structure in the torrent-file. <tt class="literal"><span class="pre">add_torrent</span></tt> will throw <a class="reference" href="#duplicate-torrent">duplicate_torrent</a> exception
|
structure in the torrent-file. <tt class="literal"><span class="pre">add_torrent</span></tt> will throw <a class="reference" href="#duplicate-torrent">duplicate_torrent</a> exception
|
||||||
if the torrent already exists in the session.</p>
|
if the torrent already exists in the session.</p>
|
||||||
<p>The optional last parameter, <tt class="literal"><span class="pre">resume_data</span></tt> can be given if up to date fast-resume data
|
<p>The optional last parameter, <tt class="literal"><span class="pre">resume_data</span></tt> can be given if up to date fast-resume data
|
||||||
@@ -316,7 +317,9 @@ the peer-id to identify the client and the client's version. For more details se
|
|||||||
fingerprint class.</p>
|
fingerprint class.</p>
|
||||||
<p><tt class="literal"><span class="pre">set_upload_rate_limit()</span></tt> set the maximum number of bytes allowed to be
|
<p><tt class="literal"><span class="pre">set_upload_rate_limit()</span></tt> set the maximum number of bytes allowed to be
|
||||||
sent to peers per second. This bandwidth is distributed among all the peers. If
|
sent to peers per second. This bandwidth is distributed among all the peers. If
|
||||||
you don't want to limit upload rate, you can set this to -1 (the default).</p>
|
you don't want to limit upload rate, you can set this to -1 (the default).
|
||||||
|
<tt class="literal"><span class="pre">set_download_rate_limit()</span></tt> works the same way but for download rate instead
|
||||||
|
of upload rate.</p>
|
||||||
<p><tt class="literal"><span class="pre">is_listening()</span></tt> will tell you wether or not the session has successfully
|
<p><tt class="literal"><span class="pre">is_listening()</span></tt> will tell you wether or not the session has successfully
|
||||||
opened a listening port. If it hasn't, this function will return false, and
|
opened a listening port. If it hasn't, this function will return false, and
|
||||||
then you can use <tt class="literal"><span class="pre">listen_on()</span></tt> to make another try.</p>
|
then you can use <tt class="literal"><span class="pre">listen_on()</span></tt> to make another try.</p>
|
||||||
@@ -400,10 +403,10 @@ class entry
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
typedef std::map<std::string, entry> dictionary_type;
|
typedef std::list<std::pair<std::string, entry> > dictionary_type;
|
||||||
typedef std::string string_type;
|
typedef std::string string_type;
|
||||||
typedef std::vector<entry> list_type;
|
typedef std::list<entry> list_type;
|
||||||
typedef implementation-defined integer_type;
|
typedef size_type integer_type;
|
||||||
|
|
||||||
enum data_type
|
enum data_type
|
||||||
{
|
{
|
||||||
@@ -424,7 +427,6 @@ public:
|
|||||||
entry();
|
entry();
|
||||||
entry(data_type t);
|
entry(data_type t);
|
||||||
entry(const entry& e);
|
entry(const entry& e);
|
||||||
|
|
||||||
~entry();
|
~entry();
|
||||||
|
|
||||||
void operator=(const entry& e);
|
void operator=(const entry& e);
|
||||||
@@ -433,7 +435,7 @@ public:
|
|||||||
void operator=(const list_type&);
|
void operator=(const list_type&);
|
||||||
void operator=(const integer_type&);
|
void operator=(const integer_type&);
|
||||||
|
|
||||||
integer_type& integer()
|
integer_type& integer();
|
||||||
const integer_type& integer() const;
|
const integer_type& integer() const;
|
||||||
string_type& string();
|
string_type& string();
|
||||||
const string_type& string() const;
|
const string_type& string() const;
|
||||||
@@ -442,6 +444,15 @@ public:
|
|||||||
dictionary_type& dict();
|
dictionary_type& dict();
|
||||||
const dictionary_type& dict() const;
|
const dictionary_type& dict() const;
|
||||||
|
|
||||||
|
// these functions requires that the entry
|
||||||
|
// is a dictionary, otherwise they will throw
|
||||||
|
entry& operator[](char const* key);
|
||||||
|
entry& operator[](std::string const& key);
|
||||||
|
const entry& operator[](char const* key) const;
|
||||||
|
const entry& operator[](std::string const& key) const;
|
||||||
|
entry* find_key(char const* key);
|
||||||
|
entry const* find_key(char const* key) const;
|
||||||
|
|
||||||
void print(std::ostream& os, int indent = 0) const;
|
void print(std::ostream& os, int indent = 0) const;
|
||||||
};
|
};
|
||||||
</pre>
|
</pre>
|
||||||
@@ -587,11 +598,13 @@ struct torrent_handle
|
|||||||
void force_reannounce();
|
void force_reannounce();
|
||||||
void connect_peer(const address& adr) const;
|
void connect_peer(const address& adr) const;
|
||||||
|
|
||||||
void set_ratio(float ratio);
|
|
||||||
void set_tracker_login(std::string const& username, std::string const& password);
|
void set_tracker_login(std::string const& username, std::string const& password);
|
||||||
|
|
||||||
|
void set_ratio(float ratio);
|
||||||
void set_max_uploads(int max_uploads);
|
void set_max_uploads(int max_uploads);
|
||||||
void set_max_connections(int max_connections);
|
void set_max_connections(int max_connections);
|
||||||
void set_upload_limit(int limit);
|
void set_upload_limit(int limit);
|
||||||
|
void set_download_limit(int limit);
|
||||||
void use_interface(const char* net_interface);
|
void use_interface(const char* net_interface);
|
||||||
|
|
||||||
void pause();
|
void pause();
|
||||||
@@ -628,7 +641,11 @@ attempt to upload in return for each download. e.g. if set to 2, the client will
|
|||||||
2 bytes for every byte received. The default setting for this is 0, which will make it work
|
2 bytes for every byte received. The default setting for this is 0, which will make it work
|
||||||
as a standard client.</p>
|
as a standard client.</p>
|
||||||
<p><tt class="literal"><span class="pre">set_upload_limit</span></tt> will limit the upload bandwidth used by this particular torrent to the
|
<p><tt class="literal"><span class="pre">set_upload_limit</span></tt> will limit the upload bandwidth used by this particular torrent to the
|
||||||
limit you set. It is given as the number of bytes per second the torrent is allowed to upload.</p>
|
limit you set. It is given as the number of bytes per second the torrent is allowed to upload.
|
||||||
|
<tt class="literal"><span class="pre">set_download_limit</span></tt> works the same way but for download bandwidth instead of upload bandwidth.
|
||||||
|
Note that setting i higher limit on a torrent then the global limit (<tt class="literal"><span class="pre">session::set_upload_rate_limit</span></tt>)
|
||||||
|
will not override the global rate limit. The torrent can never upload more than the global rate
|
||||||
|
limit.</p>
|
||||||
<p><tt class="literal"><span class="pre">pause()</span></tt>, and <tt class="literal"><span class="pre">resume()</span></tt> will disconnect all peers and reconnect all peers respectively.
|
<p><tt class="literal"><span class="pre">pause()</span></tt>, and <tt class="literal"><span class="pre">resume()</span></tt> will disconnect all peers and reconnect all peers respectively.
|
||||||
When a torrent is paused, it will however remember all share ratios to all peers and remember
|
When a torrent is paused, it will however remember all share ratios to all peers and remember
|
||||||
all potential (not connected) peers. You can use <tt class="literal"><span class="pre">is_paused()</span></tt> to determine if a torrent
|
all potential (not connected) peers. You can use <tt class="literal"><span class="pre">is_paused()</span></tt> to determine if a torrent
|
||||||
@@ -1235,7 +1252,7 @@ to the torrent that this peer was a member of.</p>
|
|||||||
<pre class="literal-block">
|
<pre class="literal-block">
|
||||||
struct peer_ban_alert: alert
|
struct peer_ban_alert: alert
|
||||||
{
|
{
|
||||||
peer_error_alert(
|
peer_ban_alert(
|
||||||
address const& pip
|
address const& pip
|
||||||
, torrent_handle h
|
, torrent_handle h
|
||||||
, const std::string& msg);
|
, const std::string& msg);
|
||||||
@@ -1255,10 +1272,15 @@ is generated as severity level <tt class="literal"><span class="pre">debug</span
|
|||||||
<pre class="literal-block">
|
<pre class="literal-block">
|
||||||
struct peer_error_alert: alert
|
struct peer_error_alert: alert
|
||||||
{
|
{
|
||||||
peer_error_alert(const address& pid, const std::string& msg);
|
peer_error_alert(
|
||||||
|
address const& pip
|
||||||
|
, peer_id const& pid
|
||||||
|
, const std::string& msg);
|
||||||
|
|
||||||
virtual std::auto_ptr<alert> clone() const;
|
virtual std::auto_ptr<alert> clone() const;
|
||||||
|
|
||||||
address ip;
|
address ip;
|
||||||
|
peer_id id;
|
||||||
};
|
};
|
||||||
</pre>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
@@ -1272,16 +1294,18 @@ is a handle to the torrent the peer is a member of. <tt class="literal"><span cl
|
|||||||
struct invalid_request_alert: alert
|
struct invalid_request_alert: alert
|
||||||
{
|
{
|
||||||
invalid_request_alert(
|
invalid_request_alert(
|
||||||
const peer_request& r
|
peer_request const& r
|
||||||
, const torrent_handle& h
|
, torrent_handle const& h
|
||||||
, const address& send
|
, address const& send
|
||||||
, const std::string& msg);
|
, peer_id const& pid
|
||||||
|
, std::string const& msg);
|
||||||
|
|
||||||
virtual std::auto_ptr<alert> clone() const;
|
virtual std::auto_ptr<alert> clone() const;
|
||||||
|
|
||||||
torrent_handle handle;
|
torrent_handle handle;
|
||||||
address ip;
|
address ip;
|
||||||
peer_request request;
|
peer_request request;
|
||||||
|
peer_id id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -1290,7 +1314,7 @@ struct peer_request
|
|||||||
int piece;
|
int piece;
|
||||||
int start;
|
int start;
|
||||||
int length;
|
int length;
|
||||||
bool operator==(const peer_request& r);
|
bool operator==(peer_request const& r) const;
|
||||||
};
|
};
|
||||||
</pre>
|
</pre>
|
||||||
<p>The <tt class="literal"><span class="pre">peer_request</span></tt> contains the values the client sent in its <tt class="literal"><span class="pre">request</span></tt> message. <tt class="literal"><span class="pre">piece</span></tt> is
|
<p>The <tt class="literal"><span class="pre">peer_request</span></tt> contains the values the client sent in its <tt class="literal"><span class="pre">request</span></tt> message. <tt class="literal"><span class="pre">piece</span></tt> is
|
||||||
|
@@ -29,18 +29,18 @@ The current state includes the following features:
|
|||||||
* queues torrents for file check, instead of checking all of them in parallel.
|
* queues torrents for file check, instead of checking all of them in parallel.
|
||||||
* uses separate threads for checking files and for main downloader, with a fool-proof
|
* uses separate threads for checking files and for main downloader, with a fool-proof
|
||||||
thread-safe library interface. (i.e. There's no way for the user to cause a deadlock).
|
thread-safe library interface. (i.e. There's no way for the user to cause a deadlock).
|
||||||
* can limit the upload bandwidth usage and the maximum number of unchoked peers
|
* can limit the upload and download bandwidth usage and the maximum number of unchoked peers
|
||||||
* piece-wise file allocation
|
* piece-wise, unordered, file allocation
|
||||||
* implements fair trade. User settable trade-ratio, must at least be 1:1,
|
* implements fair trade. User settable trade-ratio, must at least be 1:1,
|
||||||
but one can choose to trade 1 for 2 or any other ratio that isn't unfair to the other
|
but one can choose to trade 1 for 2 or any other ratio that isn't unfair to the other
|
||||||
party.
|
party. (i.e. real tit for tat)
|
||||||
* fast resume support, a way to get rid of the costly piece check at the start
|
* fast resume support, a way to get rid of the costly piece check at the start
|
||||||
of a resumed torrent. Saves the storage state, piece_picker state as well as all local
|
of a resumed torrent. Saves the storage state, piece_picker state as well as all local
|
||||||
peers in a separate fast-resume file.
|
peers in a separate fast-resume file.
|
||||||
* supports the extension protocol `described by Nolar`__. See extensions_.
|
* supports the extension protocol `described by Nolar`__. See extensions_.
|
||||||
* supports files > 2 gigabytes (currently only on windows).
|
* supports files > 2 gigabytes (currently only on windows).
|
||||||
* supports the ``no_peer_id=1`` extension that will ease the load off trackers.
|
* supports the ``no_peer_id=1`` extension that will ease the load off trackers.
|
||||||
* supports the `udp-tracker protocol`__.
|
* supports the `udp-tracker protocol`__ by Olaf van der Spek.
|
||||||
* possibility to limit the number of connections.
|
* possibility to limit the number of connections.
|
||||||
* delays have messages if there's no other outgoing traffic to the peer, and doesn't
|
* delays have messages if there's no other outgoing traffic to the peer, and doesn't
|
||||||
send have messages to peers that already has the piece. This saves bandwidth.
|
send have messages to peers that already has the piece. This saves bandwidth.
|
||||||
@@ -129,7 +129,7 @@ cygwin and msvc
|
|||||||
---------------
|
---------------
|
||||||
|
|
||||||
Note that if you're building on windows using the ``msvc`` toolset, you cannot run it
|
Note that if you're building on windows using the ``msvc`` toolset, you cannot run it
|
||||||
from a cygwin terminal, you'll have to run it from a cmd terminal. The same goes for
|
from a cygwin terminal, you'll have to run it from a ``cmd`` terminal. The same goes for
|
||||||
cygwin, if you're building with gcc (mingw) you'll have to run it from a cygwin terminal.
|
cygwin, if you're building with gcc (mingw) you'll have to run it from a cygwin terminal.
|
||||||
Also, make sure the paths are correct in the different environments. In cygwin, the paths
|
Also, make sure the paths are correct in the different environments. In cygwin, the paths
|
||||||
(``BOOST_BUILD_PATH`` and ``BOOST_ROOT``) should be in the typical unix-format (e.g.
|
(``BOOST_BUILD_PATH`` and ``BOOST_ROOT``) should be in the typical unix-format (e.g.
|
||||||
@@ -225,6 +225,7 @@ The ``session`` class has the following synopsis::
|
|||||||
|
|
||||||
void set_http_settings(const http_settings& settings);
|
void set_http_settings(const http_settings& settings);
|
||||||
void set_upload_rate_limit(int bytes_per_second);
|
void set_upload_rate_limit(int bytes_per_second);
|
||||||
|
void set_download_rate_limit(int bytes_per_second);
|
||||||
|
|
||||||
bool is_listening() const;
|
bool is_listening() const;
|
||||||
unsigned short listen_port() const;
|
unsigned short listen_port() const;
|
||||||
@@ -242,7 +243,7 @@ Once it's created, it will spawn the main thread that will do all the work.
|
|||||||
The main thread will be idle as long it doesn't have any torrents to participate in.
|
The main thread will be idle as long it doesn't have any torrents to participate in.
|
||||||
You add torrents through the ``add_torrent()``-function where you give an
|
You add torrents through the ``add_torrent()``-function where you give an
|
||||||
object representing the information found in the torrent file and the path where you
|
object representing the information found in the torrent file and the path where you
|
||||||
want to save the files. The ``save_path`` will be prepended to the directory-
|
want to save the files. The ``save_path`` will be prepended to the directory
|
||||||
structure in the torrent-file. ``add_torrent`` will throw duplicate_torrent_ exception
|
structure in the torrent-file. ``add_torrent`` will throw duplicate_torrent_ exception
|
||||||
if the torrent already exists in the session.
|
if the torrent already exists in the session.
|
||||||
|
|
||||||
@@ -266,6 +267,8 @@ fingerprint class.
|
|||||||
``set_upload_rate_limit()`` set the maximum number of bytes allowed to be
|
``set_upload_rate_limit()`` set the maximum number of bytes allowed to be
|
||||||
sent to peers per second. This bandwidth is distributed among all the peers. If
|
sent to peers per second. This bandwidth is distributed among all the peers. If
|
||||||
you don't want to limit upload rate, you can set this to -1 (the default).
|
you don't want to limit upload rate, you can set this to -1 (the default).
|
||||||
|
``set_download_rate_limit()`` works the same way but for download rate instead
|
||||||
|
of upload rate.
|
||||||
|
|
||||||
``is_listening()`` will tell you wether or not the session has successfully
|
``is_listening()`` will tell you wether or not the session has successfully
|
||||||
opened a listening port. If it hasn't, this function will return false, and
|
opened a listening port. If it hasn't, this function will return false, and
|
||||||
@@ -374,10 +377,10 @@ or a string. This is its synopsis::
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
typedef std::map<std::string, entry> dictionary_type;
|
typedef std::list<std::pair<std::string, entry> > dictionary_type;
|
||||||
typedef std::string string_type;
|
typedef std::string string_type;
|
||||||
typedef std::vector<entry> list_type;
|
typedef std::list<entry> list_type;
|
||||||
typedef implementation-defined integer_type;
|
typedef size_type integer_type;
|
||||||
|
|
||||||
enum data_type
|
enum data_type
|
||||||
{
|
{
|
||||||
@@ -398,7 +401,6 @@ or a string. This is its synopsis::
|
|||||||
entry();
|
entry();
|
||||||
entry(data_type t);
|
entry(data_type t);
|
||||||
entry(const entry& e);
|
entry(const entry& e);
|
||||||
|
|
||||||
~entry();
|
~entry();
|
||||||
|
|
||||||
void operator=(const entry& e);
|
void operator=(const entry& e);
|
||||||
@@ -407,7 +409,7 @@ or a string. This is its synopsis::
|
|||||||
void operator=(const list_type&);
|
void operator=(const list_type&);
|
||||||
void operator=(const integer_type&);
|
void operator=(const integer_type&);
|
||||||
|
|
||||||
integer_type& integer()
|
integer_type& integer();
|
||||||
const integer_type& integer() const;
|
const integer_type& integer() const;
|
||||||
string_type& string();
|
string_type& string();
|
||||||
const string_type& string() const;
|
const string_type& string() const;
|
||||||
@@ -416,6 +418,15 @@ or a string. This is its synopsis::
|
|||||||
dictionary_type& dict();
|
dictionary_type& dict();
|
||||||
const dictionary_type& dict() const;
|
const dictionary_type& dict() const;
|
||||||
|
|
||||||
|
// these functions requires that the entry
|
||||||
|
// is a dictionary, otherwise they will throw
|
||||||
|
entry& operator[](char const* key);
|
||||||
|
entry& operator[](std::string const& key);
|
||||||
|
const entry& operator[](char const* key) const;
|
||||||
|
const entry& operator[](std::string const& key) const;
|
||||||
|
entry* find_key(char const* key);
|
||||||
|
entry const* find_key(char const* key) const;
|
||||||
|
|
||||||
void print(std::ostream& os, int indent = 0) const;
|
void print(std::ostream& os, int indent = 0) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -586,11 +597,13 @@ Its declaration looks like this::
|
|||||||
void force_reannounce();
|
void force_reannounce();
|
||||||
void connect_peer(const address& adr) const;
|
void connect_peer(const address& adr) const;
|
||||||
|
|
||||||
void set_ratio(float ratio);
|
|
||||||
void set_tracker_login(std::string const& username, std::string const& password);
|
void set_tracker_login(std::string const& username, std::string const& password);
|
||||||
|
|
||||||
|
void set_ratio(float ratio);
|
||||||
void set_max_uploads(int max_uploads);
|
void set_max_uploads(int max_uploads);
|
||||||
void set_max_connections(int max_connections);
|
void set_max_connections(int max_connections);
|
||||||
void set_upload_limit(int limit);
|
void set_upload_limit(int limit);
|
||||||
|
void set_download_limit(int limit);
|
||||||
void use_interface(const char* net_interface);
|
void use_interface(const char* net_interface);
|
||||||
|
|
||||||
void pause();
|
void pause();
|
||||||
@@ -634,6 +647,10 @@ as a standard client.
|
|||||||
|
|
||||||
``set_upload_limit`` will limit the upload bandwidth used by this particular torrent to the
|
``set_upload_limit`` will limit the upload bandwidth used by this particular torrent to the
|
||||||
limit you set. It is given as the number of bytes per second the torrent is allowed to upload.
|
limit you set. It is given as the number of bytes per second the torrent is allowed to upload.
|
||||||
|
``set_download_limit`` works the same way but for download bandwidth instead of upload bandwidth.
|
||||||
|
Note that setting i higher limit on a torrent then the global limit (``session::set_upload_rate_limit``)
|
||||||
|
will not override the global rate limit. The torrent can never upload more than the global rate
|
||||||
|
limit.
|
||||||
|
|
||||||
``pause()``, and ``resume()`` will disconnect all peers and reconnect all peers respectively.
|
``pause()``, and ``resume()`` will disconnect all peers and reconnect all peers respectively.
|
||||||
When a torrent is paused, it will however remember all share ratios to all peers and remember
|
When a torrent is paused, it will however remember all share ratios to all peers and remember
|
||||||
@@ -1300,7 +1317,7 @@ to the torrent that this peer was a member of.
|
|||||||
|
|
||||||
struct peer_ban_alert: alert
|
struct peer_ban_alert: alert
|
||||||
{
|
{
|
||||||
peer_error_alert(
|
peer_ban_alert(
|
||||||
address const& pip
|
address const& pip
|
||||||
, torrent_handle h
|
, torrent_handle h
|
||||||
, const std::string& msg);
|
, const std::string& msg);
|
||||||
@@ -1323,10 +1340,15 @@ is generated as severity level ``debug``.
|
|||||||
|
|
||||||
struct peer_error_alert: alert
|
struct peer_error_alert: alert
|
||||||
{
|
{
|
||||||
peer_error_alert(const address& pid, const std::string& msg);
|
peer_error_alert(
|
||||||
|
address const& pip
|
||||||
|
, peer_id const& pid
|
||||||
|
, const std::string& msg);
|
||||||
|
|
||||||
virtual std::auto_ptr<alert> clone() const;
|
virtual std::auto_ptr<alert> clone() const;
|
||||||
|
|
||||||
address ip;
|
address ip;
|
||||||
|
peer_id id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -1343,16 +1365,18 @@ is a handle to the torrent the peer is a member of. ``
|
|||||||
struct invalid_request_alert: alert
|
struct invalid_request_alert: alert
|
||||||
{
|
{
|
||||||
invalid_request_alert(
|
invalid_request_alert(
|
||||||
const peer_request& r
|
peer_request const& r
|
||||||
, const torrent_handle& h
|
, torrent_handle const& h
|
||||||
, const address& send
|
, address const& send
|
||||||
, const std::string& msg);
|
, peer_id const& pid
|
||||||
|
, std::string const& msg);
|
||||||
|
|
||||||
virtual std::auto_ptr<alert> clone() const;
|
virtual std::auto_ptr<alert> clone() const;
|
||||||
|
|
||||||
torrent_handle handle;
|
torrent_handle handle;
|
||||||
address ip;
|
address ip;
|
||||||
peer_request request;
|
peer_request request;
|
||||||
|
peer_id id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -1361,7 +1385,7 @@ is a handle to the torrent the peer is a member of. ``
|
|||||||
int piece;
|
int piece;
|
||||||
int start;
|
int start;
|
||||||
int length;
|
int length;
|
||||||
bool operator==(const peer_request& r);
|
bool operator==(peer_request const& r) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -245,7 +245,7 @@ int main(int argc, char* argv[])
|
|||||||
std::make_pair(6881, 6889)
|
std::make_pair(6881, 6889)
|
||||||
, fingerprint("LT", 0, 1, 0, 0));
|
, fingerprint("LT", 0, 1, 0, 0));
|
||||||
|
|
||||||
ses.set_upload_rate_limit(20 * 1024);
|
ses.set_upload_rate_limit(100000);
|
||||||
ses.set_http_settings(settings);
|
ses.set_http_settings(settings);
|
||||||
ses.set_severity_level(alert::debug);
|
ses.set_severity_level(alert::debug);
|
||||||
|
|
||||||
@@ -345,16 +345,29 @@ int main(int argc, char* argv[])
|
|||||||
a = ses.pop_alert();
|
a = ses.pop_alert();
|
||||||
while (a.get())
|
while (a.get())
|
||||||
{
|
{
|
||||||
torrent_finished_alert* p = dynamic_cast<torrent_finished_alert*>(a.get());
|
if (torrent_finished_alert* p = dynamic_cast<torrent_finished_alert*>(a.get()))
|
||||||
if (p)
|
|
||||||
{
|
{
|
||||||
// limit the bandwidth for all seeding torrents
|
// limit the bandwidth for all seeding torrents
|
||||||
p->handle.set_max_connections(10);
|
p->handle.set_max_connections(10);
|
||||||
p->handle.set_max_uploads(5);
|
p->handle.set_max_uploads(5);
|
||||||
p->handle.set_upload_limit(30000);
|
p->handle.set_upload_limit(10000);
|
||||||
|
events.push_back(
|
||||||
|
p->handle.get_torrent_info().name() + ": " + a->msg());
|
||||||
}
|
}
|
||||||
|
else if (peer_error_alert* p = dynamic_cast<peer_error_alert*>(a.get()))
|
||||||
|
{
|
||||||
|
events.push_back(identify_client(p->id) + ": " + a->msg());
|
||||||
|
}
|
||||||
|
else if (invalid_request_alert* p = dynamic_cast<invalid_request_alert*>(a.get()))
|
||||||
|
{
|
||||||
|
events.push_back(identify_client(p->id) + ": " + a->msg());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
events.push_back(a->msg());
|
||||||
|
}
|
||||||
|
|
||||||
if (events.size() >= 10) events.pop_front();
|
if (events.size() >= 10) events.pop_front();
|
||||||
events.push_back(a->msg());
|
|
||||||
a = ses.pop_alert();
|
a = ses.pop_alert();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -90,15 +90,17 @@ namespace libtorrent
|
|||||||
|
|
||||||
struct peer_error_alert: alert
|
struct peer_error_alert: alert
|
||||||
{
|
{
|
||||||
peer_error_alert(const address& pip, const std::string& msg)
|
peer_error_alert(address const& pip, peer_id const& pid, const std::string& msg)
|
||||||
: alert(alert::debug, msg)
|
: alert(alert::debug, msg)
|
||||||
, ip(pip)
|
, ip(pip)
|
||||||
|
, id(pid)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
virtual std::auto_ptr<alert> clone() const
|
virtual std::auto_ptr<alert> clone() const
|
||||||
{ return std::auto_ptr<alert>(new peer_error_alert(*this)); }
|
{ return std::auto_ptr<alert>(new peer_error_alert(*this)); }
|
||||||
|
|
||||||
address ip;
|
address ip;
|
||||||
|
peer_id id;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct chat_message_alert: alert
|
struct chat_message_alert: alert
|
||||||
@@ -122,14 +124,16 @@ namespace libtorrent
|
|||||||
struct invalid_request_alert: alert
|
struct invalid_request_alert: alert
|
||||||
{
|
{
|
||||||
invalid_request_alert(
|
invalid_request_alert(
|
||||||
const peer_request& r
|
peer_request const& r
|
||||||
, const torrent_handle& h
|
, torrent_handle const& h
|
||||||
, const address& sender
|
, address const& sender
|
||||||
, const std::string& msg)
|
, peer_id const& pid
|
||||||
|
, std::string const& msg)
|
||||||
: alert(alert::debug, msg)
|
: alert(alert::debug, msg)
|
||||||
, handle(h)
|
, handle(h)
|
||||||
, ip(sender)
|
, ip(sender)
|
||||||
, request(r)
|
, request(r)
|
||||||
|
, id(pid)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
virtual std::auto_ptr<alert> clone() const
|
virtual std::auto_ptr<alert> clone() const
|
||||||
@@ -138,6 +142,7 @@ namespace libtorrent
|
|||||||
torrent_handle handle;
|
torrent_handle handle;
|
||||||
address ip;
|
address ip;
|
||||||
peer_request request;
|
peer_request request;
|
||||||
|
peer_id id;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct torrent_finished_alert: alert
|
struct torrent_finished_alert: alert
|
||||||
|
@@ -107,10 +107,10 @@ namespace libtorrent
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// we need a vector here to maintain the order
|
// we need a list here instead of a map, to maintain
|
||||||
// of elements. Since the info-hash is reconstructed
|
// the order of elements. Since the info-hash is
|
||||||
// from an entry, it's important that the order is
|
// reconstructed from an entry, it's important that
|
||||||
// preserved.
|
// the order is preserved.
|
||||||
typedef std::list<std::pair<std::string, entry> > dictionary_type;
|
typedef std::list<std::pair<std::string, entry> > dictionary_type;
|
||||||
typedef std::string string_type;
|
typedef std::string string_type;
|
||||||
typedef std::list<entry> list_type;
|
typedef std::list<entry> list_type;
|
||||||
@@ -125,76 +125,32 @@ namespace libtorrent
|
|||||||
undefined_t
|
undefined_t
|
||||||
};
|
};
|
||||||
|
|
||||||
data_type type() const { return m_type; }
|
data_type type() const;
|
||||||
|
|
||||||
entry(const dictionary_type&);
|
entry(const dictionary_type&);
|
||||||
entry(const string_type&);
|
entry(const string_type&);
|
||||||
entry(const list_type&);
|
entry(const list_type&);
|
||||||
entry(const integer_type&);
|
entry(const integer_type&);
|
||||||
|
|
||||||
entry(): m_type(undefined_t) {}
|
entry();
|
||||||
entry(data_type t): m_type(t) { construct(t); }
|
entry(data_type t);
|
||||||
entry(const entry& e) { copy(e); }
|
entry(const entry& e);
|
||||||
~entry() { destruct(); }
|
~entry();
|
||||||
|
|
||||||
void operator=(const entry& e)
|
|
||||||
{
|
|
||||||
destruct();
|
|
||||||
copy(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
void operator=(const entry& e);
|
||||||
void operator=(const dictionary_type&);
|
void operator=(const dictionary_type&);
|
||||||
void operator=(const string_type&);
|
void operator=(const string_type&);
|
||||||
void operator=(const list_type&);
|
void operator=(const list_type&);
|
||||||
void operator=(const integer_type&);
|
void operator=(const integer_type&);
|
||||||
|
|
||||||
integer_type& integer()
|
integer_type& integer();
|
||||||
{
|
const integer_type& integer() const;
|
||||||
if (m_type != int_t) throw type_error("invalid type requested from entry");
|
string_type& string();
|
||||||
return *reinterpret_cast<integer_type*>(data);
|
const string_type& string() const;
|
||||||
}
|
list_type& list();
|
||||||
|
const list_type& list() const;
|
||||||
const integer_type& integer() const
|
dictionary_type& dict();
|
||||||
{
|
const dictionary_type& dict() const;
|
||||||
if (m_type != int_t) throw type_error("invalid type requested from entry");
|
|
||||||
return *reinterpret_cast<const integer_type*>(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
string_type& string()
|
|
||||||
{
|
|
||||||
if (m_type != string_t) throw type_error("invalid type requested from entry");
|
|
||||||
return *reinterpret_cast<string_type*>(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
const string_type& string() const
|
|
||||||
{
|
|
||||||
if (m_type != string_t) throw type_error("invalid type requested from entry");
|
|
||||||
return *reinterpret_cast<const string_type*>(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
list_type& list()
|
|
||||||
{
|
|
||||||
if (m_type != list_t) throw type_error("invalid type requested from entry");
|
|
||||||
return *reinterpret_cast<list_type*>(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
const list_type& list() const
|
|
||||||
{
|
|
||||||
if (m_type != list_t) throw type_error("invalid type requested from entry");
|
|
||||||
return *reinterpret_cast<const list_type*>(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
dictionary_type& dict()
|
|
||||||
{
|
|
||||||
if (m_type != dictionary_t) throw type_error("invalid type requested from entry");
|
|
||||||
return *reinterpret_cast<dictionary_type*>(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
const dictionary_type& dict() const
|
|
||||||
{
|
|
||||||
if (m_type != dictionary_t) throw type_error("invalid type requested from entry");
|
|
||||||
return *reinterpret_cast<const dictionary_type*>(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// these functions requires that the entry
|
// these functions requires that the entry
|
||||||
// is a dictionary, otherwise they will throw
|
// is a dictionary, otherwise they will throw
|
||||||
@@ -246,6 +202,67 @@ namespace libtorrent
|
|||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline entry::data_type entry::type() const { return m_type; }
|
||||||
|
|
||||||
|
inline entry::entry(): m_type(undefined_t) {}
|
||||||
|
inline entry::entry(data_type t): m_type(t) { construct(t); }
|
||||||
|
inline entry::entry(const entry& e) { copy(e); }
|
||||||
|
inline entry::~entry() { destruct(); }
|
||||||
|
|
||||||
|
inline void entry::operator=(const entry& e)
|
||||||
|
{
|
||||||
|
destruct();
|
||||||
|
copy(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline entry::integer_type& entry::integer()
|
||||||
|
{
|
||||||
|
if (m_type != int_t) throw type_error("invalid type requested from entry");
|
||||||
|
return *reinterpret_cast<integer_type*>(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline entry::integer_type const& entry::integer() const
|
||||||
|
{
|
||||||
|
if (m_type != int_t) throw type_error("invalid type requested from entry");
|
||||||
|
return *reinterpret_cast<const integer_type*>(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline entry::string_type& entry::string()
|
||||||
|
{
|
||||||
|
if (m_type != string_t) throw type_error("invalid type requested from entry");
|
||||||
|
return *reinterpret_cast<string_type*>(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline entry::string_type const& entry::string() const
|
||||||
|
{
|
||||||
|
if (m_type != string_t) throw type_error("invalid type requested from entry");
|
||||||
|
return *reinterpret_cast<const string_type*>(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline entry::list_type& entry::list()
|
||||||
|
{
|
||||||
|
if (m_type != list_t) throw type_error("invalid type requested from entry");
|
||||||
|
return *reinterpret_cast<list_type*>(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline entry::list_type const& entry::list() const
|
||||||
|
{
|
||||||
|
if (m_type != list_t) throw type_error("invalid type requested from entry");
|
||||||
|
return *reinterpret_cast<const list_type*>(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline entry::dictionary_type& entry::dict()
|
||||||
|
{
|
||||||
|
if (m_type != dictionary_t) throw type_error("invalid type requested from entry");
|
||||||
|
return *reinterpret_cast<dictionary_type*>(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline entry::dictionary_type const& entry::dict() const
|
||||||
|
{
|
||||||
|
if (m_type != dictionary_t) throw type_error("invalid type requested from entry");
|
||||||
|
return *reinterpret_cast<const dictionary_type*>(data);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // TORRENT_ENTRY_HPP_INCLUDED
|
#endif // TORRENT_ENTRY_HPP_INCLUDED
|
||||||
|
@@ -117,7 +117,9 @@ namespace libtorrent
|
|||||||
void receive_data();
|
void receive_data();
|
||||||
|
|
||||||
// tells if this connection has data it want to send
|
// tells if this connection has data it want to send
|
||||||
bool has_data() const;
|
// and has enough upload bandwidth quota left to send it.
|
||||||
|
bool can_write() const;
|
||||||
|
bool can_read() const;
|
||||||
|
|
||||||
bool is_seed() const;
|
bool is_seed() const;
|
||||||
|
|
||||||
@@ -171,13 +173,6 @@ namespace libtorrent
|
|||||||
void disconnect();
|
void disconnect();
|
||||||
bool is_disconnecting() const { return m_disconnecting; }
|
bool is_disconnecting() const { return m_disconnecting; }
|
||||||
|
|
||||||
// returns the send quota this peer has
|
|
||||||
// left until will stop sending.
|
|
||||||
// if the send_quota is -1, it means the
|
|
||||||
// quota is unlimited.
|
|
||||||
int send_quota_left() const;
|
|
||||||
resource_request* upload_bandwidth_quota();
|
|
||||||
|
|
||||||
// This is called for every peer right after the upload
|
// This is called for every peer right after the upload
|
||||||
// bandwidth has been distributed among them
|
// bandwidth has been distributed among them
|
||||||
// It will reset the used bandwidth to 0 and
|
// It will reset the used bandwidth to 0 and
|
||||||
@@ -248,7 +243,9 @@ namespace libtorrent
|
|||||||
|
|
||||||
// how much bandwidth we're using, how much we want,
|
// how much bandwidth we're using, how much we want,
|
||||||
// and how much we are allowed to use.
|
// and how much we are allowed to use.
|
||||||
resource_request m_upload_bandwidth_quota;
|
resource_request m_ul_bandwidth_quota;
|
||||||
|
resource_request m_dl_bandwidth_quota;
|
||||||
|
resource_request m_unchoked_quota;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@@ -340,8 +337,8 @@ namespace libtorrent
|
|||||||
boost::shared_ptr<libtorrent::socket> m_socket;
|
boost::shared_ptr<libtorrent::socket> m_socket;
|
||||||
|
|
||||||
// upload bandwidth used this second.
|
// upload bandwidth used this second.
|
||||||
// Must not exceed m_upload_bandwidth_quota.given.
|
// Must not exceed m_ul_bandwidth_quota.given.
|
||||||
// int m_upload_bandwidth_quota_used;
|
// int m_ul_bandwidth_quota_used;
|
||||||
|
|
||||||
// this is the torrent this connection is
|
// this is the torrent this connection is
|
||||||
// associated with. If the connection is an
|
// associated with. If the connection is an
|
||||||
@@ -372,7 +369,8 @@ namespace libtorrent
|
|||||||
// sent to this peer, we check this and
|
// sent to this peer, we check this and
|
||||||
// if it's not added to the selector we
|
// if it's not added to the selector we
|
||||||
// add it. (this is done in send_buffer_updated())
|
// add it. (this is done in send_buffer_updated())
|
||||||
bool m_added_to_selector;
|
bool m_writability_monitored;
|
||||||
|
bool m_readability_monitored;
|
||||||
|
|
||||||
// remote peer's id
|
// remote peer's id
|
||||||
peer_id m_peer_id;
|
peer_id m_peer_id;
|
||||||
|
@@ -40,7 +40,7 @@ namespace libtorrent
|
|||||||
int piece;
|
int piece;
|
||||||
int start;
|
int start;
|
||||||
int length;
|
int length;
|
||||||
bool operator==(const peer_request& r)
|
bool operator==(peer_request const& r) const
|
||||||
{ return piece == r.piece && start == r.start && length == r.length; }
|
{ return piece == r.piece && start == r.start && length == r.length; }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -44,6 +44,13 @@ namespace libtorrent
|
|||||||
, given(0)
|
, given(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
int left() const
|
||||||
|
{
|
||||||
|
assert(given >= used);
|
||||||
|
return given - used;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// I'm right now actively using:
|
// I'm right now actively using:
|
||||||
int used;
|
int used;
|
||||||
|
|
||||||
|
@@ -225,6 +225,7 @@ namespace libtorrent
|
|||||||
// bytes per second. -1 means
|
// bytes per second. -1 means
|
||||||
// unlimited
|
// unlimited
|
||||||
int m_upload_rate;
|
int m_upload_rate;
|
||||||
|
int m_download_rate;
|
||||||
|
|
||||||
// handles delayed alerts
|
// handles delayed alerts
|
||||||
alert_manager m_alerts;
|
alert_manager m_alerts;
|
||||||
@@ -292,6 +293,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
void set_http_settings(const http_settings& s);
|
void set_http_settings(const http_settings& s);
|
||||||
void set_upload_rate_limit(int bytes_per_second);
|
void set_upload_rate_limit(int bytes_per_second);
|
||||||
|
void set_download_rate_limit(int bytes_per_second);
|
||||||
|
|
||||||
// TODO: add a session_status that contain
|
// TODO: add a session_status that contain
|
||||||
// some indication of if the listen-port works
|
// some indication of if the listen-port works
|
||||||
|
@@ -240,12 +240,21 @@ namespace libtorrent
|
|||||||
void remove_writable(boost::shared_ptr<socket> s)
|
void remove_writable(boost::shared_ptr<socket> s)
|
||||||
{ m_writable.erase(std::find(m_writable.begin(), m_writable.end(), s)); }
|
{ m_writable.erase(std::find(m_writable.begin(), m_writable.end(), s)); }
|
||||||
|
|
||||||
|
void remove_readable(boost::shared_ptr<socket> s)
|
||||||
|
{ m_readable.erase(std::find(m_readable.begin(), m_readable.end(), s)); }
|
||||||
|
|
||||||
bool is_writability_monitored(boost::shared_ptr<socket> s)
|
bool is_writability_monitored(boost::shared_ptr<socket> s)
|
||||||
{
|
{
|
||||||
return std::find(m_writable.begin(), m_writable.end(), s)
|
return std::find(m_writable.begin(), m_writable.end(), s)
|
||||||
!= m_writable.end();
|
!= m_writable.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_readability_monitored(boost::shared_ptr<socket> s)
|
||||||
|
{
|
||||||
|
return std::find(m_readable.begin(), m_readable.end(), s)
|
||||||
|
!= m_readable.end();
|
||||||
|
}
|
||||||
|
|
||||||
void wait(int timeout
|
void wait(int timeout
|
||||||
, std::vector<boost::shared_ptr<socket> >& readable
|
, std::vector<boost::shared_ptr<socket> >& readable
|
||||||
, std::vector<boost::shared_ptr<socket> >& writable
|
, std::vector<boost::shared_ptr<socket> >& writable
|
||||||
|
@@ -92,27 +92,20 @@ namespace libtorrent
|
|||||||
|
|
||||||
~torrent();
|
~torrent();
|
||||||
|
|
||||||
|
// this will flag the torrent as aborted. The main
|
||||||
|
// loop in session_impl will check for this state
|
||||||
|
// on all torrents once every second, and take
|
||||||
|
// the necessary actions then.
|
||||||
void abort() { m_abort = true; m_event = tracker_request::stopped; }
|
void abort() { m_abort = true; m_event = tracker_request::stopped; }
|
||||||
bool is_aborted() const { return m_abort; }
|
bool is_aborted() const { return m_abort; }
|
||||||
|
|
||||||
// is called every second by session.
|
// is called every second by session. This will
|
||||||
|
// caclulate the upload/download and number
|
||||||
|
// of connections this torrent needs. And prepare
|
||||||
|
// it for being used by allocate_resources.
|
||||||
void second_tick();
|
void second_tick();
|
||||||
|
|
||||||
// returns true if it time for this torrent to make another
|
// debug purpose only
|
||||||
// tracker request
|
|
||||||
bool should_request() const
|
|
||||||
{
|
|
||||||
namespace time = boost::posix_time;
|
|
||||||
return !m_paused &&
|
|
||||||
m_next_request < time::second_clock::local_time();
|
|
||||||
}
|
|
||||||
|
|
||||||
void force_tracker_request()
|
|
||||||
{
|
|
||||||
namespace time = boost::posix_time;
|
|
||||||
m_next_request = time::second_clock::local_time();
|
|
||||||
}
|
|
||||||
|
|
||||||
void print(std::ostream& os) const;
|
void print(std::ostream& os) const;
|
||||||
|
|
||||||
void check_files(
|
void check_files(
|
||||||
@@ -132,13 +125,6 @@ namespace libtorrent
|
|||||||
void use_interface(const char* net_interface);
|
void use_interface(const char* net_interface);
|
||||||
peer_connection& connect_to_peer(const address& a);
|
peer_connection& connect_to_peer(const address& a);
|
||||||
|
|
||||||
const torrent_info& torrent_file() const
|
|
||||||
{ return m_torrent_file; }
|
|
||||||
|
|
||||||
policy& get_policy() { return *m_policy; }
|
|
||||||
|
|
||||||
piece_manager& filesystem() { return m_storage; }
|
|
||||||
|
|
||||||
void set_ratio(float ratio)
|
void set_ratio(float ratio)
|
||||||
{ assert(ratio >= 0.0f); m_ratio = ratio; }
|
{ assert(ratio >= 0.0f); m_ratio = ratio; }
|
||||||
|
|
||||||
@@ -169,10 +155,6 @@ namespace libtorrent
|
|||||||
// the number of peers that belong to this torrent
|
// the number of peers that belong to this torrent
|
||||||
int num_peers() const { return (int)m_connections.size(); }
|
int num_peers() const { return (int)m_connections.size(); }
|
||||||
|
|
||||||
// returns true if this torrent has a connection
|
|
||||||
// to a peer with the given peer_id
|
|
||||||
// bool has_peer(const peer_id& id) const;
|
|
||||||
|
|
||||||
typedef std::map<address, peer_connection*>::iterator peer_iterator;
|
typedef std::map<address, peer_connection*>::iterator peer_iterator;
|
||||||
typedef std::map<address, peer_connection*>::const_iterator const_peer_iterator;
|
typedef std::map<address, peer_connection*>::const_iterator const_peer_iterator;
|
||||||
|
|
||||||
@@ -186,8 +168,10 @@ namespace libtorrent
|
|||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// TRACKER MANAGEMENT
|
// TRACKER MANAGEMENT
|
||||||
|
|
||||||
// this is a callback called by the tracker_connection class
|
// these are callbacks called by the tracker_connection instance
|
||||||
|
// (either http_tracker_connection or udp_tracker_connection)
|
||||||
// when this torrent got a response from its tracker request
|
// when this torrent got a response from its tracker request
|
||||||
|
// or when a failure occured
|
||||||
virtual void tracker_response(std::vector<peer_entry>& e, int interval);
|
virtual void tracker_response(std::vector<peer_entry>& e, int interval);
|
||||||
virtual void tracker_request_timed_out();
|
virtual void tracker_request_timed_out();
|
||||||
virtual void tracker_request_error(int response_code, const std::string& str);
|
virtual void tracker_request_error(int response_code, const std::string& str);
|
||||||
@@ -195,10 +179,32 @@ namespace libtorrent
|
|||||||
// generates a request string for sending
|
// generates a request string for sending
|
||||||
// to the tracker
|
// to the tracker
|
||||||
tracker_request generate_tracker_request();
|
tracker_request generate_tracker_request();
|
||||||
std::string tracker_password() const;
|
|
||||||
|
|
||||||
boost::posix_time::ptime next_announce() const
|
// if no password and username is set
|
||||||
{ return m_next_request; }
|
// this will return an empty string, otherwise
|
||||||
|
// it will concatenate the login and password
|
||||||
|
// ready to be sent over http (but without
|
||||||
|
// base64 encoding).
|
||||||
|
std::string tracker_login() const;
|
||||||
|
|
||||||
|
// returns the absolute time when the next tracker
|
||||||
|
// announce will take place.
|
||||||
|
boost::posix_time::ptime next_announce() const;
|
||||||
|
|
||||||
|
// returns true if it is time for this torrent to make another
|
||||||
|
// tracker request
|
||||||
|
bool should_request() const;
|
||||||
|
|
||||||
|
// forcefully sets next_announce to the current time
|
||||||
|
void force_tracker_request();
|
||||||
|
|
||||||
|
// sets the username and password that will be sent to
|
||||||
|
// the tracker
|
||||||
|
void set_tracker_login(std::string const& name, std::string const& pw);
|
||||||
|
|
||||||
|
// the address of the tracker that we managed to
|
||||||
|
// announce ourself at the last time we tried to announce
|
||||||
|
const address& current_tracker() const;
|
||||||
|
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// PIECE MANAGEMENT
|
// PIECE MANAGEMENT
|
||||||
@@ -242,9 +248,6 @@ namespace libtorrent
|
|||||||
// all seeds and let the tracker know we're finished.
|
// all seeds and let the tracker know we're finished.
|
||||||
void completed();
|
void completed();
|
||||||
|
|
||||||
piece_picker& picker() { return m_picker; }
|
|
||||||
|
|
||||||
|
|
||||||
bool verify_piece(int piece_index);
|
bool verify_piece(int piece_index);
|
||||||
|
|
||||||
// this is called from the peer_connection
|
// this is called from the peer_connection
|
||||||
@@ -266,18 +269,14 @@ namespace libtorrent
|
|||||||
|
|
||||||
boost::filesystem::path save_path() const
|
boost::filesystem::path save_path() const
|
||||||
{ return m_storage.save_path(); }
|
{ return m_storage.save_path(); }
|
||||||
|
|
||||||
alert_manager& alerts() const;
|
alert_manager& alerts() const;
|
||||||
|
piece_picker& picker() { return m_picker; }
|
||||||
|
policy& get_policy() { return *m_policy; }
|
||||||
|
piece_manager& filesystem() { return m_storage; }
|
||||||
|
torrent_info const& torrent_file() const { return m_torrent_file; }
|
||||||
|
|
||||||
torrent_handle get_handle() const;
|
torrent_handle get_handle() const;
|
||||||
|
|
||||||
void set_tracker_login(std::string const& name, std::string const& pw)
|
|
||||||
{
|
|
||||||
m_username = name;
|
|
||||||
m_password = pw;
|
|
||||||
}
|
|
||||||
|
|
||||||
const address& current_tracker() const;
|
|
||||||
|
|
||||||
// DEBUG
|
// DEBUG
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
logger* spawn_logger(const char* title);
|
logger* spawn_logger(const char* title);
|
||||||
@@ -286,18 +285,20 @@ namespace libtorrent
|
|||||||
void check_invariant();
|
void check_invariant();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// --------------------------------------------
|
||||||
|
// RESOURCE MANAGEMENT
|
||||||
|
|
||||||
// this will distribute the given upload/download
|
// this will distribute the given upload/download
|
||||||
// quotas among the peers
|
// quotas and number of connections, among the peers
|
||||||
void distribute_resources();
|
void distribute_resources();
|
||||||
|
|
||||||
resource_request m_upload_bandwidth_quota;
|
resource_request m_ul_bandwidth_quota;
|
||||||
|
resource_request m_dl_bandwidth_quota;
|
||||||
|
resource_request m_unchoked_quota;
|
||||||
|
resource_request m_connections_quota;
|
||||||
|
|
||||||
void set_upload_limit(int limit)
|
void set_upload_limit(int limit);
|
||||||
{
|
void set_download_limit(int limit);
|
||||||
assert(limit >= -1);
|
|
||||||
if (limit == -1) limit = std::numeric_limits<int>::max();
|
|
||||||
m_upload_bandwidth_limit = limit;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@@ -391,8 +392,51 @@ namespace libtorrent
|
|||||||
// the max number of bytes this torrent
|
// the max number of bytes this torrent
|
||||||
// can upload per second
|
// can upload per second
|
||||||
int m_upload_bandwidth_limit;
|
int m_upload_bandwidth_limit;
|
||||||
|
int m_download_bandwidth_limit;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline boost::posix_time::ptime torrent::next_announce() const
|
||||||
|
{ return m_next_request; }
|
||||||
|
|
||||||
|
// returns true if it is time for this torrent to make another
|
||||||
|
// tracker request
|
||||||
|
inline bool torrent::should_request() const
|
||||||
|
{
|
||||||
|
namespace time = boost::posix_time;
|
||||||
|
return !m_paused &&
|
||||||
|
m_next_request < time::second_clock::local_time();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void torrent::force_tracker_request()
|
||||||
|
{
|
||||||
|
namespace time = boost::posix_time;
|
||||||
|
m_next_request = time::second_clock::local_time();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void torrent::set_tracker_login(
|
||||||
|
std::string const& name
|
||||||
|
, std::string const& pw)
|
||||||
|
{
|
||||||
|
m_username = name;
|
||||||
|
m_password = pw;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void torrent::set_upload_limit(int limit)
|
||||||
|
{
|
||||||
|
assert(limit >= -1);
|
||||||
|
if (limit == -1) limit = std::numeric_limits<int>::max();
|
||||||
|
if (limit < num_peers() * 10) limit = num_peers() * 10;
|
||||||
|
m_upload_bandwidth_limit = limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void torrent::set_download_limit(int limit)
|
||||||
|
{
|
||||||
|
assert(limit >= -1);
|
||||||
|
if (limit == -1) limit = std::numeric_limits<int>::max();
|
||||||
|
if (limit < num_peers() * 10) limit = num_peers() * 10;
|
||||||
|
m_download_bandwidth_limit = limit;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // TORRENT_TORRENT_HPP_INCLUDED
|
#endif // TORRENT_TORRENT_HPP_INCLUDED
|
||||||
|
@@ -380,14 +380,6 @@ namespace libtorrent
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#ifndef NDEBUG
|
|
||||||
if (requester())
|
|
||||||
{
|
|
||||||
requester()->debug_log(
|
|
||||||
std::string("m_content_length = ")
|
|
||||||
+ boost::lexical_cast<std::string>(m_content_length));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else if (line.substr(0, 18) == "Content-Encoding: ")
|
else if (line.substr(0, 18) == "Content-Encoding: ")
|
||||||
{
|
{
|
||||||
|
@@ -92,7 +92,8 @@ namespace libtorrent
|
|||||||
, m_attached_to_torrent(true)
|
, m_attached_to_torrent(true)
|
||||||
, m_ses(ses)
|
, m_ses(ses)
|
||||||
, m_active(true)
|
, m_active(true)
|
||||||
, m_added_to_selector(false)
|
, m_writability_monitored(false)
|
||||||
|
, m_readability_monitored(true)
|
||||||
, m_peer_interested(false)
|
, m_peer_interested(false)
|
||||||
, m_peer_choked(true)
|
, m_peer_choked(true)
|
||||||
, m_interesting(false)
|
, m_interesting(false)
|
||||||
@@ -110,8 +111,11 @@ namespace libtorrent
|
|||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
m_upload_bandwidth_quota.min = 10;
|
m_ul_bandwidth_quota.min = 10;
|
||||||
m_upload_bandwidth_quota.max = 10;
|
m_ul_bandwidth_quota.max = 10;
|
||||||
|
m_dl_bandwidth_quota.min = 10;
|
||||||
|
m_dl_bandwidth_quota.max = std::numeric_limits<int>::max();
|
||||||
|
m_dl_bandwidth_quota.given = 400;
|
||||||
|
|
||||||
assert(!m_socket->is_blocking());
|
assert(!m_socket->is_blocking());
|
||||||
assert(m_torrent != 0);
|
assert(m_torrent != 0);
|
||||||
@@ -156,7 +160,8 @@ namespace libtorrent
|
|||||||
, m_attached_to_torrent(0)
|
, m_attached_to_torrent(0)
|
||||||
, m_ses(ses)
|
, m_ses(ses)
|
||||||
, m_active(false)
|
, m_active(false)
|
||||||
, m_added_to_selector(false)
|
, m_writability_monitored(false)
|
||||||
|
, m_readability_monitored(true)
|
||||||
, m_peer_id()
|
, m_peer_id()
|
||||||
, m_peer_interested(false)
|
, m_peer_interested(false)
|
||||||
, m_peer_choked(true)
|
, m_peer_choked(true)
|
||||||
@@ -172,7 +177,6 @@ namespace libtorrent
|
|||||||
, m_disconnecting(false)
|
, m_disconnecting(false)
|
||||||
, m_became_uninterested(boost::posix_time::second_clock::local_time())
|
, m_became_uninterested(boost::posix_time::second_clock::local_time())
|
||||||
, m_became_uninteresting(boost::posix_time::second_clock::local_time())
|
, m_became_uninteresting(boost::posix_time::second_clock::local_time())
|
||||||
// , m_upload_bandwidth_quota_used(0)
|
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
@@ -180,9 +184,13 @@ namespace libtorrent
|
|||||||
// that are part of a torrent. Since this is an incoming
|
// that are part of a torrent. Since this is an incoming
|
||||||
// connection, we have to give it some initial bandwidth
|
// connection, we have to give it some initial bandwidth
|
||||||
// to send the handshake
|
// to send the handshake
|
||||||
m_upload_bandwidth_quota.min = 10;
|
m_ul_bandwidth_quota.min = 10;
|
||||||
m_upload_bandwidth_quota.max = 400;
|
m_ul_bandwidth_quota.max = 400;
|
||||||
m_upload_bandwidth_quota.given = 400;
|
m_ul_bandwidth_quota.given = 400;
|
||||||
|
|
||||||
|
m_dl_bandwidth_quota.min = 10;
|
||||||
|
m_dl_bandwidth_quota.max = std::numeric_limits<int>::max();
|
||||||
|
m_dl_bandwidth_quota.given = 400;
|
||||||
|
|
||||||
assert(!m_socket->is_blocking());
|
assert(!m_socket->is_blocking());
|
||||||
|
|
||||||
@@ -280,22 +288,19 @@ namespace libtorrent
|
|||||||
m_free_upload += free_upload;
|
m_free_upload += free_upload;
|
||||||
}
|
}
|
||||||
|
|
||||||
int peer_connection::send_quota_left() const
|
|
||||||
{
|
|
||||||
return m_upload_bandwidth_quota.given - m_upload_bandwidth_quota.used;
|
|
||||||
}
|
|
||||||
|
|
||||||
void peer_connection::reset_upload_quota()
|
void peer_connection::reset_upload_quota()
|
||||||
{
|
{
|
||||||
m_upload_bandwidth_quota.used = 0;
|
m_ul_bandwidth_quota.used = 0;
|
||||||
|
m_dl_bandwidth_quota.used = 0;
|
||||||
|
if (!m_readability_monitored)
|
||||||
|
{
|
||||||
|
assert(!m_selector.is_readability_monitored(m_socket));
|
||||||
|
m_selector.monitor_readability(m_socket);
|
||||||
|
m_readability_monitored = true;
|
||||||
|
}
|
||||||
send_buffer_updated();
|
send_buffer_updated();
|
||||||
}
|
}
|
||||||
|
|
||||||
resource_request* peer_connection::upload_bandwidth_quota()
|
|
||||||
{
|
|
||||||
return &m_upload_bandwidth_quota;
|
|
||||||
}
|
|
||||||
|
|
||||||
void peer_connection::send_handshake()
|
void peer_connection::send_handshake()
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
@@ -687,6 +692,7 @@ namespace libtorrent
|
|||||||
r
|
r
|
||||||
, m_torrent->get_handle()
|
, m_torrent->get_handle()
|
||||||
, m_socket->sender()
|
, m_socket->sender()
|
||||||
|
, m_peer_id
|
||||||
, "peer sent an illegal request, ignoring"));
|
, "peer sent an illegal request, ignoring"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -797,8 +803,9 @@ namespace libtorrent
|
|||||||
{
|
{
|
||||||
m_torrent->alerts().post_alert(
|
m_torrent->alerts().post_alert(
|
||||||
peer_error_alert(
|
peer_error_alert(
|
||||||
m_socket->sender()
|
m_socket->sender()
|
||||||
, "got a block that was not requested"));
|
, m_peer_id
|
||||||
|
, "got a block that was not requested"));
|
||||||
}
|
}
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
(*m_logger) << " *** The block we just got was not requested ***\n";
|
(*m_logger) << " *** The block we just got was not requested ***\n";
|
||||||
@@ -864,9 +871,9 @@ namespace libtorrent
|
|||||||
m_requests.erase(i);
|
m_requests.erase(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!has_data() && m_added_to_selector)
|
if (!can_write() && m_writability_monitored)
|
||||||
{
|
{
|
||||||
m_added_to_selector = false;
|
m_writability_monitored = false;
|
||||||
m_selector.remove_writable(m_socket);
|
m_selector.remove_writable(m_socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1312,7 +1319,9 @@ namespace libtorrent
|
|||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
m_statistics.second_tick();
|
m_statistics.second_tick();
|
||||||
m_upload_bandwidth_quota.used = (int)ceil(statistics().upload_rate());
|
m_ul_bandwidth_quota.used = std::min(
|
||||||
|
(int)ceil(statistics().upload_rate())
|
||||||
|
, m_ul_bandwidth_quota.given);
|
||||||
|
|
||||||
send_buffer_updated();
|
send_buffer_updated();
|
||||||
|
|
||||||
@@ -1329,9 +1338,9 @@ namespace libtorrent
|
|||||||
// than we have uploaded OR if we are a seed
|
// than we have uploaded OR if we are a seed
|
||||||
// have an unlimited upload rate
|
// have an unlimited upload rate
|
||||||
if(!m_send_buffer.empty() || (!m_requests.empty() && !is_choked()))
|
if(!m_send_buffer.empty() || (!m_requests.empty() && !is_choked()))
|
||||||
m_upload_bandwidth_quota.max = std::numeric_limits<int>::max();
|
m_ul_bandwidth_quota.max = std::numeric_limits<int>::max();
|
||||||
else
|
else
|
||||||
m_upload_bandwidth_quota.max = m_upload_bandwidth_quota.min;
|
m_ul_bandwidth_quota.max = m_ul_bandwidth_quota.min;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1355,8 +1364,8 @@ namespace libtorrent
|
|||||||
upload_speed_limit = std::min(upload_speed_limit,
|
upload_speed_limit = std::min(upload_speed_limit,
|
||||||
(double)std::numeric_limits<int>::max());
|
(double)std::numeric_limits<int>::max());
|
||||||
|
|
||||||
m_upload_bandwidth_quota.max
|
m_ul_bandwidth_quota.max
|
||||||
= std::max((int)upload_speed_limit, m_upload_bandwidth_quota.min);
|
= std::max((int)upload_speed_limit, m_ul_bandwidth_quota.min);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1371,7 +1380,7 @@ namespace libtorrent
|
|||||||
// if we have downloaded more than one piece more
|
// if we have downloaded more than one piece more
|
||||||
// than we have uploaded OR if we are a seed
|
// than we have uploaded OR if we are a seed
|
||||||
// have an unlimited upload rate
|
// have an unlimited upload rate
|
||||||
m_upload_bandwidth_quota.wanted = std::numeric_limits<int>::max();
|
m_ul_bandwidth_quota.wanted = std::numeric_limits<int>::max();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1390,10 +1399,10 @@ namespace libtorrent
|
|||||||
{
|
{
|
||||||
bias = -static_cast<int>(m_statistics.download_rate() * ratio) / 2;
|
bias = -static_cast<int>(m_statistics.download_rate() * ratio) / 2;
|
||||||
}
|
}
|
||||||
m_upload_bandwidth_quota.wanted = static_cast<int>(m_statistics.download_rate()) + bias;
|
m_ul_bandwidth_quota.wanted = static_cast<int>(m_statistics.download_rate()) + bias;
|
||||||
|
|
||||||
// the maximum send_quota given our download rate from this peer
|
// the maximum send_quota given our download rate from this peer
|
||||||
if (m_upload_bandwidth_quota.wanted < 256) m_upload_bandwidth_quota.wanted = 256;
|
if (m_ul_bandwidth_quota.wanted < 256) m_ul_bandwidth_quota.wanted = 256;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
@@ -1410,10 +1419,16 @@ namespace libtorrent
|
|||||||
assert(!m_socket->is_blocking());
|
assert(!m_socket->is_blocking());
|
||||||
assert(m_packet_size > 0);
|
assert(m_packet_size > 0);
|
||||||
assert(m_socket->is_readable());
|
assert(m_socket->is_readable());
|
||||||
|
assert(can_read());
|
||||||
|
assert(m_selector.is_readability_monitored(m_socket));
|
||||||
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
assert(m_packet_size > 0);
|
assert(m_packet_size > 0);
|
||||||
int received = m_socket->receive(&m_recv_buffer[m_recv_pos], m_packet_size - m_recv_pos);
|
int max_receive = std::min(
|
||||||
|
m_dl_bandwidth_quota.left()
|
||||||
|
, m_packet_size - m_recv_pos);
|
||||||
|
int received = m_socket->receive(&m_recv_buffer[m_recv_pos], max_receive);
|
||||||
|
|
||||||
// connection closed
|
// connection closed
|
||||||
if (received == 0)
|
if (received == 0)
|
||||||
@@ -1438,6 +1453,14 @@ namespace libtorrent
|
|||||||
m_last_receive = boost::posix_time::second_clock::local_time();
|
m_last_receive = boost::posix_time::second_clock::local_time();
|
||||||
|
|
||||||
m_recv_pos += received;
|
m_recv_pos += received;
|
||||||
|
m_dl_bandwidth_quota.used += received;
|
||||||
|
if (!can_read())
|
||||||
|
{
|
||||||
|
assert(m_readability_monitored);
|
||||||
|
assert(m_selector.is_readability_monitored(m_socket));
|
||||||
|
m_selector.remove_readable(m_socket);
|
||||||
|
m_readability_monitored = false;
|
||||||
|
}
|
||||||
|
|
||||||
switch(m_state)
|
switch(m_state)
|
||||||
{
|
{
|
||||||
@@ -1675,19 +1698,28 @@ namespace libtorrent
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if we have used all our download quota,
|
||||||
|
// break the receive loop
|
||||||
|
if (!can_read()) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(m_packet_size > 0);
|
assert(m_packet_size > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool peer_connection::has_data() const
|
bool peer_connection::can_write() const
|
||||||
{
|
{
|
||||||
// if we have requests or pending data to be sent or announcements to be made
|
// if we have requests or pending data to be sent or announcements to be made
|
||||||
// we want to send data
|
// we want to send data
|
||||||
return ((!m_requests.empty() && !m_choked)
|
return ((!m_requests.empty() && !m_choked)
|
||||||
|| !m_send_buffer.empty())
|
|| !m_send_buffer.empty())
|
||||||
&& send_quota_left() > 0;
|
&& m_ul_bandwidth_quota.left() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool peer_connection::can_read() const
|
||||||
|
{
|
||||||
|
return m_dl_bandwidth_quota.left() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------
|
// --------------------------
|
||||||
@@ -1700,7 +1732,7 @@ namespace libtorrent
|
|||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
assert(m_socket->is_writable());
|
assert(m_socket->is_writable());
|
||||||
assert(has_data());
|
assert(can_write());
|
||||||
|
|
||||||
// only add new piece-chunks if the send buffer is small enough
|
// only add new piece-chunks if the send buffer is small enough
|
||||||
// otherwise there will be no end to how large it will be!
|
// otherwise there will be no end to how large it will be!
|
||||||
@@ -1766,15 +1798,15 @@ namespace libtorrent
|
|||||||
m_announce_queue.clear();
|
m_announce_queue.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(m_upload_bandwidth_quota.used <= m_upload_bandwidth_quota.given);
|
assert(m_ul_bandwidth_quota.used <= m_ul_bandwidth_quota.given);
|
||||||
|
|
||||||
// send the actual buffer
|
// send the actual buffer
|
||||||
if (!m_send_buffer.empty())
|
if (!m_send_buffer.empty())
|
||||||
{
|
{
|
||||||
|
int amount_to_send
|
||||||
|
= std::min(m_ul_bandwidth_quota.left(), (int)m_send_buffer.size());
|
||||||
|
|
||||||
int amount_to_send = (int)m_send_buffer.size();
|
assert(amount_to_send > 0);
|
||||||
amount_to_send = std::min(send_quota_left(), amount_to_send);
|
|
||||||
assert(amount_to_send>0);
|
|
||||||
|
|
||||||
// we have data that's scheduled for sending
|
// we have data that's scheduled for sending
|
||||||
int sent = m_socket->send(
|
int sent = m_socket->send(
|
||||||
@@ -1783,7 +1815,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
if (sent > 0)
|
if (sent > 0)
|
||||||
{
|
{
|
||||||
m_upload_bandwidth_quota.used += sent;
|
m_ul_bandwidth_quota.used += sent;
|
||||||
|
|
||||||
// manage the payload markers
|
// manage the payload markers
|
||||||
int amount_payload = 0;
|
int amount_payload = 0;
|
||||||
@@ -1840,14 +1872,14 @@ namespace libtorrent
|
|||||||
m_last_sent = boost::posix_time::second_clock::local_time();
|
m_last_sent = boost::posix_time::second_clock::local_time();
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(m_added_to_selector);
|
assert(m_writability_monitored);
|
||||||
send_buffer_updated();
|
send_buffer_updated();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
void peer_connection::check_invariant() const
|
void peer_connection::check_invariant() const
|
||||||
{
|
{
|
||||||
assert(has_data() == m_selector.is_writability_monitored(m_socket));
|
assert(can_write() == m_selector.is_writability_monitored(m_socket));
|
||||||
/*
|
/*
|
||||||
assert(m_num_pieces == std::count(
|
assert(m_num_pieces == std::count(
|
||||||
m_have_piece.begin()
|
m_have_piece.begin()
|
||||||
@@ -1923,25 +1955,25 @@ namespace libtorrent
|
|||||||
|
|
||||||
void peer_connection::send_buffer_updated()
|
void peer_connection::send_buffer_updated()
|
||||||
{
|
{
|
||||||
if (!has_data())
|
if (!can_write())
|
||||||
{
|
{
|
||||||
if (m_added_to_selector)
|
if (m_writability_monitored)
|
||||||
{
|
{
|
||||||
m_selector.remove_writable(m_socket);
|
m_selector.remove_writable(m_socket);
|
||||||
m_added_to_selector = false;
|
m_writability_monitored = false;
|
||||||
}
|
}
|
||||||
assert(!m_selector.is_writability_monitored(m_socket));
|
assert(!m_selector.is_writability_monitored(m_socket));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(send_quota_left() > 0);
|
assert(m_ul_bandwidth_quota.left() > 0);
|
||||||
assert(has_data());
|
assert(can_write());
|
||||||
if (!m_added_to_selector)
|
if (!m_writability_monitored)
|
||||||
{
|
{
|
||||||
m_selector.monitor_writability(m_socket);
|
m_selector.monitor_writability(m_socket);
|
||||||
m_added_to_selector = true;
|
m_writability_monitored = true;
|
||||||
}
|
}
|
||||||
assert(m_added_to_selector);
|
assert(m_writability_monitored);
|
||||||
assert(m_selector.is_writability_monitored(m_socket));
|
assert(m_selector.is_writability_monitored(m_socket));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -748,6 +748,8 @@ namespace libtorrent
|
|||||||
// it's probably just a NAT-check. Ignore the
|
// it's probably just a NAT-check. Ignore the
|
||||||
// num connections constraint then.
|
// num connections constraint then.
|
||||||
// TODO: mske sure this works
|
// TODO: mske sure this works
|
||||||
|
// TODO: only allow _one_ connection to use this
|
||||||
|
// override at a time
|
||||||
if (m_torrent->num_peers() >= m_max_connections
|
if (m_torrent->num_peers() >= m_max_connections
|
||||||
&& c.get_socket()->sender().ip() != m_torrent->current_tracker().ip())
|
&& c.get_socket()->sender().ip() != m_torrent->current_tracker().ip())
|
||||||
{
|
{
|
||||||
@@ -853,7 +855,7 @@ namespace libtorrent
|
|||||||
if (m_torrent->alerts().should_post(alert::debug))
|
if (m_torrent->alerts().should_post(alert::debug))
|
||||||
{
|
{
|
||||||
m_torrent->alerts().post_alert(
|
m_torrent->alerts().post_alert(
|
||||||
peer_error_alert(remote, e.what()));
|
peer_error_alert(remote, id, e.what()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(protocol_error& e)
|
catch(protocol_error& e)
|
||||||
@@ -861,7 +863,7 @@ namespace libtorrent
|
|||||||
if (m_torrent->alerts().should_post(alert::debug))
|
if (m_torrent->alerts().should_post(alert::debug))
|
||||||
{
|
{
|
||||||
m_torrent->alerts().post_alert(
|
m_torrent->alerts().post_alert(
|
||||||
peer_error_alert(remote, e.what()));
|
peer_error_alert(remote, id, e.what()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -271,6 +271,7 @@ namespace libtorrent { namespace detail
|
|||||||
, m_listen_interface(listen_interface, listen_port_range.first)
|
, m_listen_interface(listen_interface, listen_port_range.first)
|
||||||
, m_abort(false)
|
, m_abort(false)
|
||||||
, m_upload_rate(-1)
|
, m_upload_rate(-1)
|
||||||
|
, m_download_rate(-1)
|
||||||
, m_incoming_connection(false)
|
, m_incoming_connection(false)
|
||||||
{
|
{
|
||||||
assert(listen_port_range.first > 0);
|
assert(listen_port_range.first > 0);
|
||||||
@@ -309,7 +310,6 @@ namespace libtorrent { namespace detail
|
|||||||
{
|
{
|
||||||
m_connections.erase(m_disconnect_peer.back());
|
m_connections.erase(m_disconnect_peer.back());
|
||||||
m_disconnect_peer.pop_back();
|
m_disconnect_peer.pop_back();
|
||||||
assert(m_selector.count_read_monitors() == (int)m_connections.size() + (bool)m_listen_socket);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -420,8 +420,6 @@ namespace libtorrent { namespace detail
|
|||||||
#endif
|
#endif
|
||||||
boost::mutex::scoped_lock l(m_mutex);
|
boost::mutex::scoped_lock l(m_mutex);
|
||||||
|
|
||||||
assert(m_selector.count_read_monitors() == (int)m_connections.size() + (bool)m_listen_socket);
|
|
||||||
|
|
||||||
if (m_abort)
|
if (m_abort)
|
||||||
{
|
{
|
||||||
m_tracker_manager.abort_all_requests();
|
m_tracker_manager.abort_all_requests();
|
||||||
@@ -467,7 +465,7 @@ namespace libtorrent { namespace detail
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
assert(m_selector.is_writability_monitored(p->first));
|
assert(m_selector.is_writability_monitored(p->first));
|
||||||
assert(p->second->has_data());
|
assert(p->second->can_write());
|
||||||
assert(p->second->get_socket()->is_writable());
|
assert(p->second->get_socket()->is_writable());
|
||||||
p->second->send_data();
|
p->second->send_data();
|
||||||
}
|
}
|
||||||
@@ -486,7 +484,6 @@ namespace libtorrent { namespace detail
|
|||||||
|
|
||||||
// pause the torrent
|
// pause the torrent
|
||||||
t->pause();
|
t->pause();
|
||||||
assert(m_selector.count_read_monitors() == (int)m_connections.size() + (bool)m_listen_socket);
|
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
@@ -495,13 +492,15 @@ namespace libtorrent { namespace detail
|
|||||||
if (m_alerts.should_post(alert::debug))
|
if (m_alerts.should_post(alert::debug))
|
||||||
{
|
{
|
||||||
m_alerts.post_alert(
|
m_alerts.post_alert(
|
||||||
peer_error_alert(p->first->sender(), e.what()));
|
peer_error_alert(
|
||||||
|
p->first->sender()
|
||||||
|
, p->second->id()
|
||||||
|
, e.what()));
|
||||||
}
|
}
|
||||||
|
|
||||||
p->second->set_failed();
|
p->second->set_failed();
|
||||||
m_selector.remove(*i);
|
m_selector.remove(*i);
|
||||||
m_connections.erase(p);
|
m_connections.erase(p);
|
||||||
assert(m_selector.count_read_monitors() == (int)m_connections.size() + (bool)m_listen_socket);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -573,7 +572,6 @@ namespace libtorrent { namespace detail
|
|||||||
, e.what()));
|
, e.what()));
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(m_selector.count_read_monitors() == (int)m_connections.size() + (bool)m_listen_socket);
|
|
||||||
t->pause();
|
t->pause();
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
@@ -581,14 +579,16 @@ namespace libtorrent { namespace detail
|
|||||||
if (m_alerts.should_post(alert::debug))
|
if (m_alerts.should_post(alert::debug))
|
||||||
{
|
{
|
||||||
m_alerts.post_alert(
|
m_alerts.post_alert(
|
||||||
peer_error_alert(p->first->sender(), e.what()));
|
peer_error_alert(
|
||||||
|
p->first->sender()
|
||||||
|
, p->second->id()
|
||||||
|
, e.what()));
|
||||||
}
|
}
|
||||||
// the connection wants to disconnect for some reason, remove it
|
// the connection wants to disconnect for some reason, remove it
|
||||||
// from the connection-list
|
// from the connection-list
|
||||||
p->second->set_failed();
|
p->second->set_failed();
|
||||||
m_selector.remove(*i);
|
m_selector.remove(*i);
|
||||||
m_connections.erase(p);
|
m_connections.erase(p);
|
||||||
assert(m_selector.count_read_monitors() == (int)m_connections.size() + (bool)m_listen_socket);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -613,7 +613,8 @@ namespace libtorrent { namespace detail
|
|||||||
m_alerts.post_alert(
|
m_alerts.post_alert(
|
||||||
peer_error_alert(
|
peer_error_alert(
|
||||||
p->first->sender()
|
p->first->sender()
|
||||||
, "socket received an exception"));
|
, p->second->id()
|
||||||
|
, "connection closed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
m_selector.remove(*i);
|
m_selector.remove(*i);
|
||||||
@@ -622,7 +623,6 @@ namespace libtorrent { namespace detail
|
|||||||
{
|
{
|
||||||
p->second->set_failed();
|
p->second->set_failed();
|
||||||
m_connections.erase(p);
|
m_connections.erase(p);
|
||||||
assert(m_selector.count_read_monitors() == (int)m_connections.size() + (bool)m_listen_socket);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -659,12 +659,14 @@ namespace libtorrent { namespace detail
|
|||||||
if (m_alerts.should_post(alert::debug))
|
if (m_alerts.should_post(alert::debug))
|
||||||
{
|
{
|
||||||
m_alerts.post_alert(
|
m_alerts.post_alert(
|
||||||
peer_error_alert(j->first->sender(), "connection timed out"));
|
peer_error_alert(
|
||||||
|
j->first->sender()
|
||||||
|
, j->second->id()
|
||||||
|
, "connection timed out"));
|
||||||
}
|
}
|
||||||
j->second->set_failed();
|
j->second->set_failed();
|
||||||
m_selector.remove(j->first);
|
m_selector.remove(j->first);
|
||||||
m_connections.erase(j);
|
m_connections.erase(j);
|
||||||
assert(m_selector.count_read_monitors() == (int)m_connections.size() + (bool)m_listen_socket);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -713,7 +715,13 @@ namespace libtorrent { namespace detail
|
|||||||
? std::numeric_limits<int>::max()
|
? std::numeric_limits<int>::max()
|
||||||
: m_upload_rate
|
: m_upload_rate
|
||||||
, m_torrents
|
, m_torrents
|
||||||
, &torrent::m_upload_bandwidth_quota);
|
, &torrent::m_ul_bandwidth_quota);
|
||||||
|
|
||||||
|
allocate_resources(m_download_rate == -1
|
||||||
|
? std::numeric_limits<int>::max()
|
||||||
|
: m_download_rate
|
||||||
|
, m_torrents
|
||||||
|
, &torrent::m_dl_bandwidth_quota);
|
||||||
|
|
||||||
for (std::map<sha1_hash, boost::shared_ptr<torrent> >::iterator i
|
for (std::map<sha1_hash, boost::shared_ptr<torrent> >::iterator i
|
||||||
= m_torrents.begin(); i != m_torrents.end(); ++i)
|
= m_torrents.begin(); i != m_torrents.end(); ++i)
|
||||||
@@ -795,15 +803,18 @@ namespace libtorrent { namespace detail
|
|||||||
i != m_connections.end();
|
i != m_connections.end();
|
||||||
++i)
|
++i)
|
||||||
{
|
{
|
||||||
if (i->second->has_data() != m_selector.is_writability_monitored(i->first))
|
if (i->second->can_write() != m_selector.is_writability_monitored(i->first)
|
||||||
|
|| i->second->can_read() != m_selector.is_readability_monitored(i->first))
|
||||||
{
|
{
|
||||||
std::ofstream error_log("error.log", std::ios_base::app);
|
std::ofstream error_log("error.log", std::ios_base::app);
|
||||||
boost::shared_ptr<peer_connection> p = i->second;
|
boost::shared_ptr<peer_connection> p = i->second;
|
||||||
error_log << "session_imple::check_invariant()\n"
|
error_log << "selector::is_writability_monitored() " << m_selector.is_writability_monitored(i->first) << "\n";
|
||||||
"peer_connection::has_data() != is_writability_monitored()\n";
|
error_log << "selector::is_readability_monitored() " << m_selector.is_readability_monitored(i->first) << "\n";
|
||||||
error_log << "peer_connection::has_data() " << p->has_data() << "\n";
|
error_log << "peer_connection::can_write() " << p->can_write() << "\n";
|
||||||
error_log << "peer_connection::send_quota_left " << p->send_quota_left() << "\n";
|
error_log << "peer_connection::can_read() " << p->can_read() << "\n";
|
||||||
error_log << "peer_connection::upload_bandwidth_quota()->given " << p->upload_bandwidth_quota()->given << "\n";
|
error_log << "peer_connection::ul_quota_left " << p->m_ul_bandwidth_quota.left() << "\n";
|
||||||
|
error_log << "peer_connection::dl_quota_left " << p->m_dl_bandwidth_quota.left() << "\n";
|
||||||
|
error_log << "peer_connection::m_ul_bandwidth_quota.given " << p->m_ul_bandwidth_quota.given << "\n";
|
||||||
error_log << "peer_connection::get_peer_id " << p->get_peer_id() << "\n";
|
error_log << "peer_connection::get_peer_id " << p->get_peer_id() << "\n";
|
||||||
error_log << "place: " << place << "\n";
|
error_log << "place: " << place << "\n";
|
||||||
error_log.flush();
|
error_log.flush();
|
||||||
@@ -1007,12 +1018,26 @@ namespace libtorrent
|
|||||||
|
|
||||||
for (detail::session_impl::connection_map::iterator i
|
for (detail::session_impl::connection_map::iterator i
|
||||||
= m_impl.m_connections.begin();
|
= m_impl.m_connections.begin();
|
||||||
i != m_impl.m_connections.end();)
|
i != m_impl.m_connections.end(); ++i)
|
||||||
{
|
{
|
||||||
i->second->upload_bandwidth_quota()->given = std::numeric_limits<int>::max();
|
i->second->m_ul_bandwidth_quota.given = std::numeric_limits<int>::max();
|
||||||
// i->second->update_send_quota_left();
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void session::set_download_rate_limit(int bytes_per_second)
|
||||||
|
{
|
||||||
|
assert(bytes_per_second > 0 || bytes_per_second == -1);
|
||||||
|
boost::mutex::scoped_lock l(m_impl.m_mutex);
|
||||||
|
m_impl.m_download_rate = bytes_per_second;
|
||||||
|
if (m_impl.m_download_rate != -1 || !m_impl.m_connections.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (detail::session_impl::connection_map::iterator i
|
||||||
|
= m_impl.m_connections.begin();
|
||||||
|
i != m_impl.m_connections.end(); ++i)
|
||||||
|
{
|
||||||
|
i->second->m_dl_bandwidth_quota.given = std::numeric_limits<int>::max();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::auto_ptr<alert> session::pop_alert()
|
std::auto_ptr<alert> session::pop_alert()
|
||||||
|
@@ -1189,8 +1189,9 @@ namespace libtorrent
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert(file_offset > current_offset);
|
assert(file_offset > current_offset);
|
||||||
int skip_blocks = (file_offset - current_offset + m_info.piece_length() - 1)
|
int skip_blocks = static_cast<int>(
|
||||||
/ m_info.piece_length();
|
(file_offset - current_offset + m_info.piece_length() - 1)
|
||||||
|
/ m_info.piece_length());
|
||||||
|
|
||||||
for (int i = current_slot; i < current_slot + skip_blocks; ++i)
|
for (int i = current_slot; i < current_slot + skip_blocks; ++i)
|
||||||
{
|
{
|
||||||
|
@@ -166,6 +166,7 @@ namespace libtorrent
|
|||||||
, m_ratio(0.f)
|
, m_ratio(0.f)
|
||||||
, m_net_interface(net_interface.ip(), address::any_port)
|
, m_net_interface(net_interface.ip(), address::any_port)
|
||||||
, m_upload_bandwidth_limit(std::numeric_limits<int>::max())
|
, m_upload_bandwidth_limit(std::numeric_limits<int>::max())
|
||||||
|
, m_download_bandwidth_limit(std::numeric_limits<int>::max())
|
||||||
{
|
{
|
||||||
assert(torrent_file.begin_files() != torrent_file.end_files());
|
assert(torrent_file.begin_files() != torrent_file.end_files());
|
||||||
m_have_pieces.resize(torrent_file.num_pieces(), false);
|
m_have_pieces.resize(torrent_file.num_pieces(), false);
|
||||||
@@ -404,7 +405,7 @@ namespace libtorrent
|
|||||||
i->second->announce_piece(index);
|
i->second->announce_piece(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string torrent::tracker_password() const
|
std::string torrent::tracker_login() const
|
||||||
{
|
{
|
||||||
if (m_username.empty() && m_password.empty()) return "";
|
if (m_username.empty() && m_password.empty()) return "";
|
||||||
return m_username + ":" + m_password;
|
return m_username + ":" + m_password;
|
||||||
@@ -639,9 +640,13 @@ namespace libtorrent
|
|||||||
m_policy->pulse();
|
m_policy->pulse();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_upload_bandwidth_quota.used = 0;
|
m_ul_bandwidth_quota.used = 0;
|
||||||
m_upload_bandwidth_quota.max = 0;
|
m_ul_bandwidth_quota.max = 0;
|
||||||
m_upload_bandwidth_quota.min = 0;
|
m_ul_bandwidth_quota.min = 0;
|
||||||
|
|
||||||
|
m_dl_bandwidth_quota.used = 0;
|
||||||
|
m_dl_bandwidth_quota.min = 0;
|
||||||
|
m_dl_bandwidth_quota.max = 0;
|
||||||
|
|
||||||
for (peer_iterator i = m_connections.begin();
|
for (peer_iterator i = m_connections.begin();
|
||||||
i != m_connections.end();
|
i != m_connections.end();
|
||||||
@@ -649,26 +654,49 @@ namespace libtorrent
|
|||||||
{
|
{
|
||||||
peer_connection* p = i->second;
|
peer_connection* p = i->second;
|
||||||
m_stat += p->statistics();
|
m_stat += p->statistics();
|
||||||
|
|
||||||
|
// updates the peer connection's ul/dl bandwidth
|
||||||
|
// resource requests
|
||||||
p->second_tick();
|
p->second_tick();
|
||||||
m_upload_bandwidth_quota.used += p->m_upload_bandwidth_quota.used;
|
|
||||||
m_upload_bandwidth_quota.min += p->m_upload_bandwidth_quota.min;
|
m_ul_bandwidth_quota.used += p->m_ul_bandwidth_quota.used;
|
||||||
m_upload_bandwidth_quota.max = saturated_add(
|
m_ul_bandwidth_quota.min += p->m_ul_bandwidth_quota.min;
|
||||||
m_upload_bandwidth_quota.max
|
m_dl_bandwidth_quota.used += p->m_dl_bandwidth_quota.used;
|
||||||
, p->m_upload_bandwidth_quota.max);
|
m_dl_bandwidth_quota.min += p->m_dl_bandwidth_quota.min;
|
||||||
|
|
||||||
|
m_ul_bandwidth_quota.max = saturated_add(
|
||||||
|
m_ul_bandwidth_quota.max
|
||||||
|
, p->m_ul_bandwidth_quota.max);
|
||||||
|
|
||||||
|
m_dl_bandwidth_quota.max = saturated_add(
|
||||||
|
m_dl_bandwidth_quota.max
|
||||||
|
, p->m_dl_bandwidth_quota.max);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_upload_bandwidth_quota.max
|
m_ul_bandwidth_quota.max
|
||||||
= std::min(m_upload_bandwidth_quota.max, m_upload_bandwidth_limit);
|
= std::min(m_ul_bandwidth_quota.max, m_upload_bandwidth_limit);
|
||||||
|
|
||||||
|
m_dl_bandwidth_quota.max
|
||||||
|
= std::min(m_dl_bandwidth_quota.max, m_download_bandwidth_limit);
|
||||||
|
|
||||||
m_stat.second_tick();
|
m_stat.second_tick();
|
||||||
}
|
}
|
||||||
|
|
||||||
void torrent::distribute_resources()
|
void torrent::distribute_resources()
|
||||||
{
|
{
|
||||||
allocate_resources(m_upload_bandwidth_quota.given
|
// distribute allowed upload among the peers
|
||||||
|
allocate_resources(m_ul_bandwidth_quota.given
|
||||||
, m_connections
|
, m_connections
|
||||||
, &peer_connection::m_upload_bandwidth_quota);
|
, &peer_connection::m_ul_bandwidth_quota);
|
||||||
|
|
||||||
|
// distribute allowed download among the peers
|
||||||
|
allocate_resources(m_dl_bandwidth_quota.given
|
||||||
|
, m_connections
|
||||||
|
, &peer_connection::m_dl_bandwidth_quota);
|
||||||
|
|
||||||
|
// tell all peers to reset their used quota. This is
|
||||||
|
// a new second and they can again use up their quota
|
||||||
for (std::map<address, peer_connection*>::iterator i = m_connections.begin();
|
for (std::map<address, peer_connection*>::iterator i = m_connections.begin();
|
||||||
i != m_connections.end(); ++i)
|
i != m_connections.end(); ++i)
|
||||||
{
|
{
|
||||||
|
@@ -446,15 +446,15 @@ namespace libtorrent
|
|||||||
p.total_download = statistics.total_payload_download();
|
p.total_download = statistics.total_payload_download();
|
||||||
p.total_upload = statistics.total_payload_upload();
|
p.total_upload = statistics.total_payload_upload();
|
||||||
|
|
||||||
if (peer->upload_bandwidth_quota()->given == std::numeric_limits<int>::max())
|
if (peer->m_ul_bandwidth_quota.given == std::numeric_limits<int>::max())
|
||||||
p.upload_limit = -1;
|
p.upload_limit = -1;
|
||||||
else
|
else
|
||||||
p.upload_limit = peer->upload_bandwidth_quota()->given;
|
p.upload_limit = peer->m_ul_bandwidth_quota.given;
|
||||||
|
|
||||||
if (peer->upload_bandwidth_quota()->max == std::numeric_limits<int>::max())
|
if (peer->m_ul_bandwidth_quota.max == std::numeric_limits<int>::max())
|
||||||
p.upload_ceiling = -1;
|
p.upload_ceiling = -1;
|
||||||
else
|
else
|
||||||
p.upload_ceiling = peer->upload_bandwidth_quota()->max;
|
p.upload_ceiling = peer->m_ul_bandwidth_quota.given;
|
||||||
|
|
||||||
p.load_balancing = peer->total_free_upload();
|
p.load_balancing = peer->total_free_upload();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user