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_HPP_INCLUDE
|
|
|
|
#define TORRENT_TORRENT_HPP_INCLUDE
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
#include <vector>
|
|
|
|
#include <set>
|
|
|
|
#include <list>
|
|
|
|
#include <iostream>
|
|
|
|
|
2004-01-25 19:18:36 +01:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
#pragma warning(push, 1)
|
|
|
|
#endif
|
|
|
|
|
2003-10-23 01:00:57 +02:00
|
|
|
#include <boost/limits.hpp>
|
|
|
|
#include <boost/filesystem/path.hpp>
|
2005-05-30 19:43:03 +02:00
|
|
|
#include <boost/tuple/tuple.hpp>
|
2005-10-13 09:59:05 +02:00
|
|
|
#include <boost/enable_shared_from_this.hpp>
|
2005-11-01 19:30:39 +01:00
|
|
|
#include <boost/scoped_ptr.hpp>
|
2007-01-10 16:02:25 +01:00
|
|
|
#include <boost/intrusive_ptr.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-26 18:35:23 +01:00
|
|
|
#include "libtorrent/torrent_handle.hpp"
|
2003-10-23 01:00:57 +02:00
|
|
|
#include "libtorrent/entry.hpp"
|
|
|
|
#include "libtorrent/torrent_info.hpp"
|
|
|
|
#include "libtorrent/socket.hpp"
|
|
|
|
#include "libtorrent/policy.hpp"
|
2004-01-31 11:46:15 +01:00
|
|
|
#include "libtorrent/tracker_manager.hpp"
|
2003-12-07 06:53:04 +01:00
|
|
|
#include "libtorrent/stat.hpp"
|
2003-12-22 08:14:35 +01:00
|
|
|
#include "libtorrent/alert.hpp"
|
2004-03-23 23:58:18 +01:00
|
|
|
#include "libtorrent/resource_request.hpp"
|
2005-10-13 09:59:05 +02:00
|
|
|
#include "libtorrent/piece_picker.hpp"
|
2005-11-01 19:30:39 +01:00
|
|
|
#include "libtorrent/config.hpp"
|
2006-04-25 23:04:48 +02:00
|
|
|
#include "libtorrent/escape_string.hpp"
|
2007-01-10 16:02:25 +01:00
|
|
|
#include "libtorrent/bandwidth_manager.hpp"
|
2007-03-16 06:29:23 +01:00
|
|
|
#include "libtorrent/storage.hpp"
|
2003-10-23 01:00:57 +02:00
|
|
|
|
|
|
|
namespace libtorrent
|
|
|
|
{
|
2005-07-06 15:18:10 +02:00
|
|
|
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
2003-10-23 01:00:57 +02:00
|
|
|
struct logger;
|
|
|
|
#endif
|
|
|
|
|
2004-06-14 01:30:42 +02:00
|
|
|
class piece_manager;
|
2006-11-14 01:08:16 +01:00
|
|
|
struct torrent_plugin;
|
2004-06-14 01:30:42 +02:00
|
|
|
|
2006-10-11 16:02:21 +02:00
|
|
|
namespace aux
|
2003-10-23 01:00:57 +02:00
|
|
|
{
|
|
|
|
struct session_impl;
|
2004-06-14 01:30:42 +02:00
|
|
|
struct piece_checker_data;
|
2003-10-23 01:00:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// a torrent is a class that holds information
|
|
|
|
// for a specific download. It updates itself against
|
|
|
|
// the tracker
|
2005-11-01 19:30:39 +01:00
|
|
|
class TORRENT_EXPORT torrent: public request_callback
|
2005-10-13 09:59:05 +02:00
|
|
|
, public boost::enable_shared_from_this<torrent>
|
2003-10-23 01:00:57 +02:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
2003-12-07 06:53:04 +01:00
|
|
|
torrent(
|
2006-10-11 16:02:21 +02:00
|
|
|
aux::session_impl& ses
|
|
|
|
, aux::checker_impl& checker
|
2005-10-16 01:16:39 +02:00
|
|
|
, torrent_info const& tf
|
2004-06-14 01:30:42 +02:00
|
|
|
, boost::filesystem::path const& save_path
|
2006-04-25 23:04:48 +02:00
|
|
|
, tcp::endpoint const& net_interface
|
2005-07-10 12:42:00 +02:00
|
|
|
, bool compact_mode
|
2006-04-25 23:04:48 +02:00
|
|
|
, int block_size
|
2007-03-16 06:29:23 +01:00
|
|
|
, session_settings const& s
|
|
|
|
, storage_constructor_type sc);
|
2004-06-14 01:30:42 +02:00
|
|
|
|
|
|
|
// used with metadata-less torrents
|
|
|
|
// (the metadata is downloaded from the peers)
|
|
|
|
torrent(
|
2006-10-11 16:02:21 +02:00
|
|
|
aux::session_impl& ses
|
|
|
|
, aux::checker_impl& checker
|
2004-06-14 01:30:42 +02:00
|
|
|
, char const* tracker_url
|
|
|
|
, sha1_hash const& info_hash
|
2006-11-14 01:08:16 +01:00
|
|
|
, char const* name
|
2004-06-14 01:30:42 +02:00
|
|
|
, boost::filesystem::path const& save_path
|
2006-04-25 23:04:48 +02:00
|
|
|
, tcp::endpoint const& net_interface
|
2005-07-10 12:42:00 +02:00
|
|
|
, bool compact_mode
|
2006-04-25 23:04:48 +02:00
|
|
|
, int block_size
|
2007-03-16 06:29:23 +01:00
|
|
|
, session_settings const& s
|
|
|
|
, storage_constructor_type sc);
|
2003-12-14 06:56:12 +01:00
|
|
|
|
|
|
|
~torrent();
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2007-04-11 19:44:15 +02:00
|
|
|
// starts the announce timer
|
|
|
|
void start();
|
|
|
|
|
2006-11-14 01:08:16 +01:00
|
|
|
#ifndef TORRENT_DISABLE_EXTENSIONS
|
|
|
|
void add_extension(boost::shared_ptr<torrent_plugin>);
|
|
|
|
#endif
|
|
|
|
|
2004-06-14 01:30:42 +02:00
|
|
|
// this is called when the torrent has metadata.
|
|
|
|
// it will initialize the storage and the piece-picker
|
|
|
|
void init();
|
|
|
|
|
2004-03-28 19:45:37 +02:00
|
|
|
// this will flag the torrent as aborted. The main
|
|
|
|
// loop in session_impl will check for this state
|
|
|
|
// on all torrents once every second, and take
|
|
|
|
// the necessary actions then.
|
2005-03-05 15:17:17 +01:00
|
|
|
void abort();
|
2003-10-23 01:00:57 +02:00
|
|
|
bool is_aborted() const { return m_abort; }
|
|
|
|
|
2005-10-17 15:45:53 +02:00
|
|
|
// returns true if this torrent is being allocated
|
|
|
|
// by the checker thread.
|
|
|
|
bool is_allocating() const;
|
|
|
|
|
2006-05-15 00:30:05 +02:00
|
|
|
session_settings const& settings() const;
|
|
|
|
|
2006-11-30 12:56:19 +01:00
|
|
|
aux::session_impl& session() { return m_ses; }
|
|
|
|
|
2006-09-04 19:17:45 +02:00
|
|
|
void set_sequenced_download_threshold(int threshold);
|
2007-03-28 01:49:05 +02:00
|
|
|
|
|
|
|
bool verify_resume_data(entry& rd, std::string& error)
|
|
|
|
{ assert(m_storage); return m_storage->verify_resume_data(rd, error); }
|
|
|
|
|
2004-03-28 19:45:37 +02:00
|
|
|
// is called every second by session. This will
|
|
|
|
// caclulate the upload/download and number
|
|
|
|
// of connections this torrent needs. And prepare
|
|
|
|
// it for being used by allocate_resources.
|
2006-04-25 23:04:48 +02:00
|
|
|
void second_tick(stat& accumulator, float tick_interval);
|
2003-12-01 06:01:40 +01:00
|
|
|
|
2004-03-28 19:45:37 +02:00
|
|
|
// debug purpose only
|
2003-10-23 01:00:57 +02:00
|
|
|
void print(std::ostream& os) const;
|
|
|
|
|
2006-11-14 01:08:16 +01:00
|
|
|
std::string name() const;
|
|
|
|
|
2006-10-11 16:02:21 +02:00
|
|
|
bool check_fastresume(aux::piece_checker_data&);
|
2005-10-13 09:59:05 +02:00
|
|
|
std::pair<bool, float> check_files();
|
|
|
|
void files_checked(std::vector<piece_picker::downloading_piece> const&
|
|
|
|
unfinished_pieces);
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2003-12-07 06:53:04 +01:00
|
|
|
stat statistics() const { return m_stat; }
|
|
|
|
size_type bytes_left() const;
|
2006-01-07 14:48:14 +01:00
|
|
|
boost::tuples::tuple<size_type, size_type> bytes_done() const;
|
2006-09-24 02:48:31 +02:00
|
|
|
size_type quantized_bytes_done() const;
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2004-03-21 03:03:37 +01:00
|
|
|
void pause();
|
|
|
|
void resume();
|
|
|
|
bool is_paused() const { return m_paused; }
|
|
|
|
|
2007-03-20 02:59:00 +01:00
|
|
|
// ============ start deprecation =============
|
2005-06-23 01:04:37 +02:00
|
|
|
void filter_piece(int index, bool filter);
|
|
|
|
void filter_pieces(std::vector<bool> const& bitmask);
|
2005-05-25 12:01:01 +02:00
|
|
|
bool is_piece_filtered(int index) const;
|
|
|
|
void filtered_pieces(std::vector<bool>& bitmask) const;
|
2005-07-04 01:33:47 +02:00
|
|
|
void filter_files(std::vector<bool> const& files);
|
2007-03-20 02:59:00 +01:00
|
|
|
// ============ end deprecation =============
|
|
|
|
|
|
|
|
void set_piece_priority(int index, int priority);
|
|
|
|
int piece_priority(int index) const;
|
|
|
|
|
|
|
|
void prioritize_pieces(std::vector<int> const& pieces);
|
|
|
|
void piece_priorities(std::vector<int>&) const;
|
|
|
|
|
|
|
|
void prioritize_files(std::vector<int> const& files);
|
|
|
|
|
2003-10-31 05:02:51 +01:00
|
|
|
torrent_status status() const;
|
2006-06-11 15:48:39 +02:00
|
|
|
void file_progress(std::vector<float>& fp) const;
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2004-02-26 01:27:06 +01:00
|
|
|
void use_interface(const char* net_interface);
|
2006-04-25 23:04:48 +02:00
|
|
|
tcp::endpoint const& get_interface() const { return m_net_interface; }
|
|
|
|
|
|
|
|
void connect_to_url_seed(std::string const& url);
|
2007-04-10 23:23:13 +02:00
|
|
|
peer_connection& connect_to_peer(policy::peer* peerinfo);
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2004-01-12 04:05:10 +01:00
|
|
|
void set_ratio(float ratio)
|
2004-01-25 13:37:15 +01:00
|
|
|
{ assert(ratio >= 0.0f); m_ratio = ratio; }
|
2004-01-12 04:05:10 +01:00
|
|
|
|
|
|
|
float ratio() const
|
2004-01-25 13:37:15 +01:00
|
|
|
{ return m_ratio; }
|
2004-01-12 04:05:10 +01:00
|
|
|
|
2007-01-29 08:39:33 +01:00
|
|
|
void resolve_countries(bool r)
|
|
|
|
{ m_resolve_countries = r; }
|
|
|
|
|
|
|
|
bool resolving_countries() const { return m_resolve_countries; }
|
|
|
|
|
2007-01-10 16:02:25 +01:00
|
|
|
// --------------------------------------------
|
|
|
|
// BANDWIDTH MANAGEMENT
|
|
|
|
|
|
|
|
bandwidth_limit m_bandwidth_limit[2];
|
|
|
|
|
|
|
|
void request_bandwidth(int channel
|
2007-02-01 08:33:04 +01:00
|
|
|
, boost::intrusive_ptr<peer_connection> p
|
|
|
|
, bool non_prioritized);
|
2007-01-10 16:02:25 +01:00
|
|
|
|
|
|
|
void expire_bandwidth(int channel, int amount);
|
|
|
|
void assign_bandwidth(int channel, int amount);
|
2007-02-20 00:06:20 +01:00
|
|
|
|
|
|
|
int bandwidth_throttle(int channel) const;
|
2007-01-10 16:02:25 +01:00
|
|
|
|
2003-10-23 01:00:57 +02:00
|
|
|
// --------------------------------------------
|
|
|
|
// PEER MANAGEMENT
|
2006-04-25 23:04:48 +02:00
|
|
|
|
|
|
|
// add or remove a url that will be attempted for
|
|
|
|
// finding the file(s) in this torrent.
|
|
|
|
void add_url_seed(std::string const& url)
|
|
|
|
{ m_web_seeds.insert(url); }
|
|
|
|
|
|
|
|
void remove_url_seed(std::string const& url)
|
|
|
|
{ m_web_seeds.erase(url); }
|
2003-10-23 01:00:57 +02:00
|
|
|
|
|
|
|
// used by peer_connection to attach itself to a torrent
|
|
|
|
// since incoming connections don't know what torrent
|
|
|
|
// they're a part of until they have received an info_hash.
|
2003-12-01 06:01:40 +01:00
|
|
|
void attach_peer(peer_connection* p);
|
2003-10-23 01:00:57 +02:00
|
|
|
|
|
|
|
// this will remove the peer and make sure all
|
|
|
|
// the pieces it had have their reference counter
|
|
|
|
// decreased in the piece_picker
|
|
|
|
void remove_peer(peer_connection* p);
|
|
|
|
|
2006-04-25 23:04:48 +02:00
|
|
|
peer_connection* connection_for(tcp::endpoint const& a)
|
2004-01-13 04:08:59 +01:00
|
|
|
{
|
|
|
|
peer_iterator i = m_connections.find(a);
|
|
|
|
if (i == m_connections.end()) return 0;
|
|
|
|
return i->second;
|
|
|
|
}
|
|
|
|
|
2003-10-23 01:00:57 +02:00
|
|
|
// the number of peers that belong to this torrent
|
2004-01-25 19:18:36 +01:00
|
|
|
int num_peers() const { return (int)m_connections.size(); }
|
2004-08-05 15:56:26 +02:00
|
|
|
int num_seeds() const;
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2006-04-25 23:04:48 +02:00
|
|
|
typedef std::map<tcp::endpoint, peer_connection*>::iterator peer_iterator;
|
|
|
|
typedef std::map<tcp::endpoint, peer_connection*>::const_iterator const_peer_iterator;
|
2003-11-05 00:27:06 +01:00
|
|
|
|
2004-01-13 04:08:59 +01:00
|
|
|
const_peer_iterator begin() const { return m_connections.begin(); }
|
|
|
|
const_peer_iterator end() const { return m_connections.end(); }
|
2003-11-05 00:27:06 +01:00
|
|
|
|
|
|
|
peer_iterator begin() { return m_connections.begin(); }
|
|
|
|
peer_iterator end() { return m_connections.end(); }
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2007-01-29 08:39:33 +01:00
|
|
|
void resolve_peer_country(boost::intrusive_ptr<peer_connection> const& p) const;
|
2003-10-23 01:00:57 +02:00
|
|
|
|
|
|
|
// --------------------------------------------
|
|
|
|
// TRACKER MANAGEMENT
|
|
|
|
|
2004-03-28 19:45:37 +02:00
|
|
|
// these are callbacks called by the tracker_connection instance
|
|
|
|
// (either http_tracker_connection or udp_tracker_connection)
|
2003-10-23 01:00:57 +02:00
|
|
|
// when this torrent got a response from its tracker request
|
2004-03-28 19:45:37 +02:00
|
|
|
// or when a failure occured
|
2005-03-24 13:13:47 +01:00
|
|
|
virtual void tracker_response(
|
|
|
|
tracker_request const& r
|
|
|
|
, std::vector<peer_entry>& e, int interval
|
2005-02-23 09:57:54 +01:00
|
|
|
, int complete, int incomplete);
|
2005-03-24 13:13:47 +01:00
|
|
|
virtual void tracker_request_timed_out(
|
|
|
|
tracker_request const& r);
|
|
|
|
virtual void tracker_request_error(tracker_request const& r
|
|
|
|
, int response_code, const std::string& str);
|
2005-08-11 01:32:39 +02:00
|
|
|
virtual void tracker_warning(std::string const& msg);
|
2003-10-23 01:00:57 +02:00
|
|
|
|
|
|
|
// generates a request string for sending
|
|
|
|
// to the tracker
|
2004-03-21 03:03:37 +01:00
|
|
|
tracker_request generate_tracker_request();
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2004-03-28 19:45:37 +02:00
|
|
|
// if no password and username is set
|
|
|
|
// this will return an empty string, otherwise
|
|
|
|
// it will concatenate the login and password
|
|
|
|
// ready to be sent over http (but without
|
|
|
|
// base64 encoding).
|
|
|
|
std::string tracker_login() const;
|
|
|
|
|
|
|
|
// returns the absolute time when the next tracker
|
|
|
|
// announce will take place.
|
2007-04-05 00:27:36 +02:00
|
|
|
ptime next_announce() const;
|
2004-03-28 19:45:37 +02:00
|
|
|
|
|
|
|
// returns true if it is time for this torrent to make another
|
|
|
|
// tracker request
|
2004-07-24 13:54:17 +02:00
|
|
|
bool should_request();
|
2004-03-28 19:45:37 +02:00
|
|
|
|
|
|
|
// forcefully sets next_announce to the current time
|
|
|
|
void force_tracker_request();
|
2007-04-05 00:27:36 +02:00
|
|
|
void force_tracker_request(ptime);
|
2005-08-01 16:24:19 +02:00
|
|
|
|
2004-03-28 19:45:37 +02:00
|
|
|
// sets the username and password that will be sent to
|
|
|
|
// the tracker
|
|
|
|
void set_tracker_login(std::string const& name, std::string const& pw);
|
|
|
|
|
2006-04-25 23:04:48 +02:00
|
|
|
// the tcp::endpoint of the tracker that we managed to
|
2004-03-28 19:45:37 +02:00
|
|
|
// announce ourself at the last time we tried to announce
|
2006-04-25 23:04:48 +02:00
|
|
|
const tcp::endpoint& current_tracker() const;
|
2003-10-23 01:00:57 +02:00
|
|
|
|
|
|
|
// --------------------------------------------
|
|
|
|
// PIECE MANAGEMENT
|
|
|
|
|
|
|
|
// returns true if we have downloaded the given piece
|
2004-01-25 05:18:08 +01:00
|
|
|
bool have_piece(int index) const
|
2004-01-25 13:37:15 +01:00
|
|
|
{
|
|
|
|
assert(index >= 0 && index < (signed)m_have_pieces.size());
|
|
|
|
return m_have_pieces[index];
|
|
|
|
}
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2003-12-17 04:40:13 +01:00
|
|
|
const std::vector<bool>& pieces() const
|
|
|
|
{ return m_have_pieces; }
|
|
|
|
|
2004-06-14 01:30:42 +02:00
|
|
|
int num_pieces() const { return m_num_pieces; }
|
|
|
|
|
2003-10-23 01:00:57 +02:00
|
|
|
// when we get a have- or bitfield- messages, this is called for every
|
|
|
|
// piece a peer has gained.
|
2003-12-18 04:30:41 +01:00
|
|
|
void peer_has(int index)
|
2004-01-25 13:37:15 +01:00
|
|
|
{
|
2006-12-04 13:20:34 +01:00
|
|
|
if (m_picker.get())
|
|
|
|
{
|
|
|
|
assert(!is_seed());
|
|
|
|
assert(index >= 0 && index < (signed)m_have_pieces.size());
|
|
|
|
m_picker->inc_refcount(index);
|
|
|
|
}
|
|
|
|
#ifndef NDEBUG
|
|
|
|
else
|
|
|
|
{
|
|
|
|
assert(is_seed());
|
|
|
|
}
|
|
|
|
#endif
|
2004-01-25 13:37:15 +01:00
|
|
|
}
|
2007-04-15 04:14:02 +02:00
|
|
|
|
|
|
|
void peer_has_all()
|
|
|
|
{
|
|
|
|
if (m_picker.get())
|
|
|
|
{
|
|
|
|
assert(!is_seed());
|
|
|
|
m_picker->inc_refcount_all();
|
|
|
|
}
|
|
|
|
#ifndef NDEBUG
|
|
|
|
else
|
|
|
|
{
|
|
|
|
assert(is_seed());
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
2003-10-23 01:00:57 +02:00
|
|
|
|
|
|
|
// when peer disconnects, this is called for every piece it had
|
|
|
|
void peer_lost(int index)
|
2004-01-25 13:37:15 +01:00
|
|
|
{
|
2006-12-04 13:20:34 +01:00
|
|
|
if (m_picker.get())
|
|
|
|
{
|
|
|
|
assert(!is_seed());
|
|
|
|
assert(index >= 0 && index < (signed)m_have_pieces.size());
|
|
|
|
m_picker->dec_refcount(index);
|
|
|
|
}
|
|
|
|
#ifndef NDEBUG
|
|
|
|
else
|
|
|
|
{
|
|
|
|
assert(is_seed());
|
|
|
|
}
|
|
|
|
#endif
|
2004-01-25 13:37:15 +01:00
|
|
|
}
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2006-04-25 23:04:48 +02:00
|
|
|
int block_size() const { assert(m_block_size > 0); return m_block_size; }
|
2003-10-23 01:00:57 +02:00
|
|
|
|
|
|
|
// this will tell all peers that we just got his piece
|
|
|
|
// and also let the piece picker know that we have this piece
|
|
|
|
// so it wont pick it for download
|
|
|
|
void announce_piece(int index);
|
|
|
|
|
2004-01-20 23:59:21 +01:00
|
|
|
void disconnect_all();
|
2004-01-21 14:16:11 +01:00
|
|
|
|
|
|
|
// this is called wheh the torrent has completed
|
|
|
|
// the download. It will post an event, disconnect
|
|
|
|
// all seeds and let the tracker know we're finished.
|
|
|
|
void completed();
|
2007-03-07 19:50:38 +01:00
|
|
|
|
|
|
|
// this is the asio callback that is called when a name
|
|
|
|
// lookup for a PEER is completed.
|
|
|
|
void on_peer_name_lookup(asio::error_code const& e, tcp::resolver::iterator i
|
|
|
|
, peer_id pid);
|
|
|
|
|
2006-04-25 23:04:48 +02:00
|
|
|
// this is the asio callback that is called when a name
|
2007-03-07 19:50:38 +01:00
|
|
|
// lookup for a WEB SEED is completed.
|
2006-11-14 01:08:16 +01:00
|
|
|
void on_name_lookup(asio::error_code const& e, tcp::resolver::iterator i
|
2007-02-12 06:46:29 +01:00
|
|
|
, std::string url, tcp::endpoint proxy);
|
|
|
|
|
|
|
|
// this is the asio callback that is called when a name
|
|
|
|
// lookup for a proxy for a web seed is completed.
|
|
|
|
void on_proxy_name_lookup(asio::error_code const& e, tcp::resolver::iterator i
|
2006-08-01 17:27:08 +02:00
|
|
|
, std::string url);
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2005-06-11 01:12:50 +02:00
|
|
|
// this is called when the torrent has finished. i.e.
|
|
|
|
// all the pieces we have not filtered have been downloaded.
|
|
|
|
// If no pieces are filtered, this is called first and then
|
|
|
|
// completed() is called immediately after it.
|
|
|
|
void finished();
|
|
|
|
|
2003-12-07 06:53:04 +01:00
|
|
|
bool verify_piece(int piece_index);
|
|
|
|
|
2003-12-01 22:27:27 +01:00
|
|
|
// this is called from the peer_connection
|
|
|
|
// each time a piece has failed the hash
|
|
|
|
// test
|
|
|
|
void piece_failed(int index);
|
2006-04-25 23:04:48 +02:00
|
|
|
void received_redundant_data(int num_bytes)
|
|
|
|
{ assert(num_bytes > 0); m_total_redundant_bytes += num_bytes; }
|
2003-12-01 22:27:27 +01:00
|
|
|
|
2007-04-12 00:27:58 +02:00
|
|
|
// this is true if we have all the pieces
|
2003-12-09 19:09:34 +01:00
|
|
|
bool is_seed() const
|
2004-06-14 01:30:42 +02:00
|
|
|
{
|
|
|
|
return valid_metadata()
|
|
|
|
&& m_num_pieces == m_torrent_file.num_pieces();
|
|
|
|
}
|
2003-12-09 19:09:34 +01:00
|
|
|
|
2007-04-12 00:27:58 +02:00
|
|
|
// this is true if we have all the pieces that we want
|
|
|
|
bool is_finished() const
|
|
|
|
{
|
|
|
|
if (is_seed()) return true;
|
|
|
|
return valid_metadata() && m_torrent_file.num_pieces()
|
2007-04-12 00:50:01 +02:00
|
|
|
- m_num_pieces - m_picker->num_filtered() == 0;
|
2007-04-12 00:27:58 +02:00
|
|
|
}
|
|
|
|
|
2004-06-14 01:30:42 +02:00
|
|
|
boost::filesystem::path save_path() const;
|
2004-01-07 01:48:02 +01:00
|
|
|
alert_manager& alerts() const;
|
2004-06-14 01:30:42 +02:00
|
|
|
piece_picker& picker()
|
|
|
|
{
|
2007-03-17 00:28:26 +01:00
|
|
|
assert(!is_seed());
|
2004-06-14 01:30:42 +02:00
|
|
|
assert(m_picker.get());
|
|
|
|
return *m_picker;
|
|
|
|
}
|
2007-03-17 00:28:26 +01:00
|
|
|
bool has_picker() const
|
|
|
|
{
|
2007-04-17 23:50:48 +02:00
|
|
|
assert((valid_metadata() && !is_seed()) == bool(m_picker.get() != 0));
|
|
|
|
return m_picker.get() != 0;
|
2007-03-17 00:28:26 +01:00
|
|
|
}
|
2006-05-28 21:03:54 +02:00
|
|
|
policy& get_policy()
|
|
|
|
{
|
|
|
|
assert(m_policy);
|
|
|
|
return *m_policy;
|
|
|
|
}
|
2004-06-14 01:30:42 +02:00
|
|
|
piece_manager& filesystem();
|
2006-05-28 21:03:54 +02:00
|
|
|
torrent_info const& torrent_file() const
|
|
|
|
{ return m_torrent_file; }
|
2004-02-22 23:40:45 +01:00
|
|
|
|
2004-09-12 12:12:16 +02:00
|
|
|
std::vector<announce_entry> const& trackers() const
|
|
|
|
{ return m_trackers; }
|
|
|
|
|
|
|
|
void replace_trackers(std::vector<announce_entry> const& urls);
|
|
|
|
|
2004-03-28 19:45:37 +02:00
|
|
|
torrent_handle get_handle() const;
|
2004-03-01 01:50:00 +01:00
|
|
|
|
2005-03-19 13:22:40 +01:00
|
|
|
// LOGGING
|
2005-07-06 15:18:10 +02:00
|
|
|
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
2003-11-20 20:58:29 +01:00
|
|
|
virtual void debug_log(const std::string& line);
|
2005-03-19 13:22:40 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// DEBUG
|
|
|
|
#ifndef NDEBUG
|
2004-06-14 01:30:42 +02:00
|
|
|
void check_invariant() const;
|
2003-11-20 20:58:29 +01:00
|
|
|
#endif
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2004-03-28 19:45:37 +02:00
|
|
|
// --------------------------------------------
|
|
|
|
// RESOURCE MANAGEMENT
|
|
|
|
|
2006-11-20 22:03:58 +01:00
|
|
|
void distribute_resources(float tick_interval);
|
2004-03-23 23:58:18 +01:00
|
|
|
|
2004-10-29 15:21:09 +02:00
|
|
|
resource_request m_uploads_quota;
|
2004-03-28 19:45:37 +02:00
|
|
|
resource_request m_connections_quota;
|
2004-03-23 23:58:18 +01:00
|
|
|
|
2006-04-25 23:04:48 +02:00
|
|
|
void set_peer_upload_limit(tcp::endpoint ip, int limit);
|
|
|
|
void set_peer_download_limit(tcp::endpoint ip, int limit);
|
|
|
|
|
2004-03-28 19:45:37 +02:00
|
|
|
void set_upload_limit(int limit);
|
2007-04-10 11:25:17 +02:00
|
|
|
int upload_limit() const;
|
2004-03-28 19:45:37 +02:00
|
|
|
void set_download_limit(int limit);
|
2007-04-10 11:25:17 +02:00
|
|
|
int download_limit() const;
|
|
|
|
|
2004-10-29 15:21:09 +02:00
|
|
|
void set_max_uploads(int limit);
|
|
|
|
void set_max_connections(int limit);
|
2004-07-18 02:39:58 +02:00
|
|
|
bool move_storage(boost::filesystem::path const& save_path);
|
2004-03-23 23:58:18 +01:00
|
|
|
|
2005-10-16 22:15:54 +02:00
|
|
|
// unless this returns true, new connections must wait
|
|
|
|
// with their initialization.
|
|
|
|
bool ready_for_connections() const
|
|
|
|
{ return m_connections_initialized; }
|
2005-10-16 11:15:46 +02:00
|
|
|
bool valid_metadata() const
|
2005-10-16 22:15:54 +02:00
|
|
|
{ return m_storage.get() != 0; }
|
2004-06-14 01:30:42 +02:00
|
|
|
|
2006-11-14 01:08:16 +01:00
|
|
|
// parses the info section from the given
|
|
|
|
// bencoded tree and moves the torrent
|
|
|
|
// to the checker thread for initial checking
|
|
|
|
// of the storage.
|
|
|
|
void set_metadata(entry const&);
|
|
|
|
|
2003-11-26 15:11:25 +01:00
|
|
|
private:
|
2007-02-12 10:20:49 +01:00
|
|
|
|
2003-10-23 01:00:57 +02:00
|
|
|
void try_next_tracker();
|
2004-09-12 12:12:16 +02:00
|
|
|
int prioritize_tracker(int tracker_index);
|
2007-01-29 08:39:33 +01:00
|
|
|
void on_country_lookup(asio::error_code const& error, tcp::resolver::iterator i
|
|
|
|
, boost::intrusive_ptr<peer_connection> p) const;
|
2007-02-19 01:01:39 +01:00
|
|
|
bool request_bandwidth_from_session(int channel) const;
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2007-03-21 03:09:50 +01:00
|
|
|
void update_peer_interest();
|
|
|
|
|
2004-06-14 01:30:42 +02:00
|
|
|
torrent_info m_torrent_file;
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2003-10-23 18:55:52 +02:00
|
|
|
// is set to true when the torrent has
|
|
|
|
// been aborted.
|
2003-10-23 01:00:57 +02:00
|
|
|
bool m_abort;
|
|
|
|
|
2004-03-21 03:03:37 +01:00
|
|
|
// is true if this torrent has been paused
|
|
|
|
bool m_paused;
|
2004-07-24 13:54:17 +02:00
|
|
|
// this is true from the time when the torrent was
|
|
|
|
// paused to the time should_request() is called
|
|
|
|
bool m_just_paused;
|
2004-03-21 03:03:37 +01:00
|
|
|
|
2004-01-21 14:16:11 +01:00
|
|
|
tracker_request::event_t m_event;
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2004-01-15 17:45:34 +01:00
|
|
|
void parse_response(const entry& e, std::vector<peer_entry>& peer_list);
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2004-06-14 01:30:42 +02:00
|
|
|
// the size of a request block
|
|
|
|
// each piece is divided into these
|
|
|
|
// blocks when requested
|
|
|
|
int m_block_size;
|
|
|
|
|
2005-03-05 15:17:17 +01:00
|
|
|
// if this pointer is 0, the torrent is in
|
2004-06-14 01:30:42 +02:00
|
|
|
// a state where the metadata hasn't been
|
|
|
|
// received yet.
|
2005-11-01 19:30:39 +01:00
|
|
|
boost::scoped_ptr<piece_manager> m_storage;
|
2003-10-23 01:00:57 +02:00
|
|
|
|
|
|
|
// the time of next tracker request
|
2007-04-05 00:27:36 +02:00
|
|
|
ptime m_next_request;
|
2003-10-23 01:00:57 +02:00
|
|
|
|
|
|
|
// -----------------------------
|
|
|
|
// DATA FROM TRACKER RESPONSE
|
|
|
|
|
|
|
|
// the number number of seconds between requests
|
|
|
|
// from the tracker
|
|
|
|
int m_duration;
|
|
|
|
|
2005-02-21 14:59:24 +01:00
|
|
|
// the scrape data from the tracker response, this
|
|
|
|
// is optional and may be -1.
|
|
|
|
int m_complete;
|
|
|
|
int m_incomplete;
|
2006-04-25 23:04:48 +02:00
|
|
|
|
2005-10-01 17:12:10 +02:00
|
|
|
#ifndef NDEBUG
|
|
|
|
public:
|
|
|
|
#endif
|
2006-04-25 23:04:48 +02:00
|
|
|
std::map<tcp::endpoint, peer_connection*> m_connections;
|
2005-10-01 17:12:10 +02:00
|
|
|
#ifndef NDEBUG
|
|
|
|
private:
|
|
|
|
#endif
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2006-04-25 23:04:48 +02:00
|
|
|
// The list of web seeds in this torrent. Seeds
|
|
|
|
// with fatal errors are removed from the set
|
|
|
|
std::set<std::string> m_web_seeds;
|
2006-05-20 17:30:40 +02:00
|
|
|
|
|
|
|
// urls of the web seeds that we are currently
|
|
|
|
// resolving the address for
|
|
|
|
std::set<std::string> m_resolving_web_seeds;
|
2006-04-25 23:04:48 +02:00
|
|
|
|
|
|
|
// used to resolve the names of web seeds
|
2007-01-29 08:39:33 +01:00
|
|
|
mutable tcp::resolver m_host_resolver;
|
2006-08-01 17:27:08 +02:00
|
|
|
|
2007-01-29 08:39:33 +01:00
|
|
|
// this is true while there is a country
|
|
|
|
// resolution in progress. To avoid flodding
|
|
|
|
// the DNS request queue, only one ip is reolved
|
|
|
|
// at a time.
|
|
|
|
mutable bool m_resolving_country;
|
|
|
|
|
|
|
|
// this is true if the user has enabled
|
|
|
|
// country resolution in this torrent
|
|
|
|
bool m_resolve_countries;
|
|
|
|
|
2007-04-04 04:06:07 +02:00
|
|
|
// this announce timer is used both
|
|
|
|
// by Local service discovery and
|
|
|
|
// by the DHT.
|
|
|
|
deadline_timer m_announce_timer;
|
|
|
|
|
2007-04-11 19:22:19 +02:00
|
|
|
static void on_announce_disp(boost::weak_ptr<torrent> p
|
|
|
|
, asio::error_code const& e);
|
|
|
|
|
2007-04-04 04:06:07 +02:00
|
|
|
// this is called once per announce interval
|
2007-04-11 19:22:19 +02:00
|
|
|
void on_announce();
|
2007-04-04 04:06:07 +02:00
|
|
|
|
2006-08-01 17:27:08 +02:00
|
|
|
#ifndef TORRENT_DISABLE_DHT
|
2006-08-29 03:15:24 +02:00
|
|
|
static void on_dht_announce_response_disp(boost::weak_ptr<torrent> t
|
|
|
|
, std::vector<tcp::endpoint> const& peers);
|
2006-08-01 17:27:08 +02:00
|
|
|
void on_dht_announce_response(std::vector<tcp::endpoint> const& peers);
|
2007-02-12 10:20:49 +01:00
|
|
|
bool should_announce_dht() const;
|
2006-08-01 17:27:08 +02:00
|
|
|
#endif
|
2006-04-25 23:04:48 +02:00
|
|
|
|
2003-12-07 06:53:04 +01:00
|
|
|
// this is the upload and download statistics for the whole torrent.
|
|
|
|
// it's updated from all its peers once every second.
|
|
|
|
libtorrent::stat m_stat;
|
|
|
|
|
2003-10-23 01:00:57 +02:00
|
|
|
// -----------------------------
|
|
|
|
|
|
|
|
boost::shared_ptr<policy> m_policy;
|
|
|
|
|
2003-12-07 06:53:04 +01:00
|
|
|
// a back reference to the session
|
|
|
|
// this torrent belongs to.
|
2006-10-11 16:02:21 +02:00
|
|
|
aux::session_impl& m_ses;
|
|
|
|
aux::checker_impl& m_checker;
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2005-11-01 19:30:39 +01:00
|
|
|
boost::scoped_ptr<piece_picker> m_picker;
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2007-01-10 16:02:25 +01:00
|
|
|
// the queue of peer_connections that want more bandwidth
|
2007-02-01 08:33:04 +01:00
|
|
|
std::deque<bw_queue_entry> m_bandwidth_queue[2];
|
2007-01-10 16:02:25 +01:00
|
|
|
|
2004-09-12 12:12:16 +02:00
|
|
|
std::vector<announce_entry> m_trackers;
|
2003-10-23 01:00:57 +02:00
|
|
|
// this is an index into m_torrent_file.trackers()
|
|
|
|
int m_last_working_tracker;
|
|
|
|
int m_currently_trying_tracker;
|
2004-04-02 00:29:51 +02:00
|
|
|
// the number of connection attempts that has
|
2004-09-12 12:12:16 +02:00
|
|
|
// failed in a row, this is currently used to
|
|
|
|
// determine the timeout until next try.
|
2004-04-02 00:29:51 +02:00
|
|
|
int m_failed_trackers;
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2003-12-01 06:01:40 +01:00
|
|
|
// this is a counter that is increased every
|
|
|
|
// second, and when it reaches 10, the policy::pulse()
|
|
|
|
// is called and the time scaler is reset to 0.
|
|
|
|
int m_time_scaler;
|
2003-12-07 06:53:04 +01:00
|
|
|
|
|
|
|
// the bitmask that says which pieces we have
|
|
|
|
std::vector<bool> m_have_pieces;
|
|
|
|
|
|
|
|
// the number of pieces we have. The same as
|
|
|
|
// std::accumulate(m_have_pieces.begin(),
|
|
|
|
// m_have_pieces.end(), 0)
|
|
|
|
int m_num_pieces;
|
2003-12-22 08:14:35 +01:00
|
|
|
|
2007-03-17 00:28:26 +01:00
|
|
|
// in case the piece picker hasn't been constructed
|
|
|
|
// when this settings is set, this variable will keep
|
|
|
|
// its value until the piece picker is created
|
|
|
|
int m_sequenced_download_threshold;
|
|
|
|
|
2003-12-22 08:14:35 +01:00
|
|
|
// is false by default and set to
|
|
|
|
// true when the first tracker reponse
|
|
|
|
// is received
|
|
|
|
bool m_got_tracker_response;
|
2004-01-12 04:05:10 +01:00
|
|
|
|
|
|
|
// the upload/download ratio that each peer
|
|
|
|
// tries to maintain.
|
|
|
|
// 0 is infinite
|
|
|
|
float m_ratio;
|
2004-02-22 23:40:45 +01:00
|
|
|
|
2004-04-18 14:28:02 +02:00
|
|
|
// the number of bytes that has been
|
|
|
|
// downloaded that failed the hash-test
|
|
|
|
size_type m_total_failed_bytes;
|
2006-04-25 23:04:48 +02:00
|
|
|
size_type m_total_redundant_bytes;
|
2004-04-18 14:28:02 +02:00
|
|
|
|
2004-02-22 23:40:45 +01:00
|
|
|
std::string m_username;
|
|
|
|
std::string m_password;
|
2004-03-23 23:58:18 +01:00
|
|
|
|
|
|
|
// the network interface all outgoing connections
|
|
|
|
// are opened through
|
2006-04-25 23:04:48 +02:00
|
|
|
tcp::endpoint m_net_interface;
|
2004-03-23 23:58:18 +01:00
|
|
|
|
2004-06-14 01:30:42 +02:00
|
|
|
boost::filesystem::path m_save_path;
|
2005-05-13 02:39:39 +02:00
|
|
|
|
|
|
|
// determines the storage state for this torrent.
|
|
|
|
const bool m_compact_mode;
|
2005-06-15 14:54:35 +02:00
|
|
|
|
2005-07-10 12:42:00 +02:00
|
|
|
// defaults to 16 kiB, but can be set by the user
|
|
|
|
// when creating the torrent
|
|
|
|
const int m_default_block_size;
|
2005-10-16 11:15:46 +02:00
|
|
|
|
|
|
|
// this is set to false as long as the connections
|
|
|
|
// of this torrent hasn't been initialized. If we
|
|
|
|
// have metadata from the start, connections are
|
|
|
|
// initialized immediately, if we didn't have metadata,
|
|
|
|
// they are initialized right after files_checked().
|
|
|
|
// valid_resume_data() will return false as long as
|
|
|
|
// the connections aren't initialized, to avoid
|
|
|
|
// them from altering the piece-picker before it
|
|
|
|
// has been initialized with files_checked().
|
|
|
|
bool m_connections_initialized;
|
2006-04-25 23:04:48 +02:00
|
|
|
|
2006-11-14 01:08:16 +01:00
|
|
|
// if the torrent is started without metadata, it may
|
|
|
|
// still be given a name until the metadata is received
|
|
|
|
// once the metadata is received this field will no
|
|
|
|
// longer be used and will be reset
|
|
|
|
boost::scoped_ptr<std::string> m_name;
|
|
|
|
|
2006-04-25 23:04:48 +02:00
|
|
|
session_settings const& m_settings;
|
2007-03-16 06:29:23 +01:00
|
|
|
|
|
|
|
storage_constructor_type m_storage_constructor;
|
2006-11-14 01:08:16 +01:00
|
|
|
|
|
|
|
#ifndef TORRENT_DISABLE_EXTENSIONS
|
|
|
|
typedef std::list<boost::shared_ptr<torrent_plugin> > extension_list_t;
|
|
|
|
extension_list_t m_extensions;
|
|
|
|
#endif
|
2006-04-25 23:04:48 +02:00
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
// this is the amount downloaded when this torrent
|
|
|
|
// is started. i.e.
|
|
|
|
// total_done - m_initial_done <= total_payload_download
|
|
|
|
size_type m_initial_done;
|
|
|
|
#endif
|
2006-11-20 22:03:58 +01:00
|
|
|
|
|
|
|
#ifdef TORRENT_LOGGING
|
|
|
|
boost::shared_ptr<logger> m_log;
|
2006-11-24 15:22:52 +01:00
|
|
|
boost::shared_ptr<logger> m_peer_log;
|
2006-11-20 22:03:58 +01:00
|
|
|
int m_second_count;
|
|
|
|
|
2006-11-21 16:51:28 +01:00
|
|
|
enum { debug_bw_history_size = 10 };
|
|
|
|
int m_ul_history[debug_bw_history_size];
|
|
|
|
int m_dl_history[debug_bw_history_size];
|
2006-11-20 22:03:58 +01:00
|
|
|
#endif
|
2003-10-23 01:00:57 +02:00
|
|
|
};
|
|
|
|
|
2007-04-05 00:27:36 +02:00
|
|
|
inline ptime torrent::next_announce() const
|
2004-03-28 19:45:37 +02:00
|
|
|
{
|
2004-07-24 13:54:17 +02:00
|
|
|
return m_next_request;
|
2004-03-28 19:45:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void torrent::force_tracker_request()
|
2005-05-03 15:13:57 +02:00
|
|
|
{
|
2007-04-05 00:27:36 +02:00
|
|
|
m_next_request = time_now();
|
2005-05-03 15:13:57 +02:00
|
|
|
}
|
|
|
|
|
2007-04-05 00:27:36 +02:00
|
|
|
inline void torrent::force_tracker_request(ptime t)
|
2004-03-28 19:45:37 +02:00
|
|
|
{
|
2005-05-03 15:13:57 +02:00
|
|
|
m_next_request = t;
|
2004-03-28 19:45:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void torrent::set_tracker_login(
|
|
|
|
std::string const& name
|
|
|
|
, std::string const& pw)
|
|
|
|
{
|
|
|
|
m_username = name;
|
|
|
|
m_password = pw;
|
|
|
|
}
|
|
|
|
|
2003-10-23 01:00:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif // TORRENT_TORRENT_HPP_INCLUDED
|
2005-03-19 13:22:40 +01:00
|
|
|
|