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>
54
#include <boost/function_equal.hpp>
60
#include "libtorrent/peer_id.hpp"
61
#include "libtorrent/torrent_info.hpp"
62
#include "libtorrent/tracker_manager.hpp"
63
#include "libtorrent/bencode.hpp"
64
#include "libtorrent/hasher.hpp"
65
#include "libtorrent/entry.hpp"
66
#include "libtorrent/session.hpp"
67
#include "libtorrent/fingerprint.hpp"
68
#include "libtorrent/entry.hpp"
69
#include "libtorrent/alert_types.hpp"
70
#include "libtorrent/invariant_check.hpp"
71
#include "libtorrent/file.hpp"
72
#include "libtorrent/bt_peer_connection.hpp"
73
#include "libtorrent/ip_filter.hpp"
74
#include "libtorrent/socket.hpp"
75
#include "libtorrent/aux_/session_impl.hpp"
76
#include "libtorrent/kademlia/dht_tracker.hpp"
77
#include "libtorrent/enum_net.hpp"
78
#include "libtorrent/config.hpp"
79
#include "libtorrent/upnp.hpp"
80
#include "libtorrent/natpmp.hpp"
81
#include "libtorrent/lsd.hpp"
83
#ifndef TORRENT_WINDOWS
84
#include <sys/resource.h>
87
#ifndef TORRENT_DISABLE_ENCRYPTION
89
#include <openssl/crypto.h>
93
// openssl requires this to clean up internal
94
// structures it allocates
95
struct openssl_cleanup
97
~openssl_cleanup() { CRYPTO_cleanup_all_ex_data(); }
98
} openssl_global_destructor;
102
#ifdef TORRENT_WINDOWS
103
// for ERROR_SEM_TIMEOUT
104
#include <winerror.h>
107
using boost::shared_ptr;
108
using boost::weak_ptr;
110
using libtorrent::aux::session_impl;
112
namespace libtorrent {
114
namespace fs = boost::filesystem;
119
std::string generate_auth_string(std::string const& user
120
, std::string const& passwd)
122
if (user.empty()) return std::string();
123
return user + ":" + passwd;
130
struct seed_random_generator
132
seed_random_generator()
134
std::srand(total_microseconds(time_now() - min_time()));
138
session_impl::session_impl(
139
std::pair<int, int> listen_port_range
140
, fingerprint const& cl_fprint
141
, char const* listen_interface
142
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
143
, fs::path const& logpath
147
#ifndef TORRENT_DISABLE_POOL_ALLOCATOR
148
m_send_buffers(send_buffer_size),
152
, m_disk_thread(m_io_service)
153
, m_half_open(m_io_service)
154
, m_download_channel(m_io_service, peer_connection::download_channel)
155
#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT
156
, m_upload_channel(m_io_service, peer_connection::upload_channel, true)
158
, m_upload_channel(m_io_service, peer_connection::upload_channel)
160
, m_tracker_manager(m_settings, m_tracker_proxy)
161
, m_listen_port_retries(listen_port_range.second - listen_port_range.first)
165
, m_allowed_upload_slots(8)
166
, m_max_connections(200)
168
, m_unchoke_time_scaler(0)
169
, m_auto_manage_time_scaler(0)
170
, m_optimistic_unchoke_time_scaler(0)
171
, m_disconnect_time_scaler(90)
172
, m_auto_scrape_time_scaler(180)
173
, m_incoming_connection(false)
174
, m_last_tick(time_now())
175
#ifndef TORRENT_DISABLE_DHT
176
, m_dht_same_port(true)
177
, m_external_udp_port(0)
178
, m_dht_socket(m_io_service, bind(&session_impl::on_receive_udp, this, _1, _2, _3, _4)
181
, m_timer(m_io_service)
182
, m_next_connect_torrent(0)
183
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
186
#ifndef TORRENT_DISABLE_GEO_IP
190
, m_total_failed_bytes(0)
191
, m_total_redundant_bytes(0)
194
m_listen_interface = tcp::endpoint(address::from_string(listen_interface, ec), listen_port_range.first);
197
m_tcp_mapping[0] = -1;
198
m_tcp_mapping[1] = -1;
199
m_udp_mapping[0] = -1;
200
m_udp_mapping[1] = -1;
202
// windows XP has a limit on the number of
203
// simultaneous half-open TCP connections
204
DWORD windows_version = ::GetVersion();
205
if ((windows_version & 0xff) >= 6)
207
// on vista the limit is 5 (in home edition)
208
m_half_open.limit(4);
213
m_half_open.limit(8);
217
m_bandwidth_manager[peer_connection::download_channel] = &m_download_channel;
218
m_bandwidth_manager[peer_connection::upload_channel] = &m_upload_channel;
220
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
221
m_logger = create_log("main_session", listen_port(), false);
222
(*m_logger) << time_now_string() << "\n";
224
(*m_logger) << "sizeof(torrent): " << sizeof(torrent) << "\n";
225
(*m_logger) << "sizeof(peer_connection): " << sizeof(peer_connection) << "\n";
226
(*m_logger) << "sizeof(bt_peer_connection): " << sizeof(bt_peer_connection) << "\n";
227
(*m_logger) << "sizeof(policy::peer): " << sizeof(policy::peer) << "\n";
228
(*m_logger) << "sizeof(tcp::endpoint): " << sizeof(tcp::endpoint) << "\n";
229
(*m_logger) << "sizeof(address): " << sizeof(address) << "\n";
230
(*m_logger) << "sizeof(address_v4): " << sizeof(address_v4) << "\n";
231
(*m_logger) << "sizeof(address_v6): " << sizeof(address_v6) << "\n";
232
(*m_logger) << "sizeof(void*): " << sizeof(void*) << "\n";
236
m_stats_logger.open("session_stats.log", std::ios::trunc);
241
"4. downloading torrents\n"
242
"5. seeding torrents\n"
244
"7. connecting peers\n"
245
"8. disk block buffers\n"
247
m_buffer_usage_logger.open("buffer_stats.log", std::ios::trunc);
248
m_second_counter = 0;
249
m_buffer_allocations = 0;
252
// ---- generate a peer id ----
253
static seed_random_generator seeder;
255
m_key = rand() + (rand() << 15) + (rand() << 30);
256
std::string print = cl_fprint.to_string();
257
TORRENT_ASSERT(print.length() <= 20);
259
// the client's fingerprint
262
, print.begin() + print.length()
263
, m_peer_id.begin());
265
// http-accepted characters:
266
// excluding ', since some buggy trackers don't support that
267
static char const printable[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
268
"abcdefghijklmnopqrstuvwxyz-_.!~*()";
271
for (unsigned char* i = m_peer_id.begin() + print.length();
272
i != m_peer_id.end(); ++i)
274
*i = printable[rand() % (sizeof(printable)-1)];
277
m_timer.expires_from_now(seconds(1), ec);
279
bind(&session_impl::second_tick, this, _1));
281
m_thread.reset(new boost::thread(boost::ref(*this)));
284
#ifndef TORRENT_DISABLE_GEO_IP
290
free_ptr(void* p): ptr_(p) {}
291
~free_ptr() { free(ptr_); }
295
char const* session_impl::country_for_ip(address const& a)
297
if (!a.is_v4() || m_country_db == 0) return 0;
298
return GeoIP_country_code_by_ipnum(m_country_db, a.to_v4().to_ulong());
301
int session_impl::as_for_ip(address const& a)
303
if (!a.is_v4() || m_asnum_db == 0) return 0;
304
char* name = GeoIP_name_by_ipnum(m_asnum_db, a.to_v4().to_ulong());
305
if (name == 0) return 0;
307
// GeoIP returns the name as AS??? where ? is the AS-number
308
return atoi(name + 2);
311
std::string session_impl::as_name_for_ip(address const& a)
313
if (!a.is_v4() || m_asnum_db == 0) return std::string();
314
char* name = GeoIP_name_by_ipnum(m_asnum_db, a.to_v4().to_ulong());
315
if (name == 0) return std::string();
317
char* tmp = std::strchr(name, ' ');
318
if (tmp == 0) return std::string();
322
std::pair<const int, int>* session_impl::lookup_as(int as)
324
std::map<int, int>::iterator i = m_as_peak.lower_bound(as);
326
if (i == m_as_peak.end() || i->first != as)
328
// we don't have any data for this AS, insert a new entry
329
i = m_as_peak.insert(i, std::pair<int, int>(as, 0));
334
bool session_impl::load_asnum_db(char const* file)
336
mutex_t::scoped_lock l(m_mutex);
337
if (m_asnum_db) GeoIP_delete(m_asnum_db);
338
m_asnum_db = GeoIP_open(file, GEOIP_STANDARD);
342
bool session_impl::load_country_db(char const* file)
344
mutex_t::scoped_lock l(m_mutex);
345
if (m_country_db) GeoIP_delete(m_country_db);
346
m_country_db = GeoIP_open(file, GEOIP_STANDARD);
352
void session_impl::load_state(entry const& ses_state)
354
if (ses_state.type() != entry::dictionary_t) return;
355
mutex_t::scoped_lock l(m_mutex);
356
#ifndef TORRENT_DISABLE_GEO_IP
357
entry const* as_map = ses_state.find_key("AS map");
358
if (as_map && as_map->type() == entry::dictionary_t)
360
entry::dictionary_type const& as_peak = as_map->dict();
361
for (entry::dictionary_type::const_iterator i = as_peak.begin()
362
, end(as_peak.end()); i != end; ++i)
364
int as_num = atoi(i->first.c_str());
365
if (i->second.type() != entry::int_t || i->second.integer() == 0) continue;
366
int& peak = m_as_peak[as_num];
367
if (peak < i->second.integer()) peak = i->second.integer();
373
entry session_impl::state() const
375
mutex_t::scoped_lock l(m_mutex);
377
#ifndef TORRENT_DISABLE_GEO_IP
378
entry::dictionary_type& as_map = ret["AS map"].dict();
380
for (std::map<int, int>::const_iterator i = m_as_peak.begin()
381
, end(m_as_peak.end()); i != end; ++i)
383
if (i->second == 0) continue;
384
sprintf(buf, "%05d", i->first);
385
as_map[buf] = i->second;
391
#ifndef TORRENT_DISABLE_EXTENSIONS
392
void session_impl::add_extension(
393
boost::function<boost::shared_ptr<torrent_plugin>(torrent*, void*)> ext)
397
typedef boost::shared_ptr<torrent_plugin>(*function_t)(torrent*, void*);
398
function_t const* f = ext.target<function_t>();
402
for (extension_list_t::iterator i = m_extensions.begin(); i != m_extensions.end(); ++i)
403
if (function_equal(*i, *f)) return;
406
m_extensions.push_back(ext);
410
#ifndef TORRENT_DISABLE_DHT
411
void session_impl::add_dht_node(udp::endpoint n)
413
if (m_dht) m_dht->add_node(n);
417
void session_impl::pause()
419
mutex_t::scoped_lock l(m_mutex);
420
if (m_paused) return;
422
for (torrent_map::iterator i = m_torrents.begin()
423
, end(m_torrents.end()); i != end; ++i)
425
torrent& t = *i->second;
426
if (!t.is_torrent_paused()) t.do_pause();
430
void session_impl::resume()
432
mutex_t::scoped_lock l(m_mutex);
433
if (!m_paused) return;
435
for (torrent_map::iterator i = m_torrents.begin()
436
, end(m_torrents.end()); i != end; ++i)
438
torrent& t = *i->second;
443
void session_impl::abort()
445
mutex_t::scoped_lock l(m_mutex);
447
#if defined(TORRENT_LOGGING)
448
(*m_logger) << time_now_string() << " *** ABORT CALLED ***\n";
450
// abort the main thread
452
m_queued_for_checking.clear();
453
if (m_lsd) m_lsd->close();
454
if (m_upnp) m_upnp->close();
455
if (m_natpmp) m_natpmp->close();
456
#ifndef TORRENT_DISABLE_DHT
457
if (m_dht) m_dht->stop();
458
m_dht_socket.close();
463
// close the listen sockets
464
for (std::list<listen_socket_t>::iterator i = m_listen_sockets.begin()
465
, end(m_listen_sockets.end()); i != end; ++i)
470
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
471
(*m_logger) << time_now_string() << " aborting all torrents (" << m_torrents.size() << ")\n";
473
// abort all torrents
474
for (torrent_map::iterator i = m_torrents.begin()
475
, end(m_torrents.end()); i != end; ++i)
480
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
481
(*m_logger) << time_now_string() << " aborting all tracker requests\n";
483
m_tracker_manager.abort_all_requests();
485
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
486
(*m_logger) << time_now_string() << " sending event=stopped to trackers\n";
489
for (torrent_map::iterator i = m_torrents.begin();
490
i != m_torrents.end(); ++i)
492
torrent& t = *i->second;
496
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
497
(*m_logger) << time_now_string() << " sent " << counter << " tracker stop requests\n";
500
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
501
(*m_logger) << time_now_string() << " aborting all connections (" << m_connections.size() << ")\n";
505
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
506
(*m_logger) << time_now_string() << " connection queue: " << m_half_open.size() << "\n";
509
// abort all connections
510
while (!m_connections.empty())
513
int conn = m_connections.size();
515
(*m_connections.begin())->disconnect("stopping torrent");
516
TORRENT_ASSERT(conn == int(m_connections.size()) + 1);
519
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
520
(*m_logger) << time_now_string() << " connection queue: " << m_half_open.size() << "\n";
522
TORRENT_ASSERT(m_half_open.size() == 0);
524
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
525
(*m_logger) << time_now_string() << " shutting down connection queue\n";
528
m_download_channel.close();
529
m_upload_channel.close();
532
void session_impl::set_port_filter(port_filter const& f)
534
mutex_t::scoped_lock l(m_mutex);
536
// TODO: recalculate all connect candidates for all torrents
539
void session_impl::set_ip_filter(ip_filter const& f)
541
mutex_t::scoped_lock l(m_mutex);
547
// Close connections whose endpoint is filtered
548
// by the new ip-filter
549
for (torrent_map::iterator i = m_torrents.begin()
550
, end(m_torrents.end()); i != end; ++i)
551
i->second->ip_filter_updated();
554
ip_filter const& session_impl::get_ip_filter() const
556
mutex_t::scoped_lock l(m_mutex);
560
void session_impl::set_settings(session_settings const& s)
562
mutex_t::scoped_lock l(m_mutex);
566
TORRENT_ASSERT(s.file_pool_size > 0);
568
// less than 5 seconds unchoke interval is insane
569
TORRENT_ASSERT(s.unchoke_interval >= 5);
570
if (m_settings.cache_size != s.cache_size)
571
m_disk_thread.set_cache_size(s.cache_size);
572
if (m_settings.cache_expiry != s.cache_expiry)
573
m_disk_thread.set_cache_expiry(s.cache_expiry);
574
// if queuing settings were changed, recalculate
575
// queued torrents sooner
576
if ((m_settings.active_downloads != s.active_downloads
577
|| m_settings.active_seeds != s.active_seeds
578
|| m_settings.active_limit != s.active_limit)
579
&& m_auto_manage_time_scaler > 2)
580
m_auto_manage_time_scaler = 2;
582
if (m_settings.connection_speed <= 0) m_settings.connection_speed = 200;
584
m_files.resize(m_settings.file_pool_size);
585
if (!s.auto_upload_slots) m_allowed_upload_slots = m_max_uploads;
586
// replace all occurances of '\n' with ' '.
587
std::string::iterator i = m_settings.user_agent.begin();
588
while ((i = std::find(i, m_settings.user_agent.end(), '\n'))
589
!= m_settings.user_agent.end())
593
tcp::endpoint session_impl::get_ipv6_interface() const
595
return m_ipv6_interface;
598
tcp::endpoint session_impl::get_ipv4_interface() const
600
return m_ipv4_interface;
603
session_impl::listen_socket_t session_impl::setup_listener(tcp::endpoint ep
604
, int retries, bool v6_only)
608
s.sock.reset(new socket_acceptor(m_io_service));
609
s.sock->open(ep.protocol(), ec);
610
s.sock->set_option(socket_acceptor::reuse_address(true), ec);
611
if (ep.protocol() == tcp::v6())
613
s.sock->set_option(v6only(v6_only), ec);
614
#ifdef TORRENT_WINDOWS
615
// enable Teredo on windows
616
s.sock->set_option(v6_protection_level(PROTECTION_LEVEL_UNRESTRICTED), ec);
619
s.sock->bind(ep, ec);
620
while (ec && retries > 0)
625
ep.port(ep.port() + 1);
626
s.sock->bind(ep, ec);
630
// instead of giving up, try
631
// let the OS pick a port
634
s.sock->bind(ep, ec);
638
// not even that worked, give up
639
if (m_alerts.should_post<listen_failed_alert>())
640
m_alerts.post_alert(listen_failed_alert(ep, ec));
641
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
642
std::stringstream msg;
643
msg << "cannot bind to interface '";
644
print_endpoint(msg, ep) << "' " << ec.message();
645
(*m_logger) << msg.str() << "\n";
647
return listen_socket_t();
649
s.external_port = s.sock->local_endpoint(ec).port();
650
s.sock->listen(5, ec);
653
if (m_alerts.should_post<listen_failed_alert>())
654
m_alerts.post_alert(listen_failed_alert(ep, ec));
655
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
656
std::stringstream msg;
657
msg << "cannot listen on interface '";
658
print_endpoint(msg, ep) << "' " << ec.message();
659
(*m_logger) << msg.str() << "\n";
661
return listen_socket_t();
664
if (m_alerts.should_post<listen_succeeded_alert>())
665
m_alerts.post_alert(listen_succeeded_alert(ep));
667
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
668
(*m_logger) << "listening on: " << ep
669
<< " external port: " << s.external_port << "\n";
674
void session_impl::open_listen_port()
676
// close the open listen sockets
677
m_listen_sockets.clear();
678
m_incoming_connection = false;
680
m_ipv6_interface = tcp::endpoint();
681
m_ipv4_interface = tcp::endpoint();
683
if (is_any(m_listen_interface.address()))
685
// this means we should open two listen sockets
686
// one for IPv4 and one for IPv6
688
listen_socket_t s = setup_listener(
689
tcp::endpoint(address_v4::any(), m_listen_interface.port())
690
, m_listen_port_retries);
694
m_listen_sockets.push_back(s);
695
async_accept(s.sock);
698
// only try to open the IPv6 port if IPv6 is installed
702
tcp::endpoint(address_v6::any(), m_listen_interface.port())
703
, m_listen_port_retries, true);
707
m_listen_sockets.push_back(s);
708
async_accept(s.sock);
712
// set our main IPv4 and IPv6 interfaces
713
// used to send to the tracker
715
std::vector<ip_interface> ifs = enum_net_interfaces(m_io_service, ec);
716
for (std::vector<ip_interface>::const_iterator i = ifs.begin()
717
, end(ifs.end()); i != end; ++i)
719
address const& addr = i->interface_address;
720
if (addr.is_v6() && !is_local(addr) && !is_loopback(addr))
721
m_ipv6_interface = tcp::endpoint(addr, m_listen_interface.port());
722
else if (addr.is_v4() && !is_local(addr) && !is_loopback(addr))
723
m_ipv4_interface = tcp::endpoint(addr, m_listen_interface.port());
728
// we should only open a single listen socket, that
729
// binds to the given interface
731
listen_socket_t s = setup_listener(
732
m_listen_interface, m_listen_port_retries);
736
m_listen_sockets.push_back(s);
737
async_accept(s.sock);
739
if (m_listen_interface.address().is_v6())
740
m_ipv6_interface = m_listen_interface;
742
m_ipv4_interface = m_listen_interface;
746
if (!m_listen_sockets.empty())
749
tcp::endpoint local = m_listen_sockets.front().sock->local_endpoint(ec);
754
if (m_tcp_mapping[0] != -1) m_natpmp->delete_mapping(m_tcp_mapping[0]);
755
m_tcp_mapping[0] = m_natpmp->add_mapping(natpmp::tcp
756
, local.port(), local.port());
760
if (m_tcp_mapping[1] != -1) m_upnp->delete_mapping(m_tcp_mapping[1]);
761
m_tcp_mapping[1] = m_upnp->add_mapping(upnp::tcp
762
, local.port(), local.port());
767
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
768
m_logger = create_log("main_session", listen_port(), false);
772
#ifndef TORRENT_DISABLE_DHT
774
void session_impl::on_receive_udp(error_code const& e
775
, udp::endpoint const& ep, char const* buf, int len)
779
if (e == asio::error::connection_refused
780
|| e == asio::error::connection_reset
781
|| e == asio::error::connection_aborted)
782
m_dht->on_unreachable(ep);
784
if (m_alerts.should_post<udp_error_alert>())
785
m_alerts.post_alert(udp_error_alert(ep, e));
789
if (len > 20 && *buf == 'd' && m_dht)
791
// this is probably a dht message
792
m_dht->on_receive(ep, buf, len);
798
void session_impl::async_accept(boost::shared_ptr<socket_acceptor> const& listener)
800
shared_ptr<socket_type> c(new socket_type(m_io_service));
801
c->instantiate<stream_socket>(m_io_service);
802
listener->async_accept(c->get<stream_socket>()
803
, bind(&session_impl::on_incoming_connection, this, c
804
, boost::weak_ptr<socket_acceptor>(listener), _1));
807
void session_impl::on_incoming_connection(shared_ptr<socket_type> const& s
808
, weak_ptr<socket_acceptor> listen_socket, error_code const& e)
810
boost::shared_ptr<socket_acceptor> listener = listen_socket.lock();
811
if (!listener) return;
813
if (e == asio::error::operation_aborted) return;
815
mutex_t::scoped_lock l(m_mutex);
821
tcp::endpoint ep = listener->local_endpoint(ec);
822
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
823
std::string msg = "error accepting connection on '"
824
+ boost::lexical_cast<std::string>(ep) + "' " + e.message();
825
(*m_logger) << msg << "\n";
827
#ifdef TORRENT_WINDOWS
828
// Windows sometimes generates this error. It seems to be
829
// non-fatal and we have to do another async_accept.
830
if (e.value() == ERROR_SEM_TIMEOUT)
832
async_accept(listener);
837
// Leopard sometimes generates an "invalid argument" error. It seems to be
838
// non-fatal and we have to do another async_accept.
839
if (e.value() == EINVAL)
841
async_accept(listener);
845
if (m_alerts.should_post<listen_failed_alert>())
846
m_alerts.post_alert(listen_failed_alert(ep, e));
849
async_accept(listener);
851
// we got a connection request!
852
tcp::endpoint endp = s->remote_endpoint(ec);
856
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
857
(*m_logger) << endp << " <== INCOMING CONNECTION FAILED, could "
858
"not retrieve remote endpoint " << ec.message() << "\n";
863
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
864
(*m_logger) << time_now_string() << " <== INCOMING CONNECTION " << endp << "\n";
867
// local addresses do not count, since it's likely
868
// coming from our own client through local service discovery
869
// and it does not reflect whether or not a router is open
870
// for incoming connections or not.
871
if (!is_local(endp.address()))
872
m_incoming_connection = true;
874
if (m_ip_filter.access(endp.address()) & ip_filter::blocked)
876
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
877
(*m_logger) << "filtered blocked ip\n";
879
if (m_alerts.should_post<peer_blocked_alert>())
880
m_alerts.post_alert(peer_blocked_alert(endp.address()));
884
// don't allow more connections than the max setting
885
if (num_connections() >= max_connections())
887
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
888
(*m_logger) << "number of connections limit exceeded (conns: "
889
<< num_connections() << ", limit: " << max_connections()
890
<< "), connection rejected\n";
895
// check if we have any active torrents
896
// if we don't reject the connection
897
if (m_torrents.empty())
899
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
900
(*m_logger) << " There are no torrents, disconnect\n";
905
bool has_active_torrent = false;
906
for (torrent_map::iterator i = m_torrents.begin()
907
, end(m_torrents.end()); i != end; ++i)
909
if (!i->second->is_paused())
911
has_active_torrent = true;
915
if (!has_active_torrent)
917
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
918
(*m_logger) << " There are no _active_ torrents, disconnect\n";
923
boost::intrusive_ptr<peer_connection> c(
924
new bt_peer_connection(*this, s, endp, 0));
926
c->m_in_constructor = false;
929
if (!c->is_disconnecting())
931
m_connections.insert(c);
935
void session_impl::close_connection(peer_connection const* p
936
, char const* message)
938
mutex_t::scoped_lock l(m_mutex);
944
// for (aux::session_impl::torrent_map::const_iterator i = m_torrents.begin()
945
// , end(m_torrents.end()); i != end; ++i)
946
// TORRENT_ASSERT(!i->second->has_peer((peer_connection*)p));
949
#if defined(TORRENT_LOGGING)
950
(*m_logger) << time_now_string() << " CLOSING CONNECTION "
951
<< p->remote() << " : " << message << "\n";
954
TORRENT_ASSERT(p->is_disconnecting());
956
if (!p->is_choked()) --m_num_unchoked;
957
// connection_map::iterator i = std::lower_bound(m_connections.begin(), m_connections.end()
958
// , p, bind(&boost::intrusive_ptr<peer_connection>::get, _1) < p);
959
// if (i->get() != p) i == m_connections.end();
960
connection_map::iterator i = std::find_if(m_connections.begin(), m_connections.end()
961
, bind(&boost::intrusive_ptr<peer_connection>::get, _1) == p);
962
if (i != m_connections.end()) m_connections.erase(i);
965
void session_impl::set_peer_id(peer_id const& id)
967
mutex_t::scoped_lock l(m_mutex);
971
void session_impl::set_key(int key)
973
mutex_t::scoped_lock l(m_mutex);
977
void session_impl::unchoke_peer(peer_connection& c)
979
torrent* t = c.associated_torrent().lock().get();
981
if (t->unchoke_peer(c))
985
int session_impl::next_port()
987
std::pair<int, int> const& out_ports = m_settings.outgoing_ports;
988
if (m_next_port < out_ports.first || m_next_port > out_ports.second)
989
m_next_port = out_ports.first;
991
int port = m_next_port;
993
if (m_next_port > out_ports.second) m_next_port = out_ports.first;
994
#if defined TORRENT_LOGGING
995
(*m_logger) << time_now_string() << " *** BINDING OUTGOING CONNECTION [ "
996
"port: " << port << " ]\n";
1001
void session_impl::second_tick(error_code const& e)
1003
session_impl::mutex_t::scoped_lock l(m_mutex);
1008
if (m_abort) return;
1012
#if defined TORRENT_LOGGING
1013
(*m_logger) << "*** SECOND TIMER FAILED " << e.message() << "\n";
1019
float tick_interval = total_microseconds(time_now() - m_last_tick) / 1000000.f;
1020
m_last_tick = time_now();
1023
m_timer.expires_from_now(seconds(1), ec);
1025
bind(&session_impl::second_tick, this, _1));
1027
#ifdef TORRENT_STATS
1029
int downloading_torrents = 0;
1030
int seeding_torrents = 0;
1031
for (torrent_map::iterator i = m_torrents.begin()
1032
, end(m_torrents.end()); i != end; ++i)
1034
if (i->second->is_seed())
1037
++downloading_torrents;
1039
int num_complete_connections = 0;
1040
int num_half_open = 0;
1041
for (connection_map::iterator i = m_connections.begin()
1042
, end(m_connections.end()); i != end; ++i)
1044
if ((*i)->is_connecting())
1047
++num_complete_connections;
1051
<< m_second_counter << "\t"
1052
<< m_stat.upload_rate() << "\t"
1053
<< m_stat.download_rate() << "\t"
1054
<< downloading_torrents << "\t"
1055
<< seeding_torrents << "\t"
1056
<< num_complete_connections << "\t"
1057
<< num_half_open << "\t"
1058
<< m_disk_thread.disk_allocations() << "\t"
1062
// --------------------------------------------------------------
1063
// check for incoming connections that might have timed out
1064
// --------------------------------------------------------------
1066
for (connection_map::iterator i = m_connections.begin();
1067
i != m_connections.end();)
1069
peer_connection* p = (*i).get();
1071
// ignore connections that already have a torrent, since they
1072
// are ticked through the torrents' second_tick
1073
if (!p->associated_torrent().expired()) continue;
1074
if (m_last_tick - p->connected_time() > seconds(m_settings.handshake_timeout))
1075
p->disconnect("timeout: incoming connection");
1078
// --------------------------------------------------------------
1079
// second_tick every torrent
1080
// --------------------------------------------------------------
1082
int congested_torrents = 0;
1083
int uncongested_torrents = 0;
1085
// count the number of seeding torrents vs. downloading
1086
// torrents we are running
1088
int num_downloads = 0;
1090
// count the number of peers of downloading torrents
1091
int num_downloads_peers = 0;
1093
torrent_map::iterator least_recently_scraped = m_torrents.begin();
1094
int num_paused_auto_managed = 0;
1096
int num_checking = 0;
1098
for (torrent_map::iterator i = m_torrents.begin();
1099
i != m_torrents.end();)
1101
torrent& t = *i->second;
1102
TORRENT_ASSERT(!t.is_aborted());
1103
if (t.bandwidth_queue_size(peer_connection::upload_channel))
1104
++congested_torrents;
1106
++uncongested_torrents;
1108
if (t.state() == torrent_status::checking_files) ++num_checking;
1109
else if (t.state() == torrent_status::queued_for_checking)
1110
if (t.is_auto_managed() && t.is_paused() && !t.has_error())
1112
++num_paused_auto_managed;
1113
if (!least_recently_scraped->second->is_auto_managed()
1114
|| !least_recently_scraped->second->is_paused()
1115
|| least_recently_scraped->second->last_scrape() > t.last_scrape())
1117
least_recently_scraped = i;
1121
if (t.is_finished())
1128
num_downloads_peers += t.num_peers();
1131
t.second_tick(m_stat, tick_interval);
1135
// some people claim that there sometimes can be cases where
1136
// there is no torrent being checked, but there are torrents
1137
// waiting to be checked. I have never seen this, and I can't
1138
// see a way for it to happen. But, if it does, start one of
1139
// the queued torrents
1140
if (num_checking == 0 && num_queued > 0)
1142
TORRENT_ASSERT(false);
1143
check_queue_t::iterator i = std::min_element(m_queued_for_checking.begin()
1144
, m_queued_for_checking.end(), boost::bind(&torrent::queue_position, _1)
1145
< boost::bind(&torrent::queue_position, _2));
1146
if (i != m_queued_for_checking.end())
1148
(*i)->start_checking();
1152
if (m_settings.rate_limit_ip_overhead)
1154
// drain the IP overhead from the bandwidth limiters
1155
m_download_channel.drain(m_stat.download_ip_overhead());
1156
m_upload_channel.drain(m_stat.upload_ip_overhead());
1159
m_stat.second_tick(tick_interval);
1161
// --------------------------------------------------------------
1162
// scrape paused torrents that are auto managed
1163
// --------------------------------------------------------------
1166
--m_auto_scrape_time_scaler;
1167
if (m_auto_scrape_time_scaler <= 0)
1169
m_auto_scrape_time_scaler = m_settings.auto_scrape_interval
1170
/ (std::max)(1, num_paused_auto_managed);
1171
if (m_auto_scrape_time_scaler < m_settings.auto_scrape_min_interval)
1172
m_auto_scrape_time_scaler = m_settings.auto_scrape_min_interval;
1174
if (least_recently_scraped != m_torrents.end())
1176
least_recently_scraped->second->scrape_tracker();
1181
// --------------------------------------------------------------
1182
// connect new peers
1183
// --------------------------------------------------------------
1185
// let torrents connect to peers if they want to
1186
// if there are any torrents and any free slots
1188
// this loop will "hand out" max(connection_speed
1189
// , half_open.free_slots()) to the torrents, in a
1190
// round robin fashion, so that every torrent is
1191
// equallt likely to connect to a peer
1193
int free_slots = m_half_open.free_slots();
1194
if (!m_torrents.empty()
1195
&& free_slots > -m_half_open.limit()
1196
&& num_connections() < m_max_connections
1199
// this is the maximum number of connections we will
1200
// attempt this tick
1201
int max_connections = m_settings.connection_speed;
1202
int average_peers = 0;
1203
if (num_downloads > 0)
1204
average_peers = num_downloads_peers / num_downloads;
1206
torrent_map::iterator i = m_torrents.begin();
1207
if (m_next_connect_torrent < int(m_torrents.size()))
1208
std::advance(i, m_next_connect_torrent);
1210
m_next_connect_torrent = 0;
1211
int steps_since_last_connect = 0;
1212
int num_torrents = int(m_torrents.size());
1215
torrent& t = *i->second;
1216
if (t.want_more_peers())
1218
int connect_points = 100;
1219
// have a bias against torrents with more peers
1221
if (!t.is_seed() && t.num_peers() > average_peers)
1222
connect_points /= 2;
1223
// if this is a seed and there is a torrent that
1224
// is downloading, lower the rate at which this
1225
// torrent gets connections.
1226
// dividing by num_seeds will have the effect
1227
// that all seed will get as many connections
1228
// together, as a single downloading torrent.
1229
if (t.is_seed() && num_downloads > 0)
1230
connect_points /= num_seeds + 1;
1231
if (connect_points <= 0) connect_points = 1;
1232
t.give_connect_points(connect_points);
1235
if (t.try_connect_peer())
1239
steps_since_last_connect = 0;
1242
catch (std::bad_alloc&)
1244
// we ran out of memory trying to connect to a peer
1245
// lower the global limit to the number of peers
1247
m_max_connections = num_connections();
1248
if (m_max_connections < 2) m_max_connections = 2;
1251
++m_next_connect_torrent;
1252
++steps_since_last_connect;
1254
if (i == m_torrents.end())
1256
TORRENT_ASSERT(m_next_connect_torrent == num_torrents);
1257
i = m_torrents.begin();
1258
m_next_connect_torrent = 0;
1260
// if we have gone two whole loops without
1261
// handing out a single connection, break
1262
if (steps_since_last_connect > num_torrents * 2) break;
1263
// if there are no more free connection slots, abort
1264
if (free_slots <= -m_half_open.limit()) break;
1265
// if we should not make any more connections
1266
// attempts this tick, abort
1267
if (max_connections == 0) break;
1268
// maintain the global limit on number of connections
1269
if (num_connections() >= m_max_connections) break;
1273
// --------------------------------------------------------------
1274
// auto managed torrent
1275
// --------------------------------------------------------------
1276
m_auto_manage_time_scaler--;
1277
if (m_auto_manage_time_scaler <= 0)
1279
m_auto_manage_time_scaler = settings().auto_manage_interval;
1280
recalculate_auto_managed_torrents();
1283
// --------------------------------------------------------------
1284
// unchoke set and optimistic unchoke calculations
1285
// --------------------------------------------------------------
1286
m_unchoke_time_scaler--;
1287
if (m_unchoke_time_scaler <= 0 && !m_connections.empty())
1289
m_unchoke_time_scaler = settings().unchoke_interval;
1290
recalculate_unchoke_slots(congested_torrents
1291
, uncongested_torrents);
1294
// --------------------------------------------------------------
1295
// disconnect peers when we have too many
1296
// --------------------------------------------------------------
1297
--m_disconnect_time_scaler;
1298
if (m_disconnect_time_scaler <= 0)
1300
m_disconnect_time_scaler = 90;
1302
// every 90 seconds, disconnect the worst peers
1303
// if we have reached the connection limit
1304
if (num_connections() >= max_connections() * m_settings.peer_turnover_cutoff
1305
&& !m_torrents.empty())
1307
torrent_map::iterator i = std::max_element(m_torrents.begin(), m_torrents.end()
1308
, bind(&torrent::num_peers, bind(&torrent_map::value_type::second, _1))
1309
< bind(&torrent::num_peers, bind(&torrent_map::value_type::second, _2)));
1311
TORRENT_ASSERT(i != m_torrents.end());
1312
int peers_to_disconnect = (std::min)((std::max)(int(i->second->num_peers()
1313
* m_settings.peer_turnover), 1)
1314
, i->second->get_policy().num_connect_candidates());
1315
i->second->disconnect_peers(peers_to_disconnect);
1319
// if we haven't reached the global max. see if any torrent
1320
// has reached its local limit
1321
for (torrent_map::iterator i = m_torrents.begin()
1322
, end(m_torrents.end()); i != end; ++i)
1324
boost::shared_ptr<torrent> t = i->second;
1325
if (t->num_peers() < t->max_connections() * m_settings.peer_turnover_cutoff)
1328
int peers_to_disconnect = (std::min)((std::max)(int(i->second->num_peers()
1329
* m_settings.peer_turnover), 1)
1330
, i->second->get_policy().num_connect_candidates());
1331
t->disconnect_peers(peers_to_disconnect);
1339
bool is_active(torrent* t, session_settings const& s)
1341
return !(s.dont_count_slow_torrents
1342
&& t->statistics().upload_payload_rate() == 0.f
1343
&& t->statistics().download_payload_rate() == 0.f
1344
&& time_now() - t->started() > seconds(s.auto_manage_startup));
1348
void session_impl::recalculate_auto_managed_torrents()
1350
// these vectors are filled with auto managed torrents
1351
std::vector<torrent*> downloaders;
1352
downloaders.reserve(m_torrents.size());
1353
std::vector<torrent*> seeds;
1354
seeds.reserve(m_torrents.size());
1356
// these counters are set to the number of torrents
1357
// of each kind we're allowed to have active
1358
int num_downloaders = settings().active_downloads;
1359
int num_seeds = settings().active_seeds;
1360
int hard_limit = settings().active_limit;
1362
if (num_downloaders == -1)
1363
num_downloaders = (std::numeric_limits<int>::max)();
1364
if (num_seeds == -1)
1365
num_seeds = (std::numeric_limits<int>::max)();
1366
if (hard_limit == -1)
1367
hard_limit = (std::numeric_limits<int>::max)();
1369
for (torrent_map::iterator i = m_torrents.begin()
1370
, end(m_torrents.end()); i != end; ++i)
1372
torrent* t = i->second.get();
1374
if (t->is_auto_managed() && !t->has_error())
1376
// this torrent is auto managed, add it to
1377
// the list (depending on if it's a seed or not)
1378
if (t->is_finished())
1381
downloaders.push_back(t);
1383
else if (!t->is_paused())
1386
if (is_active(t, settings()))
1388
// this is not an auto managed torrent,
1389
// if it's running and active, decrease the
1397
bool handled_by_extension = false;
1399
#ifndef TORRENT_DISABLE_EXTENSIONS
1400
// TODO: allow extensions to sort torrents for queuing
1403
if (!handled_by_extension)
1405
std::sort(downloaders.begin(), downloaders.end()
1406
, bind(&torrent::sequence_number, _1) < bind(&torrent::sequence_number, _2));
1408
std::sort(seeds.begin(), seeds.end()
1409
, bind(&torrent::seed_rank, _1, boost::ref(m_settings))
1410
> bind(&torrent::seed_rank, _2, boost::ref(m_settings)));
1413
for (std::vector<torrent*>::iterator i = downloaders.begin()
1414
, end(downloaders.end()); i != end; ++i)
1417
if (!t->is_paused() && !is_active(t, settings())
1424
if (num_downloaders > 0 && hard_limit > 0)
1428
if (t->is_paused()) t->resume();
1432
if (!t->is_paused()) t->pause();
1436
for (std::vector<torrent*>::iterator i = seeds.begin()
1437
, end(seeds.end()); i != end; ++i)
1440
if (!t->is_paused() && !is_active(t, settings())
1447
if (num_seeds > 0 && hard_limit > 0)
1451
if (t->is_paused()) t->resume();
1455
if (!t->is_paused()) t->pause();
1460
void session_impl::recalculate_unchoke_slots(int congested_torrents
1461
, int uncongested_torrents)
1463
std::vector<peer_connection*> peers;
1464
for (connection_map::iterator i = m_connections.begin()
1465
, end(m_connections.end()); i != end; ++i)
1467
peer_connection* p = i->get();
1469
torrent* t = p->associated_torrent().lock().get();
1470
if (!p->peer_info_struct()
1472
|| !p->is_peer_interested()
1473
|| p->is_disconnecting()
1474
|| p->is_connecting()
1475
|| (p->share_diff() < -free_upload_amount
1478
if (!(*i)->is_choked() && t)
1480
policy::peer* pi = p->peer_info_struct();
1481
if (pi && pi->optimistically_unchoked)
1483
pi->optimistically_unchoked = false;
1484
// force a new optimistic unchoke
1485
m_optimistic_unchoke_time_scaler = 0;
1487
t->choke_peer(*(*i));
1491
peers.push_back(i->get());
1494
// sorts the peers that are eligible for unchoke by download rate and secondary
1495
// by total upload. The reason for this is, if all torrents are being seeded,
1496
// the download rate will be 0, and the peers we have sent the least to should
1498
std::sort(peers.begin(), peers.end()
1499
, bind(&peer_connection::unchoke_compare, _1, _2));
1501
std::for_each(m_connections.begin(), m_connections.end()
1502
, bind(&peer_connection::reset_choke_counters, _1));
1505
int upload_limit = m_bandwidth_manager[peer_connection::upload_channel]->throttle();
1506
if (m_settings.auto_upload_slots && upload_limit != bandwidth_limit::inf)
1508
// if our current upload rate is less than 90% of our
1509
// limit AND most torrents are not "congested", i.e.
1510
// they are not holding back because of a per-torrent
1512
if (m_stat.upload_rate() < upload_limit * 0.9f
1513
&& m_allowed_upload_slots <= m_num_unchoked + 1
1514
&& congested_torrents < uncongested_torrents
1515
&& m_upload_channel.queue_size() < 2)
1517
++m_allowed_upload_slots;
1519
else if (m_upload_channel.queue_size() > 1
1520
&& m_allowed_upload_slots > m_max_uploads)
1522
--m_allowed_upload_slots;
1526
// reserve one upload slot for optimistic unchokes
1527
int unchoke_set_size = m_allowed_upload_slots - 1;
1530
// go through all the peers and unchoke the first ones and choke
1531
// all the other ones.
1532
for (std::vector<peer_connection*>::iterator i = peers.begin()
1533
, end(peers.end()); i != end; ++i)
1535
peer_connection* p = *i;
1537
torrent* t = p->associated_torrent().lock().get();
1539
if (unchoke_set_size > 0)
1543
if (!t->unchoke_peer(*p))
1550
TORRENT_ASSERT(p->peer_info_struct());
1551
if (p->peer_info_struct()->optimistically_unchoked)
1553
// force a new optimistic unchoke
1554
// since this one just got promoted into the
1555
// proper unchoke set
1556
m_optimistic_unchoke_time_scaler = 0;
1557
p->peer_info_struct()->optimistically_unchoked = false;
1562
TORRENT_ASSERT(p->peer_info_struct());
1563
if (!p->is_choked() && !p->peer_info_struct()->optimistically_unchoked)
1565
if (!p->is_choked())
1570
if (m_allowed_upload_slots > 0)
1572
m_optimistic_unchoke_time_scaler--;
1573
if (m_optimistic_unchoke_time_scaler <= 0)
1575
m_optimistic_unchoke_time_scaler
1576
= settings().optimistic_unchoke_multiplier;
1578
// find the peer that has been waiting the longest to be optimistically
1580
connection_map::iterator current_optimistic_unchoke = m_connections.end();
1581
connection_map::iterator optimistic_unchoke_candidate = m_connections.end();
1582
ptime last_unchoke = max_time();
1584
for (connection_map::iterator i = m_connections.begin()
1585
, end(m_connections.end()); i != end; ++i)
1587
peer_connection* p = i->get();
1589
policy::peer* pi = p->peer_info_struct();
1591
torrent* t = p->associated_torrent().lock().get();
1594
if (pi->optimistically_unchoked)
1596
TORRENT_ASSERT(!p->is_choked());
1597
TORRENT_ASSERT(current_optimistic_unchoke == m_connections.end());
1598
current_optimistic_unchoke = i;
1601
if (pi->last_optimistically_unchoked < last_unchoke
1602
&& !p->is_connecting()
1603
&& !p->is_disconnecting()
1604
&& p->is_peer_interested()
1605
&& t->free_upload_slots()
1607
&& t->valid_metadata())
1609
last_unchoke = pi->last_optimistically_unchoked;
1610
optimistic_unchoke_candidate = i;
1614
if (optimistic_unchoke_candidate != m_connections.end()
1615
&& optimistic_unchoke_candidate != current_optimistic_unchoke)
1617
if (current_optimistic_unchoke != m_connections.end())
1619
torrent* t = (*current_optimistic_unchoke)->associated_torrent().lock().get();
1621
(*current_optimistic_unchoke)->peer_info_struct()->optimistically_unchoked = false;
1622
t->choke_peer(*current_optimistic_unchoke->get());
1629
torrent* t = (*optimistic_unchoke_candidate)->associated_torrent().lock().get();
1631
bool ret = t->unchoke_peer(*optimistic_unchoke_candidate->get());
1632
TORRENT_ASSERT(ret);
1633
(*optimistic_unchoke_candidate)->peer_info_struct()->optimistically_unchoked = true;
1639
void session_impl::operator()()
1644
session_impl::mutex_t::scoped_lock l(m_mutex);
1645
if (m_listen_interface.port() != 0) open_listen_port();
1651
m_io_service.run(ec);
1652
TORRENT_ASSERT(m_abort == true);
1655
#ifdef TORRENT_DEBUG
1656
std::cerr << ec.message() << "\n";
1657
std::string err = ec.message();
1659
TORRENT_ASSERT(false);
1661
m_io_service.reset();
1665
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
1666
(*m_logger) << time_now_string() << " locking mutex\n";
1669
session_impl::mutex_t::scoped_lock l(m_mutex);
1671
#ifdef TORRENT_DEBUG
1672
for (torrent_map::iterator i = m_torrents.begin();
1673
i != m_torrents.end(); ++i)
1675
TORRENT_ASSERT(i->second->num_peers() == 0);
1679
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
1680
(*m_logger) << time_now_string() << " cleaning up torrents\n";
1684
TORRENT_ASSERT(m_torrents.empty());
1685
TORRENT_ASSERT(m_connections.empty());
1689
// the return value from this function is valid only as long as the
1690
// session is locked!
1691
boost::weak_ptr<torrent> session_impl::find_torrent(sha1_hash const& info_hash)
1693
std::map<sha1_hash, boost::shared_ptr<torrent> >::iterator i
1694
= m_torrents.find(info_hash);
1695
#ifdef TORRENT_DEBUG
1696
for (std::map<sha1_hash, boost::shared_ptr<torrent> >::iterator j
1697
= m_torrents.begin(); j != m_torrents.end(); ++j)
1699
torrent* p = boost::get_pointer(j->second);
1703
if (i != m_torrents.end()) return i->second;
1704
return boost::weak_ptr<torrent>();
1707
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
1708
boost::shared_ptr<logger> session_impl::create_log(std::string const& name
1709
, int instance, bool append)
1711
// current options are file_logger, cout_logger and null_logger
1712
return boost::shared_ptr<logger>(new logger(m_logpath, name + ".log", instance, append));
1716
std::vector<torrent_handle> session_impl::get_torrents()
1718
mutex_t::scoped_lock l(m_mutex);
1719
std::vector<torrent_handle> ret;
1721
for (session_impl::torrent_map::iterator i
1722
= m_torrents.begin(), end(m_torrents.end());
1725
if (i->second->is_aborted()) continue;
1726
ret.push_back(torrent_handle(i->second));
1731
torrent_handle session_impl::find_torrent_handle(sha1_hash const& info_hash)
1733
return torrent_handle(find_torrent(info_hash));
1736
torrent_handle session_impl::add_torrent(add_torrent_params const& params)
1738
TORRENT_ASSERT(!params.save_path.empty());
1740
if (params.ti && params.ti->num_files() == 0)
1742
#ifndef BOOST_NO_EXCEPTIONS
1743
throw std::runtime_error("no files in torrent");
1745
return torrent_handle();
1749
// lock the session and the checker thread (the order is important!)
1750
mutex_t::scoped_lock l(m_mutex);
1756
#ifndef BOOST_NO_EXCEPTIONS
1757
throw std::runtime_error("session is closing");
1759
return torrent_handle();
1763
// figure out the info hash of the torrent
1764
sha1_hash const* ih = 0;
1765
if (params.ti) ih = ¶ms.ti->info_hash();
1766
else ih = ¶ms.info_hash;
1768
// is the torrent already active?
1769
boost::shared_ptr<torrent> torrent_ptr = find_torrent(*ih).lock();
1772
if (!params.duplicate_is_error)
1773
return torrent_handle(torrent_ptr);
1775
#ifndef BOOST_NO_EXCEPTIONS
1776
throw duplicate_torrent();
1778
return torrent_handle();
1783
for (torrent_map::const_iterator i = m_torrents.begin()
1784
, end(m_torrents.end()); i != end; ++i)
1786
int pos = i->second->queue_position();
1787
if (pos >= queue_pos) queue_pos = pos + 1;
1790
// create the torrent and the data associated with
1791
// the checker thread and store it before starting
1795
torrent_ptr.reset(new torrent(*this, params.ti, params.save_path
1796
, m_listen_interface, params.storage_mode, 16 * 1024
1797
, params.storage, params.paused, params.resume_data
1798
, queue_pos, params.auto_managed));
1802
torrent_ptr.reset(new torrent(*this, params.tracker_url, *ih, params.name
1803
, params.save_path, m_listen_interface, params.storage_mode, 16 * 1024
1804
, params.storage, params.paused, params.resume_data
1805
, queue_pos, params.auto_managed));
1807
torrent_ptr->start();
1809
#ifndef TORRENT_DISABLE_EXTENSIONS
1810
for (extension_list_t::iterator i = m_extensions.begin()
1811
, end(m_extensions.end()); i != end; ++i)
1813
boost::shared_ptr<torrent_plugin> tp((*i)(torrent_ptr.get(), params.userdata));
1814
if (tp) torrent_ptr->add_extension(tp);
1818
#ifndef TORRENT_DISABLE_DHT
1819
if (m_dht && params.ti)
1821
torrent_info::nodes_t const& nodes = params.ti->nodes();
1822
std::for_each(nodes.begin(), nodes.end(), bind(
1823
(void(dht::dht_tracker::*)(std::pair<std::string, int> const&))
1824
&dht::dht_tracker::add_node
1825
, boost::ref(m_dht), _1));
1829
m_torrents.insert(std::make_pair(*ih, torrent_ptr));
1831
// if this is an auto managed torrent, force a recalculation
1832
// of which torrents to have active
1833
if (params.auto_managed && m_auto_manage_time_scaler > 2)
1834
m_auto_manage_time_scaler = 2;
1836
return torrent_handle(torrent_ptr);
1839
void session_impl::check_torrent(boost::shared_ptr<torrent> const& t)
1841
if (m_abort) return;
1842
TORRENT_ASSERT(t->should_check_files());
1843
TORRENT_ASSERT(t->state() != torrent_status::checking_files);
1844
if (m_queued_for_checking.empty()) t->start_checking();
1845
else t->set_state(torrent_status::queued_for_checking);
1846
TORRENT_ASSERT(std::find(m_queued_for_checking.begin()
1847
, m_queued_for_checking.end(), t) == m_queued_for_checking.end());
1848
m_queued_for_checking.push_back(t);
1851
void session_impl::done_checking(boost::shared_ptr<torrent> const& t)
1855
if (m_queued_for_checking.empty()) return;
1856
boost::shared_ptr<torrent> next_check = *m_queued_for_checking.begin();
1857
check_queue_t::iterator done = m_queued_for_checking.end();
1858
for (check_queue_t::iterator i = m_queued_for_checking.begin()
1859
, end(m_queued_for_checking.end()); i != end; ++i)
1861
TORRENT_ASSERT(*i == t || (*i)->should_check_files());
1862
if (*i == t) done = i;
1863
if (next_check == t || next_check->queue_position() > (*i)->queue_position())
1866
// only start a new one if we removed the one that is checking
1867
if (done == m_queued_for_checking.end()) return;
1869
if (next_check != t && t->state() == torrent_status::checking_files)
1870
next_check->start_checking();
1871
m_queued_for_checking.erase(done);
1874
void session_impl::remove_torrent(const torrent_handle& h, int options)
1876
boost::shared_ptr<torrent> tptr = h.m_torrent.lock();
1878
#ifdef BOOST_NO_EXCEPTIONS
1881
throw invalid_handle();
1884
mutex_t::scoped_lock l(m_mutex);
1888
session_impl::torrent_map::iterator i =
1889
m_torrents.find(tptr->torrent_file().info_hash());
1891
if (i != m_torrents.end())
1893
torrent& t = *i->second;
1894
if (options & session::delete_files)
1898
#ifdef TORRENT_DEBUG
1899
sha1_hash i_hash = t.torrent_file().info_hash();
1901
t.set_queue_position(-1);
1902
m_torrents.erase(i);
1903
std::list<boost::shared_ptr<torrent> >::iterator k
1904
= std::find(m_queued_for_checking.begin(), m_queued_for_checking.end(), tptr);
1905
if (k != m_queued_for_checking.end()) m_queued_for_checking.erase(k);
1906
TORRENT_ASSERT(m_torrents.find(i_hash) == m_torrents.end());
1911
bool session_impl::listen_on(
1912
std::pair<int, int> const& port_range
1913
, const char* net_interface)
1915
session_impl::mutex_t::scoped_lock l(m_mutex);
1919
tcp::endpoint new_interface;
1920
if (net_interface && std::strlen(net_interface) > 0)
1923
new_interface = tcp::endpoint(address::from_string(net_interface, ec), port_range.first);
1926
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
1927
(*m_logger) << time_now_string() << "listen_on: " << net_interface
1928
<< " failed: " << ec.message() << "\n";
1934
new_interface = tcp::endpoint(address_v4::any(), port_range.first);
1936
m_listen_port_retries = port_range.second - port_range.first;
1938
// if the interface is the same and the socket is open
1939
// don't do anything
1940
if (new_interface == m_listen_interface
1941
&& !m_listen_sockets.empty()) return true;
1943
m_listen_interface = new_interface;
1947
bool new_listen_address = m_listen_interface.address() != new_interface.address();
1949
#ifndef TORRENT_DISABLE_DHT
1950
if ((new_listen_address || m_dht_same_port) && m_dht)
1952
if (m_dht_same_port)
1953
m_dht_settings.service_port = new_interface.port();
1954
// the listen interface changed, rebind the dht listen socket as well
1955
m_dht_socket.bind(m_dht_settings.service_port);
1958
if (m_udp_mapping[0] != -1) m_natpmp->delete_mapping(m_udp_mapping[0]);
1959
m_udp_mapping[0] = m_natpmp->add_mapping(natpmp::udp
1960
, m_dht_settings.service_port
1961
, m_dht_settings.service_port);
1965
if (m_udp_mapping[1] != -1) m_upnp->delete_mapping(m_udp_mapping[1]);
1966
m_udp_mapping[1] = m_upnp->add_mapping(upnp::udp
1967
, m_dht_settings.service_port
1968
, m_dht_settings.service_port);
1973
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
1974
m_logger = create_log("main_session", listen_port(), false);
1975
(*m_logger) << time_now_string() << "\n";
1978
return !m_listen_sockets.empty();
1981
unsigned short session_impl::listen_port() const
1983
mutex_t::scoped_lock l(m_mutex);
1984
if (m_listen_sockets.empty()) return 0;
1985
return m_listen_sockets.front().external_port;;
1988
void session_impl::announce_lsd(sha1_hash const& ih)
1990
mutex_t::scoped_lock l(m_mutex);
1991
// use internal listen port for local peers
1993
m_lsd->announce(ih, m_listen_interface.port());
1996
void session_impl::on_lsd_peer(tcp::endpoint peer, sha1_hash const& ih)
1998
mutex_t::scoped_lock l(m_mutex);
2002
boost::shared_ptr<torrent> t = find_torrent(ih).lock();
2004
// don't add peers from lsd to private torrents
2005
if (t->torrent_file().priv()) return;
2007
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
2008
(*m_logger) << time_now_string()
2009
<< ": added peer from local discovery: " << peer << "\n";
2011
t->get_policy().peer_from_tracker(peer, peer_id(0), peer_info::lsd, 0);
2014
void session_impl::on_port_mapping(int mapping, int port
2015
, std::string const& errmsg, int map_transport)
2017
#ifndef TORRENT_DISABLE_DHT
2018
if (mapping == m_udp_mapping[map_transport] && port != 0)
2020
m_external_udp_port = port;
2021
m_dht_settings.service_port = port;
2022
if (m_alerts.should_post<portmap_alert>())
2023
m_alerts.post_alert(portmap_alert(mapping, port
2029
if (mapping == m_tcp_mapping[map_transport] && port != 0)
2031
if (!m_listen_sockets.empty())
2032
m_listen_sockets.front().external_port = port;
2033
if (m_alerts.should_post<portmap_alert>())
2034
m_alerts.post_alert(portmap_alert(mapping, port
2039
if (!errmsg.empty())
2041
if (m_alerts.should_post<portmap_error_alert>())
2042
m_alerts.post_alert(portmap_error_alert(mapping
2043
, map_transport, errmsg));
2047
if (m_alerts.should_post<portmap_alert>())
2048
m_alerts.post_alert(portmap_alert(mapping, port
2053
session_status session_impl::status() const
2055
mutex_t::scoped_lock l(m_mutex);
2061
s.num_peers = (int)m_connections.size();
2062
s.num_unchoked = m_num_unchoked;
2063
s.allowed_upload_slots = m_allowed_upload_slots;
2065
s.total_redundant_bytes = m_total_redundant_bytes;
2066
s.total_failed_bytes = m_total_failed_bytes;
2068
s.up_bandwidth_queue = m_upload_channel.queue_size();
2069
s.down_bandwidth_queue = m_download_channel.queue_size();
2071
s.has_incoming_connections = m_incoming_connection;
2073
s.download_rate = m_stat.download_rate();
2074
s.upload_rate = m_stat.upload_rate();
2076
s.payload_download_rate = m_stat.download_payload_rate();
2077
s.payload_upload_rate = m_stat.upload_payload_rate();
2079
s.total_download = m_stat.total_protocol_download()
2080
+ m_stat.total_payload_download();
2082
s.total_upload = m_stat.total_protocol_upload()
2083
+ m_stat.total_payload_upload();
2085
s.total_payload_download = m_stat.total_payload_download();
2086
s.total_payload_upload = m_stat.total_payload_upload();
2088
#ifndef TORRENT_DISABLE_DHT
2091
m_dht->dht_status(s);
2096
s.dht_node_cache = 0;
2098
s.dht_global_nodes = 0;
2105
#ifndef TORRENT_DISABLE_DHT
2107
void session_impl::start_dht(entry const& startup_state)
2109
mutex_t::scoped_lock l(m_mutex);
2118
if (m_dht_settings.service_port == 0
2121
m_dht_same_port = true;
2122
if (m_listen_interface.port() > 0)
2123
m_dht_settings.service_port = m_listen_interface.port();
2125
m_dht_settings.service_port = 45000 + (rand() % 10000);
2127
m_external_udp_port = m_dht_settings.service_port;
2128
if (m_natpmp.get() && m_udp_mapping[0] == -1)
2130
m_udp_mapping[0] = m_natpmp->add_mapping(natpmp::udp
2131
, m_dht_settings.service_port
2132
, m_dht_settings.service_port);
2134
if (m_upnp.get() && m_udp_mapping[1] == -1)
2136
m_udp_mapping[1] = m_upnp->add_mapping(upnp::udp
2137
, m_dht_settings.service_port
2138
, m_dht_settings.service_port);
2140
m_dht = new dht::dht_tracker(m_dht_socket, m_dht_settings, &startup_state);
2141
if (!m_dht_socket.is_open() || m_dht_socket.local_port() != m_dht_settings.service_port)
2143
m_dht_socket.bind(m_dht_settings.service_port);
2146
for (std::list<std::pair<std::string, int> >::iterator i = m_dht_router_nodes.begin()
2147
, end(m_dht_router_nodes.end()); i != end; ++i)
2149
m_dht->add_router_node(*i);
2151
std::list<std::pair<std::string, int> >().swap(m_dht_router_nodes);
2153
m_dht->start(startup_state);
2156
void session_impl::stop_dht()
2158
mutex_t::scoped_lock l(m_mutex);
2164
void session_impl::set_dht_settings(dht_settings const& settings)
2166
mutex_t::scoped_lock l(m_mutex);
2167
// only change the dht listen port in case the settings
2168
// contains a vaiid port, and if it is different from
2169
// the current setting
2170
if (settings.service_port != 0)
2171
m_dht_same_port = false;
2173
m_dht_same_port = true;
2174
if (!m_dht_same_port
2175
&& settings.service_port != m_dht_settings.service_port
2178
m_dht_socket.bind(settings.service_port);
2182
if (m_udp_mapping[0] != -1) m_upnp->delete_mapping(m_udp_mapping[0]);
2183
m_udp_mapping[0] = m_natpmp->add_mapping(natpmp::udp
2184
, m_dht_settings.service_port
2185
, m_dht_settings.service_port);
2189
if (m_udp_mapping[1] != -1) m_upnp->delete_mapping(m_udp_mapping[1]);
2190
m_udp_mapping[1] = m_upnp->add_mapping(upnp::udp
2191
, m_dht_settings.service_port
2192
, m_dht_settings.service_port);
2194
m_external_udp_port = settings.service_port;
2196
m_dht_settings = settings;
2197
if (m_dht_same_port)
2198
m_dht_settings.service_port = m_listen_interface.port();
2201
void session_impl::dht_state_callback(boost::condition& c
2202
, entry& e, bool& done) const
2204
mutex_t::scoped_lock l(m_mutex);
2205
if (m_dht) e = m_dht->state();
2210
entry session_impl::dht_state() const
2212
boost::condition cond;
2213
mutex_t::scoped_lock l(m_mutex);
2214
if (!m_dht) return entry();
2217
m_io_service.post(boost::bind(&session_impl::dht_state_callback
2218
, this, boost::ref(cond), boost::ref(e), boost::ref(done)));
2219
while (!done) cond.wait(l);
2223
void session_impl::add_dht_node(std::pair<std::string, int> const& node)
2225
TORRENT_ASSERT(m_dht);
2226
mutex_t::scoped_lock l(m_mutex);
2227
m_dht->add_node(node);
2230
void session_impl::add_dht_router(std::pair<std::string, int> const& node)
2232
// router nodes should be added before the DHT is started (and bootstrapped)
2233
mutex_t::scoped_lock l(m_mutex);
2234
if (m_dht) m_dht->add_router_node(node);
2235
else m_dht_router_nodes.push_back(node);
2240
#ifndef TORRENT_DISABLE_ENCRYPTION
2241
void session_impl::set_pe_settings(pe_settings const& settings)
2243
mutex_t::scoped_lock l(m_mutex);
2244
m_pe_settings = settings;
2248
bool session_impl::is_listening() const
2250
mutex_t::scoped_lock l(m_mutex);
2251
return !m_listen_sockets.empty();
2254
session_impl::~session_impl()
2256
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
2257
(*m_logger) << time_now_string() << "\n\n *** shutting down session *** \n\n";
2260
TORRENT_ASSERT(m_connections.empty());
2262
// we need to wait for the disk-io thread to
2263
// die first, to make sure it won't post any
2264
// more messages to the io_service containing references
2265
// to disk_io_pool inside the disk_io_thread. Once
2266
// the main thread has handled all the outstanding requests
2267
// we know it's safe to destruct the disk thread.
2268
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
2269
(*m_logger) << time_now_string() << " waiting for disk io thread\n";
2271
m_disk_thread.join();
2273
#ifndef TORRENT_DISABLE_GEO_IP
2274
if (m_asnum_db) GeoIP_delete(m_asnum_db);
2275
if (m_country_db) GeoIP_delete(m_country_db);
2277
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
2278
(*m_logger) << time_now_string() << " waiting for main thread\n";
2282
TORRENT_ASSERT(m_torrents.empty());
2283
TORRENT_ASSERT(m_connections.empty());
2284
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
2285
(*m_logger) << time_now_string() << " shutdown complete!\n";
2287
TORRENT_ASSERT(m_connections.empty());
2290
void session_impl::set_max_uploads(int limit)
2292
TORRENT_ASSERT(limit >= 0 || limit == -1);
2293
mutex_t::scoped_lock l(m_mutex);
2297
if (limit < 0) limit = (std::numeric_limits<int>::max)();
2298
if (m_max_uploads == limit) return;
2299
m_max_uploads = limit;
2300
m_allowed_upload_slots = limit;
2303
void session_impl::set_max_connections(int limit)
2305
TORRENT_ASSERT(limit > 0 || limit == -1);
2306
mutex_t::scoped_lock l(m_mutex);
2312
limit = (std::numeric_limits<int>::max)();
2313
#ifndef TORRENT_WINDOWS
2315
if (getrlimit(RLIMIT_NOFILE, &l) == 0
2316
&& l.rlim_cur != RLIM_INFINITY)
2318
limit = l.rlim_cur - m_settings.file_pool_size;
2319
if (limit < 5) limit = 5;
2323
m_max_connections = limit;
2326
void session_impl::set_max_half_open_connections(int limit)
2328
TORRENT_ASSERT(limit > 0 || limit == -1);
2329
mutex_t::scoped_lock l(m_mutex);
2333
if (limit <= 0) limit = (std::numeric_limits<int>::max)();
2334
m_half_open.limit(limit);
2337
void session_impl::set_download_rate_limit(int bytes_per_second)
2339
TORRENT_ASSERT(bytes_per_second > 0 || bytes_per_second == -1);
2340
mutex_t::scoped_lock l(m_mutex);
2344
if (bytes_per_second <= 0) bytes_per_second = bandwidth_limit::inf;
2345
m_bandwidth_manager[peer_connection::download_channel]->throttle(bytes_per_second);
2348
void session_impl::set_upload_rate_limit(int bytes_per_second)
2350
TORRENT_ASSERT(bytes_per_second > 0 || bytes_per_second == -1);
2351
mutex_t::scoped_lock l(m_mutex);
2355
if (bytes_per_second <= 0) bytes_per_second = bandwidth_limit::inf;
2356
m_bandwidth_manager[peer_connection::upload_channel]->throttle(bytes_per_second);
2359
std::auto_ptr<alert> session_impl::pop_alert()
2361
mutex_t::scoped_lock l(m_mutex);
2366
if (m_alerts.pending())
2367
return m_alerts.get();
2368
return std::auto_ptr<alert>(0);
2371
alert const* session_impl::wait_for_alert(time_duration max_wait)
2373
return m_alerts.wait_for_alert(max_wait);
2376
void session_impl::set_alert_mask(int m)
2378
mutex_t::scoped_lock l(m_mutex);
2379
m_alerts.set_alert_mask(m);
2382
size_t session_impl::set_alert_queue_size_limit(size_t queue_size_limit_)
2384
mutex_t::scoped_lock l(m_mutex);
2385
return m_alerts.set_alert_queue_size_limit(queue_size_limit_);
2388
int session_impl::upload_rate_limit() const
2390
mutex_t::scoped_lock l(m_mutex);
2394
int ret = m_bandwidth_manager[peer_connection::upload_channel]->throttle();
2395
return ret == (std::numeric_limits<int>::max)() ? -1 : ret;
2398
int session_impl::download_rate_limit() const
2400
mutex_t::scoped_lock l(m_mutex);
2401
int ret = m_bandwidth_manager[peer_connection::download_channel]->throttle();
2402
return ret == (std::numeric_limits<int>::max)() ? -1 : ret;
2405
void session_impl::start_lsd()
2407
mutex_t::scoped_lock l(m_mutex);
2413
m_lsd = new lsd(m_io_service
2414
, m_listen_interface.address()
2415
, bind(&session_impl::on_lsd_peer, this, _1, _2));
2418
natpmp* session_impl::start_natpmp()
2420
mutex_t::scoped_lock l(m_mutex);
2424
if (m_natpmp) return m_natpmp.get();
2426
m_natpmp = new natpmp(m_io_service
2427
, m_listen_interface.address()
2428
, bind(&session_impl::on_port_mapping
2429
, this, _1, _2, _3, 0));
2431
if (m_listen_interface.port() > 0)
2433
m_tcp_mapping[0] = m_natpmp->add_mapping(natpmp::tcp
2434
, m_listen_interface.port(), m_listen_interface.port());
2436
#ifndef TORRENT_DISABLE_DHT
2438
m_udp_mapping[0] = m_natpmp->add_mapping(natpmp::udp
2439
, m_dht_settings.service_port
2440
, m_dht_settings.service_port);
2442
return m_natpmp.get();
2445
upnp* session_impl::start_upnp()
2447
mutex_t::scoped_lock l(m_mutex);
2451
if (m_upnp) return m_upnp.get();
2453
m_upnp = new upnp(m_io_service, m_half_open
2454
, m_listen_interface.address()
2455
, m_settings.user_agent
2456
, bind(&session_impl::on_port_mapping
2457
, this, _1, _2, _3, 1)
2458
, m_settings.upnp_ignore_nonrouters);
2460
m_upnp->discover_device();
2461
if (m_listen_interface.port() > 0)
2463
m_tcp_mapping[1] = m_upnp->add_mapping(upnp::tcp
2464
, m_listen_interface.port(), m_listen_interface.port());
2466
#ifndef TORRENT_DISABLE_DHT
2468
m_udp_mapping[1] = m_upnp->add_mapping(upnp::udp
2469
, m_dht_settings.service_port
2470
, m_dht_settings.service_port);
2472
return m_upnp.get();
2475
void session_impl::stop_lsd()
2477
mutex_t::scoped_lock l(m_mutex);
2483
void session_impl::stop_natpmp()
2485
mutex_t::scoped_lock l(m_mutex);
2491
void session_impl::stop_upnp()
2493
mutex_t::scoped_lock l(m_mutex);
2497
m_udp_mapping[1] = -1;
2498
m_tcp_mapping[1] = -1;
2503
void session_impl::set_external_address(address const& ip)
2505
TORRENT_ASSERT(ip != address());
2507
if (is_local(ip)) return;
2508
if (is_loopback(ip)) return;
2509
if (m_external_address == ip) return;
2511
m_external_address = ip;
2512
if (m_alerts.should_post<external_ip_alert>())
2513
m_alerts.post_alert(external_ip_alert(ip));
2516
void session_impl::free_disk_buffer(char* buf)
2518
m_disk_thread.free_buffer(buf);
2521
char* session_impl::allocate_disk_buffer()
2523
return m_disk_thread.allocate_buffer();
2526
std::pair<char*, int> session_impl::allocate_buffer(int size)
2528
TORRENT_ASSERT(size > 0);
2529
int num_buffers = (size + send_buffer_size - 1) / send_buffer_size;
2530
TORRENT_ASSERT(num_buffers > 0);
2532
boost::mutex::scoped_lock l(m_send_buffer_mutex);
2533
#ifdef TORRENT_STATS
2534
TORRENT_ASSERT(m_buffer_allocations >= 0);
2535
m_buffer_allocations += num_buffers;
2536
m_buffer_usage_logger << log_time() << " protocol_buffer: "
2537
<< (m_buffer_allocations * send_buffer_size) << std::endl;
2539
#ifdef TORRENT_DISABLE_POOL_ALLOCATOR
2540
int num_bytes = num_buffers * send_buffer_size;
2541
return std::make_pair((char*)malloc(num_bytes), num_bytes);
2543
return std::make_pair((char*)m_send_buffers.ordered_malloc(num_buffers)
2544
, num_buffers * send_buffer_size);
2548
#ifdef TORRENT_STATS
2549
void session_impl::log_buffer_usage()
2551
int send_buffer_capacity = 0;
2552
int used_send_buffer = 0;
2553
for (connection_map::const_iterator i = m_connections.begin()
2554
, end(m_connections.end()); i != end; ++i)
2556
send_buffer_capacity += (*i)->send_buffer_capacity();
2557
used_send_buffer += (*i)->send_buffer_size();
2559
TORRENT_ASSERT(send_buffer_capacity >= used_send_buffer);
2560
m_buffer_usage_logger << log_time() << " send_buffer_size: " << send_buffer_capacity << std::endl;
2561
m_buffer_usage_logger << log_time() << " used_send_buffer: " << used_send_buffer << std::endl;
2562
m_buffer_usage_logger << log_time() << " send_buffer_utilization: "
2563
<< (used_send_buffer * 100.f / send_buffer_capacity) << std::endl;
2567
void session_impl::free_buffer(char* buf, int size)
2569
TORRENT_ASSERT(size > 0);
2570
TORRENT_ASSERT(size % send_buffer_size == 0);
2571
int num_buffers = size / send_buffer_size;
2572
TORRENT_ASSERT(num_buffers > 0);
2574
boost::mutex::scoped_lock l(m_send_buffer_mutex);
2575
#ifdef TORRENT_STATS
2576
m_buffer_allocations -= num_buffers;
2577
TORRENT_ASSERT(m_buffer_allocations >= 0);
2578
m_buffer_usage_logger << log_time() << " protocol_buffer: "
2579
<< (m_buffer_allocations * send_buffer_size) << std::endl;
2581
#ifdef TORRENT_DISABLE_POOL_ALLOCATOR
2584
m_send_buffers.ordered_free(buf, num_buffers);
2588
#ifdef TORRENT_DEBUG
2589
void session_impl::check_invariant() const
2591
std::set<int> unique;
2592
int total_downloaders = 0;
2593
for (torrent_map::const_iterator i = m_torrents.begin()
2594
, end(m_torrents.end()); i != end; ++i)
2596
int pos = i->second->queue_position();
2599
TORRENT_ASSERT(pos == -1);
2602
++total_downloaders;
2603
unique.insert(i->second->queue_position());
2605
TORRENT_ASSERT(int(unique.size()) == total_downloaders);
2607
TORRENT_ASSERT(m_max_connections > 0);
2608
TORRENT_ASSERT(m_max_uploads >= 0);
2609
TORRENT_ASSERT(m_allowed_upload_slots >= m_max_uploads);
2611
int num_optimistic = 0;
2612
for (connection_map::const_iterator i = m_connections.begin();
2613
i != m_connections.end(); ++i)
2616
boost::shared_ptr<torrent> t = (*i)->associated_torrent().lock();
2618
peer_connection* p = i->get();
2619
TORRENT_ASSERT(!p->is_disconnecting());
2620
if (!p->is_choked()) ++unchokes;
2621
if (p->peer_info_struct()
2622
&& p->peer_info_struct()->optimistically_unchoked)
2625
TORRENT_ASSERT(!p->is_choked());
2627
if (t && p->peer_info_struct())
2629
TORRENT_ASSERT(t->get_policy().has_connection(p));
2632
TORRENT_ASSERT(num_optimistic == 0 || num_optimistic == 1);
2633
if (m_num_unchoked != unchokes)
2635
TORRENT_ASSERT(false);
2637
for (std::map<sha1_hash, boost::shared_ptr<torrent> >::const_iterator j
2638
= m_torrents.begin(); j != m_torrents.end(); ++j)
2640
TORRENT_ASSERT(boost::get_pointer(j->second));