*** empty log message ***

This commit is contained in:
Arvid Norberg 2003-12-22 07:14:35 +00:00
parent 5ac9f67f23
commit c432c9ad68
21 changed files with 830 additions and 333 deletions

View File

@ -1,5 +1,6 @@
SOURCES =
entry.cpp
identify_client.cpp
peer_connection.cpp
piece_picker.cpp
policy.cpp

View File

@ -44,23 +44,24 @@
<li><a class="reference" href="#big-number" id="id22" name="id22">big_number</a></li>
<li><a class="reference" href="#hasher" id="id23" name="id23">hasher</a></li>
<li><a class="reference" href="#fingerprint" id="id24" name="id24">fingerprint</a></li>
<li><a class="reference" href="#exceptions" id="id25" name="id25">exceptions</a><ul>
<li><a class="reference" href="#invalid-handle" id="id26" name="id26">invalid_handle</a></li>
<li><a class="reference" href="#duplicate-torrent" id="id27" name="id27">duplicate_torrent</a></li>
<li><a class="reference" href="#invalid-encoding" id="id28" name="id28">invalid_encoding</a></li>
<li><a class="reference" href="#type-error" id="id29" name="id29">type_error</a></li>
<li><a class="reference" href="#invalid-torrent-file" id="id30" name="id30">invalid_torrent_file</a></li>
<li><a class="reference" href="#alert" id="id25" name="id25">alert</a></li>
<li><a class="reference" href="#exceptions" id="id26" name="id26">exceptions</a><ul>
<li><a class="reference" href="#invalid-handle" id="id27" name="id27">invalid_handle</a></li>
<li><a class="reference" href="#duplicate-torrent" id="id28" name="id28">duplicate_torrent</a></li>
<li><a class="reference" href="#invalid-encoding" id="id29" name="id29">invalid_encoding</a></li>
<li><a class="reference" href="#type-error" id="id30" name="id30">type_error</a></li>
<li><a class="reference" href="#invalid-torrent-file" id="id31" name="id31">invalid_torrent_file</a></li>
</ul>
</li>
<li><a class="reference" href="#example-usage" id="id31" name="id31">example usage</a><ul>
<li><a class="reference" href="#dump-torrent" id="id32" name="id32">dump_torrent</a></li>
<li><a class="reference" href="#simple-client" id="id33" name="id33">simple client</a></li>
<li><a class="reference" href="#example-usage" id="id32" name="id32">example usage</a><ul>
<li><a class="reference" href="#dump-torrent" id="id33" name="id33">dump_torrent</a></li>
<li><a class="reference" href="#simple-client" id="id34" name="id34">simple client</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference" href="#feedback" id="id34" name="id34">Feedback</a></li>
<li><a class="reference" href="#aknowledgements" id="id35" name="id35">Aknowledgements</a></li>
<li><a class="reference" href="#feedback" id="id35" name="id35">Feedback</a></li>
<li><a class="reference" href="#aknowledgements" id="id36" name="id36">Aknowledgements</a></li>
</ul>
</div>
<div class="section" id="introduction">
@ -98,8 +99,7 @@ download to peers as free upload. To maintain a global 1:1 ratio.</li>
<p>Functions that are yet to be implemented:</p>
<blockquote>
<ul class="simple">
<li>more generous optimistic unchoke</li>
<li>better choke/unchoke algorithm</li>
<li>choke/unchoke policy for seed-mode</li>
<li>fast resume</li>
<li>number of connections limit</li>
<li>better handling of peers that send bad data</li>
@ -174,6 +174,10 @@ class session: public boost::noncopyable
void set_http_settings(const http_settings&amp; settings);
void set_upload_rate_limit(int bytes_per_second);
std::auto_ptr&lt;alert&gt; pop_alert();
void set_severity_level(alert::severity_t s);
};
</pre>
<p>Once it's created, it will spawn the main thread that will do all the work.
@ -208,6 +212,89 @@ about the torrent's progress, its peers etc. It is also used to abort a torrent.
increase the port number by one and try again. If it still fails it will continue
increasing the port number until it succeeds or has failed 9 ports. <em>This will
change in the future to give more control of the listen-port.</em></p>
<p>The <tt class="literal"><span class="pre">pop_alert()</span></tt> function is the interface for retrieving alerts, warnings and
errors from libtorrent. If there hasn't occured any errors (matching your severity
level) <tt class="literal"><span class="pre">pop_alert()</span></tt> will return a zero pointer. If there has been some error, it will
return a pointer to an alert object describing it. You can then use the query the
<a class="reference" href="#alert">alert</a> object for information about the error or message. To retrieve any alerts, you
have to select a severity level using <tt class="literal"><span class="pre">set_severity_level()</span></tt>. It defaults to
<tt class="literal"><span class="pre">alert::none</span></tt>, which means that you don't get any messages at all, ever. You have
the following levels to select among:</p>
<table border class="table">
<colgroup>
<col width="19%" />
<col width="81%" />
</colgroup>
<tbody valign="top">
<tr><td><tt class="literal"><span class="pre">none</span></tt></td>
<td>No alert will ever have this severity level, which
effectively filters all messages.</td>
</tr>
<tr><td><tt class="literal"><span class="pre">fatal</span></tt></td>
<td>Fatal errors will have this severity level. Examples can
be disk full or something else that will make it
impossible to continue normal execution.</td>
</tr>
<tr><td><tt class="literal"><span class="pre">critical</span></tt></td>
<td>Signals errors that requires user interaction.</td>
</tr>
<tr><td><tt class="literal"><span class="pre">warning</span></tt></td>
<td>Messages with the warning severity can be a tracker that
times out or responds with invalid data. It will be
retried automatically, and the possible next tracker in
a multitracker sequence will be tried. It does not
require any user interaction.</td>
</tr>
<tr><td><tt class="literal"><span class="pre">info</span></tt></td>
<td>Events that can be considered normal, but still deserves
an event. This could be a piece hash that fails.</td>
</tr>
<tr><td><tt class="literal"><span class="pre">debug</span></tt></td>
<td>This will include alot of debug events that can be used
both for debugging libtorrent but also when debugging
other clients that are connected to libtorrent. It will
report strange behaviors among the connected peers.</td>
</tr>
</tbody>
</table>
<p>When setting a severity level, you will receive messages of that severity and all
messages that are more sever. If you set <tt class="literal"><span class="pre">alert::none</span></tt> (the default) you will not recieve
any events at all.</p>
<p>When you get an alert, you can use <tt class="literal"><span class="pre">typeid()</span></tt> or <tt class="literal"><span class="pre">dynamic_cast&lt;&gt;</span></tt> to get more detailed
information on exactly which type it is. i.e. what kind of error it is. You can also use a
dispatcher mechanism that's available in libtorrent.</p>
<p>TODO: describe the type dispatching mechanism</p>
<p>The currently available alert types are:</p>
<blockquote>
<ul class="simple">
<li>tracker_alert</li>
<li>hash_failed_alert</li>
</ul>
</blockquote>
<p>You can try a <tt class="literal"><span class="pre">dynamic_cast</span></tt> to these types to get more message-pecific information. Here
are their definitions:</p>
<pre class="literal-block">
struct tracker_alert: alert
{
tracker_alert(const torrent_handle&amp; h, const std::string&amp; msg);
virtual std::auto_ptr&lt;alert&gt; clone() const;
torrent_handle handle;
};
struct hash_failed_alert: alert
{
hash_failed_alert(
const torrent_handle&amp; h
, int index
, const std::string&amp; msg);
virtual std::auto_ptr&lt;alert&gt; clone() const;
torrent_handle handle;
int piece_index;
};
</pre>
</div>
<div class="section" id="parsing-torrent-files">
<h2><a class="toc-backref" href="#id11" name="parsing-torrent-files">parsing torrent files</a></h2>
@ -451,6 +538,7 @@ struct torrent_status
invalid_handle,
queued_for_checking,
checking_files,
connecting_to_tracker,
downloading,
seeding
};
@ -458,10 +546,16 @@ struct torrent_status
state_t state;
float progress;
boost::posix_time::time_duration next_announce;
std::size_t total_download;
std::size_t total_upload;
std::size_t total_payload_download;
std::size_t total_payload_upload;
float download_rate;
float upload_rate;
std::vector&lt;bool&gt; pieces;
std::size_t total_done;
};
@ -471,8 +565,8 @@ torrent's current task. It may be checking files or downloading. The torrent's
current task is in the <tt class="literal"><span class="pre">state</span></tt> member, it will be one of the following:</p>
<table border class="table">
<colgroup>
<col width="28%" />
<col width="72%" />
<col width="31%" />
<col width="69%" />
</colgroup>
<tbody valign="top">
<tr><td><tt class="literal"><span class="pre">queued_for_checking</span></tt></td>
@ -484,6 +578,10 @@ This torrent will wait for its turn.</td>
<td>The torrent has not started its download yet, and is
currently checking existing files.</td>
</tr>
<tr><td><tt class="literal"><span class="pre">connecting_to_tracker</span></tt></td>
<td>The torrent has sent a request to the tracker and is
currently waiting for a response</td>
</tr>
<tr><td><tt class="literal"><span class="pre">downloading</span></tt></td>
<td>The torrent is being downloaded. This is the state
most torrents will be in most of the time. The progress
@ -499,6 +597,9 @@ is a pure seeder.</td>
<p><tt class="literal"><span class="pre">next_announce</span></tt> is the time until the torrent will announce itself to the tracker.</p>
<p><tt class="literal"><span class="pre">total_download</span></tt> and <tt class="literal"><span class="pre">total_upload</span></tt> is the number of bytes downloaded and
uploaded to all peers, accumulated, <em>this session</em> only.</p>
<p><tt class="literal"><span class="pre">total_payload_download</span></tt> and <tt class="literal"><span class="pre">total_payload_upload</span></tt> counts the amount of bytes
send and received this session, but only the actual oayload data (i.e the interesting
data), these counters ignore any protocol overhead.</p>
<p><tt class="literal"><span class="pre">pieces</span></tt> is the bitmask that representw which pieces we have (set to true) and
the pieces we don't have.</p>
<p><tt class="literal"><span class="pre">download_rate</span></tt> and <tt class="literal"><span class="pre">upload_rate</span></tt> are the total rates for all peers for this
@ -792,12 +893,35 @@ sure not to clash with anybody else. Here are some taken id's:</p>
version of your client. All these numbers must be within the range [0, 9].</p>
<p><tt class="literal"><span class="pre">to_string()</span></tt> will generate the actual string put in the peer-id, and return it.</p>
</div>
<div class="section" id="alert">
<h2><a class="toc-backref" href="#id25" name="alert">alert</a></h2>
<p>The <tt class="literal"><span class="pre">alert</span></tt> class is used to pass messages of events from the libtorrent code
to the user. It is a base class that specific messages are derived from. This
is its synopsis:</p>
<pre class="literal-block">
class alert
{
public:
enum severity_t { debug, info, warning, critital, fatal, none };
alert(severity_t severity, const std::string&amp; msg);
virtual ~alert() {}
const std::string&amp; msg() const;
severity_t severity() const;
virtual std::auto_ptr&lt;alert&gt; clone() const = 0;
};
</pre>
</div>
<div class="section" id="exceptions">
<h2><a class="toc-backref" href="#id25" name="exceptions">exceptions</a></h2>
<h2><a class="toc-backref" href="#id26" name="exceptions">exceptions</a></h2>
<p>There are a number of exceptions that can be thrown from different places in libtorrent,
here's a complete list with description.</p>
<div class="section" id="invalid-handle">
<h3><a class="toc-backref" href="#id26" name="invalid-handle">invalid_handle</a></h3>
<h3><a class="toc-backref" href="#id27" name="invalid-handle">invalid_handle</a></h3>
<p>This exception is thrown when querying information from a <tt class="literal"><span class="pre">torrent_handle</span></tt> that hasn't
been initialized or that has become invalid.</p>
<pre class="literal-block">
@ -808,7 +932,7 @@ struct invalid_handle: std::exception
</pre>
</div>
<div class="section" id="duplicate-torrent">
<h3><a class="toc-backref" href="#id27" name="duplicate-torrent">duplicate_torrent</a></h3>
<h3><a class="toc-backref" href="#id28" name="duplicate-torrent">duplicate_torrent</a></h3>
<p>This is thrown by <tt class="literal"><span class="pre">session::add_torrent()</span></tt> if the torrent already has been added to
the session.</p>
<pre class="literal-block">
@ -819,7 +943,7 @@ struct duplicate_torrent: std::exception
</pre>
</div>
<div class="section" id="invalid-encoding">
<h3><a class="toc-backref" href="#id28" name="invalid-encoding">invalid_encoding</a></h3>
<h3><a class="toc-backref" href="#id29" name="invalid-encoding">invalid_encoding</a></h3>
<p>This is thrown by <tt class="literal"><span class="pre">bdecode()</span></tt> if the input data is not a valid bencoding.</p>
<pre class="literal-block">
struct invalid_encoding: std::exception
@ -829,7 +953,7 @@ struct invalid_encoding: std::exception
</pre>
</div>
<div class="section" id="type-error">
<h3><a class="toc-backref" href="#id29" name="type-error">type_error</a></h3>
<h3><a class="toc-backref" href="#id30" name="type-error">type_error</a></h3>
<p>This is thrown from the accessors of <tt class="literal"><span class="pre">entry</span></tt> if the data type of the <tt class="literal"><span class="pre">entry</span></tt> doesn't
match the type you want to extract from it.</p>
<pre class="literal-block">
@ -840,7 +964,7 @@ struct type_error: std::runtime_error
</pre>
</div>
<div class="section" id="invalid-torrent-file">
<h3><a class="toc-backref" href="#id30" name="invalid-torrent-file">invalid_torrent_file</a></h3>
<h3><a class="toc-backref" href="#id31" name="invalid-torrent-file">invalid_torrent_file</a></h3>
<p>This exception is thrown from the constructor of <tt class="literal"><span class="pre">torrent_info</span></tt> if the given bencoded information
doesn't meet the requirements on what information has to be present in a torrent file.</p>
<pre class="literal-block">
@ -852,9 +976,9 @@ struct invalid_torrent_file: std::exception
</div>
</div>
<div class="section" id="example-usage">
<h2><a class="toc-backref" href="#id31" name="example-usage">example usage</a></h2>
<h2><a class="toc-backref" href="#id32" name="example-usage">example usage</a></h2>
<div class="section" id="dump-torrent">
<h3><a class="toc-backref" href="#id32" name="dump-torrent">dump_torrent</a></h3>
<h3><a class="toc-backref" href="#id33" name="dump-torrent">dump_torrent</a></h3>
<p>This is an example of a program that will take a torrent-file as a parameter and
print information about it to std out:</p>
<pre class="literal-block">
@ -918,7 +1042,7 @@ int main(int argc, char* argv[])
</pre>
</div>
<div class="section" id="simple-client">
<h3><a class="toc-backref" href="#id33" name="simple-client">simple client</a></h3>
<h3><a class="toc-backref" href="#id34" name="simple-client">simple client</a></h3>
<p>This is a simple client. It doesn't have much output to keep it simple:</p>
<pre class="literal-block">
#include &lt;iostream&gt;
@ -971,12 +1095,12 @@ int main(int argc, char* argv[])
</div>
</div>
<div class="section" id="feedback">
<h1><a class="toc-backref" href="#id34" name="feedback">Feedback</a></h1>
<h1><a class="toc-backref" href="#id35" name="feedback">Feedback</a></h1>
<p>There's a <a class="reference" href="http://lists.sourceforge.net/lists/listinfo/libtorrent-discuss">mailing list</a>.</p>
<p>You can usually find me as hydri in <tt class="literal"><span class="pre">#btports</span> <span class="pre">&#64;</span> <span class="pre">irc.freenode.net</span></tt>.</p>
</div>
<div class="section" id="aknowledgements">
<h1><a class="toc-backref" href="#id35" name="aknowledgements">Aknowledgements</a></h1>
<h1><a class="toc-backref" href="#id36" name="aknowledgements">Aknowledgements</a></h1>
<p>Written by Arvid Norberg and Daniel Wallin. Copyright (c) 2003</p>
<p>Contributions by Magnus Jonsson</p>
<p>Thanks to Reimond Retz for bugfixes, suggestions and testing</p>

