fix duplicant_torrent and libtorrent bugfixes
This commit is contained in:
parent
2eb3868115
commit
cfe1bd241d
|
@ -43,6 +43,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#endif
|
||||
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/condition.hpp>
|
||||
|
||||
#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
|
||||
#include <boost/preprocessor/repetition/enum.hpp>
|
||||
|
@ -99,10 +100,13 @@ namespace libtorrent {
|
|||
void set_severity(alert::severity_t severity);
|
||||
bool should_post(alert::severity_t severity) const;
|
||||
|
||||
alert const* wait_for_alert(time_duration max_wait);
|
||||
|
||||
private:
|
||||
std::queue<alert*> m_alerts;
|
||||
alert::severity_t m_severity;
|
||||
mutable boost::mutex m_mutex;
|
||||
boost::condition m_condition;
|
||||
};
|
||||
|
||||
struct TORRENT_EXPORT unhandled_alert : std::exception
|
||||
|
|
|
@ -280,6 +280,8 @@ namespace libtorrent
|
|||
void set_severity_level(alert::severity_t s);
|
||||
std::auto_ptr<alert> pop_alert();
|
||||
|
||||
alert const* wait_for_alert(time_duration max_wait);
|
||||
|
||||
int upload_rate_limit() const;
|
||||
int download_rate_limit() const;
|
||||
|
||||
|
|
|
@ -60,6 +60,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/session_status.hpp"
|
||||
#include "libtorrent/version.hpp"
|
||||
#include "libtorrent/fingerprint.hpp"
|
||||
#include "libtorrent/time.hpp"
|
||||
|
||||
#include "libtorrent/storage.hpp"
|
||||
|
||||
|
@ -264,6 +265,8 @@ namespace libtorrent
|
|||
std::auto_ptr<alert> pop_alert();
|
||||
void set_severity_level(alert::severity_t s);
|
||||
|
||||
alert const* wait_for_alert(time_duration max_wait);
|
||||
|
||||
connection_queue& get_connection_queue();
|
||||
|
||||
// starts/stops UPnP, NATPMP or LSD port mappers
|
||||
|
|
|
@ -95,6 +95,7 @@ namespace libtorrent
|
|||
, peer_timeout(120)
|
||||
, urlseed_timeout(20)
|
||||
, urlseed_pipeline_size(5)
|
||||
, urlseed_wait_retry(30)
|
||||
, file_pool_size(40)
|
||||
, allow_multiple_connections_per_ip(false)
|
||||
, max_failcount(3)
|
||||
|
@ -186,6 +187,9 @@ namespace libtorrent
|
|||
// controls the pipelining size of url-seeds
|
||||
int urlseed_pipeline_size;
|
||||
|
||||
// time to wait until a new retry takes place
|
||||
int urlseed_wait_retry;
|
||||
|
||||
// sets the upper limit on the total number of files this
|
||||
// session will keep open. The reason why files are
|
||||
// left open at all is that some anti virus software
|
||||
|
|
|
@ -98,6 +98,7 @@ namespace libtorrent
|
|||
time_duration() {}
|
||||
time_duration operator/(int rhs) const { return time_duration(diff / rhs); }
|
||||
explicit time_duration(boost::int64_t d) : diff(d) {}
|
||||
time_duration& operator-=(time_duration const& c) { diff -= c.diff; return *this; }
|
||||
boost::int64_t diff;
|
||||
};
|
||||
|
||||
|
|
|
@ -206,7 +206,7 @@ namespace libtorrent
|
|||
tcp::endpoint const& get_interface() const { return m_net_interface; }
|
||||
|
||||
void connect_to_url_seed(std::string const& url);
|
||||
bool connect_to_peer(policy::peer* peerinfo) throw();
|
||||
bool connect_to_peer(policy::peer* peerinfo);
|
||||
|
||||
void set_ratio(float ratio)
|
||||
{ TORRENT_ASSERT(ratio >= 0.0f); m_ratio = ratio; }
|
||||
|
@ -254,6 +254,8 @@ namespace libtorrent
|
|||
void remove_url_seed(std::string const& url)
|
||||
{ m_web_seeds.erase(url); }
|
||||
|
||||
void retry_url_seed(std::string const& url);
|
||||
|
||||
std::set<std::string> url_seeds() const
|
||||
{ return m_web_seeds; }
|
||||
|
||||
|
@ -293,6 +295,9 @@ namespace libtorrent
|
|||
|
||||
void resolve_peer_country(boost::intrusive_ptr<peer_connection> const& p) const;
|
||||
|
||||
void get_peer_info(std::vector<peer_info>& v);
|
||||
void get_download_queue(std::vector<partial_piece_info>& queue);
|
||||
|
||||
// --------------------------------------------
|
||||
// TRACKER MANAGEMENT
|
||||
|
||||
|
@ -624,6 +629,10 @@ namespace libtorrent
|
|||
// with fatal errors are removed from the set
|
||||
std::set<std::string> m_web_seeds;
|
||||
|
||||
// a list of web seeds that have failed and are
|
||||
// waiting to be retried
|
||||
std::map<std::string, ptime> m_web_seeds_next_retry;
|
||||
|
||||
// urls of the web seeds that we are currently
|
||||
// resolving the address for
|
||||
std::set<std::string> m_resolving_web_seeds;
|
||||
|
|
|
@ -69,9 +69,15 @@ namespace libtorrent
|
|||
|
||||
struct TORRENT_EXPORT file_entry
|
||||
{
|
||||
file_entry(): offset(0), size(0), file_base(0) {}
|
||||
|
||||
fs::path path;
|
||||
size_type offset; // the offset of this file inside the torrent
|
||||
size_type size; // the size of this file
|
||||
// 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;
|
||||
// if the path was incorrectly encoded, this is
|
||||
// the original corrupt encoded string. It is
|
||||
// preserved in order to be able to reproduce
|
||||
|
@ -117,7 +123,7 @@ namespace libtorrent
|
|||
void add_file(fs::path file, size_type size);
|
||||
void add_url_seed(std::string const& url);
|
||||
|
||||
bool remap_files(std::vector<std::pair<std::string, libtorrent::size_type> > const& map);
|
||||
bool remap_files(std::vector<file_entry> const& map);
|
||||
|
||||
std::vector<file_slice> map_block(int piece, size_type offset
|
||||
, int size, bool storage = false) const;
|
||||
|
@ -271,7 +277,7 @@ namespace libtorrent
|
|||
|
||||
// this vector is typically empty. If it is not
|
||||
// empty, it means the user has re-mapped the
|
||||
// files in this torrent to diffefrent names
|
||||
// files in this torrent to different names
|
||||
// on disk. This is only used when reading and
|
||||
// writing the disk.
|
||||
std::vector<file_entry> m_remapped_files;
|
||||
|
|
|
@ -64,18 +64,18 @@ am__libtorrent_la_SOURCES_DIST = entry.cpp escape_string.cpp \
|
|||
peer_connection.cpp bt_peer_connection.cpp \
|
||||
web_peer_connection.cpp natpmp.cpp piece_picker.cpp policy.cpp \
|
||||
session.cpp session_impl.cpp sha1.cpp stat.cpp storage.cpp \
|
||||
torrent.cpp torrent_handle.cpp pe_crypto.cpp torrent_info.cpp \
|
||||
tracker_manager.cpp http_connection.cpp \
|
||||
http_tracker_connection.cpp udp_tracker_connection.cpp \
|
||||
alert.cpp identify_client.cpp ip_filter.cpp file.cpp \
|
||||
metadata_transfer.cpp logger.cpp file_pool.cpp ut_pex.cpp \
|
||||
lsd.cpp upnp.cpp instantiate_connection.cpp socks5_stream.cpp \
|
||||
socks4_stream.cpp http_stream.cpp connection_queue.cpp \
|
||||
disk_io_thread.cpp kademlia/closest_nodes.cpp \
|
||||
kademlia/dht_tracker.cpp kademlia/find_data.cpp \
|
||||
kademlia/node.cpp kademlia/node_id.cpp kademlia/refresh.cpp \
|
||||
kademlia/routing_table.cpp kademlia/rpc_manager.cpp \
|
||||
kademlia/traversal_algorithm.cpp
|
||||
mapped_storage.cpp torrent.cpp torrent_handle.cpp \
|
||||
pe_crypto.cpp torrent_info.cpp tracker_manager.cpp \
|
||||
http_connection.cpp http_tracker_connection.cpp \
|
||||
udp_tracker_connection.cpp alert.cpp identify_client.cpp \
|
||||
ip_filter.cpp file.cpp metadata_transfer.cpp logger.cpp \
|
||||
file_pool.cpp ut_pex.cpp lsd.cpp upnp.cpp \
|
||||
instantiate_connection.cpp socks5_stream.cpp socks4_stream.cpp \
|
||||
http_stream.cpp connection_queue.cpp disk_io_thread.cpp \
|
||||
kademlia/closest_nodes.cpp kademlia/dht_tracker.cpp \
|
||||
kademlia/find_data.cpp kademlia/node.cpp kademlia/node_id.cpp \
|
||||
kademlia/refresh.cpp kademlia/routing_table.cpp \
|
||||
kademlia/rpc_manager.cpp kademlia/traversal_algorithm.cpp
|
||||
@USE_DHT_TRUE@am__objects_1 = closest_nodes.lo dht_tracker.lo \
|
||||
@USE_DHT_TRUE@ find_data.lo node.lo node_id.lo refresh.lo \
|
||||
@USE_DHT_TRUE@ routing_table.lo rpc_manager.lo \
|
||||
|
@ -84,8 +84,9 @@ am_libtorrent_la_OBJECTS = entry.lo escape_string.lo assert.lo \
|
|||
enum_net.lo broadcast_socket.lo peer_connection.lo \
|
||||
bt_peer_connection.lo web_peer_connection.lo natpmp.lo \
|
||||
piece_picker.lo policy.lo session.lo session_impl.lo sha1.lo \
|
||||
stat.lo storage.lo torrent.lo torrent_handle.lo pe_crypto.lo \
|
||||
torrent_info.lo tracker_manager.lo http_connection.lo \
|
||||
stat.lo storage.lo mapped_storage.lo torrent.lo \
|
||||
torrent_handle.lo pe_crypto.lo torrent_info.lo \
|
||||
tracker_manager.lo http_connection.lo \
|
||||
http_tracker_connection.lo udp_tracker_connection.lo alert.lo \
|
||||
identify_client.lo ip_filter.lo file.lo metadata_transfer.lo \
|
||||
logger.lo file_pool.lo ut_pex.lo lsd.lo upnp.lo \
|
||||
|
@ -251,7 +252,7 @@ libtorrent_la_SOURCES = entry.cpp escape_string.cpp \
|
|||
assert.cpp enum_net.cpp broadcast_socket.cpp \
|
||||
peer_connection.cpp bt_peer_connection.cpp web_peer_connection.cpp \
|
||||
natpmp.cpp piece_picker.cpp policy.cpp session.cpp session_impl.cpp sha1.cpp \
|
||||
stat.cpp storage.cpp torrent.cpp torrent_handle.cpp pe_crypto.cpp \
|
||||
stat.cpp storage.cpp mapped_storage.cpp torrent.cpp torrent_handle.cpp pe_crypto.cpp \
|
||||
torrent_info.cpp tracker_manager.cpp http_connection.cpp \
|
||||
http_tracker_connection.cpp udp_tracker_connection.cpp \
|
||||
alert.cpp identify_client.cpp ip_filter.cpp file.cpp metadata_transfer.cpp \
|
||||
|
@ -422,6 +423,7 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ip_filter.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logger.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lsd.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mapped_storage.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/metadata_transfer.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/natpmp.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/node.Plo@am__quote@
|
||||
|
|
|
@ -33,6 +33,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/pch.hpp"
|
||||
|
||||
#include "libtorrent/alert.hpp"
|
||||
#include <boost/thread/xtime.hpp>
|
||||
|
||||
namespace libtorrent {
|
||||
|
||||
|
@ -77,6 +78,30 @@ namespace libtorrent {
|
|||
}
|
||||
}
|
||||
|
||||
alert const* alert_manager::wait_for_alert(time_duration max_wait)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_mutex);
|
||||
|
||||
if (!m_alerts.empty()) return m_alerts.front();
|
||||
|
||||
int secs = total_seconds(max_wait);
|
||||
max_wait -= seconds(secs);
|
||||
boost::xtime xt;
|
||||
boost::xtime_get(&xt, boost::TIME_UTC);
|
||||
xt.sec += secs;
|
||||
boost::int64_t nsec = xt.nsec + total_microseconds(max_wait) * 1000;
|
||||
if (nsec > 1000000000)
|
||||
{
|
||||
nsec -= 1000000000;
|
||||
xt.sec += 1;
|
||||
}
|
||||
xt.nsec = nsec;
|
||||
if (!m_condition.timed_wait(lock, xt)) return 0;
|
||||
TORRENT_ASSERT(!m_alerts.empty());
|
||||
if (m_alerts.empty()) return 0;
|
||||
return m_alerts.front();
|
||||
}
|
||||
|
||||
void alert_manager::post_alert(const alert& alert_)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_mutex);
|
||||
|
@ -90,6 +115,7 @@ namespace libtorrent {
|
|||
delete result;
|
||||
}
|
||||
m_alerts.push(alert_.clone().release());
|
||||
m_condition.notify_all();
|
||||
}
|
||||
|
||||
std::auto_ptr<alert> alert_manager::get()
|
||||
|
|
|
@ -273,6 +273,9 @@ namespace libtorrent { namespace dht
|
|||
udp::endpoint ep(listen_interface, listen_port);
|
||||
m_socket.open(ep.protocol());
|
||||
m_socket.bind(ep);
|
||||
m_socket.async_receive_from(asio::buffer(&m_in_buf[m_buffer][0]
|
||||
, m_in_buf[m_buffer].size()), m_remote_endpoint[m_buffer]
|
||||
, m_strand.wrap(bind(&dht_tracker::on_receive, self(), _1, _2)));
|
||||
}
|
||||
|
||||
void dht_tracker::tick(asio::error_code const& e)
|
||||
|
|
|
@ -226,6 +226,10 @@ bool rpc_manager::incoming(msg const& m)
|
|||
std::ofstream reply_stats("libtorrent_logs/round_trip_ms.log", std::ios::app);
|
||||
reply_stats << m.addr << "\t" << total_milliseconds(time_now() - o->sent)
|
||||
<< std::endl;
|
||||
#endif
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
TORRENT_LOG(rpc) << "Reply with transaction id: "
|
||||
<< tid << " from " << m.addr;
|
||||
#endif
|
||||
o->reply(m);
|
||||
m_transactions[tid] = 0;
|
||||
|
@ -284,6 +288,10 @@ time_duration rpc_manager::tick()
|
|||
try
|
||||
{
|
||||
m_transactions[m_oldest_transaction_id] = 0;
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
TORRENT_LOG(rpc) << "Timing out transaction id: "
|
||||
<< m_oldest_transaction_id << " from " << o->target_addr;
|
||||
#endif
|
||||
timeouts.push_back(o);
|
||||
} catch (std::exception) {}
|
||||
}
|
||||
|
@ -309,7 +317,13 @@ unsigned int rpc_manager::new_transaction_id(observer_ptr o)
|
|||
// moving the observer into the set of aborted transactions
|
||||
// it will prevent it from spawning new requests right now,
|
||||
// since that would break the invariant
|
||||
m_aborted_transactions.push_back(m_transactions[m_next_transaction_id]);
|
||||
observer_ptr o = m_transactions[m_next_transaction_id];
|
||||
m_aborted_transactions.push_back(o);
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
TORRENT_LOG(rpc) << "[new_transaction_id] Aborting message with transaction id: "
|
||||
<< m_next_transaction_id << " sent to " << o->target_addr
|
||||
<< " " << total_seconds(time_now() - o->sent) << " seconds ago";
|
||||
#endif
|
||||
m_transactions[m_next_transaction_id] = 0;
|
||||
TORRENT_ASSERT(m_oldest_transaction_id == m_next_transaction_id);
|
||||
}
|
||||
|
|
|
@ -422,6 +422,11 @@ namespace libtorrent
|
|||
return m_impl->pop_alert();
|
||||
}
|
||||
|
||||
alert const* session::wait_for_alert(time_duration max_wait)
|
||||
{
|
||||
return m_impl->wait_for_alert(max_wait);
|
||||
}
|
||||
|
||||
void session::set_severity_level(alert::severity_t s)
|
||||
{
|
||||
m_impl->set_severity_level(s);
|
||||
|
|
|
@ -2252,6 +2252,11 @@ namespace detail
|
|||
return std::auto_ptr<alert>(0);
|
||||
}
|
||||
|
||||
alert const* session_impl::wait_for_alert(time_duration max_wait)
|
||||
{
|
||||
return m_alerts.wait_for_alert(max_wait);
|
||||
}
|
||||
|
||||
void session_impl::set_severity_level(alert::severity_t s)
|
||||
{
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
|
@ -2414,6 +2419,11 @@ namespace detail
|
|||
{
|
||||
TORRENT_ASSERT(false);
|
||||
}
|
||||
for (std::map<sha1_hash, boost::shared_ptr<torrent> >::const_iterator j
|
||||
= m_torrents.begin(); j != m_torrents.end(); ++j)
|
||||
{
|
||||
TORRENT_ASSERT(boost::get_pointer(j->second));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -43,7 +43,8 @@ namespace libtorrent
|
|||
if (e)
|
||||
{
|
||||
(*h)(e);
|
||||
close();
|
||||
asio::error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -54,8 +55,8 @@ namespace libtorrent
|
|||
if (i == tcp::resolver::iterator())
|
||||
{
|
||||
asio::error_code ec = asio::error::operation_not_supported;
|
||||
(*h)(e);
|
||||
close();
|
||||
(*h)(ec);
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -68,7 +69,8 @@ namespace libtorrent
|
|||
if (e)
|
||||
{
|
||||
(*h)(e);
|
||||
close();
|
||||
asio::error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -93,7 +95,8 @@ namespace libtorrent
|
|||
if (e)
|
||||
{
|
||||
(*h)(e);
|
||||
close();
|
||||
asio::error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -107,7 +110,8 @@ namespace libtorrent
|
|||
if (e)
|
||||
{
|
||||
(*h)(e);
|
||||
close();
|
||||
asio::error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -119,8 +123,9 @@ namespace libtorrent
|
|||
|
||||
if (reply_version != 0)
|
||||
{
|
||||
(*h)(asio::error::operation_not_supported);
|
||||
close();
|
||||
asio::error_code ec = asio::error::operation_not_supported;
|
||||
(*h)(ec);
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -140,7 +145,7 @@ namespace libtorrent
|
|||
case 93: ec = asio::error::no_permission; break;
|
||||
}
|
||||
(*h)(ec);
|
||||
close();
|
||||
close(ec);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -44,7 +44,8 @@ namespace libtorrent
|
|||
if (e || i == tcp::resolver::iterator())
|
||||
{
|
||||
(*h)(e);
|
||||
close();
|
||||
asio::error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -57,7 +58,8 @@ namespace libtorrent
|
|||
if (e)
|
||||
{
|
||||
(*h)(e);
|
||||
close();
|
||||
asio::error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -86,7 +88,8 @@ namespace libtorrent
|
|||
if (e)
|
||||
{
|
||||
(*h)(e);
|
||||
close();
|
||||
asio::error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -100,7 +103,8 @@ namespace libtorrent
|
|||
if (e)
|
||||
{
|
||||
(*h)(e);
|
||||
close();
|
||||
asio::error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -113,7 +117,8 @@ namespace libtorrent
|
|||
if (version < 5)
|
||||
{
|
||||
(*h)(asio::error::operation_not_supported);
|
||||
close();
|
||||
asio::error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -126,7 +131,8 @@ namespace libtorrent
|
|||
if (m_user.empty())
|
||||
{
|
||||
(*h)(asio::error::operation_not_supported);
|
||||
close();
|
||||
asio::error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -144,7 +150,8 @@ namespace libtorrent
|
|||
else
|
||||
{
|
||||
(*h)(asio::error::operation_not_supported);
|
||||
close();
|
||||
asio::error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -155,7 +162,8 @@ namespace libtorrent
|
|||
if (e)
|
||||
{
|
||||
(*h)(e);
|
||||
close();
|
||||
asio::error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -170,7 +178,8 @@ namespace libtorrent
|
|||
if (e)
|
||||
{
|
||||
(*h)(e);
|
||||
close();
|
||||
asio::error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -183,19 +192,21 @@ namespace libtorrent
|
|||
if (version != 1)
|
||||
{
|
||||
(*h)(asio::error::operation_not_supported);
|
||||
close();
|
||||
asio::error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
(*h)(asio::error::operation_not_supported);
|
||||
close();
|
||||
asio::error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<char>().swap(m_buffer);
|
||||
(*h)(e);
|
||||
socks_connect(h);
|
||||
}
|
||||
|
||||
void socks5_stream::socks_connect(boost::shared_ptr<handler_type> h)
|
||||
|
@ -222,7 +233,8 @@ namespace libtorrent
|
|||
if (e)
|
||||
{
|
||||
(*h)(e);
|
||||
close();
|
||||
asio::error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -236,7 +248,8 @@ namespace libtorrent
|
|||
if (e)
|
||||
{
|
||||
(*h)(e);
|
||||
close();
|
||||
asio::error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -248,7 +261,8 @@ namespace libtorrent
|
|||
if (version < 5)
|
||||
{
|
||||
(*h)(asio::error::operation_not_supported);
|
||||
close();
|
||||
asio::error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
int response = read_uint8(p);
|
||||
|
@ -267,7 +281,8 @@ namespace libtorrent
|
|||
case 8: e = asio::error::address_family_not_supported; break;
|
||||
}
|
||||
(*h)(e);
|
||||
close();
|
||||
asio::error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
p += 1; // reserved
|
||||
|
@ -291,7 +306,8 @@ namespace libtorrent
|
|||
else
|
||||
{
|
||||
(*h)(asio::error::operation_not_supported);
|
||||
close();
|
||||
asio::error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
m_buffer.resize(skip_bytes);
|
||||
|
@ -305,7 +321,8 @@ namespace libtorrent
|
|||
if (e)
|
||||
{
|
||||
(*h)(e);
|
||||
close();
|
||||
asio::error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -768,10 +768,10 @@ namespace libtorrent
|
|||
|
||||
TORRENT_ASSERT(file_offset < file_iter->size);
|
||||
|
||||
TORRENT_ASSERT(slices[0].offset == file_offset);
|
||||
TORRENT_ASSERT(slices[0].offset == file_offset + file_iter->file_base);
|
||||
|
||||
size_type new_pos = in->seek(file_offset);
|
||||
if (new_pos != file_offset)
|
||||
size_type new_pos = in->seek(file_offset + file_iter->file_base);
|
||||
if (new_pos != file_offset + file_iter->file_base)
|
||||
{
|
||||
// the file was not big enough
|
||||
if (!fill_zero)
|
||||
|
@ -782,7 +782,7 @@ namespace libtorrent
|
|||
|
||||
#ifndef NDEBUG
|
||||
size_type in_tell = in->tell();
|
||||
TORRENT_ASSERT(in_tell == file_offset);
|
||||
TORRENT_ASSERT(in_tell == file_offset + file_iter->file_base);
|
||||
#endif
|
||||
|
||||
int left_to_read = size;
|
||||
|
@ -846,7 +846,7 @@ namespace libtorrent
|
|||
file_offset = 0;
|
||||
in = m_files.open_file(
|
||||
this, path, file::in);
|
||||
in->seek(0);
|
||||
in->seek(file_iter->file_base);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -892,11 +892,11 @@ namespace libtorrent
|
|||
this, p, file::out | file::in);
|
||||
|
||||
TORRENT_ASSERT(file_offset < file_iter->size);
|
||||
TORRENT_ASSERT(slices[0].offset == file_offset);
|
||||
TORRENT_ASSERT(slices[0].offset == file_offset + file_iter->file_base);
|
||||
|
||||
size_type pos = out->seek(file_offset);
|
||||
size_type pos = out->seek(file_offset + file_iter->file_base);
|
||||
|
||||
if (pos != file_offset)
|
||||
if (pos != file_offset + file_iter->file_base)
|
||||
{
|
||||
std::stringstream s;
|
||||
s << "no storage for slot " << slot;
|
||||
|
@ -962,7 +962,7 @@ namespace libtorrent
|
|||
out = m_files.open_file(
|
||||
this, p, file::out | file::in);
|
||||
|
||||
out->seek(0);
|
||||
out->seek(file_iter->file_base);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -287,6 +287,10 @@ namespace libtorrent
|
|||
#ifndef TORRENT_DISABLE_DHT
|
||||
bool torrent::should_announce_dht() const
|
||||
{
|
||||
if (m_ses.m_listen_sockets.empty()) return false;
|
||||
|
||||
if (!m_ses.m_dht) return false;
|
||||
|
||||
// don't announce private torrents
|
||||
if (m_torrent_file->is_valid() && m_torrent_file->priv()) return false;
|
||||
|
||||
|
@ -434,6 +438,7 @@ namespace libtorrent
|
|||
bind(&torrent::on_announce_disp, self, _1)));
|
||||
|
||||
// announce with the local discovery service
|
||||
if (!m_paused)
|
||||
m_ses.announce_lsd(m_torrent_file->info_hash());
|
||||
}
|
||||
else
|
||||
|
@ -444,14 +449,12 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
if (m_paused) return;
|
||||
if (!m_ses.m_dht) return;
|
||||
ptime now = time_now();
|
||||
if (should_announce_dht() && now - m_last_dht_announce > minutes(14))
|
||||
{
|
||||
m_last_dht_announce = now;
|
||||
// TODO: There should be a way to abort an announce operation on the dht.
|
||||
// when the torrent is destructed
|
||||
if (m_ses.m_listen_sockets.empty()) return;
|
||||
m_ses.m_dht->announce(m_torrent_file->info_hash()
|
||||
, m_ses.m_listen_sockets.front().external_port
|
||||
, m_ses.m_strand.wrap(bind(&torrent::on_dht_announce_response_disp, self, _1)));
|
||||
|
@ -701,7 +704,7 @@ namespace libtorrent
|
|||
const int last_piece = m_torrent_file->num_pieces() - 1;
|
||||
|
||||
size_type total_done
|
||||
= m_num_pieces * m_torrent_file->piece_length();
|
||||
= size_type(m_num_pieces) * m_torrent_file->piece_length();
|
||||
|
||||
// if we have the last piece, we have to correct
|
||||
// the amount we have, since the first calculation
|
||||
|
@ -726,16 +729,17 @@ namespace libtorrent
|
|||
return tuple<size_type, size_type>(0,0);
|
||||
|
||||
const int last_piece = m_torrent_file->num_pieces() - 1;
|
||||
const int piece_size = m_torrent_file->piece_length();
|
||||
|
||||
if (is_seed())
|
||||
return make_tuple(m_torrent_file->total_size()
|
||||
, m_torrent_file->total_size());
|
||||
|
||||
size_type wanted_done = (m_num_pieces - m_picker->num_have_filtered())
|
||||
* m_torrent_file->piece_length();
|
||||
size_type wanted_done = size_type(m_num_pieces - m_picker->num_have_filtered())
|
||||
* piece_size;
|
||||
|
||||
size_type total_done
|
||||
= m_num_pieces * m_torrent_file->piece_length();
|
||||
= size_type(m_num_pieces) * piece_size;
|
||||
TORRENT_ASSERT(m_num_pieces < m_torrent_file->num_pieces());
|
||||
|
||||
// if we have the last piece, we have to correct
|
||||
|
@ -743,12 +747,18 @@ namespace libtorrent
|
|||
// assumed all pieces were of equal size
|
||||
if (m_have_pieces[last_piece])
|
||||
{
|
||||
TORRENT_ASSERT(total_done >= piece_size);
|
||||
int corr = m_torrent_file->piece_size(last_piece)
|
||||
- m_torrent_file->piece_length();
|
||||
- piece_size;
|
||||
TORRENT_ASSERT(corr <= 0);
|
||||
TORRENT_ASSERT(corr > -piece_size);
|
||||
total_done += corr;
|
||||
if (m_picker->piece_priority(last_piece) != 0)
|
||||
{
|
||||
TORRENT_ASSERT(wanted_done >= piece_size);
|
||||
wanted_done += corr;
|
||||
}
|
||||
}
|
||||
|
||||
TORRENT_ASSERT(total_done <= m_torrent_file->total_size());
|
||||
TORRENT_ASSERT(wanted_done <= m_torrent_file->total_size());
|
||||
|
@ -757,7 +767,7 @@ namespace libtorrent
|
|||
= m_picker->get_download_queue();
|
||||
|
||||
const int blocks_per_piece = static_cast<int>(
|
||||
m_torrent_file->piece_length() / m_block_size);
|
||||
piece_size / m_block_size);
|
||||
|
||||
for (std::vector<piece_picker::downloading_piece>::const_iterator i =
|
||||
dl_queue.begin(); i != dl_queue.end(); ++i)
|
||||
|
@ -779,6 +789,7 @@ namespace libtorrent
|
|||
{
|
||||
TORRENT_ASSERT(m_picker->is_finished(piece_block(index, j)) == (i->info[j].state == piece_picker::block_info::state_finished));
|
||||
corr += (i->info[j].state == piece_picker::block_info::state_finished) * m_block_size;
|
||||
TORRENT_ASSERT(corr >= 0);
|
||||
TORRENT_ASSERT(index != last_piece || j < m_picker->blocks_in_last_piece()
|
||||
|| i->info[j].state != piece_picker::block_info::state_finished);
|
||||
}
|
||||
|
@ -1913,7 +1924,101 @@ namespace libtorrent
|
|||
}
|
||||
#endif
|
||||
|
||||
bool torrent::connect_to_peer(policy::peer* peerinfo) throw()
|
||||
void torrent::get_peer_info(std::vector<peer_info>& v)
|
||||
{
|
||||
v.clear();
|
||||
for (peer_iterator i = begin();
|
||||
i != end(); ++i)
|
||||
{
|
||||
peer_connection* peer = *i;
|
||||
|
||||
// incoming peers that haven't finished the handshake should
|
||||
// not be included in this list
|
||||
if (peer->associated_torrent().expired()) continue;
|
||||
|
||||
v.push_back(peer_info());
|
||||
peer_info& p = v.back();
|
||||
|
||||
peer->get_peer_info(p);
|
||||
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
|
||||
if (resolving_countries())
|
||||
resolve_peer_country(intrusive_ptr<peer_connection>(peer));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void torrent::get_download_queue(std::vector<partial_piece_info>& queue)
|
||||
{
|
||||
queue.clear();
|
||||
if (!valid_metadata() || is_seed()) return;
|
||||
piece_picker const& p = picker();
|
||||
std::vector<piece_picker::downloading_piece> const& q
|
||||
= p.get_download_queue();
|
||||
|
||||
for (std::vector<piece_picker::downloading_piece>::const_iterator i
|
||||
= q.begin(); i != q.end(); ++i)
|
||||
{
|
||||
partial_piece_info pi;
|
||||
pi.piece_state = (partial_piece_info::state_t)i->state;
|
||||
pi.blocks_in_piece = p.blocks_in_piece(i->index);
|
||||
pi.finished = (int)i->finished;
|
||||
pi.writing = (int)i->writing;
|
||||
pi.requested = (int)i->requested;
|
||||
int piece_size = torrent_file().piece_size(i->index);
|
||||
for (int j = 0; j < pi.blocks_in_piece; ++j)
|
||||
{
|
||||
block_info& bi = pi.blocks[j];
|
||||
bi.state = i->info[j].state;
|
||||
bi.block_size = j < pi.blocks_in_piece - 1 ? m_block_size
|
||||
: piece_size - (j * m_block_size);
|
||||
bool complete = bi.state == block_info::writing
|
||||
|| bi.state == block_info::finished;
|
||||
if (i->info[j].peer == 0)
|
||||
{
|
||||
bi.peer = tcp::endpoint();
|
||||
bi.bytes_progress = complete ? bi.block_size : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
policy::peer* p = static_cast<policy::peer*>(i->info[j].peer);
|
||||
if (p->connection)
|
||||
{
|
||||
bi.peer = p->connection->remote();
|
||||
if (bi.state == block_info::requested)
|
||||
{
|
||||
boost::optional<piece_block_progress> pbp
|
||||
= p->connection->downloading_piece_progress();
|
||||
if (pbp && pbp->piece_index == i->index && pbp->block_index == j)
|
||||
{
|
||||
bi.bytes_progress = pbp->bytes_downloaded;
|
||||
TORRENT_ASSERT(bi.bytes_progress <= bi.block_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
bi.bytes_progress = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bi.bytes_progress = complete ? bi.block_size : 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bi.peer = p->ip;
|
||||
bi.bytes_progress = complete ? bi.block_size : 0;
|
||||
}
|
||||
}
|
||||
|
||||
pi.blocks[j].num_peers = i->info[j].num_peers;
|
||||
}
|
||||
pi.piece_index = i->index;
|
||||
queue.push_back(pi);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool torrent::connect_to_peer(policy::peer* peerinfo)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
|
@ -2249,16 +2354,18 @@ namespace libtorrent
|
|||
m_next_request = time_now() + seconds(delay);
|
||||
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
// only start the announce if we want to announce with the dht
|
||||
if (should_announce_dht())
|
||||
{
|
||||
if (m_abort) return;
|
||||
|
||||
// only start the announce if we want to announce with the dht
|
||||
ptime now = time_now();
|
||||
if (should_announce_dht() && now - m_last_dht_announce > minutes(14))
|
||||
{
|
||||
// force the DHT to reannounce
|
||||
m_last_dht_announce = time_now() - minutes(15);
|
||||
m_last_dht_announce = now;
|
||||
boost::weak_ptr<torrent> self(shared_from_this());
|
||||
m_announce_timer.expires_from_now(seconds(1));
|
||||
m_announce_timer.async_wait(m_ses.m_strand.wrap(
|
||||
bind(&torrent::on_announce_disp, self, _1)));
|
||||
m_ses.m_dht->announce(m_torrent_file->info_hash()
|
||||
, m_ses.m_listen_sockets.front().external_port
|
||||
, m_ses.m_strand.wrap(bind(&torrent::on_dht_announce_response_disp, self, _1)));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -2747,6 +2854,18 @@ namespace libtorrent
|
|||
|
||||
// ---- WEB SEEDS ----
|
||||
|
||||
// re-insert urls that are to be retries into the m_web_seeds
|
||||
typedef std::map<std::string, ptime>::iterator iter_t;
|
||||
for (iter_t i = m_web_seeds_next_retry.begin(); i != m_web_seeds_next_retry.end();)
|
||||
{
|
||||
iter_t erase_element = i++;
|
||||
if (erase_element->second <= time_now())
|
||||
{
|
||||
m_web_seeds.insert(erase_element->first);
|
||||
m_web_seeds_next_retry.erase(erase_element);
|
||||
}
|
||||
}
|
||||
|
||||
// if we have everything we want we don't need to connect to any web-seed
|
||||
if (!is_finished() && !m_web_seeds.empty())
|
||||
{
|
||||
|
@ -2809,6 +2928,12 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
|
||||
void torrent::retry_url_seed(std::string const& url)
|
||||
{
|
||||
m_web_seeds_next_retry[url] = time_now()
|
||||
+ seconds(m_ses.settings().urlseed_wait_retry);
|
||||
}
|
||||
|
||||
bool torrent::try_connect_peer()
|
||||
{
|
||||
TORRENT_ASSERT(want_more_peers());
|
||||
|
|
|
@ -78,32 +78,90 @@ using boost::bind;
|
|||
using boost::mutex;
|
||||
using libtorrent::aux::session_impl;
|
||||
|
||||
#ifdef BOOST_NO_EXCEPTIONS
|
||||
|
||||
#define TORRENT_FORWARD(call) \
|
||||
if (m_ses == 0) return; \
|
||||
TORRENT_ASSERT(m_chk); \
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); \
|
||||
mutex::scoped_lock l2(m_chk->m_mutex); \
|
||||
torrent* t = find_torrent(m_ses, m_chk, m_info_hash); \
|
||||
if (t == 0) return; \
|
||||
t->call
|
||||
|
||||
#define TORRENT_FORWARD_RETURN(call, def) \
|
||||
if (m_ses == 0) return def; \
|
||||
TORRENT_ASSERT(m_chk); \
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); \
|
||||
mutex::scoped_lock l2(m_chk->m_mutex); \
|
||||
torrent* t = find_torrent(m_ses, m_chk, m_info_hash); \
|
||||
if (t == 0) return def; \
|
||||
return t->call
|
||||
|
||||
#define TORRENT_FORWARD_RETURN2(call, def) \
|
||||
if (m_ses == 0) return def; \
|
||||
TORRENT_ASSERT(m_chk); \
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); \
|
||||
mutex::scoped_lock l2(m_chk->m_mutex); \
|
||||
torrent* t = find_torrent(m_ses, m_chk, m_info_hash); \
|
||||
if (t == 0) return def; \
|
||||
t->call
|
||||
|
||||
#else
|
||||
|
||||
#define TORRENT_FORWARD(call) \
|
||||
if (m_ses == 0) throw_invalid_handle(); \
|
||||
TORRENT_ASSERT(m_chk); \
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); \
|
||||
mutex::scoped_lock l2(m_chk->m_mutex); \
|
||||
torrent* t = find_torrent(m_ses, m_chk, m_info_hash); \
|
||||
if (t == 0) throw_invalid_handle(); \
|
||||
t->call
|
||||
|
||||
#define TORRENT_FORWARD_RETURN(call, def) \
|
||||
if (m_ses == 0) throw_invalid_handle(); \
|
||||
TORRENT_ASSERT(m_chk); \
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); \
|
||||
mutex::scoped_lock l2(m_chk->m_mutex); \
|
||||
torrent* t = find_torrent(m_ses, m_chk, m_info_hash); \
|
||||
if (t == 0) return def; \
|
||||
return t->call
|
||||
|
||||
#define TORRENT_FORWARD_RETURN2(call, def) \
|
||||
if (m_ses == 0) throw_invalid_handle(); \
|
||||
TORRENT_ASSERT(m_chk); \
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); \
|
||||
mutex::scoped_lock l2(m_chk->m_mutex); \
|
||||
torrent* t = find_torrent(m_ses, m_chk, m_info_hash); \
|
||||
if (t == 0) return def; \
|
||||
t->call
|
||||
|
||||
#endif
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
namespace
|
||||
{
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
void throw_invalid_handle()
|
||||
{
|
||||
throw invalid_handle();
|
||||
}
|
||||
#endif
|
||||
|
||||
boost::shared_ptr<torrent> find_torrent(
|
||||
torrent* find_torrent(
|
||||
session_impl* ses
|
||||
, aux::checker_impl* chk
|
||||
, sha1_hash const& hash)
|
||||
{
|
||||
aux::piece_checker_data* d = chk->find_torrent(hash);
|
||||
if (d != 0) return d->torrent_ptr;
|
||||
if (d != 0) return d->torrent_ptr.get();
|
||||
|
||||
boost::shared_ptr<torrent> t = ses->find_torrent(hash).lock();
|
||||
if (t) return t;
|
||||
|
||||
// throwing directly instead of calling
|
||||
// the throw_invalid_handle() function
|
||||
// avoids a warning in gcc
|
||||
throw invalid_handle();
|
||||
if (t) return t.get();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,132 +177,68 @@ namespace libtorrent
|
|||
void torrent_handle::set_max_uploads(int max_uploads) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
TORRENT_ASSERT(max_uploads >= 2 || max_uploads == -1);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->set_max_uploads(max_uploads);
|
||||
TORRENT_FORWARD(set_max_uploads(max_uploads));
|
||||
}
|
||||
|
||||
void torrent_handle::use_interface(const char* net_interface) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->use_interface(net_interface);
|
||||
TORRENT_FORWARD(use_interface(net_interface));
|
||||
}
|
||||
|
||||
void torrent_handle::set_max_connections(int max_connections) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
TORRENT_ASSERT(max_connections >= 2 || max_connections == -1);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->set_max_connections(max_connections);
|
||||
TORRENT_FORWARD(set_max_connections(max_connections));
|
||||
}
|
||||
|
||||
void torrent_handle::set_peer_upload_limit(tcp::endpoint ip, int limit) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
TORRENT_ASSERT(limit >= -1);
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->set_peer_upload_limit(ip, limit);
|
||||
TORRENT_FORWARD(set_peer_upload_limit(ip, limit));
|
||||
}
|
||||
|
||||
void torrent_handle::set_peer_download_limit(tcp::endpoint ip, int limit) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
TORRENT_ASSERT(limit >= -1);
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->set_peer_download_limit(ip, limit);
|
||||
TORRENT_FORWARD(set_peer_download_limit(ip, limit));
|
||||
}
|
||||
|
||||
void torrent_handle::set_upload_limit(int limit) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
TORRENT_ASSERT(limit >= -1);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->set_upload_limit(limit);
|
||||
TORRENT_FORWARD(set_upload_limit(limit));
|
||||
}
|
||||
|
||||
int torrent_handle::upload_limit() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
return find_torrent(m_ses, m_chk, m_info_hash)->upload_limit();
|
||||
TORRENT_FORWARD_RETURN(upload_limit(), 0);
|
||||
}
|
||||
|
||||
void torrent_handle::set_download_limit(int limit) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
TORRENT_ASSERT(limit >= -1);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->set_download_limit(limit);
|
||||
TORRENT_FORWARD(set_download_limit(limit));
|
||||
}
|
||||
|
||||
int torrent_handle::download_limit() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
return find_torrent(m_ses, m_chk, m_info_hash)->download_limit();
|
||||
TORRENT_FORWARD_RETURN(download_limit(), 0);
|
||||
}
|
||||
|
||||
void torrent_handle::move_storage(
|
||||
fs::path const& save_path) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->move_storage(save_path);
|
||||
TORRENT_FORWARD(move_storage(save_path));
|
||||
}
|
||||
|
||||
void torrent_handle::add_extension(
|
||||
|
@ -252,123 +246,62 @@ namespace libtorrent
|
|||
, void* userdata)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
return find_torrent(m_ses, m_chk, m_info_hash)->add_extension(ext, userdata);
|
||||
TORRENT_FORWARD(add_extension(ext, userdata));
|
||||
}
|
||||
|
||||
bool torrent_handle::has_metadata() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
return find_torrent(m_ses, m_chk, m_info_hash)->valid_metadata();
|
||||
TORRENT_FORWARD_RETURN(valid_metadata(), false);
|
||||
}
|
||||
|
||||
bool torrent_handle::is_seed() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
return find_torrent(m_ses, m_chk, m_info_hash)->is_seed();
|
||||
TORRENT_FORWARD_RETURN(is_seed(), false);
|
||||
}
|
||||
|
||||
bool torrent_handle::is_paused() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
return find_torrent(m_ses, m_chk, m_info_hash)->is_paused();
|
||||
TORRENT_FORWARD_RETURN(is_paused(), false);
|
||||
}
|
||||
|
||||
void torrent_handle::pause() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->pause();
|
||||
TORRENT_FORWARD(pause());
|
||||
}
|
||||
|
||||
void torrent_handle::resume() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->resume();
|
||||
TORRENT_FORWARD(resume());
|
||||
}
|
||||
|
||||
void torrent_handle::set_tracker_login(std::string const& name
|
||||
, std::string const& password) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->set_tracker_login(name, password);
|
||||
TORRENT_FORWARD(resume());
|
||||
}
|
||||
|
||||
void torrent_handle::file_progress(std::vector<float>& progress)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
|
||||
aux::piece_checker_data* d = m_chk->find_torrent(m_info_hash);
|
||||
if (d != 0)
|
||||
{
|
||||
if (!d->processing)
|
||||
{
|
||||
torrent_info const& info = d->torrent_ptr->torrent_file();
|
||||
progress.clear();
|
||||
progress.resize(info.num_files(), 0.f);
|
||||
return;
|
||||
}
|
||||
d->torrent_ptr->file_progress(progress);
|
||||
return;
|
||||
}
|
||||
|
||||
boost::shared_ptr<torrent> t = m_ses->find_torrent(m_info_hash).lock();
|
||||
if (t) return t->file_progress(progress);
|
||||
|
||||
throw_invalid_handle();
|
||||
TORRENT_FORWARD(file_progress(progress));
|
||||
}
|
||||
|
||||
torrent_status torrent_handle::status() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
if (m_ses == 0)
|
||||
#ifdef BOOST_NO_EXCEPTIONS
|
||||
return torrent_status();
|
||||
#else
|
||||
throw_invalid_handle();
|
||||
#endif
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l(m_ses->m_mutex);
|
||||
|
@ -396,107 +329,60 @@ namespace libtorrent
|
|||
boost::shared_ptr<torrent> t = m_ses->find_torrent(m_info_hash).lock();
|
||||
if (t) return t->status();
|
||||
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
throw_invalid_handle();
|
||||
#endif
|
||||
return torrent_status();
|
||||
}
|
||||
|
||||
void torrent_handle::set_sequenced_download_threshold(int threshold) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->set_sequenced_download_threshold(threshold);
|
||||
TORRENT_FORWARD(set_sequenced_download_threshold(threshold));
|
||||
}
|
||||
|
||||
std::string torrent_handle::name() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
return find_torrent(m_ses, m_chk, m_info_hash)->name();
|
||||
TORRENT_FORWARD_RETURN(name(), "");
|
||||
}
|
||||
|
||||
|
||||
void torrent_handle::piece_availability(std::vector<int>& avail) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->piece_availability(avail);
|
||||
TORRENT_FORWARD(piece_availability(avail));
|
||||
}
|
||||
|
||||
void torrent_handle::piece_priority(int index, int priority) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->set_piece_priority(index, priority);
|
||||
TORRENT_FORWARD(set_piece_priority(index, priority));
|
||||
}
|
||||
|
||||
int torrent_handle::piece_priority(int index) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
return find_torrent(m_ses, m_chk, m_info_hash)->piece_priority(index);
|
||||
TORRENT_FORWARD_RETURN(piece_priority(index), 0);
|
||||
}
|
||||
|
||||
void torrent_handle::prioritize_pieces(std::vector<int> const& pieces) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->prioritize_pieces(pieces);
|
||||
TORRENT_FORWARD(prioritize_pieces(pieces));
|
||||
}
|
||||
|
||||
std::vector<int> torrent_handle::piece_priorities() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
std::vector<int> ret;
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->piece_priorities(ret);
|
||||
TORRENT_FORWARD_RETURN2(piece_priorities(ret), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void torrent_handle::prioritize_files(std::vector<int> const& files) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->prioritize_files(files);
|
||||
TORRENT_FORWARD(prioritize_files(files));
|
||||
}
|
||||
|
||||
// ============ start deprecation ===============
|
||||
|
@ -504,63 +390,33 @@ namespace libtorrent
|
|||
void torrent_handle::filter_piece(int index, bool filter) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->filter_piece(index, filter);
|
||||
TORRENT_FORWARD(filter_piece(index, filter));
|
||||
}
|
||||
|
||||
void torrent_handle::filter_pieces(std::vector<bool> const& pieces) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->filter_pieces(pieces);
|
||||
TORRENT_FORWARD(filter_pieces(pieces));
|
||||
}
|
||||
|
||||
bool torrent_handle::is_piece_filtered(int index) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
return find_torrent(m_ses, m_chk, m_info_hash)->is_piece_filtered(index);
|
||||
TORRENT_FORWARD_RETURN(is_piece_filtered(index), false);
|
||||
}
|
||||
|
||||
std::vector<bool> torrent_handle::filtered_pieces() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
std::vector<bool> ret;
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->filtered_pieces(ret);
|
||||
TORRENT_FORWARD_RETURN2(filtered_pieces(ret), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void torrent_handle::filter_files(std::vector<bool> const& files) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->filter_files(files);
|
||||
TORRENT_FORWARD(filter_files(files));
|
||||
}
|
||||
|
||||
// ============ end deprecation ===============
|
||||
|
@ -569,111 +425,91 @@ namespace libtorrent
|
|||
std::vector<announce_entry> const& torrent_handle::trackers() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
return find_torrent(m_ses, m_chk, m_info_hash)->trackers();
|
||||
const static std::vector<announce_entry> empty;
|
||||
TORRENT_FORWARD_RETURN(trackers(), empty);
|
||||
}
|
||||
|
||||
void torrent_handle::add_url_seed(std::string const& url) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->add_url_seed(url);
|
||||
TORRENT_FORWARD(add_url_seed(url));
|
||||
}
|
||||
|
||||
void torrent_handle::remove_url_seed(std::string const& url) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->remove_url_seed(url);
|
||||
TORRENT_FORWARD(remove_url_seed(url));
|
||||
}
|
||||
|
||||
std::set<std::string> torrent_handle::url_seeds() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
return find_torrent(m_ses, m_chk, m_info_hash)->url_seeds();
|
||||
const static std::set<std::string> empty;
|
||||
TORRENT_FORWARD_RETURN(url_seeds(), empty);
|
||||
}
|
||||
|
||||
void torrent_handle::replace_trackers(
|
||||
std::vector<announce_entry> const& urls) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->replace_trackers(urls);
|
||||
TORRENT_FORWARD(replace_trackers(urls));
|
||||
}
|
||||
|
||||
torrent_info const& torrent_handle::get_torrent_info() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
#ifdef BOOST_NO_EXCEPTIONS
|
||||
const static torrent_info empty;
|
||||
if (m_ses == 0) return empty;
|
||||
#else
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
#endif
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
boost::shared_ptr<torrent> t = find_torrent(m_ses, m_chk, m_info_hash);
|
||||
if (!t->valid_metadata()) throw_invalid_handle();
|
||||
torrent* t = find_torrent(m_ses, m_chk, m_info_hash);
|
||||
if (t == 0 || !t->valid_metadata())
|
||||
#ifdef BOOST_NO_EXCEPTIONS
|
||||
return empty;
|
||||
#else
|
||||
throw_invalid_handle();
|
||||
#endif
|
||||
return t->torrent_file();
|
||||
}
|
||||
|
||||
bool torrent_handle::is_valid() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) return false;
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l(m_ses->m_mutex);
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
aux::piece_checker_data* d = m_chk->find_torrent(m_info_hash);
|
||||
if (d != 0) return true;
|
||||
|
||||
{
|
||||
boost::weak_ptr<torrent> t = m_ses->find_torrent(m_info_hash);
|
||||
if (!t.expired()) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
torrent* t = find_torrent(m_ses, m_chk, m_info_hash);
|
||||
return t;
|
||||
}
|
||||
|
||||
entry torrent_handle::write_resume_data() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
std::vector<int> piece_index;
|
||||
if (m_ses == 0) return entry();
|
||||
if (m_ses == 0)
|
||||
#ifdef BOOST_NO_EXCEPTIONS
|
||||
return entry();
|
||||
#else
|
||||
throw_invalid_handle();
|
||||
#endif
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l(m_ses->m_mutex);
|
||||
boost::shared_ptr<torrent> t = m_ses->find_torrent(m_info_hash).lock();
|
||||
if (!t) return entry();
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
|
||||
if (!t->valid_metadata()) return entry();
|
||||
boost::shared_ptr<torrent> t = m_ses->find_torrent(m_info_hash).lock();
|
||||
if (!t || !t->valid_metadata())
|
||||
#ifdef BOOST_NO_EXCEPTIONS
|
||||
return entry();
|
||||
#else
|
||||
throw_invalid_handle();
|
||||
#endif
|
||||
|
||||
std::vector<bool> have_pieces = t->pieces();
|
||||
|
||||
|
@ -748,6 +584,7 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<int> piece_index;
|
||||
t->filesystem().export_piece_map(piece_index, have_pieces);
|
||||
entry::list_type& slots = ret["slots"].list();
|
||||
std::copy(piece_index.begin(), piece_index.end(), std::back_inserter(slots));
|
||||
|
@ -796,20 +633,19 @@ namespace libtorrent
|
|||
fs::path torrent_handle::save_path() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
return find_torrent(m_ses, m_chk, m_info_hash)->save_path();
|
||||
TORRENT_FORWARD_RETURN(save_path(), fs::path());
|
||||
}
|
||||
|
||||
void torrent_handle::connect_peer(tcp::endpoint const& adr, int source) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
if (m_ses == 0)
|
||||
#ifdef BOOST_NO_EXCEPTIONS
|
||||
return;
|
||||
#else
|
||||
throw_invalid_handle();
|
||||
#endif
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l(m_ses->m_mutex);
|
||||
|
@ -823,7 +659,12 @@ namespace libtorrent
|
|||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
|
||||
aux::piece_checker_data* d = m_chk->find_torrent(m_info_hash);
|
||||
if (d == 0) throw_invalid_handle();
|
||||
if (d == 0)
|
||||
#ifdef BOOST_NO_EXCEPTIONS
|
||||
return;
|
||||
#else
|
||||
throw_invalid_handle();
|
||||
#endif
|
||||
d->peers.push_back(adr);
|
||||
return;
|
||||
}
|
||||
|
@ -837,205 +678,55 @@ namespace libtorrent
|
|||
boost::posix_time::time_duration duration) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l(m_ses->m_mutex);
|
||||
boost::shared_ptr<torrent> t = m_ses->find_torrent(m_info_hash).lock();
|
||||
if (!t) throw_invalid_handle();
|
||||
|
||||
t->force_tracker_request(time_now()
|
||||
+ seconds(duration.total_seconds()));
|
||||
TORRENT_FORWARD(force_tracker_request(time_now() + seconds(duration.total_seconds())));
|
||||
}
|
||||
|
||||
void torrent_handle::force_reannounce() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l(m_ses->m_mutex);
|
||||
boost::shared_ptr<torrent> t = m_ses->find_torrent(m_info_hash).lock();
|
||||
if (!t) throw_invalid_handle();
|
||||
|
||||
t->force_tracker_request();
|
||||
TORRENT_FORWARD(force_tracker_request());
|
||||
}
|
||||
|
||||
void torrent_handle::scrape_tracker() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l(m_ses->m_mutex);
|
||||
boost::shared_ptr<torrent> t = m_ses->find_torrent(m_info_hash).lock();
|
||||
if (!t) throw_invalid_handle();
|
||||
|
||||
t->scrape_tracker();
|
||||
TORRENT_FORWARD(scrape_tracker());
|
||||
}
|
||||
|
||||
void torrent_handle::set_ratio(float ratio) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
TORRENT_ASSERT(ratio >= 0.f);
|
||||
if (ratio < 1.f && ratio > 0.f)
|
||||
ratio = 1.f;
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->set_ratio(ratio);
|
||||
TORRENT_FORWARD(set_ratio(ratio));
|
||||
}
|
||||
|
||||
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
|
||||
void torrent_handle::resolve_countries(bool r)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->resolve_countries(r);
|
||||
TORRENT_FORWARD(resolve_countries(r));
|
||||
}
|
||||
|
||||
bool torrent_handle::resolve_countries() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
return find_torrent(m_ses, m_chk, m_info_hash)->resolving_countries();
|
||||
TORRENT_FORWARD_RETURN(resolving_countries(), false);
|
||||
}
|
||||
#endif
|
||||
|
||||
void torrent_handle::get_peer_info(std::vector<peer_info>& v) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
v.clear();
|
||||
|
||||
session_impl::mutex_t::scoped_lock l(m_ses->m_mutex);
|
||||
|
||||
boost::shared_ptr<const torrent> t = m_ses->find_torrent(m_info_hash).lock();
|
||||
if (!t) return;
|
||||
|
||||
for (torrent::const_peer_iterator i = t->begin();
|
||||
i != t->end(); ++i)
|
||||
{
|
||||
peer_connection* peer = *i;
|
||||
|
||||
// incoming peers that haven't finished the handshake should
|
||||
// not be included in this list
|
||||
if (peer->associated_torrent().expired()) continue;
|
||||
|
||||
v.push_back(peer_info());
|
||||
peer_info& p = v.back();
|
||||
|
||||
peer->get_peer_info(p);
|
||||
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
|
||||
if (t->resolving_countries())
|
||||
t->resolve_peer_country(intrusive_ptr<peer_connection>(peer));
|
||||
#endif
|
||||
}
|
||||
TORRENT_FORWARD(get_peer_info(v));
|
||||
}
|
||||
|
||||
void torrent_handle::get_download_queue(std::vector<partial_piece_info>& queue) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
TORRENT_ASSERT(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l(m_ses->m_mutex);
|
||||
boost::shared_ptr<torrent> t = m_ses->find_torrent(m_info_hash).lock();
|
||||
|
||||
queue.clear();
|
||||
if (!t) return;
|
||||
if (!t->valid_metadata()) return;
|
||||
// if we're a seed, the piece picker has been removed
|
||||
if (t->is_seed()) return;
|
||||
|
||||
const piece_picker& p = t->picker();
|
||||
|
||||
const std::vector<piece_picker::downloading_piece>& q
|
||||
= p.get_download_queue();
|
||||
|
||||
int block_size = t->block_size();
|
||||
|
||||
for (std::vector<piece_picker::downloading_piece>::const_iterator i
|
||||
= q.begin(); i != q.end(); ++i)
|
||||
{
|
||||
partial_piece_info pi;
|
||||
pi.piece_state = (partial_piece_info::state_t)i->state;
|
||||
pi.blocks_in_piece = p.blocks_in_piece(i->index);
|
||||
pi.finished = (int)i->finished;
|
||||
pi.writing = (int)i->writing;
|
||||
pi.requested = (int)i->requested;
|
||||
int piece_size = t->torrent_file().piece_size(i->index);
|
||||
for (int j = 0; j < pi.blocks_in_piece; ++j)
|
||||
{
|
||||
block_info& bi = pi.blocks[j];
|
||||
bi.state = i->info[j].state;
|
||||
bi.block_size = j < pi.blocks_in_piece - 1 ? block_size
|
||||
: piece_size - (j * block_size);
|
||||
bool complete = bi.state == block_info::writing
|
||||
|| bi.state == block_info::finished;
|
||||
if (i->info[j].peer == 0)
|
||||
{
|
||||
bi.peer = tcp::endpoint();
|
||||
bi.bytes_progress = complete ? bi.block_size : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
policy::peer* p = static_cast<policy::peer*>(i->info[j].peer);
|
||||
if (p->connection)
|
||||
{
|
||||
bi.peer = p->connection->remote();
|
||||
if (bi.state == block_info::requested)
|
||||
{
|
||||
boost::optional<piece_block_progress> pbp
|
||||
= p->connection->downloading_piece_progress();
|
||||
if (pbp && pbp->piece_index == i->index && pbp->block_index == j)
|
||||
{
|
||||
bi.bytes_progress = pbp->bytes_downloaded;
|
||||
TORRENT_ASSERT(bi.bytes_progress <= bi.block_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
bi.bytes_progress = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bi.bytes_progress = complete ? bi.block_size : 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bi.peer = p->ip;
|
||||
bi.bytes_progress = complete ? bi.block_size : 0;
|
||||
}
|
||||
}
|
||||
|
||||
pi.blocks[j].num_peers = i->info[j].num_peers;
|
||||
}
|
||||
pi.piece_index = i->index;
|
||||
queue.push_back(pi);
|
||||
}
|
||||
TORRENT_FORWARD(get_download_queue(queue));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -165,7 +165,7 @@ namespace
|
|||
{
|
||||
target.size = dict["length"].integer();
|
||||
target.path = root_dir;
|
||||
|
||||
target.file_base = 0;
|
||||
|
||||
// prefer the name.utf-8
|
||||
// because if it exists, it is more
|
||||
|
@ -824,20 +824,19 @@ namespace libtorrent
|
|||
m_nodes.push_back(node);
|
||||
}
|
||||
|
||||
bool torrent_info::remap_files(std::vector<std::pair<std::string
|
||||
, libtorrent::size_type> > const& map)
|
||||
bool torrent_info::remap_files(std::vector<file_entry> const& map)
|
||||
{
|
||||
typedef std::vector<std::pair<std::string, size_type> > files_t;
|
||||
|
||||
size_type offset = 0;
|
||||
m_remapped_files.resize(map.size());
|
||||
|
||||
for (int i = 0; i < int(map.size()); ++i)
|
||||
{
|
||||
file_entry& fe = m_remapped_files[i];
|
||||
fe.path = map[i].first;
|
||||
fe.path = map[i].path;
|
||||
fe.offset = offset;
|
||||
fe.size = map[i].second;
|
||||
fe.size = map[i].size;
|
||||
fe.file_base = map[i].file_base;
|
||||
fe.orig_path.reset();
|
||||
offset += fe.size;
|
||||
}
|
||||
if (offset != total_size())
|
||||
|
@ -846,6 +845,26 @@ namespace libtorrent
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
std::vector<file_entry> map2(m_remapped_files);
|
||||
std::sort(map2.begin(), map2.end()
|
||||
, bind(&file_entry::file_base, _1) < bind(&file_entry::file_base, _2));
|
||||
std::stable_sort(map2.begin(), map2.end()
|
||||
, bind(&file_entry::path, _1) < bind(&file_entry::path, _2));
|
||||
fs::path last_path;
|
||||
size_type last_end = 0;
|
||||
for (std::vector<file_entry>::iterator i = map2.begin(), end(map2.end());
|
||||
i != end; ++i)
|
||||
{
|
||||
if (last_path == i->path)
|
||||
{
|
||||
assert(last_end <= i->file_base);
|
||||
}
|
||||
last_end = i->file_base + i->size;
|
||||
last_path = i->path;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -871,7 +890,7 @@ namespace libtorrent
|
|||
{
|
||||
file_slice f;
|
||||
f.file_index = counter;
|
||||
f.offset = file_offset;
|
||||
f.offset = file_offset + file_iter->file_base;
|
||||
f.size = (std::min)(file_iter->size - file_offset, (size_type)size);
|
||||
size -= f.size;
|
||||
file_offset += f.size;
|
||||
|
|
|
@ -306,10 +306,12 @@ namespace libtorrent
|
|||
|
||||
namespace
|
||||
{
|
||||
bool range_contains(peer_request const& range, peer_request const& req)
|
||||
bool range_contains(peer_request const& range, peer_request const& req, int piece_size)
|
||||
{
|
||||
return range.start <= req.start
|
||||
&& range.start + range.length >= req.start + req.length;
|
||||
size_type range_start = size_type(range.piece) * piece_size + range.start;
|
||||
size_type req_start = size_type(req.piece) * piece_size + req.start;
|
||||
return range_start <= req_start
|
||||
&& range_start + range.length >= req_start + req.length;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -358,7 +360,11 @@ namespace libtorrent
|
|||
&& !(m_parser.status_code() >= 300 // redirect
|
||||
&& m_parser.status_code() < 400))
|
||||
{
|
||||
// we should not try this server again.
|
||||
if (m_parser.status_code() == 503)
|
||||
{
|
||||
// temporarily unavailable, retry later
|
||||
t->retry_url_seed(m_url);
|
||||
}
|
||||
t->remove_url_seed(m_url);
|
||||
std::string error_msg = boost::lexical_cast<std::string>(m_parser.status_code())
|
||||
+ " " + m_parser.message();
|
||||
|
@ -470,6 +476,9 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
|
||||
// std::cerr << "REQUESTS: m_requests: " << m_requests.size()
|
||||
// << " file_requests: " << m_file_requests.size() << std::endl;
|
||||
|
||||
torrent_info const& info = t->torrent_file();
|
||||
|
||||
if (m_requests.empty() || m_file_requests.empty())
|
||||
|
@ -484,16 +493,13 @@ namespace libtorrent
|
|||
size_type rs = size_type(in_range.piece) * info.piece_length() + in_range.start;
|
||||
size_type re = rs + in_range.length;
|
||||
size_type fs = size_type(front_request.piece) * info.piece_length() + front_request.start;
|
||||
/*
|
||||
size_type fe = fs + front_request.length;
|
||||
if (fs < rs || fe > re)
|
||||
{
|
||||
throw std::runtime_error("invalid range in HTTP response");
|
||||
}
|
||||
|
||||
// skip the http header and the blocks we've already read. The
|
||||
// http_body.begin is now in sync with the request at the front
|
||||
// of the request queue
|
||||
// TORRENT_ASSERT(in_range.start - int(m_piece.size()) <= front_request.start);
|
||||
std::cerr << "RANGE: r = (" << rs << ", " << re << " ) "
|
||||
"f = (" << fs << ", " << fe << ") "
|
||||
"file_index = " << file_index << " received_body = " << m_received_body << std::endl;
|
||||
*/
|
||||
|
||||
// the http response body consists of 3 parts
|
||||
// 1. the middle of a block or the ending of a block
|
||||
|
@ -501,14 +507,20 @@ namespace libtorrent
|
|||
// 3. the start of a block
|
||||
// in that order, these parts are parsed.
|
||||
|
||||
bool range_overlaps_request = in_range.start + in_range.length
|
||||
> front_request.start + int(m_piece.size());
|
||||
bool range_overlaps_request = re > fs + int(m_piece.size());
|
||||
|
||||
if (!range_overlaps_request)
|
||||
{
|
||||
// this means the end of the incoming request ends _before_ the
|
||||
// first expected byte (fs + m_piece.size())
|
||||
throw std::runtime_error("invalid range in HTTP response");
|
||||
}
|
||||
|
||||
// if the request is contained in the range (i.e. the entire request
|
||||
// fits in the range) we should not start a partial piece, since we soon
|
||||
// will receive enough to call incoming_piece() and pass the read buffer
|
||||
// directly (in the next loop below).
|
||||
if (range_overlaps_request && !range_contains(in_range, front_request))
|
||||
if (range_overlaps_request && !range_contains(in_range, front_request, info.piece_length()))
|
||||
{
|
||||
// the start of the next block to receive is stored
|
||||
// in m_piece. We need to append the rest of that
|
||||
|
@ -549,7 +561,7 @@ namespace libtorrent
|
|||
|
||||
// report all received blocks to the bittorrent engine
|
||||
while (!m_requests.empty()
|
||||
&& range_contains(in_range, m_requests.front())
|
||||
&& range_contains(in_range, m_requests.front(), info.piece_length())
|
||||
&& recv_buffer.left() >= m_requests.front().length)
|
||||
{
|
||||
peer_request r = m_requests.front();
|
||||
|
|
|
@ -273,13 +273,15 @@ boost::filesystem::path const& save_path)
|
|||
return (new_torrent.unique_ID);
|
||||
}
|
||||
catch (invalid_encoding&)
|
||||
{
|
||||
printf("invalid encoding...bad torrent\n");
|
||||
}
|
||||
{ RAISE_PTR(InvalidEncodingError, ""); }
|
||||
catch (invalid_handle&)
|
||||
{
|
||||
printf("invalid handle. something bad happened in libtorrent\n");
|
||||
}
|
||||
{ printf("invalid handle error on add_torrent"); }
|
||||
catch (invalid_torrent_file&)
|
||||
{ RAISE_PTR(InvalidTorrentError, ""); }
|
||||
catch (boost::filesystem::filesystem_error&)
|
||||
{ RAISE_PTR(FilesystemError, ""); }
|
||||
catch (duplicate_torrent&)
|
||||
{ RAISE_PTR(DuplicateTorrentError, "libtorrent reports this is a duplicate torrent"); }
|
||||
catch (...) {}
|
||||
}
|
||||
|
||||
|
@ -1999,35 +2001,6 @@ static PyObject *torrent_add_url_seed(PyObject *self, PyObject *args)
|
|||
Py_INCREF(Py_None); return Py_None;
|
||||
}
|
||||
|
||||
static PyObject *torrent_remap_files(PyObject *self, PyObject *args)
|
||||
{
|
||||
python_long unique_ID;
|
||||
PyObject *file_path_object;
|
||||
PyObject *file_size_object;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "iOO", &unique_ID, &file_path_object, &file_size_object))
|
||||
return NULL;
|
||||
long index = get_index_from_unique_ID(unique_ID);
|
||||
if (PyErr_Occurred())
|
||||
return NULL;
|
||||
|
||||
if (M_torrents->at(index).handle.is_valid()){
|
||||
|
||||
std::vector<std::pair<std::string, libtorrent::size_type> > remap_vector;
|
||||
for (long i = 0; i < PyList_Size(file_size_object); i++) {
|
||||
remap_vector.push_back(std::make_pair(PyString_AsString(PyList_GetItem(file_path_object, i)), PyInt_AsLong(PyList_GetItem(file_size_object, i))));
|
||||
}
|
||||
torrent_info t = M_torrents->at(index).handle.get_torrent_info();
|
||||
bool ret = t.remap_files(remap_vector);
|
||||
if (ret){
|
||||
printf("remap worked!\n");
|
||||
}
|
||||
else{
|
||||
printf("remap failed!\n");
|
||||
}
|
||||
}
|
||||
Py_INCREF(Py_None); return Py_None;
|
||||
}
|
||||
static PyObject *torrent_scrape_tracker(PyObject *self, PyObject *args)
|
||||
{
|
||||
python_long unique_ID;
|
||||
|
@ -2112,7 +2085,6 @@ static PyMethodDef deluge_core_methods[] =
|
|||
{"get_piece_info", torrent_get_piece_info, METH_VARARGS, "."},
|
||||
{"get_all_piece_info", torrent_get_all_piece_info, METH_VARARGS, "."},
|
||||
{"get_file_piece_range", torrent_get_file_piece_range, METH_VARARGS, "."},
|
||||
{"remap_files", torrent_remap_files, METH_VARARGS, "."},
|
||||
{"scrape_tracker", torrent_scrape_tracker, METH_VARARGS, "."},
|
||||
{NULL}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue