AUTO_LT_SYNC
[tore.git] / libtorrent / src / torrent.cpp
blob1ecede4832d7e903dc396483476c27c9b95c9b5b
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 <numeric>
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/bind.hpp>
52 #include <boost/thread/mutex.hpp>
54 #ifdef _MSC_VER
55 #pragma warning(pop)
56 #endif
58 #include "libtorrent/torrent_handle.hpp"
59 #include "libtorrent/session.hpp"
60 #include "libtorrent/torrent_info.hpp"
61 #include "libtorrent/tracker_manager.hpp"
62 #include "libtorrent/parse_url.hpp"
63 #include "libtorrent/bencode.hpp"
64 #include "libtorrent/hasher.hpp"
65 #include "libtorrent/entry.hpp"
66 #include "libtorrent/peer.hpp"
67 #include "libtorrent/bt_peer_connection.hpp"
68 #include "libtorrent/web_peer_connection.hpp"
69 #include "libtorrent/peer_id.hpp"
70 #include "libtorrent/alert.hpp"
71 #include "libtorrent/identify_client.hpp"
72 #include "libtorrent/alert_types.hpp"
73 #include "libtorrent/extensions.hpp"
74 #include "libtorrent/aux_/session_impl.hpp"
75 #include "libtorrent/instantiate_connection.hpp"
76 #include "libtorrent/assert.hpp"
78 using namespace libtorrent;
79 using boost::tuples::tuple;
80 using boost::tuples::get;
81 using boost::tuples::make_tuple;
82 using boost::bind;
83 using boost::mutex;
84 using libtorrent::aux::session_impl;
86 namespace
89 enum
91 // wait 60 seconds before retrying a failed tracker
92 tracker_retry_delay_min = 60
93 // when tracker_failed_max trackers
94 // has failed, wait 10 minutes instead
95 , tracker_retry_delay_max = 10 * 60
96 , tracker_failed_max = 5
99 struct find_peer_by_ip
101 find_peer_by_ip(tcp::endpoint const& a, const torrent* t)
102 : ip(a)
103 , tor(t)
104 { TORRENT_ASSERT(t != 0); }
106 bool operator()(session_impl::connection_map::value_type const& c) const
108 tcp::endpoint const& sender = c->remote();
109 if (sender.address() != ip.address()) return false;
110 if (tor != c->associated_torrent().lock().get()) return false;
111 return true;
114 tcp::endpoint const& ip;
115 torrent const* tor;
118 struct peer_by_id
120 peer_by_id(const peer_id& i): pid(i) {}
122 bool operator()(session_impl::connection_map::value_type const& p) const
124 if (p->pid() != pid) return false;
125 // have a special case for all zeros. We can have any number
126 // of peers with that pid, since it's used to indicate no pid.
127 if (std::count(pid.begin(), pid.end(), 0) == 20) return false;
128 return true;
131 peer_id const& pid;
135 namespace libtorrent
138 torrent::torrent(
139 session_impl& ses
140 , boost::intrusive_ptr<torrent_info> tf
141 , fs::path const& save_path
142 , tcp::endpoint const& net_interface
143 , storage_mode_t storage_mode
144 , int block_size
145 , storage_constructor_type sc
146 , bool paused
147 , std::vector<char>* resume_data
148 , int seq
149 , bool auto_managed)
150 : m_policy(this)
151 , m_active_time(seconds(0))
152 , m_seeding_time(seconds(0))
153 , m_total_uploaded(0)
154 , m_total_downloaded(0)
155 , m_started(time_now())
156 , m_last_scrape(min_time())
157 , m_torrent_file(tf)
158 , m_storage(0)
159 , m_next_tracker_announce(time_now())
160 , m_host_resolver(ses.m_io_service)
161 , m_lsd_announce_timer(ses.m_io_service)
162 , m_tracker_timer(ses.m_io_service)
163 #ifndef TORRENT_DISABLE_DHT
164 , m_last_dht_announce(time_now() - minutes(15))
165 #endif
166 , m_ses(ses)
167 , m_picker(new piece_picker())
168 , m_trackers(m_torrent_file->trackers())
169 , m_total_failed_bytes(0)
170 , m_total_redundant_bytes(0)
171 , m_net_interface(net_interface.address(), 0)
172 , m_save_path(complete(save_path))
173 , m_storage_mode(storage_mode)
174 , m_state(torrent_status::queued_for_checking)
175 , m_settings(ses.settings())
176 , m_storage_constructor(sc)
177 , m_progress(0.f)
178 , m_ratio(0.f)
179 , m_max_uploads((std::numeric_limits<int>::max)())
180 , m_num_uploads(0)
181 , m_max_connections((std::numeric_limits<int>::max)())
182 , m_block_size((std::min)(block_size, tf->piece_length()))
183 , m_complete(-1)
184 , m_incomplete(-1)
185 , m_deficit_counter(0)
186 , m_duration(1800)
187 , m_sequence_number(seq)
188 , m_last_working_tracker(-1)
189 , m_currently_trying_tracker(0)
190 , m_failed_trackers(0)
191 , m_time_scaler(0)
192 , m_abort(false)
193 , m_paused(paused)
194 , m_auto_managed(auto_managed)
195 #ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
196 , m_resolving_country(false)
197 , m_resolve_countries(false)
198 #endif
199 , m_sequential_download(false)
200 , m_got_tracker_response(false)
201 , m_connections_initialized(true)
202 , m_has_incoming(false)
203 , m_files_checked(false)
204 , m_announcing(false)
205 , m_start_sent(false)
206 , m_complete_sent(false)
208 if (resume_data) m_resume_data.swap(*resume_data);
210 #ifndef TORRENT_DISABLE_ENCRYPTION
211 hasher h;
212 h.update("req2", 4);
213 h.update((char*)&tf->info_hash()[0], 20);
214 m_obfuscated_hash = h.final();
215 #endif
218 torrent::torrent(
219 session_impl& ses
220 , char const* tracker_url
221 , sha1_hash const& info_hash
222 , char const* name
223 , fs::path const& save_path
224 , tcp::endpoint const& net_interface
225 , storage_mode_t storage_mode
226 , int block_size
227 , storage_constructor_type sc
228 , bool paused
229 , std::vector<char>* resume_data
230 , int seq
231 , bool auto_managed)
232 : m_policy(this)
233 , m_active_time(seconds(0))
234 , m_seeding_time(seconds(0))
235 , m_total_uploaded(0)
236 , m_total_downloaded(0)
237 , m_started(time_now())
238 , m_last_scrape(min_time())
239 , m_torrent_file(new torrent_info(info_hash))
240 , m_storage(0)
241 , m_next_tracker_announce(time_now())
242 , m_host_resolver(ses.m_io_service)
243 , m_lsd_announce_timer(ses.m_io_service)
244 , m_tracker_timer(ses.m_io_service)
245 #ifndef TORRENT_DISABLE_DHT
246 , m_last_dht_announce(time_now() - minutes(15))
247 #endif
248 , m_ses(ses)
249 , m_picker(new piece_picker())
250 , m_total_failed_bytes(0)
251 , m_total_redundant_bytes(0)
252 , m_net_interface(net_interface.address(), 0)
253 , m_save_path(complete(save_path))
254 , m_storage_mode(storage_mode)
255 , m_state(torrent_status::queued_for_checking)
256 , m_settings(ses.settings())
257 , m_storage_constructor(sc)
258 , m_progress(0.f)
259 , m_ratio(0.f)
260 , m_max_uploads((std::numeric_limits<int>::max)())
261 , m_num_uploads(0)
262 , m_max_connections((std::numeric_limits<int>::max)())
263 , m_block_size(block_size)
264 , m_complete(-1)
265 , m_incomplete(-1)
266 , m_deficit_counter(0)
267 , m_duration(1800)
268 , m_sequence_number(seq)
269 , m_last_working_tracker(-1)
270 , m_currently_trying_tracker(0)
271 , m_failed_trackers(0)
272 , m_time_scaler(0)
273 , m_abort(false)
274 , m_paused(paused)
275 , m_auto_managed(auto_managed)
276 #ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
277 , m_resolving_country(false)
278 , m_resolve_countries(false)
279 #endif
280 , m_sequential_download(false)
281 , m_got_tracker_response(false)
282 , m_connections_initialized(false)
283 , m_has_incoming(false)
284 , m_files_checked(false)
285 , m_announcing(false)
286 , m_start_sent(false)
287 , m_complete_sent(false)
289 if (resume_data) m_resume_data.swap(*resume_data);
291 #ifndef TORRENT_DISABLE_ENCRYPTION
292 hasher h;
293 h.update("req2", 4);
294 h.update((char*)&info_hash[0], 20);
295 m_obfuscated_hash = h.final();
296 #endif
298 #ifndef NDEBUG
299 m_files_checked = false;
300 #endif
301 INVARIANT_CHECK;
303 if (name) m_name.reset(new std::string(name));
305 if (tracker_url)
307 m_trackers.push_back(announce_entry(tracker_url));
308 m_torrent_file->add_tracker(tracker_url);
312 void torrent::start()
314 if (!m_resume_data.empty())
316 if (lazy_bdecode(&m_resume_data[0], &m_resume_data[0]
317 + m_resume_data.size(), m_resume_entry) != 0)
319 std::vector<char>().swap(m_resume_data);
320 if (m_ses.m_alerts.should_post<fastresume_rejected_alert>())
322 m_ses.m_alerts.post_alert(fastresume_rejected_alert(get_handle(), "parse failed"));
323 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
324 (*m_ses.m_logger) << "fastresume data for "
325 << torrent_file().name() << " rejected: parse failed\n";
326 #endif
331 // we need to start announcing since we don't have any
332 // metadata. To receive peers to ask for it.
333 if (m_torrent_file->is_valid()) init();
334 else
336 set_state(torrent_status::downloading_metadata);
337 if (!m_trackers.empty()) start_announcing();
340 if (m_abort) return;
343 #ifndef TORRENT_DISABLE_DHT
344 bool torrent::should_announce_dht() const
346 if (m_ses.m_listen_sockets.empty()) return false;
348 if (!m_ses.m_dht) return false;
349 if (m_torrent_file->is_valid() && !m_files_checked) return false;
351 // don't announce private torrents
352 if (m_torrent_file->is_valid() && m_torrent_file->priv()) return false;
353 if (m_trackers.empty()) return true;
355 return m_failed_trackers > 0 || !m_ses.settings().use_dht_as_fallback;
357 #endif
359 torrent::~torrent()
361 // The invariant can't be maintained here, since the torrent
362 // is being destructed, all weak references to it have been
363 // reset, which means that all its peers already have an
364 // invalidated torrent pointer (so it cannot be verified to be correct)
366 // i.e. the invariant can only be maintained if all connections have
367 // been closed by the time the torrent is destructed. And they are
368 // supposed to be closed. So we can still do the invariant check.
370 TORRENT_ASSERT(m_connections.empty());
372 INVARIANT_CHECK;
374 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
375 for (peer_iterator i = m_connections.begin();
376 i != m_connections.end(); ++i)
378 (*(*i)->m_logger) << "*** DESTRUCTING TORRENT\n";
380 #endif
382 TORRENT_ASSERT(m_abort);
383 if (!m_connections.empty())
384 disconnect_all();
387 peer_request torrent::to_req(piece_block const& p)
389 int block_offset = p.block_index * m_block_size;
390 int block_size = (std::min)(torrent_file().piece_size(
391 p.piece_index) - block_offset, m_block_size);
392 TORRENT_ASSERT(block_size > 0);
393 TORRENT_ASSERT(block_size <= m_block_size);
395 peer_request r;
396 r.piece = p.piece_index;
397 r.start = block_offset;
398 r.length = block_size;
399 return r;
402 std::string torrent::name() const
404 if (valid_metadata()) return m_torrent_file->name();
405 if (m_name) return *m_name;
406 return "";
409 #ifndef TORRENT_DISABLE_EXTENSIONS
411 void torrent::add_extension(boost::shared_ptr<torrent_plugin> ext)
413 m_extensions.push_back(ext);
416 void torrent::add_extension(boost::function<boost::shared_ptr<torrent_plugin>(torrent*, void*)> const& ext
417 , void* userdata)
419 boost::shared_ptr<torrent_plugin> tp(ext(this, userdata));
420 if (!tp) return;
422 add_extension(tp);
424 for (peer_iterator i = m_connections.begin();
425 i != m_connections.end(); ++i)
427 peer_connection* p = *i;
428 boost::shared_ptr<peer_plugin> pp(tp->new_connection(p));
429 if (pp) p->add_extension(pp);
432 // if files are checked for this torrent, call the extension
433 // to let it initialize itself
434 if (m_connections_initialized)
435 tp->on_files_checked();
438 #endif
440 // this may not be called from a constructor because of the call to
441 // shared_from_this()
442 void torrent::init()
444 TORRENT_ASSERT(m_torrent_file->is_valid());
445 TORRENT_ASSERT(m_torrent_file->num_files() > 0);
446 TORRENT_ASSERT(m_torrent_file->total_size() >= 0);
448 m_file_priority.clear();
449 m_file_priority.resize(m_torrent_file->num_files(), 1);
451 m_block_size = (std::min)(m_block_size, m_torrent_file->piece_length());
453 if (m_torrent_file->num_pieces()
454 > piece_picker::max_pieces)
456 m_error = "too many pieces in torrent";
457 pause();
460 // the shared_from_this() will create an intentional
461 // cycle of ownership, se the hpp file for description.
462 m_owning_storage = new piece_manager(shared_from_this(), m_torrent_file
463 , m_save_path, m_ses.m_files, m_ses.m_disk_thread, m_storage_constructor
464 , m_storage_mode);
465 m_storage = m_owning_storage.get();
466 m_picker->init((std::max)(m_torrent_file->piece_length() / m_block_size, 1)
467 , int((m_torrent_file->total_size()+m_block_size-1)/m_block_size));
469 std::vector<std::string> const& url_seeds = m_torrent_file->url_seeds();
470 std::copy(url_seeds.begin(), url_seeds.end(), std::inserter(m_web_seeds
471 , m_web_seeds.begin()));
473 set_state(torrent_status::queued_for_checking);
475 if (m_resume_entry.type() == lazy_entry::dict_t)
477 char const* error = 0;
478 if (m_resume_entry.dict_find_string_value("file-format") != "libtorrent resume file")
479 error = "invalid file format tag";
481 std::string info_hash = m_resume_entry.dict_find_string_value("info-hash");
482 if (!error && info_hash.empty())
483 error = "missing info-hash";
485 if (!error && sha1_hash(info_hash) != m_torrent_file->info_hash())
486 error = "mismatching info-hash";
488 if (error && m_ses.m_alerts.should_post<fastresume_rejected_alert>())
490 m_ses.m_alerts.post_alert(fastresume_rejected_alert(get_handle(), error));
491 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
492 (*m_ses.m_logger) << "fastresume data for "
493 << torrent_file().name() << " rejected: "
494 << error << "\n";
495 #endif
498 if (error)
500 std::vector<char>().swap(m_resume_data);
501 lazy_entry().swap(m_resume_entry);
503 else
505 read_resume_data(m_resume_entry);
509 TORRENT_ASSERT(m_block_size > 0);
510 int file = 0;
511 for (file_storage::iterator i = m_torrent_file->files().begin()
512 , end(m_torrent_file->files().end()); i != end; ++i, ++file)
514 if (!i->pad_file) continue;
516 peer_request pr = m_torrent_file->map_file(file, 0, m_torrent_file->file_at(file).size);
517 int off = pr.start % m_block_size;
518 if (off != 0) { pr.length -= m_block_size - off; pr.start += m_block_size - off; }
519 TORRENT_ASSERT((pr.start % m_block_size) == 0);
521 int blocks_per_piece = m_torrent_file->piece_length() / m_block_size;
522 piece_block pb(pr.piece, pr.start / m_block_size);
523 for (; pr.length >= m_block_size; pr.length -= m_block_size, ++pb.block_index)
525 if (pb.block_index == blocks_per_piece) { pb.block_index = 0; ++pb.piece_index; }
526 m_picker->mark_as_finished(pb, 0);
530 m_storage->async_check_fastresume(&m_resume_entry
531 , bind(&torrent::on_resume_data_checked
532 , shared_from_this(), _1, _2));
535 void torrent::on_resume_data_checked(int ret, disk_io_job const& j)
537 session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
539 if (ret == piece_manager::fatal_disk_error)
541 if (m_ses.m_alerts.should_post<file_error_alert>())
543 m_ses.m_alerts.post_alert(file_error_alert(j.error_file, get_handle(), j.str));
544 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
545 (*m_ses.m_logger) << time_now_string() << ": fatal disk error ["
546 " error: " << j.str <<
547 " torrent: " << torrent_file().name() <<
548 " ]\n";
549 #endif
551 m_error = j.str;
552 pause();
554 std::vector<char>().swap(m_resume_data);
555 lazy_entry().swap(m_resume_entry);
557 return;
560 if (m_resume_entry.type() == lazy_entry::dict_t)
562 // parse out "peers" from the resume data and add them to the peer list
563 if (lazy_entry const* peers_entry = m_resume_entry.dict_find_list("peers"))
565 peer_id id(0);
567 for (int i = 0; i < peers_entry->list_size(); ++i)
569 lazy_entry const* e = peers_entry->list_at(i);
570 if (e->type() != lazy_entry::dict_t) continue;
571 std::string ip = e->dict_find_string_value("ip");
572 int port = e->dict_find_int_value("port");
573 if (ip.empty() || port == 0) continue;
574 tcp::endpoint a(address::from_string(ip), (unsigned short)port);
575 m_policy.peer_from_tracker(a, id, peer_info::resume_data, 0);
579 // parse out "banned_peers" and add them as banned
580 if (lazy_entry const* banned_peers_entry = m_resume_entry.dict_find_list("banned_peers"))
582 peer_id id(0);
584 for (int i = 0; i < banned_peers_entry->list_size(); ++i)
586 lazy_entry const* e = banned_peers_entry->list_at(i);
587 if (e->type() != lazy_entry::dict_t) continue;
588 std::string ip = e->dict_find_string_value("ip");
589 int port = e->dict_find_int_value("port");
590 if (ip.empty() || port == 0) continue;
591 tcp::endpoint a(address::from_string(ip), (unsigned short)port);
592 policy::peer* p = m_policy.peer_from_tracker(a, id, peer_info::resume_data, 0);
593 if (p) p->banned = true;
598 bool fastresume_rejected = !j.str.empty();
600 if (fastresume_rejected && m_ses.m_alerts.should_post<fastresume_rejected_alert>())
602 m_ses.m_alerts.post_alert(fastresume_rejected_alert(get_handle(), j.str));
603 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
604 (*m_ses.m_logger) << "fastresume data for "
605 << torrent_file().name() << " rejected: "
606 << j.str << "\n";
607 #endif
610 if (ret == 0)
612 // there are either no files for this torrent
613 // or the resume_data was accepted
615 if (!fastresume_rejected && m_resume_entry.type() == lazy_entry::dict_t)
617 // parse have bitmask
618 lazy_entry const* pieces = m_resume_entry.dict_find("pieces");
619 if (pieces && pieces->type() == lazy_entry::string_t
620 && int(pieces->string_length()) == m_torrent_file->num_pieces())
622 char const* pieces_str = pieces->string_ptr();
623 for (int i = 0, end(pieces->string_length()); i < end; ++i)
625 if ((pieces_str[i] & 1) == 0) continue;
626 m_picker->we_have(i);
630 // parse unfinished pieces
631 int num_blocks_per_piece =
632 static_cast<int>(torrent_file().piece_length()) / block_size();
634 if (lazy_entry const* unfinished_ent = m_resume_entry.dict_find_list("unfinished"))
636 for (int i = 0; i < unfinished_ent->list_size(); ++i)
638 lazy_entry const* e = unfinished_ent->list_at(i);
639 if (e->type() != lazy_entry::dict_t) continue;
640 int piece = e->dict_find_int_value("piece", -1);
641 if (piece < 0 || piece > torrent_file().num_pieces()) continue;
643 if (m_picker->have_piece(piece))
644 m_picker->we_dont_have(piece);
646 std::string bitmask = e->dict_find_string_value("bitmask");
647 if (bitmask.empty()) continue;
649 const int num_bitmask_bytes = (std::max)(num_blocks_per_piece / 8, 1);
650 if ((int)bitmask.size() != num_bitmask_bytes) continue;
651 for (int j = 0; j < num_bitmask_bytes; ++j)
653 unsigned char bits = bitmask[j];
654 int num_bits = (std::min)(num_blocks_per_piece - j*8, 8);
655 for (int k = 0; k < num_bits; ++k)
657 const int bit = j * 8 + k;
658 if (bits & (1 << k))
660 m_picker->mark_as_finished(piece_block(piece, bit), 0);
661 if (m_picker->is_piece_finished(piece))
662 async_verify_piece(piece, bind(&torrent::piece_finished
663 , shared_from_this(), piece, _1));
671 files_checked();
673 else
675 // either the fastresume data was rejected or there are
676 // some files
677 if (!is_torrent_paused() || is_auto_managed())
678 m_ses.check_torrent(shared_from_this());
681 std::vector<char>().swap(m_resume_data);
682 lazy_entry().swap(m_resume_entry);
685 void torrent::force_recheck()
687 if (m_state == torrent_status::checking_files
688 || m_state == torrent_status::queued_for_checking)
689 return;
691 disconnect_all();
693 m_owning_storage->async_release_files();
694 m_owning_storage = new piece_manager(shared_from_this(), m_torrent_file
695 , m_save_path, m_ses.m_files, m_ses.m_disk_thread, m_storage_constructor
696 , m_storage_mode);
697 m_storage = m_owning_storage.get();
698 if (!m_picker) m_picker.reset(new piece_picker());
699 m_picker->init(m_torrent_file->piece_length() / m_block_size
700 , int((m_torrent_file->total_size()+m_block_size-1)/m_block_size));
701 // assume that we don't have anything
702 m_files_checked = false;
703 set_state(torrent_status::queued_for_checking);
705 if (m_auto_managed)
706 set_queue_position((std::numeric_limits<int>::max)());
708 std::vector<char>().swap(m_resume_data);
709 lazy_entry().swap(m_resume_entry);
710 m_storage->async_check_fastresume(&m_resume_entry
711 , bind(&torrent::on_force_recheck
712 , shared_from_this(), _1, _2));
715 void torrent::on_force_recheck(int ret, disk_io_job const& j)
717 session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
719 if (ret == piece_manager::fatal_disk_error)
721 if (m_ses.m_alerts.should_post<file_error_alert>())
723 m_ses.m_alerts.post_alert(file_error_alert(j.error_file, get_handle(), j.str));
724 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
725 (*m_ses.m_logger) << time_now_string() << ": fatal disk error ["
726 " error: " << j.str <<
727 " torrent: " << torrent_file().name() <<
728 " ]\n";
729 #endif
731 m_error = j.str;
732 pause();
733 return;
735 if (!is_torrent_paused() || is_auto_managed())
736 m_ses.check_torrent(shared_from_this());
739 void torrent::start_checking()
741 set_state(torrent_status::checking_files);
743 m_storage->async_check_files(bind(
744 &torrent::on_piece_checked
745 , shared_from_this(), _1, _2));
748 void torrent::on_piece_checked(int ret, disk_io_job const& j)
750 session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
752 if (ret == piece_manager::disk_check_aborted)
754 m_error = "aborted";
755 m_ses.done_checking(shared_from_this());
756 return;
758 if (ret == piece_manager::fatal_disk_error)
760 if (m_ses.m_alerts.should_post<file_error_alert>())
762 m_ses.m_alerts.post_alert(file_error_alert(j.error_file, get_handle(), j.str));
763 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
764 (*m_ses.m_logger) << time_now_string() << ": fatal disk error ["
765 " error: " << j.str <<
766 " torrent: " << torrent_file().name() <<
767 " ]\n";
768 #endif
770 m_error = j.str;
771 pause();
772 m_ses.done_checking(shared_from_this());
773 return;
776 m_progress = j.piece / float(torrent_file().num_pieces());
778 TORRENT_ASSERT(m_picker);
779 if (j.offset >= 0 && !m_picker->have_piece(j.offset))
780 m_picker->we_have(j.offset);
782 // we're not done checking yet
783 // this handler will be called repeatedly until
784 // we're done, or encounter a failure
785 if (ret == piece_manager::need_full_check) return;
787 if (!m_abort) m_ses.done_checking(shared_from_this());
788 files_checked();
791 void torrent::use_interface(const char* net_interface)
793 INVARIANT_CHECK;
795 m_net_interface = tcp::endpoint(address::from_string(net_interface), 0);
798 void torrent::on_tracker_announce_disp(boost::weak_ptr<torrent> p
799 , error_code const& e)
801 if (e) return;
802 boost::shared_ptr<torrent> t = p.lock();
803 if (!t) return;
804 t->on_tracker_announce();
807 void torrent::on_tracker_announce()
809 session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
811 if (m_abort) return;
812 announce_with_tracker();
815 void torrent::on_lsd_announce_disp(boost::weak_ptr<torrent> p
816 , error_code const& e)
818 if (e) return;
819 boost::shared_ptr<torrent> t = p.lock();
820 if (!t) return;
821 t->on_lsd_announce();
824 void torrent::on_lsd_announce()
826 session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
828 if (m_abort) return;
830 TORRENT_ASSERT(!m_torrent_file->priv());
831 if (m_torrent_file->is_valid() && m_torrent_file->priv())
832 return;
834 if (is_paused()) return;
836 boost::weak_ptr<torrent> self(shared_from_this());
838 error_code ec;
840 // announce on local network every 5 minutes
841 m_lsd_announce_timer.expires_from_now(minutes(5), ec);
842 m_lsd_announce_timer.async_wait(
843 bind(&torrent::on_lsd_announce_disp, self, _1));
845 // announce with the local discovery service
846 m_ses.announce_lsd(m_torrent_file->info_hash());
848 #ifndef TORRENT_DISABLE_DHT
849 if (!m_ses.m_dht) return;
850 ptime now = time_now();
851 if (should_announce_dht() && now - m_last_dht_announce > minutes(14))
853 m_last_dht_announce = now;
854 m_ses.m_dht->announce(m_torrent_file->info_hash()
855 , m_ses.m_listen_sockets.front().external_port
856 , bind(&torrent::on_dht_announce_response_disp, self, _1));
858 #endif
861 #ifndef TORRENT_DISABLE_DHT
863 void torrent::on_dht_announce_response_disp(boost::weak_ptr<libtorrent::torrent> t
864 , std::vector<tcp::endpoint> const& peers)
866 boost::shared_ptr<libtorrent::torrent> tor = t.lock();
867 if (!tor) return;
868 tor->on_dht_announce_response(peers);
871 void torrent::on_dht_announce_response(std::vector<tcp::endpoint> const& peers)
873 if (peers.empty()) return;
875 if (m_ses.m_alerts.should_post<dht_reply_alert>())
877 m_ses.m_alerts.post_alert(dht_reply_alert(
878 get_handle(), peers.size()));
880 std::for_each(peers.begin(), peers.end(), bind(
881 &policy::peer_from_tracker, boost::ref(m_policy), _1, peer_id(0)
882 , peer_info::dht, 0));
885 #endif
887 void torrent::announce_with_tracker(tracker_request::event_t e)
889 INVARIANT_CHECK;
891 if (m_trackers.empty()) return;
893 restart_tracker_timer(time_now() + seconds(tracker_retry_delay_max));
895 if (m_abort) e = tracker_request::stopped;
897 if (e == tracker_request::none)
899 if (!m_start_sent) e = tracker_request::started;
900 if (!m_complete_sent && is_seed()) e = tracker_request::completed;
903 tracker_request req;
904 req.info_hash = m_torrent_file->info_hash();
905 req.pid = m_ses.get_peer_id();
906 req.downloaded = m_stat.total_payload_download();
907 req.uploaded = m_stat.total_payload_upload();
908 req.left = bytes_left();
909 if (req.left == -1) req.left = 16*1024;
910 req.event = e;
911 tcp::endpoint ep = m_ses.get_ipv6_interface();
912 error_code ec;
913 if (ep != tcp::endpoint())
914 req.ipv6 = ep.address().to_string(ec);
916 req.url = m_trackers[m_currently_trying_tracker].url;
917 // if we are aborting. we don't want any new peers
918 req.num_want = (req.event == tracker_request::stopped)
919 ?0:m_settings.num_want;
921 req.listen_port = m_ses.m_listen_sockets.empty()
922 ?0:m_ses.m_listen_sockets.front().external_port;
923 req.key = m_ses.m_key;
925 #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
926 if (m_abort)
928 boost::shared_ptr<aux::tracker_logger> tl(new aux::tracker_logger(m_ses));
929 m_ses.m_tracker_manager.queue_request(m_ses.m_io_service, m_ses.m_half_open, req
930 , tracker_login(), m_ses.m_listen_interface.address(), tl);
932 else
933 #endif
934 m_ses.m_tracker_manager.queue_request(m_ses.m_io_service, m_ses.m_half_open, req
935 , tracker_login(), m_ses.m_listen_interface.address()
936 , m_abort?boost::shared_ptr<torrent>():shared_from_this());
938 if (m_ses.m_alerts.should_post<tracker_announce_alert>())
940 m_ses.m_alerts.post_alert(
941 tracker_announce_alert(get_handle(), req.url, req.event));
945 void torrent::scrape_tracker()
947 if (m_trackers.empty()) return;
949 TORRENT_ASSERT(m_currently_trying_tracker >= 0);
950 TORRENT_ASSERT(m_currently_trying_tracker < int(m_trackers.size()));
952 tracker_request req;
953 req.info_hash = m_torrent_file->info_hash();
954 req.kind = tracker_request::scrape_request;
955 req.url = m_trackers[m_currently_trying_tracker].url;
956 m_ses.m_tracker_manager.queue_request(m_ses.m_io_service, m_ses.m_half_open, req
957 , tracker_login(), m_ses.m_listen_interface.address(), shared_from_this());
959 m_last_scrape = time_now();
962 void torrent::tracker_warning(tracker_request const& req, std::string const& msg)
964 session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
966 INVARIANT_CHECK;
968 if (m_ses.m_alerts.should_post<tracker_warning_alert>())
969 m_ses.m_alerts.post_alert(tracker_warning_alert(get_handle(), req.url, msg));
972 void torrent::tracker_scrape_response(tracker_request const& req
973 , int complete, int incomplete, int downloaded)
975 session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
977 INVARIANT_CHECK;
978 TORRENT_ASSERT(req.kind == tracker_request::scrape_request);
980 if (complete >= 0) m_complete = complete;
981 if (incomplete >= 0) m_incomplete = incomplete;
983 if (m_ses.m_alerts.should_post<scrape_reply_alert>())
985 m_ses.m_alerts.post_alert(scrape_reply_alert(
986 get_handle(), m_incomplete, m_complete, req.url));
990 void torrent::tracker_response(
991 tracker_request const& r
992 , std::vector<peer_entry>& peer_list
993 , int interval
994 , int complete
995 , int incomplete
996 , address const& external_ip)
998 session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
1000 INVARIANT_CHECK;
1001 TORRENT_ASSERT(r.kind == tracker_request::announce_request);
1003 if (external_ip != address())
1004 m_ses.set_external_address(external_ip);
1006 if (!m_start_sent && r.event == tracker_request::started)
1007 m_start_sent = true;
1008 if (!m_complete_sent && r.event == tracker_request::completed)
1009 m_complete_sent = true;
1011 m_failed_trackers = 0;
1013 if (interval < m_ses.settings().min_announce_interval)
1014 interval = m_ses.settings().min_announce_interval;
1016 m_last_working_tracker
1017 = prioritize_tracker(m_currently_trying_tracker);
1018 m_currently_trying_tracker = 0;
1020 m_duration = interval;
1021 restart_tracker_timer(time_now() + seconds(m_duration));
1023 if (complete >= 0) m_complete = complete;
1024 if (incomplete >= 0) m_incomplete = incomplete;
1025 if (complete >= 0 && incomplete >= 0)
1026 m_last_scrape = time_now();
1028 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
1029 std::stringstream s;
1030 s << "TRACKER RESPONSE:\n"
1031 "interval: " << m_duration << "\n"
1032 "peers:\n";
1033 for (std::vector<peer_entry>::const_iterator i = peer_list.begin();
1034 i != peer_list.end(); ++i)
1036 s << " " << std::setfill(' ') << std::setw(16) << i->ip
1037 << " " << std::setw(5) << std::dec << i->port << " ";
1038 if (!i->pid.is_all_zeros()) s << " " << i->pid << " " << identify_client(i->pid);
1039 s << "\n";
1041 s << "external ip: " << external_ip << "\n";
1042 debug_log(s.str());
1043 #endif
1044 // for each of the peers we got from the tracker
1045 for (std::vector<peer_entry>::iterator i = peer_list.begin();
1046 i != peer_list.end(); ++i)
1048 // don't make connections to ourself
1049 if (i->pid == m_ses.get_peer_id())
1050 continue;
1052 error_code ec;
1053 tcp::endpoint a(address::from_string(i->ip, ec), i->port);
1055 if (ec)
1057 // assume this is because we got a hostname instead of
1058 // an ip address from the tracker
1060 tcp::resolver::query q(i->ip, boost::lexical_cast<std::string>(i->port));
1061 m_host_resolver.async_resolve(q,
1062 bind(&torrent::on_peer_name_lookup, shared_from_this(), _1, _2, i->pid));
1064 else
1066 m_policy.peer_from_tracker(a, i->pid, peer_info::tracker, 0);
1070 if (m_ses.m_alerts.should_post<tracker_reply_alert>())
1072 m_ses.m_alerts.post_alert(tracker_reply_alert(
1073 get_handle(), peer_list.size(), r.url));
1075 m_got_tracker_response = true;
1078 void torrent::on_peer_name_lookup(error_code const& e, tcp::resolver::iterator host
1079 , peer_id pid)
1081 session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
1083 INVARIANT_CHECK;
1085 if (e || host == tcp::resolver::iterator() ||
1086 m_ses.is_aborted()) return;
1088 if (m_ses.m_ip_filter.access(host->endpoint().address()) & ip_filter::blocked)
1090 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
1091 error_code ec;
1092 debug_log("blocked ip from tracker: " + host->endpoint().address().to_string(ec));
1093 #endif
1094 if (m_ses.m_alerts.should_post<peer_blocked_alert>())
1096 m_ses.m_alerts.post_alert(peer_blocked_alert(host->endpoint().address()));
1099 return;
1102 m_policy.peer_from_tracker(*host, pid, peer_info::tracker, 0);
1105 size_type torrent::bytes_left() const
1107 // if we don't have the metadata yet, we
1108 // cannot tell how big the torrent is.
1109 if (!valid_metadata()) return -1;
1110 return m_torrent_file->total_size()
1111 - quantized_bytes_done();
1114 size_type torrent::quantized_bytes_done() const
1116 // INVARIANT_CHECK;
1118 if (!valid_metadata()) return 0;
1120 if (m_torrent_file->num_pieces() == 0)
1121 return 0;
1123 if (is_seed()) return m_torrent_file->total_size();
1125 const int last_piece = m_torrent_file->num_pieces() - 1;
1127 size_type total_done
1128 = size_type(num_have()) * m_torrent_file->piece_length();
1130 // if we have the last piece, we have to correct
1131 // the amount we have, since the first calculation
1132 // assumed all pieces were of equal size
1133 if (m_picker->have_piece(last_piece))
1135 int corr = m_torrent_file->piece_size(last_piece)
1136 - m_torrent_file->piece_length();
1137 total_done += corr;
1139 return total_done;
1142 // the first value is the total number of bytes downloaded
1143 // the second value is the number of bytes of those that haven't
1144 // been filtered as not wanted we have downloaded
1145 tuple<size_type, size_type> torrent::bytes_done() const
1147 INVARIANT_CHECK;
1149 if (!valid_metadata() || m_torrent_file->num_pieces() == 0)
1150 return tuple<size_type, size_type>(0,0);
1152 const int last_piece = m_torrent_file->num_pieces() - 1;
1153 const int piece_size = m_torrent_file->piece_length();
1155 if (is_seed())
1156 return make_tuple(m_torrent_file->total_size()
1157 , m_torrent_file->total_size());
1159 TORRENT_ASSERT(num_have() >= m_picker->num_have_filtered());
1160 size_type wanted_done = size_type(num_have() - m_picker->num_have_filtered())
1161 * piece_size;
1162 TORRENT_ASSERT(wanted_done >= 0);
1164 size_type total_done
1165 = size_type(num_have()) * piece_size;
1166 TORRENT_ASSERT(num_have() < m_torrent_file->num_pieces());
1168 // if we have the last piece, we have to correct
1169 // the amount we have, since the first calculation
1170 // assumed all pieces were of equal size
1171 if (m_picker->have_piece(last_piece))
1173 TORRENT_ASSERT(total_done >= piece_size);
1174 int corr = m_torrent_file->piece_size(last_piece)
1175 - piece_size;
1176 TORRENT_ASSERT(corr <= 0);
1177 TORRENT_ASSERT(corr > -piece_size);
1178 total_done += corr;
1179 if (m_picker->piece_priority(last_piece) != 0)
1181 TORRENT_ASSERT(wanted_done >= piece_size);
1182 wanted_done += corr;
1186 TORRENT_ASSERT(total_done <= m_torrent_file->total_size());
1187 TORRENT_ASSERT(wanted_done <= m_torrent_file->total_size());
1188 TORRENT_ASSERT(total_done >= wanted_done);
1190 const std::vector<piece_picker::downloading_piece>& dl_queue
1191 = m_picker->get_download_queue();
1193 const int blocks_per_piece = piece_size / m_block_size;
1195 for (std::vector<piece_picker::downloading_piece>::const_iterator i =
1196 dl_queue.begin(); i != dl_queue.end(); ++i)
1198 int corr = 0;
1199 int index = i->index;
1200 if (m_picker->have_piece(index)) continue;
1201 TORRENT_ASSERT(i->finished <= m_picker->blocks_in_piece(index));
1203 #ifndef NDEBUG
1204 for (std::vector<piece_picker::downloading_piece>::const_iterator j = boost::next(i);
1205 j != dl_queue.end(); ++j)
1207 TORRENT_ASSERT(j->index != index);
1209 #endif
1211 for (int j = 0; j < blocks_per_piece; ++j)
1213 TORRENT_ASSERT(m_picker->is_finished(piece_block(index, j)) == (i->info[j].state == piece_picker::block_info::state_finished));
1214 corr += (i->info[j].state == piece_picker::block_info::state_finished) * m_block_size;
1215 TORRENT_ASSERT(corr >= 0);
1216 TORRENT_ASSERT(index != last_piece || j < m_picker->blocks_in_last_piece()
1217 || i->info[j].state != piece_picker::block_info::state_finished);
1220 // correction if this was the last piece
1221 // and if we have the last block
1222 if (i->index == last_piece
1223 && i->info[m_picker->blocks_in_last_piece()-1].state
1224 == piece_picker::block_info::state_finished)
1226 corr -= m_block_size;
1227 corr += m_torrent_file->piece_size(last_piece) % m_block_size;
1229 total_done += corr;
1230 if (m_picker->piece_priority(index) != 0)
1231 wanted_done += corr;
1234 TORRENT_ASSERT(total_done <= m_torrent_file->total_size());
1235 TORRENT_ASSERT(wanted_done <= m_torrent_file->total_size());
1237 std::map<piece_block, int> downloading_piece;
1238 for (const_peer_iterator i = begin(); i != end(); ++i)
1240 peer_connection* pc = *i;
1241 boost::optional<piece_block_progress> p
1242 = pc->downloading_piece_progress();
1243 if (p)
1245 if (m_picker->have_piece(p->piece_index))
1246 continue;
1248 piece_block block(p->piece_index, p->block_index);
1249 if (m_picker->is_finished(block))
1250 continue;
1252 std::map<piece_block, int>::iterator dp
1253 = downloading_piece.find(block);
1254 if (dp != downloading_piece.end())
1256 if (dp->second < p->bytes_downloaded)
1257 dp->second = p->bytes_downloaded;
1259 else
1261 downloading_piece[block] = p->bytes_downloaded;
1263 #ifndef NDEBUG
1264 TORRENT_ASSERT(p->bytes_downloaded <= p->full_block_bytes);
1265 int last_piece = m_torrent_file->num_pieces() - 1;
1266 if (p->piece_index == last_piece
1267 && p->block_index == m_torrent_file->piece_size(last_piece) / block_size())
1268 TORRENT_ASSERT(p->full_block_bytes == m_torrent_file->piece_size(last_piece) % block_size());
1269 else
1270 TORRENT_ASSERT(p->full_block_bytes == block_size());
1271 #endif
1274 for (std::map<piece_block, int>::iterator i = downloading_piece.begin();
1275 i != downloading_piece.end(); ++i)
1277 total_done += i->second;
1278 if (m_picker->piece_priority(i->first.piece_index) != 0)
1279 wanted_done += i->second;
1282 TORRENT_ASSERT(total_done <= m_torrent_file->total_size());
1283 TORRENT_ASSERT(wanted_done <= m_torrent_file->total_size());
1285 #ifndef NDEBUG
1287 if (total_done >= m_torrent_file->total_size())
1289 // Thist happens when a piece has been downloaded completely
1290 // but not yet verified against the hash
1291 std::cerr << "num_have: " << num_have() << std::endl;
1293 std::cerr << "unfinished:" << std::endl;
1295 for (std::vector<piece_picker::downloading_piece>::const_iterator i =
1296 dl_queue.begin(); i != dl_queue.end(); ++i)
1298 std::cerr << " " << i->index << " ";
1299 for (int j = 0; j < blocks_per_piece; ++j)
1301 std::cerr << (i->info[j].state == piece_picker::block_info::state_finished ? "1" : "0");
1303 std::cerr << std::endl;
1306 std::cerr << "downloading pieces:" << std::endl;
1308 for (std::map<piece_block, int>::iterator i = downloading_piece.begin();
1309 i != downloading_piece.end(); ++i)
1311 std::cerr << " " << i->first.piece_index << ":" << i->first.block_index
1312 << " " << i->second << std::endl;
1317 TORRENT_ASSERT(total_done <= m_torrent_file->total_size());
1318 TORRENT_ASSERT(wanted_done <= m_torrent_file->total_size());
1320 #endif
1322 TORRENT_ASSERT(total_done >= wanted_done);
1323 return make_tuple(total_done, wanted_done);
1326 // passed_hash_check
1327 // 0: success, piece passed check
1328 // -1: disk failure
1329 // -2: piece failed check
1330 void torrent::piece_finished(int index, int passed_hash_check)
1332 session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
1334 #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
1335 (*m_ses.m_logger) << time_now_string() << " *** PIECE_FINISHED [ p: "
1336 << index << " chk: " << ((passed_hash_check == 0)
1337 ?"passed":passed_hash_check == -1
1338 ?"disk failed":"failed") << " ]\n";
1339 #endif
1341 TORRENT_ASSERT(valid_metadata());
1343 if (passed_hash_check == 0)
1345 // the following call may cause picker to become invalid
1346 // in case we just became a seed
1347 piece_passed(index);
1349 else if (passed_hash_check == -2)
1351 // piece_failed() will restore the piece
1352 piece_failed(index);
1354 else
1356 TORRENT_ASSERT(passed_hash_check == -1);
1357 m_picker->restore_piece(index);
1358 restore_piece_state(index);
1362 void torrent::piece_passed(int index)
1364 // INVARIANT_CHECK;
1366 TORRENT_ASSERT(index >= 0);
1367 TORRENT_ASSERT(index < m_torrent_file->num_pieces());
1369 if (m_ses.m_alerts.should_post<piece_finished_alert>())
1371 m_ses.m_alerts.post_alert(piece_finished_alert(get_handle()
1372 , index));
1375 bool was_finished = m_picker->num_filtered() + num_have()
1376 == torrent_file().num_pieces();
1378 std::vector<void*> downloaders;
1379 m_picker->get_downloaders(downloaders, index);
1381 // increase the trust point of all peers that sent
1382 // parts of this piece.
1383 std::set<void*> peers;
1384 std::copy(downloaders.begin(), downloaders.end(), std::inserter(peers, peers.begin()));
1386 m_picker->we_have(index);
1387 for (peer_iterator i = m_connections.begin(); i != m_connections.end();)
1389 peer_connection* p = *i;
1390 ++i;
1391 p->announce_piece(index);
1394 for (std::set<void*>::iterator i = peers.begin()
1395 , end(peers.end()); i != end; ++i)
1397 policy::peer* p = static_cast<policy::peer*>(*i);
1398 if (p == 0) continue;
1399 p->on_parole = false;
1400 ++p->trust_points;
1401 // TODO: make this limit user settable
1402 if (p->trust_points > 20) p->trust_points = 20;
1403 if (p->connection) p->connection->received_valid_data(index);
1406 #ifndef TORRENT_DISABLE_EXTENSIONS
1407 for (extension_list_t::iterator i = m_extensions.begin()
1408 , end(m_extensions.end()); i != end; ++i)
1410 #ifndef BOOST_NO_EXCEPTIONS
1411 try {
1412 #endif
1413 (*i)->on_piece_pass(index);
1414 #ifndef BOOST_NO_EXCEPTIONS
1415 } catch (std::exception&) {}
1416 #endif
1418 #endif
1420 // since this piece just passed, we might have
1421 // become uninterested in some peers where this
1422 // was the last piece we were interested in
1423 for (peer_iterator i = m_connections.begin();
1424 i != m_connections.end();)
1426 peer_connection* p = *i;
1427 // update_interest may disconnect the peer and
1428 // invalidate the iterator
1429 ++i;
1430 // if we're not interested already, no need to check
1431 if (!p->is_interesting()) continue;
1432 // if the peer doesn't have the piece we just got, it
1433 // wouldn't affect our interest
1434 if (!p->has_piece(index)) continue;
1435 p->update_interest();
1438 if (!was_finished && is_finished())
1440 // torrent finished
1441 // i.e. all the pieces we're interested in have
1442 // been downloaded. Release the files (they will open
1443 // in read only mode if needed)
1444 finished();
1445 // if we just became a seed, picker is now invalid, since it
1446 // is deallocated by the torrent once it starts seeding
1450 void torrent::piece_failed(int index)
1452 // if the last piece fails the peer connection will still
1453 // think that it has received all of it until this function
1454 // resets the download queue. So, we cannot do the
1455 // invariant check here since it assumes:
1456 // (total_done == m_torrent_file->total_size()) => is_seed()
1457 INVARIANT_CHECK;
1459 TORRENT_ASSERT(m_storage);
1460 TORRENT_ASSERT(m_storage->refcount() > 0);
1461 TORRENT_ASSERT(m_picker.get());
1462 TORRENT_ASSERT(index >= 0);
1463 TORRENT_ASSERT(index < m_torrent_file->num_pieces());
1465 if (m_ses.m_alerts.should_post<hash_failed_alert>())
1466 m_ses.m_alerts.post_alert(hash_failed_alert(get_handle(), index));
1468 // increase the total amount of failed bytes
1469 add_failed_bytes(m_torrent_file->piece_size(index));
1471 std::vector<void*> downloaders;
1472 m_picker->get_downloaders(downloaders, index);
1474 // decrease the trust point of all peers that sent
1475 // parts of this piece.
1476 // first, build a set of all peers that participated
1477 std::set<void*> peers;
1478 std::copy(downloaders.begin(), downloaders.end(), std::inserter(peers, peers.begin()));
1480 #ifndef NDEBUG
1481 for (std::vector<void*>::iterator i = downloaders.begin()
1482 , end(downloaders.end()); i != end; ++i)
1484 policy::peer* p = (policy::peer*)*i;
1485 if (p && p->connection)
1487 p->connection->piece_failed = true;
1490 #endif
1492 #ifndef TORRENT_DISABLE_EXTENSIONS
1493 for (extension_list_t::iterator i = m_extensions.begin()
1494 , end(m_extensions.end()); i != end; ++i)
1496 #ifndef BOOST_NO_EXCEPTIONS
1497 try {
1498 #endif
1499 (*i)->on_piece_failed(index);
1500 #ifndef BOOST_NO_EXCEPTIONS
1501 } catch (std::exception&) {}
1502 #endif
1504 #endif
1506 for (std::set<void*>::iterator i = peers.begin()
1507 , end(peers.end()); i != end; ++i)
1509 policy::peer* p = static_cast<policy::peer*>(*i);
1510 if (p == 0) continue;
1511 if (p->connection) p->connection->received_invalid_data(index);
1513 // either, we have received too many failed hashes
1514 // or this was the only peer that sent us this piece.
1515 // TODO: make this a changable setting
1516 if (p->trust_points <= -7
1517 || peers.size() == 1)
1519 // we don't trust this peer anymore
1520 // ban it.
1521 if (m_ses.m_alerts.should_post<peer_ban_alert>())
1523 peer_id pid(0);
1524 if (p->connection) pid = p->connection->pid();
1525 m_ses.m_alerts.post_alert(peer_ban_alert(
1526 get_handle(), p->ip(), pid));
1529 // mark the peer as banned
1530 p->banned = true;
1532 if (p->connection)
1534 #ifdef TORRENT_LOGGING
1535 (*m_ses.m_logger) << time_now_string() << " *** BANNING PEER [ " << p->ip()
1536 << " ] 'too many corrupt pieces'\n";
1537 #endif
1538 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
1539 (*p->connection->m_logger) << "*** BANNING PEER [ " << p->ip()
1540 << " ] 'too many corrupt pieces'\n";
1541 #endif
1542 p->connection->disconnect("too many corrupt pieces, banning peer");
1547 // we have to let the piece_picker know that
1548 // this piece failed the check as it can restore it
1549 // and mark it as being interesting for download
1550 // TODO: do this more intelligently! and keep track
1551 // of how much crap (data that failed hash-check) and
1552 // how much redundant data we have downloaded
1553 // if some clients has sent more than one piece
1554 // start with redownloading the pieces that the client
1555 // that has sent the least number of pieces
1556 m_picker->restore_piece(index);
1557 restore_piece_state(index);
1558 TORRENT_ASSERT(m_storage);
1560 TORRENT_ASSERT(m_picker->have_piece(index) == false);
1562 #ifndef NDEBUG
1563 for (std::vector<void*>::iterator i = downloaders.begin()
1564 , end(downloaders.end()); i != end; ++i)
1566 policy::peer* p = (policy::peer*)*i;
1567 if (p && p->connection)
1569 p->connection->piece_failed = false;
1572 #endif
1575 void torrent::restore_piece_state(int index)
1577 TORRENT_ASSERT(has_picker());
1578 for (peer_iterator i = m_connections.begin();
1579 i != m_connections.end(); ++i)
1581 peer_connection* p = *i;
1582 std::deque<pending_block> const& dq = p->download_queue();
1583 std::deque<piece_block> const& rq = p->request_queue();
1584 for (std::deque<pending_block>::const_iterator k = dq.begin()
1585 , end(dq.end()); k != end; ++k)
1587 if (k->block.piece_index != index) continue;
1588 m_picker->mark_as_downloading(k->block, p->peer_info_struct()
1589 , (piece_picker::piece_state_t)p->peer_speed());
1591 for (std::deque<piece_block>::const_iterator k = rq.begin()
1592 , end(rq.end()); k != end; ++k)
1594 if (k->piece_index != index) continue;
1595 m_picker->mark_as_downloading(*k, p->peer_info_struct()
1596 , (piece_picker::piece_state_t)p->peer_speed());
1601 void torrent::abort()
1603 INVARIANT_CHECK;
1605 m_abort = true;
1606 // if the torrent is paused, it doesn't need
1607 // to announce with even=stopped again.
1608 if (!is_paused())
1610 stop_announcing();
1613 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
1614 for (peer_iterator i = m_connections.begin();
1615 i != m_connections.end(); ++i)
1617 (*(*i)->m_logger) << "*** ABORTING TORRENT\n";
1619 #endif
1621 // disconnect all peers and close all
1622 // files belonging to the torrents
1623 disconnect_all();
1624 if (m_owning_storage.get())
1625 m_storage->async_release_files(
1626 bind(&torrent::on_files_released, shared_from_this(), _1, _2));
1628 if (m_state == torrent_status::checking_files)
1629 m_ses.done_checking(shared_from_this());
1631 m_owning_storage = 0;
1632 m_host_resolver.cancel();
1635 void torrent::on_files_deleted(int ret, disk_io_job const& j)
1637 session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
1639 if (ret != 0)
1641 if (alerts().should_post<torrent_delete_failed_alert>())
1642 alerts().post_alert(torrent_delete_failed_alert(get_handle(), j.str));
1644 else
1646 if (alerts().should_post<torrent_deleted_alert>())
1647 alerts().post_alert(torrent_deleted_alert(get_handle()));
1651 void torrent::on_files_released(int ret, disk_io_job const& j)
1654 session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
1656 if (alerts().should_post<torrent_paused_alert>())
1658 alerts().post_alert(torrent_paused_alert(get_handle()));
1663 void torrent::on_save_resume_data(int ret, disk_io_job const& j)
1665 session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
1667 if (!j.resume_data && alerts().should_post<save_resume_data_failed_alert>())
1669 alerts().post_alert(save_resume_data_failed_alert(get_handle(), j.str));
1670 return;
1673 if (j.resume_data && alerts().should_post<save_resume_data_alert>())
1675 write_resume_data(*j.resume_data);
1676 alerts().post_alert(save_resume_data_alert(j.resume_data
1677 , get_handle()));
1681 void torrent::on_file_renamed(int ret, disk_io_job const& j)
1683 session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
1686 if (ret == 0)
1688 if (alerts().should_post<file_renamed_alert>())
1689 alerts().post_alert(file_renamed_alert(get_handle(), j.str, j.piece));
1690 m_torrent_file->files().rename_file(j.piece, j.str);
1692 else
1694 if (alerts().should_post<file_rename_failed_alert>())
1695 alerts().post_alert(file_rename_failed_alert(get_handle(), j.str, j.piece));
1700 void torrent::on_torrent_paused(int ret, disk_io_job const& j)
1702 session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
1704 if (alerts().should_post<torrent_paused_alert>())
1705 alerts().post_alert(torrent_paused_alert(get_handle()));
1708 std::string torrent::tracker_login() const
1710 if (m_username.empty() && m_password.empty()) return "";
1711 return m_username + ":" + m_password;
1714 void torrent::piece_availability(std::vector<int>& avail) const
1716 INVARIANT_CHECK;
1718 TORRENT_ASSERT(valid_metadata());
1719 if (is_seed())
1721 avail.clear();
1722 return;
1725 m_picker->get_availability(avail);
1728 void torrent::set_piece_priority(int index, int priority)
1730 // INVARIANT_CHECK;
1732 TORRENT_ASSERT(valid_metadata());
1733 if (is_seed()) return;
1735 // this call is only valid on torrents with metadata
1736 TORRENT_ASSERT(m_picker.get());
1737 TORRENT_ASSERT(index >= 0);
1738 TORRENT_ASSERT(index < m_torrent_file->num_pieces());
1740 bool was_finished = is_finished();
1741 bool filter_updated = m_picker->set_piece_priority(index, priority);
1742 TORRENT_ASSERT(num_have() >= m_picker->num_have_filtered());
1743 if (filter_updated) update_peer_interest(was_finished);
1746 int torrent::piece_priority(int index) const
1748 // INVARIANT_CHECK;
1750 TORRENT_ASSERT(valid_metadata());
1751 if (is_seed()) return 1;
1753 // this call is only valid on torrents with metadata
1754 TORRENT_ASSERT(m_picker.get());
1755 TORRENT_ASSERT(index >= 0);
1756 TORRENT_ASSERT(index < m_torrent_file->num_pieces());
1758 return m_picker->piece_priority(index);
1761 void torrent::prioritize_pieces(std::vector<int> const& pieces)
1763 INVARIANT_CHECK;
1765 // this call is only valid on torrents with metadata
1766 TORRENT_ASSERT(valid_metadata());
1767 if (is_seed()) return;
1769 TORRENT_ASSERT(m_picker.get());
1771 int index = 0;
1772 bool filter_updated = false;
1773 bool was_finished = is_finished();
1774 for (std::vector<int>::const_iterator i = pieces.begin()
1775 , end(pieces.end()); i != end; ++i, ++index)
1777 TORRENT_ASSERT(*i >= 0);
1778 TORRENT_ASSERT(*i <= 7);
1779 filter_updated |= m_picker->set_piece_priority(index, *i);
1780 TORRENT_ASSERT(num_have() >= m_picker->num_have_filtered());
1782 if (filter_updated) update_peer_interest(was_finished);
1785 void torrent::piece_priorities(std::vector<int>& pieces) const
1787 INVARIANT_CHECK;
1789 // this call is only valid on torrents with metadata
1790 TORRENT_ASSERT(valid_metadata());
1791 if (is_seed())
1793 pieces.clear();
1794 pieces.resize(m_torrent_file->num_pieces(), 1);
1795 return;
1798 TORRENT_ASSERT(m_picker.get());
1799 m_picker->piece_priorities(pieces);
1802 namespace
1804 void set_if_greater(int& piece_prio, int file_prio)
1806 if (file_prio > piece_prio) piece_prio = file_prio;
1810 void torrent::prioritize_files(std::vector<int> const& files)
1812 INVARIANT_CHECK;
1814 // this call is only valid on torrents with metadata
1815 if (!valid_metadata() || is_seed()) return;
1817 // the bitmask need to have exactly one bit for every file
1818 // in the torrent
1819 TORRENT_ASSERT(int(files.size()) == m_torrent_file->num_files());
1821 if (m_torrent_file->num_pieces() == 0) return;
1823 std::copy(files.begin(), files.end(), m_file_priority.begin());
1824 update_piece_priorities();
1827 void torrent::set_file_priority(int index, int prio)
1829 INVARIANT_CHECK;
1830 TORRENT_ASSERT(index < m_torrent_file->num_files());
1831 TORRENT_ASSERT(index >= 0);
1832 if (m_file_priority[index] == prio) return;
1833 m_file_priority[index] = prio;
1834 update_piece_priorities();
1837 int torrent::file_priority(int index) const
1839 TORRENT_ASSERT(index < m_torrent_file->num_files());
1840 TORRENT_ASSERT(index >= 0);
1841 return m_file_priority[index];
1844 void torrent::file_priorities(std::vector<int>& files) const
1846 INVARIANT_CHECK;
1847 files.resize(m_file_priority.size());
1848 std::copy(m_file_priority.begin(), m_file_priority.end(), files.begin());
1851 void torrent::update_piece_priorities()
1853 INVARIANT_CHECK;
1855 if (m_torrent_file->num_pieces() == 0) return;
1857 size_type position = 0;
1858 int piece_length = m_torrent_file->piece_length();
1859 // initialize the piece priorities to 0, then only allow
1860 // setting higher priorities
1861 std::vector<int> pieces(m_torrent_file->num_pieces(), 0);
1862 for (int i = 0; i < int(m_file_priority.size()); ++i)
1864 size_type start = position;
1865 size_type size = m_torrent_file->files().at(i).size;
1866 if (size == 0) continue;
1867 position += size;
1868 if (m_file_priority[i] == 0) continue;
1870 // mark all pieces of the file with this file's priority
1871 // but only if the priority is higher than the pieces
1872 // already set (to avoid problems with overlapping pieces)
1873 int start_piece = int(start / piece_length);
1874 int last_piece = int((position - 1) / piece_length);
1875 TORRENT_ASSERT(last_piece < int(pieces.size()));
1876 // if one piece spans several files, we might
1877 // come here several times with the same start_piece, end_piece
1878 std::for_each(pieces.begin() + start_piece
1879 , pieces.begin() + last_piece + 1
1880 , bind(&set_if_greater, _1, m_file_priority[i]));
1882 prioritize_pieces(pieces);
1885 // this is called when piece priorities have been updated
1886 // updates the interested flag in peers
1887 void torrent::update_peer_interest(bool was_finished)
1889 for (peer_iterator i = begin(); i != end();)
1891 peer_connection* p = *i;
1892 // update_interest may disconnect the peer and
1893 // invalidate the iterator
1894 ++i;
1895 p->update_interest();
1898 // the torrent just became finished
1899 if (is_finished() && !was_finished)
1901 finished();
1903 else if (!is_finished() && was_finished)
1905 // if we used to be finished, but we aren't anymore
1906 // we may need to connect to peers again
1907 resume_download();
1908 m_policy.recalculate_connect_candidates();
1912 void torrent::filter_piece(int index, bool filter)
1914 INVARIANT_CHECK;
1916 TORRENT_ASSERT(valid_metadata());
1917 if (is_seed()) return;
1919 // this call is only valid on torrents with metadata
1920 TORRENT_ASSERT(m_picker.get());
1921 TORRENT_ASSERT(index >= 0);
1922 TORRENT_ASSERT(index < m_torrent_file->num_pieces());
1924 bool was_finished = is_finished();
1925 m_picker->set_piece_priority(index, filter ? 1 : 0);
1926 update_peer_interest(was_finished);
1929 void torrent::filter_pieces(std::vector<bool> const& bitmask)
1931 INVARIANT_CHECK;
1933 // this call is only valid on torrents with metadata
1934 TORRENT_ASSERT(valid_metadata());
1935 if (is_seed()) return;
1937 TORRENT_ASSERT(m_picker.get());
1939 bool was_finished = is_finished();
1940 int index = 0;
1941 for (std::vector<bool>::const_iterator i = bitmask.begin()
1942 , end(bitmask.end()); i != end; ++i, ++index)
1944 if ((m_picker->piece_priority(index) == 0) == *i) continue;
1945 if (*i)
1946 m_picker->set_piece_priority(index, 0);
1947 else
1948 m_picker->set_piece_priority(index, 1);
1950 update_peer_interest(was_finished);
1953 bool torrent::is_piece_filtered(int index) const
1955 // this call is only valid on torrents with metadata
1956 TORRENT_ASSERT(valid_metadata());
1957 if (is_seed()) return false;
1959 TORRENT_ASSERT(m_picker.get());
1960 TORRENT_ASSERT(index >= 0);
1961 TORRENT_ASSERT(index < m_torrent_file->num_pieces());
1963 return m_picker->piece_priority(index) == 0;
1966 void torrent::filtered_pieces(std::vector<bool>& bitmask) const
1968 INVARIANT_CHECK;
1970 // this call is only valid on torrents with metadata
1971 TORRENT_ASSERT(valid_metadata());
1972 if (is_seed())
1974 bitmask.clear();
1975 bitmask.resize(m_torrent_file->num_pieces(), false);
1976 return;
1979 TORRENT_ASSERT(m_picker.get());
1980 m_picker->filtered_pieces(bitmask);
1983 void torrent::filter_files(std::vector<bool> const& bitmask)
1985 INVARIANT_CHECK;
1987 // this call is only valid on torrents with metadata
1988 if (!valid_metadata() || is_seed()) return;
1990 // the bitmask need to have exactly one bit for every file
1991 // in the torrent
1992 TORRENT_ASSERT((int)bitmask.size() == m_torrent_file->num_files());
1994 size_type position = 0;
1996 if (m_torrent_file->num_pieces())
1998 int piece_length = m_torrent_file->piece_length();
1999 // mark all pieces as filtered, then clear the bits for files
2000 // that should be downloaded
2001 std::vector<bool> piece_filter(m_torrent_file->num_pieces(), true);
2002 for (int i = 0; i < (int)bitmask.size(); ++i)
2004 size_type start = position;
2005 position += m_torrent_file->files().at(i).size;
2006 // is the file selected for download?
2007 if (!bitmask[i])
2009 // mark all pieces of the file as downloadable
2010 int start_piece = int(start / piece_length);
2011 int last_piece = int(position / piece_length);
2012 // if one piece spans several files, we might
2013 // come here several times with the same start_piece, end_piece
2014 std::fill(piece_filter.begin() + start_piece, piece_filter.begin()
2015 + last_piece + 1, false);
2018 filter_pieces(piece_filter);
2022 void torrent::replace_trackers(std::vector<announce_entry> const& urls)
2024 m_trackers = urls;
2025 if (m_currently_trying_tracker >= (int)m_trackers.size())
2026 m_currently_trying_tracker = (int)m_trackers.size()-1;
2027 m_last_working_tracker = -1;
2028 if (!m_trackers.empty()) start_announcing();
2029 else stop_announcing();
2032 void torrent::choke_peer(peer_connection& c)
2034 INVARIANT_CHECK;
2036 TORRENT_ASSERT(!c.is_choked());
2037 TORRENT_ASSERT(m_num_uploads > 0);
2038 c.send_choke();
2039 --m_num_uploads;
2042 bool torrent::unchoke_peer(peer_connection& c)
2044 INVARIANT_CHECK;
2046 TORRENT_ASSERT(c.is_choked());
2047 if (m_num_uploads >= m_max_uploads) return false;
2048 if (!c.send_unchoke()) return false;
2049 ++m_num_uploads;
2050 return true;
2053 void torrent::cancel_block(piece_block block)
2055 INVARIANT_CHECK;
2057 for (peer_iterator i = m_connections.begin()
2058 , end(m_connections.end()); i != end; ++i)
2060 (*i)->cancel_request(block);
2064 void torrent::remove_peer(peer_connection* p)
2066 // INVARIANT_CHECK;
2068 TORRENT_ASSERT(p != 0);
2070 peer_iterator i = m_connections.find(p);
2071 if (i == m_connections.end())
2073 TORRENT_ASSERT(false);
2074 return;
2077 if (ready_for_connections())
2079 TORRENT_ASSERT(p->associated_torrent().lock().get() == this);
2081 if (p->is_seed())
2083 if (m_picker.get())
2085 m_picker->dec_refcount_all();
2088 else
2090 if (m_picker.get())
2092 bitfield const& pieces = p->get_bitfield();
2093 TORRENT_ASSERT(pieces.count() < int(pieces.size()));
2094 m_picker->dec_refcount(pieces);
2099 if (!p->is_choked())
2101 --m_num_uploads;
2102 m_ses.m_unchoke_time_scaler = 0;
2105 if (p->peer_info_struct() && p->peer_info_struct()->optimistically_unchoked)
2107 m_ses.m_optimistic_unchoke_time_scaler = 0;
2110 m_policy.connection_closed(*p);
2111 p->set_peer_info(0);
2112 TORRENT_ASSERT(i != m_connections.end());
2113 m_connections.erase(i);
2115 // remove from bandwidth request-queue
2116 for (int c = 0; c < 2; ++c)
2118 for (queue_t::iterator i = m_bandwidth_queue[c].begin()
2119 , end(m_bandwidth_queue[c].end()); i != end; ++i)
2121 if (i->peer != p) continue;
2122 m_bandwidth_queue[c].erase(i);
2123 break;
2128 void torrent::connect_to_url_seed(std::string const& url)
2130 INVARIANT_CHECK;
2132 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
2133 (*m_ses.m_logger) << time_now_string() << " resolving web seed: " << url << "\n";
2134 #endif
2136 std::string protocol;
2137 std::string auth;
2138 std::string hostname;
2139 int port;
2140 std::string path;
2141 char const* error;
2142 boost::tie(protocol, auth, hostname, port, path, error)
2143 = parse_url_components(url);
2145 if (error)
2147 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
2148 (*m_ses.m_logger) << time_now_string() << " failed to parse web seed url: " << error << "\n";
2149 #endif
2150 // never try it again
2151 remove_url_seed(url);
2152 return;
2155 #ifdef TORRENT_USE_OPENSSL
2156 if (protocol != "http" && protocol != "https")
2157 #else
2158 if (protocol != "http")
2159 #endif
2161 if (m_ses.m_alerts.should_post<url_seed_alert>())
2163 m_ses.m_alerts.post_alert(
2164 url_seed_alert(get_handle(), url, "unknown protocol"));
2166 // never try it again
2167 remove_url_seed(url);
2168 return;
2171 if (hostname.empty())
2173 if (m_ses.m_alerts.should_post<url_seed_alert>())
2175 m_ses.m_alerts.post_alert(
2176 url_seed_alert(get_handle(), url, "invalid hostname"));
2178 // never try it again
2179 remove_url_seed(url);
2180 return;
2183 if (port == 0)
2185 if (m_ses.m_alerts.should_post<url_seed_alert>())
2187 m_ses.m_alerts.post_alert(
2188 url_seed_alert(get_handle(), url, "invalid port"));
2190 // never try it again
2191 remove_url_seed(url);
2192 return;
2195 m_resolving_web_seeds.insert(url);
2196 proxy_settings const& ps = m_ses.web_seed_proxy();
2197 if (ps.type == proxy_settings::http
2198 || ps.type == proxy_settings::http_pw)
2200 // use proxy
2201 tcp::resolver::query q(ps.hostname
2202 , boost::lexical_cast<std::string>(ps.port));
2203 m_host_resolver.async_resolve(q,
2204 bind(&torrent::on_proxy_name_lookup, shared_from_this(), _1, _2, url));
2206 else
2208 if (m_ses.m_port_filter.access(port) & port_filter::blocked)
2210 if (m_ses.m_alerts.should_post<url_seed_alert>())
2212 m_ses.m_alerts.post_alert(
2213 url_seed_alert(get_handle(), url, "port blocked by port-filter"));
2215 // never try it again
2216 remove_url_seed(url);
2217 return;
2220 tcp::resolver::query q(hostname, boost::lexical_cast<std::string>(port));
2221 m_host_resolver.async_resolve(q,
2222 bind(&torrent::on_name_lookup, shared_from_this(), _1, _2, url
2223 , tcp::endpoint()));
2228 void torrent::on_proxy_name_lookup(error_code const& e, tcp::resolver::iterator host
2229 , std::string url)
2231 session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
2233 INVARIANT_CHECK;
2235 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
2236 (*m_ses.m_logger) << time_now_string() << " completed resolve proxy hostname for: " << url << "\n";
2237 #endif
2239 if (e || host == tcp::resolver::iterator())
2241 if (m_ses.m_alerts.should_post<url_seed_alert>())
2243 m_ses.m_alerts.post_alert(
2244 url_seed_alert(get_handle(), url, e.message()));
2247 // the name lookup failed for the http host. Don't try
2248 // this host again
2249 remove_url_seed(url);
2250 return;
2253 if (m_ses.is_aborted()) return;
2255 tcp::endpoint a(host->endpoint());
2257 using boost::tuples::ignore;
2258 std::string hostname;
2259 int port;
2260 char const* error;
2261 boost::tie(ignore, ignore, hostname, port, ignore, error)
2262 = parse_url_components(url);
2264 if (error)
2266 if (m_ses.m_alerts.should_post<url_seed_alert>())
2268 m_ses.m_alerts.post_alert(
2269 url_seed_alert(get_handle(), url, error));
2271 remove_url_seed(url);
2272 return;
2275 if (m_ses.m_ip_filter.access(a.address()) & ip_filter::blocked)
2277 if (m_ses.m_alerts.should_post<peer_blocked_alert>())
2278 m_ses.m_alerts.post_alert(peer_blocked_alert(a.address()));
2279 return;
2282 tcp::resolver::query q(hostname, boost::lexical_cast<std::string>(port));
2283 m_host_resolver.async_resolve(q,
2284 bind(&torrent::on_name_lookup, shared_from_this(), _1, _2, url, a));
2287 void torrent::on_name_lookup(error_code const& e, tcp::resolver::iterator host
2288 , std::string url, tcp::endpoint proxy)
2290 session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
2292 INVARIANT_CHECK;
2294 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
2295 (*m_ses.m_logger) << time_now_string() << " completed resolve: " << url << "\n";
2296 #endif
2298 std::set<std::string>::iterator i = m_resolving_web_seeds.find(url);
2299 if (i != m_resolving_web_seeds.end()) m_resolving_web_seeds.erase(i);
2301 if (e || host == tcp::resolver::iterator())
2303 if (m_ses.m_alerts.should_post<url_seed_alert>())
2305 std::stringstream msg;
2306 msg << "HTTP seed hostname lookup failed: " << e.message();
2307 m_ses.m_alerts.post_alert(
2308 url_seed_alert(get_handle(), url, msg.str()));
2310 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
2311 (*m_ses.m_logger) << " ** HOSTNAME LOOKUP FAILED!**: " << url << "\n";
2312 #endif
2314 // the name lookup failed for the http host. Don't try
2315 // this host again
2316 remove_url_seed(url);
2317 return;
2320 if (m_ses.is_aborted()) return;
2322 tcp::endpoint a(host->endpoint());
2324 if (m_ses.m_ip_filter.access(a.address()) & ip_filter::blocked)
2326 if (m_ses.m_alerts.should_post<peer_blocked_alert>())
2327 m_ses.m_alerts.post_alert(peer_blocked_alert(a.address()));
2328 return;
2331 boost::shared_ptr<socket_type> s(new (std::nothrow) socket_type(m_ses.m_io_service));
2332 if (!s) return;
2334 bool ret = instantiate_connection(m_ses.m_io_service, m_ses.web_seed_proxy(), *s);
2335 (void)ret;
2336 TORRENT_ASSERT(ret);
2338 if (m_ses.web_seed_proxy().type == proxy_settings::http
2339 || m_ses.web_seed_proxy().type == proxy_settings::http_pw)
2341 // the web seed connection will talk immediately to
2342 // the proxy, without requiring CONNECT support
2343 s->get<http_stream>()->set_no_connect(true);
2346 boost::intrusive_ptr<peer_connection> c(new (std::nothrow) web_peer_connection(
2347 m_ses, shared_from_this(), s, a, url, 0));
2348 if (!c) return;
2350 #ifndef NDEBUG
2351 c->m_in_constructor = false;
2352 #endif
2354 #ifndef TORRENT_DISABLE_EXTENSIONS
2355 for (extension_list_t::iterator i = m_extensions.begin()
2356 , end(m_extensions.end()); i != end; ++i)
2358 boost::shared_ptr<peer_plugin> pp((*i)->new_connection(c.get()));
2359 if (pp) c->add_extension(pp);
2361 #endif
2363 // add the newly connected peer to this torrent's peer list
2364 m_connections.insert(boost::get_pointer(c));
2365 m_ses.m_connections.insert(c);
2367 #ifndef BOOST_NO_EXCEPTIONS
2370 #endif
2371 // add the newly connected peer to this torrent's peer list
2372 m_connections.insert(boost::get_pointer(c));
2373 m_ses.m_connections.insert(c);
2374 c->start();
2376 m_ses.m_half_open.enqueue(
2377 bind(&peer_connection::connect, c, _1)
2378 , bind(&peer_connection::timed_out, c)
2379 , seconds(settings().peer_connect_timeout));
2380 #ifndef BOOST_NO_EXCEPTIONS
2382 catch (std::exception& e)
2384 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
2385 (*m_ses.m_logger) << " ** HOSTNAME LOOKUP FAILED!**: " << e.what() << "\n";
2386 #endif
2387 c->disconnect(e.what(), 1);
2389 #endif
2392 #ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
2393 namespace
2395 unsigned long swap_bytes(unsigned long a)
2397 return (a >> 24) | ((a & 0xff0000) >> 8) | ((a & 0xff00) << 8) | (a << 24);
2401 void torrent::resolve_peer_country(boost::intrusive_ptr<peer_connection> const& p) const
2403 if (m_resolving_country
2404 || p->has_country()
2405 || p->is_connecting()
2406 || p->is_queued()
2407 || p->in_handshake()
2408 || p->remote().address().is_v6()) return;
2410 asio::ip::address_v4 reversed(swap_bytes(p->remote().address().to_v4().to_ulong()));
2411 error_code ec;
2412 tcp::resolver::query q(reversed.to_string(ec) + ".zz.countries.nerd.dk", "0");
2413 if (ec)
2415 p->set_country("!!");
2416 return;
2418 m_resolving_country = true;
2419 m_host_resolver.async_resolve(q,
2420 bind(&torrent::on_country_lookup, shared_from_this(), _1, _2, p));
2423 namespace
2425 struct country_entry
2427 int code;
2428 char const* name;
2432 void torrent::on_country_lookup(error_code const& error, tcp::resolver::iterator i
2433 , intrusive_ptr<peer_connection> p) const
2435 session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
2437 INVARIANT_CHECK;
2439 m_resolving_country = false;
2441 // must be ordered in increasing order
2442 static const country_entry country_map[] =
2444 { 4, "AF"}, { 8, "AL"}, { 10, "AQ"}, { 12, "DZ"}, { 16, "AS"}
2445 , { 20, "AD"}, { 24, "AO"}, { 28, "AG"}, { 31, "AZ"}, { 32, "AR"}
2446 , { 36, "AU"}, { 40, "AT"}, { 44, "BS"}, { 48, "BH"}, { 50, "BD"}
2447 , { 51, "AM"}, { 52, "BB"}, { 56, "BE"}, { 60, "BM"}, { 64, "BT"}
2448 , { 68, "BO"}, { 70, "BA"}, { 72, "BW"}, { 74, "BV"}, { 76, "BR"}
2449 , { 84, "BZ"}, { 86, "IO"}, { 90, "SB"}, { 92, "VG"}, { 96, "BN"}
2450 , {100, "BG"}, {104, "MM"}, {108, "BI"}, {112, "BY"}, {116, "KH"}
2451 , {120, "CM"}, {124, "CA"}, {132, "CV"}, {136, "KY"}, {140, "CF"}
2452 , {144, "LK"}, {148, "TD"}, {152, "CL"}, {156, "CN"}, {158, "TW"}
2453 , {162, "CX"}, {166, "CC"}, {170, "CO"}, {174, "KM"}, {175, "YT"}
2454 , {178, "CG"}, {180, "CD"}, {184, "CK"}, {188, "CR"}, {191, "HR"}
2455 , {192, "CU"}, {203, "CZ"}, {204, "BJ"}, {208, "DK"}, {212, "DM"}
2456 , {214, "DO"}, {218, "EC"}, {222, "SV"}, {226, "GQ"}, {231, "ET"}
2457 , {232, "ER"}, {233, "EE"}, {234, "FO"}, {238, "FK"}, {239, "GS"}
2458 , {242, "FJ"}, {246, "FI"}, {248, "AX"}, {250, "FR"}, {254, "GF"}
2459 , {258, "PF"}, {260, "TF"}, {262, "DJ"}, {266, "GA"}, {268, "GE"}
2460 , {270, "GM"}, {275, "PS"}, {276, "DE"}, {288, "GH"}, {292, "GI"}
2461 , {296, "KI"}, {300, "GR"}, {304, "GL"}, {308, "GD"}, {312, "GP"}
2462 , {316, "GU"}, {320, "GT"}, {324, "GN"}, {328, "GY"}, {332, "HT"}
2463 , {334, "HM"}, {336, "VA"}, {340, "HN"}, {344, "HK"}, {348, "HU"}
2464 , {352, "IS"}, {356, "IN"}, {360, "ID"}, {364, "IR"}, {368, "IQ"}
2465 , {372, "IE"}, {376, "IL"}, {380, "IT"}, {384, "CI"}, {388, "JM"}
2466 , {392, "JP"}, {398, "KZ"}, {400, "JO"}, {404, "KE"}, {408, "KP"}
2467 , {410, "KR"}, {414, "KW"}, {417, "KG"}, {418, "LA"}, {422, "LB"}
2468 , {426, "LS"}, {428, "LV"}, {430, "LR"}, {434, "LY"}, {438, "LI"}
2469 , {440, "LT"}, {442, "LU"}, {446, "MO"}, {450, "MG"}, {454, "MW"}
2470 , {458, "MY"}, {462, "MV"}, {466, "ML"}, {470, "MT"}, {474, "MQ"}
2471 , {478, "MR"}, {480, "MU"}, {484, "MX"}, {492, "MC"}, {496, "MN"}
2472 , {498, "MD"}, {500, "MS"}, {504, "MA"}, {508, "MZ"}, {512, "OM"}
2473 , {516, "NA"}, {520, "NR"}, {524, "NP"}, {528, "NL"}, {530, "AN"}
2474 , {533, "AW"}, {540, "NC"}, {548, "VU"}, {554, "NZ"}, {558, "NI"}
2475 , {562, "NE"}, {566, "NG"}, {570, "NU"}, {574, "NF"}, {578, "NO"}
2476 , {580, "MP"}, {581, "UM"}, {583, "FM"}, {584, "MH"}, {585, "PW"}
2477 , {586, "PK"}, {591, "PA"}, {598, "PG"}, {600, "PY"}, {604, "PE"}
2478 , {608, "PH"}, {612, "PN"}, {616, "PL"}, {620, "PT"}, {624, "GW"}
2479 , {626, "TL"}, {630, "PR"}, {634, "QA"}, {634, "QA"}, {638, "RE"}
2480 , {642, "RO"}, {643, "RU"}, {646, "RW"}, {654, "SH"}, {659, "KN"}
2481 , {660, "AI"}, {662, "LC"}, {666, "PM"}, {670, "VC"}, {674, "SM"}
2482 , {678, "ST"}, {682, "SA"}, {686, "SN"}, {690, "SC"}, {694, "SL"}
2483 , {702, "SG"}, {703, "SK"}, {704, "VN"}, {705, "SI"}, {706, "SO"}
2484 , {710, "ZA"}, {716, "ZW"}, {724, "ES"}, {732, "EH"}, {736, "SD"}
2485 , {740, "SR"}, {744, "SJ"}, {748, "SZ"}, {752, "SE"}, {756, "CH"}
2486 , {760, "SY"}, {762, "TJ"}, {764, "TH"}, {768, "TG"}, {772, "TK"}
2487 , {776, "TO"}, {780, "TT"}, {784, "AE"}, {788, "TN"}, {792, "TR"}
2488 , {795, "TM"}, {796, "TC"}, {798, "TV"}, {800, "UG"}, {804, "UA"}
2489 , {807, "MK"}, {818, "EG"}, {826, "GB"}, {834, "TZ"}, {840, "US"}
2490 , {850, "VI"}, {854, "BF"}, {858, "UY"}, {860, "UZ"}, {862, "VE"}
2491 , {876, "WF"}, {882, "WS"}, {887, "YE"}, {891, "CS"}, {894, "ZM"}
2494 if (error || i == tcp::resolver::iterator())
2496 // this is used to indicate that we shouldn't
2497 // try to resolve it again
2498 p->set_country("--");
2499 return;
2502 while (i != tcp::resolver::iterator()
2503 && !i->endpoint().address().is_v4()) ++i;
2504 if (i != tcp::resolver::iterator())
2506 // country is an ISO 3166 country code
2507 int country = i->endpoint().address().to_v4().to_ulong() & 0xffff;
2509 // look up the country code in the map
2510 const int size = sizeof(country_map)/sizeof(country_map[0]);
2511 country_entry tmp = {country, ""};
2512 country_entry const* i =
2513 std::lower_bound(country_map, country_map + size, tmp
2514 , bind(&country_entry::code, _1) < bind(&country_entry::code, _2));
2515 if (i == country_map + size
2516 || i->code != country)
2518 // unknown country!
2519 p->set_country("!!");
2520 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
2521 (*m_ses.m_logger) << "IP " << p->remote().address() << " was mapped to unknown country: " << country << "\n";
2522 #endif
2523 return;
2526 p->set_country(i->name);
2529 #endif
2531 void torrent::read_resume_data(lazy_entry const& rd)
2533 m_total_uploaded = rd.dict_find_int_value("total_uploaded");
2534 m_total_downloaded = rd.dict_find_int_value("total_downloaded");
2535 m_active_time = seconds(rd.dict_find_int_value("active_time"));
2536 m_seeding_time = seconds(rd.dict_find_int_value("seeding_time"));
2537 m_complete = rd.dict_find_int_value("num_seeds", -1);
2538 m_incomplete = rd.dict_find_int_value("num_downloaders", -1);
2539 set_upload_limit(rd.dict_find_int_value("upload_rate_limit", -1));
2540 set_download_limit(rd.dict_find_int_value("download_rate_limit", -1));
2541 set_max_connections(rd.dict_find_int_value("max_connections", -1));
2542 set_max_uploads(rd.dict_find_int_value("max_uploads", -1));
2544 lazy_entry const* file_priority = rd.dict_find_list("file_priority");
2545 if (file_priority && file_priority->list_size()
2546 == m_torrent_file->num_files())
2548 for (int i = 0; i < file_priority->list_size(); ++i)
2549 m_file_priority[i] = file_priority->list_int_value_at(i, 1);
2550 update_piece_priorities();
2552 lazy_entry const* piece_priority = rd.dict_find_string("piece_priority");
2553 if (piece_priority && piece_priority->string_length()
2554 == m_torrent_file->num_pieces())
2556 char const* p = piece_priority->string_ptr();
2557 for (int i = 0; i < piece_priority->string_length(); ++i)
2558 m_picker->set_piece_priority(i, p[i]);
2561 int auto_managed_ = rd.dict_find_int_value("auto_managed", -1);
2562 if (auto_managed_ != -1) auto_managed(auto_managed_);
2564 int sequential_ = rd.dict_find_int_value("sequential_download", -1);
2565 if (sequential_ != -1) set_sequential_download(sequential_);
2567 int paused_ = rd.dict_find_int_value("paused", -1);
2568 if (paused_ == 1) pause();
2569 else if (paused_ == 0) resume();
2571 lazy_entry const* trackers = rd.dict_find_list("trackers");
2572 if (trackers)
2574 int tier = 0;
2575 for (int i = 0; i < trackers->list_size(); ++i)
2577 lazy_entry const* tier_list = trackers->list_at(i);
2578 if (tier_list == 0 || tier_list->type() != lazy_entry::list_t)
2579 continue;
2580 for (int j = 0; j < tier_list->list_size(); ++j)
2582 announce_entry e(tier_list->list_string_value_at(j));
2583 if (std::find_if(m_trackers.begin(), m_trackers.end()
2584 , boost::bind(&announce_entry::url, _1) == e.url) != m_trackers.end())
2585 continue;
2586 e.tier = tier;
2587 m_trackers.push_back(e);
2589 ++tier;
2591 std::sort(m_trackers.begin(), m_trackers.end(), boost::bind(&announce_entry::tier, _1)
2592 < boost::bind(&announce_entry::tier, _2));
2595 lazy_entry const* mapped_files = rd.dict_find_list("mapped_files");
2596 if (mapped_files && mapped_files->list_size() == m_torrent_file->num_files())
2598 for (int i = 0; i < m_torrent_file->num_files(); ++i)
2600 std::string new_filename = mapped_files->list_string_value_at(i);
2601 if (new_filename.empty()) continue;
2602 m_torrent_file->files().rename_file(i, new_filename);
2606 lazy_entry const* url_list = rd.dict_find_list("url-list");
2607 if (url_list)
2609 for (int i = 0; i < url_list->list_size(); ++i)
2611 std::string url = url_list->list_string_value_at(i);
2612 if (url.empty()) continue;
2613 m_web_seeds.insert(url);
2618 void torrent::write_resume_data(entry& ret) const
2620 ret["file-format"] = "libtorrent resume file";
2621 ret["file-version"] = 1;
2623 ret["total_uploaded"] = m_total_uploaded;
2624 ret["total_downloaded"] = m_total_downloaded;
2626 ret["active_time"] = total_seconds(m_active_time);
2627 ret["seeding_time"] = total_seconds(m_seeding_time);
2629 int seeds = 0;
2630 int downloaders = 0;
2631 if (m_complete >= 0) seeds = m_complete;
2632 else seeds = m_policy.num_seeds();
2633 if (m_incomplete >= 0) downloaders = m_incomplete;
2634 else downloaders = m_policy.num_peers() - m_policy.num_seeds();
2636 ret["num_seeds"] = seeds;
2637 ret["num_downloaders"] = downloaders;
2639 ret["sequential_download"] = m_sequential_download;
2641 const sha1_hash& info_hash = torrent_file().info_hash();
2642 ret["info-hash"] = std::string((char*)info_hash.begin(), (char*)info_hash.end());
2644 // blocks per piece
2645 int num_blocks_per_piece =
2646 static_cast<int>(torrent_file().piece_length()) / block_size();
2647 ret["blocks per piece"] = num_blocks_per_piece;
2649 // if this torrent is a seed, we won't have a piece picker
2650 // and there will be no half-finished pieces.
2651 if (!is_seed())
2653 const std::vector<piece_picker::downloading_piece>& q
2654 = m_picker->get_download_queue();
2656 // unfinished pieces
2657 ret["unfinished"] = entry::list_type();
2658 entry::list_type& up = ret["unfinished"].list();
2660 // info for each unfinished piece
2661 for (std::vector<piece_picker::downloading_piece>::const_iterator i
2662 = q.begin(); i != q.end(); ++i)
2664 if (i->finished == 0) continue;
2666 entry piece_struct(entry::dictionary_t);
2668 // the unfinished piece's index
2669 piece_struct["piece"] = i->index;
2671 std::string bitmask;
2672 const int num_bitmask_bytes
2673 = (std::max)(num_blocks_per_piece / 8, 1);
2675 for (int j = 0; j < num_bitmask_bytes; ++j)
2677 unsigned char v = 0;
2678 int bits = (std::min)(num_blocks_per_piece - j*8, 8);
2679 for (int k = 0; k < bits; ++k)
2680 v |= (i->info[j*8+k].state == piece_picker::block_info::state_finished)
2681 ? (1 << k) : 0;
2682 bitmask.insert(bitmask.end(), v);
2683 TORRENT_ASSERT(bits == 8 || j == num_bitmask_bytes - 1);
2685 piece_struct["bitmask"] = bitmask;
2686 // push the struct onto the unfinished-piece list
2687 up.push_back(piece_struct);
2691 // save trackers
2692 if (!m_trackers.empty())
2694 entry::list_type& tr_list = ret["trackers"].list();
2695 tr_list.push_back(entry::list_type());
2696 int tier = 0;
2697 for (std::vector<announce_entry>::const_iterator i = m_trackers.begin()
2698 , end(m_trackers.end()); i != end; ++i)
2700 if (i->tier == tier)
2702 tr_list.back().list().push_back(i->url);
2704 else
2706 tr_list.push_back(entry::list_t);
2707 tr_list.back().list().push_back(i->url);
2708 tier = i->tier;
2713 // save web seeds
2714 if (!m_web_seeds.empty())
2716 entry::list_type& url_list = ret["url-list"].list();
2717 for (std::set<std::string>::const_iterator i = m_web_seeds.begin()
2718 , end(m_web_seeds.end()); i != end; ++i)
2720 url_list.push_back(*i);
2724 // write have bitmask
2725 entry::string_type& pieces = ret["pieces"].string();
2726 pieces.resize(m_torrent_file->num_pieces());
2727 if (is_seed())
2729 std::memset(&pieces[0], 1, pieces.size());
2731 else
2733 for (int i = 0, end(pieces.size()); i < end; ++i)
2734 pieces[i] = m_picker->have_piece(i) ? 1 : 0;
2737 // write local peers
2739 entry::list_type& peer_list = ret["peers"].list();
2740 entry::list_type& banned_peer_list = ret["banned_peers"].list();
2742 int max_failcount = m_ses.m_settings.max_failcount;
2744 for (policy::const_iterator i = m_policy.begin_peer()
2745 , end(m_policy.end_peer()); i != end; ++i)
2747 error_code ec;
2748 if (i->second.banned)
2750 entry peer(entry::dictionary_t);
2751 peer["ip"] = i->second.addr.to_string(ec);
2752 if (ec) continue;
2753 peer["port"] = i->second.port;
2754 banned_peer_list.push_back(peer);
2755 continue;
2757 // we cannot save remote connection
2758 // since we don't know their listen port
2759 // unless they gave us their listen port
2760 // through the extension handshake
2761 // so, if the peer is not connectable (i.e. we
2762 // don't know its listen port) or if it has
2763 // been banned, don't save it.
2764 if (i->second.type == policy::peer::not_connectable) continue;
2766 // don't save peers that doesn't work
2767 if (i->second.failcount >= max_failcount) continue;
2769 entry peer(entry::dictionary_t);
2770 peer["ip"] = i->second.addr.to_string(ec);
2771 if (ec) continue;
2772 peer["port"] = i->second.port;
2773 peer_list.push_back(peer);
2776 ret["upload_rate_limit"] = upload_limit();
2777 ret["download_rate_limit"] = download_limit();
2778 ret["max_connections"] = max_connections();
2779 ret["max_uploads"] = max_uploads();
2780 ret["paused"] = m_paused;
2781 ret["auto_managed"] = m_auto_managed;
2783 // write piece priorities
2784 entry::string_type& piece_priority = ret["piece_priority"].string();
2785 piece_priority.resize(m_torrent_file->num_pieces());
2786 if (is_seed())
2788 std::memset(&piece_priority[0], 1, pieces.size());
2790 else
2792 for (int i = 0, end(piece_priority.size()); i < end; ++i)
2793 piece_priority[i] = m_picker->piece_priority(i);
2796 // write file priorities
2797 entry::list_type& file_priority = ret["file_priority"].list();
2798 file_priority.clear();
2799 for (int i = 0, end(m_file_priority.size()); i < end; ++i)
2800 file_priority.push_back(m_file_priority[i]);
2804 void torrent::get_full_peer_list(std::vector<peer_list_entry>& v) const
2806 v.clear();
2807 v.reserve(m_policy.num_peers());
2808 for (policy::const_iterator i = m_policy.begin_peer();
2809 i != m_policy.end_peer(); ++i)
2811 peer_list_entry e;
2812 e.ip = i->second.ip();
2813 e.flags = i->second.banned ? peer_list_entry::banned : 0;
2814 e.failcount = i->second.failcount;
2815 e.source = i->second.source;
2816 v.push_back(e);
2820 void torrent::get_peer_info(std::vector<peer_info>& v)
2822 v.clear();
2823 for (peer_iterator i = begin();
2824 i != end(); ++i)
2826 peer_connection* peer = *i;
2828 // incoming peers that haven't finished the handshake should
2829 // not be included in this list
2830 if (peer->associated_torrent().expired()) continue;
2832 v.push_back(peer_info());
2833 peer_info& p = v.back();
2835 peer->get_peer_info(p);
2836 #ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
2837 if (resolving_countries())
2838 resolve_peer_country(intrusive_ptr<peer_connection>(peer));
2839 #endif
2843 void torrent::get_download_queue(std::vector<partial_piece_info>& queue)
2845 queue.clear();
2846 if (!valid_metadata() || is_seed()) return;
2847 piece_picker const& p = picker();
2848 std::vector<piece_picker::downloading_piece> const& q
2849 = p.get_download_queue();
2851 for (std::vector<piece_picker::downloading_piece>::const_iterator i
2852 = q.begin(); i != q.end(); ++i)
2854 partial_piece_info pi;
2855 pi.piece_state = (partial_piece_info::state_t)i->state;
2856 pi.blocks_in_piece = p.blocks_in_piece(i->index);
2857 pi.finished = (int)i->finished;
2858 pi.writing = (int)i->writing;
2859 pi.requested = (int)i->requested;
2860 int piece_size = int(torrent_file().piece_size(i->index));
2861 int num_blocks = (std::min)(pi.blocks_in_piece, int(partial_piece_info::max_blocks_per_piece));
2862 for (int j = 0; j < num_blocks; ++j)
2864 block_info& bi = pi.blocks[j];
2865 bi.state = i->info[j].state;
2866 bi.block_size = j < pi.blocks_in_piece - 1 ? m_block_size
2867 : piece_size - (j * m_block_size);
2868 bool complete = bi.state == block_info::writing
2869 || bi.state == block_info::finished;
2870 if (i->info[j].peer == 0)
2872 bi.peer = tcp::endpoint();
2873 bi.bytes_progress = complete ? bi.block_size : 0;
2875 else
2877 policy::peer* p = static_cast<policy::peer*>(i->info[j].peer);
2878 if (p->connection)
2880 bi.peer = p->connection->remote();
2881 if (bi.state == block_info::requested)
2883 boost::optional<piece_block_progress> pbp
2884 = p->connection->downloading_piece_progress();
2885 if (pbp && pbp->piece_index == i->index && pbp->block_index == j)
2887 bi.bytes_progress = pbp->bytes_downloaded;
2888 TORRENT_ASSERT(bi.bytes_progress <= bi.block_size);
2890 else
2892 bi.bytes_progress = 0;
2895 else
2897 bi.bytes_progress = complete ? bi.block_size : 0;
2900 else
2902 bi.peer = p->ip();
2903 bi.bytes_progress = complete ? bi.block_size : 0;
2907 pi.blocks[j].num_peers = i->info[j].num_peers;
2909 pi.piece_index = i->index;
2910 queue.push_back(pi);
2915 bool torrent::connect_to_peer(policy::peer* peerinfo)
2917 INVARIANT_CHECK;
2919 TORRENT_ASSERT(peerinfo);
2920 TORRENT_ASSERT(peerinfo->connection == 0);
2922 peerinfo->connected = time_now();
2923 #ifndef NDEBUG
2924 // this asserts that we don't have duplicates in the policy's peer list
2925 peer_iterator i_ = std::find_if(m_connections.begin(), m_connections.end()
2926 , bind(&peer_connection::remote, _1) == peerinfo->ip());
2927 TORRENT_ASSERT(i_ == m_connections.end()
2928 || dynamic_cast<bt_peer_connection*>(*i_) == 0);
2929 #endif
2931 TORRENT_ASSERT(want_more_peers());
2932 TORRENT_ASSERT(m_ses.num_connections() < m_ses.max_connections());
2934 tcp::endpoint a(peerinfo->ip());
2935 TORRENT_ASSERT((m_ses.m_ip_filter.access(peerinfo->addr) & ip_filter::blocked) == 0);
2937 boost::shared_ptr<socket_type> s(new socket_type(m_ses.m_io_service));
2939 bool ret = instantiate_connection(m_ses.m_io_service, m_ses.peer_proxy(), *s);
2940 (void)ret;
2941 TORRENT_ASSERT(ret);
2943 boost::intrusive_ptr<peer_connection> c(new bt_peer_connection(
2944 m_ses, shared_from_this(), s, a, peerinfo));
2946 #ifndef NDEBUG
2947 c->m_in_constructor = false;
2948 #endif
2950 c->add_stat(peerinfo->prev_amount_download, peerinfo->prev_amount_upload);
2951 peerinfo->prev_amount_download = 0;
2952 peerinfo->prev_amount_upload = 0;
2954 #ifndef TORRENT_DISABLE_EXTENSIONS
2955 for (extension_list_t::iterator i = m_extensions.begin()
2956 , end(m_extensions.end()); i != end; ++i)
2958 #ifndef BOOST_NO_EXCEPTIONS
2959 try {
2960 #endif
2961 boost::shared_ptr<peer_plugin> pp((*i)->new_connection(c.get()));
2962 if (pp) c->add_extension(pp);
2963 #ifndef BOOST_NO_EXCEPTIONS
2964 } catch (std::exception&) {}
2965 #endif
2967 #endif
2969 // add the newly connected peer to this torrent's peer list
2970 m_connections.insert(boost::get_pointer(c));
2971 m_ses.m_connections.insert(c);
2972 peerinfo->connection = c.get();
2973 c->start();
2975 int timeout = settings().peer_connect_timeout;
2976 if (peerinfo) timeout += 3 * peerinfo->failcount;
2978 #ifndef BOOST_NO_EXCEPTIONS
2981 #endif
2982 m_ses.m_half_open.enqueue(
2983 bind(&peer_connection::connect, c, _1)
2984 , bind(&peer_connection::timed_out, c)
2985 , seconds(timeout));
2986 #ifndef BOOST_NO_EXCEPTIONS
2988 catch (std::exception& e)
2990 std::set<peer_connection*>::iterator i
2991 = m_connections.find(boost::get_pointer(c));
2992 if (i != m_connections.end()) m_connections.erase(i);
2993 c->disconnect(e.what());
2994 return false;
2996 #endif
2998 return peerinfo->connection;
3001 bool torrent::set_metadata(char const* metadata_buf, int metadata_size)
3003 INVARIANT_CHECK;
3005 if (m_torrent_file->is_valid()) return false;
3007 hasher h;
3008 h.update(metadata_buf, metadata_size);
3009 sha1_hash info_hash = h.final();
3011 if (info_hash != m_torrent_file->info_hash())
3013 if (alerts().should_post<metadata_failed_alert>())
3015 alerts().post_alert(metadata_failed_alert(get_handle()));
3017 return false;
3020 lazy_entry metadata;
3021 std::string error = "parser error";
3022 int ret = lazy_bdecode(metadata_buf, metadata_buf + metadata_size, metadata);
3023 if (ret != 0 || !m_torrent_file->parse_info_section(metadata, error))
3025 // this means the metadata is correct, since we
3026 // verified it against the info-hash, but we
3027 // failed to parse it. Pause the torrent
3028 if (alerts().should_post<metadata_failed_alert>())
3030 alerts().post_alert(metadata_failed_alert(get_handle()));
3032 set_error("invalid metadata: " + error);
3033 pause();
3034 return false;
3037 if (m_ses.m_alerts.should_post<metadata_received_alert>())
3039 m_ses.m_alerts.post_alert(metadata_received_alert(
3040 get_handle()));
3043 init();
3045 return true;
3048 bool torrent::attach_peer(peer_connection* p)
3050 // INVARIANT_CHECK;
3052 TORRENT_ASSERT(p != 0);
3053 TORRENT_ASSERT(!p->is_local());
3055 m_has_incoming = true;
3057 if ((m_state == torrent_status::queued_for_checking
3058 || m_state == torrent_status::checking_files)
3059 && valid_metadata())
3061 p->disconnect("torrent is not ready to accept peers");
3062 return false;
3065 if (m_ses.m_connections.find(p) == m_ses.m_connections.end())
3067 p->disconnect("peer is not properly constructed");
3068 return false;
3071 if (m_ses.is_aborted())
3073 p->disconnect("session is closing");
3074 return false;
3077 if (int(m_connections.size()) >= m_max_connections)
3079 p->disconnect("reached connection limit");
3080 return false;
3083 #ifndef BOOST_NO_EXCEPTIONS
3086 #endif
3087 #ifndef TORRENT_DISABLE_EXTENSIONS
3088 for (extension_list_t::iterator i = m_extensions.begin()
3089 , end(m_extensions.end()); i != end; ++i)
3091 boost::shared_ptr<peer_plugin> pp((*i)->new_connection(p));
3092 if (pp) p->add_extension(pp);
3094 #endif
3095 if (!m_policy.new_connection(*p))
3096 return false;
3097 #ifndef BOOST_NO_EXCEPTIONS
3099 catch (std::exception& e)
3101 #if defined TORRENT_LOGGING
3102 (*m_ses.m_logger) << time_now_string() << " CLOSING CONNECTION "
3103 << p->remote() << " policy::new_connection threw: " << e.what() << "\n";
3104 #endif
3105 p->disconnect(e.what());
3106 return false;
3108 #endif
3109 TORRENT_ASSERT(m_connections.find(p) == m_connections.end());
3110 peer_iterator ci = m_connections.insert(p).first;
3111 #ifndef NDEBUG
3112 error_code ec;
3113 TORRENT_ASSERT(p->remote() == p->get_socket()->remote_endpoint(ec) || ec);
3114 #endif
3116 #if !defined NDEBUG && !defined TORRENT_DISABLE_INVARIANT_CHECKS
3117 m_policy.check_invariant();
3118 #endif
3119 return true;
3122 bool torrent::want_more_peers() const
3124 return int(m_connections.size()) < m_max_connections
3125 && !is_paused()
3126 && m_state != torrent_status::checking_files
3127 && (m_state != torrent_status::queued_for_checking
3128 || !valid_metadata())
3129 && m_policy.num_connect_candidates() > 0
3130 && !m_abort;
3133 void torrent::disconnect_all()
3135 session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
3137 // doesn't work with the m_paused -> m_num_peers == 0 condition
3138 // INVARIANT_CHECK;
3140 while (!m_connections.empty())
3142 peer_connection* p = *m_connections.begin();
3143 TORRENT_ASSERT(p->associated_torrent().lock().get() == this);
3145 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
3146 if (m_abort)
3147 (*p->m_logger) << "*** CLOSING CONNECTION 'aborting'\n";
3148 else
3149 (*p->m_logger) << "*** CLOSING CONNECTION 'pausing'\n";
3150 #endif
3151 #ifndef NDEBUG
3152 std::size_t size = m_connections.size();
3153 #endif
3154 if (p->is_disconnecting())
3155 m_connections.erase(m_connections.begin());
3156 else
3157 p->disconnect(m_abort?"stopping torrent":"pausing torrent");
3158 TORRENT_ASSERT(m_connections.size() <= size);
3162 namespace
3164 // this returns true if lhs is a better disconnect candidate than rhs
3165 bool compare_disconnect_peer(peer_connection const* lhs, peer_connection const* rhs)
3167 // prefer to disconnect peers we're not interested in
3168 if (lhs->is_interesting() != rhs->is_interesting())
3169 return rhs->is_interesting();
3171 // prefer to disconnect peers that are not seeds
3172 if (lhs->is_seed() != rhs->is_seed())
3173 return rhs->is_seed();
3175 // prefer to disconnect peers that are on parole
3176 if (lhs->on_parole() != rhs->on_parole())
3177 return lhs->on_parole();
3179 // prefer to disconnect peers that send data at a lower rate
3180 size_type lhs_transferred = lhs->statistics().total_payload_download();
3181 size_type rhs_transferred = rhs->statistics().total_payload_download();
3183 if (lhs_transferred != rhs_transferred
3184 && lhs_transferred > 0
3185 && rhs_transferred > 0)
3187 ptime now = time_now();
3188 size_type lhs_time_connected = total_seconds(now - lhs->connected_time());
3189 size_type rhs_time_connected = total_seconds(now - rhs->connected_time());
3191 double lhs_rate = double(lhs_transferred) / (lhs_time_connected + 1);
3192 double rhs_rate = double(rhs_transferred) / (rhs_time_connected + 1);
3194 return lhs_rate < rhs_rate;
3197 // prefer to disconnect peers that chokes us
3198 if (lhs->is_choked() != rhs->is_choked())
3199 return lhs->is_choked();
3201 return lhs->last_received() < rhs->last_received();
3205 int torrent::disconnect_peers(int num)
3207 int ret = 0;
3208 // buils a list of all connected peers and sort it by 'disconnectability'.
3209 std::vector<peer_connection*> peers(m_connections.size());
3210 std::copy(m_connections.begin(), m_connections.end(), peers.begin());
3211 std::sort(peers.begin(), peers.end(), boost::bind(&compare_disconnect_peer, _1, _2));
3213 // never disconnect peers that connected less than 90 seconds ago
3214 ptime cut_off = time_now() - seconds(90);
3216 for (std::vector<peer_connection*>::iterator i = peers.begin()
3217 , end(peers.end()); i != end && ret < num; ++i)
3219 peer_connection* p = *i;
3220 if (p->connected_time() > cut_off) continue;
3221 ++ret;
3222 p->disconnect("optimistic disconnect");
3224 return ret;
3227 int torrent::bandwidth_throttle(int channel) const
3229 return m_bandwidth_limit[channel].throttle();
3232 int torrent::bandwidth_queue_size(int channel) const
3234 return (int)m_bandwidth_queue[channel].size();
3237 void torrent::request_bandwidth(int channel
3238 , boost::intrusive_ptr<peer_connection> const& p
3239 , int max_block_size, int priority)
3241 TORRENT_ASSERT(max_block_size > 0);
3242 TORRENT_ASSERT(m_bandwidth_limit[channel].throttle() > 0);
3243 TORRENT_ASSERT(p->max_assignable_bandwidth(channel) > 0);
3244 TORRENT_ASSERT(p->m_channel_state[channel] == peer_info::bw_torrent);
3245 int block_size = (std::min)(m_bandwidth_limit[channel].throttle() / 10
3246 , max_block_size);
3247 if (block_size <= 0) block_size = 1;
3249 if (m_bandwidth_limit[channel].max_assignable() > 0)
3251 perform_bandwidth_request(channel, p, block_size, priority);
3253 else
3255 // skip forward in the queue until we find a prioritized peer
3256 // or hit the front of it.
3257 queue_t::reverse_iterator i = m_bandwidth_queue[channel].rbegin();
3258 while (i != m_bandwidth_queue[channel].rend() && priority > i->priority)
3260 ++i->priority;
3261 ++i;
3263 m_bandwidth_queue[channel].insert(i.base(), bw_queue_entry<peer_connection, torrent>(
3264 p, block_size, priority));
3268 void torrent::expire_bandwidth(int channel, int amount)
3270 session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
3272 INVARIANT_CHECK;
3274 TORRENT_ASSERT(amount > 0);
3275 m_bandwidth_limit[channel].expire(amount);
3276 queue_t tmp;
3277 while (!m_bandwidth_queue[channel].empty())
3279 bw_queue_entry<peer_connection, torrent> qe = m_bandwidth_queue[channel].front();
3280 if (m_bandwidth_limit[channel].max_assignable() == 0)
3281 break;
3282 m_bandwidth_queue[channel].pop_front();
3283 if (qe.peer->max_assignable_bandwidth(channel) <= 0)
3285 TORRENT_ASSERT(m_ses.m_bandwidth_manager[channel]->is_in_history(qe.peer.get()));
3286 if (!qe.peer->is_disconnecting()) tmp.push_back(qe);
3287 continue;
3289 perform_bandwidth_request(channel, qe.peer
3290 , qe.max_block_size, qe.priority);
3292 m_bandwidth_queue[channel].insert(m_bandwidth_queue[channel].begin(), tmp.begin(), tmp.end());
3295 void torrent::perform_bandwidth_request(int channel
3296 , boost::intrusive_ptr<peer_connection> const& p
3297 , int block_size
3298 , int priority)
3300 TORRENT_ASSERT(p->m_channel_state[channel] == peer_info::bw_torrent);
3301 p->m_channel_state[channel] = peer_info::bw_global;
3302 m_ses.m_bandwidth_manager[channel]->request_bandwidth(p
3303 , block_size, priority);
3304 m_bandwidth_limit[channel].assign(block_size);
3307 void torrent::assign_bandwidth(int channel, int amount, int blk)
3309 session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
3311 TORRENT_ASSERT(amount > 0);
3312 TORRENT_ASSERT(amount <= blk);
3313 if (amount < blk)
3314 expire_bandwidth(channel, blk - amount);
3317 // called when torrent is finished (all interesting
3318 // pieces have been downloaded)
3319 void torrent::finished()
3321 INVARIANT_CHECK;
3323 TORRENT_ASSERT(is_finished());
3324 TORRENT_ASSERT(m_state != torrent_status::finished && m_state != torrent_status::seeding);
3326 if (alerts().should_post<torrent_finished_alert>())
3328 alerts().post_alert(torrent_finished_alert(
3329 get_handle()));
3332 set_state(torrent_status::finished);
3333 set_queue_position(-1);
3335 // we have to call completed() before we start
3336 // disconnecting peers, since there's an assert
3337 // to make sure we're cleared the piece picker
3338 if (is_seed()) completed();
3340 // disconnect all seeds
3341 // TODO: should disconnect all peers that have the pieces we have
3342 // not just seeds
3343 std::vector<peer_connection*> seeds;
3344 for (peer_iterator i = m_connections.begin();
3345 i != m_connections.end(); ++i)
3347 peer_connection* p = *i;
3348 TORRENT_ASSERT(p->associated_torrent().lock().get() == this);
3349 if (p->upload_only())
3351 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
3352 (*p->m_logger) << "*** SEED, CLOSING CONNECTION\n";
3353 #endif
3354 seeds.push_back(p);
3357 std::for_each(seeds.begin(), seeds.end()
3358 , bind(&peer_connection::disconnect, _1, "torrent finished, disconnecting seed", 0));
3360 TORRENT_ASSERT(m_storage);
3361 // we need to keep the object alive during this operation
3362 m_storage->async_release_files(
3363 bind(&torrent::on_files_released, shared_from_this(), _1, _2));
3366 // this is called when we were finished, but some files were
3367 // marked for downloading, and we are no longer finished
3368 void torrent::resume_download()
3370 INVARIANT_CHECK;
3372 TORRENT_ASSERT(!is_finished());
3373 set_state(torrent_status::downloading);
3374 set_queue_position((std::numeric_limits<int>::max)());
3377 // called when torrent is complete (all pieces downloaded)
3378 void torrent::completed()
3380 m_picker.reset();
3382 set_state(torrent_status::seeding);
3383 if (!m_complete_sent && m_announcing) announce_with_tracker();
3386 // this will move the tracker with the given index
3387 // to a prioritized position in the list (move it towards
3388 // the begining) and return the new index to the tracker.
3389 int torrent::prioritize_tracker(int index)
3391 INVARIANT_CHECK;
3393 TORRENT_ASSERT(index >= 0);
3394 if (index >= (int)m_trackers.size()) return (int)m_trackers.size()-1;
3396 while (index > 0 && m_trackers[index].tier == m_trackers[index-1].tier)
3398 std::swap(m_trackers[index].url, m_trackers[index-1].url);
3399 --index;
3401 return index;
3404 void torrent::try_next_tracker(tracker_request const& req)
3406 INVARIANT_CHECK;
3408 ++m_currently_trying_tracker;
3410 if ((unsigned)m_currently_trying_tracker < m_trackers.size())
3412 announce_with_tracker(req.event);
3413 return;
3416 int delay = tracker_retry_delay_min
3417 + (std::min)(int(m_failed_trackers), int(tracker_failed_max))
3418 * (tracker_retry_delay_max - tracker_retry_delay_min)
3419 / tracker_failed_max;
3421 ++m_failed_trackers;
3422 // if we've looped the tracker list, wait a bit before retrying
3423 m_currently_trying_tracker = 0;
3425 // if we're stopping, just give up. Don't bother retrying
3426 if (req.event == tracker_request::stopped)
3427 return;
3429 restart_tracker_timer(time_now() + seconds(delay));
3431 #ifndef TORRENT_DISABLE_DHT
3432 if (m_abort) return;
3434 // only start the announce if we want to announce with the dht
3435 ptime now = time_now();
3436 if (should_announce_dht() && now - m_last_dht_announce > minutes(14))
3438 // force the DHT to reannounce
3439 m_last_dht_announce = now;
3440 boost::weak_ptr<torrent> self(shared_from_this());
3441 m_ses.m_dht->announce(m_torrent_file->info_hash()
3442 , m_ses.m_listen_sockets.front().external_port
3443 , bind(&torrent::on_dht_announce_response_disp, self, _1));
3445 #endif
3449 void torrent::files_checked()
3451 session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
3453 TORRENT_ASSERT(m_torrent_file->is_valid());
3454 INVARIANT_CHECK;
3456 // we might be finished already, in which case we should
3457 // not switch to downloading mode.
3458 if (m_state != torrent_status::finished)
3459 set_state(torrent_status::downloading);
3461 if (m_ses.m_alerts.should_post<torrent_checked_alert>())
3463 m_ses.m_alerts.post_alert(torrent_checked_alert(
3464 get_handle()));
3467 if (!is_seed())
3469 // if we just finished checking and we're not a seed, we are
3470 // likely to be unpaused
3471 if (m_ses.m_auto_manage_time_scaler > 1)
3472 m_ses.m_auto_manage_time_scaler = 1;
3474 if (is_finished() && m_state != torrent_status::finished) finished();
3476 else
3478 m_complete_sent = true;
3479 if (m_state != torrent_status::finished) finished();
3482 #ifndef TORRENT_DISABLE_EXTENSIONS
3483 for (extension_list_t::iterator i = m_extensions.begin()
3484 , end(m_extensions.end()); i != end; ++i)
3486 #ifndef BOOST_NO_EXCEPTIONS
3487 try {
3488 #endif
3489 (*i)->on_files_checked();
3490 #ifndef BOOST_NO_EXCEPTIONS
3491 } catch (std::exception&) {}
3492 #endif
3494 #endif
3496 if (!m_connections_initialized)
3498 m_connections_initialized = true;
3499 // all peer connections have to initialize themselves now that the metadata
3500 // is available
3501 for (torrent::peer_iterator i = m_connections.begin();
3502 i != m_connections.end();)
3504 peer_connection* pc = *i;
3505 ++i;
3506 if (pc->is_disconnecting()) continue;
3507 pc->on_metadata_impl();
3508 if (pc->is_disconnecting()) continue;
3509 pc->init();
3513 m_files_checked = true;
3515 start_announcing();
3518 alert_manager& torrent::alerts() const
3520 return m_ses.m_alerts;
3523 fs::path torrent::save_path() const
3525 return m_save_path;
3528 bool torrent::rename_file(int index, std::string const& name)
3530 INVARIANT_CHECK;
3532 TORRENT_ASSERT(index >= 0);
3533 TORRENT_ASSERT(index < m_torrent_file->num_files());
3535 if (!m_owning_storage.get()) return false;
3537 m_owning_storage->async_rename_file(index, name
3538 , bind(&torrent::on_file_renamed, shared_from_this(), _1, _2));
3539 return true;
3542 void torrent::move_storage(fs::path const& save_path)
3544 INVARIANT_CHECK;
3546 if (m_owning_storage.get())
3548 m_owning_storage->async_move_storage(save_path
3549 , bind(&torrent::on_storage_moved, shared_from_this(), _1, _2));
3551 else
3553 m_save_path = save_path;
3557 void torrent::on_storage_moved(int ret, disk_io_job const& j)
3559 session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
3561 if (alerts().should_post<storage_moved_alert>())
3563 alerts().post_alert(storage_moved_alert(get_handle(), j.str));
3565 m_save_path = j.str;
3568 piece_manager& torrent::filesystem()
3570 TORRENT_ASSERT(m_owning_storage.get());
3571 TORRENT_ASSERT(m_storage);
3572 return *m_storage;
3576 torrent_handle torrent::get_handle()
3578 return torrent_handle(shared_from_this());
3581 session_settings const& torrent::settings() const
3583 return m_ses.settings();
3586 #ifndef NDEBUG
3587 void torrent::check_invariant() const
3589 session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
3591 if (is_paused()) TORRENT_ASSERT(num_peers() == 0);
3593 if (!m_ses.m_queued_for_checking.empty())
3595 // if there are torrents waiting to be checked
3596 // assert that there's a torrent that is being
3597 // processed right now
3598 int found = 0;
3599 for (aux::session_impl::torrent_map::iterator i = m_ses.m_torrents.begin()
3600 , end(m_ses.m_torrents.end()); i != end; ++i)
3601 if (i->second->m_state == torrent_status::checking_files) ++found;
3602 // the case of 2 is in the special case where one switches over from
3603 // checking to complete
3604 TORRENT_ASSERT(found == 1 || found == 2);
3607 TORRENT_ASSERT(m_resume_entry.type() == lazy_entry::dict_t
3608 || m_resume_entry.type() == lazy_entry::none_t);
3610 TORRENT_ASSERT(m_bandwidth_queue[0].size() <= m_connections.size());
3611 TORRENT_ASSERT(m_bandwidth_queue[1].size() <= m_connections.size());
3613 for (int c = 0; c < 2; ++c)
3615 queue_t::const_iterator j = m_bandwidth_queue[c].begin();
3616 if (j == m_bandwidth_queue[c].end()) continue;
3617 ++j;
3618 for (queue_t::const_iterator i = m_bandwidth_queue[c].begin()
3619 , end(m_bandwidth_queue[c].end()); i != end && j != end; ++i, ++j)
3620 TORRENT_ASSERT(i->priority >= j->priority);
3623 int num_uploads = 0;
3624 std::map<piece_block, int> num_requests;
3625 for (const_peer_iterator i = begin(); i != end(); ++i)
3627 #ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS
3628 // make sure this peer is not a dangling pointer
3629 TORRENT_ASSERT(m_ses.has_peer(*i));
3630 #endif
3631 peer_connection const& p = *(*i);
3632 for (std::deque<piece_block>::const_iterator i = p.request_queue().begin()
3633 , end(p.request_queue().end()); i != end; ++i)
3634 ++num_requests[*i];
3635 for (std::deque<pending_block>::const_iterator i = p.download_queue().begin()
3636 , end(p.download_queue().end()); i != end; ++i)
3637 ++num_requests[i->block];
3638 if (!p.is_choked()) ++num_uploads;
3639 torrent* associated_torrent = p.associated_torrent().lock().get();
3640 if (associated_torrent != this)
3641 TORRENT_ASSERT(false);
3643 TORRENT_ASSERT(num_uploads == m_num_uploads);
3645 if (has_picker())
3647 for (std::map<piece_block, int>::iterator i = num_requests.begin()
3648 , end(num_requests.end()); i != end; ++i)
3650 if (!m_picker->is_downloaded(i->first))
3651 TORRENT_ASSERT(m_picker->num_peers(i->first) == i->second);
3653 TORRENT_ASSERT(num_have() >= m_picker->num_have_filtered());
3656 if (valid_metadata())
3658 TORRENT_ASSERT(m_abort || !m_picker || m_picker->num_pieces() == m_torrent_file->num_pieces());
3660 else
3662 TORRENT_ASSERT(m_abort || m_picker->num_pieces() == 0);
3665 #ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS
3666 for (policy::const_iterator i = m_policy.begin_peer()
3667 , end(m_policy.end_peer()); i != end; ++i)
3669 TORRENT_ASSERT(i->second.addr == i->first);
3671 #endif
3673 size_type total_done = quantized_bytes_done();
3674 if (m_torrent_file->is_valid())
3676 if (is_seed())
3677 TORRENT_ASSERT(total_done == m_torrent_file->total_size());
3678 else
3679 TORRENT_ASSERT(total_done != m_torrent_file->total_size() || !m_files_checked);
3681 TORRENT_ASSERT(m_block_size <= m_torrent_file->piece_length());
3683 else
3685 TORRENT_ASSERT(total_done == 0);
3688 if (m_picker && !m_abort)
3690 // make sure that pieces that have completed the download
3691 // of all their blocks are in the disk io thread's queue
3692 // to be checked.
3693 const std::vector<piece_picker::downloading_piece>& dl_queue
3694 = m_picker->get_download_queue();
3695 for (std::vector<piece_picker::downloading_piece>::const_iterator i =
3696 dl_queue.begin(); i != dl_queue.end(); ++i)
3698 const int blocks_per_piece = m_picker->blocks_in_piece(i->index);
3700 bool complete = true;
3701 for (int j = 0; j < blocks_per_piece; ++j)
3703 if (i->info[j].state == piece_picker::block_info::state_finished)
3704 continue;
3705 complete = false;
3706 break;
3711 // This check is very expensive.
3712 TORRENT_ASSERT(!valid_metadata() || m_block_size > 0);
3713 TORRENT_ASSERT(!valid_metadata() || (m_torrent_file->piece_length() % m_block_size) == 0);
3714 // if (is_seed()) TORRENT_ASSERT(m_picker.get() == 0);
3716 #endif
3718 void torrent::set_sequential_download(bool sd)
3719 { m_sequential_download = sd; }
3721 void torrent::set_queue_position(int p)
3723 TORRENT_ASSERT((p == -1) == is_finished()
3724 || (!m_auto_managed && p == -1)
3725 || (m_abort && p == -1));
3726 if (is_finished() && p != -1) return;
3727 if (p == m_sequence_number) return;
3729 session_impl::torrent_map& torrents = m_ses.m_torrents;
3730 if (p >= 0 && m_sequence_number == -1)
3732 int max_seq = -1;
3733 for (session_impl::torrent_map::iterator i = torrents.begin()
3734 , end(torrents.end()); i != end; ++i)
3736 torrent* t = i->second.get();
3737 if (t->m_sequence_number > max_seq) max_seq = t->m_sequence_number;
3739 m_sequence_number = (std::min)(max_seq + 1, p);
3741 else if (p < 0)
3743 for (session_impl::torrent_map::iterator i = torrents.begin()
3744 , end(torrents.end()); i != end; ++i)
3746 torrent* t = i->second.get();
3747 if (t == this) continue;
3748 if (t->m_sequence_number >= m_sequence_number
3749 && t->m_sequence_number != -1)
3750 --t->m_sequence_number;
3752 m_sequence_number = p;
3754 else if (p < m_sequence_number)
3756 for (session_impl::torrent_map::iterator i = torrents.begin()
3757 , end(torrents.end()); i != end; ++i)
3759 torrent* t = i->second.get();
3760 if (t == this) continue;
3761 if (t->m_sequence_number >= p
3762 && t->m_sequence_number < m_sequence_number
3763 && t->m_sequence_number != -1)
3764 ++t->m_sequence_number;
3766 m_sequence_number = p;
3768 else if (p > m_sequence_number)
3770 int max_seq = 0;
3771 for (session_impl::torrent_map::iterator i = torrents.begin()
3772 , end(torrents.end()); i != end; ++i)
3774 torrent* t = i->second.get();
3775 int pos = t->m_sequence_number;
3776 if (pos > max_seq) max_seq = pos;
3777 if (t == this) continue;
3779 if (pos <= p
3780 && pos > m_sequence_number
3781 && pos != -1)
3782 --t->m_sequence_number;
3785 m_sequence_number = (std::min)(max_seq, p);
3788 if (m_ses.m_auto_manage_time_scaler > 2)
3789 m_ses.m_auto_manage_time_scaler = 2;
3792 void torrent::set_max_uploads(int limit)
3794 TORRENT_ASSERT(limit >= -1);
3795 if (limit <= 0) limit = (std::numeric_limits<int>::max)();
3796 m_max_uploads = limit;
3799 void torrent::set_max_connections(int limit)
3801 TORRENT_ASSERT(limit >= -1);
3802 if (limit <= 0) limit = (std::numeric_limits<int>::max)();
3803 m_max_connections = limit;
3806 void torrent::set_peer_upload_limit(tcp::endpoint ip, int limit)
3808 TORRENT_ASSERT(limit >= -1);
3809 peer_iterator i = std::find_if(m_connections.begin(), m_connections.end()
3810 , bind(&peer_connection::remote, _1) == ip);
3811 if (i == m_connections.end()) return;
3812 (*i)->set_upload_limit(limit);
3815 void torrent::set_peer_download_limit(tcp::endpoint ip, int limit)
3817 TORRENT_ASSERT(limit >= -1);
3818 peer_iterator i = std::find_if(m_connections.begin(), m_connections.end()
3819 , bind(&peer_connection::remote, _1) == ip);
3820 if (i == m_connections.end()) return;
3821 (*i)->set_download_limit(limit);
3824 void torrent::set_upload_limit(int limit)
3826 TORRENT_ASSERT(limit >= -1);
3827 if (limit <= 0) limit = (std::numeric_limits<int>::max)();
3828 if (limit < num_peers() * 10) limit = num_peers() * 10;
3829 m_bandwidth_limit[peer_connection::upload_channel].throttle(limit);
3832 int torrent::upload_limit() const
3834 int limit = m_bandwidth_limit[peer_connection::upload_channel].throttle();
3835 if (limit == (std::numeric_limits<int>::max)()) limit = -1;
3836 return limit;
3839 void torrent::set_download_limit(int limit)
3841 TORRENT_ASSERT(limit >= -1);
3842 if (limit <= 0) limit = (std::numeric_limits<int>::max)();
3843 if (limit < num_peers() * 10) limit = num_peers() * 10;
3844 m_bandwidth_limit[peer_connection::download_channel].throttle(limit);
3847 int torrent::download_limit() const
3849 int limit = m_bandwidth_limit[peer_connection::download_channel].throttle();
3850 if (limit == (std::numeric_limits<int>::max)()) limit = -1;
3851 return limit;
3854 void torrent::delete_files()
3856 #if defined TORRENT_VERBOSE_LOGGING
3857 for (peer_iterator i = m_connections.begin();
3858 i != m_connections.end(); ++i)
3860 (*(*i)->m_logger) << "*** DELETING FILES IN TORRENT\n";
3862 #endif
3864 disconnect_all();
3865 stop_announcing();
3867 if (m_owning_storage.get())
3869 TORRENT_ASSERT(m_storage);
3870 m_storage->async_delete_files(
3871 bind(&torrent::on_files_deleted, shared_from_this(), _1, _2));
3875 void torrent::clear_error()
3877 if (m_error.empty()) return;
3878 if (m_ses.m_auto_manage_time_scaler > 2)
3879 m_ses.m_auto_manage_time_scaler = 2;
3880 m_error.clear();
3883 void torrent::auto_managed(bool a)
3885 INVARIANT_CHECK;
3887 if (m_auto_managed == a) return;
3888 bool checking_files = should_check_files();
3889 m_auto_managed = a;
3890 // recalculate which torrents should be
3891 // paused
3892 m_ses.m_auto_manage_time_scaler = 0;
3894 if (!checking_files && should_check_files())
3895 m_ses.check_torrent(shared_from_this());
3896 else if (checking_files && !should_check_files())
3898 // TODO: pause checking
3902 // the higher seed rank, the more important to seed
3903 int torrent::seed_rank(session_settings const& s) const
3905 enum flags
3907 seed_ratio_not_met = 0x400000,
3908 recently_started = 0x200000,
3909 no_seeds = 0x100000,
3910 prio_mask = 0xfffff
3913 if (!is_finished()) return 0;
3915 int scale = 100;
3916 if (!is_seed()) scale = 50;
3918 int ret = 0;
3920 ptime now(time_now());
3922 int seed_time = total_seconds(m_seeding_time);
3923 int download_time = total_seconds(m_active_time) - seed_time;
3925 // if we haven't yet met the seed limits, set the seed_ratio_not_met
3926 // flag. That will make this seed prioritized
3927 size_type downloaded = (std::max)(m_total_downloaded, m_torrent_file->total_size());
3928 if (seed_time < s.seed_time_limit
3929 && (seed_time > 1 && download_time / float(seed_time) < s.seed_time_ratio_limit)
3930 && m_total_uploaded / downloaded < s.share_ratio_limit)
3931 ret |= seed_ratio_not_met;
3933 // if this torrent is running, and it was started less
3934 // than 30 minutes ago, give it priority, to avoid oscillation
3935 if (!is_paused() && now - m_started < minutes(30))
3936 ret |= recently_started;
3938 // if we have any scrape data, use it to calculate
3939 // seed rank
3940 int seeds = 0;
3941 int downloaders = 0;
3943 if (m_complete >= 0) seeds = m_complete;
3944 else seeds = m_policy.num_seeds();
3946 if (m_incomplete >= 0) downloaders = m_incomplete;
3947 else downloaders = m_policy.num_peers() - m_policy.num_seeds();
3949 if (seeds == 0)
3951 ret |= no_seeds;
3952 ret |= downloaders & prio_mask;
3954 else
3956 ret |= (downloaders * scale / seeds) & prio_mask;
3959 return ret;
3962 // this is an async operation triggered by the client
3963 void torrent::save_resume_data()
3965 INVARIANT_CHECK;
3967 if (!m_owning_storage.get())
3969 if (alerts().should_post<save_resume_data_failed_alert>())
3971 alerts().post_alert(save_resume_data_failed_alert(get_handle()
3972 , "save resume data failed, torrent is being destructed"));
3974 return;
3977 TORRENT_ASSERT(m_storage);
3978 if (m_state == torrent_status::queued_for_checking
3979 || m_state == torrent_status::checking_files)
3981 if (alerts().should_post<save_resume_data_failed_alert>())
3983 alerts().post_alert(save_resume_data_failed_alert(get_handle()
3984 , "won't save resume data, torrent does not have a complete resume state yet"));
3986 return;
3988 m_storage->async_save_resume_data(
3989 bind(&torrent::on_save_resume_data, shared_from_this(), _1, _2));
3992 bool torrent::should_check_files() const
3994 return m_state == torrent_status::checking_files
3995 && (!is_paused() || m_auto_managed);
3998 bool torrent::is_paused() const
4000 return m_paused || m_ses.is_paused();
4003 void torrent::pause()
4005 INVARIANT_CHECK;
4007 if (m_paused) return;
4008 bool checking_files = should_check_files();
4009 m_paused = true;
4010 if (m_ses.is_paused()) return;
4011 do_pause();
4012 if (checking_files && !should_check_files())
4014 // TODO: pause checking
4018 void torrent::do_pause()
4020 if (!is_paused()) return;
4022 #ifndef TORRENT_DISABLE_EXTENSIONS
4023 for (extension_list_t::iterator i = m_extensions.begin()
4024 , end(m_extensions.end()); i != end; ++i)
4026 #ifndef BOOST_NO_EXCEPTIONS
4027 try {
4028 #endif
4029 if ((*i)->on_pause()) return;
4030 #ifndef BOOST_NO_EXCEPTIONS
4031 } catch (std::exception&) {}
4032 #endif
4034 #endif
4036 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
4037 for (peer_iterator i = m_connections.begin();
4038 i != m_connections.end(); ++i)
4040 (*(*i)->m_logger) << "*** PAUSING TORRENT\n";
4042 #endif
4044 // this will make the storage close all
4045 // files and flush all cached data
4046 if (m_owning_storage.get())
4048 TORRENT_ASSERT(m_storage);
4049 m_storage->async_release_files(
4050 bind(&torrent::on_torrent_paused, shared_from_this(), _1, _2));
4051 m_storage->async_clear_read_cache();
4053 else
4055 if (alerts().should_post<torrent_paused_alert>())
4056 alerts().post_alert(torrent_paused_alert(get_handle()));
4059 disconnect_all();
4060 stop_announcing();
4063 void torrent::resume()
4065 INVARIANT_CHECK;
4067 if (!m_paused) return;
4068 bool checking_files = should_check_files();
4069 m_paused = false;
4070 do_resume();
4071 if (!checking_files && should_check_files())
4072 m_ses.check_torrent(shared_from_this());
4075 void torrent::do_resume()
4077 if (is_paused()) return;
4079 #ifndef TORRENT_DISABLE_EXTENSIONS
4080 for (extension_list_t::iterator i = m_extensions.begin()
4081 , end(m_extensions.end()); i != end; ++i)
4083 #ifndef BOOST_NO_EXCEPTIONS
4084 try {
4085 #endif
4086 if ((*i)->on_resume()) return;
4087 #ifndef BOOST_NO_EXCEPTIONS
4088 } catch (std::exception&) {}
4089 #endif
4091 #endif
4093 if (alerts().should_post<torrent_resumed_alert>())
4094 alerts().post_alert(torrent_resumed_alert(get_handle()));
4096 m_started = time_now();
4097 m_error.clear();
4098 start_announcing();
4101 void torrent::restart_tracker_timer(ptime announce_at)
4103 if (!m_announcing) return;
4105 m_next_tracker_announce = announce_at;
4106 error_code ec;
4107 boost::weak_ptr<torrent> self(shared_from_this());
4108 m_tracker_timer.expires_at(m_next_tracker_announce, ec);
4109 m_tracker_timer.async_wait(bind(&torrent::on_tracker_announce_disp, self, _1));
4112 void torrent::start_announcing()
4114 if (is_paused()) return;
4115 // if we don't have metadata, we need to announce
4116 // before checking files, to get peers to
4117 // request the metadata from
4118 if (!m_files_checked && valid_metadata()) return;
4119 if (m_announcing) return;
4121 m_announcing = true;
4123 if (!m_trackers.empty())
4125 // tell the tracker that we're back
4126 m_start_sent = false;
4127 m_stat.clear();
4128 announce_with_tracker();
4131 // private torrents are never announced on LSD
4132 // or on DHT, we don't need this timer.
4133 if (!m_torrent_file->is_valid() || !m_torrent_file->priv())
4135 error_code ec;
4136 boost::weak_ptr<torrent> self(shared_from_this());
4137 m_lsd_announce_timer.expires_from_now(seconds(1), ec);
4138 m_lsd_announce_timer.async_wait(
4139 bind(&torrent::on_lsd_announce_disp, self, _1));
4143 void torrent::stop_announcing()
4145 if (!m_announcing) return;
4147 error_code ec;
4148 m_lsd_announce_timer.cancel(ec);
4149 m_tracker_timer.cancel(ec);
4151 m_announcing = false;
4153 if (!m_trackers.empty())
4154 announce_with_tracker(tracker_request::stopped);
4157 void torrent::second_tick(stat& accumulator, float tick_interval)
4159 INVARIANT_CHECK;
4161 #ifndef TORRENT_DISABLE_EXTENSIONS
4162 for (extension_list_t::iterator i = m_extensions.begin()
4163 , end(m_extensions.end()); i != end; ++i)
4165 #ifndef BOOST_NO_EXCEPTIONS
4166 try {
4167 #endif
4168 (*i)->tick();
4169 #ifndef BOOST_NO_EXCEPTIONS
4170 } catch (std::exception&) {}
4171 #endif
4173 #endif
4175 if (is_paused())
4177 // let the stats fade out to 0
4178 m_stat.second_tick(tick_interval);
4179 return;
4182 time_duration since_last_tick = microsec(tick_interval * 1000000L);
4183 if (is_seed()) m_seeding_time += since_last_tick;
4184 m_active_time += since_last_tick;
4186 // ---- WEB SEEDS ----
4188 // re-insert urls that are to be retrieds into the m_web_seeds
4189 typedef std::map<std::string, ptime>::iterator iter_t;
4190 for (iter_t i = m_web_seeds_next_retry.begin(); i != m_web_seeds_next_retry.end();)
4192 iter_t erase_element = i++;
4193 if (erase_element->second <= time_now())
4195 m_web_seeds.insert(erase_element->first);
4196 m_web_seeds_next_retry.erase(erase_element);
4200 // if we have everything we want we don't need to connect to any web-seed
4201 if (!is_finished() && !m_web_seeds.empty())
4203 // keep trying web-seeds if there are any
4204 // first find out which web seeds we are connected to
4205 std::set<std::string> web_seeds;
4206 for (peer_iterator i = m_connections.begin();
4207 i != m_connections.end(); ++i)
4209 web_peer_connection* p
4210 = dynamic_cast<web_peer_connection*>(*i);
4211 if (!p) continue;
4212 web_seeds.insert(p->url());
4215 for (std::set<std::string>::iterator i = m_resolving_web_seeds.begin()
4216 , end(m_resolving_web_seeds.end()); i != end; ++i)
4217 web_seeds.insert(web_seeds.begin(), *i);
4219 // from the list of available web seeds, subtract the ones we are
4220 // already connected to.
4221 std::vector<std::string> not_connected_web_seeds;
4222 std::set_difference(m_web_seeds.begin(), m_web_seeds.end(), web_seeds.begin()
4223 , web_seeds.end(), std::back_inserter(not_connected_web_seeds));
4225 // connect to all of those that we aren't connected to
4226 std::for_each(not_connected_web_seeds.begin(), not_connected_web_seeds.end()
4227 , bind(&torrent::connect_to_url_seed, this, _1));
4230 for (peer_iterator i = m_connections.begin();
4231 i != m_connections.end();)
4233 peer_connection* p = *i;
4234 ++i;
4235 p->calc_ip_overhead();
4236 m_stat += p->statistics();
4237 // updates the peer connection's ul/dl bandwidth
4238 // resource requests
4239 #ifndef BOOST_NO_EXCEPTIONS
4242 #endif
4243 p->second_tick(tick_interval);
4244 #ifndef BOOST_NO_EXCEPTIONS
4246 catch (std::exception& e)
4248 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
4249 (*p->m_logger) << "**ERROR**: " << e.what() << "\n";
4250 #endif
4251 p->disconnect(e.what(), 1);
4253 #endif
4255 accumulator += m_stat;
4256 m_total_uploaded += m_stat.last_payload_uploaded();
4257 m_total_downloaded += m_stat.last_payload_downloaded();
4258 m_stat.second_tick(tick_interval);
4260 m_time_scaler--;
4261 if (m_time_scaler <= 0)
4263 m_time_scaler = 10;
4264 m_policy.pulse();
4268 void torrent::retry_url_seed(std::string const& url)
4270 m_web_seeds_next_retry[url] = time_now()
4271 + seconds(m_ses.settings().urlseed_wait_retry);
4274 bool torrent::try_connect_peer()
4276 TORRENT_ASSERT(want_more_peers());
4277 if (m_deficit_counter < 100) return false;
4278 m_deficit_counter -= 100;
4279 bool ret = m_policy.connect_one_peer();
4280 return ret;
4283 void torrent::give_connect_points(int points)
4285 TORRENT_ASSERT(points <= 100);
4286 TORRENT_ASSERT(points > 0);
4287 TORRENT_ASSERT(want_more_peers());
4288 m_deficit_counter += points;
4291 void torrent::async_verify_piece(int piece_index, boost::function<void(int)> const& f)
4293 // INVARIANT_CHECK;
4295 TORRENT_ASSERT(m_storage);
4296 TORRENT_ASSERT(m_storage->refcount() > 0);
4297 TORRENT_ASSERT(piece_index >= 0);
4298 TORRENT_ASSERT(piece_index < m_torrent_file->num_pieces());
4299 TORRENT_ASSERT(piece_index < (int)m_picker->num_pieces());
4300 #ifndef NDEBUG
4301 if (m_picker)
4303 int blocks_in_piece = m_picker->blocks_in_piece(piece_index);
4304 for (int i = 0; i < blocks_in_piece; ++i)
4306 TORRENT_ASSERT(m_picker->num_peers(piece_block(piece_index, i)) == 0);
4309 #endif
4311 m_storage->async_hash(piece_index, bind(&torrent::on_piece_verified
4312 , shared_from_this(), _1, _2, f));
4313 #if !defined NDEBUG && !defined TORRENT_DISABLE_INVARIANT_CHECKS
4314 check_invariant();
4315 #endif
4318 void torrent::on_piece_verified(int ret, disk_io_job const& j
4319 , boost::function<void(int)> f)
4321 session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
4323 // return value:
4324 // 0: success, piece passed hash check
4325 // -1: disk failure
4326 // -2: hash check failed
4328 if (ret == -1)
4330 if (alerts().should_post<file_error_alert>())
4331 alerts().post_alert(file_error_alert(j.error_file, get_handle(), j.str));
4332 m_error = j.str;
4333 pause();
4335 f(ret);
4338 const tcp::endpoint& torrent::current_tracker() const
4340 return m_tracker_address;
4343 void torrent::file_progress(std::vector<float>& fp) const
4345 fp.clear();
4346 fp.resize(m_torrent_file->num_files(), 1.f);
4347 if (is_seed()) return;
4349 std::vector<size_type> progress;
4350 file_progress(progress);
4351 for (int i = 0; i < m_torrent_file->num_files(); ++i)
4353 file_entry const& f = m_torrent_file->file_at(i);
4354 if (f.size == 0) fp[i] = 1.f;
4355 else fp[i] = float(progress[i]) / f.size;
4359 void torrent::file_progress(std::vector<size_type>& fp) const
4361 TORRENT_ASSERT(valid_metadata());
4363 fp.resize(m_torrent_file->num_files(), 0);
4365 if (is_seed())
4367 for (int i = 0; i < m_torrent_file->num_files(); ++i)
4368 fp[i] = m_torrent_file->files().at(i).size;
4369 return;
4372 TORRENT_ASSERT(has_picker());
4374 for (int i = 0; i < m_torrent_file->num_files(); ++i)
4376 peer_request ret = m_torrent_file->files().map_file(i, 0, 0);
4377 size_type size = m_torrent_file->files().at(i).size;
4379 // zero sized files are considered
4380 // 100% done all the time
4381 if (size == 0)
4383 fp[i] = 0;
4384 continue;
4387 size_type done = 0;
4388 while (size > 0)
4390 size_type bytes_step = (std::min)(size_type(m_torrent_file->piece_size(ret.piece)
4391 - ret.start), size);
4392 if (m_picker->have_piece(ret.piece)) done += bytes_step;
4393 ++ret.piece;
4394 ret.start = 0;
4395 size -= bytes_step;
4397 TORRENT_ASSERT(size == 0);
4399 fp[i] = done;
4402 const std::vector<piece_picker::downloading_piece>& q
4403 = m_picker->get_download_queue();
4405 for (std::vector<piece_picker::downloading_piece>::const_iterator
4406 i = q.begin(), end(q.end()); i != end; ++i)
4408 size_type offset = size_type(i->index) * m_torrent_file->piece_length();
4409 torrent_info::file_iterator file = m_torrent_file->file_at_offset(offset);
4410 int file_index = file - m_torrent_file->begin_files();
4411 int num_blocks = m_picker->blocks_in_piece(i->index);
4412 piece_picker::block_info const* info = i->info;
4413 for (int k = 0; k < num_blocks; ++k)
4415 TORRENT_ASSERT(file != m_torrent_file->end_files());
4416 TORRENT_ASSERT(offset == size_type(i->index) * m_torrent_file->piece_length()
4417 + k * m_block_size);
4418 TORRENT_ASSERT(offset < m_torrent_file->total_size());
4419 while (offset >= file->offset + file->size)
4421 ++file;
4422 ++file_index;
4424 TORRENT_ASSERT(file != m_torrent_file->end_files());
4426 size_type block_size = m_block_size;
4428 if (info[k].state == piece_picker::block_info::state_none)
4430 offset += m_block_size;
4431 continue;
4434 if (info[k].state == piece_picker::block_info::state_requested)
4436 block_size = 0;
4437 policy::peer* p = static_cast<policy::peer*>(info[k].peer);
4438 if (p && p->connection)
4440 boost::optional<piece_block_progress> pbp
4441 = p->connection->downloading_piece_progress();
4442 if (pbp && pbp->piece_index == i->index && pbp->block_index == k)
4443 block_size = pbp->bytes_downloaded;
4444 TORRENT_ASSERT(block_size <= m_block_size);
4447 if (block_size == 0)
4449 offset += m_block_size;
4450 continue;
4454 if (offset + block_size > file->offset + file->size)
4456 int left_over = m_block_size - block_size;
4457 // split the block on multiple files
4458 while (block_size > 0)
4460 TORRENT_ASSERT(offset <= file->offset + file->size);
4461 size_type slice = (std::min)(file->offset + file->size - offset
4462 , block_size);
4463 fp[file_index] += slice;
4464 offset += slice;
4465 block_size -= slice;
4466 TORRENT_ASSERT(offset <= file->offset + file->size);
4467 if (offset == file->offset + file->size)
4469 ++file;
4470 ++file_index;
4471 if (file == m_torrent_file->end_files())
4473 offset += block_size;
4474 break;
4478 offset += left_over;
4479 TORRENT_ASSERT(offset == size_type(i->index) * m_torrent_file->piece_length()
4480 + (k+1) * m_block_size);
4482 else
4484 fp[file_index] += block_size;
4485 offset += m_block_size;
4487 TORRENT_ASSERT(file_index <= m_torrent_file->num_files());
4492 void torrent::set_state(torrent_status::state_t s)
4494 #ifndef NDEBUG
4495 if (s == torrent_status::seeding)
4496 TORRENT_ASSERT(is_seed());
4497 if (s == torrent_status::finished)
4498 TORRENT_ASSERT(is_finished());
4499 if (s == torrent_status::downloading && m_state == torrent_status::finished)
4500 TORRENT_ASSERT(!is_finished());
4501 #endif
4503 if (m_state == s) return;
4504 m_state = s;
4505 if (m_ses.m_alerts.should_post<state_changed_alert>())
4506 m_ses.m_alerts.post_alert(state_changed_alert(get_handle(), s));
4509 torrent_status torrent::status() const
4511 INVARIANT_CHECK;
4513 ptime now = time_now();
4515 torrent_status st;
4517 st.has_incoming = m_has_incoming;
4518 st.error = m_error;
4520 if (m_last_scrape == min_time())
4522 st.last_scrape = -1;
4524 else
4526 st.last_scrape = total_seconds(now - m_last_scrape);
4528 st.up_bandwidth_queue = (int)m_bandwidth_queue[peer_connection::upload_channel].size();
4529 st.down_bandwidth_queue = (int)m_bandwidth_queue[peer_connection::download_channel].size();
4531 st.num_peers = (int)std::count_if(m_connections.begin(), m_connections.end()
4532 , !boost::bind(&peer_connection::is_connecting, _1));
4534 st.list_peers = m_policy.num_peers();
4535 st.list_seeds = m_policy.num_seeds();
4536 st.connect_candidates = m_policy.num_connect_candidates();
4537 st.seed_rank = seed_rank(m_ses.m_settings);
4539 st.all_time_upload = m_total_uploaded;
4540 st.all_time_download = m_total_downloaded;
4542 st.active_time = total_seconds(m_active_time);
4543 st.seeding_time = total_seconds(m_seeding_time);
4545 st.storage_mode = m_storage_mode;
4547 st.num_complete = m_complete;
4548 st.num_incomplete = m_incomplete;
4549 st.paused = m_paused;
4550 boost::tie(st.total_done, st.total_wanted_done) = bytes_done();
4551 TORRENT_ASSERT(st.total_wanted_done >= 0);
4552 TORRENT_ASSERT(st.total_done >= st.total_wanted_done);
4554 // payload transfer
4555 st.total_payload_download = m_stat.total_payload_download();
4556 st.total_payload_upload = m_stat.total_payload_upload();
4558 // total transfer
4559 st.total_download = m_stat.total_payload_download()
4560 + m_stat.total_protocol_download();
4561 st.total_upload = m_stat.total_payload_upload()
4562 + m_stat.total_protocol_upload();
4564 // failed bytes
4565 st.total_failed_bytes = m_total_failed_bytes;
4566 st.total_redundant_bytes = m_total_redundant_bytes;
4568 // transfer rate
4569 st.download_rate = m_stat.download_rate();
4570 st.upload_rate = m_stat.upload_rate();
4571 st.download_payload_rate = m_stat.download_payload_rate();
4572 st.upload_payload_rate = m_stat.upload_payload_rate();
4574 st.next_announce = boost::posix_time::seconds(
4575 total_seconds(next_announce() - now));
4576 if (st.next_announce.is_negative() || is_paused())
4577 st.next_announce = boost::posix_time::seconds(0);
4579 st.announce_interval = boost::posix_time::seconds(m_duration);
4581 if (m_last_working_tracker >= 0)
4583 st.current_tracker
4584 = m_trackers[m_last_working_tracker].url;
4587 st.num_uploads = m_num_uploads;
4588 st.uploads_limit = m_max_uploads;
4589 st.num_connections = int(m_connections.size());
4590 st.connections_limit = m_max_connections;
4591 // if we don't have any metadata, stop here
4593 st.state = m_state;
4595 if (!valid_metadata())
4597 st.state = torrent_status::downloading_metadata;
4598 st.progress = m_progress;
4599 st.block_size = 0;
4600 return st;
4603 st.block_size = block_size();
4605 // fill in status that depends on metadata
4607 st.total_wanted = m_torrent_file->total_size();
4608 TORRENT_ASSERT(st.total_wanted >= 0);
4609 TORRENT_ASSERT(st.total_wanted >= m_torrent_file->piece_length()
4610 * (m_torrent_file->num_pieces() - 1));
4612 if (m_picker.get() && (m_picker->num_filtered() > 0
4613 || m_picker->num_have_filtered() > 0))
4615 int num_filtered_pieces = m_picker->num_filtered()
4616 + m_picker->num_have_filtered();
4617 int last_piece_index = m_torrent_file->num_pieces() - 1;
4618 if (m_picker->piece_priority(last_piece_index) == 0)
4620 st.total_wanted -= m_torrent_file->piece_size(last_piece_index);
4621 --num_filtered_pieces;
4624 st.total_wanted -= size_type(num_filtered_pieces) * m_torrent_file->piece_length();
4627 TORRENT_ASSERT(st.total_wanted >= st.total_wanted_done);
4629 if (m_state == torrent_status::checking_files)
4630 st.progress = m_progress;
4631 else if (st.total_wanted == 0) st.progress = 1.f;
4632 else st.progress = st.total_wanted_done
4633 / static_cast<float>(st.total_wanted);
4635 if (has_picker())
4637 int num_pieces = m_picker->num_pieces();
4638 st.pieces.resize(num_pieces, false);
4639 for (int i = 0; i < num_pieces; ++i)
4640 if (m_picker->have_piece(i)) st.pieces.set_bit(i);
4642 st.num_pieces = num_have();
4643 st.num_seeds = num_seeds();
4644 if (m_picker.get())
4645 st.distributed_copies = m_picker->distributed_copies();
4646 else
4647 st.distributed_copies = -1;
4648 return st;
4651 void torrent::add_redundant_bytes(int b)
4653 TORRENT_ASSERT(b > 0);
4654 m_total_redundant_bytes += b;
4655 m_ses.add_redundant_bytes(b);
4658 void torrent::add_failed_bytes(int b)
4660 TORRENT_ASSERT(b > 0);
4661 m_total_failed_bytes += b;
4662 m_ses.add_failed_bytes(b);
4665 int torrent::num_seeds() const
4667 INVARIANT_CHECK;
4669 return (int)std::count_if(m_connections.begin(), m_connections.end()
4670 , boost::bind(&peer_connection::is_seed, _1));
4673 void torrent::tracker_request_timed_out(
4674 tracker_request const& r)
4676 session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
4678 INVARIANT_CHECK;
4680 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
4681 debug_log("*** tracker timed out");
4682 #endif
4684 if (r.kind == tracker_request::announce_request)
4686 if (m_ses.m_alerts.should_post<tracker_error_alert>())
4688 m_ses.m_alerts.post_alert(tracker_error_alert(get_handle()
4689 , m_failed_trackers + 1, 0, r.url, "tracker timed out"));
4692 else if (r.kind == tracker_request::scrape_request)
4694 if (m_ses.m_alerts.should_post<scrape_failed_alert>())
4696 m_ses.m_alerts.post_alert(scrape_failed_alert(get_handle()
4697 , r.url, "tracker timed out"));
4701 if (r.kind == tracker_request::announce_request)
4702 try_next_tracker(r);
4705 // TODO: with some response codes, we should just consider
4706 // the tracker as a failure and not retry
4707 // it anymore
4708 void torrent::tracker_request_error(tracker_request const& r
4709 , int response_code, const std::string& str)
4711 session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
4713 INVARIANT_CHECK;
4715 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
4716 debug_log(std::string("*** tracker error: ") + str);
4717 #endif
4718 if (r.kind == tracker_request::announce_request)
4720 if (m_ses.m_alerts.should_post<tracker_error_alert>())
4722 m_ses.m_alerts.post_alert(tracker_error_alert(get_handle()
4723 , m_failed_trackers + 1, response_code, r.url, str));
4726 else if (r.kind == tracker_request::scrape_request)
4728 if (m_ses.m_alerts.should_post<scrape_failed_alert>())
4730 m_ses.m_alerts.post_alert(scrape_failed_alert(get_handle(), r.url, str));
4734 if (r.kind == tracker_request::announce_request)
4735 try_next_tracker(r);
4739 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
4740 void torrent::debug_log(const std::string& line)
4742 (*m_ses.m_logger) << time_now_string() << " " << line << "\n";
4744 #endif