View File

@ -49,8 +49,7 @@ __ http://home.elp.rr.com/tur/multitracker-spec.txt
Functions that are yet to be implemented:
* more generous optimistic unchoke
* better choke/unchoke algorithm
* choke/unchoke policy for seed-mode
* fast resume
* number of connections limit
* better handling of peers that send bad data
@ -139,6 +138,10 @@ The ``session`` class has the following synopsis::
void set_http_settings(const http_settings& settings);
void set_upload_rate_limit(int bytes_per_second);
std::auto_ptr<alert> pop_alert();
void set_severity_level(alert::severity_t s);
};
Once it's created, it will spawn the main thread that will do all the work.
@ -182,6 +185,84 @@ increase the port number by one and try again. If it still fails it will continu
increasing the port number until it succeeds or has failed 9 ports. *This will
change in the future to give more control of the listen-port.*
The ``pop_alert()`` function is the interface for retrieving alerts, warnings and
errors from libtorrent. If there hasn't occured any errors (matching your severity
level) ``pop_alert()`` will return a zero pointer. If there has been some error, it will
return a pointer to an alert object describing it. You can then use the query the
alert_ object for information about the error or message. To retrieve any alerts, you
have to select a severity level using ``set_severity_level()``. It defaults to
``alert::none``, which means that you don't get any messages at all, ever. You have
the following levels to select among:
+--------------+----------------------------------------------------------+
| ``none`` | No alert will ever have this severity level, which |
| | effectively filters all messages. |
| | |
+--------------+----------------------------------------------------------+
| ``fatal`` | Fatal errors will have this severity level. Examples can |
| | be disk full or something else that will make it |
| | impossible to continue normal execution. |
| | |
+--------------+----------------------------------------------------------+
| ``critical`` | Signals errors that requires user interaction. |
| | |
+--------------+----------------------------------------------------------+
| ``warning`` | Messages with the warning severity can be a tracker that |
| | times out or responds with invalid data. It will be |
| | retried automatically, and the possible next tracker in |
| | a multitracker sequence will be tried. It does not |
| | require any user interaction. |
| | |
+--------------+----------------------------------------------------------+
| ``info`` | Events that can be considered normal, but still deserves |
| | an event. This could be a piece hash that fails. |
| | |
+--------------+----------------------------------------------------------+
| ``debug`` | This will include alot of debug events that can be used |
| | both for debugging libtorrent but also when debugging |
| | other clients that are connected to libtorrent. It will |
| | report strange behaviors among the connected peers. |
| | |
+--------------+----------------------------------------------------------+
When setting a severity level, you will receive messages of that severity and all
messages that are more sever. If you set ``alert::none`` (the default) you will not recieve
any events at all.
When you get an alert, you can use ``typeid()`` or ``dynamic_cast<>`` to get more detailed
information on exactly which type it is. i.e. what kind of error it is. You can also use a
dispatcher mechanism that's available in libtorrent.
TODO: describe the type dispatching mechanism
The currently available alert types are:
* tracker_alert
* hash_failed_alert
You can try a ``dynamic_cast`` to these types to get more message-pecific information. Here
are their definitions::
struct tracker_alert: alert
{
tracker_alert(const torrent_handle& h, const std::string& msg);
virtual std::auto_ptr<alert> clone() const;
torrent_handle handle;
};
struct hash_failed_alert: alert
{
hash_failed_alert(
const torrent_handle& h
, int index
, const std::string& msg);
virtual std::auto_ptr<alert> clone() const;
torrent_handle handle;
int piece_index;
};
@ -471,6 +552,7 @@ It contains the following fields::
invalid_handle,
queued_for_checking,
checking_files,
connecting_to_tracker,
downloading,
seeding
};
@ -478,10 +560,16 @@ It contains the following fields::
state_t state;
float progress;
boost::posix_time::time_duration next_announce;
std::size_t total_download;
std::size_t total_upload;
std::size_t total_payload_download;
std::size_t total_payload_upload;
float download_rate;
float upload_rate;
std::vector<bool> pieces;
std::size_t total_done;
};
@ -490,28 +578,40 @@ It contains the following fields::
torrent's current task. It may be checking files or downloading. The torrent's
current task is in the ``state`` member, it will be one of the following:
+-----------------------+----------------------------------------------------------+
|``queued_for_checking``|The torrent is in the queue for being checked. But there |
| |currently is another torrent that are being checked. |
| |This torrent will wait for its turn. |
+-----------------------+----------------------------------------------------------+
|``checking_files`` |The torrent has not started its download yet, and is |
| |currently checking existing files. |
+-----------------------+----------------------------------------------------------+
|``downloading`` |The torrent is being downloaded. This is the state |
| |most torrents will be in most of the time. The progress |
| |meter will tell how much of the files that has been |
| |downloaded. |
+-----------------------+----------------------------------------------------------+
|``seeding`` |In this state the torrent has finished downloading and |
| |is a pure seeder. |
+-----------------------+----------------------------------------------------------+
+--------------------------+----------------------------------------------------------+
|``queued_for_checking`` |The torrent is in the queue for being checked. But there |
| |currently is another torrent that are being checked. |
| |This torrent will wait for its turn. |
| | |
+--------------------------+----------------------------------------------------------+
|``checking_files`` |The torrent has not started its download yet, and is |
| |currently checking existing files. |
| | |
+--------------------------+----------------------------------------------------------+
|``connecting_to_tracker`` |The torrent has sent a request to the tracker and is |
| |currently waiting for a response |
| | |
+--------------------------+----------------------------------------------------------+
|``downloading`` |The torrent is being downloaded. This is the state |
| |most torrents will be in most of the time. The progress |
| |meter will tell how much of the files that has been |
| |downloaded. |
| | |
+--------------------------+----------------------------------------------------------+
|``seeding`` |In this state the torrent has finished downloading and |
| |is a pure seeder. |
| | |
+--------------------------+----------------------------------------------------------+
``next_announce`` is the time until the torrent will announce itself to the tracker.
``total_download`` and ``total_upload`` is the number of bytes downloaded and
uploaded to all peers, accumulated, *this session* only.
``total_payload_download`` and ``total_payload_upload`` counts the amount of bytes
send and received this session, but only the actual oayload data (i.e the interesting
data), these counters ignore any protocol overhead.
``pieces`` is the bitmask that representw which pieces we have (set to true) and
the pieces we don't have.
@ -840,6 +940,32 @@ version of your client. All these numbers must be within the range [0, 9].
``to_string()`` will generate the actual string put in the peer-id, and return it.
alert
-----
The ``alert`` class is used to pass messages of events from the libtorrent code
to the user. It is a base class that specific messages are derived from. This
is its synopsis::
class alert
{
public:
enum severity_t { debug, info, warning, critital, fatal, none };
alert(severity_t severity, const std::string& msg);
virtual ~alert() {}
const std::string& msg() const;
severity_t severity() const;
virtual std::auto_ptr<alert> clone() const = 0;
};
exceptions
----------

