*** empty log message ***

This commit is contained in:
Arvid Norberg
2004-03-28 17:45:37 +00:00
parent a9b3c6dd41
commit fac783b4d8
19 changed files with 526 additions and 282 deletions

27
Jamfile
View File

@@ -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

View File

@@ -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 &gt; 2 gigabytes (currently only on windows).</li> <li>supports files &gt; 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&amp; settings); void set_http_settings(const http_settings&amp; 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&lt;std::string, entry&gt; dictionary_type; typedef std::list&lt;std::pair&lt;std::string, entry&gt; &gt; dictionary_type;
typedef std::string string_type; typedef std::string string_type;
typedef std::vector&lt;entry&gt; list_type; typedef std::list&lt;entry&gt; 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&amp; e); entry(const entry&amp; e);
~entry(); ~entry();
void operator=(const entry&amp; e); void operator=(const entry&amp; e);
@@ -433,7 +435,7 @@ public:
void operator=(const list_type&amp;); void operator=(const list_type&amp;);
void operator=(const integer_type&amp;); void operator=(const integer_type&amp;);
integer_type&amp; integer() integer_type&amp; integer();
const integer_type&amp; integer() const; const integer_type&amp; integer() const;
string_type&amp; string(); string_type&amp; string();
const string_type&amp; string() const; const string_type&amp; string() const;
@@ -442,6 +444,15 @@ public:
dictionary_type&amp; dict(); dictionary_type&amp; dict();
const dictionary_type&amp; dict() const; const dictionary_type&amp; dict() const;
// these functions requires that the entry
// is a dictionary, otherwise they will throw
entry&amp; operator[](char const* key);
entry&amp; operator[](std::string const&amp; key);
const entry&amp; operator[](char const* key) const;
const entry&amp; operator[](std::string const&amp; key) const;
entry* find_key(char const* key);
entry const* find_key(char const* key) const;
void print(std::ostream&amp; os, int indent = 0) const; void print(std::ostream&amp; 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&amp; adr) const; void connect_peer(const address&amp; adr) const;
void set_ratio(float ratio);
void set_tracker_login(std::string const&amp; username, std::string const&amp; password); void set_tracker_login(std::string const&amp; username, std::string const&amp; 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&amp; pip address const&amp; pip
, torrent_handle h , torrent_handle h
, const std::string&amp; msg); , const std::string&amp; 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&amp; pid, const std::string&amp; msg); peer_error_alert(
address const&amp; pip
, peer_id const&amp; pid
, const std::string&amp; msg);
virtual std::auto_ptr&lt;alert&gt; clone() const; virtual std::auto_ptr&lt;alert&gt; 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&amp; r peer_request const&amp; r
, const torrent_handle&amp; h , torrent_handle const&amp; h
, const address&amp; send , address const&amp; send
, const std::string&amp; msg); , peer_id const&amp; pid
, std::string const&amp; msg);
virtual std::auto_ptr&lt;alert&gt; clone() const; virtual std::auto_ptr&lt;alert&gt; 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&amp; r); bool operator==(peer_request const&amp; 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

View File

@@ -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;
}; };

View File

@@ -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();
} }

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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; }
}; };
} }

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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: ")
{ {

View File

@@ -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));
} }

View File

@@ -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()));
} }
} }
} }

View File

@@ -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()

View File

@@ -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)
{ {

View File

@@ -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)
{ {

View File

@@ -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();