3
Copyright (c) 2003, Arvid Norberg
6
Redistribution and use in source and binary forms, with or without
7
modification, are permitted provided that the following conditions
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"
46
#pragma warning(push, 1)
49
#include <boost/filesystem/convenience.hpp>
50
#include <boost/bind.hpp>
51
#include <boost/thread/mutex.hpp>
57
#include "libtorrent/torrent_handle.hpp"
58
#include "libtorrent/session.hpp"
59
#include "libtorrent/torrent_info.hpp"
60
#include "libtorrent/tracker_manager.hpp"
61
#include "libtorrent/parse_url.hpp"
62
#include "libtorrent/bencode.hpp"
63
#include "libtorrent/hasher.hpp"
64
#include "libtorrent/entry.hpp"
65
#include "libtorrent/peer.hpp"
66
#include "libtorrent/bt_peer_connection.hpp"
67
#include "libtorrent/web_peer_connection.hpp"
68
#include "libtorrent/peer_id.hpp"
69
#include "libtorrent/alert.hpp"
70
#include "libtorrent/identify_client.hpp"
71
#include "libtorrent/alert_types.hpp"
72
#include "libtorrent/extensions.hpp"
73
#include "libtorrent/aux_/session_impl.hpp"
74
#include "libtorrent/instantiate_connection.hpp"
75
#include "libtorrent/assert.hpp"
76
#include "libtorrent/broadcast_socket.hpp"
78
using namespace libtorrent;
79
using boost::tuples::tuple;
80
using boost::tuples::get;
81
using boost::tuples::make_tuple;
83
using libtorrent::aux::session_impl;
90
// wait 60 seconds before retrying a failed tracker
91
tracker_retry_delay_min = 60
92
// when tracker_failed_max trackers
93
// has failed, wait 10 minutes instead
94
, tracker_retry_delay_max = 10 * 60
95
, tracker_failed_max = 5
98
struct find_peer_by_ip
100
find_peer_by_ip(tcp::endpoint const& a, const torrent* t)
103
{ TORRENT_ASSERT(t != 0); }
105
bool operator()(session_impl::connection_map::value_type const& c) const
107
tcp::endpoint const& sender = c->remote();
108
if (sender.address() != ip.address()) return false;
109
if (tor != c->associated_torrent().lock().get()) return false;
113
tcp::endpoint const& ip;
119
peer_by_id(const peer_id& i): pid(i) {}
121
bool operator()(session_impl::connection_map::value_type const& p) const
123
if (p->pid() != pid) return false;
124
// have a special case for all zeros. We can have any number
125
// of peers with that pid, since it's used to indicate no pid.
126
if (std::count(pid.begin(), pid.end(), 0) == 20) return false;
139
, boost::intrusive_ptr<torrent_info> tf
140
, fs::path const& save_path
141
, tcp::endpoint const& net_interface
142
, storage_mode_t storage_mode
144
, storage_constructor_type sc
146
, std::vector<char>* resume_data
150
, m_active_time(seconds(0))
151
, m_seeding_time(seconds(0))
152
, m_total_uploaded(0)
153
, m_total_downloaded(0)
154
, m_started(time_now())
155
, m_last_scrape(min_time())
158
, m_next_tracker_announce(time_now())
159
, m_host_resolver(ses.m_io_service)
160
, m_lsd_announce_timer(ses.m_io_service)
161
, m_tracker_timer(ses.m_io_service)
162
#ifndef TORRENT_DISABLE_DHT
163
, m_last_dht_announce(time_now() - minutes(15))
166
, m_picker(new piece_picker())
167
, m_trackers(m_torrent_file->trackers())
168
, m_total_failed_bytes(0)
169
, m_total_redundant_bytes(0)
170
, m_net_interface(net_interface.address(), 0)
171
, m_save_path(complete(save_path))
172
, m_storage_mode(storage_mode)
173
, m_state(torrent_status::checking_resume_data)
174
, m_settings(ses.settings())
175
, m_storage_constructor(sc)
178
, m_max_uploads((std::numeric_limits<int>::max)())
180
, m_max_connections((std::numeric_limits<int>::max)())
181
, m_block_size((std::min)(block_size, tf->piece_length()))
184
, m_deficit_counter(0)
186
, m_sequence_number(seq)
187
, m_last_working_tracker(-1)
188
, m_currently_trying_tracker(0)
189
, m_failed_trackers(0)
193
, m_auto_managed(auto_managed)
194
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
195
, m_resolving_country(false)
196
, m_resolve_countries(false)
198
, m_sequential_download(false)
199
, m_got_tracker_response(false)
200
, m_connections_initialized(true)
201
, m_has_incoming(false)
202
, m_files_checked(false)
203
, m_queued_for_checking(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
213
h.update((char*)&tf->info_hash()[0], 20);
214
m_obfuscated_hash = h.final();
220
, char const* tracker_url
221
, sha1_hash const& info_hash
223
, fs::path const& save_path
224
, tcp::endpoint const& net_interface
225
, storage_mode_t storage_mode
227
, storage_constructor_type sc
229
, std::vector<char>* resume_data
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))
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))
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::checking_resume_data)
256
, m_settings(ses.settings())
257
, m_storage_constructor(sc)
260
, m_max_uploads((std::numeric_limits<int>::max)())
262
, m_max_connections((std::numeric_limits<int>::max)())
263
, m_block_size(block_size)
266
, m_deficit_counter(0)
268
, m_sequence_number(seq)
269
, m_last_working_tracker(-1)
270
, m_currently_trying_tracker(0)
271
, m_failed_trackers(0)
275
, m_auto_managed(auto_managed)
276
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
277
, m_resolving_country(false)
278
, m_resolve_countries(false)
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_queued_for_checking(false)
286
, m_announcing(false)
287
, m_start_sent(false)
288
, m_complete_sent(false)
290
if (resume_data) m_resume_data.swap(*resume_data);
292
#ifndef TORRENT_DISABLE_ENCRYPTION
295
h.update((char*)&info_hash[0], 20);
296
m_obfuscated_hash = h.final();
300
m_files_checked = false;
304
if (name) m_name.reset(new std::string(name));
306
if (tracker_url && std::strlen(tracker_url) > 0)
308
m_trackers.push_back(announce_entry(tracker_url));
309
m_torrent_file->add_tracker(tracker_url);
313
void torrent::start()
315
if (!m_resume_data.empty())
317
if (lazy_bdecode(&m_resume_data[0], &m_resume_data[0]
318
+ m_resume_data.size(), m_resume_entry) != 0)
320
std::vector<char>().swap(m_resume_data);
321
if (m_ses.m_alerts.should_post<fastresume_rejected_alert>())
323
m_ses.m_alerts.post_alert(fastresume_rejected_alert(get_handle(), "parse failed"));
324
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
325
(*m_ses.m_logger) << "fastresume data for "
326
<< torrent_file().name() << " rejected: parse failed\n";
332
// we need to start announcing since we don't have any
333
// metadata. To receive peers to ask for it.
334
if (m_torrent_file->is_valid()) init();
337
set_state(torrent_status::downloading_metadata);
338
if (!m_trackers.empty()) start_announcing();
344
#ifndef TORRENT_DISABLE_DHT
345
bool torrent::should_announce_dht() const
347
if (m_ses.m_listen_sockets.empty()) return false;
349
if (!m_ses.m_dht) return false;
350
if (m_torrent_file->is_valid() && !m_files_checked) return false;
352
// don't announce private torrents
353
if (m_torrent_file->is_valid() && m_torrent_file->priv()) return false;
354
if (m_trackers.empty()) return true;
356
return m_failed_trackers > 0 || !m_ses.settings().use_dht_as_fallback;
362
// The invariant can't be maintained here, since the torrent
363
// is being destructed, all weak references to it have been
364
// reset, which means that all its peers already have an
365
// invalidated torrent pointer (so it cannot be verified to be correct)
367
// i.e. the invariant can only be maintained if all connections have
368
// been closed by the time the torrent is destructed. And they are
369
// supposed to be closed. So we can still do the invariant check.
371
TORRENT_ASSERT(m_connections.empty());
375
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
376
for (peer_iterator i = m_connections.begin();
377
i != m_connections.end(); ++i)
379
(*(*i)->m_logger) << "*** DESTRUCTING TORRENT\n";
383
TORRENT_ASSERT(m_abort);
384
if (!m_connections.empty())
388
peer_request torrent::to_req(piece_block const& p)
390
int block_offset = p.block_index * m_block_size;
391
int block_size = (std::min)(torrent_file().piece_size(
392
p.piece_index) - block_offset, m_block_size);
393
TORRENT_ASSERT(block_size > 0);
394
TORRENT_ASSERT(block_size <= m_block_size);
397
r.piece = p.piece_index;
398
r.start = block_offset;
399
r.length = block_size;
403
std::string torrent::name() const
405
if (valid_metadata()) return m_torrent_file->name();
406
if (m_name) return *m_name;
410
#ifndef TORRENT_DISABLE_EXTENSIONS
412
void torrent::add_extension(boost::shared_ptr<torrent_plugin> ext)
414
m_extensions.push_back(ext);
417
void torrent::add_extension(boost::function<boost::shared_ptr<torrent_plugin>(torrent*, void*)> const& ext
420
boost::shared_ptr<torrent_plugin> tp(ext(this, userdata));
425
for (peer_iterator i = m_connections.begin();
426
i != m_connections.end(); ++i)
428
peer_connection* p = *i;
429
boost::shared_ptr<peer_plugin> pp(tp->new_connection(p));
430
if (pp) p->add_extension(pp);
433
// if files are checked for this torrent, call the extension
434
// to let it initialize itself
435
if (m_connections_initialized)
436
tp->on_files_checked();
441
// this may not be called from a constructor because of the call to
442
// shared_from_this()
445
TORRENT_ASSERT(m_torrent_file->is_valid());
446
TORRENT_ASSERT(m_torrent_file->num_files() > 0);
447
TORRENT_ASSERT(m_torrent_file->total_size() >= 0);
449
m_file_priority.clear();
450
m_file_priority.resize(m_torrent_file->num_files(), 1);
452
m_block_size = (std::min)(m_block_size, m_torrent_file->piece_length());
454
if (m_torrent_file->num_pieces()
455
> piece_picker::max_pieces)
457
set_error("too many pieces in torrent");
461
// the shared_from_this() will create an intentional
462
// cycle of ownership, se the hpp file for description.
463
m_owning_storage = new piece_manager(shared_from_this(), m_torrent_file
464
, m_save_path, m_ses.m_files, m_ses.m_disk_thread, m_storage_constructor
466
m_storage = m_owning_storage.get();
467
m_picker->init((std::max)(m_torrent_file->piece_length() / m_block_size, 1)
468
, int((m_torrent_file->total_size()+m_block_size-1)/m_block_size));
470
std::vector<std::string> const& url_seeds = m_torrent_file->url_seeds();
471
std::copy(url_seeds.begin(), url_seeds.end(), std::inserter(m_web_seeds
472
, m_web_seeds.begin()));
474
set_state(torrent_status::checking_resume_data);
476
if (m_resume_entry.type() == lazy_entry::dict_t)
478
char const* error = 0;
479
if (m_resume_entry.dict_find_string_value("file-format") != "libtorrent resume file")
480
error = "invalid file format tag";
482
std::string info_hash = m_resume_entry.dict_find_string_value("info-hash");
483
if (!error && info_hash.empty())
484
error = "missing info-hash";
486
if (!error && sha1_hash(info_hash) != m_torrent_file->info_hash())
487
error = "mismatching info-hash";
489
if (error && m_ses.m_alerts.should_post<fastresume_rejected_alert>())
491
m_ses.m_alerts.post_alert(fastresume_rejected_alert(get_handle(), error));
496
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
497
(*m_ses.m_logger) << "fastresume data for "
498
<< torrent_file().name() << " rejected: "
501
std::vector<char>().swap(m_resume_data);
502
lazy_entry().swap(m_resume_entry);
506
read_resume_data(m_resume_entry);
510
m_storage->async_check_fastresume(&m_resume_entry
511
, bind(&torrent::on_resume_data_checked
512
, shared_from_this(), _1, _2));
515
void torrent::on_resume_data_checked(int ret, disk_io_job const& j)
517
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
519
if (ret == piece_manager::fatal_disk_error)
521
if (m_ses.m_alerts.should_post<file_error_alert>())
523
m_ses.m_alerts.post_alert(file_error_alert(j.error_file, get_handle(), j.str));
525
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
526
(*m_ses.m_logger) << time_now_string() << ": fatal disk error ["
527
" error: " << j.str <<
528
" torrent: " << torrent_file().name() <<
534
std::vector<char>().swap(m_resume_data);
535
lazy_entry().swap(m_resume_entry);
540
if (m_resume_entry.type() == lazy_entry::dict_t)
542
// parse out "peers" from the resume data and add them to the peer list
543
if (lazy_entry const* peers_entry = m_resume_entry.dict_find_list("peers"))
547
for (int i = 0; i < peers_entry->list_size(); ++i)
549
lazy_entry const* e = peers_entry->list_at(i);
550
if (e->type() != lazy_entry::dict_t) continue;
551
std::string ip = e->dict_find_string_value("ip");
552
int port = e->dict_find_int_value("port");
553
if (ip.empty() || port == 0) continue;
555
tcp::endpoint a(address::from_string(ip, ec), (unsigned short)port);
557
m_policy.peer_from_tracker(a, id, peer_info::resume_data, 0);
561
// parse out "banned_peers" and add them as banned
562
if (lazy_entry const* banned_peers_entry = m_resume_entry.dict_find_list("banned_peers"))
566
for (int i = 0; i < banned_peers_entry->list_size(); ++i)
568
lazy_entry const* e = banned_peers_entry->list_at(i);
569
if (e->type() != lazy_entry::dict_t) continue;
570
std::string ip = e->dict_find_string_value("ip");
571
int port = e->dict_find_int_value("port");
572
if (ip.empty() || port == 0) continue;
574
tcp::endpoint a(address::from_string(ip, ec), (unsigned short)port);
576
policy::peer* p = m_policy.peer_from_tracker(a, id, peer_info::resume_data, 0);
577
if (p) p->banned = true;
582
bool fastresume_rejected = !j.str.empty();
584
if (fastresume_rejected && m_ses.m_alerts.should_post<fastresume_rejected_alert>())
586
m_ses.m_alerts.post_alert(fastresume_rejected_alert(get_handle(), j.str));
587
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
588
(*m_ses.m_logger) << "fastresume data for "
589
<< torrent_file().name() << " rejected: "
596
// there are either no files for this torrent
597
// or the resume_data was accepted
599
if (!fastresume_rejected && m_resume_entry.type() == lazy_entry::dict_t)
601
// parse have bitmask
602
lazy_entry const* pieces = m_resume_entry.dict_find("pieces");
603
if (pieces && pieces->type() == lazy_entry::string_t
604
&& int(pieces->string_length()) == m_torrent_file->num_pieces())
606
char const* pieces_str = pieces->string_ptr();
607
for (int i = 0, end(pieces->string_length()); i < end; ++i)
609
if ((pieces_str[i] & 1) == 0) continue;
610
m_picker->we_have(i);
615
lazy_entry const* slots = m_resume_entry.dict_find("slots");
616
if (slots && slots->type() == lazy_entry::list_t)
618
for (int i = 0; i < slots->list_size(); ++i)
620
int piece = slots->list_int_value_at(i, -1);
621
if (piece >= 0) m_picker->we_have(piece);
626
// parse unfinished pieces
627
int num_blocks_per_piece =
628
static_cast<int>(torrent_file().piece_length()) / block_size();
630
if (lazy_entry const* unfinished_ent = m_resume_entry.dict_find_list("unfinished"))
632
for (int i = 0; i < unfinished_ent->list_size(); ++i)
634
lazy_entry const* e = unfinished_ent->list_at(i);
635
if (e->type() != lazy_entry::dict_t) continue;
636
int piece = e->dict_find_int_value("piece", -1);
637
if (piece < 0 || piece > torrent_file().num_pieces()) continue;
639
if (m_picker->have_piece(piece))
640
m_picker->we_dont_have(piece);
642
std::string bitmask = e->dict_find_string_value("bitmask");
643
if (bitmask.empty()) continue;
645
const int num_bitmask_bytes = (std::max)(num_blocks_per_piece / 8, 1);
646
if ((int)bitmask.size() != num_bitmask_bytes) continue;
647
for (int j = 0; j < num_bitmask_bytes; ++j)
649
unsigned char bits = bitmask[j];
650
int num_bits = (std::min)(num_blocks_per_piece - j*8, 8);
651
for (int k = 0; k < num_bits; ++k)
653
const int bit = j * 8 + k;
656
m_picker->mark_as_finished(piece_block(piece, bit), 0);
657
if (m_picker->is_piece_finished(piece))
658
async_verify_piece(piece, bind(&torrent::piece_finished
659
, shared_from_this(), piece, _1));
671
// either the fastresume data was rejected or there are
673
set_state(torrent_status::queued_for_checking);
674
if (should_check_files())
675
queue_torrent_check();
678
std::vector<char>().swap(m_resume_data);
679
lazy_entry().swap(m_resume_entry);
682
void torrent::queue_torrent_check()
684
if (m_queued_for_checking) return;
685
m_queued_for_checking = true;
686
m_ses.check_torrent(shared_from_this());
689
void torrent::dequeue_torrent_check()
691
if (!m_queued_for_checking) return;
692
m_queued_for_checking = false;
693
m_ses.done_checking(shared_from_this());
696
void torrent::force_recheck()
698
// if the torrent is already queued to check its files
700
if (should_check_files()
701
|| m_state == torrent_status::checking_resume_data)
706
m_owning_storage->async_release_files();
707
if (!m_picker) m_picker.reset(new piece_picker());
708
m_picker->init(m_torrent_file->piece_length() / m_block_size
709
, int((m_torrent_file->total_size()+m_block_size-1)/m_block_size));
710
// assume that we don't have anything
711
m_files_checked = false;
712
set_state(torrent_status::checking_resume_data);
714
m_policy.recalculate_connect_candidates();
717
set_queue_position((std::numeric_limits<int>::max)());
719
std::vector<char>().swap(m_resume_data);
720
lazy_entry().swap(m_resume_entry);
721
m_storage->async_check_fastresume(&m_resume_entry
722
, bind(&torrent::on_force_recheck
723
, shared_from_this(), _1, _2));
726
void torrent::on_force_recheck(int ret, disk_io_job const& j)
728
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
730
if (ret == piece_manager::fatal_disk_error)
732
if (m_ses.m_alerts.should_post<file_error_alert>())
734
m_ses.m_alerts.post_alert(file_error_alert(j.error_file, get_handle(), j.str));
736
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
737
(*m_ses.m_logger) << time_now_string() << ": fatal disk error ["
738
" error: " << j.str <<
739
" torrent: " << torrent_file().name() <<
748
// if there are no files, just start
753
set_state(torrent_status::queued_for_checking);
754
if (should_check_files())
755
queue_torrent_check();
759
void torrent::start_checking()
761
TORRENT_ASSERT(should_check_files());
762
set_state(torrent_status::checking_files);
764
m_storage->async_check_files(bind(
765
&torrent::on_piece_checked
766
, shared_from_this(), _1, _2));
769
void torrent::on_piece_checked(int ret, disk_io_job const& j)
771
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
774
if (ret == piece_manager::disk_check_aborted)
779
if (ret == piece_manager::fatal_disk_error)
781
if (m_ses.m_alerts.should_post<file_error_alert>())
783
m_ses.m_alerts.post_alert(file_error_alert(j.error_file, get_handle(), j.str));
785
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
786
(*m_ses.m_logger) << time_now_string() << ": fatal disk error ["
787
" error: " << j.str <<
788
" torrent: " << torrent_file().name() <<
796
m_progress = j.piece / float(torrent_file().num_pieces());
798
TORRENT_ASSERT(m_picker);
799
if (j.offset >= 0 && !m_picker->have_piece(j.offset))
800
m_picker->we_have(j.offset);
802
// we're not done checking yet
803
// this handler will be called repeatedly until
804
// we're done, or encounter a failure
805
if (ret == piece_manager::need_full_check) return;
807
dequeue_torrent_check();
811
void torrent::use_interface(const char* net_interface)
816
address a(address::from_string(net_interface, ec));
818
m_net_interface = tcp::endpoint(a, 0);
821
void torrent::on_tracker_announce_disp(boost::weak_ptr<torrent> p
822
, error_code const& e)
825
boost::shared_ptr<torrent> t = p.lock();
827
t->on_tracker_announce();
830
void torrent::on_tracker_announce()
832
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
835
announce_with_tracker();
838
void torrent::on_lsd_announce_disp(boost::weak_ptr<torrent> p
839
, error_code const& e)
842
boost::shared_ptr<torrent> t = p.lock();
844
t->on_lsd_announce();
847
void torrent::on_lsd_announce()
849
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
853
TORRENT_ASSERT(!m_torrent_file->priv());
854
if (m_torrent_file->is_valid() && m_torrent_file->priv())
857
if (is_paused()) return;
859
boost::weak_ptr<torrent> self(shared_from_this());
863
// announce on local network every 5 minutes
864
m_lsd_announce_timer.expires_from_now(minutes(5), ec);
865
m_lsd_announce_timer.async_wait(
866
bind(&torrent::on_lsd_announce_disp, self, _1));
868
// announce with the local discovery service
869
m_ses.announce_lsd(m_torrent_file->info_hash());
871
#ifndef TORRENT_DISABLE_DHT
872
if (!m_ses.m_dht) return;
873
ptime now = time_now();
874
if (should_announce_dht() && now - m_last_dht_announce > minutes(14))
876
m_last_dht_announce = now;
877
m_ses.m_dht->announce(m_torrent_file->info_hash()
878
, m_ses.m_listen_sockets.front().external_port
879
, bind(&torrent::on_dht_announce_response_disp, self, _1));
884
#ifndef TORRENT_DISABLE_DHT
886
void torrent::on_dht_announce_response_disp(boost::weak_ptr<libtorrent::torrent> t
887
, std::vector<tcp::endpoint> const& peers)
889
boost::shared_ptr<libtorrent::torrent> tor = t.lock();
891
tor->on_dht_announce_response(peers);
894
void torrent::on_dht_announce_response(std::vector<tcp::endpoint> const& peers)
896
if (peers.empty()) return;
898
if (m_ses.m_alerts.should_post<dht_reply_alert>())
900
m_ses.m_alerts.post_alert(dht_reply_alert(
901
get_handle(), peers.size()));
903
std::for_each(peers.begin(), peers.end(), bind(
904
&policy::peer_from_tracker, boost::ref(m_policy), _1, peer_id(0)
905
, peer_info::dht, 0));
910
void torrent::announce_with_tracker(tracker_request::event_t e)
914
if (m_trackers.empty()) return;
916
if (m_currently_trying_tracker < 0) m_currently_trying_tracker = 0;
918
restart_tracker_timer(time_now() + seconds(tracker_retry_delay_max));
920
if (m_abort) e = tracker_request::stopped;
922
if (e == tracker_request::none)
924
if (!m_start_sent) e = tracker_request::started;
925
if (!m_complete_sent && is_seed()) e = tracker_request::completed;
929
req.info_hash = m_torrent_file->info_hash();
930
req.pid = m_ses.get_peer_id();
931
req.downloaded = m_stat.total_payload_download();
932
req.uploaded = m_stat.total_payload_upload();
933
req.left = bytes_left();
934
if (req.left == -1) req.left = 16*1024;
938
ep = m_ses.get_ipv6_interface();
939
if (ep != tcp::endpoint()) req.ipv6 = ep.address().to_string(ec);
940
ep = m_ses.get_ipv4_interface();
941
if (ep != tcp::endpoint()) req.ipv4 = ep.address().to_string(ec);
943
req.url = m_trackers[m_currently_trying_tracker].url;
944
// if we are aborting. we don't want any new peers
945
req.num_want = (req.event == tracker_request::stopped)
946
?0:m_settings.num_want;
948
req.listen_port = m_ses.m_listen_sockets.empty()
949
?0:m_ses.m_listen_sockets.front().external_port;
950
req.key = m_ses.m_key;
952
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
955
boost::shared_ptr<aux::tracker_logger> tl(new aux::tracker_logger(m_ses));
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(), tl);
961
m_ses.m_tracker_manager.queue_request(m_ses.m_io_service, m_ses.m_half_open, req
962
, tracker_login(), m_ses.m_listen_interface.address()
963
, m_abort?boost::shared_ptr<torrent>():shared_from_this());
965
if (m_ses.m_alerts.should_post<tracker_announce_alert>())
967
m_ses.m_alerts.post_alert(
968
tracker_announce_alert(get_handle(), req.url, req.event));
972
void torrent::scrape_tracker()
974
if (m_trackers.empty()) return;
976
TORRENT_ASSERT(m_currently_trying_tracker >= 0);
977
TORRENT_ASSERT(m_currently_trying_tracker < int(m_trackers.size()));
980
req.info_hash = m_torrent_file->info_hash();
981
req.kind = tracker_request::scrape_request;
982
req.url = m_trackers[m_currently_trying_tracker].url;
983
m_ses.m_tracker_manager.queue_request(m_ses.m_io_service, m_ses.m_half_open, req
984
, tracker_login(), m_ses.m_listen_interface.address(), shared_from_this());
986
m_last_scrape = time_now();
989
void torrent::tracker_warning(tracker_request const& req, std::string const& msg)
991
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
995
if (m_ses.m_alerts.should_post<tracker_warning_alert>())
996
m_ses.m_alerts.post_alert(tracker_warning_alert(get_handle(), req.url, msg));
999
void torrent::tracker_scrape_response(tracker_request const& req
1000
, int complete, int incomplete, int downloaded)
1002
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
1005
TORRENT_ASSERT(req.kind == tracker_request::scrape_request);
1007
if (complete >= 0) m_complete = complete;
1008
if (incomplete >= 0) m_incomplete = incomplete;
1010
if (m_ses.m_alerts.should_post<scrape_reply_alert>())
1012
m_ses.m_alerts.post_alert(scrape_reply_alert(
1013
get_handle(), m_incomplete, m_complete, req.url));
1017
void torrent::tracker_response(
1018
tracker_request const& r
1019
, std::vector<peer_entry>& peer_list
1023
, address const& external_ip)
1025
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
1028
TORRENT_ASSERT(r.kind == tracker_request::announce_request);
1030
if (external_ip != address())
1031
m_ses.set_external_address(external_ip);
1033
if (!m_start_sent && r.event == tracker_request::started)
1034
m_start_sent = true;
1035
if (!m_complete_sent && r.event == tracker_request::completed)
1036
m_complete_sent = true;
1038
m_failed_trackers = 0;
1040
if (interval < m_ses.settings().min_announce_interval)
1041
interval = m_ses.settings().min_announce_interval;
1043
m_last_working_tracker
1044
= prioritize_tracker(m_currently_trying_tracker);
1045
m_currently_trying_tracker = 0;
1047
m_duration = interval;
1048
restart_tracker_timer(time_now() + seconds(m_duration));
1050
if (complete >= 0) m_complete = complete;
1051
if (incomplete >= 0) m_incomplete = incomplete;
1052
if (complete >= 0 && incomplete >= 0)
1053
m_last_scrape = time_now();
1055
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
1056
std::stringstream s;
1057
s << "TRACKER RESPONSE:\n"
1058
"interval: " << m_duration << "\n"
1060
for (std::vector<peer_entry>::const_iterator i = peer_list.begin();
1061
i != peer_list.end(); ++i)
1063
s << " " << std::setfill(' ') << std::setw(16) << i->ip
1064
<< " " << std::setw(5) << std::dec << i->port << " ";
1065
if (!i->pid.is_all_zeros()) s << " " << i->pid << " " << identify_client(i->pid);
1068
s << "external ip: " << external_ip << "\n";
1071
// for each of the peers we got from the tracker
1072
for (std::vector<peer_entry>::iterator i = peer_list.begin();
1073
i != peer_list.end(); ++i)
1075
// don't make connections to ourself
1076
if (i->pid == m_ses.get_peer_id())
1080
tcp::endpoint a(address::from_string(i->ip, ec), i->port);
1084
// assume this is because we got a hostname instead of
1085
// an ip address from the tracker
1087
tcp::resolver::query q(i->ip, to_string(i->port).elems);
1088
m_host_resolver.async_resolve(q,
1089
bind(&torrent::on_peer_name_lookup, shared_from_this(), _1, _2, i->pid));
1093
m_policy.peer_from_tracker(a, i->pid, peer_info::tracker, 0);
1097
if (m_ses.m_alerts.should_post<tracker_reply_alert>())
1099
m_ses.m_alerts.post_alert(tracker_reply_alert(
1100
get_handle(), peer_list.size(), r.url));
1102
m_got_tracker_response = true;
1105
void torrent::on_peer_name_lookup(error_code const& e, tcp::resolver::iterator host
1108
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
1112
if (e || host == tcp::resolver::iterator() ||
1113
m_ses.is_aborted()) return;
1115
if (m_ses.m_ip_filter.access(host->endpoint().address()) & ip_filter::blocked)
1117
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
1119
debug_log("blocked ip from tracker: " + host->endpoint().address().to_string(ec));
1121
if (m_ses.m_alerts.should_post<peer_blocked_alert>())
1123
m_ses.m_alerts.post_alert(peer_blocked_alert(host->endpoint().address()));
1129
m_policy.peer_from_tracker(*host, pid, peer_info::tracker, 0);
1132
size_type torrent::bytes_left() const
1134
// if we don't have the metadata yet, we
1135
// cannot tell how big the torrent is.
1136
if (!valid_metadata()) return -1;
1137
return m_torrent_file->total_size()
1138
- quantized_bytes_done();
1141
size_type torrent::quantized_bytes_done() const
1145
if (!valid_metadata()) return 0;
1147
if (m_torrent_file->num_pieces() == 0)
1150
if (is_seed()) return m_torrent_file->total_size();
1152
const int last_piece = m_torrent_file->num_pieces() - 1;
1154
size_type total_done
1155
= size_type(num_have()) * m_torrent_file->piece_length();
1157
// if we have the last piece, we have to correct
1158
// the amount we have, since the first calculation
1159
// assumed all pieces were of equal size
1160
if (m_picker->have_piece(last_piece))
1162
int corr = m_torrent_file->piece_size(last_piece)
1163
- m_torrent_file->piece_length();
1169
// the first value is the total number of bytes downloaded
1170
// the second value is the number of bytes of those that haven't
1171
// been filtered as not wanted we have downloaded
1172
tuple<size_type, size_type> torrent::bytes_done() const
1176
if (!valid_metadata() || m_torrent_file->num_pieces() == 0)
1177
return tuple<size_type, size_type>(0,0);
1179
const int last_piece = m_torrent_file->num_pieces() - 1;
1180
const int piece_size = m_torrent_file->piece_length();
1183
return make_tuple(m_torrent_file->total_size()
1184
, m_torrent_file->total_size());
1186
TORRENT_ASSERT(num_have() >= m_picker->num_have_filtered());
1187
size_type wanted_done = size_type(num_have() - m_picker->num_have_filtered())
1189
TORRENT_ASSERT(wanted_done >= 0);
1191
size_type total_done
1192
= size_type(num_have()) * piece_size;
1193
TORRENT_ASSERT(num_have() < m_torrent_file->num_pieces());
1195
// if we have the last piece, we have to correct
1196
// the amount we have, since the first calculation
1197
// assumed all pieces were of equal size
1198
if (m_picker->have_piece(last_piece))
1200
TORRENT_ASSERT(total_done >= piece_size);
1201
int corr = m_torrent_file->piece_size(last_piece)
1203
TORRENT_ASSERT(corr <= 0);
1204
TORRENT_ASSERT(corr > -piece_size);
1206
if (m_picker->piece_priority(last_piece) != 0)
1208
TORRENT_ASSERT(wanted_done >= piece_size);
1209
wanted_done += corr;
1213
TORRENT_ASSERT(total_done <= m_torrent_file->total_size());
1214
TORRENT_ASSERT(wanted_done <= m_torrent_file->total_size());
1215
TORRENT_ASSERT(total_done >= wanted_done);
1217
const std::vector<piece_picker::downloading_piece>& dl_queue
1218
= m_picker->get_download_queue();
1220
const int blocks_per_piece = (piece_size + m_block_size - 1) / m_block_size;
1222
for (std::vector<piece_picker::downloading_piece>::const_iterator i =
1223
dl_queue.begin(); i != dl_queue.end(); ++i)
1226
int index = i->index;
1227
if (m_picker->have_piece(index)) continue;
1228
TORRENT_ASSERT(i->finished <= m_picker->blocks_in_piece(index));
1230
#ifdef TORRENT_DEBUG
1231
for (std::vector<piece_picker::downloading_piece>::const_iterator j = boost::next(i);
1232
j != dl_queue.end(); ++j)
1234
TORRENT_ASSERT(j->index != index);
1238
for (int j = 0; j < blocks_per_piece; ++j)
1240
TORRENT_ASSERT(m_picker->is_finished(piece_block(index, j)) == (i->info[j].state == piece_picker::block_info::state_finished));
1241
corr += (i->info[j].state == piece_picker::block_info::state_finished) * m_block_size;
1242
TORRENT_ASSERT(corr >= 0);
1243
TORRENT_ASSERT(index != last_piece || j < m_picker->blocks_in_last_piece()
1244
|| i->info[j].state != piece_picker::block_info::state_finished);
1247
// correction if this was the last piece
1248
// and if we have the last block
1249
if (i->index == last_piece
1250
&& i->info[m_picker->blocks_in_last_piece()-1].state
1251
== piece_picker::block_info::state_finished)
1253
corr -= m_block_size;
1254
corr += m_torrent_file->piece_size(last_piece) % m_block_size;
1257
if (m_picker->piece_priority(index) != 0)
1258
wanted_done += corr;
1261
TORRENT_ASSERT(total_done <= m_torrent_file->total_size());
1262
TORRENT_ASSERT(wanted_done <= m_torrent_file->total_size());
1264
std::map<piece_block, int> downloading_piece;
1265
for (const_peer_iterator i = begin(); i != end(); ++i)
1267
peer_connection* pc = *i;
1268
boost::optional<piece_block_progress> p
1269
= pc->downloading_piece_progress();
1272
if (m_picker->have_piece(p->piece_index))
1275
piece_block block(p->piece_index, p->block_index);
1276
if (m_picker->is_finished(block))
1279
std::map<piece_block, int>::iterator dp
1280
= downloading_piece.find(block);
1281
if (dp != downloading_piece.end())
1283
if (dp->second < p->bytes_downloaded)
1284
dp->second = p->bytes_downloaded;
1288
downloading_piece[block] = p->bytes_downloaded;
1290
#ifdef TORRENT_DEBUG
1291
TORRENT_ASSERT(p->bytes_downloaded <= p->full_block_bytes);
1292
int last_piece = m_torrent_file->num_pieces() - 1;
1293
if (p->piece_index == last_piece
1294
&& p->block_index == m_torrent_file->piece_size(last_piece) / block_size())
1295
TORRENT_ASSERT(p->full_block_bytes == m_torrent_file->piece_size(last_piece) % block_size());
1297
TORRENT_ASSERT(p->full_block_bytes == block_size());
1301
for (std::map<piece_block, int>::iterator i = downloading_piece.begin();
1302
i != downloading_piece.end(); ++i)
1304
total_done += i->second;
1305
if (m_picker->piece_priority(i->first.piece_index) != 0)
1306
wanted_done += i->second;
1309
TORRENT_ASSERT(total_done <= m_torrent_file->total_size());
1310
TORRENT_ASSERT(wanted_done <= m_torrent_file->total_size());
1312
#ifdef TORRENT_DEBUG
1314
if (total_done >= m_torrent_file->total_size())
1316
// Thist happens when a piece has been downloaded completely
1317
// but not yet verified against the hash
1318
std::cerr << "num_have: " << num_have() << std::endl;
1320
std::cerr << "unfinished:" << std::endl;
1322
for (std::vector<piece_picker::downloading_piece>::const_iterator i =
1323
dl_queue.begin(); i != dl_queue.end(); ++i)
1325
std::cerr << " " << i->index << " ";
1326
for (int j = 0; j < blocks_per_piece; ++j)
1328
std::cerr << (i->info[j].state == piece_picker::block_info::state_finished ? "1" : "0");
1330
std::cerr << std::endl;
1333
std::cerr << "downloading pieces:" << std::endl;
1335
for (std::map<piece_block, int>::iterator i = downloading_piece.begin();
1336
i != downloading_piece.end(); ++i)
1338
std::cerr << " " << i->first.piece_index << ":" << i->first.block_index
1339
<< " " << i->second << std::endl;
1344
TORRENT_ASSERT(total_done <= m_torrent_file->total_size());
1345
TORRENT_ASSERT(wanted_done <= m_torrent_file->total_size());
1349
TORRENT_ASSERT(total_done >= wanted_done);
1350
return make_tuple(total_done, wanted_done);
1353
// passed_hash_check
1354
// 0: success, piece passed check
1356
// -2: piece failed check
1357
void torrent::piece_finished(int index, int passed_hash_check)
1359
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
1361
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
1362
(*m_ses.m_logger) << time_now_string() << " *** PIECE_FINISHED [ p: "
1363
<< index << " chk: " << ((passed_hash_check == 0)
1364
?"passed":passed_hash_check == -1
1365
?"disk failed":"failed") << " ]\n";
1368
TORRENT_ASSERT(valid_metadata());
1370
if (passed_hash_check == 0)
1372
// the following call may cause picker to become invalid
1373
// in case we just became a seed
1374
piece_passed(index);
1376
else if (passed_hash_check == -2)
1378
// piece_failed() will restore the piece
1379
piece_failed(index);
1383
TORRENT_ASSERT(passed_hash_check == -1);
1384
m_picker->restore_piece(index);
1385
restore_piece_state(index);
1389
void torrent::piece_passed(int index)
1393
TORRENT_ASSERT(index >= 0);
1394
TORRENT_ASSERT(index < m_torrent_file->num_pieces());
1396
if (m_ses.m_alerts.should_post<piece_finished_alert>())
1398
m_ses.m_alerts.post_alert(piece_finished_alert(get_handle()
1402
bool was_finished = m_picker->num_filtered() + num_have()
1403
== torrent_file().num_pieces();
1405
std::vector<void*> downloaders;
1406
m_picker->get_downloaders(downloaders, index);
1408
// increase the trust point of all peers that sent
1409
// parts of this piece.
1410
std::set<void*> peers;
1411
std::copy(downloaders.begin(), downloaders.end(), std::inserter(peers, peers.begin()));
1413
m_picker->we_have(index);
1414
for (peer_iterator i = m_connections.begin(); i != m_connections.end();)
1416
peer_connection* p = *i;
1418
p->announce_piece(index);
1421
for (std::set<void*>::iterator i = peers.begin()
1422
, end(peers.end()); i != end; ++i)
1424
policy::peer* p = static_cast<policy::peer*>(*i);
1425
if (p == 0) continue;
1426
p->on_parole = false;
1428
// TODO: make this limit user settable
1429
if (p->trust_points > 20) p->trust_points = 20;
1430
if (p->connection) p->connection->received_valid_data(index);
1433
#ifndef TORRENT_DISABLE_EXTENSIONS
1434
for (extension_list_t::iterator i = m_extensions.begin()
1435
, end(m_extensions.end()); i != end; ++i)
1437
#ifndef BOOST_NO_EXCEPTIONS
1440
(*i)->on_piece_pass(index);
1441
#ifndef BOOST_NO_EXCEPTIONS
1442
} catch (std::exception&) {}
1447
// since this piece just passed, we might have
1448
// become uninterested in some peers where this
1449
// was the last piece we were interested in
1450
for (peer_iterator i = m_connections.begin();
1451
i != m_connections.end();)
1453
peer_connection* p = *i;
1454
// update_interest may disconnect the peer and
1455
// invalidate the iterator
1457
// if we're not interested already, no need to check
1458
if (!p->is_interesting()) continue;
1459
// if the peer doesn't have the piece we just got, it
1460
// wouldn't affect our interest
1461
if (!p->has_piece(index)) continue;
1462
p->update_interest();
1465
if (!was_finished && is_finished())
1468
// i.e. all the pieces we're interested in have
1469
// been downloaded. Release the files (they will open
1470
// in read only mode if needed)
1472
// if we just became a seed, picker is now invalid, since it
1473
// is deallocated by the torrent once it starts seeding
1477
void torrent::piece_failed(int index)
1479
// if the last piece fails the peer connection will still
1480
// think that it has received all of it until this function
1481
// resets the download queue. So, we cannot do the
1482
// invariant check here since it assumes:
1483
// (total_done == m_torrent_file->total_size()) => is_seed()
1486
TORRENT_ASSERT(m_storage);
1487
TORRENT_ASSERT(m_storage->refcount() > 0);
1488
TORRENT_ASSERT(m_picker.get());
1489
TORRENT_ASSERT(index >= 0);
1490
TORRENT_ASSERT(index < m_torrent_file->num_pieces());
1492
if (m_ses.m_alerts.should_post<hash_failed_alert>())
1493
m_ses.m_alerts.post_alert(hash_failed_alert(get_handle(), index));
1495
// increase the total amount of failed bytes
1496
add_failed_bytes(m_torrent_file->piece_size(index));
1498
std::vector<void*> downloaders;
1499
m_picker->get_downloaders(downloaders, index);
1501
// decrease the trust point of all peers that sent
1502
// parts of this piece.
1503
// first, build a set of all peers that participated
1504
std::set<void*> peers;
1505
std::copy(downloaders.begin(), downloaders.end(), std::inserter(peers, peers.begin()));
1507
#ifdef TORRENT_DEBUG
1508
for (std::vector<void*>::iterator i = downloaders.begin()
1509
, end(downloaders.end()); i != end; ++i)
1511
policy::peer* p = (policy::peer*)*i;
1512
if (p && p->connection)
1514
p->connection->piece_failed = true;
1519
#ifndef TORRENT_DISABLE_EXTENSIONS
1520
for (extension_list_t::iterator i = m_extensions.begin()
1521
, end(m_extensions.end()); i != end; ++i)
1523
#ifndef BOOST_NO_EXCEPTIONS
1526
(*i)->on_piece_failed(index);
1527
#ifndef BOOST_NO_EXCEPTIONS
1528
} catch (std::exception&) {}
1533
for (std::set<void*>::iterator i = peers.begin()
1534
, end(peers.end()); i != end; ++i)
1536
policy::peer* p = static_cast<policy::peer*>(*i);
1537
if (p == 0) continue;
1538
if (p->connection) p->connection->received_invalid_data(index);
1540
// either, we have received too many failed hashes
1541
// or this was the only peer that sent us this piece.
1542
// TODO: make this a changable setting
1543
if (p->trust_points <= -7
1544
|| peers.size() == 1)
1546
// we don't trust this peer anymore
1548
if (m_ses.m_alerts.should_post<peer_ban_alert>())
1551
if (p->connection) pid = p->connection->pid();
1552
m_ses.m_alerts.post_alert(peer_ban_alert(
1553
get_handle(), p->ip(), pid));
1556
// mark the peer as banned
1557
m_policy.ban_peer(p);
1561
#ifdef TORRENT_LOGGING
1562
(*m_ses.m_logger) << time_now_string() << " *** BANNING PEER [ " << p->ip()
1563
<< " ] 'too many corrupt pieces'\n";
1565
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
1566
(*p->connection->m_logger) << "*** BANNING PEER [ " << p->ip()
1567
<< " ] 'too many corrupt pieces'\n";
1569
p->connection->disconnect("too many corrupt pieces, banning peer");
1574
// we have to let the piece_picker know that
1575
// this piece failed the check as it can restore it
1576
// and mark it as being interesting for download
1577
// TODO: do this more intelligently! and keep track
1578
// of how much crap (data that failed hash-check) and
1579
// how much redundant data we have downloaded
1580
// if some clients has sent more than one piece
1581
// start with redownloading the pieces that the client
1582
// that has sent the least number of pieces
1583
m_picker->restore_piece(index);
1584
restore_piece_state(index);
1585
TORRENT_ASSERT(m_storage);
1587
TORRENT_ASSERT(m_picker->have_piece(index) == false);
1589
#ifdef TORRENT_DEBUG
1590
for (std::vector<void*>::iterator i = downloaders.begin()
1591
, end(downloaders.end()); i != end; ++i)
1593
policy::peer* p = (policy::peer*)*i;
1594
if (p && p->connection)
1596
p->connection->piece_failed = false;
1602
void torrent::restore_piece_state(int index)
1604
TORRENT_ASSERT(has_picker());
1605
for (peer_iterator i = m_connections.begin();
1606
i != m_connections.end(); ++i)
1608
peer_connection* p = *i;
1609
std::deque<pending_block> const& dq = p->download_queue();
1610
std::deque<piece_block> const& rq = p->request_queue();
1611
for (std::deque<pending_block>::const_iterator k = dq.begin()
1612
, end(dq.end()); k != end; ++k)
1614
if (k->block.piece_index != index) continue;
1615
m_picker->mark_as_downloading(k->block, p->peer_info_struct()
1616
, (piece_picker::piece_state_t)p->peer_speed());
1618
for (std::deque<piece_block>::const_iterator k = rq.begin()
1619
, end(rq.end()); k != end; ++k)
1621
if (k->piece_index != index) continue;
1622
m_picker->mark_as_downloading(*k, p->peer_info_struct()
1623
, (piece_picker::piece_state_t)p->peer_speed());
1628
void torrent::abort()
1632
if (m_abort) return;
1635
// if the torrent is paused, it doesn't need
1636
// to announce with even=stopped again.
1642
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
1643
for (peer_iterator i = m_connections.begin();
1644
i != m_connections.end(); ++i)
1646
(*(*i)->m_logger) << "*** ABORTING TORRENT\n";
1650
// disconnect all peers and close all
1651
// files belonging to the torrents
1653
if (m_owning_storage.get())
1655
m_storage->async_release_files(
1656
bind(&torrent::on_files_released, shared_from_this(), _1, _2));
1657
m_storage->abort_disk_io();
1660
dequeue_torrent_check();
1662
if (m_state == torrent_status::checking_files)
1663
set_state(torrent_status::queued_for_checking);
1665
m_owning_storage = 0;
1666
m_host_resolver.cancel();
1669
void torrent::on_files_deleted(int ret, disk_io_job const& j)
1671
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
1675
if (alerts().should_post<torrent_delete_failed_alert>())
1676
alerts().post_alert(torrent_delete_failed_alert(get_handle(), j.str));
1680
if (alerts().should_post<torrent_deleted_alert>())
1681
alerts().post_alert(torrent_deleted_alert(get_handle()));
1685
void torrent::on_files_released(int ret, disk_io_job const& j)
1688
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
1690
if (alerts().should_post<torrent_paused_alert>())
1692
alerts().post_alert(torrent_paused_alert(get_handle()));
1697
void torrent::on_save_resume_data(int ret, disk_io_job const& j)
1699
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
1701
if (!j.resume_data && alerts().should_post<save_resume_data_failed_alert>())
1703
alerts().post_alert(save_resume_data_failed_alert(get_handle(), j.str));
1707
if (j.resume_data && alerts().should_post<save_resume_data_alert>())
1709
write_resume_data(*j.resume_data);
1710
alerts().post_alert(save_resume_data_alert(j.resume_data
1715
void torrent::on_file_renamed(int ret, disk_io_job const& j)
1717
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
1722
if (alerts().should_post<file_renamed_alert>())
1723
alerts().post_alert(file_renamed_alert(get_handle(), j.str, j.piece));
1724
m_torrent_file->rename_file(j.piece, j.str);
1728
if (alerts().should_post<file_rename_failed_alert>())
1729
alerts().post_alert(file_rename_failed_alert(get_handle(), j.str, j.piece));
1734
void torrent::on_torrent_paused(int ret, disk_io_job const& j)
1736
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
1738
if (alerts().should_post<torrent_paused_alert>())
1739
alerts().post_alert(torrent_paused_alert(get_handle()));
1742
std::string torrent::tracker_login() const
1744
if (m_username.empty() && m_password.empty()) return "";
1745
return m_username + ":" + m_password;
1748
void torrent::piece_availability(std::vector<int>& avail) const
1752
TORRENT_ASSERT(valid_metadata());
1759
m_picker->get_availability(avail);
1762
void torrent::set_piece_priority(int index, int priority)
1766
TORRENT_ASSERT(valid_metadata());
1767
if (is_seed()) return;
1769
// this call is only valid on torrents with metadata
1770
TORRENT_ASSERT(m_picker.get());
1771
TORRENT_ASSERT(index >= 0);
1772
TORRENT_ASSERT(index < m_torrent_file->num_pieces());
1774
bool was_finished = is_finished();
1775
bool filter_updated = m_picker->set_piece_priority(index, priority);
1776
TORRENT_ASSERT(num_have() >= m_picker->num_have_filtered());
1777
if (filter_updated) update_peer_interest(was_finished);
1780
int torrent::piece_priority(int index) const
1784
TORRENT_ASSERT(valid_metadata());
1785
if (is_seed()) return 1;
1787
// this call is only valid on torrents with metadata
1788
TORRENT_ASSERT(m_picker.get());
1789
TORRENT_ASSERT(index >= 0);
1790
TORRENT_ASSERT(index < m_torrent_file->num_pieces());
1792
return m_picker->piece_priority(index);
1795
void torrent::prioritize_pieces(std::vector<int> const& pieces)
1799
// this call is only valid on torrents with metadata
1800
TORRENT_ASSERT(valid_metadata());
1801
if (is_seed()) return;
1803
TORRENT_ASSERT(m_picker.get());
1806
bool filter_updated = false;
1807
bool was_finished = is_finished();
1808
for (std::vector<int>::const_iterator i = pieces.begin()
1809
, end(pieces.end()); i != end; ++i, ++index)
1811
TORRENT_ASSERT(*i >= 0);
1812
TORRENT_ASSERT(*i <= 7);
1813
filter_updated |= m_picker->set_piece_priority(index, *i);
1814
TORRENT_ASSERT(num_have() >= m_picker->num_have_filtered());
1816
if (filter_updated) update_peer_interest(was_finished);
1819
void torrent::piece_priorities(std::vector<int>& pieces) const
1823
// this call is only valid on torrents with metadata
1824
TORRENT_ASSERT(valid_metadata());
1828
pieces.resize(m_torrent_file->num_pieces(), 1);
1832
TORRENT_ASSERT(m_picker.get());
1833
m_picker->piece_priorities(pieces);
1838
void set_if_greater(int& piece_prio, int file_prio)
1840
if (file_prio > piece_prio) piece_prio = file_prio;
1844
void torrent::prioritize_files(std::vector<int> const& files)
1848
// this call is only valid on torrents with metadata
1849
if (!valid_metadata() || is_seed()) return;
1851
// the bitmask need to have exactly one bit for every file
1853
TORRENT_ASSERT(int(files.size()) == m_torrent_file->num_files());
1855
if (m_torrent_file->num_pieces() == 0) return;
1857
std::copy(files.begin(), files.end(), m_file_priority.begin());
1858
update_piece_priorities();
1861
void torrent::set_file_priority(int index, int prio)
1864
TORRENT_ASSERT(index < m_torrent_file->num_files());
1865
TORRENT_ASSERT(index >= 0);
1866
if (m_file_priority[index] == prio) return;
1867
m_file_priority[index] = prio;
1868
update_piece_priorities();
1871
int torrent::file_priority(int index) const
1873
TORRENT_ASSERT(index < m_torrent_file->num_files());
1874
TORRENT_ASSERT(index >= 0);
1875
return m_file_priority[index];
1878
void torrent::file_priorities(std::vector<int>& files) const
1881
files.resize(m_file_priority.size());
1882
std::copy(m_file_priority.begin(), m_file_priority.end(), files.begin());
1885
void torrent::update_piece_priorities()
1889
if (m_torrent_file->num_pieces() == 0) return;
1891
size_type position = 0;
1892
int piece_length = m_torrent_file->piece_length();
1893
// initialize the piece priorities to 0, then only allow
1894
// setting higher priorities
1895
std::vector<int> pieces(m_torrent_file->num_pieces(), 0);
1896
for (int i = 0; i < int(m_file_priority.size()); ++i)
1898
size_type start = position;
1899
size_type size = m_torrent_file->files().at(i).size;
1900
if (size == 0) continue;
1902
if (m_file_priority[i] == 0) continue;
1904
// mark all pieces of the file with this file's priority
1905
// but only if the priority is higher than the pieces
1906
// already set (to avoid problems with overlapping pieces)
1907
int start_piece = int(start / piece_length);
1908
int last_piece = int((position - 1) / piece_length);
1909
TORRENT_ASSERT(last_piece < int(pieces.size()));
1910
// if one piece spans several files, we might
1911
// come here several times with the same start_piece, end_piece
1912
std::for_each(pieces.begin() + start_piece
1913
, pieces.begin() + last_piece + 1
1914
, bind(&set_if_greater, _1, m_file_priority[i]));
1916
prioritize_pieces(pieces);
1919
// this is called when piece priorities have been updated
1920
// updates the interested flag in peers
1921
void torrent::update_peer_interest(bool was_finished)
1923
for (peer_iterator i = begin(); i != end();)
1925
peer_connection* p = *i;
1926
// update_interest may disconnect the peer and
1927
// invalidate the iterator
1929
p->update_interest();
1932
// the torrent just became finished
1933
if (is_finished() && !was_finished)
1937
else if (!is_finished() && was_finished)
1939
// if we used to be finished, but we aren't anymore
1940
// we may need to connect to peers again
1945
void torrent::filter_piece(int index, bool filter)
1949
TORRENT_ASSERT(valid_metadata());
1950
if (is_seed()) return;
1952
// this call is only valid on torrents with metadata
1953
TORRENT_ASSERT(m_picker.get());
1954
TORRENT_ASSERT(index >= 0);
1955
TORRENT_ASSERT(index < m_torrent_file->num_pieces());
1957
bool was_finished = is_finished();
1958
m_picker->set_piece_priority(index, filter ? 1 : 0);
1959
update_peer_interest(was_finished);
1962
void torrent::filter_pieces(std::vector<bool> const& bitmask)
1966
// this call is only valid on torrents with metadata
1967
TORRENT_ASSERT(valid_metadata());
1968
if (is_seed()) return;
1970
TORRENT_ASSERT(m_picker.get());
1972
bool was_finished = is_finished();
1974
for (std::vector<bool>::const_iterator i = bitmask.begin()
1975
, end(bitmask.end()); i != end; ++i, ++index)
1977
if ((m_picker->piece_priority(index) == 0) == *i) continue;
1979
m_picker->set_piece_priority(index, 0);
1981
m_picker->set_piece_priority(index, 1);
1983
update_peer_interest(was_finished);
1986
bool torrent::is_piece_filtered(int index) const
1988
// this call is only valid on torrents with metadata
1989
TORRENT_ASSERT(valid_metadata());
1990
if (is_seed()) return false;
1992
TORRENT_ASSERT(m_picker.get());
1993
TORRENT_ASSERT(index >= 0);
1994
TORRENT_ASSERT(index < m_torrent_file->num_pieces());
1996
return m_picker->piece_priority(index) == 0;
1999
void torrent::filtered_pieces(std::vector<bool>& bitmask) const
2003
// this call is only valid on torrents with metadata
2004
TORRENT_ASSERT(valid_metadata());
2008
bitmask.resize(m_torrent_file->num_pieces(), false);
2012
TORRENT_ASSERT(m_picker.get());
2013
m_picker->filtered_pieces(bitmask);
2016
void torrent::filter_files(std::vector<bool> const& bitmask)
2020
// this call is only valid on torrents with metadata
2021
if (!valid_metadata() || is_seed()) return;
2023
// the bitmask need to have exactly one bit for every file
2025
TORRENT_ASSERT((int)bitmask.size() == m_torrent_file->num_files());
2027
size_type position = 0;
2029
if (m_torrent_file->num_pieces())
2031
int piece_length = m_torrent_file->piece_length();
2032
// mark all pieces as filtered, then clear the bits for files
2033
// that should be downloaded
2034
std::vector<bool> piece_filter(m_torrent_file->num_pieces(), true);
2035
for (int i = 0; i < (int)bitmask.size(); ++i)
2037
size_type start = position;
2038
position += m_torrent_file->files().at(i).size;
2039
// is the file selected for download?
2042
// mark all pieces of the file as downloadable
2043
int start_piece = int(start / piece_length);
2044
int last_piece = int(position / piece_length);
2045
// if one piece spans several files, we might
2046
// come here several times with the same start_piece, end_piece
2047
std::fill(piece_filter.begin() + start_piece, piece_filter.begin()
2048
+ last_piece + 1, false);
2051
filter_pieces(piece_filter);
2055
void torrent::replace_trackers(std::vector<announce_entry> const& urls)
2058
std::remove_copy_if(urls.begin(), urls.end(), back_inserter(m_trackers)
2059
, boost::bind(&std::string::empty, boost::bind(&announce_entry::url, _1)));
2061
if (m_currently_trying_tracker >= (int)m_trackers.size())
2062
m_currently_trying_tracker = (int)m_trackers.size()-1;
2063
m_last_working_tracker = -1;
2064
if (!m_trackers.empty()) start_announcing();
2065
else stop_announcing();
2068
void torrent::choke_peer(peer_connection& c)
2072
TORRENT_ASSERT(!c.is_choked());
2073
TORRENT_ASSERT(m_num_uploads > 0);
2078
bool torrent::unchoke_peer(peer_connection& c)
2082
TORRENT_ASSERT(c.is_choked());
2083
if (m_num_uploads >= m_max_uploads) return false;
2084
if (!c.send_unchoke()) return false;
2089
void torrent::cancel_block(piece_block block)
2093
for (peer_iterator i = m_connections.begin()
2094
, end(m_connections.end()); i != end; ++i)
2096
(*i)->cancel_request(block);
2100
void torrent::remove_peer(peer_connection* p)
2104
TORRENT_ASSERT(p != 0);
2106
peer_iterator i = m_connections.find(p);
2107
if (i == m_connections.end())
2109
TORRENT_ASSERT(false);
2113
if (ready_for_connections())
2115
TORRENT_ASSERT(p->associated_torrent().lock().get() == this);
2121
m_picker->dec_refcount_all();
2128
bitfield const& pieces = p->get_bitfield();
2129
TORRENT_ASSERT(pieces.count() < int(pieces.size()));
2130
m_picker->dec_refcount(pieces);
2135
if (!p->is_choked())
2138
m_ses.m_unchoke_time_scaler = 0;
2141
if (p->peer_info_struct() && p->peer_info_struct()->optimistically_unchoked)
2143
m_ses.m_optimistic_unchoke_time_scaler = 0;
2146
m_policy.connection_closed(*p);
2147
p->set_peer_info(0);
2148
TORRENT_ASSERT(i != m_connections.end());
2149
m_connections.erase(i);
2151
// remove from bandwidth request-queue
2152
for (int c = 0; c < 2; ++c)
2154
for (queue_t::iterator i = m_bandwidth_queue[c].begin()
2155
, end(m_bandwidth_queue[c].end()); i != end; ++i)
2157
if (i->peer != p) continue;
2158
m_bandwidth_queue[c].erase(i);
2164
void torrent::connect_to_url_seed(std::string const& url)
2168
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
2169
(*m_ses.m_logger) << time_now_string() << " resolving web seed: " << url << "\n";
2172
std::string protocol;
2174
std::string hostname;
2178
boost::tie(protocol, auth, hostname, port, path, error)
2179
= parse_url_components(url);
2183
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
2184
(*m_ses.m_logger) << time_now_string() << " failed to parse web seed url: " << error << "\n";
2186
// never try it again
2187
remove_url_seed(url);
2191
#ifdef TORRENT_USE_OPENSSL
2192
if (protocol != "http" && protocol != "https")
2194
if (protocol != "http")
2197
if (m_ses.m_alerts.should_post<url_seed_alert>())
2199
m_ses.m_alerts.post_alert(
2200
url_seed_alert(get_handle(), url, "unknown protocol"));
2202
// never try it again
2203
remove_url_seed(url);
2207
if (hostname.empty())
2209
if (m_ses.m_alerts.should_post<url_seed_alert>())
2211
m_ses.m_alerts.post_alert(
2212
url_seed_alert(get_handle(), url, "invalid hostname"));
2214
// never try it again
2215
remove_url_seed(url);
2221
if (m_ses.m_alerts.should_post<url_seed_alert>())
2223
m_ses.m_alerts.post_alert(
2224
url_seed_alert(get_handle(), url, "invalid port"));
2226
// never try it again
2227
remove_url_seed(url);
2231
m_resolving_web_seeds.insert(url);
2232
proxy_settings const& ps = m_ses.web_seed_proxy();
2233
if (ps.type == proxy_settings::http
2234
|| ps.type == proxy_settings::http_pw)
2237
tcp::resolver::query q(ps.hostname, to_string(ps.port).elems);
2238
m_host_resolver.async_resolve(q,
2239
bind(&torrent::on_proxy_name_lookup, shared_from_this(), _1, _2, url));
2243
if (m_ses.m_port_filter.access(port) & port_filter::blocked)
2245
if (m_ses.m_alerts.should_post<url_seed_alert>())
2247
m_ses.m_alerts.post_alert(
2248
url_seed_alert(get_handle(), url, "port blocked by port-filter"));
2250
// never try it again
2251
remove_url_seed(url);
2255
tcp::resolver::query q(hostname, to_string(port).elems);
2256
m_host_resolver.async_resolve(q,
2257
bind(&torrent::on_name_lookup, shared_from_this(), _1, _2, url
2258
, tcp::endpoint()));
2263
void torrent::on_proxy_name_lookup(error_code const& e, tcp::resolver::iterator host
2266
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
2270
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
2271
(*m_ses.m_logger) << time_now_string() << " completed resolve proxy hostname for: " << url << "\n";
2274
if (m_abort) return;
2276
if (e || host == tcp::resolver::iterator())
2278
if (m_ses.m_alerts.should_post<url_seed_alert>())
2280
m_ses.m_alerts.post_alert(
2281
url_seed_alert(get_handle(), url, e.message()));
2284
// the name lookup failed for the http host. Don't try
2286
remove_url_seed(url);
2290
if (m_ses.is_aborted()) return;
2292
tcp::endpoint a(host->endpoint());
2294
using boost::tuples::ignore;
2295
std::string hostname;
2298
boost::tie(ignore, ignore, hostname, port, ignore, error)
2299
= parse_url_components(url);
2303
if (m_ses.m_alerts.should_post<url_seed_alert>())
2305
m_ses.m_alerts.post_alert(
2306
url_seed_alert(get_handle(), url, error));
2308
remove_url_seed(url);
2312
if (m_ses.m_ip_filter.access(a.address()) & ip_filter::blocked)
2314
if (m_ses.m_alerts.should_post<peer_blocked_alert>())
2315
m_ses.m_alerts.post_alert(peer_blocked_alert(a.address()));
2319
tcp::resolver::query q(hostname, to_string(port).elems);
2320
m_host_resolver.async_resolve(q,
2321
bind(&torrent::on_name_lookup, shared_from_this(), _1, _2, url, a));
2324
void torrent::on_name_lookup(error_code const& e, tcp::resolver::iterator host
2325
, std::string url, tcp::endpoint proxy)
2327
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
2331
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
2332
(*m_ses.m_logger) << time_now_string() << " completed resolve: " << url << "\n";
2335
if (m_abort) return;
2337
std::set<std::string>::iterator i = m_resolving_web_seeds.find(url);
2338
if (i != m_resolving_web_seeds.end()) m_resolving_web_seeds.erase(i);
2340
if (e || host == tcp::resolver::iterator())
2342
if (m_ses.m_alerts.should_post<url_seed_alert>())
2344
std::stringstream msg;
2345
msg << "HTTP seed hostname lookup failed: " << e.message();
2346
m_ses.m_alerts.post_alert(
2347
url_seed_alert(get_handle(), url, msg.str()));
2349
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
2350
(*m_ses.m_logger) << " ** HOSTNAME LOOKUP FAILED!**: " << url << "\n";
2353
// the name lookup failed for the http host. Don't try
2355
remove_url_seed(url);
2359
if (m_ses.is_aborted()) return;
2361
tcp::endpoint a(host->endpoint());
2363
if (m_ses.m_ip_filter.access(a.address()) & ip_filter::blocked)
2365
if (m_ses.m_alerts.should_post<peer_blocked_alert>())
2366
m_ses.m_alerts.post_alert(peer_blocked_alert(a.address()));
2370
boost::shared_ptr<socket_type> s(new (std::nothrow) socket_type(m_ses.m_io_service));
2373
bool ret = instantiate_connection(m_ses.m_io_service, m_ses.web_seed_proxy(), *s);
2375
TORRENT_ASSERT(ret);
2377
if (m_ses.web_seed_proxy().type == proxy_settings::http
2378
|| m_ses.web_seed_proxy().type == proxy_settings::http_pw)
2380
// the web seed connection will talk immediately to
2381
// the proxy, without requiring CONNECT support
2382
s->get<http_stream>().set_no_connect(true);
2385
boost::intrusive_ptr<peer_connection> c(new (std::nothrow) web_peer_connection(
2386
m_ses, shared_from_this(), s, a, url, 0));
2389
#ifdef TORRENT_DEBUG
2390
c->m_in_constructor = false;
2393
#ifndef TORRENT_DISABLE_EXTENSIONS
2394
for (extension_list_t::iterator i = m_extensions.begin()
2395
, end(m_extensions.end()); i != end; ++i)
2397
boost::shared_ptr<peer_plugin> pp((*i)->new_connection(c.get()));
2398
if (pp) c->add_extension(pp);
2402
#ifndef BOOST_NO_EXCEPTIONS
2406
// add the newly connected peer to this torrent's peer list
2407
m_connections.insert(boost::get_pointer(c));
2408
m_ses.m_connections.insert(c);
2411
m_ses.m_half_open.enqueue(
2412
bind(&peer_connection::connect, c, _1)
2413
, bind(&peer_connection::timed_out, c)
2414
, seconds(settings().peer_connect_timeout));
2415
#ifndef BOOST_NO_EXCEPTIONS
2417
catch (std::exception& e)
2419
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
2420
(*m_ses.m_logger) << " ** HOSTNAME LOOKUP FAILED!**: " << e.what() << "\n";
2422
c->disconnect(e.what(), 1);
2427
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
2430
unsigned long swap_bytes(unsigned long a)
2432
return (a >> 24) | ((a & 0xff0000) >> 8) | ((a & 0xff00) << 8) | ((a & 0xff) << 24);
2436
void torrent::resolve_peer_country(boost::intrusive_ptr<peer_connection> const& p) const
2438
if (m_resolving_country
2440
|| p->is_connecting()
2442
|| p->in_handshake()
2443
|| p->remote().address().is_v6()) return;
2445
asio::ip::address_v4 reversed(swap_bytes(p->remote().address().to_v4().to_ulong()));
2447
tcp::resolver::query q(reversed.to_string(ec) + ".zz.countries.nerd.dk", "0");
2450
p->set_country("!!");
2453
m_resolving_country = true;
2454
m_host_resolver.async_resolve(q,
2455
bind(&torrent::on_country_lookup, shared_from_this(), _1, _2, p));
2460
struct country_entry
2467
void torrent::on_country_lookup(error_code const& error, tcp::resolver::iterator i
2468
, intrusive_ptr<peer_connection> p) const
2470
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
2474
m_resolving_country = false;
2476
if (m_abort) return;
2478
// must be ordered in increasing order
2479
static const country_entry country_map[] =
2481
{ 4, "AF"}, { 8, "AL"}, { 10, "AQ"}, { 12, "DZ"}, { 16, "AS"}
2482
, { 20, "AD"}, { 24, "AO"}, { 28, "AG"}, { 31, "AZ"}, { 32, "AR"}
2483
, { 36, "AU"}, { 40, "AT"}, { 44, "BS"}, { 48, "BH"}, { 50, "BD"}
2484
, { 51, "AM"}, { 52, "BB"}, { 56, "BE"}, { 60, "BM"}, { 64, "BT"}
2485
, { 68, "BO"}, { 70, "BA"}, { 72, "BW"}, { 74, "BV"}, { 76, "BR"}
2486
, { 84, "BZ"}, { 86, "IO"}, { 90, "SB"}, { 92, "VG"}, { 96, "BN"}
2487
, {100, "BG"}, {104, "MM"}, {108, "BI"}, {112, "BY"}, {116, "KH"}
2488
, {120, "CM"}, {124, "CA"}, {132, "CV"}, {136, "KY"}, {140, "CF"}
2489
, {144, "LK"}, {148, "TD"}, {152, "CL"}, {156, "CN"}, {158, "TW"}
2490
, {162, "CX"}, {166, "CC"}, {170, "CO"}, {174, "KM"}, {175, "YT"}
2491
, {178, "CG"}, {180, "CD"}, {184, "CK"}, {188, "CR"}, {191, "HR"}
2492
, {192, "CU"}, {203, "CZ"}, {204, "BJ"}, {208, "DK"}, {212, "DM"}
2493
, {214, "DO"}, {218, "EC"}, {222, "SV"}, {226, "GQ"}, {231, "ET"}
2494
, {232, "ER"}, {233, "EE"}, {234, "FO"}, {238, "FK"}, {239, "GS"}
2495
, {242, "FJ"}, {246, "FI"}, {248, "AX"}, {250, "FR"}, {254, "GF"}
2496
, {258, "PF"}, {260, "TF"}, {262, "DJ"}, {266, "GA"}, {268, "GE"}
2497
, {270, "GM"}, {275, "PS"}, {276, "DE"}, {288, "GH"}, {292, "GI"}
2498
, {296, "KI"}, {300, "GR"}, {304, "GL"}, {308, "GD"}, {312, "GP"}
2499
, {316, "GU"}, {320, "GT"}, {324, "GN"}, {328, "GY"}, {332, "HT"}
2500
, {334, "HM"}, {336, "VA"}, {340, "HN"}, {344, "HK"}, {348, "HU"}
2501
, {352, "IS"}, {356, "IN"}, {360, "ID"}, {364, "IR"}, {368, "IQ"}
2502
, {372, "IE"}, {376, "IL"}, {380, "IT"}, {384, "CI"}, {388, "JM"}
2503
, {392, "JP"}, {398, "KZ"}, {400, "JO"}, {404, "KE"}, {408, "KP"}
2504
, {410, "KR"}, {414, "KW"}, {417, "KG"}, {418, "LA"}, {422, "LB"}
2505
, {426, "LS"}, {428, "LV"}, {430, "LR"}, {434, "LY"}, {438, "LI"}
2506
, {440, "LT"}, {442, "LU"}, {446, "MO"}, {450, "MG"}, {454, "MW"}
2507
, {458, "MY"}, {462, "MV"}, {466, "ML"}, {470, "MT"}, {474, "MQ"}
2508
, {478, "MR"}, {480, "MU"}, {484, "MX"}, {492, "MC"}, {496, "MN"}
2509
, {498, "MD"}, {500, "MS"}, {504, "MA"}, {508, "MZ"}, {512, "OM"}
2510
, {516, "NA"}, {520, "NR"}, {524, "NP"}, {528, "NL"}, {530, "AN"}
2511
, {533, "AW"}, {540, "NC"}, {548, "VU"}, {554, "NZ"}, {558, "NI"}
2512
, {562, "NE"}, {566, "NG"}, {570, "NU"}, {574, "NF"}, {578, "NO"}
2513
, {580, "MP"}, {581, "UM"}, {583, "FM"}, {584, "MH"}, {585, "PW"}
2514
, {586, "PK"}, {591, "PA"}, {598, "PG"}, {600, "PY"}, {604, "PE"}
2515
, {608, "PH"}, {612, "PN"}, {616, "PL"}, {620, "PT"}, {624, "GW"}
2516
, {626, "TL"}, {630, "PR"}, {634, "QA"}, {634, "QA"}, {638, "RE"}
2517
, {642, "RO"}, {643, "RU"}, {646, "RW"}, {654, "SH"}, {659, "KN"}
2518
, {660, "AI"}, {662, "LC"}, {666, "PM"}, {670, "VC"}, {674, "SM"}
2519
, {678, "ST"}, {682, "SA"}, {686, "SN"}, {690, "SC"}, {694, "SL"}
2520
, {702, "SG"}, {703, "SK"}, {704, "VN"}, {705, "SI"}, {706, "SO"}
2521
, {710, "ZA"}, {716, "ZW"}, {724, "ES"}, {732, "EH"}, {736, "SD"}
2522
, {740, "SR"}, {744, "SJ"}, {748, "SZ"}, {752, "SE"}, {756, "CH"}
2523
, {760, "SY"}, {762, "TJ"}, {764, "TH"}, {768, "TG"}, {772, "TK"}
2524
, {776, "TO"}, {780, "TT"}, {784, "AE"}, {788, "TN"}, {792, "TR"}
2525
, {795, "TM"}, {796, "TC"}, {798, "TV"}, {800, "UG"}, {804, "UA"}
2526
, {807, "MK"}, {818, "EG"}, {826, "GB"}, {834, "TZ"}, {840, "US"}
2527
, {850, "VI"}, {854, "BF"}, {858, "UY"}, {860, "UZ"}, {862, "VE"}
2528
, {876, "WF"}, {882, "WS"}, {887, "YE"}, {891, "CS"}, {894, "ZM"}
2531
if (error || i == tcp::resolver::iterator())
2533
// this is used to indicate that we shouldn't
2534
// try to resolve it again
2535
p->set_country("--");
2539
while (i != tcp::resolver::iterator()
2540
&& !i->endpoint().address().is_v4()) ++i;
2541
if (i != tcp::resolver::iterator())
2543
// country is an ISO 3166 country code
2544
int country = i->endpoint().address().to_v4().to_ulong() & 0xffff;
2546
// look up the country code in the map
2547
const int size = sizeof(country_map)/sizeof(country_map[0]);
2548
country_entry tmp = {country, ""};
2549
country_entry const* i =
2550
std::lower_bound(country_map, country_map + size, tmp
2551
, bind(&country_entry::code, _1) < bind(&country_entry::code, _2));
2552
if (i == country_map + size
2553
|| i->code != country)
2556
p->set_country("!!");
2557
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
2558
(*m_ses.m_logger) << "IP " << p->remote().address() << " was mapped to unknown country: " << country << "\n";
2563
p->set_country(i->name);
2568
void torrent::read_resume_data(lazy_entry const& rd)
2570
m_total_uploaded = rd.dict_find_int_value("total_uploaded");
2571
m_total_downloaded = rd.dict_find_int_value("total_downloaded");
2572
m_active_time = seconds(rd.dict_find_int_value("active_time"));
2573
m_seeding_time = seconds(rd.dict_find_int_value("seeding_time"));
2574
m_complete = rd.dict_find_int_value("num_seeds", -1);
2575
m_incomplete = rd.dict_find_int_value("num_downloaders", -1);
2576
set_upload_limit(rd.dict_find_int_value("upload_rate_limit", -1));
2577
set_download_limit(rd.dict_find_int_value("download_rate_limit", -1));
2578
set_max_connections(rd.dict_find_int_value("max_connections", -1));
2579
set_max_uploads(rd.dict_find_int_value("max_uploads", -1));
2581
lazy_entry const* file_priority = rd.dict_find_list("file_priority");
2582
if (file_priority && file_priority->list_size()
2583
== m_torrent_file->num_files())
2585
for (int i = 0; i < file_priority->list_size(); ++i)
2586
m_file_priority[i] = file_priority->list_int_value_at(i, 1);
2587
update_piece_priorities();
2589
lazy_entry const* piece_priority = rd.dict_find_string("piece_priority");
2590
if (piece_priority && piece_priority->string_length()
2591
== m_torrent_file->num_pieces())
2593
char const* p = piece_priority->string_ptr();
2594
for (int i = 0; i < piece_priority->string_length(); ++i)
2595
m_picker->set_piece_priority(i, p[i]);
2598
int auto_managed_ = rd.dict_find_int_value("auto_managed", -1);
2599
if (auto_managed_ != -1) m_auto_managed = auto_managed_;
2601
int sequential_ = rd.dict_find_int_value("sequential_download", -1);
2602
if (sequential_ != -1) set_sequential_download(sequential_);
2604
int paused_ = rd.dict_find_int_value("paused", -1);
2605
if (paused_ != -1) m_paused = paused_;
2607
lazy_entry const* trackers = rd.dict_find_list("trackers");
2611
for (int i = 0; i < trackers->list_size(); ++i)
2613
lazy_entry const* tier_list = trackers->list_at(i);
2614
if (tier_list == 0 || tier_list->type() != lazy_entry::list_t)
2616
for (int j = 0; j < tier_list->list_size(); ++j)
2618
announce_entry e(tier_list->list_string_value_at(j));
2619
if (std::find_if(m_trackers.begin(), m_trackers.end()
2620
, boost::bind(&announce_entry::url, _1) == e.url) != m_trackers.end())
2623
m_trackers.push_back(e);
2627
std::sort(m_trackers.begin(), m_trackers.end(), boost::bind(&announce_entry::tier, _1)
2628
< boost::bind(&announce_entry::tier, _2));
2631
lazy_entry const* mapped_files = rd.dict_find_list("mapped_files");
2632
if (mapped_files && mapped_files->list_size() == m_torrent_file->num_files())
2634
for (int i = 0; i < m_torrent_file->num_files(); ++i)
2636
std::string new_filename = mapped_files->list_string_value_at(i);
2637
if (new_filename.empty()) continue;
2638
m_torrent_file->rename_file(i, new_filename);
2642
lazy_entry const* url_list = rd.dict_find_list("url-list");
2645
for (int i = 0; i < url_list->list_size(); ++i)
2647
std::string url = url_list->list_string_value_at(i);
2648
if (url.empty()) continue;
2649
m_web_seeds.insert(url);
2654
void torrent::write_resume_data(entry& ret) const
2656
ret["file-format"] = "libtorrent resume file";
2657
ret["file-version"] = 1;
2658
ret["libtorrent-version"] = LIBTORRENT_VERSION;
2660
ret["total_uploaded"] = m_total_uploaded;
2661
ret["total_downloaded"] = m_total_downloaded;
2663
ret["active_time"] = total_seconds(m_active_time);
2664
ret["seeding_time"] = total_seconds(m_seeding_time);
2667
int downloaders = 0;
2668
if (m_complete >= 0) seeds = m_complete;
2669
else seeds = m_policy.num_seeds();
2670
if (m_incomplete >= 0) downloaders = m_incomplete;
2671
else downloaders = m_policy.num_peers() - m_policy.num_seeds();
2673
ret["num_seeds"] = seeds;
2674
ret["num_downloaders"] = downloaders;
2676
ret["sequential_download"] = m_sequential_download;
2678
const sha1_hash& info_hash = torrent_file().info_hash();
2679
ret["info-hash"] = std::string((char*)info_hash.begin(), (char*)info_hash.end());
2682
int num_blocks_per_piece =
2683
static_cast<int>(torrent_file().piece_length()) / block_size();
2684
ret["blocks per piece"] = num_blocks_per_piece;
2686
// if this torrent is a seed, we won't have a piece picker
2687
// and there will be no half-finished pieces.
2690
const std::vector<piece_picker::downloading_piece>& q
2691
= m_picker->get_download_queue();
2693
// unfinished pieces
2694
ret["unfinished"] = entry::list_type();
2695
entry::list_type& up = ret["unfinished"].list();
2697
// info for each unfinished piece
2698
for (std::vector<piece_picker::downloading_piece>::const_iterator i
2699
= q.begin(); i != q.end(); ++i)
2701
if (i->finished == 0) continue;
2703
entry piece_struct(entry::dictionary_t);
2705
// the unfinished piece's index
2706
piece_struct["piece"] = i->index;
2708
std::string bitmask;
2709
const int num_bitmask_bytes
2710
= (std::max)(num_blocks_per_piece / 8, 1);
2712
for (int j = 0; j < num_bitmask_bytes; ++j)
2714
unsigned char v = 0;
2715
int bits = (std::min)(num_blocks_per_piece - j*8, 8);
2716
for (int k = 0; k < bits; ++k)
2717
v |= (i->info[j*8+k].state == piece_picker::block_info::state_finished)
2719
bitmask.insert(bitmask.end(), v);
2720
TORRENT_ASSERT(bits == 8 || j == num_bitmask_bytes - 1);
2722
piece_struct["bitmask"] = bitmask;
2723
// push the struct onto the unfinished-piece list
2724
up.push_back(piece_struct);
2729
if (!m_trackers.empty())
2731
entry::list_type& tr_list = ret["trackers"].list();
2732
tr_list.push_back(entry::list_type());
2734
for (std::vector<announce_entry>::const_iterator i = m_trackers.begin()
2735
, end(m_trackers.end()); i != end; ++i)
2737
if (i->tier == tier)
2739
tr_list.back().list().push_back(i->url);
2743
tr_list.push_back(entry::list_t);
2744
tr_list.back().list().push_back(i->url);
2751
if (!m_web_seeds.empty())
2753
entry::list_type& url_list = ret["url-list"].list();
2754
for (std::set<std::string>::const_iterator i = m_web_seeds.begin()
2755
, end(m_web_seeds.end()); i != end; ++i)
2757
url_list.push_back(*i);
2761
// write have bitmask
2762
entry::string_type& pieces = ret["pieces"].string();
2763
pieces.resize(m_torrent_file->num_pieces());
2766
std::memset(&pieces[0], 1, pieces.size());
2770
for (int i = 0, end(pieces.size()); i < end; ++i)
2771
pieces[i] = m_picker->have_piece(i) ? 1 : 0;
2774
// write renamed files
2775
if (&m_torrent_file->files() != &m_torrent_file->orig_files())
2777
entry::list_type& fl = ret["mapped_files"].list();
2778
for (torrent_info::file_iterator i = m_torrent_file->begin_files()
2779
, end(m_torrent_file->end_files()); i != end; ++i)
2781
fl.push_back(i->path.string());
2785
// write local peers
2787
entry::list_type& peer_list = ret["peers"].list();
2788
entry::list_type& banned_peer_list = ret["banned_peers"].list();
2790
int max_failcount = m_ses.m_settings.max_failcount;
2792
for (policy::const_iterator i = m_policy.begin_peer()
2793
, end(m_policy.end_peer()); i != end; ++i)
2796
if (i->second.banned)
2798
entry peer(entry::dictionary_t);
2799
peer["ip"] = i->second.addr.to_string(ec);
2801
peer["port"] = i->second.port;
2802
banned_peer_list.push_back(peer);
2805
// we cannot save remote connection
2806
// since we don't know their listen port
2807
// unless they gave us their listen port
2808
// through the extension handshake
2809
// so, if the peer is not connectable (i.e. we
2810
// don't know its listen port) or if it has
2811
// been banned, don't save it.
2812
if (i->second.type == policy::peer::not_connectable) continue;
2814
// don't save peers that doesn't work
2815
if (i->second.failcount >= max_failcount) continue;
2817
entry peer(entry::dictionary_t);
2818
peer["ip"] = i->second.addr.to_string(ec);
2820
peer["port"] = i->second.port;
2821
peer_list.push_back(peer);
2824
ret["upload_rate_limit"] = upload_limit();
2825
ret["download_rate_limit"] = download_limit();
2826
ret["max_connections"] = max_connections();
2827
ret["max_uploads"] = max_uploads();
2828
ret["paused"] = m_paused;
2829
ret["auto_managed"] = m_auto_managed;
2831
// write piece priorities
2832
entry::string_type& piece_priority = ret["piece_priority"].string();
2833
piece_priority.resize(m_torrent_file->num_pieces());
2836
std::memset(&piece_priority[0], 1, pieces.size());
2840
for (int i = 0, end(piece_priority.size()); i < end; ++i)
2841
piece_priority[i] = m_picker->piece_priority(i);
2844
// write file priorities
2845
entry::list_type& file_priority = ret["file_priority"].list();
2846
file_priority.clear();
2847
for (int i = 0, end(m_file_priority.size()); i < end; ++i)
2848
file_priority.push_back(m_file_priority[i]);
2852
void torrent::get_full_peer_list(std::vector<peer_list_entry>& v) const
2855
v.reserve(m_policy.num_peers());
2856
for (policy::const_iterator i = m_policy.begin_peer();
2857
i != m_policy.end_peer(); ++i)
2860
e.ip = i->second.ip();
2861
e.flags = i->second.banned ? peer_list_entry::banned : 0;
2862
e.failcount = i->second.failcount;
2863
e.source = i->second.source;
2868
void torrent::get_peer_info(std::vector<peer_info>& v)
2871
for (peer_iterator i = begin();
2874
peer_connection* peer = *i;
2876
// incoming peers that haven't finished the handshake should
2877
// not be included in this list
2878
if (peer->associated_torrent().expired()) continue;
2880
v.push_back(peer_info());
2881
peer_info& p = v.back();
2883
peer->get_peer_info(p);
2884
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
2885
if (resolving_countries())
2886
resolve_peer_country(intrusive_ptr<peer_connection>(peer));
2891
void torrent::get_download_queue(std::vector<partial_piece_info>& queue)
2894
if (!valid_metadata() || is_seed()) return;
2895
piece_picker const& p = picker();
2896
std::vector<piece_picker::downloading_piece> const& q
2897
= p.get_download_queue();
2899
for (std::vector<piece_picker::downloading_piece>::const_iterator i
2900
= q.begin(); i != q.end(); ++i)
2902
partial_piece_info pi;
2903
pi.piece_state = (partial_piece_info::state_t)i->state;
2904
pi.blocks_in_piece = p.blocks_in_piece(i->index);
2905
pi.finished = (int)i->finished;
2906
pi.writing = (int)i->writing;
2907
pi.requested = (int)i->requested;
2908
int piece_size = int(torrent_file().piece_size(i->index));
2909
int num_blocks = (std::min)(pi.blocks_in_piece, int(partial_piece_info::max_blocks_per_piece));
2910
for (int j = 0; j < num_blocks; ++j)
2912
block_info& bi = pi.blocks[j];
2913
bi.state = i->info[j].state;
2914
bi.block_size = j < pi.blocks_in_piece - 1 ? m_block_size
2915
: piece_size - (j * m_block_size);
2916
bool complete = bi.state == block_info::writing
2917
|| bi.state == block_info::finished;
2918
if (i->info[j].peer == 0)
2920
bi.peer = tcp::endpoint();
2921
bi.bytes_progress = complete ? bi.block_size : 0;
2925
policy::peer* p = static_cast<policy::peer*>(i->info[j].peer);
2928
bi.peer = p->connection->remote();
2929
if (bi.state == block_info::requested)
2931
boost::optional<piece_block_progress> pbp
2932
= p->connection->downloading_piece_progress();
2933
if (pbp && pbp->piece_index == i->index && pbp->block_index == j)
2935
bi.bytes_progress = pbp->bytes_downloaded;
2936
TORRENT_ASSERT(bi.bytes_progress <= bi.block_size);
2940
bi.bytes_progress = 0;
2945
bi.bytes_progress = complete ? bi.block_size : 0;
2951
bi.bytes_progress = complete ? bi.block_size : 0;
2955
pi.blocks[j].num_peers = i->info[j].num_peers;
2957
pi.piece_index = i->index;
2958
queue.push_back(pi);
2963
bool torrent::connect_to_peer(policy::peer* peerinfo)
2967
TORRENT_ASSERT(peerinfo);
2968
TORRENT_ASSERT(peerinfo->connection == 0);
2970
peerinfo->connected = time_now();
2971
#ifdef TORRENT_DEBUG
2972
// this asserts that we don't have duplicates in the policy's peer list
2973
peer_iterator i_ = std::find_if(m_connections.begin(), m_connections.end()
2974
, bind(&peer_connection::remote, _1) == peerinfo->ip());
2975
TORRENT_ASSERT(i_ == m_connections.end()
2976
|| dynamic_cast<bt_peer_connection*>(*i_) == 0);
2979
TORRENT_ASSERT(want_more_peers());
2980
TORRENT_ASSERT(m_ses.num_connections() < m_ses.max_connections());
2982
tcp::endpoint a(peerinfo->ip());
2983
TORRENT_ASSERT((m_ses.m_ip_filter.access(peerinfo->addr) & ip_filter::blocked) == 0);
2985
boost::shared_ptr<socket_type> s(new socket_type(m_ses.m_io_service));
2987
bool ret = instantiate_connection(m_ses.m_io_service, m_ses.peer_proxy(), *s);
2989
TORRENT_ASSERT(ret);
2991
boost::intrusive_ptr<peer_connection> c(new bt_peer_connection(
2992
m_ses, shared_from_this(), s, a, peerinfo));
2994
#ifdef TORRENT_DEBUG
2995
c->m_in_constructor = false;
2998
c->add_stat(peerinfo->prev_amount_download, peerinfo->prev_amount_upload);
2999
peerinfo->prev_amount_download = 0;
3000
peerinfo->prev_amount_upload = 0;
3002
#ifndef TORRENT_DISABLE_EXTENSIONS
3003
for (extension_list_t::iterator i = m_extensions.begin()
3004
, end(m_extensions.end()); i != end; ++i)
3006
#ifndef BOOST_NO_EXCEPTIONS
3009
boost::shared_ptr<peer_plugin> pp((*i)->new_connection(c.get()));
3010
if (pp) c->add_extension(pp);
3011
#ifndef BOOST_NO_EXCEPTIONS
3012
} catch (std::exception&) {}
3017
// add the newly connected peer to this torrent's peer list
3018
m_connections.insert(boost::get_pointer(c));
3019
m_ses.m_connections.insert(c);
3020
peerinfo->connection = c.get();
3023
int timeout = settings().peer_connect_timeout;
3024
if (peerinfo) timeout += 3 * peerinfo->failcount;
3026
#ifndef BOOST_NO_EXCEPTIONS
3030
m_ses.m_half_open.enqueue(
3031
bind(&peer_connection::connect, c, _1)
3032
, bind(&peer_connection::timed_out, c)
3033
, seconds(timeout));
3034
#ifndef BOOST_NO_EXCEPTIONS
3036
catch (std::exception& e)
3038
std::set<peer_connection*>::iterator i
3039
= m_connections.find(boost::get_pointer(c));
3040
if (i != m_connections.end()) m_connections.erase(i);
3041
c->disconnect(e.what());
3046
return peerinfo->connection;
3049
bool torrent::set_metadata(lazy_entry const& metadata, std::string& error)
3053
TORRENT_ASSERT(!m_torrent_file->is_valid());
3054
if (!m_torrent_file->parse_info_section(metadata, error))
3060
if (m_ses.m_alerts.should_post<metadata_received_alert>())
3062
m_ses.m_alerts.post_alert(metadata_received_alert(
3071
bool torrent::attach_peer(peer_connection* p)
3075
TORRENT_ASSERT(p != 0);
3076
TORRENT_ASSERT(!p->is_local());
3078
m_has_incoming = true;
3080
if ((m_state == torrent_status::queued_for_checking
3081
|| m_state == torrent_status::checking_files
3082
|| m_state == torrent_status::checking_resume_data)
3083
&& valid_metadata())
3085
p->disconnect("torrent is not ready to accept peers");
3089
if (m_ses.m_connections.find(p) == m_ses.m_connections.end())
3091
p->disconnect("peer is not properly constructed");
3095
if (m_ses.is_aborted())
3097
p->disconnect("session is closing");
3101
if (int(m_connections.size()) >= m_max_connections)
3103
p->disconnect("reached connection limit");
3107
#ifndef BOOST_NO_EXCEPTIONS
3111
#ifndef TORRENT_DISABLE_EXTENSIONS
3112
for (extension_list_t::iterator i = m_extensions.begin()
3113
, end(m_extensions.end()); i != end; ++i)
3115
boost::shared_ptr<peer_plugin> pp((*i)->new_connection(p));
3116
if (pp) p->add_extension(pp);
3119
if (!m_policy.new_connection(*p))
3121
#ifndef BOOST_NO_EXCEPTIONS
3123
catch (std::exception& e)
3125
#if defined TORRENT_LOGGING
3126
(*m_ses.m_logger) << time_now_string() << " CLOSING CONNECTION "
3127
<< p->remote() << " policy::new_connection threw: " << e.what() << "\n";
3129
p->disconnect(e.what());
3133
TORRENT_ASSERT(m_connections.find(p) == m_connections.end());
3134
peer_iterator ci = m_connections.insert(p).first;
3135
#ifdef TORRENT_DEBUG
3137
TORRENT_ASSERT(p->remote() == p->get_socket()->remote_endpoint(ec) || ec);
3140
#if defined TORRENT_DEBUG && !defined TORRENT_DISABLE_INVARIANT_CHECKS
3141
m_policy.check_invariant();
3146
bool torrent::want_more_peers() const
3148
return int(m_connections.size()) < m_max_connections
3150
&& m_state != torrent_status::checking_files
3151
&& m_state != torrent_status::checking_resume_data
3152
&& (m_state != torrent_status::queued_for_checking
3153
|| !valid_metadata())
3154
&& m_policy.num_connect_candidates() > 0
3158
void torrent::disconnect_all()
3160
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
3162
// doesn't work with the m_paused -> m_num_peers == 0 condition
3165
while (!m_connections.empty())
3167
peer_connection* p = *m_connections.begin();
3168
TORRENT_ASSERT(p->associated_torrent().lock().get() == this);
3170
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
3172
(*p->m_logger) << "*** CLOSING CONNECTION 'aborting'\n";
3174
(*p->m_logger) << "*** CLOSING CONNECTION 'pausing'\n";
3176
#ifdef TORRENT_DEBUG
3177
std::size_t size = m_connections.size();
3179
if (p->is_disconnecting())
3180
m_connections.erase(m_connections.begin());
3182
p->disconnect(m_abort?"stopping torrent":"pausing torrent");
3183
TORRENT_ASSERT(m_connections.size() <= size);
3189
// this returns true if lhs is a better disconnect candidate than rhs
3190
bool compare_disconnect_peer(peer_connection const* lhs, peer_connection const* rhs)
3192
// prefer to disconnect peers we're not interested in
3193
if (lhs->is_interesting() != rhs->is_interesting())
3194
return rhs->is_interesting();
3196
// prefer to disconnect peers that are not seeds
3197
if (lhs->is_seed() != rhs->is_seed())
3198
return rhs->is_seed();
3200
// prefer to disconnect peers that are on parole
3201
if (lhs->on_parole() != rhs->on_parole())
3202
return lhs->on_parole();
3204
// prefer to disconnect peers that send data at a lower rate
3205
size_type lhs_transferred = lhs->statistics().total_payload_download();
3206
size_type rhs_transferred = rhs->statistics().total_payload_download();
3208
if (lhs_transferred != rhs_transferred
3209
&& lhs_transferred > 0
3210
&& rhs_transferred > 0)
3212
ptime now = time_now();
3213
size_type lhs_time_connected = total_seconds(now - lhs->connected_time());
3214
size_type rhs_time_connected = total_seconds(now - rhs->connected_time());
3216
double lhs_rate = double(lhs_transferred) / (lhs_time_connected + 1);
3217
double rhs_rate = double(rhs_transferred) / (rhs_time_connected + 1);
3219
return lhs_rate < rhs_rate;
3222
// prefer to disconnect peers that chokes us
3223
if (lhs->is_choked() != rhs->is_choked())
3224
return lhs->is_choked();
3226
return lhs->last_received() < rhs->last_received();
3230
int torrent::disconnect_peers(int num)
3235
// buils a list of all connected peers and sort it by 'disconnectability'.
3236
std::vector<peer_connection*> peers(m_connections.size());
3237
std::copy(m_connections.begin(), m_connections.end(), peers.begin());
3238
std::sort(peers.begin(), peers.end(), boost::bind(&compare_disconnect_peer, _1, _2));
3240
// never disconnect peers that connected less than 90 seconds ago
3241
ptime cut_off = time_now() - seconds(90);
3243
for (std::vector<peer_connection*>::iterator i = peers.begin()
3244
, end(peers.end()); i != end && ret < num; ++i)
3246
peer_connection* p = *i;
3247
if (p->connected_time() > cut_off) continue;
3249
p->disconnect("optimistic disconnect");
3254
int torrent::bandwidth_throttle(int channel) const
3256
return m_bandwidth_limit[channel].throttle();
3259
int torrent::bandwidth_queue_size(int channel) const
3261
return (int)m_bandwidth_queue[channel].size();
3264
void torrent::request_bandwidth(int channel
3265
, boost::intrusive_ptr<peer_connection> const& p
3266
, int max_block_size, int priority)
3268
TORRENT_ASSERT(max_block_size > 0);
3269
TORRENT_ASSERT(m_bandwidth_limit[channel].throttle() > 0);
3270
TORRENT_ASSERT(p->max_assignable_bandwidth(channel) > 0);
3271
TORRENT_ASSERT(p->m_channel_state[channel] == peer_info::bw_torrent);
3272
int block_size = (std::min)(m_bandwidth_limit[channel].throttle() / 10
3274
if (block_size <= 0) block_size = 1;
3276
if (m_bandwidth_limit[channel].max_assignable() > 0)
3278
perform_bandwidth_request(channel, p, block_size, priority);
3282
// skip forward in the queue until we find a prioritized peer
3283
// or hit the front of it.
3284
queue_t::reverse_iterator i = m_bandwidth_queue[channel].rbegin();
3285
while (i != m_bandwidth_queue[channel].rend() && priority > i->priority)
3290
m_bandwidth_queue[channel].insert(i.base(), bw_queue_entry<peer_connection, torrent>(
3291
p, block_size, priority));
3295
void torrent::expire_bandwidth(int channel, int amount)
3297
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
3301
TORRENT_ASSERT(amount > 0);
3302
m_bandwidth_limit[channel].expire(amount);
3304
while (!m_bandwidth_queue[channel].empty())
3306
bw_queue_entry<peer_connection, torrent> qe = m_bandwidth_queue[channel].front();
3307
if (m_bandwidth_limit[channel].max_assignable() == 0)
3309
m_bandwidth_queue[channel].pop_front();
3310
if (qe.peer->max_assignable_bandwidth(channel) <= 0)
3312
TORRENT_ASSERT(m_ses.m_bandwidth_manager[channel]->is_in_history(qe.peer.get()));
3313
if (!qe.peer->is_disconnecting()) tmp.push_back(qe);
3316
perform_bandwidth_request(channel, qe.peer
3317
, qe.max_block_size, qe.priority);
3319
m_bandwidth_queue[channel].insert(m_bandwidth_queue[channel].begin(), tmp.begin(), tmp.end());
3322
void torrent::perform_bandwidth_request(int channel
3323
, boost::intrusive_ptr<peer_connection> const& p
3327
TORRENT_ASSERT(p->m_channel_state[channel] == peer_info::bw_torrent);
3328
p->m_channel_state[channel] = peer_info::bw_global;
3329
m_ses.m_bandwidth_manager[channel]->request_bandwidth(p
3330
, block_size, priority);
3331
m_bandwidth_limit[channel].assign(block_size);
3334
void torrent::assign_bandwidth(int channel, int amount, int blk)
3336
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
3338
TORRENT_ASSERT(amount > 0);
3339
TORRENT_ASSERT(amount <= blk);
3341
expire_bandwidth(channel, blk - amount);
3344
// called when torrent is finished (all interesting
3345
// pieces have been downloaded)
3346
void torrent::finished()
3350
TORRENT_ASSERT(is_finished());
3351
TORRENT_ASSERT(m_state != torrent_status::finished && m_state != torrent_status::seeding);
3353
if (alerts().should_post<torrent_finished_alert>())
3355
alerts().post_alert(torrent_finished_alert(
3359
set_state(torrent_status::finished);
3360
set_queue_position(-1);
3362
// we have to call completed() before we start
3363
// disconnecting peers, since there's an assert
3364
// to make sure we're cleared the piece picker
3365
if (is_seed()) completed();
3367
// disconnect all seeds
3368
// TODO: should disconnect all peers that have the pieces we have
3370
std::vector<peer_connection*> seeds;
3371
for (peer_iterator i = m_connections.begin();
3372
i != m_connections.end(); ++i)
3374
peer_connection* p = *i;
3375
TORRENT_ASSERT(p->associated_torrent().lock().get() == this);
3376
if (p->upload_only())
3378
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
3379
(*p->m_logger) << "*** SEED, CLOSING CONNECTION\n";
3384
std::for_each(seeds.begin(), seeds.end()
3385
, bind(&peer_connection::disconnect, _1, "torrent finished, disconnecting seed", 0));
3387
m_policy.recalculate_connect_candidates();
3389
TORRENT_ASSERT(m_storage);
3390
// we need to keep the object alive during this operation
3391
m_storage->async_release_files(
3392
bind(&torrent::on_files_released, shared_from_this(), _1, _2));
3395
// this is called when we were finished, but some files were
3396
// marked for downloading, and we are no longer finished
3397
void torrent::resume_download()
3401
TORRENT_ASSERT(!is_finished());
3402
set_state(torrent_status::downloading);
3403
set_queue_position((std::numeric_limits<int>::max)());
3404
m_policy.recalculate_connect_candidates();
3407
// called when torrent is complete (all pieces downloaded)
3408
void torrent::completed()
3412
set_state(torrent_status::seeding);
3413
if (!m_complete_sent && m_announcing) announce_with_tracker();
3416
// this will move the tracker with the given index
3417
// to a prioritized position in the list (move it towards
3418
// the begining) and return the new index to the tracker.
3419
int torrent::prioritize_tracker(int index)
3423
TORRENT_ASSERT(index >= 0);
3424
if (index >= (int)m_trackers.size()) return (int)m_trackers.size()-1;
3426
while (index > 0 && m_trackers[index].tier == m_trackers[index-1].tier)
3428
std::swap(m_trackers[index].url, m_trackers[index-1].url);
3434
void torrent::try_next_tracker(tracker_request const& req)
3438
++m_currently_trying_tracker;
3440
if ((unsigned)m_currently_trying_tracker < m_trackers.size())
3442
announce_with_tracker(req.event);
3446
int delay = tracker_retry_delay_min
3447
+ (std::min)(int(m_failed_trackers), int(tracker_failed_max))
3448
* (tracker_retry_delay_max - tracker_retry_delay_min)
3449
/ tracker_failed_max;
3451
++m_failed_trackers;
3452
// if we've looped the tracker list, wait a bit before retrying
3453
m_currently_trying_tracker = 0;
3455
// if we're stopping, just give up. Don't bother retrying
3456
if (req.event == tracker_request::stopped)
3459
restart_tracker_timer(time_now() + seconds(delay));
3461
#ifndef TORRENT_DISABLE_DHT
3462
if (m_abort) return;
3464
// only start the announce if we want to announce with the dht
3465
ptime now = time_now();
3466
if (should_announce_dht() && now - m_last_dht_announce > minutes(14))
3468
// force the DHT to reannounce
3469
m_last_dht_announce = now;
3470
boost::weak_ptr<torrent> self(shared_from_this());
3471
m_ses.m_dht->announce(m_torrent_file->info_hash()
3472
, m_ses.m_listen_sockets.front().external_port
3473
, bind(&torrent::on_dht_announce_response_disp, self, _1));
3479
void torrent::files_checked()
3481
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
3483
TORRENT_ASSERT(m_torrent_file->is_valid());
3485
if (m_abort) return;
3487
// we might be finished already, in which case we should
3488
// not switch to downloading mode.
3489
if (m_state != torrent_status::finished)
3490
set_state(torrent_status::downloading);
3494
if (m_ses.m_alerts.should_post<torrent_checked_alert>())
3496
m_ses.m_alerts.post_alert(torrent_checked_alert(
3502
// if we just finished checking and we're not a seed, we are
3503
// likely to be unpaused
3504
if (m_ses.m_auto_manage_time_scaler > 1)
3505
m_ses.m_auto_manage_time_scaler = 1;
3507
if (is_finished() && m_state != torrent_status::finished) finished();
3511
m_complete_sent = true;
3512
if (m_state != torrent_status::finished) finished();
3515
#ifndef TORRENT_DISABLE_EXTENSIONS
3516
for (extension_list_t::iterator i = m_extensions.begin()
3517
, end(m_extensions.end()); i != end; ++i)
3519
#ifndef BOOST_NO_EXCEPTIONS
3522
(*i)->on_files_checked();
3523
#ifndef BOOST_NO_EXCEPTIONS
3524
} catch (std::exception&) {}
3529
if (!m_connections_initialized)
3531
m_connections_initialized = true;
3532
// all peer connections have to initialize themselves now that the metadata
3534
for (torrent::peer_iterator i = m_connections.begin();
3535
i != m_connections.end();)
3537
peer_connection* pc = *i;
3539
if (pc->is_disconnecting()) continue;
3540
pc->on_metadata_impl();
3541
if (pc->is_disconnecting()) continue;
3546
m_files_checked = true;
3551
alert_manager& torrent::alerts() const
3553
return m_ses.m_alerts;
3556
fs::path torrent::save_path() const
3561
bool torrent::rename_file(int index, std::string const& name)
3565
TORRENT_ASSERT(index >= 0);
3566
TORRENT_ASSERT(index < m_torrent_file->num_files());
3568
if (!m_owning_storage.get()) return false;
3570
m_owning_storage->async_rename_file(index, name
3571
, bind(&torrent::on_file_renamed, shared_from_this(), _1, _2));
3575
void torrent::move_storage(fs::path const& save_path)
3579
if (m_owning_storage.get())
3581
m_owning_storage->async_move_storage(save_path
3582
, bind(&torrent::on_storage_moved, shared_from_this(), _1, _2));
3586
m_save_path = save_path;
3587
if (alerts().should_post<storage_moved_alert>())
3589
alerts().post_alert(storage_moved_alert(get_handle(), m_save_path.string()));
3594
void torrent::on_storage_moved(int ret, disk_io_job const& j)
3596
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
3600
if (alerts().should_post<storage_moved_alert>())
3602
alerts().post_alert(storage_moved_alert(get_handle(), j.str));
3604
m_save_path = j.str;
3608
if (alerts().should_post<storage_moved_failed_alert>())
3610
alerts().post_alert(storage_moved_failed_alert(get_handle(), j.error));
3615
piece_manager& torrent::filesystem()
3617
TORRENT_ASSERT(m_owning_storage.get());
3618
TORRENT_ASSERT(m_storage);
3623
torrent_handle torrent::get_handle()
3625
return torrent_handle(shared_from_this());
3628
session_settings const& torrent::settings() const
3630
return m_ses.settings();
3633
#ifdef TORRENT_DEBUG
3634
void torrent::check_invariant() const
3636
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
3638
if (is_paused()) TORRENT_ASSERT(num_peers() == 0);
3640
if (!should_check_files())
3641
TORRENT_ASSERT(m_state != torrent_status::checking_files);
3643
TORRENT_ASSERT(m_queued_for_checking);
3645
if (!m_ses.m_queued_for_checking.empty())
3647
// if there are torrents waiting to be checked
3648
// assert that there's a torrent that is being
3649
// processed right now
3651
int found_active = 0;
3652
for (aux::session_impl::torrent_map::iterator i = m_ses.m_torrents.begin()
3653
, end(m_ses.m_torrents.end()); i != end; ++i)
3654
if (i->second->m_state == torrent_status::checking_files)
3657
if (i->second->should_check_files()) ++found_active;
3659
// the case of 2 is in the special case where one switches over from
3660
// checking to complete
3661
TORRENT_ASSERT(found_active >= 1);
3662
TORRENT_ASSERT(found_active <= 2);
3663
TORRENT_ASSERT(found >= 1);
3666
TORRENT_ASSERT(m_resume_entry.type() == lazy_entry::dict_t
3667
|| m_resume_entry.type() == lazy_entry::none_t);
3669
TORRENT_ASSERT(m_bandwidth_queue[0].size() <= m_connections.size());
3670
TORRENT_ASSERT(m_bandwidth_queue[1].size() <= m_connections.size());
3672
for (int c = 0; c < 2; ++c)
3674
queue_t::const_iterator j = m_bandwidth_queue[c].begin();
3675
if (j == m_bandwidth_queue[c].end()) continue;
3677
for (queue_t::const_iterator i = m_bandwidth_queue[c].begin()
3678
, end(m_bandwidth_queue[c].end()); i != end && j != end; ++i, ++j)
3679
TORRENT_ASSERT(i->priority >= j->priority);
3682
int num_uploads = 0;
3683
std::map<piece_block, int> num_requests;
3684
for (const_peer_iterator i = begin(); i != end(); ++i)
3686
#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS
3687
// make sure this peer is not a dangling pointer
3688
TORRENT_ASSERT(m_ses.has_peer(*i));
3690
peer_connection const& p = *(*i);
3691
for (std::deque<piece_block>::const_iterator i = p.request_queue().begin()
3692
, end(p.request_queue().end()); i != end; ++i)
3694
for (std::deque<pending_block>::const_iterator i = p.download_queue().begin()
3695
, end(p.download_queue().end()); i != end; ++i)
3696
++num_requests[i->block];
3697
if (!p.is_choked()) ++num_uploads;
3698
torrent* associated_torrent = p.associated_torrent().lock().get();
3699
if (associated_torrent != this)
3700
TORRENT_ASSERT(false);
3702
TORRENT_ASSERT(num_uploads == m_num_uploads);
3706
for (std::map<piece_block, int>::iterator i = num_requests.begin()
3707
, end(num_requests.end()); i != end; ++i)
3709
if (!m_picker->is_downloaded(i->first))
3710
TORRENT_ASSERT(m_picker->num_peers(i->first) == i->second);
3712
TORRENT_ASSERT(num_have() >= m_picker->num_have_filtered());
3715
if (valid_metadata())
3717
TORRENT_ASSERT(m_abort || !m_picker || m_picker->num_pieces() == m_torrent_file->num_pieces());
3721
TORRENT_ASSERT(m_abort || !m_picker || m_picker->num_pieces() == 0);
3724
#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS
3725
for (policy::const_iterator i = m_policy.begin_peer()
3726
, end(m_policy.end_peer()); i != end; ++i)
3728
TORRENT_ASSERT(i->second.addr == i->first);
3732
size_type total_done = quantized_bytes_done();
3733
if (m_torrent_file->is_valid())
3736
TORRENT_ASSERT(total_done == m_torrent_file->total_size());
3738
TORRENT_ASSERT(total_done != m_torrent_file->total_size() || !m_files_checked);
3740
TORRENT_ASSERT(m_block_size <= m_torrent_file->piece_length());
3744
TORRENT_ASSERT(total_done == 0);
3747
if (m_picker && !m_abort)
3749
// make sure that pieces that have completed the download
3750
// of all their blocks are in the disk io thread's queue
3752
const std::vector<piece_picker::downloading_piece>& dl_queue
3753
= m_picker->get_download_queue();
3754
for (std::vector<piece_picker::downloading_piece>::const_iterator i =
3755
dl_queue.begin(); i != dl_queue.end(); ++i)
3757
const int blocks_per_piece = m_picker->blocks_in_piece(i->index);
3759
bool complete = true;
3760
for (int j = 0; j < blocks_per_piece; ++j)
3762
if (i->info[j].state == piece_picker::block_info::state_finished)
3770
// This check is very expensive.
3771
TORRENT_ASSERT(!valid_metadata() || m_block_size > 0);
3772
TORRENT_ASSERT(!valid_metadata() || (m_torrent_file->piece_length() % m_block_size) == 0);
3773
// if (is_seed()) TORRENT_ASSERT(m_picker.get() == 0);
3777
void torrent::set_sequential_download(bool sd)
3778
{ m_sequential_download = sd; }
3780
void torrent::set_queue_position(int p)
3782
TORRENT_ASSERT((p == -1) == is_finished()
3783
|| (!m_auto_managed && p == -1)
3784
|| (m_abort && p == -1));
3785
if (is_finished() && p != -1) return;
3786
if (p == m_sequence_number) return;
3788
session_impl::torrent_map& torrents = m_ses.m_torrents;
3789
if (p >= 0 && m_sequence_number == -1)
3792
for (session_impl::torrent_map::iterator i = torrents.begin()
3793
, end(torrents.end()); i != end; ++i)
3795
torrent* t = i->second.get();
3796
if (t->m_sequence_number > max_seq) max_seq = t->m_sequence_number;
3798
m_sequence_number = (std::min)(max_seq + 1, p);
3802
for (session_impl::torrent_map::iterator i = torrents.begin()
3803
, end(torrents.end()); i != end; ++i)
3805
torrent* t = i->second.get();
3806
if (t == this) continue;
3807
if (t->m_sequence_number >= m_sequence_number
3808
&& t->m_sequence_number != -1)
3809
--t->m_sequence_number;
3811
m_sequence_number = p;
3813
else if (p < m_sequence_number)
3815
for (session_impl::torrent_map::iterator i = torrents.begin()
3816
, end(torrents.end()); i != end; ++i)
3818
torrent* t = i->second.get();
3819
if (t == this) continue;
3820
if (t->m_sequence_number >= p
3821
&& t->m_sequence_number < m_sequence_number
3822
&& t->m_sequence_number != -1)
3823
++t->m_sequence_number;
3825
m_sequence_number = p;
3827
else if (p > m_sequence_number)
3830
for (session_impl::torrent_map::iterator i = torrents.begin()
3831
, end(torrents.end()); i != end; ++i)
3833
torrent* t = i->second.get();
3834
int pos = t->m_sequence_number;
3835
if (pos > max_seq) max_seq = pos;
3836
if (t == this) continue;
3839
&& pos > m_sequence_number
3841
--t->m_sequence_number;
3844
m_sequence_number = (std::min)(max_seq, p);
3847
if (m_ses.m_auto_manage_time_scaler > 2)
3848
m_ses.m_auto_manage_time_scaler = 2;
3851
void torrent::set_max_uploads(int limit)
3853
TORRENT_ASSERT(limit >= -1);
3854
if (limit <= 0) limit = (std::numeric_limits<int>::max)();
3855
m_max_uploads = limit;
3858
void torrent::set_max_connections(int limit)
3860
TORRENT_ASSERT(limit >= -1);
3861
if (limit <= 0) limit = (std::numeric_limits<int>::max)();
3862
m_max_connections = limit;
3865
void torrent::set_peer_upload_limit(tcp::endpoint ip, int limit)
3867
TORRENT_ASSERT(limit >= -1);
3868
peer_iterator i = std::find_if(m_connections.begin(), m_connections.end()
3869
, bind(&peer_connection::remote, _1) == ip);
3870
if (i == m_connections.end()) return;
3871
(*i)->set_upload_limit(limit);
3874
void torrent::set_peer_download_limit(tcp::endpoint ip, int limit)
3876
TORRENT_ASSERT(limit >= -1);
3877
peer_iterator i = std::find_if(m_connections.begin(), m_connections.end()
3878
, bind(&peer_connection::remote, _1) == ip);
3879
if (i == m_connections.end()) return;
3880
(*i)->set_download_limit(limit);
3883
void torrent::set_upload_limit(int limit)
3885
TORRENT_ASSERT(limit >= -1);
3886
if (limit <= 0) limit = (std::numeric_limits<int>::max)();
3887
m_bandwidth_limit[peer_connection::upload_channel].throttle(limit);
3890
int torrent::upload_limit() const
3892
int limit = m_bandwidth_limit[peer_connection::upload_channel].throttle();
3893
if (limit == (std::numeric_limits<int>::max)()) limit = -1;
3897
void torrent::set_download_limit(int limit)
3899
TORRENT_ASSERT(limit >= -1);
3900
if (limit <= 0) limit = (std::numeric_limits<int>::max)();
3901
m_bandwidth_limit[peer_connection::download_channel].throttle(limit);
3904
int torrent::download_limit() const
3906
int limit = m_bandwidth_limit[peer_connection::download_channel].throttle();
3907
if (limit == (std::numeric_limits<int>::max)()) limit = -1;
3911
void torrent::delete_files()
3913
#if defined TORRENT_VERBOSE_LOGGING
3914
for (peer_iterator i = m_connections.begin();
3915
i != m_connections.end(); ++i)
3917
(*(*i)->m_logger) << "*** DELETING FILES IN TORRENT\n";
3924
if (m_owning_storage.get())
3926
TORRENT_ASSERT(m_storage);
3927
m_storage->async_delete_files(
3928
bind(&torrent::on_files_deleted, shared_from_this(), _1, _2));
3932
void torrent::clear_error()
3934
if (m_error.empty()) return;
3935
bool checking_files = should_check_files();
3936
if (m_ses.m_auto_manage_time_scaler > 2)
3937
m_ses.m_auto_manage_time_scaler = 2;
3939
if (!checking_files && should_check_files())
3940
queue_torrent_check();
3943
void torrent::set_error(std::string const& msg)
3945
bool checking_files = should_check_files();
3947
if (checking_files && !should_check_files())
3950
m_storage->abort_disk_io();
3951
dequeue_torrent_check();
3952
set_state(torrent_status::queued_for_checking);
3956
void torrent::auto_managed(bool a)
3960
if (m_auto_managed == a) return;
3961
bool checking_files = should_check_files();
3963
// recalculate which torrents should be
3965
m_ses.m_auto_manage_time_scaler = 0;
3967
if (!checking_files && should_check_files())
3969
queue_torrent_check();
3971
else if (checking_files && !should_check_files())
3974
m_storage->abort_disk_io();
3975
dequeue_torrent_check();
3976
set_state(torrent_status::queued_for_checking);
3980
// the higher seed rank, the more important to seed
3981
int torrent::seed_rank(session_settings const& s) const
3985
seed_ratio_not_met = 0x400000,
3986
recently_started = 0x200000,
3987
no_seeds = 0x100000,
3991
if (!is_seed()) return 0;
3995
ptime now(time_now());
3997
int seed_time = total_seconds(m_seeding_time);
3998
int download_time = total_seconds(m_active_time) - seed_time;
4000
// if we haven't yet met the seed limits, set the seed_ratio_not_met
4001
// flag. That will make this seed prioritized
4002
// downloaded may be 0 if the torrent is 0-sized
4003
size_type downloaded = (std::max)(m_total_downloaded, m_torrent_file->total_size());
4004
if (seed_time < s.seed_time_limit
4005
&& (download_time > 1 && seed_time / download_time < s.seed_time_ratio_limit)
4007
&& m_total_uploaded / downloaded < s.share_ratio_limit)
4008
ret |= seed_ratio_not_met;
4010
// if this torrent is running, and it was started less
4011
// than 30 minutes ago, give it priority, to avoid oscillation
4012
if (!is_paused() && now - m_started < minutes(30))
4013
ret |= recently_started;
4015
// if we have any scrape data, use it to calculate
4018
int downloaders = 0;
4020
if (m_complete >= 0) seeds = m_complete;
4021
else seeds = m_policy.num_seeds();
4023
if (m_incomplete >= 0) downloaders = m_incomplete;
4024
else downloaders = m_policy.num_peers() - m_policy.num_seeds();
4029
ret |= downloaders & prio_mask;
4033
ret |= (downloaders * 100 / seeds) & prio_mask;
4039
// this is an async operation triggered by the client
4040
void torrent::save_resume_data()
4044
if (m_owning_storage.get())
4046
TORRENT_ASSERT(m_storage);
4047
if (m_state == torrent_status::queued_for_checking
4048
|| m_state == torrent_status::checking_files
4049
|| m_state == torrent_status::checking_resume_data)
4051
if (alerts().should_post<save_resume_data_alert>())
4053
boost::shared_ptr<entry> rd(new entry);
4054
write_resume_data(*rd);
4055
alerts().post_alert(save_resume_data_alert(rd
4061
m_storage->async_save_resume_data(
4062
bind(&torrent::on_save_resume_data, shared_from_this(), _1, _2));
4067
if (alerts().should_post<save_resume_data_failed_alert>())
4069
alerts().post_alert(save_resume_data_failed_alert(get_handle()
4070
, "save resume data failed, torrent is being destructed"));
4075
bool torrent::should_check_files() const
4077
return (m_state == torrent_status::checking_files
4078
|| m_state == torrent_status::queued_for_checking)
4079
&& (!m_paused || m_auto_managed)
4084
bool torrent::is_paused() const
4086
return m_paused || m_ses.is_paused();
4089
void torrent::pause()
4093
if (m_paused) return;
4094
bool checking_files = should_check_files();
4096
if (!m_ses.is_paused())
4098
if (checking_files && !should_check_files())
4101
m_storage->abort_disk_io();
4102
dequeue_torrent_check();
4103
set_state(torrent_status::queued_for_checking);
4107
void torrent::do_pause()
4109
if (!is_paused()) return;
4111
#ifndef TORRENT_DISABLE_EXTENSIONS
4112
for (extension_list_t::iterator i = m_extensions.begin()
4113
, end(m_extensions.end()); i != end; ++i)
4115
#ifndef BOOST_NO_EXCEPTIONS
4118
if ((*i)->on_pause()) return;
4119
#ifndef BOOST_NO_EXCEPTIONS
4120
} catch (std::exception&) {}
4125
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
4126
for (peer_iterator i = m_connections.begin();
4127
i != m_connections.end(); ++i)
4129
(*(*i)->m_logger) << "*** PAUSING TORRENT\n";
4133
// this will make the storage close all
4134
// files and flush all cached data
4135
if (m_owning_storage.get())
4137
TORRENT_ASSERT(m_storage);
4138
m_storage->async_release_files(
4139
bind(&torrent::on_torrent_paused, shared_from_this(), _1, _2));
4140
m_storage->async_clear_read_cache();
4144
if (alerts().should_post<torrent_paused_alert>())
4145
alerts().post_alert(torrent_paused_alert(get_handle()));
4152
void torrent::resume()
4156
if (!m_paused) return;
4157
bool checking_files = should_check_files();
4160
if (!checking_files && should_check_files())
4161
queue_torrent_check();
4164
void torrent::do_resume()
4166
if (is_paused()) return;
4168
#ifndef TORRENT_DISABLE_EXTENSIONS
4169
for (extension_list_t::iterator i = m_extensions.begin()
4170
, end(m_extensions.end()); i != end; ++i)
4172
#ifndef BOOST_NO_EXCEPTIONS
4175
if ((*i)->on_resume()) return;
4176
#ifndef BOOST_NO_EXCEPTIONS
4177
} catch (std::exception&) {}
4182
if (alerts().should_post<torrent_resumed_alert>())
4183
alerts().post_alert(torrent_resumed_alert(get_handle()));
4185
m_started = time_now();
4190
void torrent::restart_tracker_timer(ptime announce_at)
4192
if (!m_announcing) return;
4194
m_next_tracker_announce = announce_at;
4196
boost::weak_ptr<torrent> self(shared_from_this());
4197
m_tracker_timer.expires_at(m_next_tracker_announce, ec);
4198
m_tracker_timer.async_wait(bind(&torrent::on_tracker_announce_disp, self, _1));
4201
void torrent::start_announcing()
4203
if (is_paused()) return;
4204
// if we don't have metadata, we need to announce
4205
// before checking files, to get peers to
4206
// request the metadata from
4207
if (!m_files_checked && valid_metadata()) return;
4208
if (m_announcing) return;
4210
m_announcing = true;
4212
if (!m_trackers.empty())
4214
// tell the tracker that we're back
4215
m_start_sent = false;
4217
announce_with_tracker();
4220
// private torrents are never announced on LSD
4221
// or on DHT, we don't need this timer.
4222
if (!m_torrent_file->is_valid() || !m_torrent_file->priv())
4225
boost::weak_ptr<torrent> self(shared_from_this());
4226
m_lsd_announce_timer.expires_from_now(seconds(1), ec);
4227
m_lsd_announce_timer.async_wait(
4228
bind(&torrent::on_lsd_announce_disp, self, _1));
4232
void torrent::stop_announcing()
4234
if (!m_announcing) return;
4237
m_lsd_announce_timer.cancel(ec);
4238
m_tracker_timer.cancel(ec);
4240
m_announcing = false;
4242
if (!m_trackers.empty())
4243
announce_with_tracker(tracker_request::stopped);
4246
void torrent::second_tick(stat& accumulator, float tick_interval)
4250
#ifndef TORRENT_DISABLE_EXTENSIONS
4251
for (extension_list_t::iterator i = m_extensions.begin()
4252
, end(m_extensions.end()); i != end; ++i)
4254
#ifndef BOOST_NO_EXCEPTIONS
4258
#ifndef BOOST_NO_EXCEPTIONS
4259
} catch (std::exception&) {}
4266
// let the stats fade out to 0
4267
m_stat.second_tick(tick_interval);
4271
time_duration since_last_tick = microsec(tick_interval * 1000000L);
4272
if (is_seed()) m_seeding_time += since_last_tick;
4273
m_active_time += since_last_tick;
4275
// ---- WEB SEEDS ----
4277
// re-insert urls that are to be retrieds into the m_web_seeds
4278
typedef std::map<std::string, ptime>::iterator iter_t;
4279
for (iter_t i = m_web_seeds_next_retry.begin(); i != m_web_seeds_next_retry.end();)
4281
iter_t erase_element = i++;
4282
if (erase_element->second <= time_now())
4284
m_web_seeds.insert(erase_element->first);
4285
m_web_seeds_next_retry.erase(erase_element);
4289
// if we have everything we want we don't need to connect to any web-seed
4290
if (!is_finished() && !m_web_seeds.empty() && m_files_checked)
4292
// keep trying web-seeds if there are any
4293
// first find out which web seeds we are connected to
4294
std::set<std::string> web_seeds;
4295
for (peer_iterator i = m_connections.begin();
4296
i != m_connections.end(); ++i)
4298
web_peer_connection* p
4299
= dynamic_cast<web_peer_connection*>(*i);
4301
web_seeds.insert(p->url());
4304
for (std::set<std::string>::iterator i = m_resolving_web_seeds.begin()
4305
, end(m_resolving_web_seeds.end()); i != end; ++i)
4306
web_seeds.insert(web_seeds.begin(), *i);
4308
// from the list of available web seeds, subtract the ones we are
4309
// already connected to.
4310
std::vector<std::string> not_connected_web_seeds;
4311
std::set_difference(m_web_seeds.begin(), m_web_seeds.end(), web_seeds.begin()
4312
, web_seeds.end(), std::back_inserter(not_connected_web_seeds));
4314
// connect to all of those that we aren't connected to
4315
std::for_each(not_connected_web_seeds.begin(), not_connected_web_seeds.end()
4316
, bind(&torrent::connect_to_url_seed, this, _1));
4319
for (peer_iterator i = m_connections.begin();
4320
i != m_connections.end();)
4322
peer_connection* p = *i;
4324
p->calc_ip_overhead();
4325
m_stat += p->statistics();
4326
// updates the peer connection's ul/dl bandwidth
4327
// resource requests
4328
#ifndef BOOST_NO_EXCEPTIONS
4332
p->second_tick(tick_interval);
4333
#ifndef BOOST_NO_EXCEPTIONS
4335
catch (std::exception& e)
4337
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
4338
(*p->m_logger) << "**ERROR**: " << e.what() << "\n";
4340
p->disconnect(e.what(), 1);
4344
accumulator += m_stat;
4345
m_total_uploaded += m_stat.last_payload_uploaded();
4346
m_total_downloaded += m_stat.last_payload_downloaded();
4347
m_stat.second_tick(tick_interval);
4350
if (m_time_scaler <= 0)
4357
void torrent::retry_url_seed(std::string const& url)
4359
m_web_seeds_next_retry[url] = time_now()
4360
+ seconds(m_ses.settings().urlseed_wait_retry);
4363
bool torrent::try_connect_peer()
4365
TORRENT_ASSERT(want_more_peers());
4366
if (m_deficit_counter < 100) return false;
4367
m_deficit_counter -= 100;
4368
bool ret = m_policy.connect_one_peer();
4372
void torrent::give_connect_points(int points)
4374
TORRENT_ASSERT(points <= 100);
4375
TORRENT_ASSERT(points > 0);
4376
TORRENT_ASSERT(want_more_peers());
4377
m_deficit_counter += points;
4380
void torrent::async_verify_piece(int piece_index, boost::function<void(int)> const& f)
4384
TORRENT_ASSERT(m_storage);
4385
TORRENT_ASSERT(m_storage->refcount() > 0);
4386
TORRENT_ASSERT(piece_index >= 0);
4387
TORRENT_ASSERT(piece_index < m_torrent_file->num_pieces());
4388
TORRENT_ASSERT(piece_index < (int)m_picker->num_pieces());
4389
#ifdef TORRENT_DEBUG
4392
int blocks_in_piece = m_picker->blocks_in_piece(piece_index);
4393
for (int i = 0; i < blocks_in_piece; ++i)
4395
TORRENT_ASSERT(m_picker->num_peers(piece_block(piece_index, i)) == 0);
4400
m_storage->async_hash(piece_index, bind(&torrent::on_piece_verified
4401
, shared_from_this(), _1, _2, f));
4402
#if defined TORRENT_DEBUG && !defined TORRENT_DISABLE_INVARIANT_CHECKS
4407
void torrent::on_piece_verified(int ret, disk_io_job const& j
4408
, boost::function<void(int)> f)
4410
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
4413
// 0: success, piece passed hash check
4415
// -2: hash check failed
4419
if (alerts().should_post<file_error_alert>())
4420
alerts().post_alert(file_error_alert(j.error_file, get_handle(), j.str));
4427
const tcp::endpoint& torrent::current_tracker() const
4429
return m_tracker_address;
4432
void torrent::file_progress(std::vector<float>& fp) const
4435
fp.resize(m_torrent_file->num_files(), 1.f);
4436
if (is_seed()) return;
4438
std::vector<size_type> progress;
4439
file_progress(progress);
4440
for (int i = 0; i < m_torrent_file->num_files(); ++i)
4442
file_entry const& f = m_torrent_file->file_at(i);
4443
if (f.size == 0) fp[i] = 1.f;
4444
else fp[i] = float(progress[i]) / f.size;
4448
void torrent::file_progress(std::vector<size_type>& fp) const
4450
TORRENT_ASSERT(valid_metadata());
4452
fp.resize(m_torrent_file->num_files(), 0);
4456
for (int i = 0; i < m_torrent_file->num_files(); ++i)
4457
fp[i] = m_torrent_file->files().at(i).size;
4461
TORRENT_ASSERT(has_picker());
4463
for (int i = 0; i < m_torrent_file->num_files(); ++i)
4465
peer_request ret = m_torrent_file->files().map_file(i, 0, 0);
4466
size_type size = m_torrent_file->files().at(i).size;
4468
// zero sized files are considered
4469
// 100% done all the time
4479
size_type bytes_step = (std::min)(size_type(m_torrent_file->piece_size(ret.piece)
4480
- ret.start), size);
4481
if (m_picker->have_piece(ret.piece)) done += bytes_step;
4486
TORRENT_ASSERT(size == 0);
4491
const std::vector<piece_picker::downloading_piece>& q
4492
= m_picker->get_download_queue();
4494
for (std::vector<piece_picker::downloading_piece>::const_iterator
4495
i = q.begin(), end(q.end()); i != end; ++i)
4497
size_type offset = size_type(i->index) * m_torrent_file->piece_length();
4498
torrent_info::file_iterator file = m_torrent_file->file_at_offset(offset);
4499
int file_index = file - m_torrent_file->begin_files();
4500
int num_blocks = m_picker->blocks_in_piece(i->index);
4501
piece_picker::block_info const* info = i->info;
4502
for (int k = 0; k < num_blocks; ++k)
4504
TORRENT_ASSERT(file != m_torrent_file->end_files());
4505
TORRENT_ASSERT(offset == size_type(i->index) * m_torrent_file->piece_length()
4506
+ k * m_block_size);
4507
TORRENT_ASSERT(offset < m_torrent_file->total_size());
4508
while (offset >= file->offset + file->size)
4513
TORRENT_ASSERT(file != m_torrent_file->end_files());
4515
size_type block_size = m_block_size;
4517
if (info[k].state == piece_picker::block_info::state_none)
4519
offset += m_block_size;
4523
if (info[k].state == piece_picker::block_info::state_requested)
4526
policy::peer* p = static_cast<policy::peer*>(info[k].peer);
4527
if (p && p->connection)
4529
boost::optional<piece_block_progress> pbp
4530
= p->connection->downloading_piece_progress();
4531
if (pbp && pbp->piece_index == i->index && pbp->block_index == k)
4532
block_size = pbp->bytes_downloaded;
4533
TORRENT_ASSERT(block_size <= m_block_size);
4536
if (block_size == 0)
4538
offset += m_block_size;
4543
if (offset + block_size > file->offset + file->size)
4545
int left_over = m_block_size - block_size;
4546
// split the block on multiple files
4547
while (block_size > 0)
4549
TORRENT_ASSERT(offset <= file->offset + file->size);
4550
size_type slice = (std::min)(file->offset + file->size - offset
4552
fp[file_index] += slice;
4554
block_size -= slice;
4555
TORRENT_ASSERT(offset <= file->offset + file->size);
4556
if (offset == file->offset + file->size)
4560
if (file == m_torrent_file->end_files())
4562
offset += block_size;
4567
offset += left_over;
4568
TORRENT_ASSERT(offset == size_type(i->index) * m_torrent_file->piece_length()
4569
+ (k+1) * m_block_size);
4573
fp[file_index] += block_size;
4574
offset += m_block_size;
4576
TORRENT_ASSERT(file_index <= m_torrent_file->num_files());
4581
void torrent::set_state(torrent_status::state_t s)
4583
#ifdef TORRENT_DEBUG
4584
if (s != torrent_status::checking_files
4585
&& s != torrent_status::queued_for_checking)
4587
// the only valid transition away from queued_for_checking
4588
// is to checking_files. One exception is to finished
4589
// in case all the files are marked with priority 0
4590
if (m_queued_for_checking)
4592
std::vector<int> pieces;
4593
m_picker->piece_priorities(pieces);
4594
// make sure all pieces have priority 0
4595
TORRENT_ASSERT(std::count(pieces.begin(), pieces.end(), 0) == pieces.size());
4598
if (s == torrent_status::seeding)
4599
TORRENT_ASSERT(is_seed());
4600
if (s == torrent_status::finished)
4601
TORRENT_ASSERT(is_finished());
4602
if (s == torrent_status::downloading && m_state == torrent_status::finished)
4603
TORRENT_ASSERT(!is_finished());
4606
if (m_state == s) return;
4608
if (m_ses.m_alerts.should_post<state_changed_alert>())
4609
m_ses.m_alerts.post_alert(state_changed_alert(get_handle(), s));
4612
torrent_status torrent::status() const
4616
ptime now = time_now();
4620
st.has_incoming = m_has_incoming;
4623
if (m_last_scrape == min_time())
4625
st.last_scrape = -1;
4629
st.last_scrape = total_seconds(now - m_last_scrape);
4631
st.up_bandwidth_queue = (int)m_bandwidth_queue[peer_connection::upload_channel].size();
4632
st.down_bandwidth_queue = (int)m_bandwidth_queue[peer_connection::download_channel].size();
4634
st.num_peers = (int)std::count_if(m_connections.begin(), m_connections.end()
4635
, !boost::bind(&peer_connection::is_connecting, _1));
4637
st.list_peers = m_policy.num_peers();
4638
st.list_seeds = m_policy.num_seeds();
4639
st.connect_candidates = m_policy.num_connect_candidates();
4640
st.seed_rank = seed_rank(m_ses.m_settings);
4642
st.all_time_upload = m_total_uploaded;
4643
st.all_time_download = m_total_downloaded;
4645
st.active_time = total_seconds(m_active_time);
4646
st.seeding_time = total_seconds(m_seeding_time);
4648
st.storage_mode = m_storage_mode;
4650
st.num_complete = m_complete;
4651
st.num_incomplete = m_incomplete;
4652
st.paused = m_paused;
4653
boost::tie(st.total_done, st.total_wanted_done) = bytes_done();
4654
TORRENT_ASSERT(st.total_wanted_done >= 0);
4655
TORRENT_ASSERT(st.total_done >= st.total_wanted_done);
4658
st.total_payload_download = m_stat.total_payload_download();
4659
st.total_payload_upload = m_stat.total_payload_upload();
4662
st.total_download = m_stat.total_payload_download()
4663
+ m_stat.total_protocol_download();
4664
st.total_upload = m_stat.total_payload_upload()
4665
+ m_stat.total_protocol_upload();
4668
st.total_failed_bytes = m_total_failed_bytes;
4669
st.total_redundant_bytes = m_total_redundant_bytes;
4672
st.download_rate = m_stat.download_rate();
4673
st.upload_rate = m_stat.upload_rate();
4674
st.download_payload_rate = m_stat.download_payload_rate();
4675
st.upload_payload_rate = m_stat.upload_payload_rate();
4677
st.next_announce = boost::posix_time::seconds(
4678
total_seconds(next_announce() - now));
4679
if (st.next_announce.is_negative() || is_paused())
4680
st.next_announce = boost::posix_time::seconds(0);
4682
st.announce_interval = boost::posix_time::seconds(m_duration);
4684
if (m_last_working_tracker >= 0)
4687
= m_trackers[m_last_working_tracker].url;
4690
st.num_uploads = m_num_uploads;
4691
st.uploads_limit = m_max_uploads;
4692
st.num_connections = int(m_connections.size());
4693
st.connections_limit = m_max_connections;
4694
// if we don't have any metadata, stop here
4697
// for backwards compatibility
4698
if (st.state == torrent_status::checking_resume_data)
4699
st.state = torrent_status::queued_for_checking;
4701
if (!valid_metadata())
4703
st.state = torrent_status::downloading_metadata;
4704
st.progress = m_progress;
4709
st.block_size = block_size();
4711
// fill in status that depends on metadata
4713
st.total_wanted = m_torrent_file->total_size();
4714
TORRENT_ASSERT(st.total_wanted >= 0);
4715
TORRENT_ASSERT(st.total_wanted >= m_torrent_file->piece_length()
4716
* (m_torrent_file->num_pieces() - 1));
4718
if (m_picker.get() && (m_picker->num_filtered() > 0
4719
|| m_picker->num_have_filtered() > 0))
4721
int num_filtered_pieces = m_picker->num_filtered()
4722
+ m_picker->num_have_filtered();
4723
int last_piece_index = m_torrent_file->num_pieces() - 1;
4724
if (m_picker->piece_priority(last_piece_index) == 0)
4726
st.total_wanted -= m_torrent_file->piece_size(last_piece_index);
4727
--num_filtered_pieces;
4730
st.total_wanted -= size_type(num_filtered_pieces) * m_torrent_file->piece_length();
4733
TORRENT_ASSERT(st.total_wanted >= st.total_wanted_done);
4735
if (m_state == torrent_status::checking_files)
4736
st.progress = m_progress;
4737
else if (st.total_wanted == 0) st.progress = 1.f;
4738
else st.progress = st.total_wanted_done
4739
/ static_cast<float>(st.total_wanted);
4743
int num_pieces = m_picker->num_pieces();
4744
st.pieces.resize(num_pieces, false);
4745
for (int i = 0; i < num_pieces; ++i)
4746
if (m_picker->have_piece(i)) st.pieces.set_bit(i);
4748
st.num_pieces = num_have();
4749
st.num_seeds = num_seeds();
4751
st.distributed_copies = m_picker->distributed_copies();
4753
st.distributed_copies = -1;
4757
void torrent::add_redundant_bytes(int b)
4759
TORRENT_ASSERT(b > 0);
4760
m_total_redundant_bytes += b;
4761
m_ses.add_redundant_bytes(b);
4764
void torrent::add_failed_bytes(int b)
4766
TORRENT_ASSERT(b > 0);
4767
m_total_failed_bytes += b;
4768
m_ses.add_failed_bytes(b);
4771
int torrent::num_seeds() const
4775
return (int)std::count_if(m_connections.begin(), m_connections.end()
4776
, boost::bind(&peer_connection::is_seed, _1));
4779
void torrent::tracker_request_timed_out(
4780
tracker_request const& r)
4782
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
4786
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
4787
debug_log("*** tracker timed out");
4790
if (r.kind == tracker_request::announce_request)
4792
if (m_ses.m_alerts.should_post<tracker_error_alert>())
4794
m_ses.m_alerts.post_alert(tracker_error_alert(get_handle()
4795
, m_failed_trackers + 1, 0, r.url, "tracker timed out"));
4798
else if (r.kind == tracker_request::scrape_request)
4800
if (m_ses.m_alerts.should_post<scrape_failed_alert>())
4802
m_ses.m_alerts.post_alert(scrape_failed_alert(get_handle()
4803
, r.url, "tracker timed out"));
4807
if (r.kind == tracker_request::announce_request)
4808
try_next_tracker(r);
4811
// TODO: with some response codes, we should just consider
4812
// the tracker as a failure and not retry
4814
void torrent::tracker_request_error(tracker_request const& r
4815
, int response_code, const std::string& str)
4817
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
4821
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
4822
debug_log(std::string("*** tracker error: ") + str);
4824
if (r.kind == tracker_request::announce_request)
4826
if (m_ses.m_alerts.should_post<tracker_error_alert>())
4828
m_ses.m_alerts.post_alert(tracker_error_alert(get_handle()
4829
, m_failed_trackers + 1, response_code, r.url, str));
4832
else if (r.kind == tracker_request::scrape_request)
4834
if (m_ses.m_alerts.should_post<scrape_failed_alert>())
4836
m_ses.m_alerts.post_alert(scrape_failed_alert(get_handle(), r.url, str));
4840
if (r.kind == tracker_request::announce_request)
4841
try_next_tracker(r);
4845
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
4846
void torrent::debug_log(const std::string& line)
4848
(*m_ses.m_logger) << time_now_string() << " " << line << "\n";