file_progress fix
[libtorrent.git] / src / session_impl.cpp
blob774159b6620a614e37d51ca448c855e1d73725dc
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"
76 #include "libtorrent/enum_net.hpp"
77 #include "libtorrent/config.hpp"
79 #ifndef TORRENT_WINDOWS
80 #include <sys/resource.h>
81 #endif
83 #ifndef TORRENT_DISABLE_ENCRYPTION
85 #include <openssl/crypto.h>
87 namespace
89 // openssl requires this to clean up internal
90 // structures it allocates
91 struct openssl_cleanup
93 ~openssl_cleanup() { CRYPTO_cleanup_all_ex_data(); }
94 } openssl_global_destructor;
97 #endif
98 #ifdef _WIN32
99 // for ERROR_SEM_TIMEOUT
100 #include <winerror.h>
101 #endif
103 using boost::shared_ptr;
104 using boost::weak_ptr;
105 using boost::bind;
106 using boost::mutex;
107 using libtorrent::aux::session_impl;
109 namespace libtorrent {
111 namespace fs = boost::filesystem;
113 namespace detail
116 std::string generate_auth_string(std::string const& user
117 , std::string const& passwd)
119 if (user.empty()) return std::string();
120 return user + ":" + passwd;
125 namespace aux {
127 struct seed_random_generator
129 seed_random_generator()
131 std::srand(total_microseconds(time_now() - min_time()));
135 session_impl::session_impl(
136 std::pair<int, int> listen_port_range
137 , fingerprint const& cl_fprint
138 , char const* listen_interface
139 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
140 , fs::path const& logpath
141 #endif
144 #ifndef TORRENT_DISABLE_POOL_ALLOCATOR
145 m_send_buffers(send_buffer_size),
146 #endif
147 m_files(40)
148 , m_io_service()
149 , m_disk_thread(m_io_service)
150 , m_half_open(m_io_service)
151 , m_download_channel(m_io_service, peer_connection::download_channel)
152 #ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT
153 , m_upload_channel(m_io_service, peer_connection::upload_channel, true)
154 #else
155 , m_upload_channel(m_io_service, peer_connection::upload_channel)
156 #endif
157 , m_tracker_manager(m_settings, m_tracker_proxy)
158 , m_listen_port_retries(listen_port_range.second - listen_port_range.first)
159 , m_listen_interface(address::from_string(listen_interface), listen_port_range.first)
160 , m_abort(false)
161 , m_paused(false)
162 , m_max_uploads(8)
163 , m_allowed_upload_slots(8)
164 , m_max_connections(200)
165 , m_num_unchoked(0)
166 , m_unchoke_time_scaler(0)
167 , m_auto_manage_time_scaler(0)
168 , m_optimistic_unchoke_time_scaler(0)
169 , m_disconnect_time_scaler(90)
170 , m_auto_scrape_time_scaler(180)
171 , m_incoming_connection(false)
172 , m_last_tick(time_now())
173 #ifndef TORRENT_DISABLE_DHT
174 , m_dht_same_port(true)
175 , m_external_udp_port(0)
176 , m_dht_socket(m_io_service, bind(&session_impl::on_receive_udp, this, _1, _2, _3, _4)
177 , m_half_open)
178 #endif
179 , m_timer(m_io_service)
180 , m_next_connect_torrent(0)
181 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
182 , m_logpath(logpath)
183 #endif
184 #ifndef TORRENT_DISABLE_GEO_IP
185 , m_asnum_db(0)
186 , m_country_db(0)
187 #endif
188 , m_total_failed_bytes(0)
189 , m_total_redundant_bytes(0)
191 m_tcp_mapping[0] = -1;
192 m_tcp_mapping[1] = -1;
193 m_udp_mapping[0] = -1;
194 m_udp_mapping[1] = -1;
195 #ifdef WIN32
196 // windows XP has a limit on the number of
197 // simultaneous half-open TCP connections
198 DWORD windows_version = ::GetVersion();
199 if ((windows_version & 0xff) >= 6)
201 // on vista the limit is 5 (in home edition)
202 m_half_open.limit(4);
204 else
206 // on XP SP2 it's 10
207 m_half_open.limit(8);
209 #endif
211 m_bandwidth_manager[peer_connection::download_channel] = &m_download_channel;
212 m_bandwidth_manager[peer_connection::upload_channel] = &m_upload_channel;
214 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
215 m_logger = create_log("main_session", listen_port(), false);
216 (*m_logger) << time_now_string() << "\n";
218 (*m_logger) << "sizeof(torrent): " << sizeof(torrent) << "\n";
219 (*m_logger) << "sizeof(peer_connection): " << sizeof(peer_connection) << "\n";
220 (*m_logger) << "sizeof(bt_peer_connection): " << sizeof(bt_peer_connection) << "\n";
221 (*m_logger) << "sizeof(policy::peer): " << sizeof(policy::peer) << "\n";
222 #endif
224 #ifdef TORRENT_STATS
225 m_stats_logger.open("session_stats.log", std::ios::trunc);
226 m_stats_logger <<
227 "1. second\n"
228 "2. upload rate\n"
229 "3. download rate\n"
230 "4. downloading torrents\n"
231 "5. seeding torrents\n"
232 "6. peers\n"
233 "7. connecting peers\n"
234 "8. disk block buffers\n"
235 "\n";
236 m_buffer_usage_logger.open("buffer_stats.log", std::ios::trunc);
237 m_second_counter = 0;
238 m_buffer_allocations = 0;
239 #endif
241 // ---- generate a peer id ----
242 static seed_random_generator seeder;
244 m_key = rand() + (rand() << 15) + (rand() << 30);
245 std::string print = cl_fprint.to_string();
246 TORRENT_ASSERT(print.length() <= 20);
248 // the client's fingerprint
249 std::copy(
250 print.begin()
251 , print.begin() + print.length()
252 , m_peer_id.begin());
254 // http-accepted characters:
255 static char const printable[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
256 "abcdefghijklmnopqrstuvwxyz-_.!~*'()";
258 // the random number
259 for (unsigned char* i = m_peer_id.begin() + print.length();
260 i != m_peer_id.end(); ++i)
262 *i = printable[rand() % (sizeof(printable)-1)];
265 error_code ec;
266 m_timer.expires_from_now(seconds(1), ec);
267 m_timer.async_wait(
268 bind(&session_impl::second_tick, this, _1));
270 m_thread.reset(new boost::thread(boost::ref(*this)));
273 #ifndef TORRENT_DISABLE_GEO_IP
274 namespace
276 struct free_ptr
278 void* ptr_;
279 free_ptr(void* p): ptr_(p) {}
280 ~free_ptr() { free(ptr_); }
284 char const* session_impl::country_for_ip(address const& a)
286 if (!a.is_v4() || m_country_db == 0) return 0;
287 return GeoIP_country_code_by_ipnum(m_country_db, a.to_v4().to_ulong());
290 int session_impl::as_for_ip(address const& a)
292 if (!a.is_v4() || m_asnum_db == 0) return 0;
293 char* name = GeoIP_name_by_ipnum(m_asnum_db, a.to_v4().to_ulong());
294 if (name == 0) return 0;
295 free_ptr p(name);
296 // GeoIP returns the name as AS??? where ? is the AS-number
297 return atoi(name + 2);
300 std::string session_impl::as_name_for_ip(address const& a)
302 if (!a.is_v4() || m_asnum_db == 0) return std::string();
303 char* name = GeoIP_name_by_ipnum(m_asnum_db, a.to_v4().to_ulong());
304 if (name == 0) return std::string();
305 free_ptr p(name);
306 char* tmp = std::strchr(name, ' ');
307 if (tmp == 0) return std::string();
308 return tmp + 1;
311 std::pair<const int, int>* session_impl::lookup_as(int as)
313 std::map<int, int>::iterator i = m_as_peak.lower_bound(as);
315 if (i == m_as_peak.end() || i->first != as)
317 // we don't have any data for this AS, insert a new entry
318 i = m_as_peak.insert(i, std::pair<int, int>(as, 0));
320 return &(*i);
323 bool session_impl::load_asnum_db(char const* file)
325 mutex_t::scoped_lock l(m_mutex);
326 if (m_asnum_db) GeoIP_delete(m_asnum_db);
327 m_asnum_db = GeoIP_open(file, GEOIP_STANDARD);
328 return m_asnum_db;
331 bool session_impl::load_country_db(char const* file)
333 mutex_t::scoped_lock l(m_mutex);
334 if (m_country_db) GeoIP_delete(m_country_db);
335 m_country_db = GeoIP_open(file, GEOIP_STANDARD);
336 return m_country_db;
339 #endif
341 void session_impl::load_state(entry const& ses_state)
343 if (ses_state.type() != entry::dictionary_t) return;
344 mutex_t::scoped_lock l(m_mutex);
345 #ifndef TORRENT_DISABLE_GEO_IP
346 entry const* as_map = ses_state.find_key("AS map");
347 if (as_map && as_map->type() == entry::dictionary_t)
349 entry::dictionary_type const& as_peak = as_map->dict();
350 for (entry::dictionary_type::const_iterator i = as_peak.begin()
351 , end(as_peak.end()); i != end; ++i)
353 int as_num = atoi(i->first.c_str());
354 if (i->second.type() != entry::int_t || i->second.integer() == 0) continue;
355 int& peak = m_as_peak[as_num];
356 if (peak < i->second.integer()) peak = i->second.integer();
359 #endif
362 entry session_impl::state() const
364 mutex_t::scoped_lock l(m_mutex);
365 entry ret;
366 #ifndef TORRENT_DISABLE_GEO_IP
367 entry::dictionary_type& as_map = ret["AS map"].dict();
368 char buf[10];
369 for (std::map<int, int>::const_iterator i = m_as_peak.begin()
370 , end(m_as_peak.end()); i != end; ++i)
372 if (i->second == 0) continue;
373 sprintf(buf, "%05d", i->first);
374 as_map[buf] = i->second;
376 #endif
377 return ret;
380 #ifndef TORRENT_DISABLE_EXTENSIONS
381 void session_impl::add_extension(
382 boost::function<boost::shared_ptr<torrent_plugin>(torrent*, void*)> ext)
384 m_extensions.push_back(ext);
386 #endif
388 #ifndef TORRENT_DISABLE_DHT
389 void session_impl::add_dht_node(udp::endpoint n)
391 if (m_dht) m_dht->add_node(n);
393 #endif
395 void session_impl::pause()
397 mutex_t::scoped_lock l(m_mutex);
398 if (m_paused) return;
399 m_paused = true;
400 for (torrent_map::iterator i = m_torrents.begin()
401 , end(m_torrents.end()); i != end; ++i)
403 torrent& t = *i->second;
404 if (!t.is_torrent_paused()) t.do_pause();
408 void session_impl::resume()
410 mutex_t::scoped_lock l(m_mutex);
411 if (!m_paused) return;
412 m_paused = false;
413 for (torrent_map::iterator i = m_torrents.begin()
414 , end(m_torrents.end()); i != end; ++i)
416 torrent& t = *i->second;
417 t.do_resume();
421 void session_impl::abort()
423 mutex_t::scoped_lock l(m_mutex);
424 if (m_abort) return;
425 #if defined(TORRENT_LOGGING)
426 (*m_logger) << time_now_string() << " *** ABORT CALLED ***\n";
427 #endif
428 // abort the main thread
429 m_abort = true;
430 m_queued_for_checking.clear();
431 if (m_lsd) m_lsd->close();
432 if (m_upnp) m_upnp->close();
433 if (m_natpmp) m_natpmp->close();
434 #ifndef TORRENT_DISABLE_DHT
435 if (m_dht) m_dht->stop();
436 m_dht_socket.close();
437 #endif
438 error_code ec;
439 m_timer.cancel(ec);
441 // close the listen sockets
442 for (std::list<listen_socket_t>::iterator i = m_listen_sockets.begin()
443 , end(m_listen_sockets.end()); i != end; ++i)
445 i->sock->close(ec);
448 #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
449 (*m_logger) << time_now_string() << " aborting all torrents (" << m_torrents.size() << ")\n";
450 #endif
451 // abort all torrents
452 for (torrent_map::iterator i = m_torrents.begin()
453 , end(m_torrents.end()); i != end; ++i)
455 i->second->abort();
458 #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
459 (*m_logger) << time_now_string() << " aborting all tracker requests\n";
460 #endif
461 m_tracker_manager.abort_all_requests();
463 #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
464 (*m_logger) << time_now_string() << " sending event=stopped to trackers\n";
465 int counter = 0;
466 #endif
467 for (torrent_map::iterator i = m_torrents.begin();
468 i != m_torrents.end(); ++i)
470 torrent& t = *i->second;
471 t.abort();
474 #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
475 (*m_logger) << time_now_string() << " sent " << counter << " tracker stop requests\n";
476 #endif
478 #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
479 (*m_logger) << time_now_string() << " aborting all connections (" << m_connections.size() << ")\n";
480 #endif
481 // abort all connections
482 while (!m_connections.empty())
484 #ifndef NDEBUG
485 int conn = m_connections.size();
486 #endif
487 (*m_connections.begin())->disconnect("stopping torrent");
488 TORRENT_ASSERT(conn == int(m_connections.size()) + 1);
491 #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
492 (*m_logger) << time_now_string() << " shutting down connection queue\n";
493 #endif
494 m_half_open.close();
496 m_download_channel.close();
497 m_upload_channel.close();
500 void session_impl::set_port_filter(port_filter const& f)
502 mutex_t::scoped_lock l(m_mutex);
503 m_port_filter = f;
506 void session_impl::set_ip_filter(ip_filter const& f)
508 mutex_t::scoped_lock l(m_mutex);
510 INVARIANT_CHECK;
512 m_ip_filter = f;
514 // Close connections whose endpoint is filtered
515 // by the new ip-filter
516 for (torrent_map::iterator i = m_torrents.begin()
517 , end(m_torrents.end()); i != end; ++i)
518 i->second->ip_filter_updated();
521 void session_impl::set_settings(session_settings const& s)
523 mutex_t::scoped_lock l(m_mutex);
525 INVARIANT_CHECK;
527 TORRENT_ASSERT(s.file_pool_size > 0);
529 // less than 5 seconds unchoke interval is insane
530 TORRENT_ASSERT(s.unchoke_interval >= 5);
531 if (m_settings.cache_size != s.cache_size)
532 m_disk_thread.set_cache_size(s.cache_size);
533 if (m_settings.cache_expiry != s.cache_expiry)
534 m_disk_thread.set_cache_size(s.cache_expiry);
535 // if queuing settings were changed, recalculate
536 // queued torrents sooner
537 if ((m_settings.active_downloads != s.active_downloads
538 || m_settings.active_seeds != s.active_seeds
539 || m_settings.active_limit != s.active_limit)
540 && m_auto_manage_time_scaler > 2)
541 m_auto_manage_time_scaler = 2;
542 m_settings = s;
543 if (m_settings.connection_speed <= 0) m_settings.connection_speed = 200;
545 m_files.resize(m_settings.file_pool_size);
546 if (!s.auto_upload_slots) m_allowed_upload_slots = m_max_uploads;
547 // replace all occurances of '\n' with ' '.
548 std::string::iterator i = m_settings.user_agent.begin();
549 while ((i = std::find(i, m_settings.user_agent.end(), '\n'))
550 != m_settings.user_agent.end())
551 *i = ' ';
554 tcp::endpoint session_impl::get_ipv6_interface() const
556 return m_ipv6_interface;
559 session_impl::listen_socket_t session_impl::setup_listener(tcp::endpoint ep
560 , int retries, bool v6_only)
562 error_code ec;
563 listen_socket_t s;
564 s.sock.reset(new socket_acceptor(m_io_service));
565 s.sock->open(ep.protocol(), ec);
566 s.sock->set_option(socket_acceptor::reuse_address(true), ec);
567 if (ep.protocol() == tcp::v6()) s.sock->set_option(v6only(v6_only), ec);
568 s.sock->bind(ep, ec);
569 while (ec && retries > 0)
571 ec = error_code();
572 TORRENT_ASSERT(!ec);
573 --retries;
574 ep.port(ep.port() + 1);
575 s.sock->bind(ep, ec);
577 if (ec)
579 // instead of giving up, try
580 // let the OS pick a port
581 ep.port(0);
582 ec = error_code();
583 s.sock->bind(ep, ec);
585 if (ec)
587 // not even that worked, give up
588 if (m_alerts.should_post<listen_failed_alert>())
589 m_alerts.post_alert(listen_failed_alert(ep, ec));
590 #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
591 std::stringstream msg;
592 msg << "cannot bind to interface '";
593 print_endpoint(msg, ep) << "' " << ec.message();
594 (*m_logger) << msg.str() << "\n";
595 #endif
596 return listen_socket_t();
598 s.external_port = s.sock->local_endpoint(ec).port();
599 s.sock->listen(0, ec);
600 if (ec)
602 if (m_alerts.should_post<listen_failed_alert>())
603 m_alerts.post_alert(listen_failed_alert(ep, ec));
604 #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
605 std::stringstream msg;
606 msg << "cannot listen on interface '";
607 print_endpoint(msg, ep) << "' " << ec.message();
608 (*m_logger) << msg.str() << "\n";
609 #endif
610 return listen_socket_t();
613 if (m_alerts.should_post<listen_succeeded_alert>())
614 m_alerts.post_alert(listen_succeeded_alert(ep));
616 #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
617 (*m_logger) << "listening on: " << ep
618 << " external port: " << s.external_port << "\n";
619 #endif
620 return s;
623 void session_impl::open_listen_port()
625 // close the open listen sockets
626 m_listen_sockets.clear();
627 m_incoming_connection = false;
629 if (is_any(m_listen_interface.address()))
631 // this means we should open two listen sockets
632 // one for IPv4 and one for IPv6
634 listen_socket_t s = setup_listener(
635 tcp::endpoint(address_v4::any(), m_listen_interface.port())
636 , m_listen_port_retries);
638 if (s.sock)
640 m_listen_sockets.push_back(s);
641 async_accept(s.sock);
644 s = setup_listener(
645 tcp::endpoint(address_v6::any(), m_listen_interface.port())
646 , m_listen_port_retries, true);
648 if (s.sock)
650 m_listen_sockets.push_back(s);
651 async_accept(s.sock);
654 else
656 // we should only open a single listen socket, that
657 // binds to the given interface
659 listen_socket_t s = setup_listener(
660 m_listen_interface, m_listen_port_retries);
662 if (s.sock)
664 m_listen_sockets.push_back(s);
665 async_accept(s.sock);
669 m_ipv6_interface = tcp::endpoint();
671 for (std::list<listen_socket_t>::const_iterator i = m_listen_sockets.begin()
672 , end(m_listen_sockets.end()); i != end; ++i)
674 error_code ec;
675 tcp::endpoint ep = i->sock->local_endpoint(ec);
676 if (ec || ep.address().is_v4()) continue;
678 if (ep.address().to_v6() != address_v6::any())
680 // if we're listening on a specific address
681 // pick it
682 m_ipv6_interface = ep;
684 else
686 // if we're listening on any IPv6 address, enumerate them and
687 // pick the first non-local address
688 std::vector<ip_interface> const& ifs = enum_net_interfaces(m_io_service, ec);
689 for (std::vector<ip_interface>::const_iterator i = ifs.begin()
690 , end(ifs.end()); i != end; ++i)
692 if (i->interface_address.is_v4()
693 || i->interface_address.to_v6().is_link_local()
694 || i->interface_address.to_v6().is_loopback()) continue;
695 m_ipv6_interface = tcp::endpoint(i->interface_address, ep.port());
696 break;
698 break;
702 if (!m_listen_sockets.empty())
704 error_code ec;
705 tcp::endpoint local = m_listen_sockets.front().sock->local_endpoint(ec);
706 if (!ec)
708 if (m_natpmp.get())
710 if (m_tcp_mapping[0] != -1) m_natpmp->delete_mapping(m_tcp_mapping[0]);
711 m_tcp_mapping[0] = m_natpmp->add_mapping(natpmp::tcp
712 , local.port(), local.port());
714 if (m_upnp.get())
716 if (m_tcp_mapping[1] != -1) m_upnp->delete_mapping(m_tcp_mapping[1]);
717 m_tcp_mapping[1] = m_upnp->add_mapping(upnp::tcp
718 , local.port(), local.port());
724 #ifndef TORRENT_DISABLE_DHT
726 void session_impl::on_receive_udp(error_code const& e
727 , udp::endpoint const& ep, char const* buf, int len)
729 if (e)
731 if (e == asio::error::connection_refused
732 || e == asio::error::connection_reset
733 || e == asio::error::connection_aborted)
734 m_dht->on_unreachable(ep);
736 if (m_alerts.should_post<udp_error_alert>())
737 m_alerts.post_alert(udp_error_alert(ep, e));
738 return;
741 if (len > 20 && *buf == 'd' && m_dht)
743 // this is probably a dht message
744 m_dht->on_receive(ep, buf, len);
748 #endif
750 void session_impl::async_accept(boost::shared_ptr<socket_acceptor> const& listener)
752 shared_ptr<socket_type> c(new socket_type(m_io_service));
753 c->instantiate<stream_socket>(m_io_service);
754 listener->async_accept(c->get<stream_socket>()
755 , bind(&session_impl::on_incoming_connection, this, c
756 , boost::weak_ptr<socket_acceptor>(listener), _1));
759 void session_impl::on_incoming_connection(shared_ptr<socket_type> const& s
760 , weak_ptr<socket_acceptor> listen_socket, error_code const& e)
762 boost::shared_ptr<socket_acceptor> listener = listen_socket.lock();
763 if (!listener) return;
765 if (e == asio::error::operation_aborted) return;
767 mutex_t::scoped_lock l(m_mutex);
768 if (m_abort) return;
770 error_code ec;
771 if (e)
773 tcp::endpoint ep = listener->local_endpoint(ec);
774 #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
775 std::string msg = "error accepting connection on '"
776 + boost::lexical_cast<std::string>(ep) + "' " + e.message();
777 (*m_logger) << msg << "\n";
778 #endif
779 #ifdef TORRENT_WINDOWS
780 // Windows sometimes generates this error. It seems to be
781 // non-fatal and we have to do another async_accept.
782 if (e.value() == ERROR_SEM_TIMEOUT)
784 async_accept(listener);
785 return;
787 #endif
788 #ifdef TORRENT_BSD
789 // Leopard sometimes generates an "invalid argument" error. It seems to be
790 // non-fatal and we have to do another async_accept.
791 if (e.value() == EINVAL)
793 async_accept(listener);
794 return;
796 #endif
797 if (m_alerts.should_post<listen_failed_alert>())
798 m_alerts.post_alert(listen_failed_alert(ep, e));
799 return;
801 async_accept(listener);
803 // we got a connection request!
804 tcp::endpoint endp = s->remote_endpoint(ec);
806 if (ec)
808 #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
809 (*m_logger) << endp << " <== INCOMING CONNECTION FAILED, could "
810 "not retrieve remote endpoint " << ec.message() << "\n";
811 #endif
812 return;
815 #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
816 (*m_logger) << time_now_string() << " <== INCOMING CONNECTION " << endp << "\n";
817 #endif
819 // local addresses do not count, since it's likely
820 // coming from our own client through local service discovery
821 // and it does not reflect whether or not a router is open
822 // for incoming connections or not.
823 if (!is_local(endp.address()))
824 m_incoming_connection = true;
826 if (m_ip_filter.access(endp.address()) & ip_filter::blocked)
828 #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
829 (*m_logger) << "filtered blocked ip\n";
830 #endif
831 if (m_alerts.should_post<peer_blocked_alert>())
832 m_alerts.post_alert(peer_blocked_alert(endp.address()));
833 return;
836 // don't allow more connections than the max setting
837 if (num_connections() >= max_connections())
839 #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
840 (*m_logger) << "number of connections limit exceeded (conns: "
841 << num_connections() << ", limit: " << max_connections()
842 << "), connection rejected\n";
843 #endif
844 return;
847 // check if we have any active torrents
848 // if we don't reject the connection
849 if (m_torrents.empty())
851 #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
852 (*m_logger) << " There are no torrents, disconnect\n";
853 #endif
854 return;
857 bool has_active_torrent = false;
858 for (torrent_map::iterator i = m_torrents.begin()
859 , end(m_torrents.end()); i != end; ++i)
861 if (!i->second->is_paused())
863 has_active_torrent = true;
864 break;
867 if (!has_active_torrent)
869 #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
870 (*m_logger) << " There are no _active_ torrents, disconnect\n";
871 #endif
872 return;
875 boost::intrusive_ptr<peer_connection> c(
876 new bt_peer_connection(*this, s, endp, 0));
877 #ifndef NDEBUG
878 c->m_in_constructor = false;
879 #endif
881 if (!c->is_disconnecting())
883 m_connections.insert(c);
884 c->start();
887 void session_impl::close_connection(peer_connection const* p
888 , char const* message)
890 mutex_t::scoped_lock l(m_mutex);
892 // too expensive
893 // INVARIANT_CHECK;
895 #ifndef NDEBUG
896 // for (aux::session_impl::torrent_map::const_iterator i = m_torrents.begin()
897 // , end(m_torrents.end()); i != end; ++i)
898 // TORRENT_ASSERT(!i->second->has_peer((peer_connection*)p));
899 #endif
901 #if defined(TORRENT_LOGGING)
902 (*m_logger) << time_now_string() << " CLOSING CONNECTION "
903 << p->remote() << " : " << message << "\n";
904 #endif
906 TORRENT_ASSERT(p->is_disconnecting());
908 if (!p->is_choked()) --m_num_unchoked;
909 // connection_map::iterator i = std::lower_bound(m_connections.begin(), m_connections.end()
910 // , p, bind(&boost::intrusive_ptr<peer_connection>::get, _1) < p);
911 // if (i->get() != p) i == m_connections.end();
912 connection_map::iterator i = std::find_if(m_connections.begin(), m_connections.end()
913 , bind(&boost::intrusive_ptr<peer_connection>::get, _1) == p);
914 if (i != m_connections.end()) m_connections.erase(i);
917 void session_impl::set_peer_id(peer_id const& id)
919 mutex_t::scoped_lock l(m_mutex);
920 m_peer_id = id;
923 void session_impl::set_key(int key)
925 mutex_t::scoped_lock l(m_mutex);
926 m_key = key;
929 int session_impl::next_port()
931 std::pair<int, int> const& out_ports = m_settings.outgoing_ports;
932 if (m_next_port < out_ports.first || m_next_port > out_ports.second)
933 m_next_port = out_ports.first;
935 int port = m_next_port;
936 ++m_next_port;
937 if (m_next_port > out_ports.second) m_next_port = out_ports.first;
938 #if defined TORRENT_LOGGING
939 (*m_logger) << time_now_string() << " *** BINDING OUTGOING CONNECTION [ "
940 "port: " << port << " ]\n";
941 #endif
942 return port;
945 void session_impl::second_tick(error_code const& e)
947 session_impl::mutex_t::scoped_lock l(m_mutex);
949 // too expensive
950 // INVARIANT_CHECK;
952 if (m_abort) return;
954 if (e)
956 #if defined TORRENT_LOGGING
957 (*m_logger) << "*** SECOND TIMER FAILED " << e.message() << "\n";
958 #endif
959 ::abort();
960 return;
963 float tick_interval = total_microseconds(time_now() - m_last_tick) / 1000000.f;
964 m_last_tick = time_now();
966 error_code ec;
967 m_timer.expires_from_now(seconds(1), ec);
968 m_timer.async_wait(
969 bind(&session_impl::second_tick, this, _1));
971 #ifdef TORRENT_STATS
972 ++m_second_counter;
973 int downloading_torrents = 0;
974 int seeding_torrents = 0;
975 for (torrent_map::iterator i = m_torrents.begin()
976 , end(m_torrents.end()); i != end; ++i)
978 if (i->second->is_seed())
979 ++seeding_torrents;
980 else
981 ++downloading_torrents;
983 int num_complete_connections = 0;
984 int num_half_open = 0;
985 for (connection_map::iterator i = m_connections.begin()
986 , end(m_connections.end()); i != end; ++i)
988 if ((*i)->is_connecting())
989 ++num_half_open;
990 else
991 ++num_complete_connections;
994 m_stats_logger
995 << m_second_counter << "\t"
996 << m_stat.upload_rate() << "\t"
997 << m_stat.download_rate() << "\t"
998 << downloading_torrents << "\t"
999 << seeding_torrents << "\t"
1000 << num_complete_connections << "\t"
1001 << num_half_open << "\t"
1002 << m_disk_thread.disk_allocations() << "\t"
1003 << std::endl;
1004 #endif
1006 // --------------------------------------------------------------
1007 // check for incoming connections that might have timed out
1008 // --------------------------------------------------------------
1010 for (connection_map::iterator i = m_connections.begin();
1011 i != m_connections.end();)
1013 peer_connection* p = (*i).get();
1014 ++i;
1015 // ignore connections that already have a torrent, since they
1016 // are ticket through the torrents' second_ticket
1017 if (!p->associated_torrent().expired()) continue;
1018 if (m_last_tick - p->connected_time() > seconds(m_settings.handshake_timeout))
1019 p->disconnect("timeout: incoming connection");
1022 // --------------------------------------------------------------
1023 // second_tick every torrent
1024 // --------------------------------------------------------------
1026 int congested_torrents = 0;
1027 int uncongested_torrents = 0;
1029 // count the number of seeding torrents vs. downloading
1030 // torrents we are running
1031 int num_seeds = 0;
1032 int num_downloads = 0;
1034 // count the number of peers of downloading torrents
1035 int num_downloads_peers = 0;
1037 torrent_map::iterator least_recently_scraped = m_torrents.begin();
1038 int num_paused_auto_managed = 0;
1040 // check each torrent for tracker updates
1041 // TODO: do this in a timer-event in each torrent instead
1042 for (torrent_map::iterator i = m_torrents.begin();
1043 i != m_torrents.end();)
1045 torrent& t = *i->second;
1046 TORRENT_ASSERT(!t.is_aborted());
1047 if (t.bandwidth_queue_size(peer_connection::upload_channel))
1048 ++congested_torrents;
1049 else
1050 ++uncongested_torrents;
1052 if (t.is_auto_managed() && t.is_paused() && !t.has_error())
1054 ++num_paused_auto_managed;
1055 if (!least_recently_scraped->second->is_auto_managed()
1056 || !least_recently_scraped->second->is_paused()
1057 || least_recently_scraped->second->last_scrape() > t.last_scrape())
1059 least_recently_scraped = i;
1063 if (t.is_finished())
1065 ++num_seeds;
1067 else
1069 ++num_downloads;
1070 num_downloads_peers += t.num_peers();
1073 t.second_tick(m_stat, tick_interval);
1074 ++i;
1077 // drain the IP overhead from the bandwidth limiters
1078 m_download_channel.drain(m_stat.download_ip_overhead());
1079 m_upload_channel.drain(m_stat.upload_ip_overhead());
1081 m_stat.second_tick(tick_interval);
1083 // --------------------------------------------------------------
1084 // scrape paused torrents that are auto managed
1085 // --------------------------------------------------------------
1086 --m_auto_scrape_time_scaler;
1087 if (m_auto_scrape_time_scaler <= 0)
1089 m_auto_scrape_time_scaler = m_settings.auto_scrape_interval
1090 / (std::max)(1, num_paused_auto_managed);
1091 if (m_auto_scrape_time_scaler < m_settings.auto_scrape_min_interval)
1092 m_auto_scrape_time_scaler = m_settings.auto_scrape_min_interval;
1094 if (least_recently_scraped != m_torrents.end())
1096 least_recently_scraped->second->scrape_tracker();
1100 // --------------------------------------------------------------
1101 // connect new peers
1102 // --------------------------------------------------------------
1104 // let torrents connect to peers if they want to
1105 // if there are any torrents and any free slots
1107 // this loop will "hand out" max(connection_speed
1108 // , half_open.free_slots()) to the torrents, in a
1109 // round robin fashion, so that every torrent is
1110 // equallt likely to connect to a peer
1112 int free_slots = m_half_open.free_slots();
1113 if (!m_torrents.empty()
1114 && free_slots > -m_half_open.limit()
1115 && num_connections() < m_max_connections)
1117 // this is the maximum number of connections we will
1118 // attempt this tick
1119 int max_connections = m_settings.connection_speed;
1120 int average_peers = 0;
1121 if (num_downloads > 0)
1122 average_peers = num_downloads_peers / num_downloads;
1124 torrent_map::iterator i = m_torrents.begin();
1125 if (m_next_connect_torrent < int(m_torrents.size()))
1126 std::advance(i, m_next_connect_torrent);
1127 else
1128 m_next_connect_torrent = 0;
1129 int steps_since_last_connect = 0;
1130 int num_torrents = int(m_torrents.size());
1131 for (;;)
1133 torrent& t = *i->second;
1134 if (t.want_more_peers())
1136 int connect_points = 100;
1137 // have a bias against torrents with more peers
1138 // than average
1139 if (!t.is_seed() && t.num_peers() > average_peers)
1140 connect_points /= 2;
1141 // if this is a seed and there is a torrent that
1142 // is downloading, lower the rate at which this
1143 // torrent gets connections.
1144 // dividing by num_seeds will have the effect
1145 // that all seed will get as many connections
1146 // together, as a single downloading torrent.
1147 if (t.is_seed() && num_downloads > 0)
1148 connect_points /= num_seeds + 1;
1149 if (connect_points <= 0) connect_points = 1;
1150 t.give_connect_points(connect_points);
1153 if (t.try_connect_peer())
1155 --max_connections;
1156 --free_slots;
1157 steps_since_last_connect = 0;
1160 catch (std::bad_alloc&)
1162 // we ran out of memory trying to connect to a peer
1163 // lower the global limit to the number of peers
1164 // we already have
1165 m_max_connections = num_connections();
1166 if (m_max_connections < 2) m_max_connections = 2;
1169 ++m_next_connect_torrent;
1170 ++steps_since_last_connect;
1171 ++i;
1172 if (i == m_torrents.end())
1174 TORRENT_ASSERT(m_next_connect_torrent == num_torrents);
1175 i = m_torrents.begin();
1176 m_next_connect_torrent = 0;
1178 // if we have gone two whole loops without
1179 // handing out a single connection, break
1180 if (steps_since_last_connect > num_torrents * 2) break;
1181 // if there are no more free connection slots, abort
1182 if (free_slots <= -m_half_open.limit()) break;
1183 // if we should not make any more connections
1184 // attempts this tick, abort
1185 if (max_connections == 0) break;
1186 // maintain the global limit on number of connections
1187 if (num_connections() >= m_max_connections) break;
1191 // --------------------------------------------------------------
1192 // auto managed torrent
1193 // --------------------------------------------------------------
1194 m_auto_manage_time_scaler--;
1195 if (m_auto_manage_time_scaler <= 0)
1197 m_auto_manage_time_scaler = settings().auto_manage_interval;
1198 recalculate_auto_managed_torrents();
1201 // --------------------------------------------------------------
1202 // unchoke set and optimistic unchoke calculations
1203 // --------------------------------------------------------------
1204 m_unchoke_time_scaler--;
1205 if (m_unchoke_time_scaler <= 0 && !m_connections.empty())
1207 m_unchoke_time_scaler = settings().unchoke_interval;
1208 recalculate_unchoke_slots(congested_torrents
1209 , uncongested_torrents);
1212 // --------------------------------------------------------------
1213 // disconnect peers when we have too many
1214 // --------------------------------------------------------------
1215 --m_disconnect_time_scaler;
1216 if (m_disconnect_time_scaler <= 0)
1218 m_disconnect_time_scaler = 90;
1220 // every 90 seconds, disconnect the worst peers
1221 // if we have reached the connection limit
1222 if (num_connections() >= max_connections() * m_settings.peer_turnover_cutoff
1223 && !m_torrents.empty())
1225 torrent_map::iterator i = std::max_element(m_torrents.begin(), m_torrents.end()
1226 , bind(&torrent::num_peers, bind(&torrent_map::value_type::second, _1))
1227 < bind(&torrent::num_peers, bind(&torrent_map::value_type::second, _2)));
1229 TORRENT_ASSERT(i != m_torrents.end());
1230 int peers_to_disconnect = (std::min)((std::max)(int(i->second->num_peers()
1231 * m_settings.peer_turnover), 1)
1232 , i->second->get_policy().num_connect_candidates());
1233 i->second->disconnect_peers(peers_to_disconnect);
1235 else
1237 // if we haven't reached the global max. see if any torrent
1238 // has reached its local limit
1239 for (torrent_map::iterator i = m_torrents.begin()
1240 , end(m_torrents.end()); i != end; ++i)
1242 boost::shared_ptr<torrent> t = i->second;
1243 if (t->num_peers() < t->max_connections() * m_settings.peer_turnover_cutoff)
1244 continue;
1246 int peers_to_disconnect = (std::min)((std::max)(int(i->second->num_peers()
1247 * m_settings.peer_turnover), 1)
1248 , i->second->get_policy().num_connect_candidates());
1249 t->disconnect_peers(peers_to_disconnect);
1255 namespace
1257 bool is_active(torrent* t, session_settings const& s)
1259 return !(s.dont_count_slow_torrents
1260 && t->statistics().upload_payload_rate() == 0.f
1261 && t->statistics().download_payload_rate() == 0.f);
1265 void session_impl::recalculate_auto_managed_torrents()
1267 // these vectors are filled with auto managed torrents
1268 std::vector<torrent*> downloaders;
1269 downloaders.reserve(m_torrents.size());
1270 std::vector<torrent*> seeds;
1271 seeds.reserve(m_torrents.size());
1273 // these counters are set to the number of torrents
1274 // of each kind we're allowed to have active
1275 int num_downloaders = settings().active_downloads;
1276 int num_seeds = settings().active_seeds;
1277 int hard_limit = settings().active_limit;
1279 if (num_downloaders == -1)
1280 num_downloaders = (std::numeric_limits<int>::max)();
1281 if (num_seeds == -1)
1282 num_seeds = (std::numeric_limits<int>::max)();
1283 if (hard_limit == -1)
1284 hard_limit = (std::numeric_limits<int>::max)();
1286 for (torrent_map::iterator i = m_torrents.begin()
1287 , end(m_torrents.end()); i != end; ++i)
1289 torrent* t = i->second.get();
1290 TORRENT_ASSERT(t);
1291 if (t->is_auto_managed() && !t->has_error())
1293 // this torrent is auto managed, add it to
1294 // the list (depending on if it's a seed or not)
1295 if (t->is_finished())
1296 seeds.push_back(t);
1297 else
1298 downloaders.push_back(t);
1300 else if (!t->is_paused())
1302 --hard_limit;
1303 if (is_active(t, settings()))
1305 // this is not an auto managed torrent,
1306 // if it's running and active, decrease the
1307 // counters.
1308 --num_downloaders;
1309 --num_seeds;
1314 bool handled_by_extension = false;
1316 #ifndef TORRENT_DISABLE_EXTENSIONS
1317 // TODO: allow extensions to sort torrents for queuing
1318 #endif
1320 if (!handled_by_extension)
1322 std::sort(downloaders.begin(), downloaders.end()
1323 , bind(&torrent::sequence_number, _1) < bind(&torrent::sequence_number, _2));
1325 std::sort(seeds.begin(), seeds.end()
1326 , bind(&torrent::seed_rank, _1, boost::ref(m_settings))
1327 > bind(&torrent::seed_rank, _2, boost::ref(m_settings)));
1330 for (std::vector<torrent*>::iterator i = downloaders.begin()
1331 , end(downloaders.end()); i != end; ++i)
1333 torrent* t = *i;
1334 if (!t->is_paused() && !is_active(t, settings()) && hard_limit > 0)
1336 --hard_limit;
1337 continue;
1340 if (num_downloaders > 0 && hard_limit > 0)
1342 --hard_limit;
1343 if (t->state() != torrent_status::queued_for_checking
1344 && t->state() != torrent_status::checking_files)
1346 --num_downloaders;
1347 if (t->is_paused()) t->resume();
1350 else
1352 if (!t->is_paused()) t->pause();
1356 for (std::vector<torrent*>::iterator i = seeds.begin()
1357 , end(seeds.end()); i != end; ++i)
1359 torrent* t = *i;
1360 if (!t->is_paused() && !is_active(t, settings()) && hard_limit > 0)
1362 --hard_limit;
1363 continue;
1366 if (num_seeds > 0 && hard_limit > 0)
1368 --hard_limit;
1369 --num_seeds;
1370 if (t->is_paused()) t->resume();
1372 else
1374 if (!t->is_paused()) t->pause();
1379 void session_impl::recalculate_unchoke_slots(int congested_torrents
1380 , int uncongested_torrents)
1382 std::vector<peer_connection*> peers;
1383 for (connection_map::iterator i = m_connections.begin()
1384 , end(m_connections.end()); i != end; ++i)
1386 peer_connection* p = i->get();
1387 torrent* t = p->associated_torrent().lock().get();
1388 if (!p->peer_info_struct()
1389 || t == 0
1390 || !p->is_peer_interested()
1391 || p->is_disconnecting()
1392 || p->is_connecting()
1393 || (p->share_diff() < -free_upload_amount
1394 && !t->is_seed()))
1396 if (!(*i)->is_choked() && t)
1398 policy::peer* pi = p->peer_info_struct();
1399 if (pi && pi->optimistically_unchoked)
1401 pi->optimistically_unchoked = false;
1402 // force a new optimistic unchoke
1403 m_optimistic_unchoke_time_scaler = 0;
1405 t->choke_peer(*(*i));
1407 continue;
1409 peers.push_back(i->get());
1412 // sorts the peers that are eligible for unchoke by download rate and secondary
1413 // by total upload. The reason for this is, if all torrents are being seeded,
1414 // the download rate will be 0, and the peers we have sent the least to should
1415 // be unchoked
1416 std::sort(peers.begin(), peers.end()
1417 , bind(&peer_connection::unchoke_compare, _1, _2));
1419 std::for_each(m_connections.begin(), m_connections.end()
1420 , bind(&peer_connection::reset_choke_counters, _1));
1422 // auto unchoke
1423 int upload_limit = m_bandwidth_manager[peer_connection::upload_channel]->throttle();
1424 if (m_settings.auto_upload_slots && upload_limit != bandwidth_limit::inf)
1426 // if our current upload rate is less than 90% of our
1427 // limit AND most torrents are not "congested", i.e.
1428 // they are not holding back because of a per-torrent
1429 // limit
1430 if (m_stat.upload_rate() < upload_limit * 0.9f
1431 && m_allowed_upload_slots <= m_num_unchoked + 1
1432 && congested_torrents < uncongested_torrents)
1434 ++m_allowed_upload_slots;
1436 else if (m_upload_channel.queue_size() > 1
1437 && m_allowed_upload_slots > m_max_uploads)
1439 --m_allowed_upload_slots;
1443 // reserve one upload slot for optimistic unchokes
1444 int unchoke_set_size = m_allowed_upload_slots - 1;
1446 m_num_unchoked = 0;
1447 // go through all the peers and unchoke the first ones and choke
1448 // all the other ones.
1449 for (std::vector<peer_connection*>::iterator i = peers.begin()
1450 , end(peers.end()); i != end; ++i)
1452 peer_connection* p = *i;
1453 TORRENT_ASSERT(p);
1454 torrent* t = p->associated_torrent().lock().get();
1455 TORRENT_ASSERT(t);
1456 if (unchoke_set_size > 0)
1458 if (p->is_choked())
1460 if (!t->unchoke_peer(*p))
1461 continue;
1464 --unchoke_set_size;
1465 ++m_num_unchoked;
1467 TORRENT_ASSERT(p->peer_info_struct());
1468 if (p->peer_info_struct()->optimistically_unchoked)
1470 // force a new optimistic unchoke
1471 m_optimistic_unchoke_time_scaler = 0;
1472 p->peer_info_struct()->optimistically_unchoked = false;
1475 else
1477 TORRENT_ASSERT(p->peer_info_struct());
1478 if (!p->is_choked() && !p->peer_info_struct()->optimistically_unchoked)
1479 t->choke_peer(*p);
1480 if (!p->is_choked())
1481 ++m_num_unchoked;
1485 m_optimistic_unchoke_time_scaler--;
1486 if (m_optimistic_unchoke_time_scaler <= 0)
1488 m_optimistic_unchoke_time_scaler
1489 = settings().optimistic_unchoke_multiplier;
1491 // find the peer that has been waiting the longest to be optimistically
1492 // unchoked
1493 connection_map::iterator current_optimistic_unchoke = m_connections.end();
1494 connection_map::iterator optimistic_unchoke_candidate = m_connections.end();
1495 ptime last_unchoke = max_time();
1497 for (connection_map::iterator i = m_connections.begin()
1498 , end(m_connections.end()); i != end; ++i)
1500 peer_connection* p = i->get();
1501 TORRENT_ASSERT(p);
1502 policy::peer* pi = p->peer_info_struct();
1503 if (!pi) continue;
1504 torrent* t = p->associated_torrent().lock().get();
1505 if (!t) continue;
1507 if (pi->optimistically_unchoked)
1509 TORRENT_ASSERT(!p->is_choked());
1510 TORRENT_ASSERT(current_optimistic_unchoke == m_connections.end());
1511 current_optimistic_unchoke = i;
1514 if (pi->last_optimistically_unchoked < last_unchoke
1515 && !p->is_connecting()
1516 && !p->is_disconnecting()
1517 && p->is_peer_interested()
1518 && t->free_upload_slots()
1519 && p->is_choked())
1521 last_unchoke = pi->last_optimistically_unchoked;
1522 optimistic_unchoke_candidate = i;
1526 if (optimistic_unchoke_candidate != m_connections.end()
1527 && optimistic_unchoke_candidate != current_optimistic_unchoke)
1529 if (current_optimistic_unchoke != m_connections.end())
1531 torrent* t = (*current_optimistic_unchoke)->associated_torrent().lock().get();
1532 TORRENT_ASSERT(t);
1533 (*current_optimistic_unchoke)->peer_info_struct()->optimistically_unchoked = false;
1534 t->choke_peer(*current_optimistic_unchoke->get());
1536 else
1538 ++m_num_unchoked;
1541 torrent* t = (*optimistic_unchoke_candidate)->associated_torrent().lock().get();
1542 TORRENT_ASSERT(t);
1543 bool ret = t->unchoke_peer(*optimistic_unchoke_candidate->get());
1544 TORRENT_ASSERT(ret);
1545 (*optimistic_unchoke_candidate)->peer_info_struct()->optimistically_unchoked = true;
1550 void session_impl::operator()()
1552 eh_initializer();
1555 session_impl::mutex_t::scoped_lock l(m_mutex);
1556 if (m_listen_interface.port() != 0) open_listen_port();
1559 ptime timer = time_now();
1563 #ifndef BOOST_NO_EXCEPTIONS
1566 #endif
1567 m_io_service.run();
1568 TORRENT_ASSERT(m_abort == true);
1569 #ifndef BOOST_NO_EXCEPTIONS
1571 catch (std::exception& e)
1573 #ifndef NDEBUG
1574 std::cerr << e.what() << "\n";
1575 std::string err = e.what();
1576 #endif
1577 TORRENT_ASSERT(false);
1579 #endif
1581 while (!m_abort);
1583 #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
1584 (*m_logger) << time_now_string() << " locking mutex\n";
1585 #endif
1587 session_impl::mutex_t::scoped_lock l(m_mutex);
1589 #ifndef NDEBUG
1590 for (torrent_map::iterator i = m_torrents.begin();
1591 i != m_torrents.end(); ++i)
1593 TORRENT_ASSERT(i->second->num_peers() == 0);
1595 #endif
1597 #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
1598 (*m_logger) << time_now_string() << " cleaning up torrents\n";
1599 #endif
1600 m_torrents.clear();
1602 TORRENT_ASSERT(m_torrents.empty());
1603 TORRENT_ASSERT(m_connections.empty());
1607 // the return value from this function is valid only as long as the
1608 // session is locked!
1609 boost::weak_ptr<torrent> session_impl::find_torrent(sha1_hash const& info_hash)
1611 std::map<sha1_hash, boost::shared_ptr<torrent> >::iterator i
1612 = m_torrents.find(info_hash);
1613 #ifndef NDEBUG
1614 for (std::map<sha1_hash, boost::shared_ptr<torrent> >::iterator j
1615 = m_torrents.begin(); j != m_torrents.end(); ++j)
1617 torrent* p = boost::get_pointer(j->second);
1618 TORRENT_ASSERT(p);
1620 #endif
1621 if (i != m_torrents.end()) return i->second;
1622 return boost::weak_ptr<torrent>();
1625 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
1626 boost::shared_ptr<logger> session_impl::create_log(std::string const& name
1627 , int instance, bool append)
1629 // current options are file_logger, cout_logger and null_logger
1630 return boost::shared_ptr<logger>(new logger(m_logpath, name + ".log", instance, append));
1632 #endif
1634 std::vector<torrent_handle> session_impl::get_torrents()
1636 mutex_t::scoped_lock l(m_mutex);
1637 std::vector<torrent_handle> ret;
1639 for (session_impl::torrent_map::iterator i
1640 = m_torrents.begin(), end(m_torrents.end());
1641 i != end; ++i)
1643 if (i->second->is_aborted()) continue;
1644 ret.push_back(torrent_handle(i->second));
1646 return ret;
1649 torrent_handle session_impl::find_torrent_handle(sha1_hash const& info_hash)
1651 return torrent_handle(find_torrent(info_hash));
1654 torrent_handle session_impl::add_torrent(add_torrent_params const& params)
1656 TORRENT_ASSERT(!params.save_path.empty());
1658 if (params.ti && params.ti->files().num_files() == 0)
1660 #ifndef BOOST_NO_EXCEPTIONS
1661 throw std::runtime_error("no files in torrent");
1662 #else
1663 return torrent_handle();
1664 #endif
1667 // lock the session and the checker thread (the order is important!)
1668 mutex_t::scoped_lock l(m_mutex);
1670 // INVARIANT_CHECK;
1672 if (is_aborted())
1674 #ifndef BOOST_NO_EXCEPTIONS
1675 throw std::runtime_error("session is closing");
1676 #else
1677 return torrent_handle();
1678 #endif
1681 // figure out the info hash of the torrent
1682 sha1_hash const* ih = 0;
1683 if (params.ti) ih = &params.ti->info_hash();
1684 else ih = &params.info_hash;
1686 // is the torrent already active?
1687 boost::shared_ptr<torrent> torrent_ptr = find_torrent(*ih).lock();
1688 if (torrent_ptr)
1690 if (!params.duplicate_is_error)
1691 return torrent_handle(torrent_ptr);
1693 #ifndef BOOST_NO_EXCEPTIONS
1694 throw duplicate_torrent();
1695 #else
1696 return torrent_handle();
1697 #endif
1700 int queue_pos = 0;
1701 for (torrent_map::const_iterator i = m_torrents.begin()
1702 , end(m_torrents.end()); i != end; ++i)
1704 int pos = i->second->queue_position();
1705 if (pos >= queue_pos) queue_pos = pos + 1;
1708 // create the torrent and the data associated with
1709 // the checker thread and store it before starting
1710 // the thread
1711 if (params.ti)
1713 torrent_ptr.reset(new torrent(*this, params.ti, params.save_path
1714 , m_listen_interface, params.storage_mode, 16 * 1024
1715 , params.storage, params.paused, params.resume_data
1716 , queue_pos, params.auto_managed));
1718 else
1720 torrent_ptr.reset(new torrent(*this, params.tracker_url, *ih, params.name
1721 , params.save_path, m_listen_interface, params.storage_mode, 16 * 1024
1722 , params.storage, params.paused, params.resume_data
1723 , queue_pos, params.auto_managed));
1725 torrent_ptr->start();
1727 #ifndef TORRENT_DISABLE_EXTENSIONS
1728 for (extension_list_t::iterator i = m_extensions.begin()
1729 , end(m_extensions.end()); i != end; ++i)
1731 boost::shared_ptr<torrent_plugin> tp((*i)(torrent_ptr.get(), params.userdata));
1732 if (tp) torrent_ptr->add_extension(tp);
1734 #endif
1736 #ifndef TORRENT_DISABLE_DHT
1737 if (m_dht && params.ti)
1739 torrent_info::nodes_t const& nodes = params.ti->nodes();
1740 std::for_each(nodes.begin(), nodes.end(), bind(
1741 (void(dht::dht_tracker::*)(std::pair<std::string, int> const&))
1742 &dht::dht_tracker::add_node
1743 , boost::ref(m_dht), _1));
1745 #endif
1747 m_torrents.insert(std::make_pair(*ih, torrent_ptr));
1749 // if this is an auto managed torrent, force a recalculation
1750 // of which torrents to have active
1751 if (params.auto_managed && m_auto_manage_time_scaler > 2)
1752 m_auto_manage_time_scaler = 2;
1754 return torrent_handle(torrent_ptr);
1757 void session_impl::check_torrent(boost::shared_ptr<torrent> const& t)
1759 if (m_abort) return;
1760 if (m_queued_for_checking.empty()) t->start_checking();
1761 m_queued_for_checking.push_back(t);
1764 void session_impl::done_checking(boost::shared_ptr<torrent> const& t)
1766 if (m_queued_for_checking.empty()) return;
1767 check_queue_t::iterator next_check = m_queued_for_checking.begin();
1768 check_queue_t::iterator done = m_queued_for_checking.end();
1769 for (check_queue_t::iterator i = m_queued_for_checking.begin()
1770 , end(m_queued_for_checking.end()); i != end; ++i)
1772 if (*i == t) done = i;
1773 if (next_check == done || (*next_check)->queue_position() > (*i)->queue_position())
1774 next_check = i;
1776 if (next_check != done) (*next_check)->start_checking();
1777 m_queued_for_checking.erase(done);
1780 void session_impl::remove_torrent(const torrent_handle& h, int options)
1782 boost::shared_ptr<torrent> tptr = h.m_torrent.lock();
1783 if (!tptr)
1784 #ifdef BOOST_NO_EXCEPTIONS
1785 return;
1786 #else
1787 throw invalid_handle();
1788 #endif
1790 mutex_t::scoped_lock l(m_mutex);
1792 INVARIANT_CHECK;
1794 session_impl::torrent_map::iterator i =
1795 m_torrents.find(tptr->torrent_file().info_hash());
1797 if (i != m_torrents.end())
1799 torrent& t = *i->second;
1800 if (options & session::delete_files)
1801 t.delete_files();
1802 t.abort();
1804 #ifndef NDEBUG
1805 sha1_hash i_hash = t.torrent_file().info_hash();
1806 #endif
1807 i->second->set_queue_position(-1);
1808 m_torrents.erase(i);
1809 TORRENT_ASSERT(m_torrents.find(i_hash) == m_torrents.end());
1810 return;
1814 bool session_impl::listen_on(
1815 std::pair<int, int> const& port_range
1816 , const char* net_interface)
1818 session_impl::mutex_t::scoped_lock l(m_mutex);
1820 INVARIANT_CHECK;
1822 tcp::endpoint new_interface;
1823 if (net_interface && std::strlen(net_interface) > 0)
1824 new_interface = tcp::endpoint(address::from_string(net_interface), port_range.first);
1825 else
1826 new_interface = tcp::endpoint(address_v4::any(), port_range.first);
1828 m_listen_port_retries = port_range.second - port_range.first;
1830 // if the interface is the same and the socket is open
1831 // don't do anything
1832 if (new_interface == m_listen_interface
1833 && !m_listen_sockets.empty()) return true;
1835 m_listen_interface = new_interface;
1837 open_listen_port();
1839 bool new_listen_address = m_listen_interface.address() != new_interface.address();
1841 #ifndef TORRENT_DISABLE_DHT
1842 if ((new_listen_address || m_dht_same_port) && m_dht)
1844 if (m_dht_same_port)
1845 m_dht_settings.service_port = new_interface.port();
1846 // the listen interface changed, rebind the dht listen socket as well
1847 m_dht_socket.bind(m_dht_settings.service_port);
1848 if (m_natpmp.get())
1850 if (m_udp_mapping[0] != -1) m_natpmp->delete_mapping(m_udp_mapping[0]);
1851 m_udp_mapping[0] = m_natpmp->add_mapping(natpmp::tcp
1852 , m_dht_settings.service_port
1853 , m_dht_settings.service_port);
1855 if (m_upnp.get())
1857 if (m_udp_mapping[1] != -1) m_upnp->delete_mapping(m_udp_mapping[1]);
1858 m_udp_mapping[1] = m_upnp->add_mapping(upnp::tcp
1859 , m_dht_settings.service_port
1860 , m_dht_settings.service_port);
1863 #endif
1865 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
1866 m_logger = create_log("main_session", listen_port(), false);
1867 (*m_logger) << time_now_string() << "\n";
1868 #endif
1870 return !m_listen_sockets.empty();
1873 unsigned short session_impl::listen_port() const
1875 mutex_t::scoped_lock l(m_mutex);
1876 if (m_listen_sockets.empty()) return 0;
1877 return m_listen_sockets.front().external_port;;
1880 void session_impl::announce_lsd(sha1_hash const& ih)
1882 mutex_t::scoped_lock l(m_mutex);
1883 // use internal listen port for local peers
1884 if (m_lsd.get())
1885 m_lsd->announce(ih, m_listen_interface.port());
1888 void session_impl::on_lsd_peer(tcp::endpoint peer, sha1_hash const& ih)
1890 mutex_t::scoped_lock l(m_mutex);
1892 INVARIANT_CHECK;
1894 boost::shared_ptr<torrent> t = find_torrent(ih).lock();
1895 if (!t) return;
1896 // don't add peers from lsd to private torrents
1897 if (t->torrent_file().priv()) return;
1899 #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
1900 (*m_logger) << time_now_string()
1901 << ": added peer from local discovery: " << peer << "\n";
1902 #endif
1903 t->get_policy().peer_from_tracker(peer, peer_id(0), peer_info::lsd, 0);
1906 void session_impl::on_port_mapping(int mapping, int port
1907 , std::string const& errmsg, int map_transport)
1909 #ifndef TORRENT_DISABLE_DHT
1910 if (mapping == m_udp_mapping[map_transport] && port != 0)
1912 m_external_udp_port = port;
1913 m_dht_settings.service_port = port;
1914 if (m_alerts.should_post<portmap_alert>())
1915 m_alerts.post_alert(portmap_alert(mapping, port
1916 , map_transport));
1917 return;
1919 #endif
1921 if (mapping == m_tcp_mapping[map_transport] && port != 0)
1923 if (!m_listen_sockets.empty())
1924 m_listen_sockets.front().external_port = port;
1925 if (m_alerts.should_post<portmap_alert>())
1926 m_alerts.post_alert(portmap_alert(mapping, port
1927 , map_transport));
1928 return;
1931 if (!errmsg.empty())
1933 if (m_alerts.should_post<portmap_error_alert>())
1934 m_alerts.post_alert(portmap_error_alert(mapping
1935 , map_transport, errmsg));
1937 else
1939 if (m_alerts.should_post<portmap_alert>())
1940 m_alerts.post_alert(portmap_alert(mapping, port
1941 , map_transport));
1945 session_status session_impl::status() const
1947 mutex_t::scoped_lock l(m_mutex);
1949 // INVARIANT_CHECK;
1951 session_status s;
1953 s.num_peers = (int)m_connections.size();
1954 s.num_unchoked = m_num_unchoked;
1955 s.allowed_upload_slots = m_allowed_upload_slots;
1957 s.total_redundant_bytes = m_total_redundant_bytes;
1958 s.total_failed_bytes = m_total_failed_bytes;
1960 s.up_bandwidth_queue = m_upload_channel.queue_size();
1961 s.down_bandwidth_queue = m_download_channel.queue_size();
1963 s.has_incoming_connections = m_incoming_connection;
1965 s.download_rate = m_stat.download_rate();
1966 s.upload_rate = m_stat.upload_rate();
1968 s.payload_download_rate = m_stat.download_payload_rate();
1969 s.payload_upload_rate = m_stat.upload_payload_rate();
1971 s.total_download = m_stat.total_protocol_download()
1972 + m_stat.total_payload_download();
1974 s.total_upload = m_stat.total_protocol_upload()
1975 + m_stat.total_payload_upload();
1977 s.total_payload_download = m_stat.total_payload_download();
1978 s.total_payload_upload = m_stat.total_payload_upload();
1980 #ifndef TORRENT_DISABLE_DHT
1981 if (m_dht)
1983 m_dht->dht_status(s);
1985 else
1987 s.dht_nodes = 0;
1988 s.dht_node_cache = 0;
1989 s.dht_torrents = 0;
1990 s.dht_global_nodes = 0;
1992 #endif
1994 return s;
1997 #ifndef TORRENT_DISABLE_DHT
1999 void session_impl::start_dht(entry const& startup_state)
2001 mutex_t::scoped_lock l(m_mutex);
2003 INVARIANT_CHECK;
2005 if (m_dht)
2007 m_dht->stop();
2008 m_dht = 0;
2010 if (m_dht_settings.service_port == 0
2011 || m_dht_same_port)
2013 m_dht_same_port = true;
2014 // if you hit this assert you are trying to start the
2015 // DHT with the same port as the tcp listen port
2016 // (which is default) _before_ you have opened the
2017 // tcp listen port (so there is no configured port to use)
2018 // basically, make sure you call listen_on() before
2019 // start_dht(). See documentation for listen_on() for
2020 // more information.
2021 TORRENT_ASSERT(m_listen_interface.port() > 0);
2022 m_dht_settings.service_port = m_listen_interface.port();
2024 m_external_udp_port = m_dht_settings.service_port;
2025 if (m_natpmp.get() && m_udp_mapping[0] == -1)
2027 m_udp_mapping[0] = m_natpmp->add_mapping(natpmp::udp
2028 , m_dht_settings.service_port
2029 , m_dht_settings.service_port);
2031 if (m_upnp.get() && m_udp_mapping[1] == -1)
2033 m_udp_mapping[1] = m_upnp->add_mapping(upnp::udp
2034 , m_dht_settings.service_port
2035 , m_dht_settings.service_port);
2037 m_dht = new dht::dht_tracker(m_dht_socket, m_dht_settings, startup_state);
2038 if (!m_dht_socket.is_open() || m_dht_socket.local_port() != m_dht_settings.service_port)
2040 m_dht_socket.bind(m_dht_settings.service_port);
2044 void session_impl::stop_dht()
2046 mutex_t::scoped_lock l(m_mutex);
2047 if (!m_dht) return;
2048 m_dht->stop();
2049 m_dht = 0;
2052 void session_impl::set_dht_settings(dht_settings const& settings)
2054 mutex_t::scoped_lock l(m_mutex);
2055 // only change the dht listen port in case the settings
2056 // contains a vaiid port, and if it is different from
2057 // the current setting
2058 if (settings.service_port != 0)
2059 m_dht_same_port = false;
2060 else
2061 m_dht_same_port = true;
2062 if (!m_dht_same_port
2063 && settings.service_port != m_dht_settings.service_port
2064 && m_dht)
2066 m_dht_socket.bind(settings.service_port);
2068 if (m_natpmp.get())
2070 if (m_udp_mapping[0] != -1) m_upnp->delete_mapping(m_udp_mapping[0]);
2071 m_udp_mapping[0] = m_natpmp->add_mapping(natpmp::udp
2072 , m_dht_settings.service_port
2073 , m_dht_settings.service_port);
2075 if (m_upnp.get())
2077 if (m_udp_mapping[1] != -1) m_upnp->delete_mapping(m_udp_mapping[1]);
2078 m_udp_mapping[1] = m_upnp->add_mapping(upnp::udp
2079 , m_dht_settings.service_port
2080 , m_dht_settings.service_port);
2082 m_external_udp_port = settings.service_port;
2084 m_dht_settings = settings;
2085 if (m_dht_same_port)
2086 m_dht_settings.service_port = m_listen_interface.port();
2089 entry session_impl::dht_state() const
2091 mutex_t::scoped_lock l(m_mutex);
2092 if (!m_dht) return entry();
2093 return m_dht->state();
2096 void session_impl::add_dht_node(std::pair<std::string, int> const& node)
2098 TORRENT_ASSERT(m_dht);
2099 mutex_t::scoped_lock l(m_mutex);
2100 m_dht->add_node(node);
2103 void session_impl::add_dht_router(std::pair<std::string, int> const& node)
2105 TORRENT_ASSERT(m_dht);
2106 mutex_t::scoped_lock l(m_mutex);
2107 m_dht->add_router_node(node);
2110 #endif
2112 #ifndef TORRENT_DISABLE_ENCRYPTION
2113 void session_impl::set_pe_settings(pe_settings const& settings)
2115 mutex_t::scoped_lock l(m_mutex);
2116 m_pe_settings = settings;
2118 #endif
2120 bool session_impl::is_listening() const
2122 mutex_t::scoped_lock l(m_mutex);
2123 return !m_listen_sockets.empty();
2126 session_impl::~session_impl()
2128 #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
2129 (*m_logger) << time_now_string() << "\n\n *** shutting down session *** \n\n";
2130 #endif
2131 abort();
2133 #ifndef TORRENT_DISABLE_GEO_IP
2134 if (m_asnum_db) GeoIP_delete(m_asnum_db);
2135 if (m_country_db) GeoIP_delete(m_country_db);
2136 #endif
2137 #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
2138 (*m_logger) << time_now_string() << " waiting for main thread\n";
2139 #endif
2140 m_thread->join();
2142 TORRENT_ASSERT(m_torrents.empty());
2144 #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
2145 (*m_logger) << time_now_string() << " waiting for disk io thread\n";
2146 #endif
2147 m_disk_thread.join();
2149 TORRENT_ASSERT(m_torrents.empty());
2150 TORRENT_ASSERT(m_connections.empty());
2151 #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
2152 (*m_logger) << time_now_string() << " shutdown complete!\n";
2153 #endif
2156 void session_impl::set_max_uploads(int limit)
2158 TORRENT_ASSERT(limit > 0 || limit == -1);
2159 mutex_t::scoped_lock l(m_mutex);
2161 INVARIANT_CHECK;
2163 if (limit <= 0) limit = (std::numeric_limits<int>::max)();
2164 if (m_max_uploads == limit) return;
2165 m_max_uploads = limit;
2166 m_allowed_upload_slots = limit;
2169 void session_impl::set_max_connections(int limit)
2171 TORRENT_ASSERT(limit > 0 || limit == -1);
2172 mutex_t::scoped_lock l(m_mutex);
2174 INVARIANT_CHECK;
2176 if (limit <= 0)
2178 limit = (std::numeric_limits<int>::max)();
2179 #ifndef TORRENT_WINDOWS
2180 rlimit l;
2181 if (getrlimit(RLIMIT_NOFILE, &l) == 0
2182 && l.rlim_cur != RLIM_INFINITY)
2184 limit = l.rlim_cur - m_settings.file_pool_size;
2185 if (limit < 5) limit = 5;
2187 #endif
2189 m_max_connections = limit;
2192 void session_impl::set_max_half_open_connections(int limit)
2194 TORRENT_ASSERT(limit > 0 || limit == -1);
2195 mutex_t::scoped_lock l(m_mutex);
2197 INVARIANT_CHECK;
2199 if (limit <= 0) limit = (std::numeric_limits<int>::max)();
2200 m_half_open.limit(limit);
2203 void session_impl::set_download_rate_limit(int bytes_per_second)
2205 TORRENT_ASSERT(bytes_per_second > 0 || bytes_per_second == -1);
2206 mutex_t::scoped_lock l(m_mutex);
2208 INVARIANT_CHECK;
2210 if (bytes_per_second <= 0) bytes_per_second = bandwidth_limit::inf;
2211 m_bandwidth_manager[peer_connection::download_channel]->throttle(bytes_per_second);
2214 void session_impl::set_upload_rate_limit(int bytes_per_second)
2216 TORRENT_ASSERT(bytes_per_second > 0 || bytes_per_second == -1);
2217 mutex_t::scoped_lock l(m_mutex);
2219 INVARIANT_CHECK;
2221 if (bytes_per_second <= 0) bytes_per_second = bandwidth_limit::inf;
2222 m_bandwidth_manager[peer_connection::upload_channel]->throttle(bytes_per_second);
2225 std::auto_ptr<alert> session_impl::pop_alert()
2227 mutex_t::scoped_lock l(m_mutex);
2229 // too expensive
2230 // INVARIANT_CHECK;
2232 if (m_alerts.pending())
2233 return m_alerts.get();
2234 return std::auto_ptr<alert>(0);
2237 alert const* session_impl::wait_for_alert(time_duration max_wait)
2239 return m_alerts.wait_for_alert(max_wait);
2242 void session_impl::set_alert_mask(int m)
2244 mutex_t::scoped_lock l(m_mutex);
2245 m_alerts.set_alert_mask(m);
2248 int session_impl::upload_rate_limit() const
2250 mutex_t::scoped_lock l(m_mutex);
2252 INVARIANT_CHECK;
2254 int ret = m_bandwidth_manager[peer_connection::upload_channel]->throttle();
2255 return ret == (std::numeric_limits<int>::max)() ? -1 : ret;
2258 int session_impl::download_rate_limit() const
2260 mutex_t::scoped_lock l(m_mutex);
2261 int ret = m_bandwidth_manager[peer_connection::download_channel]->throttle();
2262 return ret == (std::numeric_limits<int>::max)() ? -1 : ret;
2265 void session_impl::start_lsd()
2267 mutex_t::scoped_lock l(m_mutex);
2269 INVARIANT_CHECK;
2271 if (m_lsd) return;
2273 m_lsd = new lsd(m_io_service
2274 , m_listen_interface.address()
2275 , bind(&session_impl::on_lsd_peer, this, _1, _2));
2278 natpmp* session_impl::start_natpmp()
2280 mutex_t::scoped_lock l(m_mutex);
2282 INVARIANT_CHECK;
2284 if (m_natpmp) return m_natpmp.get();
2286 m_natpmp = new natpmp(m_io_service
2287 , m_listen_interface.address()
2288 , bind(&session_impl::on_port_mapping
2289 , this, _1, _2, _3, 0));
2291 if (m_listen_interface.port() > 0)
2293 m_tcp_mapping[0] = m_natpmp->add_mapping(natpmp::tcp
2294 , m_listen_interface.port(), m_listen_interface.port());
2296 #ifndef TORRENT_DISABLE_DHT
2297 if (m_dht)
2298 m_udp_mapping[0] = m_natpmp->add_mapping(natpmp::udp
2299 , m_dht_settings.service_port
2300 , m_dht_settings.service_port);
2301 #endif
2302 return m_natpmp.get();
2305 upnp* session_impl::start_upnp()
2307 mutex_t::scoped_lock l(m_mutex);
2309 INVARIANT_CHECK;
2311 if (m_upnp) return m_upnp.get();
2313 m_upnp = new upnp(m_io_service, m_half_open
2314 , m_listen_interface.address()
2315 , m_settings.user_agent
2316 , bind(&session_impl::on_port_mapping
2317 , this, _1, _2, _3, 1)
2318 , m_settings.upnp_ignore_nonrouters);
2320 m_upnp->discover_device();
2321 if (m_listen_interface.port() > 0)
2323 m_tcp_mapping[1] = m_upnp->add_mapping(upnp::tcp
2324 , m_listen_interface.port(), m_listen_interface.port());
2326 #ifndef TORRENT_DISABLE_DHT
2327 if (m_dht)
2328 m_udp_mapping[1] = m_upnp->add_mapping(upnp::udp
2329 , m_dht_settings.service_port
2330 , m_dht_settings.service_port);
2331 #endif
2332 return m_upnp.get();
2335 void session_impl::stop_lsd()
2337 mutex_t::scoped_lock l(m_mutex);
2338 if (m_lsd.get())
2339 m_lsd->close();
2340 m_lsd = 0;
2343 void session_impl::stop_natpmp()
2345 mutex_t::scoped_lock l(m_mutex);
2346 if (m_natpmp.get())
2347 m_natpmp->close();
2348 m_natpmp = 0;
2351 void session_impl::stop_upnp()
2353 mutex_t::scoped_lock l(m_mutex);
2354 if (m_upnp.get())
2356 m_upnp->close();
2357 m_udp_mapping[1] = -1;
2358 m_tcp_mapping[1] = -1;
2360 m_upnp = 0;
2363 void session_impl::set_external_address(address const& ip)
2365 TORRENT_ASSERT(ip != address());
2367 if (m_external_address == ip) return;
2369 m_external_address = ip;
2370 if (m_alerts.should_post<external_ip_alert>())
2371 m_alerts.post_alert(external_ip_alert(ip));
2374 void session_impl::free_disk_buffer(char* buf)
2376 m_disk_thread.free_buffer(buf);
2379 char* session_impl::allocate_disk_buffer()
2381 return m_disk_thread.allocate_buffer();
2384 std::pair<char*, int> session_impl::allocate_buffer(int size)
2386 TORRENT_ASSERT(size > 0);
2387 int num_buffers = (size + send_buffer_size - 1) / send_buffer_size;
2388 TORRENT_ASSERT(num_buffers > 0);
2390 boost::mutex::scoped_lock l(m_send_buffer_mutex);
2391 #ifdef TORRENT_STATS
2392 TORRENT_ASSERT(m_buffer_allocations >= 0);
2393 m_buffer_allocations += num_buffers;
2394 m_buffer_usage_logger << log_time() << " protocol_buffer: "
2395 << (m_buffer_allocations * send_buffer_size) << std::endl;
2396 #endif
2397 #ifdef TORRENT_DISABLE_POOL_ALLOCATOR
2398 int num_bytes = num_buffers * send_buffer_size;
2399 return std::make_pair((char*)malloc(num_bytes), num_bytes);
2400 #else
2401 return std::make_pair((char*)m_send_buffers.ordered_malloc(num_buffers)
2402 , num_buffers * send_buffer_size);
2403 #endif
2406 void session_impl::free_buffer(char* buf, int size)
2408 TORRENT_ASSERT(size > 0);
2409 TORRENT_ASSERT(size % send_buffer_size == 0);
2410 int num_buffers = size / send_buffer_size;
2411 TORRENT_ASSERT(num_buffers > 0);
2413 boost::mutex::scoped_lock l(m_send_buffer_mutex);
2414 #ifdef TORRENT_STATS
2415 m_buffer_allocations -= num_buffers;
2416 TORRENT_ASSERT(m_buffer_allocations >= 0);
2417 m_buffer_usage_logger << log_time() << " protocol_buffer: "
2418 << (m_buffer_allocations * send_buffer_size) << std::endl;
2419 #endif
2420 #ifdef TORRENT_DISABLE_POOL_ALLOCATOR
2421 free(buf);
2422 #else
2423 m_send_buffers.ordered_free(buf, num_buffers);
2424 #endif
2427 #ifndef NDEBUG
2428 void session_impl::check_invariant() const
2430 std::set<int> unique;
2431 int total_downloaders = 0;
2432 for (torrent_map::const_iterator i = m_torrents.begin()
2433 , end(m_torrents.end()); i != end; ++i)
2435 int pos = i->second->queue_position();
2436 if (pos < 0)
2438 TORRENT_ASSERT(pos == -1);
2439 continue;
2441 ++total_downloaders;
2442 unique.insert(i->second->queue_position());
2444 TORRENT_ASSERT(unique.size() == total_downloaders);
2446 TORRENT_ASSERT(m_max_connections > 0);
2447 TORRENT_ASSERT(m_max_uploads > 0);
2448 TORRENT_ASSERT(m_allowed_upload_slots >= m_max_uploads);
2449 int unchokes = 0;
2450 int num_optimistic = 0;
2451 for (connection_map::const_iterator i = m_connections.begin();
2452 i != m_connections.end(); ++i)
2454 TORRENT_ASSERT(*i);
2455 boost::shared_ptr<torrent> t = (*i)->associated_torrent().lock();
2457 peer_connection* p = i->get();
2458 TORRENT_ASSERT(!p->is_disconnecting());
2459 if (!p->is_choked()) ++unchokes;
2460 if (p->peer_info_struct()
2461 && p->peer_info_struct()->optimistically_unchoked)
2463 ++num_optimistic;
2464 TORRENT_ASSERT(!p->is_choked());
2466 if (t && p->peer_info_struct())
2468 TORRENT_ASSERT(t->get_policy().has_connection(p));
2471 TORRENT_ASSERT(num_optimistic == 0 || num_optimistic == 1);
2472 if (m_num_unchoked != unchokes)
2474 TORRENT_ASSERT(false);
2476 for (std::map<sha1_hash, boost::shared_ptr<torrent> >::const_iterator j
2477 = m_torrents.begin(); j != m_torrents.end(); ++j)
2479 TORRENT_ASSERT(boost::get_pointer(j->second));
2482 #endif