*** empty log message ***
This commit is contained in:
parent
88f1d8200a
commit
19a4dad706
124
docs/manual.html
124
docs/manual.html
|
@ -14,56 +14,59 @@
|
|||
<p class="topic-title"><a name="contents">Contents</a></p>
|
||||
<ul class="simple">
|
||||
<li><a class="reference" href="#introduction" id="id9" name="id9">introduction</a></li>
|
||||
<li><a class="reference" href="#building" id="id10" name="id10">building</a></li>
|
||||
<li><a class="reference" href="#using" id="id11" name="id11">using</a></li>
|
||||
<li><a class="reference" href="#session" id="id12" name="id12">session</a></li>
|
||||
<li><a class="reference" href="#parsing-torrent-files" id="id13" name="id13">parsing torrent files</a></li>
|
||||
<li><a class="reference" href="#entry" id="id14" name="id14">entry</a></li>
|
||||
<li><a class="reference" href="#torrent-info" id="id15" name="id15">torrent_info</a></li>
|
||||
<li><a class="reference" href="#torrent-handle" id="id16" name="id16">torrent_handle</a><ul>
|
||||
<li><a class="reference" href="#status" id="id17" name="id17">status()</a></li>
|
||||
<li><a class="reference" href="#get-download-queue" id="id18" name="id18">get_download_queue()</a></li>
|
||||
<li><a class="reference" href="#get-peer-info" id="id19" name="id19">get_peer_info()</a></li>
|
||||
<li><a class="reference" href="#get-torrent-info" id="id20" name="id20">get_torrent_info()</a></li>
|
||||
<li><a class="reference" href="#is-valid" id="id21" name="id21">is_valid()</a></li>
|
||||
<li><a class="reference" href="#building" id="id10" name="id10">building</a><ul>
|
||||
<li><a class="reference" href="#release-and-debug-builds" id="id11" name="id11">release and debug builds</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference" href="#address" id="id22" name="id22">address</a></li>
|
||||
<li><a class="reference" href="#http-settings" id="id23" name="id23">http_settings</a></li>
|
||||
<li><a class="reference" href="#big-number" id="id24" name="id24">big_number</a></li>
|
||||
<li><a class="reference" href="#hasher" id="id25" name="id25">hasher</a></li>
|
||||
<li><a class="reference" href="#fingerprint" id="id26" name="id26">fingerprint</a><ul>
|
||||
<li><a class="reference" href="#identify-client" id="id27" name="id27">identify_client</a></li>
|
||||
<li><a class="reference" href="#using" id="id12" name="id12">using</a></li>
|
||||
<li><a class="reference" href="#session" id="id13" name="id13">session</a></li>
|
||||
<li><a class="reference" href="#parsing-torrent-files" id="id14" name="id14">parsing torrent files</a></li>
|
||||
<li><a class="reference" href="#entry" id="id15" name="id15">entry</a></li>
|
||||
<li><a class="reference" href="#torrent-info" id="id16" name="id16">torrent_info</a></li>
|
||||
<li><a class="reference" href="#torrent-handle" id="id17" name="id17">torrent_handle</a><ul>
|
||||
<li><a class="reference" href="#status" id="id18" name="id18">status()</a></li>
|
||||
<li><a class="reference" href="#get-download-queue" id="id19" name="id19">get_download_queue()</a></li>
|
||||
<li><a class="reference" href="#get-peer-info" id="id20" name="id20">get_peer_info()</a></li>
|
||||
<li><a class="reference" href="#get-torrent-info" id="id21" name="id21">get_torrent_info()</a></li>
|
||||
<li><a class="reference" href="#is-valid" id="id22" name="id22">is_valid()</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference" href="#alerts" id="id28" name="id28">alerts</a><ul>
|
||||
<li><a class="reference" href="#tracker-alert" id="id29" name="id29">tracker_alert</a></li>
|
||||
<li><a class="reference" href="#hash-failed-alert" id="id30" name="id30">hash_failed_alert</a></li>
|
||||
<li><a class="reference" href="#peer-error-alert" id="id31" name="id31">peer_error_alert</a></li>
|
||||
<li><a class="reference" href="#invalid-request-alert" id="id32" name="id32">invalid_request_alert</a></li>
|
||||
<li><a class="reference" href="#torrent-finished-alert" id="id33" name="id33">torrent_finished_alert</a></li>
|
||||
<li><a class="reference" href="#dispatcher" id="id34" name="id34">dispatcher</a></li>
|
||||
<li><a class="reference" href="#address" id="id23" name="id23">address</a></li>
|
||||
<li><a class="reference" href="#http-settings" id="id24" name="id24">http_settings</a></li>
|
||||
<li><a class="reference" href="#big-number" id="id25" name="id25">big_number</a></li>
|
||||
<li><a class="reference" href="#hasher" id="id26" name="id26">hasher</a></li>
|
||||
<li><a class="reference" href="#fingerprint" id="id27" name="id27">fingerprint</a><ul>
|
||||
<li><a class="reference" href="#identify-client" id="id28" name="id28">identify_client</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference" href="#exceptions" id="id35" name="id35">exceptions</a><ul>
|
||||
<li><a class="reference" href="#invalid-handle" id="id36" name="id36">invalid_handle</a></li>
|
||||
<li><a class="reference" href="#duplicate-torrent" id="id37" name="id37">duplicate_torrent</a></li>
|
||||
<li><a class="reference" href="#invalid-encoding" id="id38" name="id38">invalid_encoding</a></li>
|
||||
<li><a class="reference" href="#type-error" id="id39" name="id39">type_error</a></li>
|
||||
<li><a class="reference" href="#invalid-torrent-file" id="id40" name="id40">invalid_torrent_file</a></li>
|
||||
<li><a class="reference" href="#alerts" id="id29" name="id29">alerts</a><ul>
|
||||
<li><a class="reference" href="#tracker-alert" id="id30" name="id30">tracker_alert</a></li>
|
||||
<li><a class="reference" href="#hash-failed-alert" id="id31" name="id31">hash_failed_alert</a></li>
|
||||
<li><a class="reference" href="#peer-error-alert" id="id32" name="id32">peer_error_alert</a></li>
|
||||
<li><a class="reference" href="#invalid-request-alert" id="id33" name="id33">invalid_request_alert</a></li>
|
||||
<li><a class="reference" href="#torrent-finished-alert" id="id34" name="id34">torrent_finished_alert</a></li>
|
||||
<li><a class="reference" href="#dispatcher" id="id35" name="id35">dispatcher</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference" href="#examples" id="id41" name="id41">examples</a><ul>
|
||||
<li><a class="reference" href="#dump-torrent" id="id42" name="id42">dump_torrent</a></li>
|
||||
<li><a class="reference" href="#simple-client" id="id43" name="id43">simple client</a></li>
|
||||
<li><a class="reference" href="#exceptions" id="id36" name="id36">exceptions</a><ul>
|
||||
<li><a class="reference" href="#invalid-handle" id="id37" name="id37">invalid_handle</a></li>
|
||||
<li><a class="reference" href="#duplicate-torrent" id="id38" name="id38">duplicate_torrent</a></li>
|
||||
<li><a class="reference" href="#invalid-encoding" id="id39" name="id39">invalid_encoding</a></li>
|
||||
<li><a class="reference" href="#type-error" id="id40" name="id40">type_error</a></li>
|
||||
<li><a class="reference" href="#invalid-torrent-file" id="id41" name="id41">invalid_torrent_file</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference" href="#fast-resume" id="id44" name="id44">fast resume</a><ul>
|
||||
<li><a class="reference" href="#file-format" id="id45" name="id45">file format</a></li>
|
||||
<li><a class="reference" href="#examples" id="id42" name="id42">examples</a><ul>
|
||||
<li><a class="reference" href="#dump-torrent" id="id43" name="id43">dump_torrent</a></li>
|
||||
<li><a class="reference" href="#simple-client" id="id44" name="id44">simple client</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference" href="#extensions" id="id46" name="id46">extensions</a></li>
|
||||
<li><a class="reference" href="#aknowledgements" id="id47" name="id47">aknowledgements</a></li>
|
||||
<li><a class="reference" href="#fast-resume" id="id45" name="id45">fast resume</a><ul>
|
||||
<li><a class="reference" href="#file-format" id="id46" name="id46">file format</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference" href="#extensions" id="id47" name="id47">extensions</a></li>
|
||||
<li><a class="reference" href="#aknowledgements" id="id48" name="id48">aknowledgements</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="introduction">
|
||||
|
@ -105,6 +108,8 @@ peers in a separate fast-resume file.</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>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>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<p>Functions that are yet to be implemented:</p>
|
||||
|
@ -136,9 +141,6 @@ boost.filesystem, boost.date_time and various other boost libraries as well as z
|
|||
</div>
|
||||
<div class="section" id="building">
|
||||
<h1><a name="building">building</a></h1>
|
||||
<p>Whwn building in release mode you need to define NDEBUG in order to avoid
|
||||
all asserts and invariant checks within libtorrent. Developer studio does
|
||||
this by default.</p>
|
||||
<p>To build libtorrent you need <a class="reference" href="http://www.boost.org">boost</a> and bjam installed.
|
||||
Then you can use <tt class="literal"><span class="pre">bjam</span></tt> to build libtorrent.</p>
|
||||
<p>To make bjam work, you need to set the environment variable <tt class="literal"><span class="pre">BOOST_ROOT</span></tt> to the
|
||||
|
@ -168,6 +170,46 @@ of the file:</p>
|
|||
<p>In developer studio, you may have to set the compiler options "force conformance in for
|
||||
loop scope" and "treat wchar_t as built-in type" to Yes.</p>
|
||||
<p>TODO: more detailed build instructions.</p>
|
||||
<div class="section" id="release-and-debug-builds">
|
||||
<h2><a name="release-and-debug-builds">release and debug builds</a></h2>
|
||||
<p>If you just invoke the makefile you'll get a debug build. In debug the libtorrent vill
|
||||
have pretty expensive invariant checks and asserts built into it. If you want to disable
|
||||
such checks (you want to do that in a release build) you can see the table below for which
|
||||
defines you can use to control the build.</p>
|
||||
<table border class="table">
|
||||
<colgroup>
|
||||
<col width="39%" />
|
||||
<col width="61%" />
|
||||
</colgroup>
|
||||
<thead valign="bottom">
|
||||
<tr><th>macro</th>
|
||||
<th>description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody valign="top">
|
||||
<tr><td><tt class="literal"><span class="pre">NDEBUG</span></tt></td>
|
||||
<td>If you define this macro, all asserts,
|
||||
invariant checks and general debug code will be
|
||||
removed. This option takes precedence over
|
||||
other debug settings.</td>
|
||||
</tr>
|
||||
<tr><td><tt class="literal"><span class="pre">TORRENT_VERBOSE_LOGGING</span></tt></td>
|
||||
<td>If you define this macro, every peer connection
|
||||
will log its traffic to a log file.
|
||||
This setting requires a debug build, i.e.
|
||||
if you set <tt class="literal"><span class="pre">NDEBUG</span></tt> aswell, no logs will be
|
||||
written.</td>
|
||||
</tr>
|
||||
<tr><td><tt class="literal"><span class="pre">TORRENT_STORAGE_DEBUG</span></tt></td>
|
||||
<td>This will enable extra expensive invariant
|
||||
checks in the storage, including logging of
|
||||
piece sorting.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>If you experience that libtorrent uses unreasonable amounts of cpu, it will definately help to
|
||||
define <tt class="literal"><span class="pre">NDEBUG</span></tt>.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="using">
|
||||
<h1><a name="using">using</a></h1>
|
||||
|
|
|
@ -42,6 +42,8 @@ The current state includes the following features:
|
|||
* supports the ``no_peer_id=1`` extension that will ease the load off trackers.
|
||||
* supports the `udp-tracker protocol`__.
|
||||
* 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.
|
||||
|
||||
__ http://home.elp.rr.com/tur/multitracker-spec.txt
|
||||
.. _Azureus: http://azureus.sourceforge.net
|
||||
|
@ -77,11 +79,6 @@ libtorrent is released under the BSD-license_.
|
|||
building
|
||||
========
|
||||
|
||||
Whwn building in release mode you need to define NDEBUG in order to avoid
|
||||
all asserts and invariant checks within libtorrent. Developer studio does
|
||||
this by default.
|
||||
|
||||
|
||||
To build libtorrent you need boost_ and bjam installed.
|
||||
Then you can use ``bjam`` to build libtorrent.
|
||||
|
||||
|
@ -122,6 +119,37 @@ loop scope" and "treat wchar_t as built-in type" to Yes.
|
|||
TODO: more detailed build instructions.
|
||||
|
||||
|
||||
release and debug builds
|
||||
------------------------
|
||||
|
||||
If you just invoke the makefile you'll get a debug build. In debug the libtorrent vill
|
||||
have pretty expensive invariant checks and asserts built into it. If you want to disable
|
||||
such checks (you want to do that in a release build) you can see the table below for which
|
||||
defines you can use to control the build.
|
||||
|
||||
+-------------------------------+-------------------------------------------------+
|
||||
| macro | description |
|
||||
+===============================+=================================================+
|
||||
| ``NDEBUG`` | If you define this macro, all asserts, |
|
||||
| | invariant checks and general debug code will be |
|
||||
| | removed. This option takes precedence over |
|
||||
| | other debug settings. |
|
||||
+-------------------------------+-------------------------------------------------+
|
||||
| ``TORRENT_VERBOSE_LOGGING`` | If you define this macro, every peer connection |
|
||||
| | will log its traffic to a log file. |
|
||||
| | This setting requires a debug build, i.e. |
|
||||
| | if you set ``NDEBUG`` aswell, no logs will be |
|
||||
| | written. |
|
||||
+-------------------------------+-------------------------------------------------+
|
||||
| ``TORRENT_STORAGE_DEBUG`` | This will enable extra expensive invariant |
|
||||
| | checks in the storage, including logging of |
|
||||
| | piece sorting. |
|
||||
+-------------------------------+-------------------------------------------------+
|
||||
|
||||
|
||||
If you experience that libtorrent uses unreasonable amounts of cpu, it will definately help to
|
||||
define ``NDEBUG``.
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -400,7 +400,7 @@ int main(int argc, char* argv[])
|
|||
}
|
||||
*/
|
||||
}
|
||||
/*
|
||||
|
||||
out << "___________________________________\n";
|
||||
|
||||
i->get_download_queue(queue);
|
||||
|
@ -421,7 +421,7 @@ int main(int argc, char* argv[])
|
|||
}
|
||||
|
||||
out << "___________________________________\n";
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
for (std::deque<std::string>::iterator i = events.begin();
|
||||
|
|
|
@ -80,6 +80,7 @@ namespace libtorrent
|
|||
virtual std::auto_ptr<alert> clone() const
|
||||
{ return std::auto_ptr<alert>(new peer_error_alert(*this)); }
|
||||
|
||||
// TODO: use address instead of peer_id
|
||||
peer_id id;
|
||||
};
|
||||
|
||||
|
@ -98,6 +99,7 @@ namespace libtorrent
|
|||
{ return std::auto_ptr<alert>(new chat_message_alert(*this)); }
|
||||
|
||||
torrent_handle handle;
|
||||
// TODO: use address instead of peer_id
|
||||
peer_id sender;
|
||||
};
|
||||
|
||||
|
@ -118,6 +120,7 @@ namespace libtorrent
|
|||
{ return std::auto_ptr<alert>(new invalid_request_alert(*this)); }
|
||||
|
||||
torrent_handle handle;
|
||||
// TODO: use address instead of peer_id
|
||||
peer_id sender;
|
||||
peer_request request;
|
||||
};
|
||||
|
|
|
@ -41,14 +41,34 @@ extern "C"
|
|||
unsigned char buffer[64];
|
||||
} SHA1_CTX;
|
||||
|
||||
/* from sha1.c */
|
||||
void SHA1Init(SHA1_CTX* context);
|
||||
void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len);
|
||||
void SHA1Final(unsigned char* digest, SHA1_CTX* context);
|
||||
|
||||
/* from zlib/adler32.c */
|
||||
unsigned long adler32(unsigned long adler, const char* data, unsigned int len);
|
||||
}
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
||||
class adler32_crc
|
||||
{
|
||||
public:
|
||||
adler32_crc(): m_adler(adler32(0, 0, 0)) {}
|
||||
|
||||
void update(const char* data, int len)
|
||||
{ m_adler = adler32(m_adler, data, len); }
|
||||
unsigned long final() const { return m_adler; }
|
||||
void reset() { m_adler = adler32(0, 0, 0); }
|
||||
|
||||
private:
|
||||
|
||||
unsigned long m_adler;
|
||||
|
||||
};
|
||||
|
||||
class hasher
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -220,7 +220,6 @@ namespace libtorrent
|
|||
void announce_piece(int index)
|
||||
{
|
||||
m_announce_queue.push_back(index);
|
||||
send_buffer_updated();
|
||||
}
|
||||
|
||||
// called from the main loop when this connection has any
|
||||
|
|
|
@ -92,7 +92,7 @@ namespace libtorrent
|
|||
// info about each block
|
||||
block_info info[max_blocks_per_piece];
|
||||
|
||||
// TODO: store a hash and a peer_connection reference
|
||||
// TODO: store a crc and a peer_connection reference
|
||||
// for each block. Then if the hash test fails on the
|
||||
// piece, redownload one block from another peer
|
||||
// then the first time, and check the hash again.
|
||||
|
|
|
@ -72,13 +72,15 @@ namespace libtorrent
|
|||
// workaround for microsofts
|
||||
// hardware exceptions that makes
|
||||
// it hard to debug stuff
|
||||
#if !defined(NDEBUG) && defined(_MSC_VER)
|
||||
#if defined(_MSC_VER)
|
||||
struct eh_initializer
|
||||
{
|
||||
eh_initializer()
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
_clearfp();
|
||||
_controlfp(_EM_INEXACT | _EM_UNDERFLOW, _MCW_EM );
|
||||
#endif
|
||||
::_set_se_translator(straight_to_debugger);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#define TORRENT_STORAGE_HPP_INCLUDE
|
||||
|
||||
#include <vector>
|
||||
#include <bitset>
|
||||
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
@ -103,6 +104,12 @@ namespace libtorrent
|
|||
void allocate_slots(int num_slots);
|
||||
void mark_failed(int index);
|
||||
|
||||
unsigned long piece_crc(
|
||||
int slot_index
|
||||
, int block_size
|
||||
, const std::bitset<256>& bitmask);
|
||||
int slot_for_piece(int piece_index) const;
|
||||
|
||||
size_type read(char* buf, int piece_index, size_type offset, size_type size);
|
||||
void write(const char* buf, int piece_index, size_type offset, size_type size);
|
||||
|
||||
|
|
|
@ -201,6 +201,12 @@ namespace libtorrent
|
|||
// non standard encodings
|
||||
// ----------------------
|
||||
|
||||
if (std::equal(PID, PID + 4, "exbc"))
|
||||
{
|
||||
std::stringstream s;
|
||||
s << "BitComet " << (int)PID[4] << "." << (int)PID[5]/10 << (int)PID[5]%10;
|
||||
return s.str();
|
||||
}
|
||||
|
||||
if (std::equal(PID + 5, PID + 5 + 8, "Azureus"))
|
||||
{
|
||||
|
@ -214,7 +220,7 @@ namespace libtorrent
|
|||
|
||||
if (std::equal(PID, PID + 7, "btfans"))
|
||||
{
|
||||
return "BitComet";
|
||||
return "SimpleBT";
|
||||
}
|
||||
|
||||
if (std::equal(PID, PID + 8, "turbobt"))
|
||||
|
|
|
@ -1455,8 +1455,7 @@ namespace libtorrent
|
|||
// 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()
|
||||
|| !m_announce_queue.empty())
|
||||
|| !m_send_buffer.empty())
|
||||
&& m_send_quota_left != 0;
|
||||
}
|
||||
|
||||
|
@ -1634,7 +1633,11 @@ namespace libtorrent
|
|||
{
|
||||
boost::posix_time::time_duration d;
|
||||
d = boost::posix_time::second_clock::local_time() - m_last_sent;
|
||||
if (d.seconds() > m_timeout / 2)
|
||||
if (d.seconds() < m_timeout / 2) return;
|
||||
|
||||
// we must either send a keep-alive
|
||||
// message or something else.
|
||||
if (m_announce_queue.empty())
|
||||
{
|
||||
char noop[] = {0,0,0,0};
|
||||
m_send_buffer.insert(m_send_buffer.end(), noop, noop+4);
|
||||
|
@ -1642,11 +1645,23 @@ namespace libtorrent
|
|||
#ifndef NDEBUG
|
||||
(*m_logger) << " ==> NOP\n";
|
||||
#endif
|
||||
send_buffer_updated();
|
||||
}
|
||||
else
|
||||
{
|
||||
for (std::vector<int>::iterator i = m_announce_queue.begin();
|
||||
i != m_announce_queue.end();
|
||||
++i)
|
||||
{
|
||||
send_have(*i);
|
||||
}
|
||||
m_announce_queue.clear();
|
||||
}
|
||||
send_buffer_updated();
|
||||
}
|
||||
|
||||
// TODO: this could be implemented more efficient
|
||||
// by maintaining a counter of the number of pieces
|
||||
// the peer has
|
||||
bool peer_connection::is_seed() const
|
||||
{
|
||||
return std::count(m_have_piece.begin(), m_have_piece.end(), true)
|
||||
|
|
|
@ -280,13 +280,6 @@ namespace
|
|||
|
||||
namespace libtorrent
|
||||
{
|
||||
/*
|
||||
TODO: implement some kind of limit of the number of sockets
|
||||
opened, to use for systems where a user has a limited number
|
||||
of open file descriptors. and for windows which has a buggy tcp-stack.
|
||||
This means also to implement a 'connecion purger', that identifies
|
||||
more or less useless connections and closes them.
|
||||
*/
|
||||
|
||||
policy::policy(torrent* t)
|
||||
: m_num_peers(0)
|
||||
|
@ -624,6 +617,8 @@ namespace libtorrent
|
|||
{
|
||||
assert(!c.is_local());
|
||||
|
||||
// TODO: make an exception if the incoming connection
|
||||
// is from the tracker
|
||||
if(m_torrent->num_peers() >= m_max_connections)
|
||||
throw protocol_error("too many connections, refusing incoming connection"); // cause a disconnect
|
||||
|
||||
|
@ -893,6 +888,7 @@ namespace libtorrent
|
|||
{
|
||||
assert(max_connections > 1 || max_connections == -1);
|
||||
if (max_connections == -1) max_connections = std::numeric_limits<int>::max();
|
||||
assert(max_connections >= 2);
|
||||
m_max_connections = max_connections;
|
||||
}
|
||||
|
||||
|
|
|
@ -378,6 +378,7 @@ namespace libtorrent
|
|||
{
|
||||
m_connections.erase(m_disconnect_peer.back());
|
||||
m_disconnect_peer.pop_back();
|
||||
assert(m_selector.count_read_monitors() == m_connections.size() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -500,12 +501,19 @@ namespace libtorrent
|
|||
assert(p->second->get_socket()->is_writable());
|
||||
p->second->send_data();
|
||||
}
|
||||
catch(std::exception&)
|
||||
catch(std::exception& e)
|
||||
{
|
||||
// the connection wants to disconnect for some reason, remove it
|
||||
// from the connection-list
|
||||
// the connection wants to disconnect for some reason,
|
||||
// remove it from the connection-list
|
||||
if (m_alerts.should_post(alert::debug))
|
||||
{
|
||||
m_alerts.post_alert(
|
||||
peer_error_alert(p->second->get_peer_id(), e.what()));
|
||||
}
|
||||
|
||||
m_selector.remove(*i);
|
||||
m_connections.erase(p);
|
||||
assert(m_selector.count_read_monitors() == m_connections.size() + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -558,10 +566,6 @@ namespace libtorrent
|
|||
{
|
||||
// (*m_logger) << "readable: " << p->first->sender().as_string() << "\n";
|
||||
p->second->receive_data();
|
||||
|
||||
#ifndef NDEBUG
|
||||
assert_invariant();
|
||||
#endif
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
|
@ -574,6 +578,7 @@ namespace libtorrent
|
|||
// from the connection-list
|
||||
m_selector.remove(*i);
|
||||
m_connections.erase(p);
|
||||
assert(m_selector.count_read_monitors() == m_connections.size() + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -593,10 +598,21 @@ namespace libtorrent
|
|||
++i)
|
||||
{
|
||||
connection_map::iterator p = m_connections.find(*i);
|
||||
if (m_alerts.should_post(alert::debug))
|
||||
{
|
||||
m_alerts.post_alert(
|
||||
peer_error_alert(
|
||||
p->second->get_peer_id()
|
||||
, "socket received an exception"));
|
||||
}
|
||||
|
||||
m_selector.remove(*i);
|
||||
// the connection may have been disconnected in the receive or send phase
|
||||
if (p != m_connections.end()) m_connections.erase(p);
|
||||
if (p != m_connections.end())
|
||||
{
|
||||
m_connections.erase(p);
|
||||
assert(m_selector.count_read_monitors() == m_connections.size() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
@ -631,6 +647,7 @@ namespace libtorrent
|
|||
{
|
||||
m_selector.remove(j->first);
|
||||
m_connections.erase(j);
|
||||
assert(m_selector.count_read_monitors() == m_connections.size() + 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1018,6 +1035,34 @@ namespace libtorrent
|
|||
p.finished_blocks[bit] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (p.finished_blocks.count() == 0) continue;
|
||||
|
||||
std::vector<int>::iterator slot_iter
|
||||
= std::find(tmp_pieces.begin(), tmp_pieces.end(), p.index);
|
||||
if (slot_iter == tmp_pieces.end())
|
||||
{
|
||||
// this piece is marked as unfinished
|
||||
// but doesn't have any storage
|
||||
return;
|
||||
}
|
||||
|
||||
assert(*slot_iter == p.index);
|
||||
int slot_index = slot_iter - tmp_pieces.begin();
|
||||
unsigned long adler
|
||||
= torrent_ptr->filesystem().piece_crc(
|
||||
slot_index
|
||||
, torrent_ptr->block_size()
|
||||
, p.finished_blocks);
|
||||
|
||||
entry::dictionary_type::iterator ad = i->dict().find("adler32");
|
||||
if (ad != i->dict().end())
|
||||
{
|
||||
// crc's didn't match, don't use the resume data
|
||||
if (ad->second.integer() != adler)
|
||||
return;
|
||||
}
|
||||
|
||||
tmp_unfinished.push_back(p);
|
||||
}
|
||||
|
||||
|
|
101
src/storage.cpp
101
src/storage.cpp
|
@ -427,6 +427,13 @@ namespace libtorrent
|
|||
void allocate_slots(int num_slots);
|
||||
void mark_failed(int index);
|
||||
|
||||
unsigned long piece_crc(
|
||||
int slot_index
|
||||
, int block_size
|
||||
, const std::bitset<256>& bitmask);
|
||||
|
||||
int slot_for_piece(int piece_index) const;
|
||||
|
||||
size_type read(char* buf, int piece_index, size_type offset, size_type size);
|
||||
void write(const char* buf, int piece_index, size_type offset, size_type size);
|
||||
|
||||
|
@ -438,17 +445,15 @@ namespace libtorrent
|
|||
private:
|
||||
// returns the slot currently associated with the given
|
||||
// piece or assigns the given piece_index to a free slot
|
||||
int slot_for_piece(int piece_index);
|
||||
int allocate_slot_for_piece(int piece_index);
|
||||
#ifndef NDEBUG
|
||||
void check_invariant() const;
|
||||
#ifdef TORRENT_STORAGE_DEBUG
|
||||
void debug_log() const;
|
||||
#endif
|
||||
#endif
|
||||
storage m_storage;
|
||||
|
||||
// total number of bytes left to be downloaded
|
||||
// TODO: this member shouldn't be necessaty any more
|
||||
size_type m_bytes_left;
|
||||
|
||||
// a bitmask representing the pieces we have
|
||||
std::vector<bool> m_have_piece;
|
||||
|
||||
|
@ -571,6 +576,57 @@ namespace libtorrent
|
|||
m_pimpl->mark_failed(index);
|
||||
}
|
||||
|
||||
int piece_manager::slot_for_piece(int piece_index) const
|
||||
{
|
||||
return m_pimpl->slot_for_piece(piece_index);
|
||||
}
|
||||
|
||||
int piece_manager::impl::slot_for_piece(int piece_index) const
|
||||
{
|
||||
assert(piece_index >= 0 && piece_index < m_info.num_pieces());
|
||||
return m_piece_to_slot[piece_index];
|
||||
}
|
||||
|
||||
unsigned long piece_manager::piece_crc(
|
||||
int index
|
||||
, int block_size
|
||||
, const std::bitset<256>& bitmask)
|
||||
{
|
||||
return m_pimpl->piece_crc(index, block_size, bitmask);
|
||||
}
|
||||
|
||||
unsigned long piece_manager::impl::piece_crc(
|
||||
int slot_index
|
||||
, int block_size
|
||||
, const std::bitset<256>& bitmask)
|
||||
{
|
||||
adler32_crc crc;
|
||||
std::vector<char> buf(block_size);
|
||||
int num_blocks = m_info.piece_size(slot_index) / block_size;
|
||||
int last_block_size = m_info.piece_size(slot_index) % block_size;
|
||||
if (last_block_size == 0) last_block_size = block_size;
|
||||
|
||||
for (int i = 0; i < num_blocks-1; ++i)
|
||||
{
|
||||
if (!bitmask[i]) continue;
|
||||
m_storage.read(
|
||||
&buf[0]
|
||||
, slot_index
|
||||
, i * block_size
|
||||
, block_size);
|
||||
crc.update(&buf[0], block_size);
|
||||
}
|
||||
if (bitmask[num_blocks - 1])
|
||||
{
|
||||
m_storage.read(
|
||||
&buf[0]
|
||||
, slot_index
|
||||
, block_size * (num_blocks - 1)
|
||||
, last_block_size);
|
||||
crc.update(&buf[0], last_block_size);
|
||||
}
|
||||
return crc.final();
|
||||
}
|
||||
|
||||
size_type piece_manager::impl::read(
|
||||
char* buf
|
||||
|
@ -598,7 +654,7 @@ namespace libtorrent
|
|||
, size_type offset
|
||||
, size_type size)
|
||||
{
|
||||
int slot = slot_for_piece(piece_index);
|
||||
int slot = allocate_slot_for_piece(piece_index);
|
||||
m_storage.write(buf, slot, offset, size);
|
||||
}
|
||||
|
||||
|
@ -626,8 +682,6 @@ namespace libtorrent
|
|||
m_piece_to_slot.resize(m_info.num_pieces(), has_no_slot);
|
||||
m_slot_to_piece.resize(m_info.num_pieces(), unallocated);
|
||||
|
||||
m_bytes_left = m_info.total_size();
|
||||
|
||||
const std::size_t piece_size = m_info.piece_length();
|
||||
const std::size_t last_piece_size = m_info.piece_size(
|
||||
m_info.num_pieces() - 1);
|
||||
|
@ -655,7 +709,6 @@ namespace libtorrent
|
|||
, piece_picker::has_index(found_piece))
|
||||
== data.unfinished_pieces.end())
|
||||
{
|
||||
m_bytes_left -= m_info.piece_size(found_piece);
|
||||
pieces[found_piece] = true;
|
||||
}
|
||||
}
|
||||
|
@ -832,10 +885,6 @@ namespace libtorrent
|
|||
m_slot_to_piece[m_piece_to_slot[found_piece]] = unassigned;
|
||||
m_free_slots.push_back(m_piece_to_slot[found_piece]);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bytes_left -= m_info.piece_size(found_piece);
|
||||
}
|
||||
|
||||
m_piece_to_slot[found_piece] = current_slot;
|
||||
m_slot_to_piece[current_slot] = found_piece;
|
||||
|
@ -892,7 +941,7 @@ namespace libtorrent
|
|||
m_pimpl->check_pieces(mutex, data, pieces);
|
||||
}
|
||||
|
||||
int piece_manager::impl::slot_for_piece(int piece_index)
|
||||
int piece_manager::impl::allocate_slot_for_piece(int piece_index)
|
||||
{
|
||||
// synchronization ------------------------------------------------------
|
||||
boost::recursive_mutex::scoped_lock lock(m_mutex);
|
||||
|
@ -979,7 +1028,9 @@ namespace libtorrent
|
|||
assert(m_piece_to_slot[piece_at_our_slot] == piece_index);
|
||||
#ifndef NDEBUG
|
||||
print_to_log(s.str());
|
||||
#ifdef TORRENT_STORAGE_DEBUG
|
||||
debug_log();
|
||||
#endif
|
||||
#endif
|
||||
std::swap(
|
||||
m_slot_to_piece[piece_index]
|
||||
|
@ -997,7 +1048,7 @@ namespace libtorrent
|
|||
assert(m_piece_to_slot[piece_index] == piece_index);
|
||||
|
||||
slot_index = piece_index;
|
||||
#ifndef NDEBUG
|
||||
#if !defined(NDEBUG) && defined(TORRENT_STORAGE_DEBUG)
|
||||
debug_log();
|
||||
#endif
|
||||
}
|
||||
|
@ -1098,7 +1149,8 @@ namespace libtorrent
|
|||
{
|
||||
assert(m_slot_to_piece[i]<m_piece_to_slot.size());
|
||||
assert(m_piece_to_slot[m_slot_to_piece[i]]==i);
|
||||
/* assert(
|
||||
#ifdef TORRENT_STORAGE_DEBUG
|
||||
assert(
|
||||
std::find(
|
||||
m_unallocated_slots.begin()
|
||||
, m_unallocated_slots.end()
|
||||
|
@ -1110,25 +1162,30 @@ namespace libtorrent
|
|||
, m_free_slots.end()
|
||||
, i) == m_free_slots.end()
|
||||
);
|
||||
*/ }
|
||||
#endif
|
||||
}
|
||||
else if (m_slot_to_piece[i] == unallocated)
|
||||
{
|
||||
/* assert(
|
||||
#ifdef TORRENT_STORAGE_DEBUG
|
||||
assert(
|
||||
std::find(
|
||||
m_unallocated_slots.begin()
|
||||
, m_unallocated_slots.end()
|
||||
, i) != m_unallocated_slots.end()
|
||||
);
|
||||
*/ }
|
||||
#endif
|
||||
}
|
||||
else if (m_slot_to_piece[i] == unassigned)
|
||||
{
|
||||
/* assert(
|
||||
#ifdef TORRENT_STORAGE_DEBUG
|
||||
assert(
|
||||
std::find(
|
||||
m_free_slots.begin()
|
||||
, m_free_slots.end()
|
||||
, i) != m_free_slots.end()
|
||||
);
|
||||
*/ }
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(false && "m_slot_to_piece[i] is invalid");
|
||||
|
@ -1136,6 +1193,7 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef TORRENT_STORAGE_DEBUG
|
||||
void piece_manager::impl::debug_log() const
|
||||
{
|
||||
std::stringstream s;
|
||||
|
@ -1153,5 +1211,6 @@ namespace libtorrent
|
|||
print_to_log(s.str());
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
} // namespace libtorrent
|
||||
|
||||
|
|
|
@ -94,7 +94,6 @@ namespace libtorrent
|
|||
|
||||
void torrent_handle::set_max_connections(int max_connections)
|
||||
{
|
||||
assert(max_connections >= 2);
|
||||
if (m_ses == 0) throw invalid_handle();
|
||||
|
||||
{
|
||||
|
@ -240,13 +239,17 @@ namespace libtorrent
|
|||
i != q.end();
|
||||
++i)
|
||||
{
|
||||
if (i->finished_blocks.count() == 0) continue;
|
||||
|
||||
entry::dictionary_type piece_struct;
|
||||
|
||||
// the unfinished piece's index
|
||||
piece_struct["piece"] = i->index;
|
||||
|
||||
std::string bitmask;
|
||||
const int num_bitmask_bytes = std::max(num_blocks_per_piece / 8, 1);
|
||||
const int num_bitmask_bytes
|
||||
= std::max(num_blocks_per_piece / 8, 1);
|
||||
|
||||
for (int j = 0; j < num_bitmask_bytes; ++j)
|
||||
{
|
||||
unsigned char v = 0;
|
||||
|
@ -256,7 +259,14 @@ namespace libtorrent
|
|||
}
|
||||
piece_struct["bitmask"] = bitmask;
|
||||
|
||||
// TODO: add a hash to piece_struct
|
||||
assert(t->filesystem().slot_for_piece(i->index) >= 0);
|
||||
unsigned long adler
|
||||
= t->filesystem().piece_crc(
|
||||
t->filesystem().slot_for_piece(i->index)
|
||||
, t->block_size()
|
||||
, i->finished_blocks);
|
||||
|
||||
piece_struct["adler32"] = adler;
|
||||
|
||||
// push the struct onto the unfinished-piece list
|
||||
up.push_back(piece_struct);
|
||||
|
|
|
@ -131,6 +131,20 @@ namespace libtorrent
|
|||
m_urls.push_back(e);
|
||||
}
|
||||
|
||||
// extract creation date
|
||||
i = dict.find("creation date");
|
||||
if (i != dict.end() && i->second.type() == entry::int_t)
|
||||
{
|
||||
m_creation_date = m_creation_date + boost::posix_time::seconds(i->second.integer());
|
||||
}
|
||||
|
||||
// extract comment
|
||||
i = dict.find("comment");
|
||||
if (i != dict.end() && i->second.type() == entry::string_t)
|
||||
{
|
||||
m_comment = i->second.string();
|
||||
}
|
||||
|
||||
i = dict.find("info");
|
||||
if (i == dict.end()) throw invalid_torrent_file();
|
||||
entry info = i->second;
|
||||
|
@ -170,20 +184,6 @@ namespace libtorrent
|
|||
extract_files(i->second.list(), m_files, m_name);
|
||||
}
|
||||
|
||||
// extract creation date
|
||||
i = info.dict().find("creation date");
|
||||
if (i != info.dict().end() && i->second.type() == entry::int_t)
|
||||
{
|
||||
m_creation_date = m_creation_date + boost::posix_time::seconds(i->second.integer());
|
||||
}
|
||||
|
||||
// extract comment
|
||||
i = info.dict().find("comment");
|
||||
if (i != info.dict().end() && i->second.type() == entry::string_t)
|
||||
{
|
||||
m_comment = i->second.string();
|
||||
}
|
||||
|
||||
// calculate total size of all pieces
|
||||
m_total_size = 0;
|
||||
for (std::vector<file_entry>::iterator i = m_files.begin(); i != m_files.end(); ++i)
|
||||
|
|
Loading…
Reference in New Issue