added more error codes. consolidated exception classes into one. moved over more places to use error_code instead of strings. fixed proper error handling for torrent_info

This commit is contained in:
Arvid Norberg 2009-02-23 01:21:19 +00:00
parent 9edf2db4c3
commit b25a8db2a6
20 changed files with 518 additions and 270 deletions

View File

@ -220,44 +220,46 @@
<li><a class="reference internal" href="#invalid-torrent-file" id="id173">invalid_torrent_file</a></li>
</ul>
</li>
<li><a class="reference internal" href="#storage-interface" id="id174">storage_interface</a><ul>
<li><a class="reference internal" href="#initialize" id="id175">initialize()</a></li>
<li><a class="reference internal" href="#readv-writev" id="id176">readv() writev()</a></li>
<li><a class="reference internal" href="#id12" id="id177">move_storage()</a></li>
<li><a class="reference internal" href="#verify-resume-data" id="id178">verify_resume_data()</a></li>
<li><a class="reference internal" href="#write-resume-data" id="id179">write_resume_data()</a></li>
<li><a class="reference internal" href="#move-slot" id="id180">move_slot()</a></li>
<li><a class="reference internal" href="#swap-slots" id="id181">swap_slots()</a></li>
<li><a class="reference internal" href="#swap-slots3" id="id182">swap_slots3()</a></li>
<li><a class="reference internal" href="#hash-for-slot" id="id183">hash_for_slot()</a></li>
<li><a class="reference internal" href="#id13" id="id184">rename_file()</a></li>
<li><a class="reference internal" href="#release-files" id="id185">release_files()</a></li>
<li><a class="reference internal" href="#delete-files" id="id186">delete_files()</a></li>
<li><a class="reference internal" href="#error-code" id="id174">error_code</a></li>
<li><a class="reference internal" href="#storage-interface" id="id175">storage_interface</a><ul>
<li><a class="reference internal" href="#initialize" id="id176">initialize()</a></li>
<li><a class="reference internal" href="#readv-writev" id="id177">readv() writev()</a></li>
<li><a class="reference internal" href="#sparse-end" id="id178">sparse_end()</a></li>
<li><a class="reference internal" href="#id12" id="id179">move_storage()</a></li>
<li><a class="reference internal" href="#verify-resume-data" id="id180">verify_resume_data()</a></li>
<li><a class="reference internal" href="#write-resume-data" id="id181">write_resume_data()</a></li>
<li><a class="reference internal" href="#move-slot" id="id182">move_slot()</a></li>
<li><a class="reference internal" href="#swap-slots" id="id183">swap_slots()</a></li>
<li><a class="reference internal" href="#swap-slots3" id="id184">swap_slots3()</a></li>
<li><a class="reference internal" href="#hash-for-slot" id="id185">hash_for_slot()</a></li>
<li><a class="reference internal" href="#id13" id="id186">rename_file()</a></li>
<li><a class="reference internal" href="#release-files" id="id187">release_files()</a></li>
<li><a class="reference internal" href="#delete-files" id="id188">delete_files()</a></li>
</ul>
</li>
<li><a class="reference internal" href="#magnet-links" id="id187">magnet links</a></li>
<li><a class="reference internal" href="#queuing" id="id188">queuing</a><ul>
<li><a class="reference internal" href="#downloading" id="id189">downloading</a></li>
<li><a class="reference internal" href="#seeding" id="id190">seeding</a></li>
<li><a class="reference internal" href="#magnet-links" id="id189">magnet links</a></li>
<li><a class="reference internal" href="#queuing" id="id190">queuing</a><ul>
<li><a class="reference internal" href="#downloading" id="id191">downloading</a></li>
<li><a class="reference internal" href="#seeding" id="id192">seeding</a></li>
</ul>
</li>
<li><a class="reference internal" href="#fast-resume" id="id191">fast resume</a><ul>
<li><a class="reference internal" href="#file-format" id="id192">file format</a></li>
<li><a class="reference internal" href="#fast-resume" id="id193">fast resume</a><ul>
<li><a class="reference internal" href="#file-format" id="id194">file format</a></li>
</ul>
</li>
<li><a class="reference internal" href="#threads" id="id193">threads</a></li>
<li><a class="reference internal" href="#storage-allocation" id="id194">storage allocation</a><ul>
<li><a class="reference internal" href="#sparse-allocation" id="id195">sparse allocation</a></li>
<li><a class="reference internal" href="#full-allocation" id="id196">full allocation</a></li>
<li><a class="reference internal" href="#compact-allocation" id="id197">compact allocation</a></li>
<li><a class="reference internal" href="#threads" id="id195">threads</a></li>
<li><a class="reference internal" href="#storage-allocation" id="id196">storage allocation</a><ul>
<li><a class="reference internal" href="#sparse-allocation" id="id197">sparse allocation</a></li>
<li><a class="reference internal" href="#full-allocation" id="id198">full allocation</a></li>
<li><a class="reference internal" href="#compact-allocation" id="id199">compact allocation</a></li>
</ul>
</li>
<li><a class="reference internal" href="#extensions" id="id198">extensions</a><ul>
<li><a class="reference internal" href="#metadata-from-peers" id="id199">metadata from peers</a></li>
<li><a class="reference internal" href="#http-seeding" id="id200">HTTP seeding</a></li>
<li><a class="reference internal" href="#extensions" id="id200">extensions</a><ul>
<li><a class="reference internal" href="#metadata-from-peers" id="id201">metadata from peers</a></li>
<li><a class="reference internal" href="#http-seeding" id="id202">HTTP seeding</a></li>
</ul>
</li>
<li><a class="reference internal" href="#filename-checks" id="id201">filename checks</a></li>
<li><a class="reference internal" href="#filename-checks" id="id203">filename checks</a></li>
</ul>
</div>
<div class="section" id="overview">
@ -1394,12 +1396,20 @@ class torrent_info
{
public:
// these constructors throws exceptions on error
torrent_info(sha1_hash const&amp; info_hash);
torrent_info(lazy_entry const&amp; torrent_file);
torrent_info(char const* buffer, int size);
torrent_info(boost::filesystem::path const&amp; filename);
torrent_info(boost::filesystem::wpath const&amp; filename);
// these constructors sets the error code on error
torrent_info(sha1_hash const&amp; info_hash, error_code&amp; ec);
torrent_info(lazy_entry const&amp; torrent_file, error_code&amp; ec);
torrent_info(char const* buffer, int size, error_code&amp; ec);
torrent_info(fs::path const&amp; filename, error_code&amp; ec);
torrent_info(fs::wpath const&amp; filename, error_code&amp; ec);
void add_tracker(std::string const&amp; url, int tier = 0);
std::vector&lt;announce_entry&gt; const&amp; trackers() const;
@ -1463,6 +1473,12 @@ torrent_info(lazy_entry const&amp; torrent_file);
torrent_info(char const* buffer, int size);
torrent_info(boost::filesystem::path const&amp; filename);
torrent_info(boost::filesystem::wpath const&amp; filename);
torrent_info(sha1_hash const&amp; info_hash, error_code&amp; ec);
torrent_info(lazy_entry const&amp; torrent_file, error_code&amp; ec);
torrent_info(char const* buffer, int size, error_code&amp; ec);
torrent_info(fs::path const&amp; filename, error_code&amp; ec);
torrent_info(fs::wpath const&amp; filename, error_code&amp; ec);
</pre>
</blockquote>
<p>The constructor that takes an info-hash will initialize the info-hash to the given value,
@ -1478,6 +1494,11 @@ initialize the torrent_info object for you.</p>
<p>The version that takes a filename will simply load the torrent file and decode it inside
the constructor, for convenience. This might not be the most suitable for applications that
want to be able to report detailed errors on what might go wrong.</p>
<p>The overloads that takes an <tt class="docutils literal"><span class="pre">error_code</span> <span class="pre">const&amp;</span></tt> never throws if an error occur, they
will simply set the error code to describe what went wrong and not fully initialize the
torrent_info object. The overloads that do not take the extra <a class="reference internal" href="#error-code">error_code</a> parameter will
always throw if an error occurs. These overloads are not available when building without
exception support.</p>
</div>
<div class="section" id="add-tracker">
<h2>add_tracker()</h2>
@ -4774,10 +4795,100 @@ doesn't meet the requirements on what information has to be present in a torrent
struct invalid_torrent_file: std::exception
{
const char* what() const throw();
boost::system::error_code error() const;
};
</pre>
</div>
</div>
<div class="section" id="error-code">
<h1>error_code</h1>
<p>libtorrent uses boost.system's <tt class="docutils literal"><span class="pre">error_code</span></tt> class to represent errors. libtorrent has
its own error category (<tt class="docutils literal"><span class="pre">libtorrent::libtorrent_category</span></tt>) whith the following error
codes:</p>
<table border="1" class="docutils">
<colgroup>
<col width="6%" />
<col width="28%" />
<col width="66%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">code</th>
<th class="head">symbol</th>
<th class="head">description</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>0</td>
<td>no_error</td>
<td>Not an error</td>
</tr>
<tr><td>1</td>
<td>file_collision</td>
<td>Two torrents has files which end up overwriting each other</td>
</tr>
<tr><td>2</td>
<td>failed_hash_check</td>
<td>A piece did not match its piece hash</td>
</tr>
<tr><td>3</td>
<td>torrent_is_no_dict</td>
<td>The .torrent file does not contain a bencoded dictionary at
its top level</td>
</tr>
<tr><td>4</td>
<td>torrent_missing_info</td>
<td>The .torrent file does not have an <tt class="docutils literal"><span class="pre">info</span></tt> dictionary</td>
</tr>
<tr><td>5</td>
<td>torrent_info_no_dict</td>
<td>The .torrent file's <tt class="docutils literal"><span class="pre">info</span></tt> entry is not a dictionary</td>
</tr>
<tr><td>6</td>
<td>torrent_missing_piece_length</td>
<td>The .torrent file does not have a <tt class="docutils literal"><span class="pre">piece</span> <span class="pre">length</span></tt> entry</td>
</tr>
<tr><td>7</td>
<td>torrent_missing_name</td>
<td>The .torrent file does not have a <tt class="docutils literal"><span class="pre">name</span></tt> entry</td>
</tr>
<tr><td>8</td>
<td>torrent_invalid_name</td>
<td>The .torrent file's name entry is invalid</td>
</tr>
<tr><td>9</td>
<td>torrent_invalid_length</td>
<td>The length of a file, or of the whole .torrent file is invalid.
Either negative or not an integer</td>
</tr>
<tr><td>10</td>
<td>torrent_file_parse_failed</td>
<td>Failed to parse a file entry in the .torrent</td>
</tr>
<tr><td>11</td>
<td>torrent_missing_pieces</td>
<td>The <tt class="docutils literal"><span class="pre">pieces</span></tt> field is missing or invalid in the .torrent file</td>
</tr>
<tr><td>12</td>
<td>torrent_invalid_hashes</td>
<td>The <tt class="docutils literal"><span class="pre">pieces</span></tt> string has incorrect length</td>
</tr>
<tr><td>13</td>
<td>too_many_pieces_in_torrent</td>
<td>The .torrent file has more pieces than is supported by libtorrent</td>
</tr>
<tr><td>14</td>
<td>invalid_swarm_metadata</td>
<td>The metadata (.torrent file) that was received from the swarm
matched the info-hash, but failed to be parsed</td>
</tr>
<tr><td>15</td>
<td>invalid_bencoding</td>
<td>The file or buffer is not correctly bencoded</td>
</tr>
</tbody>
</table>
<p>The names of these error codes are declared in then <tt class="docutils literal"><span class="pre">libtorrent::errors</span></tt> namespace.</p>
</div>
<div class="section" id="storage-interface">
<h1>storage_interface</h1>
<p>The storage interface is a pure virtual class that can be implemented to
@ -4789,6 +4900,7 @@ struct storage_interface
virtual bool initialize(bool allocate_files) = 0;
virtual int readv(file::iovec_t const* bufs, int slot, int offset, int num_bufs) = 0;
virtual int writev(file::iovec_t const* bufs, int slot, int offset, int num_bufs) = 0;
virtual int sparse_end(int start) const;
virtual bool move_storage(fs::path save_path) = 0;
virtual bool verify_resume_data(lazy_entry const&amp; rd, std::string&amp; error) = 0;
virtual bool write_resume_data(entry&amp; rd) const = 0;
@ -4851,6 +4963,18 @@ exceptions when it's not. Specifically if the read cache is disabled/or full and
client requests unaligned data, or the file itself is not aligned in the torrent.
Most clients request aligned data.</p>
</div>
<div class="section" id="sparse-end">
<h2>sparse_end()</h2>
<blockquote>
<pre class="literal-block">
int sparse_end(int start) const;
</pre>
</blockquote>
<p>This function is optional. It is supposed to return the first piece, starting at
<tt class="docutils literal"><span class="pre">start</span></tt> that is fully contained within a data-region on disk (i.e. non-sparse
region). The purpose of this is to skip parts of files that can be known to contain
zeros when checking files.</p>
</div>
<div class="section" id="id12">
<h2>move_storage()</h2>
<blockquote>

View File

@ -1255,12 +1255,20 @@ The ``torrent_info`` has the following synopsis::
{
public:
// these constructors throws exceptions on error
torrent_info(sha1_hash const& info_hash);
torrent_info(lazy_entry const& torrent_file);
torrent_info(char const* buffer, int size);
torrent_info(boost::filesystem::path const& filename);
torrent_info(boost::filesystem::wpath const& filename);
// these constructors sets the error code on error
torrent_info(sha1_hash const& info_hash, error_code& ec);
torrent_info(lazy_entry const& torrent_file, error_code& ec);
torrent_info(char const* buffer, int size, error_code& ec);
torrent_info(fs::path const& filename, error_code& ec);
torrent_info(fs::wpath const& filename, error_code& ec);
void add_tracker(std::string const& url, int tier = 0);
std::vector<announce_entry> const& trackers() const;
@ -1326,6 +1334,12 @@ torrent_info()
torrent_info(boost::filesystem::path const& filename);
torrent_info(boost::filesystem::wpath const& filename);
torrent_info(sha1_hash const& info_hash, error_code& ec);
torrent_info(lazy_entry const& torrent_file, error_code& ec);
torrent_info(char const* buffer, int size, error_code& ec);
torrent_info(fs::path const& filename, error_code& ec);
torrent_info(fs::wpath const& filename, error_code& ec);
The constructor that takes an info-hash will initialize the info-hash to the given value,
but leave all other fields empty. This is used internally when downloading torrents without
the metadata. The metadata will be created by libtorrent as soon as it has been downloaded
@ -1343,6 +1357,12 @@ The version that takes a filename will simply load the torrent file and decode i
the constructor, for convenience. This might not be the most suitable for applications that
want to be able to report detailed errors on what might go wrong.
The overloads that takes an ``error_code const&`` never throws if an error occur, they
will simply set the error code to describe what went wrong and not fully initialize the
torrent_info object. The overloads that do not take the extra error_code_ parameter will
always throw if an error occurs. These overloads are not available when building without
exception support.
add_tracker()
-------------
@ -4914,80 +4934,84 @@ including ``<libtorrent/alert.hpp>``.
exceptions
==========
There are a number of exceptions that can be thrown from different places in libtorrent,
here's a complete list with description.
Many functions in libtorrent have two versions, one that throws exceptions on
errors and one that takes an ``error_code`` reference which is filled with the
error code on errors.
There is one exception class that is used for errors in libtorrent, it is based
on boost.system's ``error_code`` class to carry the error code.
invalid_handle
--------------
This exception is thrown when querying information from a torrent_handle_ that hasn't
been initialized or that has become invalid.
::
struct invalid_handle: std::exception
{
const char* what() const throw();
};
duplicate_torrent
-----------------
This is thrown by `add_torrent()`_ if the torrent already has been added to
the session. Since `remove_torrent()`_ is asynchronous, this exception may
be thrown if the torrent is removed and then immediately added again.
::
struct duplicate_torrent: std::exception
{
const char* what() const throw();
};
invalid_encoding
----------------
This is thrown by ``bdecode()`` if the input data is not a valid bencoding.
::
struct invalid_encoding: std::exception
{
const char* what() const throw();
};
type_error
----------
This is thrown from the accessors of ``entry`` if the data type of the ``entry`` doesn't
match the type you want to extract from it.
::
struct type_error: std::runtime_error
{
type_error(const char* error);
};
invalid_torrent_file
libtorrent_exception
--------------------
This exception is thrown from the constructor of ``torrent_info`` if the given bencoded information
doesn't meet the requirements on what information has to be present in a torrent file.
::
struct invalid_torrent_file: std::exception
struct libtorrent_exception: std::exception
{
const char* what() const throw();
libtorrent_exception(error_code const& s);
virtual const char* what() const throw();
virtual ~libtorrent_exception() throw() {}
boost::system::error_code error() const;
};
error_code
==========
libtorrent uses boost.system's ``error_code`` class to represent errors. libtorrent has
its own error category (``libtorrent::libtorrent_category``) whith the following error
codes:
====== ============================ =================================================================
code symbol description
====== ============================ =================================================================
0 no_error Not an error
------ ---------------------------- -----------------------------------------------------------------
1 file_collision Two torrents has files which end up overwriting each other
------ ---------------------------- -----------------------------------------------------------------
2 failed_hash_check A piece did not match its piece hash
------ ---------------------------- -----------------------------------------------------------------
3 torrent_is_no_dict The .torrent file does not contain a bencoded dictionary at
its top level
------ ---------------------------- -----------------------------------------------------------------
4 torrent_missing_info The .torrent file does not have an ``info`` dictionary
------ ---------------------------- -----------------------------------------------------------------
5 torrent_info_no_dict The .torrent file's ``info`` entry is not a dictionary
------ ---------------------------- -----------------------------------------------------------------
6 torrent_missing_piece_length The .torrent file does not have a ``piece length`` entry
------ ---------------------------- -----------------------------------------------------------------
7 torrent_missing_name The .torrent file does not have a ``name`` entry
------ ---------------------------- -----------------------------------------------------------------
8 torrent_invalid_name The .torrent file's name entry is invalid
------ ---------------------------- -----------------------------------------------------------------
9 torrent_invalid_length The length of a file, or of the whole .torrent file is invalid.
Either negative or not an integer
------ ---------------------------- -----------------------------------------------------------------
10 torrent_file_parse_failed Failed to parse a file entry in the .torrent
------ ---------------------------- -----------------------------------------------------------------
11 torrent_missing_pieces The ``pieces`` field is missing or invalid in the .torrent file
------ ---------------------------- -----------------------------------------------------------------
12 torrent_invalid_hashes The ``pieces`` string has incorrect length
------ ---------------------------- -----------------------------------------------------------------
13 too_many_pieces_in_torrent The .torrent file has more pieces than is supported by libtorrent
------ ---------------------------- -----------------------------------------------------------------
14 invalid_swarm_metadata The metadata (.torrent file) that was received from the swarm
matched the info-hash, but failed to be parsed
------ ---------------------------- -----------------------------------------------------------------
15 invalid_bencoding The file or buffer is not correctly bencoded
------ ---------------------------- -----------------------------------------------------------------
16 no_files_in_torrent The .torrent file does not contain any files
------ ---------------------------- -----------------------------------------------------------------
17 invalid_escaped_string The string was not properly url-encoded as expected
------ ---------------------------- -----------------------------------------------------------------
18 session_is_closing Operation is not permitted since the session is shutting down
------ ---------------------------- -----------------------------------------------------------------
19 duplicate_torrent There's already a torrent with that info-hash added to the
session
====== ============================ =================================================================
The names of these error codes are declared in then ``libtorrent::errors`` namespace.
storage_interface
=================

View File

@ -206,7 +206,7 @@ namespace libtorrent
, const char* net_interface = 0);
bool is_listening() const;
torrent_handle add_torrent(add_torrent_params const&);
torrent_handle add_torrent(add_torrent_params const&, error_code& ec);
void remove_torrent(torrent_handle const& h, int options);

View File

@ -68,6 +68,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/size_type.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/error_code.hpp"
namespace libtorrent
{
@ -224,6 +225,14 @@ namespace libtorrent
return os;
}
#ifndef BOOST_NO_EXCEPTIONS
inline void throw_type_error()
{
throw libtorrent_exception(error_code(errors::invalid_entry_type
, libtorrent_category));
}
#endif
inline entry::data_type entry::type() const
{
#ifdef TORRENT_DEBUG
@ -244,7 +253,7 @@ namespace libtorrent
{
if (m_type == undefined_t) construct(int_t);
#ifndef BOOST_NO_EXCEPTIONS
if (m_type != int_t) throw type_error("invalid type requested from entry");
if (m_type != int_t) throw_type_error();
#elif defined TORRENT_DEBUG
TORRENT_ASSERT(m_type_queried);
#endif
@ -255,7 +264,7 @@ namespace libtorrent
inline entry::integer_type const& entry::integer() const
{
#ifndef BOOST_NO_EXCEPTIONS
if (m_type != int_t) throw type_error("invalid type requested from entry");
if (m_type != int_t) throw_type_error();
#elif defined TORRENT_DEBUG
TORRENT_ASSERT(m_type_queried);
#endif
@ -267,7 +276,7 @@ namespace libtorrent
{
if (m_type == undefined_t) construct(string_t);
#ifndef BOOST_NO_EXCEPTIONS
if (m_type != string_t) throw type_error("invalid type requested from entry");
if (m_type != string_t) throw_type_error();
#elif defined TORRENT_DEBUG
TORRENT_ASSERT(m_type_queried);
#endif
@ -278,7 +287,7 @@ namespace libtorrent
inline entry::string_type const& entry::string() const
{
#ifndef BOOST_NO_EXCEPTIONS
if (m_type != string_t) throw type_error("invalid type requested from entry");
if (m_type != string_t) throw_type_error();
#elif defined TORRENT_DEBUG
TORRENT_ASSERT(m_type_queried);
#endif
@ -290,7 +299,7 @@ namespace libtorrent
{
if (m_type == undefined_t) construct(list_t);
#ifndef BOOST_NO_EXCEPTIONS
if (m_type != list_t) throw type_error("invalid type requested from entry");
if (m_type != list_t) throw_type_error();
#elif defined TORRENT_DEBUG
TORRENT_ASSERT(m_type_queried);
#endif
@ -301,7 +310,7 @@ namespace libtorrent
inline entry::list_type const& entry::list() const
{
#ifndef BOOST_NO_EXCEPTIONS
if (m_type != list_t) throw type_error("invalid type requested from entry");
if (m_type != list_t) throw_type_error();
#elif defined TORRENT_DEBUG
TORRENT_ASSERT(m_type_queried);
#endif
@ -313,7 +322,7 @@ namespace libtorrent
{
if (m_type == undefined_t) construct(dictionary_t);
#ifndef BOOST_NO_EXCEPTIONS
if (m_type != dictionary_t) throw type_error("invalid type requested from entry");
if (m_type != dictionary_t) throw_type_error();
#elif defined TORRENT_DEBUG
TORRENT_ASSERT(m_type_queried);
#endif
@ -324,7 +333,7 @@ namespace libtorrent
inline entry::dictionary_type const& entry::dict() const
{
#ifndef BOOST_NO_EXCEPTIONS
if (m_type != dictionary_t) throw type_error("invalid type requested from entry");
if (m_type != dictionary_t) throw_type_error();
#elif defined TORRENT_DEBUG
TORRENT_ASSERT(m_type_queried);
#endif

View File

@ -34,6 +34,7 @@ POSSIBILITY OF SUCH DAMAGE.
#define TORRENT_ERROR_CODE_HPP_INCLUDED
#include <boost/version.hpp>
#include <boost/shared_ptr.hpp>
#if BOOST_VERSION < 103500
#include <asio/error_code.hpp>
@ -41,6 +42,8 @@ POSSIBILITY OF SUCH DAMAGE.
#include <boost/system/error_code.hpp>
#endif
#include "libtorrent/config.hpp"
namespace libtorrent
{
@ -61,6 +64,15 @@ namespace libtorrent
torrent_file_parse_failed,
torrent_missing_pieces,
torrent_invalid_hashes,
too_many_pieces_in_torrent,
invalid_swarm_metadata,
invalid_bencoding,
no_files_in_torrent,
invalid_escaped_string,
session_is_closing,
duplicate_torrent,
invalid_torrent_handle,
invalid_entry_type,
};
}
@ -70,7 +82,7 @@ namespace libtorrent
inline asio::error::error_category get_system_category() { return asio::error::system_category; }
#else
struct libtorrent_error_category : boost::system::error_category
struct TORRENT_EXPORT libtorrent_error_category : boost::system::error_category
{
virtual const char* name() const;
virtual std::string message(int ev) const;
@ -90,6 +102,23 @@ namespace libtorrent
{ return boost::system::get_generic_category(); }
#endif
#endif
#ifndef BOOST_NO_EXCEPTIONS
struct TORRENT_EXPORT libtorrent_exception: std::exception
{
libtorrent_exception(error_code const& s): m_error(s) {}
virtual const char* what() const throw()
{
if (!m_msg) m_msg.reset(new std::string(m_error.message()));
return m_msg->c_str();
}
virtual ~libtorrent_exception() throw() {}
error_code error() const { return m_error; }
private:
error_code m_error;
mutable boost::shared_ptr<std::string> m_msg;
};
#endif
}
#endif

View File

@ -39,6 +39,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <boost/array.hpp>
#include "libtorrent/config.hpp"
#include "libtorrent/size_type.hpp"
#include "libtorrent/error_code.hpp"
namespace libtorrent
{
@ -46,7 +47,7 @@ namespace libtorrent
bool TORRENT_EXPORT is_digit(char c);
bool TORRENT_EXPORT isprint(char c);
std::string TORRENT_EXPORT unescape_string(std::string const& s);
std::string TORRENT_EXPORT unescape_string(std::string const& s, error_code& ec);
std::string TORRENT_EXPORT escape_string(const char* str, int len);
std::string TORRENT_EXPORT escape_path(const char* str, int len);

View File

@ -224,6 +224,7 @@ namespace libtorrent
// all torrent_handles must be destructed before the session is destructed!
torrent_handle add_torrent(add_torrent_params const& params);
torrent_handle add_torrent(add_torrent_params const& params, error_code& ec);
#ifndef TORRENT_NO_DEPRECATE
// deprecated in 0.14

View File

@ -219,8 +219,8 @@ namespace libtorrent
void ip_filter_updated() { m_policy.ip_filter_updated(); }
void clear_error();
void set_error(std::string const& msg);
bool has_error() const { return !m_error.empty(); }
void set_error(error_code const& ec, std::string const& file);
bool has_error() const { return m_error; }
void pause();
void resume();
@ -884,9 +884,10 @@ namespace libtorrent
// the state of this torrent (queued, checking, downloading)
torrent_status::state_t m_state;
// if there's an error on this torrent, this is the
// error message
std::string m_error;
// set if there's an error on this torrent
error_code m_error;
// if the error ocurred on a file, this is the file
std::string m_error_file;
// used if there is any resume data
std::vector<char> m_resume_data;

View File

@ -66,17 +66,12 @@ namespace libtorrent
struct torrent_plugin;
struct TORRENT_EXPORT duplicate_torrent: std::exception
{
virtual const char* what() const throw()
{ return "torrent already exists in session"; }
};
struct TORRENT_EXPORT invalid_handle: std::exception
{
virtual const char* what() const throw()
{ return "invalid torrent handle used"; }
};
#ifndef BOOST_NO_EXCEPTIONS
// for compatibility with 0.14
typedef libtorrent_exception duplicate_torrent;
typedef libtorrent_exception invalid_handle;
void throw_invalid_handle();
#endif
struct TORRENT_EXPORT torrent_status
{

View File

@ -155,13 +155,8 @@ namespace libtorrent
};
#ifndef BOOST_NO_EXCEPTIONS
struct TORRENT_EXPORT invalid_torrent_file: std::exception
{
invalid_torrent_file(std::string const& s): m_error(s) {}
virtual const char* what() const throw() { return m_error.c_str(); }
virtual ~invalid_torrent_file() throw() {}
std::string m_error;
};
// for backwards compatibility with 0.14
typedef libtorrent_exception invalid_torrent_file;
#endif
int TORRENT_EXPORT load_file(fs::path const& filename, std::vector<char>& v);
@ -169,12 +164,20 @@ namespace libtorrent
class TORRENT_EXPORT torrent_info : public intrusive_ptr_base<torrent_info>
{
public:
#ifndef BOOST_NO_EXCEPTIONS
torrent_info(sha1_hash const& info_hash);
torrent_info(lazy_entry const& torrent_file);
torrent_info(char const* buffer, int size);
torrent_info(fs::path const& filename);
torrent_info(fs::wpath const& filename);
#endif
torrent_info(sha1_hash const& info_hash, error_code& ec);
torrent_info(lazy_entry const& torrent_file, error_code& ec);
torrent_info(char const* buffer, int size, error_code& ec);
torrent_info(fs::path const& filename, error_code& ec);
torrent_info(fs::wpath const& filename, error_code& ec);
~torrent_info();
file_storage const& files() const { return m_files; }

View File

@ -170,15 +170,11 @@ namespace libtorrent
{
TORRENT_ASSERT(m_files.piece_length() > 0);
if (m_files.num_files() == 0)
{
// TODO: throw something here
// throw
return entry();
}
entry dict;
if (m_files.num_files() == 0)
return dict;
if (!m_urls.empty()) dict["announce"] = m_urls.front().first;
if (!m_nodes.empty())

View File

@ -60,6 +60,15 @@ namespace libtorrent
"failed to parse files from torrent file",
"invalid or missing 'pieces' entry in torrent file",
"incorrect number of piece hashes in torrent file",
"too many pieces in torrent",
"invalid metadata received from swarm",
"invalid bencoding",
"no files in torrent",
"invalid escaped string",
"session is closing",
"torrent already exists in session",
"invalid torrent handle used",
"invalid type requested from entry",
};
if (ev < 0 || ev >= sizeof(msgs)/sizeof(msgs[0]))
return "Unknown error";

View File

@ -79,7 +79,7 @@ namespace libtorrent
return c >= 32 && c < 127;
}
std::string unescape_string(std::string const& s)
std::string unescape_string(std::string const& s, error_code& ec)
{
std::string ret;
for (std::string::const_iterator i = s.begin(); i != s.end(); ++i)
@ -96,41 +96,37 @@ namespace libtorrent
{
++i;
if (i == s.end())
#ifdef BOOST_NO_EXCEPTIONS
{
ec = error_code(errors::invalid_escaped_string, libtorrent_category);
return ret;
#else
throw std::runtime_error("invalid escaped string");
#endif
}
int high;
if(*i >= '0' && *i <= '9') high = *i - '0';
else if(*i >= 'A' && *i <= 'F') high = *i + 10 - 'A';
else if(*i >= 'a' && *i <= 'f') high = *i + 10 - 'a';
else
#ifdef BOOST_NO_EXCEPTIONS
{
ec = error_code(errors::invalid_escaped_string, libtorrent_category);
return ret;
#else
throw std::runtime_error("invalid escaped string");
#endif
}
++i;
if (i == s.end())
#ifdef BOOST_NO_EXCEPTIONS
{
ec = error_code(errors::invalid_escaped_string, libtorrent_category);
return ret;
#else
throw std::runtime_error("invalid escaped string");
#endif
}
int low;
if(*i >= '0' && *i <= '9') low = *i - '0';
else if(*i >= 'A' && *i <= 'F') low = *i + 10 - 'A';
else if(*i >= 'a' && *i <= 'f') low = *i + 10 - 'a';
else
#ifdef BOOST_NO_EXCEPTIONS
{
ec = error_code(errors::invalid_escaped_string, libtorrent_category);
return ret;
#else
throw std::runtime_error("invalid escaped string");
#endif
}
ret += char(high * 16 + low);
}

View File

@ -100,10 +100,11 @@ namespace libtorrent
std::string name;
std::string tracker;
error_code ec;
boost::optional<std::string> display_name = url_has_argument(uri, "dn");
if (display_name) name = unescape_string(display_name->c_str());
if (display_name) name = unescape_string(display_name->c_str(), ec);
boost::optional<std::string> tracker_string = url_has_argument(uri, "tr");
if (tracker_string) tracker = unescape_string(tracker_string->c_str());
if (tracker_string) tracker = unescape_string(tracker_string->c_str(), ec);
boost::optional<std::string> btih = url_has_argument(uri, "xt");
if (!btih) return torrent_handle();
@ -124,10 +125,11 @@ namespace libtorrent
std::string name;
std::string tracker;
error_code ec;
boost::optional<std::string> display_name = url_has_argument(uri, "dn");
if (display_name) name = unescape_string(display_name->c_str());
if (display_name) name = unescape_string(display_name->c_str(), ec);
boost::optional<std::string> tracker_string = url_has_argument(uri, "tr");
if (tracker_string) tracker = unescape_string(tracker_string->c_str());
if (tracker_string) tracker = unescape_string(tracker_string->c_str(), ec);
boost::optional<std::string> btih = url_has_argument(uri, "xt");
if (!btih) return torrent_handle();

View File

@ -1965,7 +1965,7 @@ namespace libtorrent
if (t->alerts().should_post<file_error_alert>())
t->alerts().post_alert(file_error_alert(j.error_file, t->get_handle(), j.str));
t->set_error(j.str);
t->set_error(j.error, j.error_file);
t->pause();
return;
}
@ -3313,7 +3313,7 @@ namespace libtorrent
{
if (t->alerts().should_post<file_error_alert>())
t->alerts().post_alert(file_error_alert(j.error_file, t->get_handle(), j.str));
t->set_error(j.str);
t->set_error(j.error, j.error_file);
t->pause();
}
return;
@ -3681,7 +3681,6 @@ namespace libtorrent
// RECEIVE DATA
// --------------------------
// throws exception when the client should be disconnected
void peer_connection::on_receive_data(const error_code& error
, std::size_t bytes_transferred)
{
@ -3976,7 +3975,6 @@ namespace libtorrent
// SEND DATA
// --------------------------
// throws exception when the client should be disconnected
void peer_connection::on_send_data(error_code const& error
, std::size_t bytes_transferred)
{

View File

@ -298,9 +298,19 @@ namespace libtorrent
return m_impl->find_torrent_handle(info_hash);
}
#ifndef BOOST_NO_EXCEPTIONS
torrent_handle session::add_torrent(add_torrent_params const& params)
{
return m_impl->add_torrent(params);
error_code ec;
torrent_handle ret = m_impl->add_torrent(params, ec);
if (ec) throw libtorrent_exception(ec);
return ret;
}
#endif
torrent_handle session::add_torrent(add_torrent_params const& params, error_code& ec)
{
return m_impl->add_torrent(params, ec);
}
#ifndef TORRENT_NO_DEPRECATE
@ -325,7 +335,7 @@ namespace libtorrent
}
p.storage_mode = storage_mode;
p.paused = paused;
return m_impl->add_torrent(p);
return add_torrent(p);
}
torrent_handle session::add_torrent(
@ -349,7 +359,7 @@ namespace libtorrent
p.storage_mode = storage_mode;
p.paused = paused;
p.userdata = userdata;
return m_impl->add_torrent(p);
return add_torrent(p);
}
torrent_handle session::add_torrent(
@ -369,7 +379,7 @@ namespace libtorrent
p.save_path = save_path;
p.paused = paused;
p.userdata = userdata;
return m_impl->add_torrent(p);
return add_torrent(p);
}
#endif

View File

@ -1837,17 +1837,15 @@ namespace aux {
return torrent_handle(find_torrent(info_hash));
}
torrent_handle session_impl::add_torrent(add_torrent_params const& params)
torrent_handle session_impl::add_torrent(add_torrent_params const& params
, error_code& ec)
{
TORRENT_ASSERT(!params.save_path.empty());
if (params.ti && params.ti->num_files() == 0)
{
#ifndef BOOST_NO_EXCEPTIONS
throw std::runtime_error("no files in torrent");
#else
ec = error_code(errors::no_files_in_torrent, libtorrent_category);
return torrent_handle();
#endif
}
// lock the session and the checker thread (the order is important!)
@ -1857,11 +1855,8 @@ namespace aux {
if (is_aborted())
{
#ifndef BOOST_NO_EXCEPTIONS
throw std::runtime_error("session is closing");
#else
ec = error_code(errors::session_is_closing, libtorrent_category);
return torrent_handle();
#endif
}
// figure out the info hash of the torrent
@ -1876,11 +1871,8 @@ namespace aux {
if (!params.duplicate_is_error)
return torrent_handle(torrent_ptr);
#ifndef BOOST_NO_EXCEPTIONS
throw duplicate_torrent();
#else
ec = error_code(errors::duplicate_torrent, libtorrent_category);
return torrent_handle();
#endif
}
int queue_pos = 0;
@ -1967,7 +1959,7 @@ namespace aux {
#ifdef BOOST_NO_EXCEPTIONS
return;
#else
throw invalid_handle();
throw_invalid_handle();
#endif
mutex_t::scoped_lock l(m_mutex);

View File

@ -344,7 +344,7 @@ namespace libtorrent
if (ret != r.length)
{
rp->fail = true;
set_error(j.str);
set_error(j.error, j.error_file);
pause();
}
else
@ -425,7 +425,7 @@ namespace libtorrent
if (has_picker()) picker().write_failed(block_finished);
if (alerts().should_post<file_error_alert>())
alerts().post_alert(file_error_alert(j.error_file, get_handle(), j.str));
set_error(j.str);
set_error(j.error, j.error_file);
pause();
return;
}
@ -504,10 +504,9 @@ namespace libtorrent
m_block_size = (std::min)(m_block_size, m_torrent_file->piece_length());
if (m_torrent_file->num_pieces()
> piece_picker::max_pieces)
if (m_torrent_file->num_pieces() > piece_picker::max_pieces)
{
set_error("too many pieces in torrent");
set_error(error_code(errors::too_many_pieces_in_torrent, libtorrent_category), "");
pause();
}
@ -621,7 +620,7 @@ namespace libtorrent
" torrent: " << torrent_file().name() <<
" ]\n";
#endif
set_error(j.str);
set_error(j.error, j.error_file);
pause();
set_state(torrent_status::queued_for_checking);
@ -790,7 +789,7 @@ namespace libtorrent
set_state(torrent_status::queued_for_checking);
return;
}
if (!m_error.empty()) m_error.clear();
clear_error();
disconnect_all();
@ -832,7 +831,7 @@ namespace libtorrent
" torrent: " << torrent_file().name() <<
" ]\n";
#endif
set_error(j.str);
set_error(j.error, j.error_file);
pause();
return;
}
@ -874,7 +873,7 @@ namespace libtorrent
" ]\n";
#endif
pause();
set_error(j.str);
set_error(j.error, j.error_file);
return;
}
@ -3427,7 +3426,7 @@ namespace libtorrent
{
alerts().post_alert(metadata_failed_alert(get_handle()));
}
set_error("invalid metadata: " + ec.message());
set_error(error_code(errors::invalid_swarm_metadata, libtorrent_category), "");
pause();
return false;
}
@ -4297,19 +4296,21 @@ namespace libtorrent
void torrent::clear_error()
{
if (m_error.empty()) return;
if (!m_error) return;
bool checking_files = should_check_files();
if (m_ses.m_auto_manage_time_scaler > 2)
m_ses.m_auto_manage_time_scaler = 2;
m_error.clear();
m_error = error_code();
m_error_file.clear();
if (!checking_files && should_check_files())
queue_torrent_check();
}
void torrent::set_error(std::string const& msg)
void torrent::set_error(error_code const& ec, std::string const& error_file)
{
bool checking_files = should_check_files();
m_error = msg;
m_error = ec;
m_error_file = error_file;
if (checking_files && !should_check_files())
{
// stop checking
@ -4441,7 +4442,7 @@ namespace libtorrent
return (m_state == torrent_status::checking_files
|| m_state == torrent_status::queued_for_checking)
&& (!m_paused || m_auto_managed)
&& m_error.empty()
&& !has_error()
&& !m_abort;
}
@ -4547,7 +4548,7 @@ namespace libtorrent
alerts().post_alert(torrent_resumed_alert(get_handle()));
m_started = time_now();
m_error.clear();
clear_error();
start_announcing();
}
@ -4830,7 +4831,7 @@ namespace libtorrent
{
if (alerts().should_post<file_error_alert>())
alerts().post_alert(file_error_alert(j.error_file, get_handle(), j.str));
set_error(j.str);
set_error(j.error, j.error_file);
pause();
}
f(ret);
@ -5028,7 +5029,7 @@ namespace libtorrent
torrent_status st;
st.has_incoming = m_has_incoming;
st.error = m_error;
if (m_error) st.error = m_error.message() + ": " + m_error_file;
st.seed_mode = m_seed_mode;
if (m_last_scrape == min_time())

View File

@ -123,15 +123,13 @@ namespace libtorrent
{
namespace fs = boost::filesystem;
namespace
{
#ifndef BOOST_NO_EXCEPTIONS
void throw_invalid_handle()
{
throw invalid_handle();
}
#endif
void throw_invalid_handle()
{
throw libtorrent_exception(error_code(
errors::invalid_torrent_handle, libtorrent_category));
}
#endif
#ifdef TORRENT_DEBUG

View File

@ -291,17 +291,25 @@ namespace libtorrent
bencode(out, torrent_file);
lazy_entry e;
lazy_bdecode(&tmp[0], &tmp[0] + tmp.size(), e);
if (lazy_bdecode(&tmp[0], &tmp[0] + tmp.size(), e) != 0)
{
#ifndef BOOST_NO_EXCEPTIONS
throw invalid_torrent_file(error_code(
errors::invalid_bencoding, libtorrent_category));
#endif
return;
}
error_code ec;
#ifndef BOOST_NO_EXCEPTIONS
if (!parse_torrent_file(e, ec))
throw invalid_torrent_file(ec.message());
throw invalid_torrent_file(ec);
#else
parse_torrent_file(e, ec);
#endif
}
#endif
#ifndef BOOST_NO_EXCEPTIONS
torrent_info::torrent_info(lazy_entry const& torrent_file)
: m_creation_date(pt::ptime(pt::not_a_date_time))
, m_multifile(false)
@ -310,12 +318,8 @@ namespace libtorrent
, m_piece_hashes(0)
{
error_code ec;
#ifndef BOOST_NO_EXCEPTIONS
if (!parse_torrent_file(torrent_file, ec))
throw invalid_torrent_file(ec.message());
#else
parse_torrent_file(torrent_file, ec);
#endif
throw invalid_torrent_file(ec);
}
torrent_info::torrent_info(char const* buffer, int size)
@ -327,13 +331,124 @@ namespace libtorrent
{
error_code ec;
lazy_entry e;
lazy_bdecode(buffer, buffer + size, e);
#ifndef BOOST_NO_EXCEPTIONS
if (lazy_bdecode(buffer, buffer + size, e) != 0)
throw invalid_torrent_file(error_code(
errors::invalid_bencoding, libtorrent_category));
if (!parse_torrent_file(e, ec))
throw invalid_torrent_file(ec.message());
#else
parse_torrent_file(e, ec);
throw invalid_torrent_file(ec);
}
torrent_info::torrent_info(fs::path const& filename)
: m_creation_date(pt::ptime(pt::not_a_date_time))
, m_multifile(false)
, m_private(false)
, m_info_section_size(0)
, m_piece_hashes(0)
{
std::vector<char> buf;
int ret = load_file(filename, buf);
if (ret < 0) return;
lazy_entry e;
if (lazy_bdecode(&buf[0], &buf[0] + buf.size(), e) != 0)
throw invalid_torrent_file(error_code(
errors::invalid_bencoding, libtorrent_category));
error_code ec;
if (!parse_torrent_file(e, ec))
throw invalid_torrent_file(ec);
}
torrent_info::torrent_info(fs::wpath const& filename)
: m_creation_date(pt::ptime(pt::not_a_date_time))
, m_multifile(false)
, m_private(false)
, m_info_section_size(0)
, m_piece_hashes(0)
{
std::vector<char> buf;
std::string utf8;
wchar_utf8(filename.string(), utf8);
int ret = load_file(utf8, buf);
if (ret < 0) return;
lazy_entry e;
if (lazy_bdecode(&buf[0], &buf[0] + buf.size(), e) != 0)
throw invalid_torrent_file(error_code(
errors::invalid_bencoding, libtorrent_category));
error_code ec;
if (!parse_torrent_file(e, ec))
throw invalid_torrent_file(ec);
}
#endif
torrent_info::torrent_info(lazy_entry const& torrent_file, error_code& ec)
: m_creation_date(pt::ptime(pt::not_a_date_time))
, m_multifile(false)
, m_private(false)
, m_info_section_size(0)
, m_piece_hashes(0)
{
parse_torrent_file(torrent_file, ec);
}
torrent_info::torrent_info(char const* buffer, int size, error_code& ec)
: m_creation_date(pt::ptime(pt::not_a_date_time))
, m_multifile(false)
, m_private(false)
, m_info_section_size(0)
, m_piece_hashes(0)
{
lazy_entry e;
if (lazy_bdecode(buffer, buffer + size, e) != 0)
{
ec = error_code(errors::invalid_bencoding, libtorrent_category);
return;
}
parse_torrent_file(e, ec);
}
torrent_info::torrent_info(fs::path const& filename, error_code& ec)
: m_creation_date(pt::ptime(pt::not_a_date_time))
, m_multifile(false)
, m_private(false)
, m_info_section_size(0)
, m_piece_hashes(0)
{
std::vector<char> buf;
int ret = load_file(filename, buf);
if (ret < 0) return;
lazy_entry e;
if (lazy_bdecode(&buf[0], &buf[0] + buf.size(), e) != 0)
{
ec = error_code(errors::invalid_bencoding, libtorrent_category);
return;
}
parse_torrent_file(e, ec);
}
torrent_info::torrent_info(fs::wpath const& filename, error_code& ec)
: m_creation_date(pt::ptime(pt::not_a_date_time))
, m_multifile(false)
, m_private(false)
, m_info_section_size(0)
, m_piece_hashes(0)
{
std::vector<char> buf;
std::string utf8;
wchar_utf8(filename.string(), utf8);
int ret = load_file(utf8, buf);
if (ret < 0) return;
lazy_entry e;
if (lazy_bdecode(&buf[0], &buf[0] + buf.size(), e) != 0)
{
ec = error_code(errors::invalid_bencoding, libtorrent_category);
return;
}
parse_torrent_file(e, ec);
}
// constructor used for creating new torrents
@ -349,62 +464,6 @@ namespace libtorrent
, m_piece_hashes(0)
{}
torrent_info::torrent_info(fs::path const& filename)
: m_creation_date(pt::ptime(pt::not_a_date_time))
, m_multifile(false)
, m_private(false)
{
std::vector<char> buf;
int ret = load_file(filename, buf);
if (ret < 0) return;
if (buf.empty())
#ifndef BOOST_NO_EXCEPTIONS
throw invalid_torrent_file("file not found");
#else
return;
#endif
lazy_entry e;
lazy_bdecode(&buf[0], &buf[0] + buf.size(), e);
error_code ec;
#ifndef BOOST_NO_EXCEPTIONS
if (!parse_torrent_file(e, ec))
throw invalid_torrent_file(ec.message());
#else
parse_torrent_file(e, ec);
#endif
}
torrent_info::torrent_info(fs::wpath const& filename)
: m_creation_date(pt::ptime(pt::not_a_date_time))
, m_multifile(false)
, m_private(false)
{
std::vector<char> buf;
std::string utf8;
wchar_utf8(filename.string(), utf8);
int ret = load_file(utf8, buf);
if (ret < 0) return;
if (buf.empty())
#ifndef BOOST_NO_EXCEPTIONS
throw invalid_torrent_file("empty file");
#else
return;
#endif
lazy_entry e;
lazy_bdecode(&buf[0], &buf[0] + buf.size(), e);
error_code ec;
#ifndef BOOST_NO_EXCEPTIONS
if (!parse_torrent_file(e, ec))
throw invalid_torrent_file(ec.message());
#else
parse_torrent_file(e, ec);
#endif
}
torrent_info::~torrent_info()
{}