*** empty log message ***
This commit is contained in:
parent
cb89ccf6be
commit
5ac9f67f23
15
Jamfile
15
Jamfile
|
@ -1,5 +1,3 @@
|
|||
|
||||
|
||||
SOURCES =
|
||||
entry.cpp
|
||||
peer_connection.cpp
|
||||
|
@ -16,15 +14,18 @@ SOURCES =
|
|||
sha1.c
|
||||
;
|
||||
|
||||
|
||||
lib torrent
|
||||
: src/$(SOURCES)
|
||||
zlib//zlib
|
||||
$(BOOST_ROOT)/libs/filesystem/build//boost_filesystem
|
||||
$(BOOST_ROOT)/libs/thread/build//boost_thread
|
||||
# <lib>zlib/zlib
|
||||
# zlib//zlib
|
||||
# <file>boost_filesystem.lib
|
||||
# <file>boost_date_time.lib
|
||||
# <file>boost_thread.dll
|
||||
: <include>$(BOOST_ROOT)
|
||||
<sysinclude>$(BOOST_ROOT)
|
||||
<include>./include
|
||||
<include>./
|
||||
<include>./zlib
|
||||
<threading>multi
|
||||
<link>static
|
||||
: debug release
|
||||
|
@ -33,7 +34,7 @@ lib torrent
|
|||
|
||||
exe client_test
|
||||
: examples/client_test.cpp
|
||||
torrent
|
||||
<lib>torrent
|
||||
: <include>$(BOOST_ROOT)
|
||||
<sysinclude>$(BOOST_ROOT)
|
||||
<include>./include
|
||||
|
|
126
docs/index.html
126
docs/index.html
|
@ -43,23 +43,24 @@
|
|||
<li><a class="reference" href="#http-settings" id="id21" name="id21">http_settings</a></li>
|
||||
<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="#exceptions" id="id24" name="id24">exceptions</a><ul>
|
||||
<li><a class="reference" href="#invalid-handle" id="id25" name="id25">invalid_handle</a></li>
|
||||
<li><a class="reference" href="#duplicate-torrent" id="id26" name="id26">duplicate_torrent</a></li>
|
||||
<li><a class="reference" href="#invalid-encoding" id="id27" name="id27">invalid_encoding</a></li>
|
||||
<li><a class="reference" href="#type-error" id="id28" name="id28">type_error</a></li>
|
||||
<li><a class="reference" href="#invalid-torrent-file" id="id29" name="id29">invalid_torrent_file</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>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference" href="#example-usage" id="id30" name="id30">example usage</a><ul>
|
||||
<li><a class="reference" href="#dump-torrent" id="id31" name="id31">dump_torrent</a></li>
|
||||
<li><a class="reference" href="#simple-client" id="id32" name="id32">simple client</a></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>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference" href="#feedback" id="id33" name="id33">Feedback</a></li>
|
||||
<li><a class="reference" href="#aknowledgements" id="id34" name="id34">Aknowledgements</a></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>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="introduction">
|
||||
|
@ -88,9 +89,10 @@ 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</li>
|
||||
<li>can limit the upload bandwidth usage and the maximum number of unchoked peers</li>
|
||||
<li>piece-wise file allocation</li>
|
||||
<li>upload rate limit, balanced depending on download speed and upload bandwidth</li>
|
||||
<li>tries to maintain a 1:1 share ratio between all peers but also shifts free
|
||||
download to peers as free upload. To maintain a global 1:1 ratio.</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<p>Functions that are yet to be implemented:</p>
|
||||
|
@ -115,6 +117,12 @@ boost.filesystem boost.date_time and various other boost libraries and zlib.</p>
|
|||
<li>Linux x86 (debian) GCC 3.0</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<p>It does not compile on</p>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li>GCC 2.95</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
</div>
|
||||
<div class="section" id="building">
|
||||
<h1><a class="toc-backref" href="#id8" name="building">building</a></h1>
|
||||
|
@ -158,7 +166,8 @@ the <tt class="literal"><span class="pre">session</span></tt>, it contains the m
|
|||
<pre class="literal-block">
|
||||
class session: public boost::noncopyable
|
||||
{
|
||||
session(int listen_port, const std::string& fingerprint = std::string());
|
||||
session(int listen_port, const fingerprint& print);
|
||||
session(int listen_port);
|
||||
|
||||
torrent_handle add_torrent(const torrent_info& t, const std::string& save_path);
|
||||
void remove_torrent(const torrent_handle& h);
|
||||
|
@ -179,9 +188,11 @@ the tracker that we've stopped participating in the swarm.</p>
|
|||
<p>If the torrent you are trying to add already exists in the session (is either queued
|
||||
for checking, being checked or downloading) <tt class="literal"><span class="pre">add_torrent()</span></tt> will throw
|
||||
<tt class="literal"><span class="pre">duplicate_torrent</span></tt> which derives from <tt class="literal"><span class="pre">std::exception</span></tt>.</p>
|
||||
<p><tt class="literal"><span class="pre">fingerprint</span></tt> is a short string that will be used in the peer_id to
|
||||
identify the client. If the string is longer than 7 characters it will
|
||||
be trimmed down to 7 characters. The default is an empty string.</p>
|
||||
<p>The difference between the two constructors is that one of them takes a fingerprint
|
||||
as argument. If this is ommited, the client will get a default fingerprint stating
|
||||
the version of libtorrent. The fingerprint is a short string that will be used in
|
||||
the peer-id to identify the client and the client's version. For more details see the
|
||||
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>
|
||||
|
@ -555,6 +566,8 @@ struct peer_info
|
|||
int upload_limit;
|
||||
int upload_ceiling;
|
||||
|
||||
int load_balancing;
|
||||
|
||||
int downloading_piece_index;
|
||||
int downloading_block_index;
|
||||
int downloading_progress;
|
||||
|
@ -586,6 +599,11 @@ should sum up to the upload limit set by <tt class="literal"><span class="pre">s
|
|||
<p><tt class="literal"><span class="pre">upload_ceiling</span></tt> is the current maximum allowed upload rate given the cownload
|
||||
rate and share ratio. If the global upload rate is inlimited, the <tt class="literal"><span class="pre">upload_limit</span></tt>
|
||||
for every peer will be the same as their <tt class="literal"><span class="pre">upload_ceiling</span></tt>.</p>
|
||||
<p><tt class="literal"><span class="pre">load_balancing</span></tt> is a measurment of the balancing of free download (that we get)
|
||||
and free upload that we give. Every peer gets a certain amount of free upload, but
|
||||
this member says how much <em>extra</em> free upload this peer has got. If it is a negative
|
||||
number it means that this was a peer from which we have got this amount of free
|
||||
download.</p>
|
||||
<p>You can know which piece, and which part of that piece, that is currently being
|
||||
downloaded from a specific peer by looking at the next four members.
|
||||
<tt class="literal"><span class="pre">downloading_piece_index</span></tt> is the index of the piece that is currently being downloaded.
|
||||
|
@ -725,12 +743,61 @@ call <tt class="literal"><span class="pre">reset()</span></tt> to reinitialize i
|
|||
<p>The sha1-algorithm used was implemented by Steve Reid and released as public domain.
|
||||
For more info, see <tt class="literal"><span class="pre">src/sha1.c</span></tt>.</p>
|
||||
</div>
|
||||
<div class="section" id="fingerprint">
|
||||
<h2><a class="toc-backref" href="#id24" name="fingerprint">fingerprint</a></h2>
|
||||
<p>The fingerprint class represents information about a client and its version. It is used
|
||||
to encode this information into the client's peer id.</p>
|
||||
<p>This is the class declaration:</p>
|
||||
<pre class="literal-block">
|
||||
struct fingerprint
|
||||
{
|
||||
fingerprint(const char* id_string, int major, int minor, int revision, int tag);
|
||||
|
||||
std::string to_string() const;
|
||||
|
||||
char id[2];
|
||||
char major_version;
|
||||
char minor_version;
|
||||
char revision_version;
|
||||
char tag_version;
|
||||
|
||||
};
|
||||
</pre>
|
||||
<p>The constructor takes a <tt class="literal"><span class="pre">const</span> <span class="pre">char*</span></tt> that should point to a string constant containing
|
||||
exactly two characters. These are the characters that should be unique for your client. Make
|
||||
sure not to clash with anybody else. Here are some taken id's:</p>
|
||||
<table border class="table">
|
||||
<colgroup>
|
||||
<col width="30%" />
|
||||
<col width="70%" />
|
||||
</colgroup>
|
||||
<thead valign="bottom">
|
||||
<tr><th>id chars</th>
|
||||
<th>client</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody valign="top">
|
||||
<tr><td>'AZ'</td>
|
||||
<td>Azureus</td>
|
||||
</tr>
|
||||
<tr><td>'LT'</td>
|
||||
<td>libtorrent (default)</td>
|
||||
</tr>
|
||||
<tr><td>'BX'</td>
|
||||
<td>BittorrentX</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>The <tt class="literal"><span class="pre">major</span></tt>, <tt class="literal"><span class="pre">minor</span></tt>, <tt class="literal"><span class="pre">revision</span></tt> and <tt class="literal"><span class="pre">tag</span></tt> parameters are used to identify the
|
||||
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="exceptions">
|
||||
<h2><a class="toc-backref" href="#id24" name="exceptions">exceptions</a></h2>
|
||||
<h2><a class="toc-backref" href="#id25" 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="#id25" name="invalid-handle">invalid_handle</a></h3>
|
||||
<h3><a class="toc-backref" href="#id26" 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">
|
||||
|
@ -741,7 +808,7 @@ struct invalid_handle: std::exception
|
|||
</pre>
|
||||
</div>
|
||||
<div class="section" id="duplicate-torrent">
|
||||
<h3><a class="toc-backref" href="#id26" name="duplicate-torrent">duplicate_torrent</a></h3>
|
||||
<h3><a class="toc-backref" href="#id27" 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">
|
||||
|
@ -752,7 +819,7 @@ struct duplicate_torrent: std::exception
|
|||
</pre>
|
||||
</div>
|
||||
<div class="section" id="invalid-encoding">
|
||||
<h3><a class="toc-backref" href="#id27" name="invalid-encoding">invalid_encoding</a></h3>
|
||||
<h3><a class="toc-backref" href="#id28" 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
|
||||
|
@ -762,7 +829,7 @@ struct invalid_encoding: std::exception
|
|||
</pre>
|
||||
</div>
|
||||
<div class="section" id="type-error">
|
||||
<h3><a class="toc-backref" href="#id28" name="type-error">type_error</a></h3>
|
||||
<h3><a class="toc-backref" href="#id29" 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">
|
||||
|
@ -773,7 +840,7 @@ struct type_error: std::runtime_error
|
|||
</pre>
|
||||
</div>
|
||||
<div class="section" id="invalid-torrent-file">
|
||||
<h3><a class="toc-backref" href="#id29" name="invalid-torrent-file">invalid_torrent_file</a></h3>
|
||||
<h3><a class="toc-backref" href="#id30" 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">
|
||||
|
@ -785,9 +852,9 @@ struct invalid_torrent_file: std::exception
|
|||
</div>
|
||||
</div>
|
||||
<div class="section" id="example-usage">
|
||||
<h2><a class="toc-backref" href="#id30" name="example-usage">example usage</a></h2>
|
||||
<h2><a class="toc-backref" href="#id31" name="example-usage">example usage</a></h2>
|
||||
<div class="section" id="dump-torrent">
|
||||
<h3><a class="toc-backref" href="#id31" name="dump-torrent">dump_torrent</a></h3>
|
||||
<h3><a class="toc-backref" href="#id32" 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">
|
||||
|
@ -851,7 +918,7 @@ int main(int argc, char* argv[])
|
|||
</pre>
|
||||
</div>
|
||||
<div class="section" id="simple-client">
|
||||
<h3><a class="toc-backref" href="#id32" name="simple-client">simple client</a></h3>
|
||||
<h3><a class="toc-backref" href="#id33" 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 <iostream>
|
||||
|
@ -880,7 +947,7 @@ int main(int argc, char* argv[])
|
|||
|
||||
try
|
||||
{
|
||||
session s(6881, "E\x1");
|
||||
session s(6881);
|
||||
|
||||
std::ifstream in(argv[1], std::ios_base::binary);
|
||||
in.unsetf(std::ios_base::skipws);
|
||||
|
@ -904,14 +971,15 @@ int main(int argc, char* argv[])
|
|||
</div>
|
||||
</div>
|
||||
<div class="section" id="feedback">
|
||||
<h1><a class="toc-backref" href="#id33" name="feedback">Feedback</a></h1>
|
||||
<h1><a class="toc-backref" href="#id34" 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">@</span> <span class="pre">irc.freenode.net</span></tt>.</p>
|
||||
</div>
|
||||
<div class="section" id="aknowledgements">
|
||||
<h1><a class="toc-backref" href="#id34" name="aknowledgements">Aknowledgements</a></h1>
|
||||
<h1><a class="toc-backref" href="#id35" 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>
|
||||
<p>Project is hosted by sourceforge.</p>
|
||||
<p><a class="reference" href="http://sourceforge.net"><img alt="sf_logo" src="http://sourceforge.net/sflogo.php?group_id=7994" /></a></p>
|
||||
</div>
|
||||
|
|
|
@ -832,6 +832,8 @@ sure not to clash with anybody else. Here are some taken id's:
|
|||
+----------+-----------------------+
|
||||
| 'LT' | libtorrent (default) |
|
||||
+----------+-----------------------+
|
||||
| 'BX' | BittorrentX |
|
||||
+----------+-----------------------+
|
||||
|
||||
The ``major``, ``minor``, ``revision`` and ``tag`` parameters are used to identify the
|
||||
version of your client. All these numbers must be within the range [0, 9].
|
||||
|
|
|
@ -302,8 +302,13 @@ int main(int argc, char* argv[])
|
|||
if (progress > j) out << "#";
|
||||
else out << "-";
|
||||
}
|
||||
out << "\n";
|
||||
out << " ";
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 19; ++i) out << " ";
|
||||
}
|
||||
out << identify_client(i->id) << "\n";
|
||||
}
|
||||
|
||||
out << "___________________________________\n";
|
||||
|
|
|
@ -65,6 +65,12 @@ namespace libtorrent
|
|||
return false;
|
||||
}
|
||||
|
||||
unsigned char& operator[](int i)
|
||||
{ assert(i >= 0 && i < number_size); return m_number[i]; }
|
||||
|
||||
unsigned char operator[](int i) const
|
||||
{ assert(i >= 0 && i < number_size); return m_number[i]; }
|
||||
|
||||
typedef const unsigned char* const_iterator;
|
||||
typedef unsigned char* iterator;
|
||||
|
||||
|
|
|
@ -182,7 +182,7 @@ namespace libtorrent
|
|||
|
||||
struct http_settings;
|
||||
|
||||
std::string extract_fingerprint(const peer_id& p);
|
||||
std::string identify_client(const peer_id& p);
|
||||
|
||||
class session: public boost::noncopyable, detail::eh_initializer
|
||||
{
|
||||
|
|
|
@ -84,6 +84,9 @@ namespace libtorrent
|
|||
|
||||
// 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
|
||||
|
|
|
@ -485,6 +485,7 @@ namespace libtorrent
|
|||
// this means we're already connected
|
||||
// to this peer. don't connect to
|
||||
// it again.
|
||||
assert(i->connection->associated_torrent() == m_torrent);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
233
src/session.cpp
233
src/session.cpp
|
@ -62,6 +62,8 @@ namespace std
|
|||
};
|
||||
#endif
|
||||
|
||||
// TODO: enable floating point exceptions in debug mode!
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
|
@ -486,6 +488,10 @@ namespace libtorrent
|
|||
{
|
||||
// (*m_logger) << "readable: " << p->first->sender().as_string() << "\n";
|
||||
p->second->receive_data();
|
||||
|
||||
#ifndef NDEBUG
|
||||
assert_invariant();
|
||||
#endif
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
|
@ -684,7 +690,19 @@ namespace libtorrent
|
|||
i != m_connections.end();
|
||||
++i)
|
||||
{
|
||||
assert(i->second->has_data() == m_selector.is_writability_monitored(i->first));
|
||||
if (i->second->has_data() != m_selector.is_writability_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::assert_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::send_quota " << p->send_quota() << "\n";
|
||||
error_log << "peer_connection::get_peer_id " << p->get_peer_id() << "\n";
|
||||
error_log.flush();
|
||||
assert(false);
|
||||
}
|
||||
if (i->second->associated_torrent())
|
||||
{
|
||||
assert(i->second->associated_torrent()
|
||||
|
@ -849,25 +867,200 @@ namespace libtorrent
|
|||
return m_impl.m_alerts.get();
|
||||
}
|
||||
|
||||
// TODO: document
|
||||
// TODO: if the first 4 charachters are printable
|
||||
// maybe they should be considered a fingerprint?
|
||||
std::string extract_fingerprint(const peer_id& p)
|
||||
namespace
|
||||
{
|
||||
std::string ret;
|
||||
const unsigned char* c = p.begin();
|
||||
while (c != p.end() && *c != 0)
|
||||
{
|
||||
if (std::isprint(*c))
|
||||
ret += *c;
|
||||
else if (*c <= 9)
|
||||
ret += '0'+ *c;
|
||||
else
|
||||
return std::string();
|
||||
++c;
|
||||
}
|
||||
if (c == p.end()) return std::string();
|
||||
|
||||
return ret;
|
||||
}
|
||||
// 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";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -466,6 +466,8 @@ namespace libtorrent {
|
|||
m_pimpl->write(buf, piece_index, offset, size);
|
||||
}
|
||||
|
||||
// TODO: must handle the case where some hashes are identical
|
||||
// correctly
|
||||
void piece_manager::impl::check_pieces(
|
||||
boost::mutex& mutex
|
||||
, detail::piece_checker_data& data
|
||||
|
@ -612,6 +614,8 @@ namespace libtorrent {
|
|||
|
||||
int found_piece = -1;
|
||||
|
||||
// TODO: there's still potential problems if some
|
||||
// pieces have the same hash
|
||||
for (int i = current_slot; i < m_info.num_pieces(); ++i)
|
||||
{
|
||||
if (pieces[i] && i != current_slot) continue;
|
||||
|
@ -620,7 +624,10 @@ namespace libtorrent {
|
|||
i == m_info.num_pieces() - 1]->get();
|
||||
|
||||
if (hash == m_info.hash_for_piece(i))
|
||||
{
|
||||
found_piece = i;
|
||||
if (i == current_slot) break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found_piece != -1)
|
||||
|
|
|
@ -73,8 +73,22 @@ namespace
|
|||
|
||||
int calculate_block_size(const torrent_info& i)
|
||||
{
|
||||
// TODO: if blocks_per_piece > 128 increase block-size
|
||||
return 16*1024;
|
||||
const int default_block_size = 16 * 1024;
|
||||
|
||||
// if pieces are too small, adjust the block size
|
||||
if (i.piece_length() < default_block_size)
|
||||
{
|
||||
return i.piece_length();
|
||||
}
|
||||
|
||||
// if pieces are too large, adjust the block size
|
||||
if (i.piece_length() / default_block_size > 128)
|
||||
{
|
||||
return i.piece_length() / 128;
|
||||
}
|
||||
|
||||
// otherwise, go with the default
|
||||
return default_block_size;
|
||||
}
|
||||
|
||||
|
||||
|
@ -199,7 +213,7 @@ namespace libtorrent
|
|||
{
|
||||
std::cout << " " << std::setfill(' ') << std::setw(16) << i->ip
|
||||
<< " " << std::setw(5) << std::dec << i->port << " "
|
||||
<< i->id << " " << extract_fingerprint(i->id) << "\n";
|
||||
<< i->id << " " << identify_client(i->id) << "\n";
|
||||
}
|
||||
std::cout << std::setfill(' ');
|
||||
|
||||
|
|
Loading…
Reference in New Issue