1
// libTorrent - BitTorrent library
2
// Copyright (C) 2005-2007, Jari Sundell
4
// This program is free software; you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation; either version 2 of the License, or
7
// (at your option) any later version.
9
// This program is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
// GNU General Public License for more details.
14
// You should have received a copy of the GNU General Public License
15
// along with this program; if not, write to the Free Software
16
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
// In addition, as a special exception, the copyright holders give
19
// permission to link the code of portions of this program with the
20
// OpenSSL library under certain conditions as described in each
21
// individual source file, and distribute linked combinations
24
// You must obey the GNU General Public License in all respects for
25
// all of the code used other than OpenSSL. If you modify file(s)
26
// with this exception, you may extend this exception to your version
27
// of the file(s), but you are not obligated to do so. If you do not
28
// wish to do so, delete this exception statement from your version.
29
// If you delete this exception statement from all source files in the
30
// program, then also delete it here.
32
// Contact: Jari Sundell <jaris@ifi.uio.no>
35
// 3185 Skoppum, NORWAY
39
#include <rak/functional.h>
40
#include <sigc++/adaptors/bind.h>
41
#include <sigc++/adaptors/hide.h>
43
#include "data/block.h"
44
#include "data/block_list.h"
45
#include "data/chunk_list.h"
46
#include "data/hash_queue.h"
47
#include "data/hash_torrent.h"
48
#include "download/available_list.h"
49
#include "download/choke_manager.h"
50
#include "download/chunk_selector.h"
51
#include "download/chunk_statistics.h"
52
#include "download/download_wrapper.h"
53
#include "protocol/peer_connection_base.h"
54
#include "protocol/peer_factory.h"
55
#include "peer/peer_info.h"
56
#include "tracker/tracker_manager.h"
57
#include "torrent/download_info.h"
58
#include "torrent/data/file.h"
59
#include "torrent/peer/connection_list.h"
61
#include "exceptions.h"
65
#include "tracker_list.h"
70
Download::info() const { return m_ptr->info(); }
73
Download::open(int flags) {
74
if (m_ptr->info()->is_open())
77
// Currently always open with no_create, as start will make sure
78
// they are created. Need to fix this.
79
m_ptr->main()->open(FileList::open_no_create);
80
m_ptr->hash_checker()->ranges().insert(0, m_ptr->main()->file_list()->size_chunks());
82
// Mark the files by default to be created and resized. The client
83
// should be allowed to pass a flag that will keep the old settings,
84
// although loading resume data should really handle everything
86
int fileFlags = File::flag_create_queued | File::flag_resize_queued;
88
if (flags & open_enable_fallocate)
89
fileFlags |= File::flag_fallocate;
91
for (FileList::iterator itr = m_ptr->main()->file_list()->begin(), last = m_ptr->main()->file_list()->end(); itr != last; itr++)
92
(*itr)->set_flags(fileFlags);
96
Download::close(int flags) {
97
if (m_ptr->info()->is_active())
104
Download::start(int flags) {
105
if (!m_ptr->hash_checker()->is_checked())
106
throw internal_error("Tried to start an unchecked download.");
108
if (!m_ptr->info()->is_open())
109
throw internal_error("Tried to start a closed download.");
111
if (m_ptr->info()->is_active())
114
// file_list()->open(flags);
116
// If the FileList::open_no_create flag was not set, our new
117
// behavior is to create all zero-length files with
118
// flag_queued_create set.
119
file_list()->open(flags & ~FileList::open_no_create);
121
if (m_ptr->connection_type() == CONNECTION_INITIAL_SEED) {
122
if (!m_ptr->main()->start_initial_seeding())
123
set_connection_type(CONNECTION_SEED);
126
m_ptr->main()->start();
127
m_ptr->main()->tracker_manager()->set_active(true);
129
// Reset the uploaded/download baseline when we restart the download
130
// so that broken trackers get the right uploaded ratio.
131
if (!(flags & start_keep_baseline)) {
132
m_ptr->info()->set_uploaded_baseline(m_ptr->info()->up_rate()->total());
133
m_ptr->info()->set_completed_baseline(m_ptr->main()->file_list()->completed_bytes());
136
if (flags & start_skip_tracker)
137
// If tracker_manager isn't active and nothing is sent, it will
139
m_ptr->main()->tracker_manager()->send_later();
141
m_ptr->main()->tracker_manager()->send_start();
145
Download::stop(int flags) {
146
if (!m_ptr->info()->is_active())
149
m_ptr->main()->stop();
150
m_ptr->main()->tracker_manager()->set_active(false);
152
if (!(flags & stop_skip_tracker))
153
m_ptr->main()->tracker_manager()->send_stop();
157
Download::hash_check(bool tryQuick) {
158
if (m_ptr->hash_checker()->is_checking())
159
throw internal_error("Download::hash_check(...) called but the hash is already being checked.");
161
if (!m_ptr->info()->is_open() || m_ptr->info()->is_active())
162
throw internal_error("Download::hash_check(...) called on a closed or active download.");
164
if (m_ptr->hash_checker()->is_checked())
165
throw internal_error("Download::hash_check(...) called but already hash checked.");
167
Bitfield* bitfield = m_ptr->main()->file_list()->mutable_bitfield();
169
if (bitfield->empty()) {
170
// The bitfield still hasn't been allocated, so no resume data was
172
bitfield->allocate();
173
bitfield->unset_all();
175
m_ptr->hash_checker()->ranges().insert(0, m_ptr->main()->file_list()->size_chunks());
178
m_ptr->main()->file_list()->update_completed();
180
return m_ptr->hash_checker()->start(tryQuick);
183
// Propably not correct, need to clear content, etc.
185
Download::hash_stop() {
186
if (!m_ptr->hash_checker()->is_checking())
189
m_ptr->hash_checker()->ranges().erase(0, m_ptr->hash_checker()->position());
190
m_ptr->hash_queue()->remove(m_ptr);
192
m_ptr->hash_checker()->clear();
196
Download::is_hash_checked() const {
197
return m_ptr->hash_checker()->is_checked();
201
Download::is_hash_checking() const {
202
return m_ptr->hash_checker()->is_checking();
206
Download::set_pex_enabled(bool enabled) {
207
m_ptr->info()->change_flags(DownloadInfo::flag_pex_enabled, enabled);
211
Download::bencode() {
212
return m_ptr->bencode();
216
Download::bencode() const {
217
return m_ptr->bencode();
221
Download::file_list() const {
222
return m_ptr->main()->file_list();
226
Download::tracker_list() const {
227
return m_ptr->main()->tracker_manager()->container();
231
Download::peer_list() {
232
return m_ptr->main()->peer_list();
236
Download::peer_list() const {
237
return m_ptr->main()->peer_list();
241
Download::transfer_list() const {
242
return m_ptr->main()->delegator()->transfer_list();
246
Download::connection_list() {
247
return m_ptr->main()->connection_list();
250
const ConnectionList*
251
Download::connection_list() const {
252
return m_ptr->main()->connection_list();
256
Download::bytes_done() const {
259
Delegator* d = m_ptr->main()->delegator();
261
for (TransferList::const_iterator itr1 = d->transfer_list()->begin(), last1 = d->transfer_list()->end(); itr1 != last1; ++itr1)
262
for (BlockList::const_iterator itr2 = (*itr1)->begin(), last2 = (*itr1)->end(); itr2 != last2; ++itr2)
263
if (itr2->is_finished())
264
a += itr2->piece().length();
266
return a + m_ptr->main()->file_list()->completed_bytes();
270
Download::chunks_hashed() const {
271
return m_ptr->hash_checker()->position();
275
Download::chunks_seen() const {
276
return !m_ptr->main()->chunk_statistics()->empty() ? &*m_ptr->main()->chunk_statistics()->begin() : NULL;
280
Download::set_chunks_done(uint32_t chunks) {
281
if (m_ptr->info()->is_open())
282
throw input_error("Download::set_chunks_done(...) Download is open.");
284
m_ptr->main()->file_list()->mutable_bitfield()->set_size_set(chunks);
288
Download::set_bitfield(bool allSet) {
289
if (m_ptr->hash_checker()->is_checked() || m_ptr->hash_checker()->is_checking())
290
throw input_error("Download::set_bitfield(...) Download in invalid state.");
292
Bitfield* bitfield = m_ptr->main()->file_list()->mutable_bitfield();
294
bitfield->allocate();
299
bitfield->unset_all();
301
m_ptr->hash_checker()->ranges().clear();
305
Download::set_bitfield(uint8_t* first, uint8_t* last) {
306
if (m_ptr->hash_checker()->is_checked() || m_ptr->hash_checker()->is_checking())
307
throw input_error("Download::set_bitfield(...) Download in invalid state.");
309
if (std::distance(first, last) != (ptrdiff_t)m_ptr->main()->file_list()->bitfield()->size_bytes())
310
throw input_error("Download::set_bitfield(...) Invalid length.");
312
Bitfield* bitfield = m_ptr->main()->file_list()->mutable_bitfield();
314
bitfield->allocate();
315
std::memcpy(bitfield->begin(), first, bitfield->size_bytes());
318
m_ptr->hash_checker()->ranges().clear();
322
Download::update_range(int flags, uint32_t first, uint32_t last) {
323
if (m_ptr->hash_checker()->is_checked() ||
324
m_ptr->hash_checker()->is_checking() ||
325
m_ptr->main()->file_list()->bitfield()->empty())
326
throw input_error("Download::clear_range(...) Download in invalid state.");
328
if (flags & update_range_recheck)
329
m_ptr->hash_checker()->ranges().insert(first, last);
331
if (flags & (update_range_clear | update_range_recheck))
332
m_ptr->main()->file_list()->mutable_bitfield()->unset_range(first, last);
336
Download::sync_chunks() {
337
m_ptr->main()->chunk_list()->sync_chunks(ChunkList::sync_all | ChunkList::sync_force);
341
Download::peers_complete() const {
342
return m_ptr->main()->chunk_statistics()->complete();
346
Download::peers_accounted() const {
347
return m_ptr->main()->chunk_statistics()->accounted();
351
Download::peers_currently_unchoked() const {
352
return m_ptr->main()->upload_choke_manager()->size_unchoked();
356
Download::peers_currently_interested() const {
357
return m_ptr->main()->upload_choke_manager()->size_total();
361
Download::size_pex() const {
362
return m_ptr->main()->info()->size_pex();
366
Download::max_size_pex() const {
367
return m_ptr->main()->info()->max_size_pex();
371
Download::accepting_new_peers() const {
372
return m_ptr->info()->is_accepting_new_peers();
376
Download::uploads_max() const {
377
if (m_ptr->main()->upload_choke_manager()->max_unchoked() == ChokeManager::unlimited)
380
return m_ptr->main()->upload_choke_manager()->max_unchoked();
384
Download::set_upload_throttle(Throttle* t) {
385
if (m_ptr->info()->is_active())
386
throw internal_error("Download::set_upload_throttle() called on active download.");
388
m_ptr->main()->set_upload_throttle(t->throttle_list());
392
Download::set_download_throttle(Throttle* t) {
393
if (m_ptr->info()->is_active())
394
throw internal_error("Download::set_download_throttle() called on active download.");
396
m_ptr->main()->set_download_throttle(t->throttle_list());
400
Download::set_uploads_max(uint32_t v) {
402
throw input_error("Max uploads must be between 0 and 2^16.");
404
// For the moment, treat 0 as unlimited.
405
m_ptr->main()->upload_choke_manager()->set_max_unchoked(v == 0 ? ChokeManager::unlimited : v);
406
m_ptr->main()->upload_choke_manager()->balance();
409
Download::ConnectionType
410
Download::connection_type() const {
411
return (ConnectionType)m_ptr->connection_type();
415
Download::set_connection_type(ConnectionType t) {
416
if (m_ptr->info()->is_meta_download()) {
417
m_ptr->main()->connection_list()->slot_new_connection(&createPeerConnectionMetadata);
422
case CONNECTION_LEECH:
423
m_ptr->main()->connection_list()->slot_new_connection(&createPeerConnectionDefault);
425
case CONNECTION_SEED:
426
m_ptr->main()->connection_list()->slot_new_connection(&createPeerConnectionSeed);
428
case CONNECTION_INITIAL_SEED:
429
if (info()->is_active() && m_ptr->main()->initial_seeding() == NULL)
430
throw input_error("Can't switch to initial seeding: download is active.");
431
m_ptr->main()->connection_list()->slot_new_connection(&createPeerConnectionInitialSeed);
434
throw input_error("torrent::Download::set_connection_type(...) received an unknown type.");
437
m_ptr->set_connection_type(t);
441
Download::update_priorities() {
442
m_ptr->receive_update_priorities();
446
Download::add_peer(const sockaddr* sa, int port) {
447
if (m_ptr->info()->is_private())
450
rak::socket_address sa_port = *rak::socket_address::cast_from(sa);
451
sa_port.set_port(port);
452
m_ptr->main()->add_peer(sa_port);