2003-10-23 01:00:57 +02:00
|
|
|
/*
|
|
|
|
|
|
|
|
Copyright (c) 2003, Arvid Norberg
|
|
|
|
All rights reserved.
|
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
|
|
modification, are permitted provided that the following conditions
|
|
|
|
are met:
|
|
|
|
|
|
|
|
* Redistributions of source code must retain the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
* Redistributions in binary form must reproduce the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer in
|
|
|
|
the documentation and/or other materials provided with the distribution.
|
|
|
|
* Neither the name of the author nor the names of its
|
|
|
|
contributors may be used to endorse or promote products derived
|
|
|
|
from this software without specific prior written permission.
|
|
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
|
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
|
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
|
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
|
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
|
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
|
POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef TORRENT_TORRENT_INFO_HPP_INCLUDE
|
|
|
|
#define TORRENT_TORRENT_INFO_HPP_INCLUDE
|
|
|
|
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
2007-08-10 18:57:53 +02:00
|
|
|
#include <iosfwd>
|
2004-01-25 19:18:36 +01:00
|
|
|
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
#pragma warning(push, 1)
|
|
|
|
#endif
|
|
|
|
|
2004-03-05 13:04:47 +01:00
|
|
|
#include <boost/optional.hpp>
|
|
|
|
#include <boost/filesystem/path.hpp>
|
2006-10-13 01:51:10 +02:00
|
|
|
#include <boost/shared_ptr.hpp>
|
2008-05-14 07:29:42 +02:00
|
|
|
#include <boost/shared_array.hpp>
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2004-01-25 19:18:36 +01:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
#pragma warning(pop)
|
|
|
|
#endif
|
|
|
|
|
2003-10-23 01:00:57 +02:00
|
|
|
#include "libtorrent/entry.hpp"
|
2008-05-14 07:29:42 +02:00
|
|
|
#include "libtorrent/lazy_entry.hpp"
|
2003-10-23 01:00:57 +02:00
|
|
|
#include "libtorrent/socket.hpp"
|
|
|
|
#include "libtorrent/peer_id.hpp"
|
2004-01-19 20:36:55 +01:00
|
|
|
#include "libtorrent/size_type.hpp"
|
2006-04-25 23:04:48 +02:00
|
|
|
#include "libtorrent/peer_request.hpp"
|
2005-11-01 19:30:39 +01:00
|
|
|
#include "libtorrent/config.hpp"
|
2007-04-05 00:27:36 +02:00
|
|
|
#include "libtorrent/time.hpp"
|
2007-09-01 05:00:31 +02:00
|
|
|
#include "libtorrent/intrusive_ptr_base.hpp"
|
2007-09-10 08:12:41 +02:00
|
|
|
#include "libtorrent/assert.hpp"
|
2003-11-20 20:58:29 +01:00
|
|
|
|
2003-10-23 01:00:57 +02:00
|
|
|
namespace libtorrent
|
|
|
|
{
|
2007-04-05 00:27:36 +02:00
|
|
|
namespace pt = boost::posix_time;
|
|
|
|
namespace gr = boost::gregorian;
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2007-06-10 22:46:09 +02:00
|
|
|
namespace fs = boost::filesystem;
|
|
|
|
|
2005-11-01 19:30:39 +01:00
|
|
|
struct TORRENT_EXPORT file_entry
|
2003-10-23 01:00:57 +02:00
|
|
|
{
|
2007-11-25 11:47:05 +01:00
|
|
|
file_entry(): offset(0), size(0), file_base(0) {}
|
|
|
|
|
2007-06-10 22:46:09 +02:00
|
|
|
fs::path path;
|
2006-06-18 00:04:25 +02:00
|
|
|
size_type offset; // the offset of this file inside the torrent
|
|
|
|
size_type size; // the size of this file
|
2007-11-25 11:47:05 +01:00
|
|
|
// the offset in the file where the storage starts.
|
|
|
|
// This is always 0 unless parts of the torrent is
|
|
|
|
// compressed into a single file, such as a so-called part file.
|
|
|
|
size_type file_base;
|
2006-10-13 01:51:10 +02:00
|
|
|
// if the path was incorrectly encoded, this is
|
2007-08-25 20:26:43 +02:00
|
|
|
// the original corrupt encoded string. It is
|
2006-10-13 01:51:10 +02:00
|
|
|
// preserved in order to be able to reproduce
|
|
|
|
// the correct info-hash
|
2007-06-10 22:46:09 +02:00
|
|
|
boost::shared_ptr<const fs::path> orig_path;
|
2003-10-23 01:00:57 +02:00
|
|
|
};
|
|
|
|
|
2006-04-25 23:04:48 +02:00
|
|
|
struct TORRENT_EXPORT file_slice
|
|
|
|
{
|
|
|
|
int file_index;
|
|
|
|
size_type offset;
|
|
|
|
size_type size;
|
|
|
|
};
|
|
|
|
|
2005-11-01 19:30:39 +01:00
|
|
|
struct TORRENT_EXPORT announce_entry
|
2003-10-23 01:00:57 +02:00
|
|
|
{
|
2004-09-12 12:12:16 +02:00
|
|
|
announce_entry(std::string const& u): url(u), tier(0) {}
|
2003-10-23 01:00:57 +02:00
|
|
|
std::string url;
|
|
|
|
int tier;
|
|
|
|
};
|
|
|
|
|
2005-11-01 19:30:39 +01:00
|
|
|
struct TORRENT_EXPORT invalid_torrent_file: std::exception
|
2003-10-23 01:00:57 +02:00
|
|
|
{
|
|
|
|
virtual const char* what() const throw() { return "invalid torrent file"; }
|
|
|
|
};
|
|
|
|
|
2007-09-01 05:00:31 +02:00
|
|
|
class TORRENT_EXPORT torrent_info : public intrusive_ptr_base<torrent_info>
|
2003-10-23 01:00:57 +02:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
2004-10-10 02:42:48 +02:00
|
|
|
torrent_info(sha1_hash const& info_hash);
|
2008-05-14 07:29:42 +02:00
|
|
|
torrent_info(lazy_entry const& torrent_file);
|
|
|
|
torrent_info(char const* buffer, int size);
|
2008-05-12 08:35:24 +02:00
|
|
|
torrent_info(char const* filename);
|
2004-10-29 15:21:09 +02:00
|
|
|
~torrent_info();
|
2004-03-03 14:47:12 +01:00
|
|
|
|
2004-03-05 13:04:47 +01:00
|
|
|
void add_tracker(std::string const& url, int tier = 0);
|
2006-04-25 23:04:48 +02:00
|
|
|
|
2007-11-25 11:47:05 +01:00
|
|
|
bool remap_files(std::vector<file_entry> const& map);
|
2007-08-25 20:26:43 +02:00
|
|
|
|
|
|
|
std::vector<file_slice> map_block(int piece, size_type offset
|
|
|
|
, int size, bool storage = false) const;
|
|
|
|
peer_request map_file(int file, size_type offset, int size
|
|
|
|
, bool storage = false) const;
|
2006-04-25 23:04:48 +02:00
|
|
|
|
2007-05-10 00:54:26 +02:00
|
|
|
std::vector<std::string> const& url_seeds() const
|
2008-05-14 07:29:42 +02:00
|
|
|
{ return m_url_seeds; }
|
2008-05-15 09:18:31 +02:00
|
|
|
void add_url_seed(std::string const& url)
|
2008-05-14 07:29:42 +02:00
|
|
|
{ m_url_seeds.push_back(url); }
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2004-01-16 00:57:11 +01:00
|
|
|
typedef std::vector<file_entry>::const_iterator file_iterator;
|
|
|
|
typedef std::vector<file_entry>::const_reverse_iterator reverse_file_iterator;
|
2003-10-23 01:00:57 +02:00
|
|
|
|
|
|
|
// list the files in the torrent file
|
2007-08-25 20:26:43 +02:00
|
|
|
file_iterator begin_files(bool storage = false) const
|
|
|
|
{
|
|
|
|
if (!storage || m_remapped_files.empty())
|
|
|
|
return m_files.begin();
|
|
|
|
else
|
|
|
|
return m_remapped_files.begin();
|
|
|
|
}
|
|
|
|
|
|
|
|
file_iterator end_files(bool storage = false) const
|
|
|
|
{
|
|
|
|
if (!storage || m_remapped_files.empty())
|
|
|
|
return m_files.end();
|
|
|
|
else
|
|
|
|
return m_remapped_files.end();
|
|
|
|
}
|
|
|
|
|
|
|
|
reverse_file_iterator rbegin_files(bool storage = false) const
|
|
|
|
{
|
|
|
|
if (!storage || m_remapped_files.empty())
|
|
|
|
return m_files.rbegin();
|
|
|
|
else
|
|
|
|
return m_remapped_files.rbegin();
|
|
|
|
}
|
|
|
|
|
|
|
|
reverse_file_iterator rend_files(bool storage = false) const
|
|
|
|
{
|
|
|
|
if (!storage || m_remapped_files.empty())
|
|
|
|
return m_files.rend();
|
|
|
|
else
|
|
|
|
return m_remapped_files.rend();
|
|
|
|
}
|
|
|
|
|
|
|
|
int num_files(bool storage = false) const
|
|
|
|
{
|
2007-10-05 02:30:00 +02:00
|
|
|
TORRENT_ASSERT(m_piece_length > 0);
|
2007-08-25 20:26:43 +02:00
|
|
|
if (!storage || m_remapped_files.empty())
|
2008-05-14 07:29:42 +02:00
|
|
|
return int(m_files.size());
|
2007-08-25 20:26:43 +02:00
|
|
|
else
|
2008-05-14 07:29:42 +02:00
|
|
|
return int(m_remapped_files.size());
|
2007-08-25 20:26:43 +02:00
|
|
|
}
|
|
|
|
|
2008-05-14 07:29:42 +02:00
|
|
|
file_entry const& file_at(int index, bool storage = false) const
|
2007-08-25 20:26:43 +02:00
|
|
|
{
|
|
|
|
if (!storage || m_remapped_files.empty())
|
|
|
|
{
|
2007-10-05 02:30:00 +02:00
|
|
|
TORRENT_ASSERT(index >= 0 && index < (int)m_files.size());
|
2007-08-25 20:26:43 +02:00
|
|
|
return m_files[index];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-10-05 02:30:00 +02:00
|
|
|
TORRENT_ASSERT(index >= 0 && index < (int)m_remapped_files.size());
|
2007-08-25 20:26:43 +02:00
|
|
|
return m_remapped_files[index];
|
|
|
|
}
|
|
|
|
}
|
2005-07-02 10:48:37 +02:00
|
|
|
|
2008-05-14 07:29:42 +02:00
|
|
|
std::vector<announce_entry> const& trackers() const { return m_urls; }
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2007-10-05 02:30:00 +02:00
|
|
|
size_type total_size() const { TORRENT_ASSERT(m_piece_length > 0); return m_total_size; }
|
2008-02-25 11:28:53 +01:00
|
|
|
int piece_length() const { TORRENT_ASSERT(m_piece_length > 0); return m_piece_length; }
|
2007-10-05 02:30:00 +02:00
|
|
|
int num_pieces() const { TORRENT_ASSERT(m_piece_length > 0); return m_num_pieces; }
|
2003-10-23 01:00:57 +02:00
|
|
|
const sha1_hash& info_hash() const { return m_info_hash; }
|
2007-10-05 02:30:00 +02:00
|
|
|
const std::string& name() const { TORRENT_ASSERT(m_piece_length > 0); return m_name; }
|
2007-04-10 11:11:32 +02:00
|
|
|
|
|
|
|
// ------- start deprecation -------
|
2008-05-14 07:29:42 +02:00
|
|
|
// these functions will be removed in a future version
|
|
|
|
torrent_info(entry const& torrent_file) TORRENT_DEPRECATED;
|
2007-08-10 18:57:53 +02:00
|
|
|
void print(std::ostream& os) const TORRENT_DEPRECATED;
|
2007-04-10 11:11:32 +02:00
|
|
|
// ------- end deprecation -------
|
|
|
|
|
2004-06-14 01:30:42 +02:00
|
|
|
bool is_valid() const { return m_piece_length > 0; }
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2006-08-01 17:27:08 +02:00
|
|
|
bool priv() const { return m_private; }
|
2004-03-07 21:50:56 +01:00
|
|
|
|
2008-02-25 11:28:53 +01:00
|
|
|
int piece_size(int index) const;
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2008-05-14 07:29:42 +02:00
|
|
|
sha1_hash hash_for_piece(int index) const
|
|
|
|
{
|
|
|
|
return sha1_hash(hash_for_piece_ptr(index));
|
|
|
|
}
|
|
|
|
|
|
|
|
char const* hash_for_piece_ptr(int index) const
|
2003-10-23 01:00:57 +02:00
|
|
|
{
|
2007-10-05 02:30:00 +02:00
|
|
|
TORRENT_ASSERT(index >= 0);
|
2008-05-14 07:29:42 +02:00
|
|
|
TORRENT_ASSERT(index < m_num_pieces);
|
|
|
|
TORRENT_ASSERT(m_piece_hashes);
|
|
|
|
TORRENT_ASSERT(m_piece_hashes >= m_info_section.get());
|
|
|
|
TORRENT_ASSERT(m_piece_hashes < m_info_section.get() + m_info_section_size);
|
|
|
|
return &m_piece_hashes[index*20];
|
2003-10-23 01:00:57 +02:00
|
|
|
}
|
|
|
|
|
2007-04-05 00:27:36 +02:00
|
|
|
boost::optional<pt::ptime> creation_date() const;
|
2003-11-20 20:58:29 +01:00
|
|
|
|
2005-08-18 00:59:21 +02:00
|
|
|
const std::string& creator() const
|
|
|
|
{ return m_created_by; }
|
|
|
|
|
2003-11-20 20:58:29 +01:00
|
|
|
const std::string& comment() const
|
|
|
|
{ return m_comment; }
|
|
|
|
|
2006-08-01 17:27:08 +02:00
|
|
|
// dht nodes to add to the routing table/bootstrap from
|
|
|
|
typedef std::vector<std::pair<std::string, int> > nodes_t;
|
|
|
|
|
|
|
|
nodes_t const& nodes() const
|
2008-05-15 09:37:34 +02:00
|
|
|
{ return m_nodes; }
|
|
|
|
void add_node(std::pair<std::string, int> const& node)
|
|
|
|
{ m_nodes.push_back(node); }
|
2006-08-01 17:27:08 +02:00
|
|
|
|
2008-05-14 07:29:42 +02:00
|
|
|
bool parse_info_section(lazy_entry const& e, std::string& error);
|
2006-08-01 17:27:08 +02:00
|
|
|
|
2008-05-14 07:29:42 +02:00
|
|
|
lazy_entry const* info(char const* key) const
|
|
|
|
{
|
|
|
|
if (m_info_dict.type() == lazy_entry::none_t)
|
|
|
|
lazy_bdecode(m_info_section.get(), m_info_section.get()
|
|
|
|
+ m_info_section_size, m_info_dict);
|
|
|
|
return m_info_dict.dict_find(key);
|
|
|
|
}
|
2004-06-14 01:30:42 +02:00
|
|
|
|
2008-05-14 07:29:42 +02:00
|
|
|
void swap(torrent_info& ti);
|
2007-03-23 00:37:24 +01:00
|
|
|
|
2008-05-14 07:29:42 +02:00
|
|
|
boost::shared_array<char> metadata() const
|
|
|
|
{ return m_info_section; }
|
2007-05-10 00:54:26 +02:00
|
|
|
|
2008-05-14 07:29:42 +02:00
|
|
|
int metadata_size() const { return m_info_section_size; }
|
2007-06-10 22:46:09 +02:00
|
|
|
|
2003-10-23 01:00:57 +02:00
|
|
|
private:
|
|
|
|
|
2008-05-14 07:29:42 +02:00
|
|
|
bool parse_torrent_file(lazy_entry const& libtorrent, std::string& error);
|
2003-10-23 01:00:57 +02:00
|
|
|
|
|
|
|
// the urls to the trackers
|
|
|
|
std::vector<announce_entry> m_urls;
|
|
|
|
|
2006-04-25 23:04:48 +02:00
|
|
|
std::vector<std::string> m_url_seeds;
|
|
|
|
|
2003-10-23 01:00:57 +02:00
|
|
|
// the length of one piece
|
2004-06-14 01:30:42 +02:00
|
|
|
// if this is 0, the torrent_info is
|
|
|
|
// in an uninitialized state
|
2008-02-25 11:28:53 +01:00
|
|
|
int m_piece_length;
|
2003-10-23 01:00:57 +02:00
|
|
|
|
|
|
|
// the list of files that this torrent consists of
|
2004-01-16 00:57:11 +01:00
|
|
|
std::vector<file_entry> m_files;
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2007-08-25 20:26:43 +02:00
|
|
|
// this vector is typically empty. If it is not
|
|
|
|
// empty, it means the user has re-mapped the
|
2007-11-25 11:47:05 +01:00
|
|
|
// files in this torrent to different names
|
2007-08-25 20:26:43 +02:00
|
|
|
// on disk. This is only used when reading and
|
|
|
|
// writing the disk.
|
|
|
|
std::vector<file_entry> m_remapped_files;
|
|
|
|
|
2006-08-01 17:27:08 +02:00
|
|
|
nodes_t m_nodes;
|
|
|
|
|
2003-10-23 01:00:57 +02:00
|
|
|
// the sum of all filesizes
|
2004-01-16 04:58:24 +01:00
|
|
|
size_type m_total_size;
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2007-05-10 00:54:26 +02:00
|
|
|
// the number of pieces in the torrent
|
|
|
|
int m_num_pieces;
|
|
|
|
|
2003-10-23 01:00:57 +02:00
|
|
|
// the hash that identifies this torrent
|
2006-04-25 23:04:48 +02:00
|
|
|
// is mutable because it's calculated
|
2005-10-16 18:58:41 +02:00
|
|
|
// lazily
|
2008-05-14 07:29:42 +02:00
|
|
|
sha1_hash m_info_hash;
|
2003-10-28 02:20:50 +01:00
|
|
|
|
|
|
|
std::string m_name;
|
2003-11-20 20:58:29 +01:00
|
|
|
|
|
|
|
// if a creation date is found in the torrent file
|
|
|
|
// this will be set to that, otherwise it'll be
|
|
|
|
// 1970, Jan 1
|
2007-04-05 00:27:36 +02:00
|
|
|
pt::ptime m_creation_date;
|
2003-11-20 20:58:29 +01:00
|
|
|
|
|
|
|
// if a comment is found in the torrent file
|
|
|
|
// this will be set to that comment
|
|
|
|
std::string m_comment;
|
2004-03-23 23:58:18 +01:00
|
|
|
|
|
|
|
// an optional string naming the software used
|
|
|
|
// to create the torrent file
|
|
|
|
std::string m_created_by;
|
2005-05-12 01:03:12 +02:00
|
|
|
|
|
|
|
// this is used when creating a torrent. If there's
|
|
|
|
// only one file there are cases where it's impossible
|
|
|
|
// to know if it should be written as a multifile torrent
|
|
|
|
// or not. e.g. test/test there's one file and one directory
|
|
|
|
// and they have the same name.
|
|
|
|
bool m_multifile;
|
2006-08-01 17:27:08 +02:00
|
|
|
|
|
|
|
// this is true if the torrent is private. i.e., is should not
|
|
|
|
// be announced on the dht
|
|
|
|
bool m_private;
|
2005-10-16 18:58:41 +02:00
|
|
|
|
2008-05-14 07:29:42 +02:00
|
|
|
// this is a copy of the info section from the torrent.
|
|
|
|
// it use maintained in this flat format in order to
|
|
|
|
// make it available through the metadata extension
|
|
|
|
boost::shared_array<char> m_info_section;
|
|
|
|
int m_info_section_size;
|
2007-05-10 00:54:26 +02:00
|
|
|
|
2008-05-14 07:29:42 +02:00
|
|
|
// this is a pointer into the m_info_section buffer
|
|
|
|
// pointing to the first byte of the first sha-1 hash
|
|
|
|
char const* m_piece_hashes;
|
|
|
|
|
|
|
|
// the info section parsed. points into m_info_section
|
|
|
|
// parsed lazily
|
|
|
|
mutable lazy_entry m_info_dict;
|
2003-10-23 01:00:57 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // TORRENT_TORRENT_INFO_HPP_INCLUDED
|
2003-10-24 13:11:28 +02:00
|
|
|
|