fixes bug where priorities where lost when force-rechecking.
[libtorrent.git] / src / session.cpp
blob3c65d02b5b747c97f55e6f3ef7580c701332f262
1 /*
3 Copyright (c) 2006, Arvid Norberg, Magnus Jonsson
4 All rights reserved.
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
8 are met:
10 * Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in
14 the documentation and/or other materials provided with the distribution.
15 * Neither the name of the author nor the names of its
16 contributors may be used to endorse or promote products derived
17 from this software without specific prior written permission.
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 POSSIBILITY OF SUCH DAMAGE.
33 #include "libtorrent/pch.hpp"
35 #include <ctime>
36 #include <iostream>
37 #include <fstream>
38 #include <iomanip>
39 #include <iterator>
40 #include <algorithm>
41 #include <set>
42 #include <cctype>
43 #include <algorithm>
45 #ifdef _MSC_VER
46 #pragma warning(push, 1)
47 #endif
49 #include <boost/lexical_cast.hpp>
50 #include <boost/filesystem/convenience.hpp>
51 #include <boost/filesystem/exception.hpp>
52 #include <boost/limits.hpp>
53 #include <boost/bind.hpp>
55 #ifdef _MSC_VER
56 #pragma warning(pop)
57 #endif
59 #include "libtorrent/peer_id.hpp"
60 #include "libtorrent/torrent_info.hpp"
61 #include "libtorrent/tracker_manager.hpp"
62 #include "libtorrent/bencode.hpp"
63 #include "libtorrent/hasher.hpp"
64 #include "libtorrent/entry.hpp"
65 #include "libtorrent/session.hpp"
66 #include "libtorrent/fingerprint.hpp"
67 #include "libtorrent/entry.hpp"
68 #include "libtorrent/alert_types.hpp"
69 #include "libtorrent/invariant_check.hpp"
70 #include "libtorrent/file.hpp"
71 #include "libtorrent/bt_peer_connection.hpp"
72 #include "libtorrent/ip_filter.hpp"
73 #include "libtorrent/socket.hpp"
74 #include "libtorrent/aux_/session_impl.hpp"
75 #include "libtorrent/kademlia/dht_tracker.hpp"
77 using boost::shared_ptr;
78 using boost::weak_ptr;
79 using boost::bind;
80 using boost::mutex;
81 using libtorrent::aux::session_impl;
83 #ifdef TORRENT_MEMDEBUG
84 void start_malloc_debug();
85 void stop_malloc_debug();
86 #endif
88 namespace libtorrent
91 std::string log_time()
93 static const ptime start = time_now();
94 char ret[200];
95 std::sprintf(ret, "%d", total_milliseconds(time_now() - start));
96 return ret;
99 namespace aux
101 filesystem_init::filesystem_init()
103 #if BOOST_VERSION < 103400
104 using namespace boost::filesystem;
105 if (path::default_name_check_writable())
106 path::default_name_check(no_check);
107 #endif
111 session::session(
112 fingerprint const& id
113 , std::pair<int, int> listen_port_range
114 , char const* listen_interface
115 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
116 , fs::path logpath
117 #endif
119 : m_impl(new session_impl(listen_port_range, id, listen_interface
120 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
121 , logpath
122 #endif
125 #ifdef TORRENT_MEMDEBUG
126 start_malloc_debug();
127 #endif
128 // turn off the filename checking in boost.filesystem
129 TORRENT_ASSERT(listen_port_range.first > 0);
130 TORRENT_ASSERT(listen_port_range.first < listen_port_range.second);
131 #ifndef NDEBUG
132 // this test was added after it came to my attention
133 // that devstudios managed c++ failed to generate
134 // correct code for boost.function
135 boost::function0<void> test = boost::ref(*m_impl);
136 TORRENT_ASSERT(!test.empty());
137 #endif
140 session::session(fingerprint const& id
141 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
142 , fs::path logpath
143 #endif
145 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
146 : m_impl(new session_impl(std::make_pair(0, 0), id, "0.0.0.0", logpath))
147 #else
148 : m_impl(new session_impl(std::make_pair(0, 0), id, "0.0.0.0"))
149 #endif
151 #ifdef TORRENT_MEMDEBUG
152 start_malloc_debug();
153 #endif
154 #ifndef NDEBUG
155 boost::function0<void> test = boost::ref(*m_impl);
156 TORRENT_ASSERT(!test.empty());
157 #endif
160 session::~session()
162 #ifdef TORRENT_MEMDEBUG
163 stop_malloc_debug();
164 #endif
165 TORRENT_ASSERT(m_impl);
166 // if there is at least one destruction-proxy
167 // abort the session and let the destructor
168 // of the proxy to syncronize
169 if (!m_impl.unique())
170 m_impl->abort();
173 void session::add_extension(boost::function<boost::shared_ptr<torrent_plugin>(torrent*, void*)> ext)
175 m_impl->add_extension(ext);
178 #ifndef TORRENT_DISABLE_GEO_IP
179 bool session::load_asnum_db(char const* file)
181 return m_impl->load_asnum_db(file);
184 bool session::load_country_db(char const* file)
186 return m_impl->load_country_db(file);
189 int session::as_for_ip(address const& addr)
191 aux::session_impl::mutex_t::scoped_lock l(m_impl->m_mutex);
192 return m_impl->as_for_ip(addr);
195 #endif
197 void session::load_state(entry const& ses_state)
199 m_impl->load_state(ses_state);
202 entry session::state() const
204 return m_impl->state();
207 void session::set_ip_filter(ip_filter const& f)
209 m_impl->set_ip_filter(f);
212 void session::set_port_filter(port_filter const& f)
214 m_impl->set_port_filter(f);
217 void session::set_peer_id(peer_id const& id)
219 m_impl->set_peer_id(id);
222 peer_id session::id() const
224 return m_impl->get_peer_id();
227 void session::set_key(int key)
229 m_impl->set_key(key);
232 std::vector<torrent_handle> session::get_torrents() const
234 return m_impl->get_torrents();
237 torrent_handle session::find_torrent(sha1_hash const& info_hash) const
239 return m_impl->find_torrent_handle(info_hash);
242 torrent_handle session::add_torrent(add_torrent_params const& params)
244 return m_impl->add_torrent(params);
247 #ifndef TORRENT_NO_DEPRECATE
248 // if the torrent already exists, this will throw duplicate_torrent
249 torrent_handle session::add_torrent(
250 torrent_info const& ti
251 , fs::path const& save_path
252 , entry const& resume_data
253 , storage_mode_t storage_mode
254 , bool paused
255 , storage_constructor_type sc)
257 boost::intrusive_ptr<torrent_info> tip(new torrent_info(ti));
258 add_torrent_params p(sc);
259 p.ti = tip;
260 p.save_path = save_path;
261 std::vector<char> buf;
262 if (resume_data.type() != entry::undefined_t)
264 bencode(std::back_inserter(buf), resume_data);
265 p.resume_data = &buf;
267 p.storage_mode = storage_mode;
268 p.paused = paused;
269 return m_impl->add_torrent(p);
272 torrent_handle session::add_torrent(
273 boost::intrusive_ptr<torrent_info> ti
274 , fs::path const& save_path
275 , entry const& resume_data
276 , storage_mode_t storage_mode
277 , bool paused
278 , storage_constructor_type sc
279 , void* userdata)
281 add_torrent_params p(sc);
282 p.ti = ti;
283 p.save_path = save_path;
284 std::vector<char> buf;
285 if (resume_data.type() != entry::undefined_t)
287 bencode(std::back_inserter(buf), resume_data);
288 p.resume_data = &buf;
290 p.storage_mode = storage_mode;
291 p.paused = paused;
292 p.userdata = userdata;
293 return m_impl->add_torrent(p);
296 torrent_handle session::add_torrent(
297 char const* tracker_url
298 , sha1_hash const& info_hash
299 , char const* name
300 , fs::path const& save_path
301 , entry const& e
302 , storage_mode_t storage_mode
303 , bool paused
304 , storage_constructor_type sc
305 , void* userdata)
307 add_torrent_params p(sc);
308 p.tracker_url = tracker_url;
309 p.info_hash = info_hash;
310 p.save_path = save_path;
311 p.paused = paused;
312 p.userdata = userdata;
313 return m_impl->add_torrent(p);
315 #endif
317 void session::remove_torrent(const torrent_handle& h, int options)
319 m_impl->remove_torrent(h, options);
322 bool session::listen_on(
323 std::pair<int, int> const& port_range
324 , const char* net_interface)
326 return m_impl->listen_on(port_range, net_interface);
329 unsigned short session::listen_port() const
331 return m_impl->listen_port();
334 session_status session::status() const
336 return m_impl->status();
339 void session::pause() { m_impl->pause(); }
340 void session::resume() { m_impl->resume(); }
341 bool session::is_paused() const { return m_impl->is_paused(); }
343 void session::get_cache_info(sha1_hash const& ih
344 , std::vector<cached_piece_info>& ret) const
346 m_impl->m_disk_thread.get_cache_info(ih, ret);
349 cache_status session::get_cache_status() const
351 return m_impl->m_disk_thread.status();
354 #ifndef TORRENT_DISABLE_DHT
356 void session::start_dht(entry const& startup_state)
358 m_impl->start_dht(startup_state);
361 void session::stop_dht()
363 m_impl->stop_dht();
366 void session::set_dht_settings(dht_settings const& settings)
368 m_impl->set_dht_settings(settings);
371 entry session::dht_state() const
373 return m_impl->dht_state();
376 void session::add_dht_node(std::pair<std::string, int> const& node)
378 m_impl->add_dht_node(node);
381 void session::add_dht_router(std::pair<std::string, int> const& node)
383 m_impl->add_dht_router(node);
386 #endif
388 #ifndef TORRENT_DISABLE_ENCRYPTION
389 void session::set_pe_settings(pe_settings const& settings)
391 m_impl->set_pe_settings(settings);
394 pe_settings const& session::get_pe_settings() const
396 return m_impl->get_pe_settings();
398 #endif
400 bool session::is_listening() const
402 return m_impl->is_listening();
405 void session::set_settings(session_settings const& s)
407 m_impl->set_settings(s);
410 session_settings const& session::settings()
412 return m_impl->settings();
415 void session::set_peer_proxy(proxy_settings const& s)
417 m_impl->set_peer_proxy(s);
420 void session::set_web_seed_proxy(proxy_settings const& s)
422 m_impl->set_web_seed_proxy(s);
425 void session::set_tracker_proxy(proxy_settings const& s)
427 m_impl->set_tracker_proxy(s);
430 proxy_settings const& session::peer_proxy() const
432 return m_impl->peer_proxy();
435 proxy_settings const& session::web_seed_proxy() const
437 return m_impl->web_seed_proxy();
440 proxy_settings const& session::tracker_proxy() const
442 return m_impl->tracker_proxy();
446 #ifndef TORRENT_DISABLE_DHT
447 void session::set_dht_proxy(proxy_settings const& s)
449 m_impl->set_dht_proxy(s);
452 proxy_settings const& session::dht_proxy() const
454 return m_impl->dht_proxy();
456 #endif
458 void session::set_max_uploads(int limit)
460 m_impl->set_max_uploads(limit);
463 void session::set_max_connections(int limit)
465 m_impl->set_max_connections(limit);
468 int session::max_half_open_connections() const
470 return m_impl->max_half_open_connections();
473 void session::set_max_half_open_connections(int limit)
475 m_impl->set_max_half_open_connections(limit);
478 int session::upload_rate_limit() const
480 return m_impl->upload_rate_limit();
483 int session::download_rate_limit() const
485 return m_impl->download_rate_limit();
488 void session::set_upload_rate_limit(int bytes_per_second)
490 m_impl->set_upload_rate_limit(bytes_per_second);
493 void session::set_download_rate_limit(int bytes_per_second)
495 m_impl->set_download_rate_limit(bytes_per_second);
498 int session::num_uploads() const
500 return m_impl->num_uploads();
503 int session::num_connections() const
505 return m_impl->num_connections();
508 std::auto_ptr<alert> session::pop_alert()
510 return m_impl->pop_alert();
513 alert const* session::wait_for_alert(time_duration max_wait)
515 return m_impl->wait_for_alert(max_wait);
518 void session::set_alert_mask(int m)
520 m_impl->set_alert_mask(m);
523 #ifndef TORRENT_NO_DEPRECATE
524 void session::set_severity_level(alert::severity_t s)
526 int m = 0;
527 switch (s)
529 case alert::debug: m = alert::all_categories; break;
530 case alert::info: m = alert::all_categories & ~(alert::debug_notification
531 | alert::progress_notification); break;
532 case alert::warning: m = alert::all_categories & ~(alert::debug_notification
533 | alert::status_notification | alert::progress_notification); break;
534 case alert::critical: m = alert::error_notification | alert::storage_notification; break;
535 case alert::fatal: m = alert::error_notification; break;
536 default: break;
539 m_impl->set_alert_mask(m);
541 #endif
543 void session::start_lsd()
545 m_impl->start_lsd();
548 natpmp* session::start_natpmp()
550 return m_impl->start_natpmp();
553 upnp* session::start_upnp()
555 return m_impl->start_upnp();
558 void session::stop_lsd()
560 m_impl->stop_lsd();
563 void session::stop_natpmp()
565 m_impl->stop_natpmp();
568 void session::stop_upnp()
570 m_impl->stop_upnp();
573 connection_queue& session::get_connection_queue()
575 return m_impl->m_half_open;