*** empty log message ***
This commit is contained in:
parent
a9b3c6dd41
commit
fac783b4d8
27
Jamfile
27
Jamfile
|
@ -14,9 +14,8 @@ lib winsock : : <name>wsock32.lib ;
|
|||
project torrent
|
||||
: requirements
|
||||
|
||||
: usage-requirements
|
||||
|
||||
<include>./include
|
||||
<include>./zlib
|
||||
<include>$(BOOST_ROOT)
|
||||
<variant>release:<define>NDEBUG
|
||||
<define>BOOST_ALL_NO_LIB
|
||||
|
@ -38,6 +37,13 @@ project torrent
|
|||
|
||||
<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
|
||||
;
|
||||
|
||||
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
|
||||
|
||||
|
@ -81,8 +102,8 @@ SOURCES =
|
|||
|
||||
lib torrent
|
||||
:
|
||||
zlib//zlib
|
||||
src/$(SOURCES)
|
||||
zlib/$(ZLIB_SOURCES)
|
||||
$(LIBS)
|
||||
/boost/thread//boost_thread
|
||||
/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>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>
|
||||
<li>can limit the upload bandwidth usage and the maximum number of unchoked peers</li>
|
||||
<li>piece-wise file allocation</li>
|
||||
<li>can limit the upload and download bandwidth usage and the maximum number of unchoked peers</li>
|
||||
<li>piece-wise, unordered, file allocation</li>
|
||||
<li>implements fair trade. User settable trade-ratio, must at least be 1:1,
|
||||
but one can choose to trade 1 for 2 or any other ratio that isn't unfair to the other
|
||||
party.</li>
|
||||
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
|
||||
of a resumed torrent. Saves the storage state, piece_picker state as well as all local
|
||||
peers in a separate fast-resume file.</li>
|
||||
<li>supports 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 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>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>
|
||||
|
@ -178,7 +178,7 @@ not support files larger than 2 Gigabytes.</p>
|
|||
<div class="section" id="cygwin-and-msvc">
|
||||
<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
|
||||
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.
|
||||
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.
|
||||
|
@ -281,6 +281,7 @@ class session: public boost::noncopyable
|
|||
|
||||
void set_http_settings(const http_settings& settings);
|
||||
void set_upload_rate_limit(int bytes_per_second);
|
||||
void set_download_rate_limit(int bytes_per_second);
|
||||
|
||||
bool is_listening() 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.
|
||||
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
|
||||
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
|
||||
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
|
||||
|
@ -316,7 +317,9 @@ the peer-id to identify the client and the client's version. For more details se
|
|||
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
|
||||
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
|
||||
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>
|
||||
|
@ -400,10 +403,10 @@ class entry
|
|||
{
|
||||
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::vector<entry> list_type;
|
||||
typedef implementation-defined integer_type;
|
||||
typedef std::list<entry> list_type;
|
||||
typedef size_type integer_type;
|
||||
|
||||
enum data_type
|
||||
{
|
||||
|
@ -424,7 +427,6 @@ public:
|
|||
entry();
|
||||
entry(data_type t);
|
||||
entry(const entry& e);
|
||||
|
||||
~entry();
|
||||
|
||||
void operator=(const entry& e);
|
||||
|
@ -433,7 +435,7 @@ public:
|
|||
void operator=(const list_type&);
|
||||
void operator=(const integer_type&);
|
||||
|
||||
integer_type& integer()
|
||||
integer_type& integer();
|
||||
const integer_type& integer() const;
|
||||
string_type& string();
|
||||
const string_type& string() const;
|
||||
|
@ -442,6 +444,15 @@ public:
|
|||
dictionary_type& dict();
|
||||
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;
|
||||
};
|
||||
</pre>
|
||||
|
@ -587,11 +598,13 @@ struct torrent_handle
|
|||
void force_reannounce();
|
||||
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_ratio(float ratio);
|
||||
void set_max_uploads(int max_uploads);
|
||||
void set_max_connections(int max_connections);
|
||||
void set_upload_limit(int limit);
|
||||
void set_download_limit(int limit);
|
||||
void use_interface(const char* net_interface);
|
||||
|
||||
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
|
||||
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
|
||||
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.
|
||||
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
|
||||
|
@ -1235,7 +1252,7 @@ to the torrent that this peer was a member of.</p>
|
|||
<pre class="literal-block">
|
||||
struct peer_ban_alert: alert
|
||||
{
|
||||
peer_error_alert(
|
||||
peer_ban_alert(
|
||||
address const& pip
|
||||
, torrent_handle h
|
||||
, 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">
|
||||
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;
|
||||
|
||||
address ip;
|
||||
peer_id id;
|
||||
};
|
||||
</pre>
|
||||
</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
|
||||
{
|
||||
invalid_request_alert(
|
||||
const peer_request& r
|
||||
, const torrent_handle& h
|
||||
, const address& send
|
||||
, const std::string& msg);
|
||||
peer_request const& r
|
||||
, torrent_handle const& h
|
||||
, address const& send
|
||||
, peer_id const& pid
|
||||
, std::string const& msg);
|
||||
|
||||
virtual std::auto_ptr<alert> clone() const;
|
||||
|
||||
torrent_handle handle;
|
||||
address ip;
|
||||
peer_request request;
|
||||
peer_id id;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1290,7 +1314,7 @@ struct peer_request
|
|||
int piece;
|
||||
int start;
|
||||
int length;
|
||||
bool operator==(const peer_request& r);
|
||||
bool operator==(peer_request const& r) const;
|
||||
};
|
||||
</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
|
||||
|
|
|
@ -29,18 +29,18 @@ The current state includes the following features:
|
|||
* 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
|
||||
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
|
||||
* piece-wise file allocation
|
||||
* can limit the upload and download bandwidth usage and the maximum number of unchoked peers
|
||||
* piece-wise, unordered, file allocation
|
||||
* implements fair trade. User settable trade-ratio, must at least be 1:1,
|
||||
but one can choose to trade 1 for 2 or any other ratio that isn't unfair to the other
|
||||
party.
|
||||
party. (i.e. real tit for tat)
|
||||
* fast resume support, a way to get rid of the costly piece check at the start
|
||||
of a resumed torrent. Saves the storage state, piece_picker state as well as all local
|
||||
peers in a separate fast-resume file.
|
||||
* supports the extension protocol `described by Nolar`__. See extensions_.
|
||||
* supports files > 2 gigabytes (currently only on windows).
|
||||
* 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.
|
||||
* 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.
|
||||
|
@ -129,7 +129,7 @@ cygwin and msvc
|
|||
---------------
|
||||
|
||||
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.
|
||||
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.
|
||||
|
@ -225,6 +225,7 @@ The ``session`` class has the following synopsis::
|
|||
|
||||
void set_http_settings(const http_settings& settings);
|
||||
void set_upload_rate_limit(int bytes_per_second);
|
||||
void set_download_rate_limit(int bytes_per_second);
|
||||
|
||||
bool is_listening() 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.
|
||||
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
|
||||
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
|
||||
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
|
||||
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).
|
||||
``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
|
||||
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:
|
||||
|
||||
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::vector<entry> list_type;
|
||||
typedef implementation-defined integer_type;
|
||||
typedef std::list<entry> list_type;
|
||||
typedef size_type integer_type;
|
||||
|
||||
enum data_type
|
||||
{
|
||||
|
@ -398,7 +401,6 @@ or a string. This is its synopsis::
|
|||
entry();
|
||||
entry(data_type t);
|
||||
entry(const entry& e);
|
||||
|
||||
~entry();
|
||||
|
||||
void operator=(const entry& e);
|
||||
|
@ -407,7 +409,7 @@ or a string. This is its synopsis::
|
|||
void operator=(const list_type&);
|
||||
void operator=(const integer_type&);
|
||||
|
||||
integer_type& integer()
|
||||
integer_type& integer();
|
||||
const integer_type& integer() const;
|
||||
string_type& string();
|
||||
const string_type& string() const;
|
||||
|
@ -416,6 +418,15 @@ or a string. This is its synopsis::
|
|||
dictionary_type& dict();
|
||||
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;
|
||||
};
|
||||
|
||||
|
@ -586,11 +597,13 @@ Its declaration looks like this::
|
|||
void force_reannounce();
|
||||
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_ratio(float ratio);
|
||||
void set_max_uploads(int max_uploads);
|
||||
void set_max_connections(int max_connections);
|
||||
void set_upload_limit(int limit);
|
||||
void set_download_limit(int limit);
|
||||
void use_interface(const char* net_interface);
|
||||
|
||||
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
|
||||
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.
|
||||
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
|
||||
{
|
||||
peer_error_alert(
|
||||
peer_ban_alert(
|
||||
address const& pip
|
||||
, torrent_handle h
|
||||
, const std::string& msg);
|
||||
|
@ -1323,10 +1340,15 @@ is generated as severity level ``debug``.
|
|||
|
||||
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;
|
||||
|
||||
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
|
||||
{
|
||||
invalid_request_alert(
|
||||
const peer_request& r
|
||||
, const torrent_handle& h
|
||||
, const address& send
|
||||
, const std::string& msg);
|
||||
peer_request const& r
|
||||
, torrent_handle const& h
|
||||
, address const& send
|
||||
, peer_id const& pid
|
||||
, std::string const& msg);
|
||||
|
||||
virtual std::auto_ptr<alert> clone() const;
|
||||
|
||||
torrent_handle handle;
|
||||
address ip;
|
||||
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 start;
|
||||
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)
|
||||
, 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_severity_level(alert::debug);
|
||||
|
||||
|
@ -345,16 +345,29 @@ int main(int argc, char* argv[])
|
|||
a = ses.pop_alert();
|
||||
while (a.get())
|
||||
{
|
||||
torrent_finished_alert* p = dynamic_cast<torrent_finished_alert*>(a.get());
|
||||
if (p)
|
||||
if (torrent_finished_alert* p = dynamic_cast<torrent_finished_alert*>(a.get()))
|
||||
{
|
||||
// limit the bandwidth for all seeding torrents
|
||||
p->handle.set_max_connections(10);
|
||||
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();
|
||||
events.push_back(a->msg());
|
||||
a = ses.pop_alert();
|
||||
}
|
||||
|
||||
|
|
|
@ -90,15 +90,17 @@ namespace libtorrent
|
|||
|
||||
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)
|
||||
, ip(pip)
|
||||
, id(pid)
|
||||
{}
|
||||
|
||||
virtual std::auto_ptr<alert> clone() const
|
||||
{ return std::auto_ptr<alert>(new peer_error_alert(*this)); }
|
||||
|
||||
address ip;
|
||||
peer_id id;
|
||||
};
|
||||
|
||||
struct chat_message_alert: alert
|
||||
|
@ -122,14 +124,16 @@ namespace libtorrent
|
|||
struct invalid_request_alert: alert
|
||||
{
|
||||
invalid_request_alert(
|
||||
const peer_request& r
|
||||
, const torrent_handle& h
|
||||
, const address& sender
|
||||
, const std::string& msg)
|
||||
peer_request const& r
|
||||
, torrent_handle const& h
|
||||
, address const& sender
|
||||
, peer_id const& pid
|
||||
, std::string const& msg)
|
||||
: alert(alert::debug, msg)
|
||||
, handle(h)
|
||||
, ip(sender)
|
||||
, request(r)
|
||||
, id(pid)
|
||||
{}
|
||||
|
||||
virtual std::auto_ptr<alert> clone() const
|
||||
|
@ -138,6 +142,7 @@ namespace libtorrent
|
|||
torrent_handle handle;
|
||||
address ip;
|
||||
peer_request request;
|
||||
peer_id id;
|
||||
};
|
||||
|
||||
struct torrent_finished_alert: alert
|
||||
|
|
|
@ -107,10 +107,10 @@ namespace libtorrent
|
|||
{
|
||||
public:
|
||||
|
||||
// we need a vector here to maintain the order
|
||||
// of elements. Since the info-hash is reconstructed
|
||||
// from an entry, it's important that the order is
|
||||
// preserved.
|
||||
// we need a list here instead of a map, to maintain
|
||||
// the order of elements. Since the info-hash is
|
||||
// reconstructed from an entry, it's important that
|
||||
// the order is preserved.
|
||||
typedef std::list<std::pair<std::string, entry> > dictionary_type;
|
||||
typedef std::string string_type;
|
||||
typedef std::list<entry> list_type;
|
||||
|
@ -125,76 +125,32 @@ namespace libtorrent
|
|||
undefined_t
|
||||
};
|
||||
|
||||
data_type type() const { return m_type; }
|
||||
data_type type() const;
|
||||
|
||||
entry(const dictionary_type&);
|
||||
entry(const string_type&);
|
||||
entry(const list_type&);
|
||||
entry(const integer_type&);
|
||||
|
||||
entry(): m_type(undefined_t) {}
|
||||
entry(data_type t): m_type(t) { construct(t); }
|
||||
entry(const entry& e) { copy(e); }
|
||||
~entry() { destruct(); }
|
||||
|
||||
void operator=(const entry& e)
|
||||
{
|
||||
destruct();
|
||||
copy(e);
|
||||
}
|
||||
entry();
|
||||
entry(data_type t);
|
||||
entry(const entry& e);
|
||||
~entry();
|
||||
|
||||
void operator=(const entry& e);
|
||||
void operator=(const dictionary_type&);
|
||||
void operator=(const string_type&);
|
||||
void operator=(const list_type&);
|
||||
void operator=(const integer_type&);
|
||||
|
||||
integer_type& integer()
|
||||
{
|
||||
if (m_type != int_t) throw type_error("invalid type requested from entry");
|
||||
return *reinterpret_cast<integer_type*>(data);
|
||||
}
|
||||
|
||||
const integer_type& integer() 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);
|
||||
}
|
||||
integer_type& integer();
|
||||
const integer_type& integer() const;
|
||||
string_type& string();
|
||||
const string_type& string() const;
|
||||
list_type& list();
|
||||
const list_type& list() const;
|
||||
dictionary_type& dict();
|
||||
const dictionary_type& dict() const;
|
||||
|
||||
// these functions requires that the entry
|
||||
// is a dictionary, otherwise they will throw
|
||||
|
@ -246,6 +202,67 @@ namespace libtorrent
|
|||
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
|
||||
|
|
|
@ -117,7 +117,9 @@ namespace libtorrent
|
|||
void receive_data();
|
||||
|
||||
// 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;
|
||||
|
||||
|
@ -171,13 +173,6 @@ namespace libtorrent
|
|||
void disconnect();
|
||||
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
|
||||
// bandwidth has been distributed among them
|
||||
// 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,
|
||||
// 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:
|
||||
|
||||
|
@ -340,8 +337,8 @@ namespace libtorrent
|
|||
boost::shared_ptr<libtorrent::socket> m_socket;
|
||||
|
||||
// upload bandwidth used this second.
|
||||
// Must not exceed m_upload_bandwidth_quota.given.
|
||||
// int m_upload_bandwidth_quota_used;
|
||||
// Must not exceed m_ul_bandwidth_quota.given.
|
||||
// int m_ul_bandwidth_quota_used;
|
||||
|
||||
// this is the torrent this connection is
|
||||
// associated with. If the connection is an
|
||||
|
@ -372,7 +369,8 @@ namespace libtorrent
|
|||
// sent to this peer, we check this and
|
||||
// if it's not added to the selector we
|
||||
// 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
|
||||
peer_id m_peer_id;
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace libtorrent
|
|||
int piece;
|
||||
int start;
|
||||
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; }
|
||||
};
|
||||
}
|
||||
|
|
|
@ -44,6 +44,13 @@ namespace libtorrent
|
|||
, given(0)
|
||||
{}
|
||||
|
||||
int left() const
|
||||
{
|
||||
assert(given >= used);
|
||||
return given - used;
|
||||
}
|
||||
|
||||
|
||||
// I'm right now actively using:
|
||||
int used;
|
||||
|
||||
|
|
|
@ -225,6 +225,7 @@ namespace libtorrent
|
|||
// bytes per second. -1 means
|
||||
// unlimited
|
||||
int m_upload_rate;
|
||||
int m_download_rate;
|
||||
|
||||
// handles delayed alerts
|
||||
alert_manager m_alerts;
|
||||
|
@ -292,6 +293,7 @@ namespace libtorrent
|
|||
|
||||
void set_http_settings(const http_settings& s);
|
||||
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
|
||||
// some indication of if the listen-port works
|
||||
|
|
|
@ -240,12 +240,21 @@ namespace libtorrent
|
|||
void remove_writable(boost::shared_ptr<socket> 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)
|
||||
{
|
||||
return std::find(m_writable.begin(), m_writable.end(), s)
|
||||
!= 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
|
||||
, std::vector<boost::shared_ptr<socket> >& readable
|
||||
, std::vector<boost::shared_ptr<socket> >& writable
|
||||
|
|
|
@ -92,27 +92,20 @@ namespace libtorrent
|
|||
|
||||
~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; }
|
||||
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();
|
||||
|
||||
// returns true if it time for this torrent to make another
|
||||
// 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();
|
||||
}
|
||||
|
||||
// debug purpose only
|
||||
void print(std::ostream& os) const;
|
||||
|
||||
void check_files(
|
||||
|
@ -132,13 +125,6 @@ namespace libtorrent
|
|||
void use_interface(const char* net_interface);
|
||||
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)
|
||||
{ assert(ratio >= 0.0f); m_ratio = ratio; }
|
||||
|
||||
|
@ -169,10 +155,6 @@ namespace libtorrent
|
|||
// the number of peers that belong to this torrent
|
||||
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*>::const_iterator const_peer_iterator;
|
||||
|
||||
|
@ -186,8 +168,10 @@ namespace libtorrent
|
|||
// --------------------------------------------
|
||||
// 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
|
||||
// or when a failure occured
|
||||
virtual void tracker_response(std::vector<peer_entry>& e, int interval);
|
||||
virtual void tracker_request_timed_out();
|
||||
virtual void tracker_request_error(int response_code, const std::string& str);
|
||||
|
@ -195,10 +179,32 @@ namespace libtorrent
|
|||
// generates a request string for sending
|
||||
// to the tracker
|
||||
tracker_request generate_tracker_request();
|
||||
std::string tracker_password() const;
|
||||
|
||||
boost::posix_time::ptime next_announce() const
|
||||
{ return m_next_request; }
|
||||
// if no password and username is set
|
||||
// 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
|
||||
|
@ -242,9 +248,6 @@ namespace libtorrent
|
|||
// all seeds and let the tracker know we're finished.
|
||||
void completed();
|
||||
|
||||
piece_picker& picker() { return m_picker; }
|
||||
|
||||
|
||||
bool verify_piece(int piece_index);
|
||||
|
||||
// this is called from the peer_connection
|
||||
|
@ -266,18 +269,14 @@ namespace libtorrent
|
|||
|
||||
boost::filesystem::path save_path() const
|
||||
{ return m_storage.save_path(); }
|
||||
|
||||
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;
|
||||
|
||||
void set_tracker_login(std::string const& name, std::string const& pw)
|
||||
{
|
||||
m_username = name;
|
||||
m_password = pw;
|
||||
}
|
||||
|
||||
const address& current_tracker() const;
|
||||
|
||||
// DEBUG
|
||||
#ifndef NDEBUG
|
||||
logger* spawn_logger(const char* title);
|
||||
|
@ -286,18 +285,20 @@ namespace libtorrent
|
|||
void check_invariant();
|
||||
#endif
|
||||
|
||||
// --------------------------------------------
|
||||
// RESOURCE MANAGEMENT
|
||||
|
||||
// this will distribute the given upload/download
|
||||
// quotas among the peers
|
||||
// quotas and number of connections, among the peers
|
||||
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)
|
||||
{
|
||||
assert(limit >= -1);
|
||||
if (limit == -1) limit = std::numeric_limits<int>::max();
|
||||
m_upload_bandwidth_limit = limit;
|
||||
}
|
||||
void set_upload_limit(int limit);
|
||||
void set_download_limit(int limit);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -391,8 +392,51 @@ namespace libtorrent
|
|||
// the max number of bytes this torrent
|
||||
// can upload per second
|
||||
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
|
||||
|
|
|
@ -380,14 +380,6 @@ namespace libtorrent
|
|||
}
|
||||
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: ")
|
||||
{
|
||||
|
|
|
@ -92,7 +92,8 @@ namespace libtorrent
|
|||
, m_attached_to_torrent(true)
|
||||
, m_ses(ses)
|
||||
, m_active(true)
|
||||
, m_added_to_selector(false)
|
||||
, m_writability_monitored(false)
|
||||
, m_readability_monitored(true)
|
||||
, m_peer_interested(false)
|
||||
, m_peer_choked(true)
|
||||
, m_interesting(false)
|
||||
|
@ -110,8 +111,11 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
m_upload_bandwidth_quota.min = 10;
|
||||
m_upload_bandwidth_quota.max = 10;
|
||||
m_ul_bandwidth_quota.min = 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_torrent != 0);
|
||||
|
@ -156,7 +160,8 @@ namespace libtorrent
|
|||
, m_attached_to_torrent(0)
|
||||
, m_ses(ses)
|
||||
, m_active(false)
|
||||
, m_added_to_selector(false)
|
||||
, m_writability_monitored(false)
|
||||
, m_readability_monitored(true)
|
||||
, m_peer_id()
|
||||
, m_peer_interested(false)
|
||||
, m_peer_choked(true)
|
||||
|
@ -172,7 +177,6 @@ namespace libtorrent
|
|||
, m_disconnecting(false)
|
||||
, m_became_uninterested(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;
|
||||
|
||||
|
@ -180,9 +184,13 @@ namespace libtorrent
|
|||
// that are part of a torrent. Since this is an incoming
|
||||
// connection, we have to give it some initial bandwidth
|
||||
// to send the handshake
|
||||
m_upload_bandwidth_quota.min = 10;
|
||||
m_upload_bandwidth_quota.max = 400;
|
||||
m_upload_bandwidth_quota.given = 400;
|
||||
m_ul_bandwidth_quota.min = 10;
|
||||
m_ul_bandwidth_quota.max = 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());
|
||||
|
||||
|
@ -280,22 +288,19 @@ namespace libtorrent
|
|||
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()
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
resource_request* peer_connection::upload_bandwidth_quota()
|
||||
{
|
||||
return &m_upload_bandwidth_quota;
|
||||
}
|
||||
|
||||
void peer_connection::send_handshake()
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
@ -687,6 +692,7 @@ namespace libtorrent
|
|||
r
|
||||
, m_torrent->get_handle()
|
||||
, m_socket->sender()
|
||||
, m_peer_id
|
||||
, "peer sent an illegal request, ignoring"));
|
||||
}
|
||||
}
|
||||
|
@ -797,8 +803,9 @@ namespace libtorrent
|
|||
{
|
||||
m_torrent->alerts().post_alert(
|
||||
peer_error_alert(
|
||||
m_socket->sender()
|
||||
, "got a block that was not requested"));
|
||||
m_socket->sender()
|
||||
, m_peer_id
|
||||
, "got a block that was not requested"));
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
(*m_logger) << " *** The block we just got was not requested ***\n";
|
||||
|
@ -864,9 +871,9 @@ namespace libtorrent
|
|||
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);
|
||||
}
|
||||
|
||||
|
@ -1312,7 +1319,9 @@ namespace libtorrent
|
|||
INVARIANT_CHECK;
|
||||
|
||||
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();
|
||||
|
||||
|
@ -1329,9 +1338,9 @@ namespace libtorrent
|
|||
// than we have uploaded OR if we are a seed
|
||||
// have an unlimited upload rate
|
||||
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
|
||||
m_upload_bandwidth_quota.max = m_upload_bandwidth_quota.min;
|
||||
m_ul_bandwidth_quota.max = m_ul_bandwidth_quota.min;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1355,8 +1364,8 @@ namespace libtorrent
|
|||
upload_speed_limit = std::min(upload_speed_limit,
|
||||
(double)std::numeric_limits<int>::max());
|
||||
|
||||
m_upload_bandwidth_quota.max
|
||||
= std::max((int)upload_speed_limit, m_upload_bandwidth_quota.min);
|
||||
m_ul_bandwidth_quota.max
|
||||
= 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
|
||||
// than we have uploaded OR if we are a seed
|
||||
// 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
|
||||
{
|
||||
|
@ -1390,10 +1399,10 @@ namespace libtorrent
|
|||
{
|
||||
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
|
||||
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_packet_size > 0);
|
||||
assert(m_socket->is_readable());
|
||||
assert(can_read());
|
||||
assert(m_selector.is_readability_monitored(m_socket));
|
||||
|
||||
for(;;)
|
||||
{
|
||||
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
|
||||
if (received == 0)
|
||||
|
@ -1438,6 +1453,14 @@ namespace libtorrent
|
|||
m_last_receive = boost::posix_time::second_clock::local_time();
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -1675,19 +1698,28 @@ namespace libtorrent
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// if we have used all our download quota,
|
||||
// break the receive loop
|
||||
if (!can_read()) break;
|
||||
}
|
||||
}
|
||||
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
|
||||
// we want to send data
|
||||
return ((!m_requests.empty() && !m_choked)
|
||||
|| !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;
|
||||
|
||||
assert(m_socket->is_writable());
|
||||
assert(has_data());
|
||||
assert(can_write());
|
||||
|
||||
// only add new piece-chunks if the send buffer is small enough
|
||||
// otherwise there will be no end to how large it will be!
|
||||
|
@ -1766,15 +1798,15 @@ namespace libtorrent
|
|||
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
|
||||
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();
|
||||
amount_to_send = std::min(send_quota_left(), amount_to_send);
|
||||
assert(amount_to_send>0);
|
||||
assert(amount_to_send > 0);
|
||||
|
||||
// we have data that's scheduled for sending
|
||||
int sent = m_socket->send(
|
||||
|
@ -1783,7 +1815,7 @@ namespace libtorrent
|
|||
|
||||
if (sent > 0)
|
||||
{
|
||||
m_upload_bandwidth_quota.used += sent;
|
||||
m_ul_bandwidth_quota.used += sent;
|
||||
|
||||
// manage the payload markers
|
||||
int amount_payload = 0;
|
||||
|
@ -1840,14 +1872,14 @@ namespace libtorrent
|
|||
m_last_sent = boost::posix_time::second_clock::local_time();
|
||||
}
|
||||
|
||||
assert(m_added_to_selector);
|
||||
assert(m_writability_monitored);
|
||||
send_buffer_updated();
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
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(
|
||||
m_have_piece.begin()
|
||||
|
@ -1923,25 +1955,25 @@ namespace libtorrent
|
|||
|
||||
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_added_to_selector = false;
|
||||
m_writability_monitored = false;
|
||||
}
|
||||
assert(!m_selector.is_writability_monitored(m_socket));
|
||||
return;
|
||||
}
|
||||
|
||||
assert(send_quota_left() > 0);
|
||||
assert(has_data());
|
||||
if (!m_added_to_selector)
|
||||
assert(m_ul_bandwidth_quota.left() > 0);
|
||||
assert(can_write());
|
||||
if (!m_writability_monitored)
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
|
|
|
@ -748,6 +748,8 @@ namespace libtorrent
|
|||
// it's probably just a NAT-check. Ignore the
|
||||
// num connections constraint then.
|
||||
// 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
|
||||
&& c.get_socket()->sender().ip() != m_torrent->current_tracker().ip())
|
||||
{
|
||||
|
@ -853,7 +855,7 @@ namespace libtorrent
|
|||
if (m_torrent->alerts().should_post(alert::debug))
|
||||
{
|
||||
m_torrent->alerts().post_alert(
|
||||
peer_error_alert(remote, e.what()));
|
||||
peer_error_alert(remote, id, e.what()));
|
||||
}
|
||||
}
|
||||
catch(protocol_error& e)
|
||||
|
@ -861,7 +863,7 @@ namespace libtorrent
|
|||
if (m_torrent->alerts().should_post(alert::debug))
|
||||
{
|
||||
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_abort(false)
|
||||
, m_upload_rate(-1)
|
||||
, m_download_rate(-1)
|
||||
, m_incoming_connection(false)
|
||||
{
|
||||
assert(listen_port_range.first > 0);
|
||||
|
@ -309,7 +310,6 @@ namespace libtorrent { namespace detail
|
|||
{
|
||||
m_connections.erase(m_disconnect_peer.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
|
||||
boost::mutex::scoped_lock l(m_mutex);
|
||||
|
||||
assert(m_selector.count_read_monitors() == (int)m_connections.size() + (bool)m_listen_socket);
|
||||
|
||||
if (m_abort)
|
||||
{
|
||||
m_tracker_manager.abort_all_requests();
|
||||
|
@ -467,7 +465,7 @@ namespace libtorrent { namespace detail
|
|||
try
|
||||
{
|
||||
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());
|
||||
p->second->send_data();
|
||||
}
|
||||
|
@ -486,7 +484,6 @@ namespace libtorrent { namespace detail
|
|||
|
||||
// pause the torrent
|
||||
t->pause();
|
||||
assert(m_selector.count_read_monitors() == (int)m_connections.size() + (bool)m_listen_socket);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
|
@ -495,13 +492,15 @@ namespace libtorrent { namespace detail
|
|||
if (m_alerts.should_post(alert::debug))
|
||||
{
|
||||
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();
|
||||
m_selector.remove(*i);
|
||||
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()));
|
||||
}
|
||||
|
||||
assert(m_selector.count_read_monitors() == (int)m_connections.size() + (bool)m_listen_socket);
|
||||
t->pause();
|
||||
}
|
||||
catch (std::exception& e)
|
||||
|
@ -581,14 +579,16 @@ namespace libtorrent { namespace detail
|
|||
if (m_alerts.should_post(alert::debug))
|
||||
{
|
||||
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
|
||||
// from the connection-list
|
||||
p->second->set_failed();
|
||||
m_selector.remove(*i);
|
||||
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(
|
||||
peer_error_alert(
|
||||
p->first->sender()
|
||||
, "socket received an exception"));
|
||||
, p->second->id()
|
||||
, "connection closed"));
|
||||
}
|
||||
|
||||
m_selector.remove(*i);
|
||||
|
@ -622,7 +623,6 @@ namespace libtorrent { namespace detail
|
|||
{
|
||||
p->second->set_failed();
|
||||
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))
|
||||
{
|
||||
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();
|
||||
m_selector.remove(j->first);
|
||||
m_connections.erase(j);
|
||||
assert(m_selector.count_read_monitors() == (int)m_connections.size() + (bool)m_listen_socket);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -713,7 +715,13 @@ namespace libtorrent { namespace detail
|
|||
? std::numeric_limits<int>::max()
|
||||
: m_upload_rate
|
||||
, 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
|
||||
= m_torrents.begin(); i != m_torrents.end(); ++i)
|
||||
|
@ -795,15 +803,18 @@ namespace libtorrent { namespace detail
|
|||
i != m_connections.end();
|
||||
++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);
|
||||
boost::shared_ptr<peer_connection> p = i->second;
|
||||
error_log << "session_imple::check_invariant()\n"
|
||||
"peer_connection::has_data() != is_writability_monitored()\n";
|
||||
error_log << "peer_connection::has_data() " << p->has_data() << "\n";
|
||||
error_log << "peer_connection::send_quota_left " << p->send_quota_left() << "\n";
|
||||
error_log << "peer_connection::upload_bandwidth_quota()->given " << p->upload_bandwidth_quota()->given << "\n";
|
||||
error_log << "selector::is_writability_monitored() " << m_selector.is_writability_monitored(i->first) << "\n";
|
||||
error_log << "selector::is_readability_monitored() " << m_selector.is_readability_monitored(i->first) << "\n";
|
||||
error_log << "peer_connection::can_write() " << p->can_write() << "\n";
|
||||
error_log << "peer_connection::can_read() " << p->can_read() << "\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 << "place: " << place << "\n";
|
||||
error_log.flush();
|
||||
|
@ -1007,12 +1018,26 @@ namespace libtorrent
|
|||
|
||||
for (detail::session_impl::connection_map::iterator i
|
||||
= 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->update_send_quota_left();
|
||||
i->second->m_ul_bandwidth_quota.given = std::numeric_limits<int>::max();
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
|
|
|
@ -1189,8 +1189,9 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
assert(file_offset > current_offset);
|
||||
int skip_blocks = (file_offset - current_offset + m_info.piece_length() - 1)
|
||||
/ m_info.piece_length();
|
||||
int skip_blocks = static_cast<int>(
|
||||
(file_offset - current_offset + m_info.piece_length() - 1)
|
||||
/ m_info.piece_length());
|
||||
|
||||
for (int i = current_slot; i < current_slot + skip_blocks; ++i)
|
||||
{
|
||||
|
|
|
@ -166,6 +166,7 @@ namespace libtorrent
|
|||
, m_ratio(0.f)
|
||||
, m_net_interface(net_interface.ip(), address::any_port)
|
||||
, 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());
|
||||
m_have_pieces.resize(torrent_file.num_pieces(), false);
|
||||
|
@ -404,7 +405,7 @@ namespace libtorrent
|
|||
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 "";
|
||||
return m_username + ":" + m_password;
|
||||
|
@ -639,9 +640,13 @@ namespace libtorrent
|
|||
m_policy->pulse();
|
||||
}
|
||||
|
||||
m_upload_bandwidth_quota.used = 0;
|
||||
m_upload_bandwidth_quota.max = 0;
|
||||
m_upload_bandwidth_quota.min = 0;
|
||||
m_ul_bandwidth_quota.used = 0;
|
||||
m_ul_bandwidth_quota.max = 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();
|
||||
i != m_connections.end();
|
||||
|
@ -649,26 +654,49 @@ namespace libtorrent
|
|||
{
|
||||
peer_connection* p = i->second;
|
||||
m_stat += p->statistics();
|
||||
|
||||
// updates the peer connection's ul/dl bandwidth
|
||||
// resource requests
|
||||
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_upload_bandwidth_quota.max = saturated_add(
|
||||
m_upload_bandwidth_quota.max
|
||||
, p->m_upload_bandwidth_quota.max);
|
||||
|
||||
m_ul_bandwidth_quota.used += p->m_ul_bandwidth_quota.used;
|
||||
m_ul_bandwidth_quota.min += p->m_ul_bandwidth_quota.min;
|
||||
m_dl_bandwidth_quota.used += p->m_dl_bandwidth_quota.used;
|
||||
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
|
||||
= std::min(m_upload_bandwidth_quota.max, m_upload_bandwidth_limit);
|
||||
m_ul_bandwidth_quota.max
|
||||
= 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();
|
||||
}
|
||||
|
||||
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
|
||||
, &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();
|
||||
i != m_connections.end(); ++i)
|
||||
{
|
||||
|
|
|
@ -446,15 +446,15 @@ namespace libtorrent
|
|||
p.total_download = statistics.total_payload_download();
|
||||
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;
|
||||
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;
|
||||
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();
|
||||
|
||||
|
|
Loading…
Reference in New Issue