View File

@ -42,6 +42,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/bencode.hpp"
#include "libtorrent/session.hpp"
#include "libtorrent/http_settings.hpp"
#include "libtorrent/identify_client.hpp"
#ifdef WIN32
@ -181,15 +182,18 @@ int main(int argc, char* argv[])
// settings.proxy_password = "foobar";
settings.user_agent = "example";
std::deque<std::string> events;
try
{
std::vector<torrent_handle> handles;
session s(6881);
session ses(6881);
// limit upload rate to 100 kB/s
s.set_upload_rate_limit(100 * 1024);
ses.set_upload_rate_limit(100 * 1024);
ses.set_http_settings(settings);
ses.set_severity_level(alert::info);
s.set_http_settings(settings);
for (int i = 0; i < argc-1; ++i)
{
try
@ -199,8 +203,8 @@ int main(int argc, char* argv[])
entry e = bdecode(std::istream_iterator<char>(in), std::istream_iterator<char>());
torrent_info t(e);
t.print(std::cout);
handles.push_back(s.add_torrent(t, ""));
handles.back().set_max_uploads(20);
handles.push_back(ses.add_torrent(t, ""));
handles.back().set_max_uploads(40);
}
catch (std::exception& e)
{
@ -219,6 +223,15 @@ int main(int argc, char* argv[])
if (c == 'q') break;
}
std::auto_ptr<alert> a;
a = ses.pop_alert();
while (a.get())
{
if (events.size() >= 6) events.pop_front();
events.push_front(a->msg());
a = ses.pop_alert();
}
std::stringstream out;
for (std::vector<torrent_handle>::iterator i = handles.begin();
i != handles.end();
@ -234,15 +247,17 @@ int main(int argc, char* argv[])
case torrent_status::checking_files:
out << "checking ";
break;
case torrent_status::connecting_to_tracker:
out << "connecting to tracker ";
break;
case torrent_status::downloading:
out << "dloading ";
out << "downloading ";
break;
case torrent_status::seeding:
out << "seeding ";
break;
};
// calculate download and upload speeds
i->get_peer_info(peers);
float down = s.download_rate;
float up = s.upload_rate;
@ -334,6 +349,13 @@ int main(int argc, char* argv[])
}
for (std::deque<std::string>::iterator i = events.begin();
i != events.end();
++i)
{
out << *i << "\n";
}
clear();
set_cursor(0, 0);
std::cout << out.str();

