3 Copyright (c) 2006, Arvid Norberg, Magnus Jonsson
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
10 * Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in
14 the documentation and/or other materials provided with the distribution.
15 * Neither the name of the author nor the names of its
16 contributors may be used to endorse or promote products derived
17 from this software without specific prior written permission.
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 POSSIBILITY OF SUCH DAMAGE.
33 #include "libtorrent/pch.hpp"
46 #pragma warning(push, 1)
49 #include <boost/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>
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>
83 #ifndef TORRENT_DISABLE_ENCRYPTION
85 #include <openssl/crypto.h>
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
;
99 // for ERROR_SEM_TIMEOUT
100 #include <winerror.h>
103 using boost::shared_ptr
;
104 using boost::weak_ptr
;
107 using libtorrent::aux::session_impl
;
109 namespace libtorrent
{
111 namespace fs
= boost::filesystem
;
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
;
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
144 #ifndef TORRENT_DISABLE_POOL_ALLOCATOR
145 m_send_buffers(send_buffer_size
),
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)
155 , m_upload_channel(m_io_service
, peer_connection::upload_channel
)
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
)
163 , m_allowed_upload_slots(8)
164 , m_max_connections(200)
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
)
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
184 #ifndef TORRENT_DISABLE_GEO_IP
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;
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);
207 m_half_open
.limit(8);
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";
225 m_stats_logger
.open("session_stats.log", std::ios::trunc
);
230 "4. downloading torrents\n"
231 "5. seeding torrents\n"
233 "7. connecting peers\n"
234 "8. disk block buffers\n"
236 m_buffer_usage_logger
.open("buffer_stats.log", std::ios::trunc
);
237 m_second_counter
= 0;
238 m_buffer_allocations
= 0;
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
251 , print
.begin() + print
.length()
252 , m_peer_id
.begin());
254 // http-accepted characters:
255 static char const printable
[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
256 "abcdefghijklmnopqrstuvwxyz-_.!~*'()";
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)];
266 m_timer
.expires_from_now(seconds(1), ec
);
268 bind(&session_impl::second_tick
, this, _1
));
270 m_thread
.reset(new boost::thread(boost::ref(*this)));
273 #ifndef TORRENT_DISABLE_GEO_IP
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;
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();
306 char* tmp
= std::strchr(name
, ' ');
307 if (tmp
== 0) return std::string();
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));
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
);
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
);
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();
362 entry
session_impl::state() const
364 mutex_t::scoped_lock
l(m_mutex
);
366 #ifndef TORRENT_DISABLE_GEO_IP
367 entry::dictionary_type
& as_map
= ret
["AS map"].dict();
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
;
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
);
388 #ifndef TORRENT_DISABLE_DHT
389 void session_impl::add_dht_node(udp::endpoint n
)
391 if (m_dht
) m_dht
->add_node(n
);
395 void session_impl::pause()
397 mutex_t::scoped_lock
l(m_mutex
);
398 if (m_paused
) return;
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;
413 for (torrent_map::iterator i
= m_torrents
.begin()
414 , end(m_torrents
.end()); i
!= end
; ++i
)
416 torrent
& t
= *i
->second
;
421 void session_impl::abort()
423 mutex_t::scoped_lock
l(m_mutex
);
425 #if defined(TORRENT_LOGGING)
426 (*m_logger
) << time_now_string() << " *** ABORT CALLED ***\n";
428 // abort the main thread
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();
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
)
448 #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
449 (*m_logger
) << time_now_string() << " aborting all torrents (" << m_torrents
.size() << ")\n";
451 // abort all torrents
452 for (torrent_map::iterator i
= m_torrents
.begin()
453 , end(m_torrents
.end()); i
!= end
; ++i
)
458 #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
459 (*m_logger
) << time_now_string() << " aborting all tracker requests\n";
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";
467 for (torrent_map::iterator i
= m_torrents
.begin();
468 i
!= m_torrents
.end(); ++i
)
470 torrent
& t
= *i
->second
;
474 #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
475 (*m_logger
) << time_now_string() << " sent " << counter
<< " tracker stop requests\n";
478 #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
479 (*m_logger
) << time_now_string() << " aborting all connections (" << m_connections
.size() << ")\n";
481 // abort all connections
482 while (!m_connections
.empty())
485 int conn
= m_connections
.size();
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";
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
);
506 void session_impl::set_ip_filter(ip_filter
const& f
)
508 mutex_t::scoped_lock
l(m_mutex
);
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
);
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;
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())
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
)
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)
574 ep
.port(ep
.port() + 1);
575 s
.sock
->bind(ep
, ec
);
579 // instead of giving up, try
580 // let the OS pick a port
583 s
.sock
->bind(ep
, 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";
596 return listen_socket_t();
598 s
.external_port
= s
.sock
->local_endpoint(ec
).port();
599 s
.sock
->listen(0, 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";
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";
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
);
640 m_listen_sockets
.push_back(s
);
641 async_accept(s
.sock
);
645 tcp::endpoint(address_v6::any(), m_listen_interface
.port())
646 , m_listen_port_retries
, true);
650 m_listen_sockets
.push_back(s
);
651 async_accept(s
.sock
);
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
);
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
)
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
682 m_ipv6_interface
= ep
;
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());
702 if (!m_listen_sockets
.empty())
705 tcp::endpoint local
= m_listen_sockets
.front().sock
->local_endpoint(ec
);
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());
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
)
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
));
741 if (len
> 20 && *buf
== 'd' && m_dht
)
743 // this is probably a dht message
744 m_dht
->on_receive(ep
, buf
, len
);
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
);
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";
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
);
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
);
797 if (m_alerts
.should_post
<listen_failed_alert
>())
798 m_alerts
.post_alert(listen_failed_alert(ep
, e
));
801 async_accept(listener
);
803 // we got a connection request!
804 tcp::endpoint endp
= s
->remote_endpoint(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";
815 #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
816 (*m_logger
) << time_now_string() << " <== INCOMING CONNECTION " << endp
<< "\n";
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";
831 if (m_alerts
.should_post
<peer_blocked_alert
>())
832 m_alerts
.post_alert(peer_blocked_alert(endp
.address()));
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";
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";
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;
867 if (!has_active_torrent
)
869 #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
870 (*m_logger
) << " There are no _active_ torrents, disconnect\n";
875 boost::intrusive_ptr
<peer_connection
> c(
876 new bt_peer_connection(*this, s
, endp
, 0));
878 c
->m_in_constructor
= false;
881 if (!c
->is_disconnecting())
883 m_connections
.insert(c
);
887 void session_impl::close_connection(peer_connection
const* p
888 , char const* message
)
890 mutex_t::scoped_lock
l(m_mutex
);
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));
901 #if defined(TORRENT_LOGGING)
902 (*m_logger
) << time_now_string() << " CLOSING CONNECTION "
903 << p
->remote() << " : " << message
<< "\n";
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
);
923 void session_impl::set_key(int key
)
925 mutex_t::scoped_lock
l(m_mutex
);
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
;
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";
945 void session_impl::second_tick(error_code
const& e
)
947 session_impl::mutex_t::scoped_lock
l(m_mutex
);
956 #if defined TORRENT_LOGGING
957 (*m_logger
) << "*** SECOND TIMER FAILED " << e
.message() << "\n";
963 float tick_interval
= total_microseconds(time_now() - m_last_tick
) / 1000000.f
;
964 m_last_tick
= time_now();
967 m_timer
.expires_from_now(seconds(1), ec
);
969 bind(&session_impl::second_tick
, this, _1
));
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())
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())
991 ++num_complete_connections
;
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"
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();
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
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
;
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())
1070 num_downloads_peers
+= t
.num_peers();
1073 t
.second_tick(m_stat
, tick_interval
);
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
);
1128 m_next_connect_torrent
= 0;
1129 int steps_since_last_connect
= 0;
1130 int num_torrents
= int(m_torrents
.size());
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
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())
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
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
;
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
);
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
)
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
);
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();
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())
1298 downloaders
.push_back(t
);
1300 else if (!t
->is_paused())
1303 if (is_active(t
, settings()))
1305 // this is not an auto managed torrent,
1306 // if it's running and active, decrease the
1314 bool handled_by_extension
= false;
1316 #ifndef TORRENT_DISABLE_EXTENSIONS
1317 // TODO: allow extensions to sort torrents for queuing
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
)
1334 if (!t
->is_paused() && !is_active(t
, settings()) && hard_limit
> 0)
1340 if (num_downloaders
> 0 && hard_limit
> 0)
1343 if (t
->state() != torrent_status::queued_for_checking
1344 && t
->state() != torrent_status::checking_files
)
1347 if (t
->is_paused()) t
->resume();
1352 if (!t
->is_paused()) t
->pause();
1356 for (std::vector
<torrent
*>::iterator i
= seeds
.begin()
1357 , end(seeds
.end()); i
!= end
; ++i
)
1360 if (!t
->is_paused() && !is_active(t
, settings()) && hard_limit
> 0)
1366 if (num_seeds
> 0 && hard_limit
> 0)
1370 if (t
->is_paused()) t
->resume();
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()
1390 || !p
->is_peer_interested()
1391 || p
->is_disconnecting()
1392 || p
->is_connecting()
1393 || (p
->share_diff() < -free_upload_amount
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
));
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
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
));
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
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;
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
;
1454 torrent
* t
= p
->associated_torrent().lock().get();
1456 if (unchoke_set_size
> 0)
1460 if (!t
->unchoke_peer(*p
))
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;
1477 TORRENT_ASSERT(p
->peer_info_struct());
1478 if (!p
->is_choked() && !p
->peer_info_struct()->optimistically_unchoked
)
1480 if (!p
->is_choked())
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
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();
1502 policy::peer
* pi
= p
->peer_info_struct();
1504 torrent
* t
= p
->associated_torrent().lock().get();
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()
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();
1533 (*current_optimistic_unchoke
)->peer_info_struct()->optimistically_unchoked
= false;
1534 t
->choke_peer(*current_optimistic_unchoke
->get());
1541 torrent
* t
= (*optimistic_unchoke_candidate
)->associated_torrent().lock().get();
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()()
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
1568 TORRENT_ASSERT(m_abort
== true);
1569 #ifndef BOOST_NO_EXCEPTIONS
1571 catch (std::exception
& e
)
1574 std::cerr
<< e
.what() << "\n";
1575 std::string err
= e
.what();
1577 TORRENT_ASSERT(false);
1583 #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
1584 (*m_logger
) << time_now_string() << " locking mutex\n";
1587 session_impl::mutex_t::scoped_lock
l(m_mutex
);
1590 for (torrent_map::iterator i = m_torrents.begin();
1591 i != m_torrents.end(); ++i)
1593 TORRENT_ASSERT(i->second->num_peers() == 0);
1597 #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
1598 (*m_logger
) << time_now_string() << " cleaning up torrents\n";
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
);
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
);
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
));
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());
1643 if (i
->second
->is_aborted()) continue;
1644 ret
.push_back(torrent_handle(i
->second
));
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");
1663 return torrent_handle();
1667 // lock the session and the checker thread (the order is important!)
1668 mutex_t::scoped_lock
l(m_mutex
);
1674 #ifndef BOOST_NO_EXCEPTIONS
1675 throw std::runtime_error("session is closing");
1677 return torrent_handle();
1681 // figure out the info hash of the torrent
1682 sha1_hash
const* ih
= 0;
1683 if (params
.ti
) ih
= ¶ms
.ti
->info_hash();
1684 else ih
= ¶ms
.info_hash
;
1686 // is the torrent already active?
1687 boost::shared_ptr
<torrent
> torrent_ptr
= find_torrent(*ih
).lock();
1690 if (!params
.duplicate_is_error
)
1691 return torrent_handle(torrent_ptr
);
1693 #ifndef BOOST_NO_EXCEPTIONS
1694 throw duplicate_torrent();
1696 return torrent_handle();
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
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
));
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
);
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
));
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())
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();
1784 #ifdef BOOST_NO_EXCEPTIONS
1787 throw invalid_handle();
1790 mutex_t::scoped_lock
l(m_mutex
);
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
)
1805 sha1_hash i_hash
= t
.torrent_file().info_hash();
1807 i
->second
->set_queue_position(-1);
1808 m_torrents
.erase(i
);
1809 TORRENT_ASSERT(m_torrents
.find(i_hash
) == m_torrents
.end());
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
);
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
);
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
;
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
);
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
);
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
);
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";
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
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
);
1894 boost::shared_ptr
<torrent
> t
= find_torrent(ih
).lock();
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";
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
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
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
));
1939 if (m_alerts
.should_post
<portmap_alert
>())
1940 m_alerts
.post_alert(portmap_alert(mapping
, port
1945 session_status
session_impl::status() const
1947 mutex_t::scoped_lock
l(m_mutex
);
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
1983 m_dht
->dht_status(s
);
1988 s
.dht_node_cache
= 0;
1990 s
.dht_global_nodes
= 0;
1997 #ifndef TORRENT_DISABLE_DHT
1999 void session_impl::start_dht(entry
const& startup_state
)
2001 mutex_t::scoped_lock
l(m_mutex
);
2010 if (m_dht_settings
.service_port
== 0
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
);
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;
2061 m_dht_same_port
= true;
2062 if (!m_dht_same_port
2063 && settings
.service_port
!= m_dht_settings
.service_port
2066 m_dht_socket
.bind(settings
.service_port
);
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
);
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
);
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
;
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";
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
);
2137 #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
2138 (*m_logger
) << time_now_string() << " waiting for main thread\n";
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";
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";
2156 void session_impl::set_max_uploads(int limit
)
2158 TORRENT_ASSERT(limit
> 0 || limit
== -1);
2159 mutex_t::scoped_lock
l(m_mutex
);
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
);
2178 limit
= (std::numeric_limits
<int>::max
)();
2179 #ifndef TORRENT_WINDOWS
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;
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
2298 m_udp_mapping
[0] = m_natpmp
->add_mapping(natpmp::udp
2299 , m_dht_settings
.service_port
2300 , m_dht_settings
.service_port
);
2302 return m_natpmp
.get();
2305 upnp
* session_impl::start_upnp()
2307 mutex_t::scoped_lock
l(m_mutex
);
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
2328 m_udp_mapping
[1] = m_upnp
->add_mapping(upnp::udp
2329 , m_dht_settings
.service_port
2330 , m_dht_settings
.service_port
);
2332 return m_upnp
.get();
2335 void session_impl::stop_lsd()
2337 mutex_t::scoped_lock
l(m_mutex
);
2343 void session_impl::stop_natpmp()
2345 mutex_t::scoped_lock
l(m_mutex
);
2351 void session_impl::stop_upnp()
2353 mutex_t::scoped_lock
l(m_mutex
);
2357 m_udp_mapping
[1] = -1;
2358 m_tcp_mapping
[1] = -1;
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
;
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
);
2401 return std::make_pair((char*)m_send_buffers
.ordered_malloc(num_buffers
)
2402 , num_buffers
* send_buffer_size
);
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
;
2420 #ifdef TORRENT_DISABLE_POOL_ALLOCATOR
2423 m_send_buffers
.ordered_free(buf
, num_buffers
);
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();
2438 TORRENT_ASSERT(pos
== -1);
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
);
2450 int num_optimistic
= 0;
2451 for (connection_map::const_iterator i
= m_connections
.begin();
2452 i
!= m_connections
.end(); ++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
)
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
));