fix piece_picker piece-shuffle bug
[libtorrent.git] / src / torrent_handle.cpp
blobe9f179e325cb86dbbba2c00aea95e312959c4958
1 /*
3 Copyright (c) 2003, Arvid Norberg
4 All rights reserved.
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
8 are met:
10 * Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in
14 the documentation and/or other materials provided with the distribution.
15 * Neither the name of the author nor the names of its
16 contributors may be used to endorse or promote products derived
17 from this software without specific prior written permission.
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 POSSIBILITY OF SUCH DAMAGE.
33 #include "libtorrent/pch.hpp"
35 #include <ctime>
36 #include <iostream>
37 #include <fstream>
38 #include <iomanip>
39 #include <iterator>
40 #include <algorithm>
41 #include <set>
42 #include <cctype>
43 #include <algorithm>
45 #ifdef _MSC_VER
46 #pragma warning(push, 1)
47 #endif
49 #include <boost/lexical_cast.hpp>
50 #include <boost/filesystem/convenience.hpp>
51 #include <boost/optional.hpp>
52 #include <boost/bind.hpp>
54 #ifdef _MSC_VER
55 #pragma warning(pop)
56 #endif
58 #include "libtorrent/peer_id.hpp"
59 #include "libtorrent/bt_peer_connection.hpp"
60 #include "libtorrent/torrent_info.hpp"
61 #include "libtorrent/tracker_manager.hpp"
62 #include "libtorrent/bencode.hpp"
63 #include "libtorrent/hasher.hpp"
64 #include "libtorrent/entry.hpp"
65 #include "libtorrent/session.hpp"
66 #include "libtorrent/aux_/session_impl.hpp"
67 #include "libtorrent/invariant_check.hpp"
69 #if defined(_MSC_VER) && _MSC_VER < 1300
70 namespace std
72 using ::srand;
73 using ::isalnum;
75 #endif
77 using boost::bind;
78 using boost::mutex;
79 using libtorrent::aux::session_impl;
81 #ifdef BOOST_NO_EXCEPTIONS
83 #define TORRENT_FORWARD(call) \
84 boost::shared_ptr<torrent> t = m_torrent.lock(); \
85 if (!t) return; \
86 session_impl::mutex_t::scoped_lock l(t->session().m_mutex); \
87 t->call
89 #define TORRENT_FORWARD_RETURN(call, def) \
90 boost::shared_ptr<torrent> t = m_torrent.lock(); \
91 if (!t) return def; \
92 session_impl::mutex_t::scoped_lock l(t->session().m_mutex); \
93 return t->call
95 #define TORRENT_FORWARD_RETURN2(call, def) \
96 boost::shared_ptr<torrent> t = m_torrent.lock(); \
97 if (!t) return def; \
98 session_impl::mutex_t::scoped_lock l(t->session().m_mutex); \
99 t->call
101 #else
103 #define TORRENT_FORWARD(call) \
104 boost::shared_ptr<torrent> t = m_torrent.lock(); \
105 if (!t) throw_invalid_handle(); \
106 session_impl::mutex_t::scoped_lock l(t->session().m_mutex); \
107 t->call
109 #define TORRENT_FORWARD_RETURN(call, def) \
110 boost::shared_ptr<torrent> t = m_torrent.lock(); \
111 if (!t) throw_invalid_handle(); \
112 session_impl::mutex_t::scoped_lock l(t->session().m_mutex); \
113 return t->call
115 #define TORRENT_FORWARD_RETURN2(call, def) \
116 boost::shared_ptr<torrent> t = m_torrent.lock(); \
117 if (!t) throw_invalid_handle(); \
118 session_impl::mutex_t::scoped_lock l(t->session().m_mutex); \
119 t->call
121 #endif
123 namespace libtorrent
125 namespace fs = boost::filesystem;
127 namespace
129 #ifndef BOOST_NO_EXCEPTIONS
130 void throw_invalid_handle()
132 throw invalid_handle();
134 #endif
137 #ifndef NDEBUG
139 void torrent_handle::check_invariant() const
142 #endif
144 sha1_hash torrent_handle::info_hash() const
146 INVARIANT_CHECK;
147 const static sha1_hash empty;
148 TORRENT_FORWARD_RETURN(torrent_file().info_hash(), empty);
151 void torrent_handle::set_max_uploads(int max_uploads) const
153 INVARIANT_CHECK;
154 TORRENT_ASSERT(max_uploads >= 2 || max_uploads == -1);
155 TORRENT_FORWARD(set_max_uploads(max_uploads));
158 void torrent_handle::use_interface(const char* net_interface) const
160 INVARIANT_CHECK;
161 TORRENT_FORWARD(use_interface(net_interface));
164 void torrent_handle::set_max_connections(int max_connections) const
166 INVARIANT_CHECK;
167 TORRENT_ASSERT(max_connections >= 2 || max_connections == -1);
168 TORRENT_FORWARD(set_max_connections(max_connections));
171 void torrent_handle::set_peer_upload_limit(tcp::endpoint ip, int limit) const
173 INVARIANT_CHECK;
174 TORRENT_ASSERT(limit >= -1);
175 TORRENT_FORWARD(set_peer_upload_limit(ip, limit));
178 void torrent_handle::set_peer_download_limit(tcp::endpoint ip, int limit) const
180 INVARIANT_CHECK;
181 TORRENT_ASSERT(limit >= -1);
182 TORRENT_FORWARD(set_peer_download_limit(ip, limit));
185 void torrent_handle::set_upload_limit(int limit) const
187 INVARIANT_CHECK;
188 TORRENT_ASSERT(limit >= -1);
189 TORRENT_FORWARD(set_upload_limit(limit));
192 int torrent_handle::upload_limit() const
194 INVARIANT_CHECK;
195 TORRENT_FORWARD_RETURN(upload_limit(), 0);
198 void torrent_handle::set_download_limit(int limit) const
200 INVARIANT_CHECK;
201 TORRENT_ASSERT(limit >= -1);
202 TORRENT_FORWARD(set_download_limit(limit));
205 int torrent_handle::download_limit() const
207 INVARIANT_CHECK;
208 TORRENT_FORWARD_RETURN(download_limit(), 0);
211 void torrent_handle::move_storage(
212 fs::path const& save_path) const
214 INVARIANT_CHECK;
215 TORRENT_FORWARD(move_storage(save_path));
218 void torrent_handle::rename_file(int index, fs::path const& new_name) const
220 INVARIANT_CHECK;
221 TORRENT_FORWARD(rename_file(index, new_name.string()));
224 void torrent_handle::add_extension(
225 boost::function<boost::shared_ptr<torrent_plugin>(torrent*, void*)> const& ext
226 , void* userdata)
228 INVARIANT_CHECK;
229 TORRENT_FORWARD(add_extension(ext, userdata));
232 bool torrent_handle::has_metadata() const
234 INVARIANT_CHECK;
235 TORRENT_FORWARD_RETURN(valid_metadata(), false);
238 bool torrent_handle::is_seed() const
240 INVARIANT_CHECK;
241 TORRENT_FORWARD_RETURN(is_seed(), false);
244 bool torrent_handle::is_finished() const
246 INVARIANT_CHECK;
247 TORRENT_FORWARD_RETURN(is_finished(), false);
250 bool torrent_handle::is_paused() const
252 INVARIANT_CHECK;
253 TORRENT_FORWARD_RETURN(is_paused(), false);
256 void torrent_handle::pause() const
258 INVARIANT_CHECK;
259 TORRENT_FORWARD(pause());
262 void torrent_handle::save_resume_data() const
264 INVARIANT_CHECK;
265 TORRENT_FORWARD(save_resume_data());
268 void torrent_handle::force_recheck() const
270 INVARIANT_CHECK;
271 TORRENT_FORWARD(force_recheck());
274 void torrent_handle::resume() const
276 INVARIANT_CHECK;
277 TORRENT_FORWARD(resume());
280 bool torrent_handle::is_auto_managed() const
282 INVARIANT_CHECK;
283 TORRENT_FORWARD_RETURN(is_auto_managed(), true);
286 void torrent_handle::auto_managed(bool m) const
288 INVARIANT_CHECK;
289 TORRENT_FORWARD(auto_managed(m));
292 int torrent_handle::queue_position() const
294 INVARIANT_CHECK;
295 TORRENT_FORWARD_RETURN(queue_position(), -1);
298 void torrent_handle::queue_position_up() const
300 INVARIANT_CHECK;
301 TORRENT_FORWARD(set_queue_position(t->queue_position() - 1));
304 void torrent_handle::queue_position_down() const
306 INVARIANT_CHECK;
307 TORRENT_FORWARD(set_queue_position(t->queue_position() + 1));
310 void torrent_handle::queue_position_top() const
312 INVARIANT_CHECK;
313 TORRENT_FORWARD(set_queue_position(0));
316 void torrent_handle::queue_position_bottom() const
318 INVARIANT_CHECK;
319 TORRENT_FORWARD(set_queue_position((std::numeric_limits<int>::max)()));
322 void torrent_handle::clear_error() const
324 INVARIANT_CHECK;
325 TORRENT_FORWARD(clear_error());
328 void torrent_handle::set_tracker_login(std::string const& name
329 , std::string const& password) const
331 INVARIANT_CHECK;
332 TORRENT_FORWARD(set_tracker_login(name, password));
335 void torrent_handle::file_progress(std::vector<float>& progress) const
337 INVARIANT_CHECK;
338 TORRENT_FORWARD(file_progress(progress));
341 void torrent_handle::file_progress(std::vector<size_type>& progress) const
343 INVARIANT_CHECK;
344 TORRENT_FORWARD(file_progress(progress));
347 torrent_status torrent_handle::status() const
349 INVARIANT_CHECK;
350 TORRENT_FORWARD_RETURN(status(), torrent_status());
353 void torrent_handle::set_sequential_download(bool sd) const
355 INVARIANT_CHECK;
356 TORRENT_FORWARD(set_sequential_download(sd));
359 bool torrent_handle::is_sequential_download() const
361 INVARIANT_CHECK;
362 TORRENT_FORWARD_RETURN(is_sequential_download(), false);
365 std::string torrent_handle::name() const
367 INVARIANT_CHECK;
368 TORRENT_FORWARD_RETURN(name(), "");
371 void torrent_handle::piece_availability(std::vector<int>& avail) const
373 INVARIANT_CHECK;
374 TORRENT_FORWARD(piece_availability(avail));
377 void torrent_handle::piece_priority(int index, int priority) const
379 INVARIANT_CHECK;
380 TORRENT_FORWARD(set_piece_priority(index, priority));
383 int torrent_handle::piece_priority(int index) const
385 INVARIANT_CHECK;
386 TORRENT_FORWARD_RETURN(piece_priority(index), 0);
389 void torrent_handle::prioritize_pieces(std::vector<int> const& pieces) const
391 INVARIANT_CHECK;
392 TORRENT_FORWARD(prioritize_pieces(pieces));
395 std::vector<int> torrent_handle::piece_priorities() const
397 INVARIANT_CHECK;
398 std::vector<int> ret;
399 TORRENT_FORWARD_RETURN2(piece_priorities(ret), ret);
400 return ret;
403 void torrent_handle::file_priority(int index, int priority) const
405 INVARIANT_CHECK;
406 TORRENT_FORWARD(set_file_priority(index, priority));
409 int torrent_handle::file_priority(int index) const
411 INVARIANT_CHECK;
412 TORRENT_FORWARD_RETURN(file_priority(index), 0);
415 void torrent_handle::prioritize_files(std::vector<int> const& files) const
417 INVARIANT_CHECK;
418 TORRENT_FORWARD(prioritize_files(files));
421 std::vector<int> torrent_handle::file_priorities() const
423 INVARIANT_CHECK;
424 std::vector<int> ret;
425 TORRENT_FORWARD_RETURN2(file_priorities(ret), ret);
426 return ret;
429 // ============ start deprecation ===============
431 void torrent_handle::filter_piece(int index, bool filter) const
433 INVARIANT_CHECK;
434 TORRENT_FORWARD(filter_piece(index, filter));
437 void torrent_handle::filter_pieces(std::vector<bool> const& pieces) const
439 INVARIANT_CHECK;
440 TORRENT_FORWARD(filter_pieces(pieces));
443 bool torrent_handle::is_piece_filtered(int index) const
445 INVARIANT_CHECK;
446 TORRENT_FORWARD_RETURN(is_piece_filtered(index), false);
449 std::vector<bool> torrent_handle::filtered_pieces() const
451 INVARIANT_CHECK;
452 std::vector<bool> ret;
453 TORRENT_FORWARD_RETURN2(filtered_pieces(ret), ret);
454 return ret;
457 void torrent_handle::filter_files(std::vector<bool> const& files) const
459 INVARIANT_CHECK;
460 TORRENT_FORWARD(filter_files(files));
463 // ============ end deprecation ===============
466 std::vector<announce_entry> const& torrent_handle::trackers() const
468 INVARIANT_CHECK;
469 const static std::vector<announce_entry> empty;
470 TORRENT_FORWARD_RETURN(trackers(), empty);
473 void torrent_handle::add_url_seed(std::string const& url) const
475 INVARIANT_CHECK;
476 TORRENT_FORWARD(add_url_seed(url));
479 void torrent_handle::remove_url_seed(std::string const& url) const
481 INVARIANT_CHECK;
482 TORRENT_FORWARD(remove_url_seed(url));
485 std::set<std::string> torrent_handle::url_seeds() const
487 INVARIANT_CHECK;
488 const static std::set<std::string> empty;
489 TORRENT_FORWARD_RETURN(url_seeds(), empty);
492 void torrent_handle::replace_trackers(
493 std::vector<announce_entry> const& urls) const
495 INVARIANT_CHECK;
496 TORRENT_FORWARD(replace_trackers(urls));
499 torrent_info const& torrent_handle::get_torrent_info() const
501 INVARIANT_CHECK;
502 #ifdef BOOST_NO_EXCEPTIONS
503 const static torrent_info empty;
504 #endif
505 boost::shared_ptr<torrent> t = m_torrent.lock();
506 if (!t)
507 #ifdef BOOST_NO_EXCEPTIONS
508 return empty;
509 #else
510 throw_invalid_handle();
511 #endif
512 session_impl::mutex_t::scoped_lock l(t->session().m_mutex);
513 if (!t->valid_metadata())
514 #ifdef BOOST_NO_EXCEPTIONS
515 return empty;
516 #else
517 throw_invalid_handle();
518 #endif
519 return t->torrent_file();
522 bool torrent_handle::is_valid() const
524 INVARIANT_CHECK;
525 return !m_torrent.expired();
528 entry torrent_handle::write_resume_data() const
530 INVARIANT_CHECK;
532 entry ret(entry::dictionary_t);
533 TORRENT_FORWARD(write_resume_data(ret));
534 t->filesystem().write_resume_data(ret);
536 return ret;
540 fs::path torrent_handle::save_path() const
542 INVARIANT_CHECK;
543 TORRENT_FORWARD_RETURN(save_path(), fs::path());
546 void torrent_handle::connect_peer(tcp::endpoint const& adr, int source) const
548 INVARIANT_CHECK;
550 boost::shared_ptr<torrent> t = m_torrent.lock();
551 if (!t)
552 #ifdef BOOST_NO_EXCEPTIONS
553 return;
554 #else
555 throw_invalid_handle();
556 #endif
557 session_impl::mutex_t::scoped_lock l(t->session().m_mutex);
559 peer_id id;
560 std::fill(id.begin(), id.end(), 0);
561 t->get_policy().peer_from_tracker(adr, id, source, 0);
564 void torrent_handle::force_reannounce(
565 boost::posix_time::time_duration duration) const
567 INVARIANT_CHECK;
568 TORRENT_FORWARD(force_tracker_request(time_now() + seconds(duration.total_seconds())));
571 void torrent_handle::force_reannounce() const
573 INVARIANT_CHECK;
574 TORRENT_FORWARD(force_tracker_request());
577 void torrent_handle::scrape_tracker() const
579 INVARIANT_CHECK;
580 TORRENT_FORWARD(scrape_tracker());
583 void torrent_handle::set_ratio(float ratio) const
585 INVARIANT_CHECK;
587 TORRENT_ASSERT(ratio >= 0.f);
588 if (ratio < 1.f && ratio > 0.f)
589 ratio = 1.f;
590 TORRENT_FORWARD(set_ratio(ratio));
593 #ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
594 void torrent_handle::resolve_countries(bool r)
596 INVARIANT_CHECK;
597 TORRENT_FORWARD(resolve_countries(r));
600 bool torrent_handle::resolve_countries() const
602 INVARIANT_CHECK;
603 TORRENT_FORWARD_RETURN(resolving_countries(), false);
605 #endif
607 void torrent_handle::get_full_peer_list(std::vector<peer_list_entry>& v) const
609 INVARIANT_CHECK;
610 TORRENT_FORWARD(get_full_peer_list(v));
613 void torrent_handle::get_peer_info(std::vector<peer_info>& v) const
615 INVARIANT_CHECK;
616 TORRENT_FORWARD(get_peer_info(v));
619 void torrent_handle::get_download_queue(std::vector<partial_piece_info>& queue) const
621 INVARIANT_CHECK;
622 TORRENT_FORWARD(get_download_queue(queue));