View File

@ -51,7 +51,7 @@ namespace libtorrent {
class alert
{
public:
enum severity_t { info, warning, critital, fatal };
enum severity_t { debug, info, warning, critital, fatal, none };
alert(severity_t severity, const std::string& msg)
: m_msg(msg)
@ -88,6 +88,8 @@ namespace libtorrent {
std::auto_ptr<alert> get();
void set_severity(alert::severity_t severity);
bool should_post(alert::severity_t severity) const
{ return severity >= m_severity; }
private:
std::queue<alert*> m_alerts;

View File

@ -34,6 +34,7 @@ POSSIBILITY OF SUCH DAMAGE.
#define TORRENT_FINGERPRINT_HPP_INCLUDED
#include <string>
#include <sstream>
#include "libtorrent/peer_id.hpp"

View File

@ -0,0 +1,45 @@
/*
Copyright (c) 2003, Arvid Norberg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TORRENT_IDENTIFY_CLIENT_HPP_INCLUDED
#define TORRENT_IDENTIFY_CLIENT_HPP_INCLUDED
#include "libtorrent/peer_id.hpp"
namespace libtorrent
{
std::string identify_client(const peer_id& p);
}
#endif // TORRENT_IDENTIFY_CLIENT_HPP_INCLUDED

View File

@ -241,8 +241,8 @@ namespace libtorrent
int share_diff() const
{
return m_free_upload
+ m_statistics.total_download()
- m_statistics.total_upload();
+ m_statistics.total_payload_download()
- m_statistics.total_payload_upload();
}
#ifndef NDEBUG

View File

@ -35,6 +35,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <iostream>
#include <iomanip>
#include <cassert>
namespace libtorrent
{

View File

@ -171,6 +171,12 @@ namespace libtorrent
// handles delayed alerts
alert_manager m_alerts;
// is false by default and set to true when
// the first incoming connection is established
// this is used to know if the client is behind
// NAT or not.
bool m_incoming_connection;
#ifndef NDEBUG
void assert_invariant();
boost::shared_ptr<logger> create_log(std::string name);
@ -182,8 +188,6 @@ namespace libtorrent
struct http_settings;
std::string identify_client(const peer_id& p);
class session: public boost::noncopyable, detail::eh_initializer
{
public:
@ -202,7 +206,10 @@ namespace libtorrent
void set_http_settings(const http_settings& s);
void set_upload_rate_limit(int bytes_per_second);
// TODO: add a session_status that contain
std::auto_ptr<alert> pop_alert();
void set_severity_level(alert::severity_t s);
private:

View File

@ -45,12 +45,12 @@ namespace libtorrent
public:
stat()
: m_downloaded(0)
, m_uploaded(0)
: m_downloaded_payload(0)
, m_uploaded_payload(0)
, m_downloaded_protocol(0)
, m_uploaded_protocol(0)
, m_total_download(0)
, m_total_upload(0)
, m_total_download_payload(0)
, m_total_upload_payload(0)
, m_total_download_protocol(0)
, m_total_upload_protocol(0)
, m_peak_downloaded_per_second(0)
@ -64,29 +64,29 @@ namespace libtorrent
void operator+=(const stat& s)
{
m_downloaded += s.m_downloaded;
m_total_download += s.m_downloaded;
m_downloaded_payload += s.m_downloaded_payload;
m_total_download_payload += s.m_downloaded_payload;
m_downloaded_protocol += s.m_downloaded_protocol;
m_total_download_protocol += s.m_downloaded_protocol;
m_uploaded += s.m_uploaded;
m_total_upload += s.m_uploaded;
m_uploaded_payload += s.m_uploaded_payload;
m_total_upload_payload += s.m_uploaded_payload;
m_uploaded_protocol += s.m_uploaded_protocol;
m_total_upload_protocol += s.m_uploaded_protocol;
}
void received_bytes(int bytes_payload, int bytes_protocol)
{
m_downloaded += bytes_payload;
m_total_download += bytes_payload;
m_downloaded_payload += bytes_payload;
m_total_download_payload += bytes_payload;
m_downloaded_protocol += bytes_protocol;
m_total_download_protocol += bytes_protocol;
}
void sent_bytes(int bytes_payload, int bytes_protocol)
{
m_uploaded += bytes_payload;
m_total_upload += bytes_payload;
m_uploaded_payload += bytes_payload;
m_total_upload_payload += bytes_payload;
m_uploaded_protocol += bytes_protocol;
m_total_upload_protocol += bytes_protocol;
@ -102,8 +102,11 @@ namespace libtorrent
float down_peak() const { return m_peak_downloaded_per_second; }
float up_peak() const { return m_peak_uploaded_per_second; }
unsigned int total_upload() const { return m_total_upload; }
unsigned int total_download() const { return m_total_download; }
unsigned int total_payload_upload() const { return m_total_upload_payload; }
unsigned int total_payload_download() const { return m_total_download_payload; }
unsigned int total_protocol_upload() const { return m_total_upload_protocol; }
unsigned int total_protocol_download() const { return m_total_download_protocol; }
private:
@ -116,8 +119,8 @@ namespace libtorrent
// the accumulators we are adding the downloads/upploads
// to this second. This only counts the actual payload
// and ignores the bytes sent as protocol chatter.
unsigned int m_downloaded;
unsigned int m_uploaded;
unsigned int m_downloaded_payload;
unsigned int m_uploaded_payload;
// the accumulators we are adding the downloads/upploads
// to this second. This only counts the protocol
@ -127,8 +130,8 @@ namespace libtorrent
// total download/upload counters
// only counting payload data
unsigned int m_total_download;
unsigned int m_total_upload;
unsigned int m_total_download_payload;
unsigned int m_total_upload_payload;
// total download/upload counters
// only counting protocol chatter

View File

@ -51,6 +51,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/storage.hpp"
#include "libtorrent/url_handler.hpp"
#include "libtorrent/stat.hpp"
#include "libtorrent/alert.hpp"
namespace libtorrent
{
@ -58,6 +59,38 @@ namespace libtorrent
struct logger;
#endif
struct tracker_alert: alert
{
tracker_alert(const torrent_handle& h
, const std::string& msg)
: alert(alert::warning, msg)
, handle(h)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new tracker_alert(*this)); }
torrent_handle handle;
};
struct hash_failed_alert: alert
{
hash_failed_alert(
const torrent_handle& h
, int index
, const std::string& msg)
: alert(alert::info, msg)
, handle(h)
, piece_index(index)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new hash_failed_alert(*this)); }
torrent_handle handle;
int piece_index;
};
namespace detail
{
struct session_impl;
@ -150,33 +183,9 @@ namespace libtorrent
// this is a callback called by the tracker_connection class
// when this torrent got a response from its tracker request
void tracker_response(const entry& e);
void tracker_request_timed_out()
{
#ifndef NDEBUG
debug_log("*** tracker timed out");
#endif
// TODO: increase the retry_delay for
// each failed attempt on the same tracker!
// maybe we should add a counter that keeps
// track of how many times a specific tracker
// has timed out?
try_next_tracker();
}
// TODO: this function should also take the
// HTTP-response code as an argument
// with some codes, we should just consider
// the tracker as a failure and not retry
// it anymore
void tracker_request_error(const char* str)
{
#ifndef NDEBUG
debug_log(std::string("*** tracker error: ") + str);
#endif
try_next_tracker();
}
virtual void tracker_response(const entry& e);
virtual void tracker_request_timed_out();
virtual void tracker_request_error(const char* str);
// generates a request string for sending
// to the tracker
@ -324,6 +333,11 @@ namespace libtorrent
// std::accumulate(m_have_pieces.begin(),
// m_have_pieces.end(), 0)
int m_num_pieces;
// is false by default and set to
// true when the first tracker reponse
// is received
bool m_got_tracker_response;
};
}

View File

@ -63,10 +63,23 @@ namespace libtorrent
struct torrent_status
{
torrent_status()
: state(queued_for_checking)
, progress(0.f)
, total_download(0)
, total_upload(0)
, total_payload_download(0)
, total_payload_upload(0)
, download_rate(0)
, upload_rate(0)
, total_done(0)
{}
enum state_t
{
queued_for_checking,
checking_files,
connecting_to_tracker,
downloading,
seeding
};
@ -76,17 +89,23 @@ namespace libtorrent
boost::posix_time::time_duration next_announce;
// transferred this session!
// total, payload plus protocol
std::size_t total_download;
std::size_t total_upload;
// payload only
std::size_t total_payload_download;
std::size_t total_payload_upload;
// current transfer rate
// payload plus protocol
float download_rate;
float upload_rate;
std::vector<bool> pieces;
// the number of bytes of the file we have
std::size_t total_done;
// TODO: add flag that says if there have
// been any incoming connections
};
struct partial_piece_info
@ -103,6 +122,8 @@ namespace libtorrent
struct torrent_handle
{
friend class session;
friend class torrent;
torrent_handle(): m_ses(0) {}
void get_peer_info(std::vector<peer_info>& v) const;

View File

@ -35,7 +35,7 @@ POSSIBILITY OF SUCH DAMAGE.
namespace libtorrent {
alert_manager::alert_manager()
: m_severity(alert::warning)
: m_severity(alert::none)
{}
alert_manager::~alert_manager()

241
src/identify_client.cpp Executable file
View File

@ -0,0 +1,241 @@
/*
Copyright (c) 2003, Arvid Norberg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include <boost/optional.hpp>
#include <cctype>
#include "libtorrent/identify_client.hpp"
#include "libtorrent/fingerprint.hpp"
namespace libtorrent
{
namespace
{
// takes a peer id and returns a valid boost::optional
// object if the peer id matched the azureus style encoding
// the returned fingerprint contains information about the
// client's id
boost::optional<fingerprint> parse_az_style(const peer_id& id)
{
fingerprint ret("..", 0, 0, 0, 0);
peer_id::const_iterator i = id.begin();
if (*i != '-') return boost::optional<fingerprint>();
++i;
for (int j = 0; j < 2; ++j)
{
if (!std::isprint(*i)) return boost::optional<fingerprint>();
ret.id[j] = *i;
++i;
}
if (!std::isdigit(*i)) return boost::optional<fingerprint>();
ret.major_version = *i - '0';
++i;
if (!std::isdigit(*i)) return boost::optional<fingerprint>();
ret.minor_version = *i - '0';
++i;
if (!std::isdigit(*i)) return boost::optional<fingerprint>();
ret.revision_version = *i - '0';
++i;
if (!std::isdigit(*i)) return boost::optional<fingerprint>();
ret.tag_version = *i - '0';
++i;
if (*i != '-') return boost::optional<fingerprint>();
return boost::optional<fingerprint>(ret);
}
// checks if a peer id can possibly contain a shadow-style
// identification
boost::optional<fingerprint> parse_shadow_style(const peer_id& id)
{
fingerprint ret("..", 0, 0, 0, 0);
peer_id::const_iterator i = id.begin();
if (!std::isprint(*i)) return boost::optional<fingerprint>();
ret.id[0] = *i;
ret.id[1] = 0;
++i;
if (id[8] == 45)
{
if (!std::isdigit(*i)) return boost::optional<fingerprint>();
ret.major_version = *i - '0';
++i;
if (!std::isdigit(*i)) return boost::optional<fingerprint>();
ret.minor_version = *i - '0';
++i;
if (!std::isdigit(*i)) return boost::optional<fingerprint>();
ret.revision_version = *i - '0';
}
else if (id[0] == 0)
{
if (*i > 127) return boost::optional<fingerprint>();
ret.major_version = *i;
++i;
if (*i > 127) return boost::optional<fingerprint>();
ret.minor_version = *i;
++i;
if (*i > 127) return boost::optional<fingerprint>();
ret.revision_version = *i;
}
else
return boost::optional<fingerprint>();
ret.tag_version = 0;
return boost::optional<fingerprint>(ret);
}
} // namespace unnamed
// TODO: document
std::string identify_client(const peer_id& p)
{
peer_id::const_iterator PID = p.begin();
boost::optional<fingerprint> f;
// look for azureus style id
f = parse_az_style(p);
if (f)
{
std::stringstream identity;
// azureus
if (std::equal(f->id, f->id+2, "AZ"))
identity << "Azureus ";
// BittorrentX
else if (std::equal(f->id, f->id+2, "BX"))
identity << "BittorrentX ";
// libtorrent
else if (std::equal(f->id, f->id+2, "LT"))
identity << "libtorrent ";
// unknown client
else
identity << std::string(f->id, f->id+2) << " ";
identity << (int)f->major_version
<< "." << (int)f->minor_version
<< "." << (int)f->revision_version
<< "." << (int)f->tag_version;
return identity.str();
}
// look for shadow style id
f = parse_shadow_style(p);
if (f)
{
std::stringstream identity;
// Shadow
if (std::equal(f->id, f->id+1, "S"))
identity << "Shadow ";
// UPnP
else if (std::equal(f->id, f->id+1, "U"))
identity << "UPnP ";
// unknown client
else
identity << std::string(f->id, f->id+1) << " ";
identity << (int)f->major_version
<< "." << (int)f->minor_version
<< "." << (int)f->revision_version;
return identity.str();
}
// ----------------------
// non standard encodings
// ----------------------
if (std::equal(PID + 5, PID + 5 + 8, "Azureus"))
{
return "Azureus 2.0.3.2";
}
if (std::equal(PID, PID + 11, "DansClient"))
{
return "XanTorrent";
}
if (std::equal(PID, PID + 7, "btfans"))
{
return "BitComet";
}
if (std::equal(PID, PID + 8, "turbobt"))
{
return "TurboBT";
}
if (std::equal(PID, PID + 13, "\0\0\0\0\0\0\0\0\0\0\0\0\x97"))
{
return "Experimental 3.2.1b2";
}
if (std::equal(PID, PID + 13, "\0\0\0\0\0\0\0\0\0\0\0\0\0"))
{
return "Experimental 3.1";
}
if (std::equal(PID, PID + 12, "\0\0\0\0\0\0\0\0\0\0\0\0"))
{
return "Generic";
}
return "Unknown";
}
}

View File

@ -36,6 +36,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/peer_connection.hpp"
#include "libtorrent/session.hpp"
#include "libtorrent/identify_client.hpp"
#if defined(_MSC_VER)
#define for if (false) {} else for
@ -381,7 +382,6 @@ bool libtorrent::peer_connection::dispatch_message(int received)
{
m_have_piece[index] = true;
// TODO: maybe this if-statement should be moved into the policy
m_torrent->peer_has(index);
if (!m_torrent->have_piece(index) && !is_interesting())
m_torrent->get_policy().peer_is_interesting(*this);
@ -859,12 +859,12 @@ void libtorrent::peer_connection::second_tick()
int bias = 0;
if (diff > -2*m_torrent->block_size())
{
bias = m_statistics.download_rate() * .5;
bias = m_statistics.download_rate() / 2;
if (bias < 10*1024) bias = 10*1024;
}
else
{
bias = -m_statistics.download_rate() * .5;
bias = -m_statistics.download_rate() / 2;
}
m_send_quota_limit = m_statistics.download_rate() + bias;
// the maximum send_quota given our download rate from this peer
@ -1030,6 +1030,16 @@ void libtorrent::peer_connection::receive_data()
if (m_recv_pos < m_packet_size) break;
assert(m_recv_pos == m_packet_size);
#ifndef NDEBUG
{
peer_id tmp;
std::copy(m_recv_buffer.begin(), m_recv_buffer.begin() + 20, (char*)tmp.begin());
std::stringstream s;
s << "received peer_id: " << tmp << " client: " << identify_client(tmp) << "\n";
(*m_logger) << s.str();
}
#endif
if (m_active)
{
// verify peer_id
@ -1052,7 +1062,7 @@ void libtorrent::peer_connection::receive_data()
if (m_torrent->has_peer(m_peer_id))
{
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " duplicate connection, closing\n";
(*m_logger) << " duplicate connection, closing\n";
#endif
throw network_error(0);
}
@ -1066,9 +1076,7 @@ void libtorrent::peer_connection::receive_data()
m_packet_size = 4;
m_recv_pos = 0;
m_recv_buffer.resize(4);
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " received peer_id\n";
#endif
break;
}
@ -1234,7 +1242,7 @@ void libtorrent::peer_connection::send_data()
, amount_to_send);
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " ==> SENT [ length: " << sent << " ]\n";
// (*m_logger) << m_socket->sender().as_string() << " ==> SENT [ length: " << sent << " ]\n";
#endif
if (sent > 0)

View File

@ -593,8 +593,8 @@ namespace libtorrent
assert(i != m_peers.end());
i->connected = boost::posix_time::second_clock::local_time();
i->prev_amount_download += c.statistics().total_download();
i->prev_amount_upload += c.statistics().total_upload();
i->prev_amount_download += c.statistics().total_payload_download();
i->prev_amount_upload += c.statistics().total_payload_upload();
if (!i->connection->is_choked() && !m_torrent->is_aborted())
{
--m_num_unchoked;
@ -651,7 +651,7 @@ namespace libtorrent
int policy::peer::total_download() const
{
if (connection != 0)
return connection->statistics().total_download()
return connection->statistics().total_payload_download()
+ prev_amount_download;
else
return prev_amount_download;
@ -660,7 +660,7 @@ namespace libtorrent
int policy::peer::total_upload() const
{
if (connection != 0)
return connection->statistics().total_upload()
return connection->statistics().total_payload_upload()
+ prev_amount_upload;
else
return prev_amount_upload;

View File

@ -337,6 +337,7 @@ namespace libtorrent
, m_tracker_manager(m_settings)
, m_listen_port(listen_port)
, m_upload_rate(-1)
, m_incoming_connection(false)
{
// ---- generate a peer id ----
@ -462,6 +463,7 @@ namespace libtorrent
if (s)
{
// we got a connection request!
m_incoming_connection = true;
#ifndef NDEBUG
(*m_logger) << s->sender().as_string() << " <== INCOMING CONNECTION\n";
#endif
@ -864,203 +866,15 @@ namespace libtorrent
std::auto_ptr<alert> session::pop_alert()
{
return m_impl.m_alerts.get();
if (m_impl.m_alerts.pending())
return m_impl.m_alerts.get();
else
return std::auto_ptr<alert>(0);
}
namespace
void session::set_severity_level(alert::severity_t s)
{
// takes a peer id and returns a valid boost::optional
// object if the peer id matched the azureus style encoding
// the returned fingerprint contains information about the
// client's id
boost::optional<fingerprint> parse_az_style(const peer_id& id)
{
fingerprint ret("..", 0, 0, 0, 0);
peer_id::const_iterator i = id.begin();
if (*i != '-') return boost::optional<fingerprint>();
++i;
for (int j = 0; j < 2; ++j)
{
if (!std::isprint(*i)) return boost::optional<fingerprint>();
ret.id[j] = *i;
++i;
}
if (!std::isdigit(*i)) return boost::optional<fingerprint>();
ret.major_version = *i - '0';
++i;
if (!std::isdigit(*i)) return boost::optional<fingerprint>();
ret.minor_version = *i - '0';
++i;
if (!std::isdigit(*i)) return boost::optional<fingerprint>();
ret.revision_version = *i - '0';
++i;
if (!std::isdigit(*i)) return boost::optional<fingerprint>();
ret.tag_version = *i - '0';
++i;
if (*i != '-') return boost::optional<fingerprint>();
return boost::optional<fingerprint>(ret);
}
// checks if a peer id can possibly contain a shadow-style
// identification
boost::optional<fingerprint> parse_shadow_style(const peer_id& id)
{
fingerprint ret("..", 0, 0, 0, 0);
peer_id::const_iterator i = id.begin();
if (!std::isprint(*i)) return boost::optional<fingerprint>();
ret.id[0] = *i;
ret.id[1] = 0;
++i;
if (id[8] == 45)
{
if (!std::isdigit(*i)) return boost::optional<fingerprint>();
ret.major_version = *i - '0';
++i;
if (!std::isdigit(*i)) return boost::optional<fingerprint>();
ret.minor_version = *i - '0';
++i;
if (!std::isdigit(*i)) return boost::optional<fingerprint>();
ret.revision_version = *i - '0';
}
else if (id[0] == 0)
{
if (*i > 127) return boost::optional<fingerprint>();
ret.major_version = *i;
++i;
if (*i > 127) return boost::optional<fingerprint>();
ret.minor_version = *i;
++i;
if (*i > 127) return boost::optional<fingerprint>();
ret.revision_version = *i;
}
else
return boost::optional<fingerprint>();
ret.tag_version = 0;
return boost::optional<fingerprint>(ret);
}
} // namespace unnamed
// TODO: document
std::string identify_client(const peer_id& p)
{
peer_id::const_iterator PID = p.begin();
boost::optional<fingerprint> f;
// look for azureus style id
f = parse_az_style(p);
if (f)
{
std::stringstream identity;
// azureus
if (std::equal(f->id, f->id+2, "AZ"))
identity << "Azureus ";
// BittorrentX
else if (std::equal(f->id, f->id+2, "BX"))
identity << "BittorrentX ";
// libtorrent
else if (std::equal(f->id, f->id+2, "LT"))
identity << "libtorrent ";
// unknown client
else
identity << std::string(f->id, f->id+2) << " ";
identity << (int)f->major_version
<< "." << (int)f->minor_version
<< "." << (int)f->revision_version
<< "." << (int)f->tag_version;
return identity.str();
}
// look for shadow style id
f = parse_shadow_style(p);
if (f)
{
std::stringstream identity;
// Shadow
if (std::equal(f->id, f->id+1, "S"))
identity << "Shadow ";
// UPnP
else if (std::equal(f->id, f->id+1, "U"))
identity << "UPnP ";
// unknown client
else
identity << std::string(f->id, f->id+1) << " ";
identity << (int)f->major_version
<< "." << (int)f->minor_version
<< "." << (int)f->revision_version;
return identity.str();
}
// ----------------------
// non standard encodings
// ----------------------
if (std::equal(PID + 5, PID + 5 + 8, "Azureus"))
{
return "Azureus 2.0.3.2";
}
if (std::equal(PID, PID + 11, "DansClient"))
{
return "XanTorrent";
}
if (std::equal(PID, PID + 7, "btfans"))
{
return "BitComet";
}
if (std::equal(PID, PID + 8, "turbobt"))
{
return "TurboBT";
}
if (std::equal(PID, PID + 13, "\0\0\0\0\0\0\0\0\0\0\0\x97"))
{
return "Experimental 3.2.1b2";
}
if (std::equal(PID, PID + 13, "\0\0\0\0\0\0\0\0\0\0\0\0"))
{
return "Experimental 3.1";
}
return "Generic";
}
m_impl.m_alerts.set_severity(s);
}
}

View File

@ -51,10 +51,10 @@ void libtorrent::stat::second_tick()
m_upload_per_second_history+history-1,
m_upload_per_second_history+1);
m_download_per_second_history[0] = m_downloaded + m_downloaded_protocol;
m_upload_per_second_history[0] = m_uploaded + m_uploaded_protocol;
m_downloaded = 0;
m_uploaded = 0;
m_download_per_second_history[0] = m_downloaded_payload + m_downloaded_protocol;
m_upload_per_second_history[0] = m_uploaded_payload + m_uploaded_protocol;
m_downloaded_payload = 0;
m_uploaded_payload = 0;
m_downloaded_protocol = 0;
m_uploaded_protocol = 0;

View File

@ -51,6 +51,8 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/entry.hpp"
#include "libtorrent/peer.hpp"
#include "libtorrent/peer_id.hpp"
#include "libtorrent/alert.hpp"
#include "libtorrent/identify_client.hpp"
#if defined(_MSC_VER) && _MSC_VER < 1300
namespace std
@ -177,6 +179,7 @@ namespace libtorrent
, m_time_scaler(0)
, m_priority(.5)
, m_num_pieces(0)
, m_got_tracker_response(false)
{
assert(torrent_file.begin_files() != torrent_file.end_files());
m_have_pieces.resize(torrent_file.num_pieces(), false);
@ -250,6 +253,7 @@ namespace libtorrent
tracker_request_error(e.what());
}
m_got_tracker_response = true;
}
bool torrent::has_peer(const peer_id& id) const
@ -282,6 +286,13 @@ namespace libtorrent
void torrent::piece_failed(int index)
{
if (m_ses.m_alerts.should_post(alert::info))
{
std::stringstream s;
s << "hash for piece " << index << " failed";
torrent_handle self(&m_ses, 0, m_torrent_file.info_hash());
m_ses.m_alerts.post_alert(hash_failed_alert(self, index, s.str()));
}
std::vector<peer_id> downloaders;
m_picker.get_downloaders(downloaders, index);
@ -365,10 +376,10 @@ namespace libtorrent
request += boost::lexical_cast<std::string>(port);
request += "&uploaded=";
request += boost::lexical_cast<std::string>(m_stat.total_upload());
request += boost::lexical_cast<std::string>(m_stat.total_payload_upload());
request += "&downloaded=";
request += boost::lexical_cast<std::string>(m_stat.total_download());
request += boost::lexical_cast<std::string>(m_stat.total_payload_download());
request += "&left=";
request += boost::lexical_cast<std::string>(bytes_left());
@ -450,7 +461,7 @@ namespace libtorrent
m_connections.erase(i);
#ifndef NDEBUG
m_picker.integrity_check(this);
// m_picker.integrity_check(this);
#endif
}
@ -628,10 +639,20 @@ namespace libtorrent
- blocks_per_piece;
}
st.total_download = m_stat.total_download();
st.total_upload = m_stat.total_upload();
// payload transfer
st.total_payload_download = m_stat.total_payload_download();
st.total_payload_upload = m_stat.total_payload_upload();
// total transfer
st.total_download = m_stat.total_payload_download()
+ m_stat.total_protocol_download();
st.total_upload = m_stat.total_payload_upload()
+ m_stat.total_protocol_upload();
// transfer rate
st.download_rate = m_stat.download_rate();
st.upload_rate = m_stat.upload_rate();
st.progress = (blocks_we_have + unverified_blocks)
/ static_cast<float>(total_blocks);
@ -644,7 +665,9 @@ namespace libtorrent
st.total_done = (blocks_we_have + unverified_blocks) * m_block_size;
st.pieces = m_have_pieces;
if (m_num_pieces == p.size())
if (m_got_tracker_response == false)
st.state = torrent_status::connecting_to_tracker;
else if (m_num_pieces == p.size())
st.state = torrent_status::seeding;
else
st.state = torrent_status::downloading;
@ -652,6 +675,53 @@ namespace libtorrent
return st;
}
void torrent::tracker_request_timed_out()
{
#ifndef NDEBUG
debug_log("*** tracker timed out");
#endif
if (m_ses.m_alerts.should_post(alert::warning))
{
std::stringstream s;
s << "tracker: \""
<< m_torrent_file.trackers()[m_currently_trying_tracker].url
<< "\" timed out";
torrent_handle self(&m_ses, 0, m_torrent_file.info_hash());
m_ses.m_alerts.post_alert(tracker_alert( self, s.str()));
}
// TODO: increase the retry_delay for
// each failed attempt on the same tracker!
// maybe we should add a counter that keeps
// track of how many times a specific tracker
// has timed out?
try_next_tracker();
}
// TODO: this function should also take the
// HTTP-response code as an argument
// with some codes, we should just consider
// the tracker as a failure and not retry
// it anymore
void torrent::tracker_request_error(const char* str)
{
#ifndef NDEBUG
debug_log(std::string("*** tracker error: ") + str);
#endif
if (m_ses.m_alerts.should_post(alert::warning))
{
std::stringstream s;
s << "tracker: \""
<< m_torrent_file.trackers()[m_currently_trying_tracker].url
<< "\" " << str;
torrent_handle self(&m_ses, 0, m_torrent_file.info_hash());
m_ses.m_alerts.post_alert(tracker_alert(self, s.str()));
}
try_next_tracker();
}
#ifndef NDEBUG
void torrent::debug_log(const std::string& line)
{

View File

@ -68,7 +68,6 @@ namespace libtorrent
{
if (m_ses == 0) throw invalid_handle();
assert(m_chk != 0);
{
boost::mutex::scoped_lock l(m_ses->m_mutex);
torrent* t = m_ses->find_torrent(m_info_hash);
@ -80,6 +79,7 @@ namespace libtorrent
}
if (m_chk)
{
boost::mutex::scoped_lock l(m_chk->m_mutex);
@ -97,13 +97,13 @@ namespace libtorrent
{
if (m_ses == 0) throw invalid_handle();
assert(m_chk != 0);
{
boost::mutex::scoped_lock l(m_ses->m_mutex);
torrent* t = m_ses->find_torrent(m_info_hash);
if (t != 0) return t->status();
}
if (m_chk)
{
boost::mutex::scoped_lock l(m_chk->m_mutex);
@ -111,10 +111,7 @@ namespace libtorrent
if (d != 0)
{
torrent_status st;
st.total_download = 0;
st.total_upload = 0;
st.download_rate = 0.f;
st.upload_rate = 0.f;
if (d == &m_chk->m_torrents.front())
st.state = torrent_status::checking_files;
else
@ -123,7 +120,6 @@ namespace libtorrent
st.next_announce = boost::posix_time::time_duration();
st.pieces.clear();
st.pieces.resize(d->torrent_ptr->torrent_file().num_pieces(), false);
st.total_done = 0;
return st;
}
}
@ -141,6 +137,7 @@ namespace libtorrent
if (t != 0) return t->torrent_file();
}
if (m_chk)
{
boost::mutex::scoped_lock l(m_chk->m_mutex);
detail::piece_checker_data* d = m_chk->find_torrent(m_info_hash);
@ -160,6 +157,7 @@ namespace libtorrent
if (t != 0) return true;
}
if (m_chk)
{
boost::mutex::scoped_lock l(m_chk->m_mutex);
detail::piece_checker_data* d = m_chk->find_torrent(m_info_hash);
@ -190,6 +188,7 @@ namespace libtorrent
}
}
if (m_chk)
{
boost::mutex::scoped_lock l(m_chk->m_mutex);
detail::piece_checker_data* d = m_chk->find_torrent(m_info_hash);
@ -207,7 +206,6 @@ namespace libtorrent
{
v.clear();
if (m_ses == 0) throw invalid_handle();
assert(m_chk != 0);
boost::mutex::scoped_lock l(m_ses->m_mutex);
@ -235,8 +233,8 @@ namespace libtorrent
// TODO: add the prev_amount_downloaded and prev_amount_uploaded
// from the peer list in the policy
p.total_download = statistics.total_download();
p.total_upload = statistics.total_upload();
p.total_download = statistics.total_payload_download();
p.total_upload = statistics.total_payload_upload();
p.upload_limit = peer->send_quota();
p.upload_ceiling = peer->send_quota_limit();
@ -274,7 +272,6 @@ namespace libtorrent
queue.clear();
if (m_ses == 0) throw invalid_handle();
assert(m_chk != 0);
boost::mutex::scoped_lock l(m_ses->m_mutex);
torrent* t = m_ses->find_torrent(m_info_hash);