delete_files bug fix
[libtorrent.git] / src / session.cpp
blob5e0ad1205025f64050693737c75a5d3f8250809e
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 // if the torrent already exists, this will throw duplicate_torrent
248 torrent_handle session::add_torrent(
249 torrent_info const& ti
250 , fs::path const& save_path
251 , entry const& resume_data
252 , storage_mode_t storage_mode
253 , bool paused
254 , storage_constructor_type sc)
256 boost::intrusive_ptr<torrent_info> tip(new torrent_info(ti));
257 add_torrent_params p(sc);
258 p.ti = tip;
259 p.save_path = save_path;
260 std::vector<char> buf;
261 if (resume_data.type() != entry::undefined_t)
263 bencode(std::back_inserter(buf), resume_data);
264 p.resume_data = &buf;
266 p.storage_mode = storage_mode;
267 p.paused = paused;
268 return m_impl->add_torrent(p);
271 torrent_handle session::add_torrent(
272 boost::intrusive_ptr<torrent_info> ti
273 , fs::path const& save_path
274 , entry const& resume_data
275 , storage_mode_t storage_mode
276 , bool paused
277 , storage_constructor_type sc
278 , void* userdata)
280 add_torrent_params p(sc);
281 p.ti = ti;
282 p.save_path = save_path;
283 std::vector<char> buf;
284 if (resume_data.type() != entry::undefined_t)
286 bencode(std::back_inserter(buf), resume_data);
287 p.resume_data = &buf;
289 p.storage_mode = storage_mode;
290 p.paused = paused;
291 p.userdata = userdata;
292 return m_impl->add_torrent(p);
295 torrent_handle session::add_torrent(
296 char const* tracker_url
297 , sha1_hash const& info_hash
298 , char const* name
299 , fs::path const& save_path
300 , entry const& e
301 , storage_mode_t storage_mode
302 , bool paused
303 , storage_constructor_type sc
304 , void* userdata)
306 add_torrent_params p(sc);
307 p.tracker_url = tracker_url;
308 p.info_hash = info_hash;
309 p.save_path = save_path;
310 p.paused = paused;
311 p.userdata = userdata;
312 return m_impl->add_torrent(p);
315 void session::remove_torrent(const torrent_handle& h, int options)
317 m_impl->remove_torrent(h, options);
320 bool session::listen_on(
321 std::pair<int, int> const& port_range
322 , const char* net_interface)
324 return m_impl->listen_on(port_range, net_interface);
327 unsigned short session::listen_port() const
329 return m_impl->listen_port();
332 session_status session::status() const
334 return m_impl->status();
337 void session::pause() { m_impl->pause(); }
338 void session::resume() { m_impl->resume(); }
339 bool session::is_paused() const { return m_impl->is_paused(); }
341 void session::get_cache_info(sha1_hash const& ih
342 , std::vector<cached_piece_info>& ret) const
344 m_impl->m_disk_thread.get_cache_info(ih, ret);
347 cache_status session::get_cache_status() const
349 return m_impl->m_disk_thread.status();
352 #ifndef TORRENT_DISABLE_DHT
354 void session::start_dht(entry const& startup_state)
356 m_impl->start_dht(startup_state);
359 void session::stop_dht()
361 m_impl->stop_dht();
364 void session::set_dht_settings(dht_settings const& settings)
366 m_impl->set_dht_settings(settings);
369 entry session::dht_state() const
371 return m_impl->dht_state();
374 void session::add_dht_node(std::pair<std::string, int> const& node)
376 m_impl->add_dht_node(node);
379 void session::add_dht_router(std::pair<std::string, int> const& node)
381 m_impl->add_dht_router(node);
384 #endif
386 #ifndef TORRENT_DISABLE_ENCRYPTION
387 void session::set_pe_settings(pe_settings const& settings)
389 m_impl->set_pe_settings(settings);
392 pe_settings const& session::get_pe_settings() const
394 return m_impl->get_pe_settings();
396 #endif
398 bool session::is_listening() const
400 return m_impl->is_listening();
403 void session::set_settings(session_settings const& s)
405 m_impl->set_settings(s);
408 session_settings const& session::settings()
410 return m_impl->settings();
413 void session::set_peer_proxy(proxy_settings const& s)
415 m_impl->set_peer_proxy(s);
418 void session::set_web_seed_proxy(proxy_settings const& s)
420 m_impl->set_web_seed_proxy(s);
423 void session::set_tracker_proxy(proxy_settings const& s)
425 m_impl->set_tracker_proxy(s);
428 proxy_settings const& session::peer_proxy() const
430 return m_impl->peer_proxy();
433 proxy_settings const& session::web_seed_proxy() const
435 return m_impl->web_seed_proxy();
438 proxy_settings const& session::tracker_proxy() const
440 return m_impl->tracker_proxy();
444 #ifndef TORRENT_DISABLE_DHT
445 void session::set_dht_proxy(proxy_settings const& s)
447 m_impl->set_dht_proxy(s);
450 proxy_settings const& session::dht_proxy() const
452 return m_impl->dht_proxy();
454 #endif
456 void session::set_max_uploads(int limit)
458 m_impl->set_max_uploads(limit);
461 void session::set_max_connections(int limit)
463 m_impl->set_max_connections(limit);
466 int session::max_half_open_connections() const
468 return m_impl->max_half_open_connections();
471 void session::set_max_half_open_connections(int limit)
473 m_impl->set_max_half_open_connections(limit);
476 int session::upload_rate_limit() const
478 return m_impl->upload_rate_limit();
481 int session::download_rate_limit() const
483 return m_impl->download_rate_limit();
486 void session::set_upload_rate_limit(int bytes_per_second)
488 m_impl->set_upload_rate_limit(bytes_per_second);
491 void session::set_download_rate_limit(int bytes_per_second)
493 m_impl->set_download_rate_limit(bytes_per_second);
496 int session::num_uploads() const
498 return m_impl->num_uploads();
501 int session::num_connections() const
503 return m_impl->num_connections();
506 std::auto_ptr<alert> session::pop_alert()
508 return m_impl->pop_alert();
511 alert const* session::wait_for_alert(time_duration max_wait)
513 return m_impl->wait_for_alert(max_wait);
516 void session::set_alert_mask(int m)
518 m_impl->set_alert_mask(m);
521 void session::set_severity_level(alert::severity_t s)
523 int m = 0;
524 switch (s)
526 case alert::debug: m = alert::all_categories; break;
527 case alert::info: m = alert::all_categories & ~(alert::debug_notification
528 | alert::progress_notification); break;
529 case alert::warning: m = alert::all_categories & ~(alert::debug_notification
530 | alert::status_notification | alert::progress_notification); break;
531 case alert::critical: m = alert::error_notification | alert::storage_notification; break;
532 case alert::fatal: m = alert::error_notification; break;
533 default: break;
536 m_impl->set_alert_mask(m);
539 void session::start_lsd()
541 m_impl->start_lsd();
544 natpmp* session::start_natpmp()
546 return m_impl->start_natpmp();
549 upnp* session::start_upnp()
551 return m_impl->start_upnp();
554 void session::stop_lsd()
556 m_impl->stop_lsd();
559 void session::stop_natpmp()
561 m_impl->stop_natpmp();
564 void session::stop_upnp()
566 m_impl->stop_upnp();
569 connection_queue& session::get_connection_queue()
571 return m_impl->m_half_open;