*** 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
: 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

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>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 &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 <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&amp; 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&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::vector&lt;entry&gt; list_type;
typedef implementation-defined integer_type;
typedef std::list&lt;entry&gt; list_type;
typedef size_type integer_type;
enum data_type
{
@ -424,7 +427,6 @@ public:
entry();
entry(data_type t);
entry(const entry&amp; e);
~entry();
void operator=(const entry&amp; e);
@ -433,7 +435,7 @@ public:
void operator=(const list_type&amp;);
void operator=(const integer_type&amp;);
integer_type&amp; integer()
integer_type&amp; integer();
const integer_type&amp; integer() const;
string_type&amp; string();
const string_type&amp; string() const;
@ -442,6 +444,15 @@ public:
dictionary_type&amp; dict();
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;
};
</pre>
@ -587,11 +598,13 @@ struct torrent_handle
void force_reannounce();
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_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&amp; pip
, torrent_handle h
, 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">
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;
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&amp; r
, const torrent_handle&amp; h
, const address&amp; send
, const std::string&amp; msg);
peer_request const&amp; r
, torrent_handle const&amp; h
, address const&amp; send
, peer_id const&amp; pid
, std::string const&amp; msg);
virtual std::auto_ptr&lt;alert&gt; 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&amp; r);
bool operator==(peer_request const&amp; 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

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.
* 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;
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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